diff --git a/docs/config.rst b/docs/config.rst index d64d2f88..f3bb1b9d 100644 --- a/docs/config.rst +++ b/docs/config.rst @@ -159,7 +159,7 @@ You can also specify that the virtualenv should *always* be reused instead of re def tests(session): pass -You are not limited to virtualenv, there is a selection of backends you can choose from as venv, conda or virtualenv (default): +You are not limited to virtualenv, there is a selection of backends you can choose from as venv, conda, mamba, or virtualenv (default): .. code-block:: python diff --git a/docs/tutorial.rst b/docs/tutorial.rst index c6e162db..57ba7f4c 100644 --- a/docs/tutorial.rst +++ b/docs/tutorial.rst @@ -375,6 +375,9 @@ incompatible versions of packages already installed with conda. session.install("contexter", "--no-deps") session.install("-e", ".", "--no-deps") +``"mamba"`` is also allowed as a choice for ``venv_backend``, which will +use/require `mamba `_ instead of conda. + Parametrization --------------- diff --git a/docs/usage.rst b/docs/usage.rst index 8103cb2a..43e9795e 100644 --- a/docs/usage.rst +++ b/docs/usage.rst @@ -110,7 +110,7 @@ Then running ``nox --session tests`` will actually run all parametrized versions Changing the sessions default backend ------------------------------------- -By default nox uses ``virtualenv`` as the virtual environment backend for the sessions, but it also supports ``conda`` and ``venv`` as well as no backend (passthrough to whatever python environment nox is running on). You can change the default behaviour by using ``-db `` or ``--default-venv-backend ``. Supported names are ``('none', 'virtualenv', 'conda', 'venv')``. +By default nox uses ``virtualenv`` as the virtual environment backend for the sessions, but it also supports ``conda``, ``mamba``, and ``venv`` as well as no backend (passthrough to whatever python environment nox is running on). You can change the default behaviour by using ``-db `` or ``--default-venv-backend ``. Supported names are ``('none', 'virtualenv', 'conda', 'mamba', 'venv')``. .. code-block:: console diff --git a/nox/sessions.py b/nox/sessions.py index 08c9cb42..83ea1675 100644 --- a/nox/sessions.py +++ b/nox/sessions.py @@ -421,7 +421,7 @@ def conda_install( extraopts = ("--offline",) self._run( - "conda", + venv.conda_cmd, "install", "--yes", *extraopts, @@ -592,12 +592,13 @@ def _create_venv(self) -> None: reuse_existing=reuse_existing, venv_params=self.func.venv_params, ) - elif backend == "conda": + elif backend in {"conda", "mamba"}: self.venv = CondaEnv( self.envdir, interpreter=self.func.python, # type: ignore reuse_existing=reuse_existing, venv_params=self.func.venv_params, + conda_cmd=backend, ) elif backend == "venv": self.venv = VirtualEnv( diff --git a/nox/virtualenv.py b/nox/virtualenv.py index 1dec7d0b..501118f9 100644 --- a/nox/virtualenv.py +++ b/nox/virtualenv.py @@ -156,6 +156,8 @@ class PassthroughEnv(ProcessEnv): hints about the actual env. """ + conda_cmd = "conda" + @staticmethod def is_offline() -> bool: """As of now this is only used in conda_install""" @@ -180,10 +182,11 @@ class CondaEnv(ProcessEnv): If not specified, this will use the currently running Python. reuse_existing (Optional[bool]): Flag indicating if the conda environment should be reused if it already exists at ``location``. + conda_cmd (str): The name of the command, can be "conda" (default) or "mamba". """ is_sandboxed = True - allowed_globals = ("conda",) + allowed_globals = ("conda", "mamba") def __init__( self, @@ -191,12 +194,15 @@ def __init__( interpreter: Optional[str] = None, reuse_existing: bool = False, venv_params: Any = None, + *, + conda_cmd: str = "conda", ): self.location_name = location self.location = os.path.abspath(location) self.interpreter = interpreter self.reuse_existing = reuse_existing self.venv_params = venv_params if venv_params else [] + self.conda_cmd = conda_cmd super(CondaEnv, self).__init__() def _clean_location(self) -> bool: @@ -205,7 +211,14 @@ def _clean_location(self) -> bool: if self.reuse_existing: return False else: - cmd = ["conda", "remove", "--yes", "--prefix", self.location, "--all"] + cmd = [ + self.conda_cmd, + "remove", + "--yes", + "--prefix", + self.location, + "--all", + ] nox.command.run(cmd, silent=True, log=False) # Make sure that location is clean try: @@ -233,7 +246,7 @@ def create(self) -> bool: return False - cmd = ["conda", "create", "--yes", "--prefix", self.location] + cmd = [self.conda_cmd, "create", "--yes", "--prefix", self.location] cmd.extend(self.venv_params) diff --git a/tests/test_sessions.py b/tests/test_sessions.py index 6bcd916d..a7d16425 100644 --- a/tests/test_sessions.py +++ b/tests/test_sessions.py @@ -384,7 +384,8 @@ def test_conda_install_not_a_condaenv(self): "auto_offline", [False, True], ids="auto_offline={}".format ) @pytest.mark.parametrize("offline", [False, True], ids="offline={}".format) - def test_conda_install(self, auto_offline, offline): + @pytest.mark.parametrize("conda", ["conda", "mamba"], ids=str) + def test_conda_install(self, auto_offline, offline, conda): runner = nox.sessions.SessionRunner( name="test", signatures=["test"], @@ -396,6 +397,7 @@ def test_conda_install(self, auto_offline, offline): runner.venv.location = "/path/to/conda/env" runner.venv.env = {} runner.venv.is_offline = lambda: offline + runner.venv.conda_cmd = conda class SessionNoSlots(nox.sessions.Session): pass @@ -406,7 +408,7 @@ class SessionNoSlots(nox.sessions.Session): args = ("--offline",) if auto_offline and offline else () session.conda_install("requests", "urllib3", auto_offline=auto_offline) run.assert_called_once_with( - "conda", + conda, "install", "--yes", *args, @@ -434,6 +436,7 @@ def test_conda_venv_reused_with_no_install(self, no_install, reused, run_called) runner.venv.location = "/path/to/conda/env" runner.venv.env = {} runner.venv.is_offline = lambda: True + runner.venv.conda_cmd = "conda" runner.global_config.no_install = no_install runner.venv._reused = reused @@ -460,6 +463,7 @@ def test_conda_install_non_default_kwargs(self, version_constraint): runner.venv.location = "/path/to/conda/env" runner.venv.env = {} runner.venv.is_offline = lambda: False + runner.venv.conda_cmd = "conda" class SessionNoSlots(nox.sessions.Session): pass