Skip to content

Commit

Permalink
feat: add mamba environment (#448)
Browse files Browse the repository at this point in the history
* feat: add mamba environment

* tests: fix issues and add a simple mamba test

* docs: mention mamba

* Update docs/tutorial.rst

Co-authored-by: Claudio Jolowicz <cjolowicz@gmail.com>

Co-authored-by: Claudio Jolowicz <cjolowicz@gmail.com>
Co-authored-by: Claudio Jolowicz <mail@claudiojolowicz.com>
  • Loading branch information
3 people committed Dec 22, 2021
1 parent f4037b2 commit 2a19748
Show file tree
Hide file tree
Showing 6 changed files with 30 additions and 9 deletions.
2 changes: 1 addition & 1 deletion docs/config.rst
Expand Up @@ -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
Expand Down
3 changes: 3 additions & 0 deletions docs/tutorial.rst
Expand Up @@ -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 <https://github.com/mamba-org/mamba>`_ instead of conda.


Parametrization
---------------
Expand Down
2 changes: 1 addition & 1 deletion docs/usage.rst
Expand Up @@ -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 <backend>`` or ``--default-venv-backend <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 <backend>`` or ``--default-venv-backend <backend>``. Supported names are ``('none', 'virtualenv', 'conda', 'mamba', 'venv')``.

.. code-block:: console
Expand Down
5 changes: 3 additions & 2 deletions nox/sessions.py
Expand Up @@ -421,7 +421,7 @@ def conda_install(
extraopts = ("--offline",)

self._run(
"conda",
venv.conda_cmd,
"install",
"--yes",
*extraopts,
Expand Down Expand Up @@ -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(
Expand Down
19 changes: 16 additions & 3 deletions nox/virtualenv.py
Expand Up @@ -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"""
Expand All @@ -180,23 +182,27 @@ 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,
location: str,
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:
Expand All @@ -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:
Expand Down Expand Up @@ -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)

Expand Down
8 changes: 6 additions & 2 deletions tests/test_sessions.py
Expand Up @@ -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"],
Expand All @@ -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
Expand All @@ -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,
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand Down

0 comments on commit 2a19748

Please sign in to comment.