Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add mamba environment #448

Merged
merged 6 commits into from Dec 22, 2021
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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