From bb7bc07ee27aaad5f6424fa9ed2a8f36dd4c539d Mon Sep 17 00:00:00 2001 From: Hind Montassif Date: Wed, 29 Jul 2026 12:09:16 +0200 Subject: [PATCH 1/7] Fix help and version of xonsh Add test --- libmamba/data/mamba.xsh | 4 +++- micromamba/tests/test_activation.py | 33 ++++++++++++++++++++++++++++- 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/libmamba/data/mamba.xsh b/libmamba/data/mamba.xsh index 31775802f6..923dbe8d05 100644 --- a/libmamba/data/mamba.xsh +++ b/libmamba/data/mamba.xsh @@ -20,7 +20,9 @@ _REACTIVATE_COMMANDS = ('install', 'update', 'upgrade', 'remove', 'uninstall') def _parse_args(args=None): from argparse import ArgumentParser p = ArgumentParser(add_help=False) - p.add_argument('command') + p.add_argument('command', nargs='?') + p.add_argument('-h', '--help', dest='help', action='store_true', default=False) + p.add_argument('-v', '--version', dest='version', action='store_true', default=False) ns, _ = p.parse_known_args(args) if ns.command == 'activate': p.add_argument('env_name_or_prefix', default='base') diff --git a/micromamba/tests/test_activation.py b/micromamba/tests/test_activation.py index acf1b50904..1e0eb940bf 100644 --- a/micromamba/tests/test_activation.py +++ b/micromamba/tests/test_activation.py @@ -1,6 +1,7 @@ import os import pathlib import platform +import re import shutil import subprocess import tempfile @@ -29,7 +30,7 @@ "bash": ".sh", "zsh": ".sh", "tcsh": ".csh", - "xonsh": ".sh", + "xonsh": ".sh", # TODO this is wrong? is this leading to some bugs in tests here? "fish": ".fish", "powershell": ".ps1", "nu": ".nu", @@ -933,6 +934,36 @@ def test_activate_envs_dirs( assert any([env_name in p for p in dict_res.values()]) +def test_xonsh_help_and_version(tmp_home, tmp_path): + if "xonsh" not in valid_interpreters: + pytest.skip("xonsh not available") + + umamba = helpers.get_umamba() + + root_prefix = tmp_path / "mamba_root" + root_prefix.mkdir() + run_dir = tmp_path / "rundir" + run_dir.mkdir() + os.environ["MAMBA_ROOT_PREFIX"] = str(root_prefix) + + s = [f"{umamba} shell init -r {root_prefix} -s xonsh"] + call_interpreter(s, run_dir, "xonsh") + + def call(s): + return call_interpreter(s, run_dir, "xonsh", interactive=True) + + s = ["micromamba --help"] + stdout, stderr = call(s) + assert not stderr, f"stderr was not empty: {stderr}" + assert "--help" in stdout + assert "Print this help message and exit" in stdout + + s = ["micromamba --version"] + stdout, stderr = call(s) + assert not stderr, f"stderr was not empty: {stderr}" + assert re.search(r"\d+\.\d+\.\d+", stdout.strip()), f"not a version: {stdout}" + + @pytest.fixture def tmp_umamba(): mamba_exe = helpers.get_umamba() From f65f8c6aa25f669c99c6f692a4e6654e8464eeb2 Mon Sep 17 00:00:00 2001 From: Hind Montassif Date: Wed, 29 Jul 2026 12:19:59 +0200 Subject: [PATCH 2/7] Make test runnable in CI --- micromamba/tests/test_activation.py | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/micromamba/tests/test_activation.py b/micromamba/tests/test_activation.py index 1e0eb940bf..bb8ca06c86 100644 --- a/micromamba/tests/test_activation.py +++ b/micromamba/tests/test_activation.py @@ -934,23 +934,17 @@ def test_activate_envs_dirs( assert any([env_name in p for p in dict_res.values()]) -def test_xonsh_help_and_version(tmp_home, tmp_path): +def test_xonsh_help_and_version(tmp_home, tmp_root_prefix, tmp_path): if "xonsh" not in valid_interpreters: pytest.skip("xonsh not available") umamba = helpers.get_umamba() - root_prefix = tmp_path / "mamba_root" - root_prefix.mkdir() - run_dir = tmp_path / "rundir" - run_dir.mkdir() - os.environ["MAMBA_ROOT_PREFIX"] = str(root_prefix) - - s = [f"{umamba} shell init -r {root_prefix} -s xonsh"] - call_interpreter(s, run_dir, "xonsh") + s = [f"{umamba} shell init -r {tmp_root_prefix} -s xonsh"] + call_interpreter(s, tmp_path, "xonsh") def call(s): - return call_interpreter(s, run_dir, "xonsh", interactive=True) + return call_interpreter(s, tmp_path, "xonsh", interactive=True) s = ["micromamba --help"] stdout, stderr = call(s) From f5697ee6f33e5f967c0604194ad987a4473afff3 Mon Sep 17 00:00:00 2001 From: Hind Montassif Date: Wed, 29 Jul 2026 15:11:01 +0200 Subject: [PATCH 3/7] Remove comment --- micromamba/tests/test_activation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/micromamba/tests/test_activation.py b/micromamba/tests/test_activation.py index bb8ca06c86..e27097d885 100644 --- a/micromamba/tests/test_activation.py +++ b/micromamba/tests/test_activation.py @@ -30,7 +30,7 @@ "bash": ".sh", "zsh": ".sh", "tcsh": ".csh", - "xonsh": ".sh", # TODO this is wrong? is this leading to some bugs in tests here? + "xonsh": ".sh", "fish": ".fish", "powershell": ".ps1", "nu": ".nu", From 5345c5c06a8476d0ca4d83590c92aa977a1b1215 Mon Sep 17 00:00:00 2001 From: Hind Montassif Date: Thu, 30 Jul 2026 16:01:01 +0200 Subject: [PATCH 4/7] Fix del var crash with xonsh --- libmamba/src/core/activation.cpp | 2 +- micromamba/tests/test_activation.py | 31 +++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/libmamba/src/core/activation.cpp b/libmamba/src/core/activation.cpp index da261b0926..9bd5a324f4 100644 --- a/libmamba/src/core/activation.cpp +++ b/libmamba/src/core/activation.cpp @@ -1123,7 +1123,7 @@ namespace mamba for (const std::string& uvar : env_transform.unset_vars) { - out << "del $" << uvar << "\n"; + out << "try:\n del $" << uvar << "\nexcept KeyError:\n pass\n"; } for (const auto& [skey, svar] : env_transform.set_vars) diff --git a/micromamba/tests/test_activation.py b/micromamba/tests/test_activation.py index e27097d885..9984c160b6 100644 --- a/micromamba/tests/test_activation.py +++ b/micromamba/tests/test_activation.py @@ -958,6 +958,37 @@ def call(s): assert re.search(r"\d+\.\d+\.\d+", stdout.strip()), f"not a version: {stdout}" +def test_xonsh_del_nonexistent_env_var(tmp_home, tmp_root_prefix, tmp_path): + if "xonsh" not in valid_interpreters: + pytest.skip("xonsh not available") + + umamba = helpers.get_umamba() + + s = [f"{umamba} shell init -r {tmp_root_prefix} -s xonsh"] + call_interpreter(s, tmp_path, "xonsh") + + def call(s): + return call_interpreter(s, tmp_path, "xonsh", interactive=True) + + helpers.create("-n", "test_unset_env", "--offline", "--no-rc", no_dry_run=True) + + prefix = tmp_root_prefix / "envs" / "test_unset_env" + state_file = prefix / "conda-meta" / "state" + state_file.write_text(helpers.json.dumps({"env_vars": {"MAMBA_UNSET_TEST": "hello"}})) + + # activate → manually delete var → deactivate + s = [ + "micromamba activate test_unset_env", + "del $MAMBA_UNSET_TEST", + "micromamba deactivate", + ] + + try: + stdout, stderr = call(s) + except subprocess.CalledProcessError: + pytest.fail("deactivate crashed on del of non-existent env var") + + @pytest.fixture def tmp_umamba(): mamba_exe = helpers.get_umamba() From 17e6a6d939eae7cbbc74f1d0fc4247b4a85ef9ab Mon Sep 17 00:00:00 2001 From: Hind Montassif Date: Thu, 30 Jul 2026 17:50:49 +0200 Subject: [PATCH 5/7] Add mamba alias --- libmamba/data/mamba.xsh | 1 + micromamba/tests/test_activation.py | 14 ++++++++------ 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/libmamba/data/mamba.xsh b/libmamba/data/mamba.xsh index 923dbe8d05..3c5afd4942 100644 --- a/libmamba/data/mamba.xsh +++ b/libmamba/data/mamba.xsh @@ -93,6 +93,7 @@ if 'CONDA_SHLVL' not in ${...}: aliases['micromamba'] = _micromamba_main +aliases['mamba'] = _micromamba_main @contextual_command_completer diff --git a/micromamba/tests/test_activation.py b/micromamba/tests/test_activation.py index 9984c160b6..6b846c6404 100644 --- a/micromamba/tests/test_activation.py +++ b/micromamba/tests/test_activation.py @@ -934,7 +934,8 @@ def test_activate_envs_dirs( assert any([env_name in p for p in dict_res.values()]) -def test_xonsh_help_and_version(tmp_home, tmp_root_prefix, tmp_path): +@pytest.mark.parametrize("alias", ["micromamba", "mamba"]) +def test_xonsh_help_and_version(tmp_home, tmp_root_prefix, tmp_path, alias): if "xonsh" not in valid_interpreters: pytest.skip("xonsh not available") @@ -946,19 +947,20 @@ def test_xonsh_help_and_version(tmp_home, tmp_root_prefix, tmp_path): def call(s): return call_interpreter(s, tmp_path, "xonsh", interactive=True) - s = ["micromamba --help"] + s = [f"{alias} --help"] stdout, stderr = call(s) assert not stderr, f"stderr was not empty: {stderr}" assert "--help" in stdout assert "Print this help message and exit" in stdout - s = ["micromamba --version"] + s = [f"{alias} --version"] stdout, stderr = call(s) assert not stderr, f"stderr was not empty: {stderr}" assert re.search(r"\d+\.\d+\.\d+", stdout.strip()), f"not a version: {stdout}" -def test_xonsh_del_nonexistent_env_var(tmp_home, tmp_root_prefix, tmp_path): +@pytest.mark.parametrize("alias", ["micromamba", "mamba"]) +def test_xonsh_del_nonexistent_env_var(tmp_home, tmp_root_prefix, tmp_path, alias): if "xonsh" not in valid_interpreters: pytest.skip("xonsh not available") @@ -978,9 +980,9 @@ def call(s): # activate → manually delete var → deactivate s = [ - "micromamba activate test_unset_env", + f"{alias} activate test_unset_env", "del $MAMBA_UNSET_TEST", - "micromamba deactivate", + f"{alias} deactivate", ] try: From 6a90761af2b71f86e9d34e6f9717d7f625b89abe Mon Sep 17 00:00:00 2001 From: Hind Montassif Date: Fri, 31 Jul 2026 11:44:22 +0200 Subject: [PATCH 6/7] Use prefix_or_name as positional arg --- libmamba/data/mamba.xsh | 4 ++-- micromamba/tests/test_activation.py | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/libmamba/data/mamba.xsh b/libmamba/data/mamba.xsh index 3c5afd4942..cefacab6c0 100644 --- a/libmamba/data/mamba.xsh +++ b/libmamba/data/mamba.xsh @@ -46,9 +46,9 @@ def _raise_pipeline_error(pipeline): def _mamba_activate_handler(env_name_or_prefix=None): if env_name_or_prefix == 'base' or not env_name_or_prefix: env_name_or_prefix = $MAMBA_ROOT_PREFIX - __xonsh__.execer.exec($($MAMBA_EXE shell activate -s xonsh -p @(env_name_or_prefix)), + __xonsh__.execer.exec($($MAMBA_EXE shell activate -s xonsh @(env_name_or_prefix)), glbs=__xonsh__.ctx, - filename="$($MAMBA_EXE shell activate -s xonsh -p " + env_name_or_prefix + ")") + filename="$($MAMBA_EXE shell activate -s xonsh " + env_name_or_prefix + ")") def _mamba_deactivate_handler(): diff --git a/micromamba/tests/test_activation.py b/micromamba/tests/test_activation.py index 6b846c6404..9118f2ffaf 100644 --- a/micromamba/tests/test_activation.py +++ b/micromamba/tests/test_activation.py @@ -990,6 +990,8 @@ def call(s): except subprocess.CalledProcessError: pytest.fail("deactivate crashed on del of non-existent env var") + assert "does not contain any filesystem separator" not in stderr + @pytest.fixture def tmp_umamba(): From f815f3a0ca85e9c1fac75600d6a40c56146266c5 Mon Sep 17 00:00:00 2001 From: Hind Montassif Date: Wed, 5 Aug 2026 11:49:50 +0200 Subject: [PATCH 7/7] Review: Use skipif --- micromamba/tests/test_activation.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/micromamba/tests/test_activation.py b/micromamba/tests/test_activation.py index 9118f2ffaf..a3593b58d0 100644 --- a/micromamba/tests/test_activation.py +++ b/micromamba/tests/test_activation.py @@ -934,11 +934,12 @@ def test_activate_envs_dirs( assert any([env_name in p for p in dict_res.values()]) +@pytest.mark.skipif( + "xonsh" not in valid_interpreters, + reason="xonsh not available", +) @pytest.mark.parametrize("alias", ["micromamba", "mamba"]) def test_xonsh_help_and_version(tmp_home, tmp_root_prefix, tmp_path, alias): - if "xonsh" not in valid_interpreters: - pytest.skip("xonsh not available") - umamba = helpers.get_umamba() s = [f"{umamba} shell init -r {tmp_root_prefix} -s xonsh"] @@ -959,11 +960,12 @@ def call(s): assert re.search(r"\d+\.\d+\.\d+", stdout.strip()), f"not a version: {stdout}" +@pytest.mark.skipif( + "xonsh" not in valid_interpreters, + reason="xonsh not available", +) @pytest.mark.parametrize("alias", ["micromamba", "mamba"]) def test_xonsh_del_nonexistent_env_var(tmp_home, tmp_root_prefix, tmp_path, alias): - if "xonsh" not in valid_interpreters: - pytest.skip("xonsh not available") - umamba = helpers.get_umamba() s = [f"{umamba} shell init -r {tmp_root_prefix} -s xonsh"]