From b529d7fe8c6812fc875b467df0a1ebd58456220b Mon Sep 17 00:00:00 2001 From: Gwyn Date: Sun, 14 Mar 2021 09:16:51 -0600 Subject: [PATCH 01/13] Adds option to skip Session dependency installs. Default is False. (#394) * skips pip installs * skips conda installs * skips run_always if no-install is set --- nox/_options.py | 8 ++++++++ nox/sessions.py | 20 ++++++++++++++++++++ tests/test_sessions.py | 30 ++++++++++++++++++++++++++++++ 3 files changed, 58 insertions(+) diff --git a/nox/_options.py b/nox/_options.py index 8f66b1aa..a861a9f6 100644 --- a/nox/_options.py +++ b/nox/_options.py @@ -402,6 +402,14 @@ def _session_completer( hidden=True, finalizer_func=_color_finalizer, ), + _option_set.Option( + "no_install", + "--no-install", + default=False, + group=options.groups["secondary"], + action="store_true", + help="Skip invocations of session methods for installing packages.", + ), ) diff --git a/nox/sessions.py b/nox/sessions.py index 52f647a1..6fa2b36e 100644 --- a/nox/sessions.py +++ b/nox/sessions.py @@ -290,6 +290,10 @@ def run_always( do not have a virtualenv. :type external: bool """ + if self._runner.global_config.no_install: + logger.info("Skipping run_always, as --no-install is set.") + return None + if not args: raise ValueError("At least one argument required to run_always().") @@ -355,6 +359,15 @@ def conda_install( .. _conda install: """ + + if self._runner.global_config.no_install: + logger.info( + "Skipping {} conda installation, as --no-install is set.".format( + args[0] + ) + ) + return None + venv = self._runner.venv prefix_args = () # type: Tuple[str, ...] @@ -417,6 +430,13 @@ def install(self, *args: str, **kwargs: Any) -> None: .. _pip: https://pip.readthedocs.org """ + + if self._runner.global_config.no_install: + logger.info( + "Skipping {} installation, as --no-install is set.".format(args[0]) + ) + return None + if not isinstance( self._runner.venv, (CondaEnv, VirtualEnv, PassthroughEnv) ): # pragma: no cover diff --git a/tests/test_sessions.py b/tests/test_sessions.py index 150c15ec..9d789119 100644 --- a/tests/test_sessions.py +++ b/tests/test_sessions.py @@ -310,6 +310,16 @@ def test_run_always_install_only(self, caplog): assert session.run_always(operator.add, 23, 19) == 42 + def test_run_always_no_install(self, caplog): + session, runner = self.make_session_and_runner() + runner.global_config.no_install = True + + with mock.patch.object(nox.command, "run") as run: + assert session.run_always(operator.add, 23, 19) is None + run.assert_not_called() + + assert "no-install" in caplog.text + def test_conda_install_bad_args(self): session, runner = self.make_session_and_runner() runner.venv = mock.create_autospec(nox.virtualenv.CondaEnv) @@ -342,6 +352,17 @@ def test_conda_install_not_a_condaenv(self): with pytest.raises(ValueError, match="conda environment"): session.conda_install() + def test_conda_no_install(self, caplog): + caplog.set_level(logging.INFO) + session, runner = self.make_session_and_runner() + runner.global_config.no_install = True + + with mock.patch.object(nox.command, "run") as run: + assert session.conda_install("baked beans", "eggs", "spam") is None + + run.assert_not_called() + assert "no-install" in caplog.text + @pytest.mark.parametrize( "auto_offline", [False, True], ids="auto_offline={}".format ) @@ -538,6 +559,15 @@ def test_skip_no_log(self): with pytest.raises(nox.sessions._SessionSkip): session.skip() + def test_session_no_install(self, caplog): + caplog.set_level(logging.INFO) + session, runner = self.make_session_and_runner() + runner.global_config.no_install = True + with mock.patch.object(nox.command, "run") as run: + assert session.install("eggs", "spam") is None + run.assert_not_called() + assert "no-install" in caplog.text + def test___slots__(self): session, _ = self.make_session_and_runner() with pytest.raises(AttributeError): From 6969cda12db5d9c688315fd95b19af7286134dee Mon Sep 17 00:00:00 2001 From: Gwyn Date: Mon, 22 Mar 2021 12:46:53 -0600 Subject: [PATCH 02/13] Adds check for no_install flag to check for reusing existing venv (#394) reuse_existing is now true if we are not installing pacakges. --- nox/sessions.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nox/sessions.py b/nox/sessions.py index 6fa2b36e..e55dabc2 100644 --- a/nox/sessions.py +++ b/nox/sessions.py @@ -536,7 +536,7 @@ def _create_venv(self) -> None: return reuse_existing = ( - self.func.reuse_venv or self.global_config.reuse_existing_virtualenvs + self.func.reuse_venv or self.global_config.reuse_existing_virtualenvs or self.global_config.no_install ) if backend is None or backend == "virtualenv": From 1be3a724bdd2c22a1ea7c59c488afcacb3692fda Mon Sep 17 00:00:00 2001 From: Gwyn Date: Mon, 22 Mar 2021 15:35:01 -0600 Subject: [PATCH 03/13] Adds tracking of whether venv has been create (#394) This boolean informs us whether we need to ignore the "no-install" command line option. --- nox/virtualenv.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/nox/virtualenv.py b/nox/virtualenv.py index 78322e08..a7fa0b57 100644 --- a/nox/virtualenv.py +++ b/nox/virtualenv.py @@ -55,6 +55,8 @@ def __init__(self, bin_paths: None = None, env: Mapping[str, str] = None) -> Non self._bin_paths = bin_paths self.env = os.environ.copy() + self._venv_created = False + if env is not None: self.env.update(env) @@ -78,6 +80,11 @@ def bin(self) -> str: raise ValueError("The environment does not have a bin directory.") return paths[0] + @property + def venv_created(self): + return self._venv_created + + def create(self) -> bool: raise NotImplementedError("ProcessEnv.create should be overwritten in subclass") @@ -244,6 +251,8 @@ def create(self) -> bool: ) nox.command.run(cmd, silent=True, log=False) + self.venv_created = True + return True @staticmethod @@ -433,4 +442,6 @@ def create(self) -> bool: ) nox.command.run(cmd, silent=True, log=False) + self._venv_created = True + return True From 6639daf1d7f66f6290860c59373b4946b298db15 Mon Sep 17 00:00:00 2001 From: Gwyn Date: Sat, 27 Mar 2021 12:24:16 -0600 Subject: [PATCH 04/13] Adds no-install flag to condaenv venv (#394) Extracted and renamed SessionNoSlots to MockableSession to clarify what it is used for. Reduced duplication of that code. Duplicated several tests for conda installs but ensured that the no-install flag was set and ignored. --- nox/sessions.py | 22 +++++++---- tests/test_sessions.py | 90 ++++++++++++++++++++++++++++++++++-------- 2 files changed, 88 insertions(+), 24 deletions(-) diff --git a/nox/sessions.py b/nox/sessions.py index e55dabc2..c1eadf72 100644 --- a/nox/sessions.py +++ b/nox/sessions.py @@ -360,15 +360,22 @@ def conda_install( .. _conda install: """ + venv = self._runner.venv + if self._runner.global_config.no_install: - logger.info( - "Skipping {} conda installation, as --no-install is set.".format( - args[0] + if (venv.venv_created): + logger.info( + "Skipping {} conda installation, as --no-install is set.".format( + args[0] + ) + ) + return None + else: + logger.info( + "Venv not created yet. Ignoring --no-install and installing {} via conda.".format( + args[0] + ) ) - ) - return None - - venv = self._runner.venv prefix_args = () # type: Tuple[str, ...] if isinstance(venv, CondaEnv): @@ -525,6 +532,7 @@ def envdir(self) -> str: return _normalize_path(self.global_config.envdir, self.friendly_name) def _create_venv(self) -> None: + backend = ( self.global_config.force_venv_backend or self.func.venv_backend diff --git a/tests/test_sessions.py b/tests/test_sessions.py index 9d789119..cd8a8ed3 100644 --- a/tests/test_sessions.py +++ b/tests/test_sessions.py @@ -57,6 +57,14 @@ def test__normalize_path_give_up(): norm_path = nox.sessions._normalize_path(envdir, "any-path") assert "any-path" in norm_path +class MockableSession(nox.sessions.Session): + """ + Defining __slots__ on a session prevents you from overriding the + run method in a mock. + Inherit session, but without __slots__ defined, and do nothing else + to enable testing of Session with mocks. + """ + pass class TestSession: def make_session_and_runner(self): @@ -77,6 +85,23 @@ def make_session_and_runner(self): runner.venv.bin_paths = ["/no/bin/for/you"] return nox.sessions.Session(runner=runner), runner + def make_session_without_venv(self): + func = mock.Mock(spec=["python"], python="3.7") + runner = nox.sessions.SessionRunner( + name="test", + signatures=["test"], + func=func, + global_config=_options.options.namespace( + posargs=mock.sentinel.posargs, + error_on_external_run=False, + install_only=False, + ), + manifest=mock.create_autospec(nox.manifest.Manifest), + ) + runner.venv = "none" + + return nox.sessions.Session(runner=runner), runner + def test_create_tmp(self): session, runner = self.make_session_and_runner() with tempfile.TemporaryDirectory() as root: @@ -320,6 +345,17 @@ def test_run_always_no_install(self, caplog): assert "no-install" in caplog.text + def test_no_install_with_no_venv(self, caplog): + caplog.set_level(logging.INFO) + session, runner = self.make_session_without_venv() + runner.global_config.no_install = True + + with mock.patch.object(nox.command, "run") as run: + assert session.install("baked beans", "eggs", "spam") is None + + run.assert_not_called() + assert "no-install" in caplog.text + def test_conda_install_bad_args(self): session, runner = self.make_session_and_runner() runner.venv = mock.create_autospec(nox.virtualenv.CondaEnv) @@ -352,7 +388,7 @@ def test_conda_install_not_a_condaenv(self): with pytest.raises(ValueError, match="conda environment"): session.conda_install() - def test_conda_no_install(self, caplog): + def test_conda_no_install_with_venv(self, caplog): caplog.set_level(logging.INFO) session, runner = self.make_session_and_runner() runner.global_config.no_install = True @@ -380,10 +416,7 @@ def test_conda_install(self, auto_offline, offline): runner.venv.env = {} runner.venv.is_offline = lambda: offline - class SessionNoSlots(nox.sessions.Session): - pass - - session = SessionNoSlots(runner=runner) + session = MockableSession(runner=runner) with mock.patch.object(session, "_run", autospec=True) as run: args = ("--offline",) if auto_offline and offline else () @@ -401,6 +434,38 @@ class SessionNoSlots(nox.sessions.Session): external="error", ) + + @pytest.mark.parametrize( + "auto_offline", [False, True], ids="auto_offline={}".format + ) + @pytest.mark.parametrize("offline", [False, True], ids="offline={}".format) + def test_conda_installs_first_time_with_no_install(self, auto_offline, offline, caplog): + runner = nox.sessions.SessionRunner( + name="test", + signatures=["test"], + func=mock.sentinel.func, + global_config=_options.options.namespace(posargs=mock.sentinel.posargs), + manifest=mock.create_autospec(nox.manifest.Manifest), + ) + + caplog.set_level(logging.INFO) + + runner.global_config.no_install = True + + runner.venv = mock.create_autospec(nox.virtualenv.CondaEnv) + runner.venv.env = {} + runner.venv.location = "/path/to/conda/env" + runner.venv.is_offline = lambda: offline + runner.venv.venv_created = False + + session = MockableSession(runner=runner) + + with mock.patch.object(session, "_run", autospec=True) as run: + args = ("--offline",) if auto_offline and offline else () + session.conda_install("requests", "urllib3", auto_offline=auto_offline) + + assert "Ignoring --no-install" in caplog.text + @pytest.mark.parametrize( "version_constraint", ["no", "yes", "already_dbl_quoted"], @@ -419,10 +484,7 @@ def test_conda_install_non_default_kwargs(self, version_constraint): runner.venv.env = {} runner.venv.is_offline = lambda: False - class SessionNoSlots(nox.sessions.Session): - pass - - session = SessionNoSlots(runner=runner) + session = MockableSession(runner=runner) if version_constraint == "no": pkg_requirement = passed_arg = "urllib3" @@ -474,10 +536,7 @@ def test_install(self): runner.venv = mock.create_autospec(nox.virtualenv.VirtualEnv) runner.venv.env = {} - class SessionNoSlots(nox.sessions.Session): - pass - - session = SessionNoSlots(runner=runner) + session = MockableSession(runner=runner) with mock.patch.object(session, "_run", autospec=True) as run: session.install("requests", "urllib3") @@ -503,10 +562,7 @@ def test_install_non_default_kwargs(self): runner.venv = mock.create_autospec(nox.virtualenv.VirtualEnv) runner.venv.env = {} - class SessionNoSlots(nox.sessions.Session): - pass - - session = SessionNoSlots(runner=runner) + session = MockableSession(runner=runner) with mock.patch.object(session, "_run", autospec=True) as run: session.install("requests", "urllib3", silent=False) From 7ac3fab65b94cd266f28b58df90b1be1e3c811f7 Mon Sep 17 00:00:00 2001 From: Gwyn Date: Sat, 27 Mar 2021 15:17:01 -0600 Subject: [PATCH 05/13] Supports no-install flag in condaenv type virtualenv (#394) --- nox/sessions.py | 44 +++++++++++-------- nox/virtualenv.py | 9 +--- tests/test_sessions.py | 97 +++++++++++++----------------------------- 3 files changed, 59 insertions(+), 91 deletions(-) diff --git a/nox/sessions.py b/nox/sessions.py index c1eadf72..d7651c7c 100644 --- a/nox/sessions.py +++ b/nox/sessions.py @@ -290,6 +290,7 @@ def run_always( do not have a virtualenv. :type external: bool """ + if self._runner.global_config.no_install: logger.info("Skipping run_always, as --no-install is set.") return None @@ -362,6 +363,17 @@ def conda_install( venv = self._runner.venv + prefix_args = () # type: Tuple[str, ...] + if isinstance(venv, CondaEnv): + prefix_args = ("--prefix", venv.location) + elif not isinstance(venv, PassthroughEnv): # pragma: no cover + raise ValueError( + "A session without a conda environment can not install dependencies from conda." + ) + + if not args: + raise ValueError("At least one argument required to install().") + if self._runner.global_config.no_install: if (venv.venv_created): logger.info( @@ -377,17 +389,6 @@ def conda_install( ) ) - prefix_args = () # type: Tuple[str, ...] - if isinstance(venv, CondaEnv): - prefix_args = ("--prefix", venv.location) - elif not isinstance(venv, PassthroughEnv): # pragma: no cover - raise ValueError( - "A session without a conda environment can not install dependencies from conda." - ) - - if not args: - raise ValueError("At least one argument required to install().") - # Escape args that should be (conda-specific; pip install does not need this) args = _dblquote_pkg_install_args(args) @@ -438,14 +439,10 @@ def install(self, *args: str, **kwargs: Any) -> None: .. _pip: https://pip.readthedocs.org """ - if self._runner.global_config.no_install: - logger.info( - "Skipping {} installation, as --no-install is set.".format(args[0]) - ) - return None + venv = self._runner.venv if not isinstance( - self._runner.venv, (CondaEnv, VirtualEnv, PassthroughEnv) + venv, (CondaEnv, VirtualEnv, PassthroughEnv) ): # pragma: no cover raise ValueError( "A session without a virtualenv can not install dependencies." @@ -453,6 +450,19 @@ def install(self, *args: str, **kwargs: Any) -> None: if not args: raise ValueError("At least one argument required to install().") + if self._runner.global_config.no_install: + if(venv.venv_created): + logger.info( + "Skipping {} installation, as --no-install is set.".format(args[0]) + ) + return None + else: + logger.info( + "Venv not created yet. Ignoring --no-install and installing {}.".format( + args[0] + ) + ) + if "silent" not in kwargs: kwargs["silent"] = True diff --git a/nox/virtualenv.py b/nox/virtualenv.py index a7fa0b57..2e4698c7 100644 --- a/nox/virtualenv.py +++ b/nox/virtualenv.py @@ -55,7 +55,7 @@ def __init__(self, bin_paths: None = None, env: Mapping[str, str] = None) -> Non self._bin_paths = bin_paths self.env = os.environ.copy() - self._venv_created = False + self.venv_created = False if env is not None: self.env.update(env) @@ -80,11 +80,6 @@ def bin(self) -> str: raise ValueError("The environment does not have a bin directory.") return paths[0] - @property - def venv_created(self): - return self._venv_created - - def create(self) -> bool: raise NotImplementedError("ProcessEnv.create should be overwritten in subclass") @@ -442,6 +437,6 @@ def create(self) -> bool: ) nox.command.run(cmd, silent=True, log=False) - self._venv_created = True + self.venv_created = True return True diff --git a/tests/test_sessions.py b/tests/test_sessions.py index cd8a8ed3..172bb6df 100644 --- a/tests/test_sessions.py +++ b/tests/test_sessions.py @@ -85,23 +85,6 @@ def make_session_and_runner(self): runner.venv.bin_paths = ["/no/bin/for/you"] return nox.sessions.Session(runner=runner), runner - def make_session_without_venv(self): - func = mock.Mock(spec=["python"], python="3.7") - runner = nox.sessions.SessionRunner( - name="test", - signatures=["test"], - func=func, - global_config=_options.options.namespace( - posargs=mock.sentinel.posargs, - error_on_external_run=False, - install_only=False, - ), - manifest=mock.create_autospec(nox.manifest.Manifest), - ) - runner.venv = "none" - - return nox.sessions.Session(runner=runner), runner - def test_create_tmp(self): session, runner = self.make_session_and_runner() with tempfile.TemporaryDirectory() as root: @@ -343,18 +326,8 @@ def test_run_always_no_install(self, caplog): assert session.run_always(operator.add, 23, 19) is None run.assert_not_called() - assert "no-install" in caplog.text - - def test_no_install_with_no_venv(self, caplog): - caplog.set_level(logging.INFO) - session, runner = self.make_session_without_venv() - runner.global_config.no_install = True - - with mock.patch.object(nox.command, "run") as run: - assert session.install("baked beans", "eggs", "spam") is None + assert "Skipping run_always" in caplog.text - run.assert_not_called() - assert "no-install" in caplog.text def test_conda_install_bad_args(self): session, runner = self.make_session_and_runner() @@ -388,17 +361,6 @@ def test_conda_install_not_a_condaenv(self): with pytest.raises(ValueError, match="conda environment"): session.conda_install() - def test_conda_no_install_with_venv(self, caplog): - caplog.set_level(logging.INFO) - session, runner = self.make_session_and_runner() - runner.global_config.no_install = True - - with mock.patch.object(nox.command, "run") as run: - assert session.conda_install("baked beans", "eggs", "spam") is None - - run.assert_not_called() - assert "no-install" in caplog.text - @pytest.mark.parametrize( "auto_offline", [False, True], ids="auto_offline={}".format ) @@ -434,37 +396,29 @@ def test_conda_install(self, auto_offline, offline): external="error", ) - - @pytest.mark.parametrize( - "auto_offline", [False, True], ids="auto_offline={}".format - ) - @pytest.mark.parametrize("offline", [False, True], ids="offline={}".format) - def test_conda_installs_first_time_with_no_install(self, auto_offline, offline, caplog): - runner = nox.sessions.SessionRunner( - name="test", - signatures=["test"], - func=mock.sentinel.func, - global_config=_options.options.namespace(posargs=mock.sentinel.posargs), - manifest=mock.create_autospec(nox.manifest.Manifest), - ) - + @pytest.mark.parametrize("no_install,venv_is_created,desired_result", + [(False, False,"Ignoring --no-install"), + (True,False,"Ignoring --no-install"), + (False,True,"Skipping"), + (True,True,"Skipping"), + ]) + def test_conda_no_install_with_venv(self, no_install, venv_is_created, desired_result, caplog): caplog.set_level(logging.INFO) - - runner.global_config.no_install = True + session, runner = self.make_session_and_runner() runner.venv = mock.create_autospec(nox.virtualenv.CondaEnv) - runner.venv.env = {} runner.venv.location = "/path/to/conda/env" - runner.venv.is_offline = lambda: offline - runner.venv.venv_created = False + runner.venv.env = {} + runner.venv.is_offline = lambda: True - session = MockableSession(runner=runner) + runner.global_config.no_install = True + runner.venv.venv_created = venv_is_created - with mock.patch.object(session, "_run", autospec=True) as run: - args = ("--offline",) if auto_offline and offline else () - session.conda_install("requests", "urllib3", auto_offline=auto_offline) + with mock.patch.object(nox.command, "run") as run: + assert session.conda_install("baked beans", "eggs", "spam") is None + + assert desired_result in caplog.text - assert "Ignoring --no-install" in caplog.text @pytest.mark.parametrize( "version_constraint", @@ -615,14 +569,23 @@ def test_skip_no_log(self): with pytest.raises(nox.sessions._SessionSkip): session.skip() - def test_session_no_install(self, caplog): + + @pytest.mark.parametrize("no_install,venv_is_created,desired_result", + [ + (True,False,"Venv not created yet"), + (True,True,"Skipping"), + ]) + def test_session_no_install(self, no_install, venv_is_created, desired_result, caplog): caplog.set_level(logging.INFO) session, runner = self.make_session_and_runner() - runner.global_config.no_install = True + + runner.global_config.no_install = no_install + runner.venv.venv_created = venv_is_created + with mock.patch.object(nox.command, "run") as run: assert session.install("eggs", "spam") is None - run.assert_not_called() - assert "no-install" in caplog.text + + assert desired_result in caplog.text def test___slots__(self): session, _ = self.make_session_and_runner() From 0d224b00465416186da67e876324601f38af6a56 Mon Sep 17 00:00:00 2001 From: Gwyn Date: Sat, 27 Mar 2021 17:56:32 -0600 Subject: [PATCH 06/13] Linting (#394) --- nox/sessions.py | 8 ++++--- nox/virtualenv.py | 2 +- noxfile.py | 2 +- tests/test_sessions.py | 52 +++++++++++++++++++++++------------------- 4 files changed, 36 insertions(+), 28 deletions(-) diff --git a/nox/sessions.py b/nox/sessions.py index d7651c7c..10d85364 100644 --- a/nox/sessions.py +++ b/nox/sessions.py @@ -375,7 +375,7 @@ def conda_install( raise ValueError("At least one argument required to install().") if self._runner.global_config.no_install: - if (venv.venv_created): + if venv.venv_created: logger.info( "Skipping {} conda installation, as --no-install is set.".format( args[0] @@ -451,7 +451,7 @@ def install(self, *args: str, **kwargs: Any) -> None: raise ValueError("At least one argument required to install().") if self._runner.global_config.no_install: - if(venv.venv_created): + if venv.venv_created: logger.info( "Skipping {} installation, as --no-install is set.".format(args[0]) ) @@ -554,7 +554,9 @@ def _create_venv(self) -> None: return reuse_existing = ( - self.func.reuse_venv or self.global_config.reuse_existing_virtualenvs or self.global_config.no_install + self.func.reuse_venv + or self.global_config.reuse_existing_virtualenvs + or self.global_config.no_install ) if backend is None or backend == "virtualenv": diff --git a/nox/virtualenv.py b/nox/virtualenv.py index 2e4698c7..bd9bb7a2 100644 --- a/nox/virtualenv.py +++ b/nox/virtualenv.py @@ -438,5 +438,5 @@ def create(self) -> bool: nox.command.run(cmd, silent=True, log=False) self.venv_created = True - + return True diff --git a/noxfile.py b/noxfile.py index 802f6dcb..1bb1096c 100644 --- a/noxfile.py +++ b/noxfile.py @@ -97,7 +97,7 @@ def lint(session): "nox", ) files = ["nox", "tests", "noxfile.py", "setup.py"] - session.run("black", "--check", *files) + session.run("black", *files) session.run("isort", "--check", "--recursive", *files) session.run("flake8", "nox", *files) diff --git a/tests/test_sessions.py b/tests/test_sessions.py index 172bb6df..2f408de1 100644 --- a/tests/test_sessions.py +++ b/tests/test_sessions.py @@ -57,15 +57,18 @@ def test__normalize_path_give_up(): norm_path = nox.sessions._normalize_path(envdir, "any-path") assert "any-path" in norm_path + class MockableSession(nox.sessions.Session): """ - Defining __slots__ on a session prevents you from overriding the - run method in a mock. + Defining __slots__ on a session prevents you from overriding the + run method in a mock. Inherit session, but without __slots__ defined, and do nothing else to enable testing of Session with mocks. """ + pass + class TestSession: def make_session_and_runner(self): func = mock.Mock(spec=["python"], python="3.7") @@ -328,7 +331,6 @@ def test_run_always_no_install(self, caplog): assert "Skipping run_always" in caplog.text - def test_conda_install_bad_args(self): session, runner = self.make_session_and_runner() runner.venv = mock.create_autospec(nox.virtualenv.CondaEnv) @@ -396,13 +398,18 @@ def test_conda_install(self, auto_offline, offline): external="error", ) - @pytest.mark.parametrize("no_install,venv_is_created,desired_result", - [(False, False,"Ignoring --no-install"), - (True,False,"Ignoring --no-install"), - (False,True,"Skipping"), - (True,True,"Skipping"), - ]) - def test_conda_no_install_with_venv(self, no_install, venv_is_created, desired_result, caplog): + @pytest.mark.parametrize( + "no_install,venv_is_created,desired_result", + [ + (False, False, "Ignoring --no-install"), + (True, False, "Ignoring --no-install"), + (False, True, "Skipping"), + (True, True, "Skipping"), + ], + ) + def test_conda_no_install_with_venv( + self, no_install, venv_is_created, desired_result, caplog + ): caplog.set_level(logging.INFO) session, runner = self.make_session_and_runner() @@ -410,16 +417,15 @@ def test_conda_no_install_with_venv(self, no_install, venv_is_created, desired_r runner.venv.location = "/path/to/conda/env" runner.venv.env = {} runner.venv.is_offline = lambda: True - + runner.global_config.no_install = True runner.venv.venv_created = venv_is_created - with mock.patch.object(nox.command, "run") as run: + with mock.patch.object(nox.command, "run"): assert session.conda_install("baked beans", "eggs", "spam") is None assert desired_result in caplog.text - @pytest.mark.parametrize( "version_constraint", ["no", "yes", "already_dbl_quoted"], @@ -569,22 +575,22 @@ def test_skip_no_log(self): with pytest.raises(nox.sessions._SessionSkip): session.skip() - - @pytest.mark.parametrize("no_install,venv_is_created,desired_result", - [ - (True,False,"Venv not created yet"), - (True,True,"Skipping"), - ]) - def test_session_no_install(self, no_install, venv_is_created, desired_result, caplog): + @pytest.mark.parametrize( + "no_install,venv_is_created,desired_result", + [(True, False, "Venv not created yet"), (True, True, "Skipping")], + ) + def test_session_no_install( + self, no_install, venv_is_created, desired_result, caplog + ): caplog.set_level(logging.INFO) session, runner = self.make_session_and_runner() - + runner.global_config.no_install = no_install runner.venv.venv_created = venv_is_created - with mock.patch.object(nox.command, "run") as run: + with mock.patch.object(nox.command, "run"): assert session.install("eggs", "spam") is None - + assert desired_result in caplog.text def test___slots__(self): From ce3c1e64baa271e840937146ace36fe6b3fd129f Mon Sep 17 00:00:00 2001 From: Gwyn Date: Sat, 27 Mar 2021 21:31:10 -0600 Subject: [PATCH 07/13] PR feedback from @cjolowicz * Updates venv_created to a private data member. * Removes irrelevant interpolation from no-install log messages. --- nox/sessions.py | 22 ++++++---------------- nox/virtualenv.py | 6 +++--- tests/test_sessions.py | 4 ++-- 3 files changed, 11 insertions(+), 21 deletions(-) diff --git a/nox/sessions.py b/nox/sessions.py index 10d85364..7e67f7c5 100644 --- a/nox/sessions.py +++ b/nox/sessions.py @@ -375,18 +375,12 @@ def conda_install( raise ValueError("At least one argument required to install().") if self._runner.global_config.no_install: - if venv.venv_created: - logger.info( - "Skipping {} conda installation, as --no-install is set.".format( - args[0] - ) - ) + if venv._venv_created: + logger.info("Skipping conda installation, as --no-install is set.") return None else: logger.info( - "Venv not created yet. Ignoring --no-install and installing {} via conda.".format( - args[0] - ) + "Venv not created yet. Ignoring --no-install and installing from conda." ) # Escape args that should be (conda-specific; pip install does not need this) @@ -451,16 +445,12 @@ def install(self, *args: str, **kwargs: Any) -> None: raise ValueError("At least one argument required to install().") if self._runner.global_config.no_install: - if venv.venv_created: - logger.info( - "Skipping {} installation, as --no-install is set.".format(args[0]) - ) + if venv._venv_created: + logger.info("Skipping installation, as --no-install is set.") return None else: logger.info( - "Venv not created yet. Ignoring --no-install and installing {}.".format( - args[0] - ) + "Venv not created yet. Ignoring --no-install and installing." ) if "silent" not in kwargs: diff --git a/nox/virtualenv.py b/nox/virtualenv.py index bd9bb7a2..a53d543a 100644 --- a/nox/virtualenv.py +++ b/nox/virtualenv.py @@ -55,7 +55,7 @@ def __init__(self, bin_paths: None = None, env: Mapping[str, str] = None) -> Non self._bin_paths = bin_paths self.env = os.environ.copy() - self.venv_created = False + self._venv_created = False if env is not None: self.env.update(env) @@ -246,7 +246,7 @@ def create(self) -> bool: ) nox.command.run(cmd, silent=True, log=False) - self.venv_created = True + self._venv_created = True return True @@ -437,6 +437,6 @@ def create(self) -> bool: ) nox.command.run(cmd, silent=True, log=False) - self.venv_created = True + self._venv_created = True return True diff --git a/tests/test_sessions.py b/tests/test_sessions.py index 2f408de1..9a0f696c 100644 --- a/tests/test_sessions.py +++ b/tests/test_sessions.py @@ -419,7 +419,7 @@ def test_conda_no_install_with_venv( runner.venv.is_offline = lambda: True runner.global_config.no_install = True - runner.venv.venv_created = venv_is_created + runner.venv._venv_created = venv_is_created with mock.patch.object(nox.command, "run"): assert session.conda_install("baked beans", "eggs", "spam") is None @@ -586,7 +586,7 @@ def test_session_no_install( session, runner = self.make_session_and_runner() runner.global_config.no_install = no_install - runner.venv.venv_created = venv_is_created + runner.venv._venv_created = venv_is_created with mock.patch.object(nox.command, "run"): assert session.install("eggs", "spam") is None From 2f38d9898f65054cef3f9af46fcb67f4dd40e209 Mon Sep 17 00:00:00 2001 From: Jam Date: Mon, 29 Mar 2021 19:24:01 -0600 Subject: [PATCH 08/13] Inadvertently committed a removal of the '--check' flag for the linter. Also removed unnecessary whitespace lines. Co-authored-by: Claudio Jolowicz --- nox/sessions.py | 4 ---- nox/virtualenv.py | 1 - noxfile.py | 2 +- tests/test_sessions.py | 2 -- 4 files changed, 1 insertion(+), 8 deletions(-) diff --git a/nox/sessions.py b/nox/sessions.py index 7e67f7c5..6a7e8af8 100644 --- a/nox/sessions.py +++ b/nox/sessions.py @@ -290,7 +290,6 @@ def run_always( do not have a virtualenv. :type external: bool """ - if self._runner.global_config.no_install: logger.info("Skipping run_always, as --no-install is set.") return None @@ -360,7 +359,6 @@ def conda_install( .. _conda install: """ - venv = self._runner.venv prefix_args = () # type: Tuple[str, ...] @@ -432,7 +430,6 @@ def install(self, *args: str, **kwargs: Any) -> None: .. _pip: https://pip.readthedocs.org """ - venv = self._runner.venv if not isinstance( @@ -532,7 +529,6 @@ def envdir(self) -> str: return _normalize_path(self.global_config.envdir, self.friendly_name) def _create_venv(self) -> None: - backend = ( self.global_config.force_venv_backend or self.func.venv_backend diff --git a/nox/virtualenv.py b/nox/virtualenv.py index a53d543a..844f02cc 100644 --- a/nox/virtualenv.py +++ b/nox/virtualenv.py @@ -54,7 +54,6 @@ class ProcessEnv: def __init__(self, bin_paths: None = None, env: Mapping[str, str] = None) -> None: self._bin_paths = bin_paths self.env = os.environ.copy() - self._venv_created = False if env is not None: diff --git a/noxfile.py b/noxfile.py index 1bb1096c..802f6dcb 100644 --- a/noxfile.py +++ b/noxfile.py @@ -97,7 +97,7 @@ def lint(session): "nox", ) files = ["nox", "tests", "noxfile.py", "setup.py"] - session.run("black", *files) + session.run("black", "--check", *files) session.run("isort", "--check", "--recursive", *files) session.run("flake8", "nox", *files) diff --git a/tests/test_sessions.py b/tests/test_sessions.py index 9a0f696c..5b092079 100644 --- a/tests/test_sessions.py +++ b/tests/test_sessions.py @@ -65,7 +65,6 @@ class MockableSession(nox.sessions.Session): Inherit session, but without __slots__ defined, and do nothing else to enable testing of Session with mocks. """ - pass @@ -584,7 +583,6 @@ def test_session_no_install( ): caplog.set_level(logging.INFO) session, runner = self.make_session_and_runner() - runner.global_config.no_install = no_install runner.venv._venv_created = venv_is_created From 4120470b5ff1b55fd197f5b95c6354c02bdfae25 Mon Sep 17 00:00:00 2001 From: Gwyn Date: Tue, 30 Mar 2021 20:42:01 -0600 Subject: [PATCH 09/13] Rename refactoring venv_created -> reused. (#394) This was good advice from @cjolowicz helping to clarify the intention of this boolean. --- nox/sessions.py | 4 ++-- nox/virtualenv.py | 6 +++--- tests/test_sessions.py | 15 +++++++-------- 3 files changed, 12 insertions(+), 13 deletions(-) diff --git a/nox/sessions.py b/nox/sessions.py index 6a7e8af8..16841248 100644 --- a/nox/sessions.py +++ b/nox/sessions.py @@ -373,7 +373,7 @@ def conda_install( raise ValueError("At least one argument required to install().") if self._runner.global_config.no_install: - if venv._venv_created: + if venv._reused: logger.info("Skipping conda installation, as --no-install is set.") return None else: @@ -442,7 +442,7 @@ def install(self, *args: str, **kwargs: Any) -> None: raise ValueError("At least one argument required to install().") if self._runner.global_config.no_install: - if venv._venv_created: + if venv._reused: logger.info("Skipping installation, as --no-install is set.") return None else: diff --git a/nox/virtualenv.py b/nox/virtualenv.py index 844f02cc..b259a49b 100644 --- a/nox/virtualenv.py +++ b/nox/virtualenv.py @@ -54,7 +54,7 @@ class ProcessEnv: def __init__(self, bin_paths: None = None, env: Mapping[str, str] = None) -> None: self._bin_paths = bin_paths self.env = os.environ.copy() - self._venv_created = False + self._reused = False if env is not None: self.env.update(env) @@ -245,7 +245,7 @@ def create(self) -> bool: ) nox.command.run(cmd, silent=True, log=False) - self._venv_created = True + self._reused = True return True @@ -436,6 +436,6 @@ def create(self) -> bool: ) nox.command.run(cmd, silent=True, log=False) - self._venv_created = True + self._reused = True return True diff --git a/tests/test_sessions.py b/tests/test_sessions.py index 5b092079..a50b4623 100644 --- a/tests/test_sessions.py +++ b/tests/test_sessions.py @@ -65,6 +65,7 @@ class MockableSession(nox.sessions.Session): Inherit session, but without __slots__ defined, and do nothing else to enable testing of Session with mocks. """ + pass @@ -398,7 +399,7 @@ def test_conda_install(self, auto_offline, offline): ) @pytest.mark.parametrize( - "no_install,venv_is_created,desired_result", + "no_install,venv_reused,desired_result", [ (False, False, "Ignoring --no-install"), (True, False, "Ignoring --no-install"), @@ -407,7 +408,7 @@ def test_conda_install(self, auto_offline, offline): ], ) def test_conda_no_install_with_venv( - self, no_install, venv_is_created, desired_result, caplog + self, no_install, venv_reused, desired_result, caplog ): caplog.set_level(logging.INFO) session, runner = self.make_session_and_runner() @@ -418,7 +419,7 @@ def test_conda_no_install_with_venv( runner.venv.is_offline = lambda: True runner.global_config.no_install = True - runner.venv._venv_created = venv_is_created + runner.venv._reused = venv_reused with mock.patch.object(nox.command, "run"): assert session.conda_install("baked beans", "eggs", "spam") is None @@ -575,16 +576,14 @@ def test_skip_no_log(self): session.skip() @pytest.mark.parametrize( - "no_install,venv_is_created,desired_result", + "no_install,venv_reused,desired_result", [(True, False, "Venv not created yet"), (True, True, "Skipping")], ) - def test_session_no_install( - self, no_install, venv_is_created, desired_result, caplog - ): + def test_session_no_install(self, no_install, venv_reused, desired_result, caplog): caplog.set_level(logging.INFO) session, runner = self.make_session_and_runner() runner.global_config.no_install = no_install - runner.venv._venv_created = venv_is_created + runner.venv._reused = venv_reused with mock.patch.object(nox.command, "run"): assert session.install("eggs", "spam") is None From 36a1e415cbe59a41b18e8acbf5a77d5ac2cc3121 Mon Sep 17 00:00:00 2001 From: Gwyn Date: Thu, 6 May 2021 20:57:44 -0600 Subject: [PATCH 10/13] Move _reused behind ._clean_location (#394) _clean_location already detects whether a venv is being reused or not, so setting the boolean within this is safe. whether a venv exists or not. --- nox/sessions.py | 12 ++++++++---- nox/virtualenv.py | 10 ++++++---- tests/test_sessions.py | 27 ++++++++++++++------------- 3 files changed, 28 insertions(+), 21 deletions(-) diff --git a/nox/sessions.py b/nox/sessions.py index 16841248..160a5243 100644 --- a/nox/sessions.py +++ b/nox/sessions.py @@ -374,11 +374,13 @@ def conda_install( if self._runner.global_config.no_install: if venv._reused: - logger.info("Skipping conda installation, as --no-install is set.") + logger.info( + "Venv exists: skipping conda installation, as --no-install is set." + ) return None else: logger.info( - "Venv not created yet. Ignoring --no-install and installing from conda." + "Venv not created yet: ignoring --no-install and installing from conda." ) # Escape args that should be (conda-specific; pip install does not need this) @@ -443,11 +445,13 @@ def install(self, *args: str, **kwargs: Any) -> None: if self._runner.global_config.no_install: if venv._reused: - logger.info("Skipping installation, as --no-install is set.") + logger.info( + "Venv exists: skipping installation, as --no-install is set." + ) return None else: logger.info( - "Venv not created yet. Ignoring --no-install and installing." + "Venv not created yet: ignoring --no-install and installing." ) if "silent" not in kwargs: diff --git a/nox/virtualenv.py b/nox/virtualenv.py index b259a49b..47a21074 100644 --- a/nox/virtualenv.py +++ b/nox/virtualenv.py @@ -225,6 +225,8 @@ def create(self) -> bool: logger.debug( "Re-using existing conda env at {}.".format(self.location_name) ) + self._reused = True + return False cmd = ["conda", "create", "--yes", "--prefix", self.location] @@ -245,8 +247,6 @@ def create(self) -> bool: ) nox.command.run(cmd, silent=True, log=False) - self._reused = True - return True @staticmethod @@ -403,6 +403,7 @@ def create(self) -> bool: [self._resolved_interpreter, "-c", "import sys; print(sys.prefix)"], silent=True, ) + created = nox.command.run( [ os.path.join(self.location, "bin", "python"), @@ -419,6 +420,9 @@ def create(self) -> bool: ) return False + self._reused = False + + if self.venv_or_virtualenv == "virtualenv": cmd = [sys.executable, "-m", "virtualenv", self.location] if self.interpreter: @@ -436,6 +440,4 @@ def create(self) -> bool: ) nox.command.run(cmd, silent=True, log=False) - self._reused = True - return True diff --git a/tests/test_sessions.py b/tests/test_sessions.py index a50b4623..dc0d16f7 100644 --- a/tests/test_sessions.py +++ b/tests/test_sessions.py @@ -322,6 +322,9 @@ def test_run_always_install_only(self, caplog): assert session.run_always(operator.add, 23, 19) == 42 def test_run_always_no_install(self, caplog): + caplog.clear() + caplog.set_level(logging.INFO) + session, runner = self.make_session_and_runner() runner.global_config.no_install = True @@ -399,16 +402,11 @@ def test_conda_install(self, auto_offline, offline): ) @pytest.mark.parametrize( - "no_install,venv_reused,desired_result", - [ - (False, False, "Ignoring --no-install"), - (True, False, "Ignoring --no-install"), - (False, True, "Skipping"), - (True, True, "Skipping"), - ], + "venv_reused,desired_result", + [(False, "Venv not created yet:"), (True, "Venv exists: skipping")], ) - def test_conda_no_install_with_venv( - self, no_install, venv_reused, desired_result, caplog + def test_conda_venv_reused_with_no_install( + self, venv_reused, desired_result, caplog ): caplog.set_level(logging.INFO) session, runner = self.make_session_and_runner() @@ -576,13 +574,16 @@ def test_skip_no_log(self): session.skip() @pytest.mark.parametrize( - "no_install,venv_reused,desired_result", - [(True, False, "Venv not created yet"), (True, True, "Skipping")], + "venv_reused,desired_result", + [(False, "Venv not created yet:"), (True, "Venv exists: skipping")], ) - def test_session_no_install(self, no_install, venv_reused, desired_result, caplog): + def test_session_venv_reused_with_no_install( + self, venv_reused, desired_result, caplog + ): + caplog.clear() caplog.set_level(logging.INFO) session, runner = self.make_session_and_runner() - runner.global_config.no_install = no_install + runner.global_config.no_install = True runner.venv._reused = venv_reused with mock.patch.object(nox.command, "run"): From 31529de8a32ca54109c44012e10bff97e869426b Mon Sep 17 00:00:00 2001 From: Gwyn Date: Sat, 17 Apr 2021 07:55:34 -0600 Subject: [PATCH 11/13] Removes automatic reuse of venvs when no-install is provided (#394) Also reduces log verbosity by only noting package reinstallation when venv is not explicitly reused. --- docs/config.rst | 1 + nox/sessions.py | 18 +++++++++--------- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/docs/config.rst b/docs/config.rst index d64d2f88..d1fcf677 100644 --- a/docs/config.rst +++ b/docs/config.rst @@ -424,6 +424,7 @@ The following options can be specified in the Noxfile: * ``nox.options.default_venv_backend`` is equivalent to specifying :ref:`-db or --default-venv-backend `. * ``nox.options.force_venv_backend`` is equivalent to specifying :ref:`-fb or --force-venv-backend `. * ``nox.options.reuse_existing_virtualenvs`` is equivalent to specifying :ref:`--reuse-existing-virtualenvs `. You can force this off by specifying ``--no-reuse-existing-virtualenvs`` during invocation. +* ``nox.options.no_install`` is equivalent to specifying :ref:`--no-install `. * ``nox.options.stop_on_first_error`` is equivalent to specifying :ref:`--stop-on-first-error `. You can force this off by specifying ``--no-stop-on-first-error`` during invocation. * ``nox.options.error_on_missing_interpreters`` is equivalent to specifying :ref:`--error-on-missing-interpreters `. You can force this off by specifying ``--no-error-on-missing-interpreters`` during invocation. * ``nox.options.error_on_external_run`` is equivalent to specifying :ref:`--error-on-external-run `. You can force this off by specifying ``--no-error-on-external-run`` during invocation. diff --git a/nox/sessions.py b/nox/sessions.py index 160a5243..f9ddce79 100644 --- a/nox/sessions.py +++ b/nox/sessions.py @@ -379,9 +379,10 @@ def conda_install( ) return None else: - logger.info( - "Venv not created yet: ignoring --no-install and installing from conda." - ) + if not self._runner.global_config.reuse_existing_virtualenvs: + logger.info( + "Venv not created yet: ignoring --no-install and installing from conda." + ) # Escape args that should be (conda-specific; pip install does not need this) args = _dblquote_pkg_install_args(args) @@ -450,9 +451,10 @@ def install(self, *args: str, **kwargs: Any) -> None: ) return None else: - logger.info( - "Venv not created yet: ignoring --no-install and installing." - ) + if not self._runner.global_config.reuse_existing_virtualenvs: + logger.info( + "Venv not created yet: ignoring --no-install and installing." + ) if "silent" not in kwargs: kwargs["silent"] = True @@ -544,9 +546,7 @@ def _create_venv(self) -> None: return reuse_existing = ( - self.func.reuse_venv - or self.global_config.reuse_existing_virtualenvs - or self.global_config.no_install + self.func.reuse_venv or self.global_config.reuse_existing_virtualenvs ) if backend is None or backend == "virtualenv": From 6ac8898817a6b8e4dee2b644c0c43f11ee810660 Mon Sep 17 00:00:00 2001 From: Gwyn Date: Thu, 22 Apr 2021 18:13:14 -0600 Subject: [PATCH 12/13] PR review cleanups (#394) Removes unneeded logger messages when --no-install is ignored. Simplifies tests and restores 100% test coverage. --- docs/config.rst | 1 - nox/sessions.py | 31 +++++++++---------------------- tests/test_sessions.py | 24 ++++++------------------ 3 files changed, 15 insertions(+), 41 deletions(-) diff --git a/docs/config.rst b/docs/config.rst index d1fcf677..d64d2f88 100644 --- a/docs/config.rst +++ b/docs/config.rst @@ -424,7 +424,6 @@ The following options can be specified in the Noxfile: * ``nox.options.default_venv_backend`` is equivalent to specifying :ref:`-db or --default-venv-backend `. * ``nox.options.force_venv_backend`` is equivalent to specifying :ref:`-fb or --force-venv-backend `. * ``nox.options.reuse_existing_virtualenvs`` is equivalent to specifying :ref:`--reuse-existing-virtualenvs `. You can force this off by specifying ``--no-reuse-existing-virtualenvs`` during invocation. -* ``nox.options.no_install`` is equivalent to specifying :ref:`--no-install `. * ``nox.options.stop_on_first_error`` is equivalent to specifying :ref:`--stop-on-first-error `. You can force this off by specifying ``--no-stop-on-first-error`` during invocation. * ``nox.options.error_on_missing_interpreters`` is equivalent to specifying :ref:`--error-on-missing-interpreters `. You can force this off by specifying ``--no-error-on-missing-interpreters`` during invocation. * ``nox.options.error_on_external_run`` is equivalent to specifying :ref:`--error-on-external-run `. You can force this off by specifying ``--no-error-on-external-run`` during invocation. diff --git a/nox/sessions.py b/nox/sessions.py index f9ddce79..9582d6d1 100644 --- a/nox/sessions.py +++ b/nox/sessions.py @@ -372,17 +372,12 @@ def conda_install( if not args: raise ValueError("At least one argument required to install().") - if self._runner.global_config.no_install: - if venv._reused: - logger.info( - "Venv exists: skipping conda installation, as --no-install is set." - ) - return None - else: - if not self._runner.global_config.reuse_existing_virtualenvs: - logger.info( - "Venv not created yet: ignoring --no-install and installing from conda." - ) + if self._runner.global_config.no_install and venv._reused: + logger.info( + "Venv exists: skipping conda installation, as --no-install is set." + ) + + return None # Escape args that should be (conda-specific; pip install does not need this) args = _dblquote_pkg_install_args(args) @@ -444,17 +439,9 @@ def install(self, *args: str, **kwargs: Any) -> None: if not args: raise ValueError("At least one argument required to install().") - if self._runner.global_config.no_install: - if venv._reused: - logger.info( - "Venv exists: skipping installation, as --no-install is set." - ) - return None - else: - if not self._runner.global_config.reuse_existing_virtualenvs: - logger.info( - "Venv not created yet: ignoring --no-install and installing." - ) + if self._runner.global_config.no_install and venv._reused: + logger.info("Venv exists: skipping installation, as --no-install is set.") + return None if "silent" not in kwargs: kwargs["silent"] = True diff --git a/tests/test_sessions.py b/tests/test_sessions.py index dc0d16f7..9c2f23b9 100644 --- a/tests/test_sessions.py +++ b/tests/test_sessions.py @@ -401,13 +401,7 @@ def test_conda_install(self, auto_offline, offline): external="error", ) - @pytest.mark.parametrize( - "venv_reused,desired_result", - [(False, "Venv not created yet:"), (True, "Venv exists: skipping")], - ) - def test_conda_venv_reused_with_no_install( - self, venv_reused, desired_result, caplog - ): + def test_conda_venv_reused_with_no_install(self, caplog): caplog.set_level(logging.INFO) session, runner = self.make_session_and_runner() @@ -417,12 +411,12 @@ def test_conda_venv_reused_with_no_install( runner.venv.is_offline = lambda: True runner.global_config.no_install = True - runner.venv._reused = venv_reused + runner.venv._reused = True with mock.patch.object(nox.command, "run"): assert session.conda_install("baked beans", "eggs", "spam") is None - assert desired_result in caplog.text + assert "Venv exists: skipping" in caplog.text @pytest.mark.parametrize( "version_constraint", @@ -573,23 +567,17 @@ def test_skip_no_log(self): with pytest.raises(nox.sessions._SessionSkip): session.skip() - @pytest.mark.parametrize( - "venv_reused,desired_result", - [(False, "Venv not created yet:"), (True, "Venv exists: skipping")], - ) - def test_session_venv_reused_with_no_install( - self, venv_reused, desired_result, caplog - ): + def test_session_venv_reused_with_no_install(self, caplog): caplog.clear() caplog.set_level(logging.INFO) session, runner = self.make_session_and_runner() runner.global_config.no_install = True - runner.venv._reused = venv_reused + runner.venv._reused = True with mock.patch.object(nox.command, "run"): assert session.install("eggs", "spam") is None - assert desired_result in caplog.text + assert "Venv exists: skipping" in caplog.text def test___slots__(self): session, _ = self.make_session_and_runner() From 0a088aeb94dba31faa5e5641d46166439ddde2ce Mon Sep 17 00:00:00 2001 From: Gwyn Date: Sat, 8 May 2021 10:36:04 -0600 Subject: [PATCH 13/13] Adds tests for _reused #394 Also removes logging for no_install. --- nox/sessions.py | 6 ------ nox/virtualenv.py | 5 +++-- tests/test_virtualenv.py | 4 ++++ 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/nox/sessions.py b/nox/sessions.py index 9582d6d1..fcad0b4c 100644 --- a/nox/sessions.py +++ b/nox/sessions.py @@ -291,7 +291,6 @@ def run_always( :type external: bool """ if self._runner.global_config.no_install: - logger.info("Skipping run_always, as --no-install is set.") return None if not args: @@ -373,10 +372,6 @@ def conda_install( raise ValueError("At least one argument required to install().") if self._runner.global_config.no_install and venv._reused: - logger.info( - "Venv exists: skipping conda installation, as --no-install is set." - ) - return None # Escape args that should be (conda-specific; pip install does not need this) @@ -440,7 +435,6 @@ def install(self, *args: str, **kwargs: Any) -> None: raise ValueError("At least one argument required to install().") if self._runner.global_config.no_install and venv._reused: - logger.info("Venv exists: skipping installation, as --no-install is set.") return None if "silent" not in kwargs: diff --git a/nox/virtualenv.py b/nox/virtualenv.py index 47a21074..604ee4ee 100644 --- a/nox/virtualenv.py +++ b/nox/virtualenv.py @@ -225,6 +225,7 @@ def create(self) -> bool: logger.debug( "Re-using existing conda env at {}.".format(self.location_name) ) + self._reused = True return False @@ -418,10 +419,10 @@ def create(self) -> bool: self.location_name ) ) - return False - self._reused = False + self._reused = True + return False if self.venv_or_virtualenv == "virtualenv": cmd = [sys.executable, "-m", "virtualenv", self.location] diff --git a/tests/test_virtualenv.py b/tests/test_virtualenv.py index cb76a877..2804d743 100644 --- a/tests/test_virtualenv.py +++ b/tests/test_virtualenv.py @@ -179,6 +179,7 @@ def test_condaenv_create(make_conda): venv.reuse_existing = True venv.create() assert dir_.join("test.txt").check() + assert venv._reused @pytest.mark.skipif(not HAS_CONDA, reason="Missing conda command.") @@ -328,7 +329,10 @@ def test_create(monkeypatch, make_one): assert dir_.join("test.txt").check() venv.reuse_existing = True monkeypatch.setattr(nox.virtualenv.nox.command, "run", mock.MagicMock()) + venv.create() + + assert venv._reused assert dir_.join("test.txt").check()