From dfe4446e3b52f85cc53b06890cb938dc070f3aa1 Mon Sep 17 00:00:00 2001 From: Tom Fleet Date: Mon, 5 Jul 2021 21:22:05 +0100 Subject: [PATCH 1/2] Add friendlier message if no noxfile.py Fixes #462. Add a friendlier message on the specific case that user is calling nox from within a directory with no noxfile. Existing test for this case modified and two additional tests added to ensure lower level errors are still handled further down. --- nox/tasks.py | 6 +++++- tests/test_tasks.py | 42 ++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 45 insertions(+), 3 deletions(-) diff --git a/nox/tasks.py b/nox/tasks.py index afb50a8d..f869f6f8 100644 --- a/nox/tasks.py +++ b/nox/tasks.py @@ -52,6 +52,7 @@ def load_nox_module(global_config: Namespace) -> Union[types.ModuleType, int]: # Be sure to expand variables os.path.expandvars(global_config.noxfile) ) + noxfile_parent_dir = os.path.realpath(os.path.dirname(global_config.noxfile)) # Check ``nox.needs_version`` by parsing the AST. check_nox_version(global_config.noxfile) @@ -60,7 +61,7 @@ def load_nox_module(global_config: Namespace) -> Union[types.ModuleType, int]: # This will ensure that the Noxfile's path is on sys.path, and that # import-time path resolutions work the way the Noxfile author would # guess. - os.chdir(os.path.realpath(os.path.dirname(global_config.noxfile))) + os.chdir(noxfile_parent_dir) return importlib.machinery.SourceFileLoader( "user_nox_module", global_config.noxfile ).load_module() @@ -68,6 +69,9 @@ def load_nox_module(global_config: Namespace) -> Union[types.ModuleType, int]: except (VersionCheckFailed, InvalidVersionSpecifier) as error: logger.error(str(error)) return 2 + except FileNotFoundError: + logger.error(f"noxfile.py not found in {noxfile_parent_dir!r}.") + return 2 except (IOError, OSError): logger.exception("Failed to load Noxfile {}".format(global_config.noxfile)) return 2 diff --git a/tests/test_tasks.py b/tests/test_tasks.py index 4031724c..ce292477 100644 --- a/tests/test_tasks.py +++ b/tests/test_tasks.py @@ -18,6 +18,7 @@ import json import os import platform +from pathlib import Path from textwrap import dedent from unittest import mock @@ -76,9 +77,46 @@ def test_load_nox_module_expandvars(): assert noxfile_module.SIGIL == "123" -def test_load_nox_module_not_found(): - config = _options.options.namespace(noxfile="bogus.py") +def test_load_nox_module_not_found(caplog, tmp_path): + bogus_noxfile = tmp_path / "bogus.py" + config = _options.options.namespace(noxfile=str(bogus_noxfile)) + assert tasks.load_nox_module(config) == 2 + assert f"noxfile.py not found in {str(tmp_path)!r}" in caplog.text + + +def test_load_nox_module_IOError(caplog): + + # Need to give it a noxfile that exists so load_nox_module can progress + # past FileNotFoundError + # use our own noxfile.py for this + our_noxfile = Path(__file__).parent.parent.joinpath("noxfile.py") + config = _options.options.namespace(noxfile=str(our_noxfile)) + + with mock.patch( + "nox.tasks.importlib.machinery.SourceFileLoader.load_module" + ) as mock_load: + mock_load.side_effect = IOError + + assert tasks.load_nox_module(config) == 2 + assert "Failed to load Noxfile" in caplog.text + + +def test_load_nox_module_OSError(caplog): + + # Need to give it a noxfile that exists so load_nox_module can progress + # past FileNotFoundError + # use our own noxfile.py for this + our_noxfile = Path(__file__).parent.parent.joinpath("noxfile.py") + config = _options.options.namespace(noxfile=str(our_noxfile)) + + with mock.patch( + "nox.tasks.importlib.machinery.SourceFileLoader.load_module" + ) as mock_load: + mock_load.side_effect = OSError + + assert tasks.load_nox_module(config) == 2 + assert "Failed to load Noxfile" in caplog.text @pytest.fixture From e81c1a67a6be2fa0e2b941106431ef6e77a2ca24 Mon Sep 17 00:00:00 2001 From: Tom Date: Tue, 6 Jul 2021 12:58:04 +0100 Subject: [PATCH 2/2] Standardise no noxfile found message for noxfile with different names --- nox/tasks.py | 4 +++- tests/test_tasks.py | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/nox/tasks.py b/nox/tasks.py index f869f6f8..ad11b5c6 100644 --- a/nox/tasks.py +++ b/nox/tasks.py @@ -70,7 +70,9 @@ def load_nox_module(global_config: Namespace) -> Union[types.ModuleType, int]: logger.error(str(error)) return 2 except FileNotFoundError: - logger.error(f"noxfile.py not found in {noxfile_parent_dir!r}.") + logger.error( + f"Failed to load Noxfile {global_config.noxfile}, no such file exists." + ) return 2 except (IOError, OSError): logger.exception("Failed to load Noxfile {}".format(global_config.noxfile)) diff --git a/tests/test_tasks.py b/tests/test_tasks.py index ce292477..c8edb8a7 100644 --- a/tests/test_tasks.py +++ b/tests/test_tasks.py @@ -82,7 +82,9 @@ def test_load_nox_module_not_found(caplog, tmp_path): config = _options.options.namespace(noxfile=str(bogus_noxfile)) assert tasks.load_nox_module(config) == 2 - assert f"noxfile.py not found in {str(tmp_path)!r}" in caplog.text + assert ( + f"Failed to load Noxfile {bogus_noxfile}, no such file exists." in caplog.text + ) def test_load_nox_module_IOError(caplog):