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

Micromamba tests improvements #2517

Merged
merged 6 commits into from
May 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
145 changes: 87 additions & 58 deletions micromamba/tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,24 @@


def pytest_addoption(parser):
"""Add pkgs-dir command line argument to pytest."""
"""Add command line argument to pytest."""
parser.addoption(
"--mamba-pkgs-dir",
action="store",
default=None,
help="Package cache to resuse between tests",
help="Package cache to reuse between tests",
)
parser.addoption(
"--no-eager-clean",
action="store_true",
default=False,
help=(
"Do not eagerly delete temporary folders such as HOME and MAMBA_ROOT_PREFIX"
"created during tests."
"These folders take a lot of disk space so we delete them eagerly."
"For debugging, it can be convenient to keep them."
"With this option, cleaning will fallback on the default pytest policy."
),
)


Expand All @@ -28,48 +40,7 @@ def pytest_addoption(parser):
##################


@pytest.fixture
def tmp_home(tmp_path: pathlib.Path) -> Generator[pathlib.Path, None, None]:
"""Change the home directory to a tmp folder for the duration of a test."""
# Try multiple combination for Unix/Windows
home_envs = ["HOME", "USERPROFILE"]
old_homes = {name: os.environ.get(name) for name in home_envs}

if len(home_envs) > 0:
new_home = tmp_path / "home"
new_home.mkdir(parents=True, exist_ok=True)
for env in home_envs:
os.environ[env] = str(new_home)
yield new_home
for env, home in old_homes.items():
if old_homes[env] is None:
del os.environ[env]
else:
os.environ[env] = home
else:
yield pathlib.Path.home()


@pytest.fixture(scope="session")
def tmp_pkgs_dirs(tmp_path_factory: pytest.TempPathFactory, request) -> pathlib.Path:
"""A common package cache for mamba downloads.

The directory is not used automatically when calling this fixture.
"""
if (p := request.config.getoption("--mamba-pkgs-dir")) is not None:
p = pathlib.Path(p)
p.mkdir(parents=True, exist_ok=True)
return p
return tmp_path_factory.mktemp("pkgs_dirs")


@pytest.fixture(params=[False])
def shared_pkgs_dirs(request) -> bool:
"""A dummy fixture to control the use of shared package dir."""
return request.param


@pytest.fixture
@pytest.fixture(autouse=True)
def tmp_environ() -> Generator[Mapping[str, Any], None, None]:
"""Saves and restore environment variables.

Expand All @@ -82,9 +53,31 @@ def tmp_environ() -> Generator[Mapping[str, Any], None, None]:


@pytest.fixture
def tmp_clean_env(
tmp_pkgs_dirs: pathlib.Path, shared_pkgs_dirs: bool, tmp_environ: None
) -> Generator[None, None, None]:
def tmp_home(
request, tmp_environ, tmp_path_factory: pytest.TempPathFactory
) -> Generator[pathlib.Path, None, None]:
"""Change the home directory to a tmp folder for the duration of a test."""
# Try multiple combination for Unix/Windows
home_envs = ["HOME", "USERPROFILE"]
used_homes = [env for env in home_envs if env in os.environ]

new_home = pathlib.Path.home()
if len(used_homes) > 0:
new_home = tmp_path_factory.mktemp("home")
new_home.mkdir(parents=True, exist_ok=True)
for env in used_homes:
os.environ[env] = str(new_home)

yield new_home

# Pytest would clean it automatically but this can be large (0.5 Gb for repodata)
# We clean it explicitly
if not request.config.getoption("--no-eager-clean"):
helpers.rmtree(new_home)


@pytest.fixture
def tmp_clean_env(tmp_environ: None) -> None:
"""Remove all Conda/Mamba activation artifacts from environment."""
for k, v in os.environ.items():
if k.startswith(("CONDA", "_CONDA", "MAMBA", "_MAMBA")):
Expand All @@ -105,38 +98,67 @@ def keep_in_path(
path_list = os.environ["PATH"].split(os.pathsep)
path_list = [p for p in path_list if keep_in_path(p)]
os.environ["PATH"] = os.pathsep.join(path_list)
# os.environ restored by tmp_clean_env and tmp_environ

if shared_pkgs_dirs:
os.environ["CONDA_PKGS_DIRS"] = str(tmp_pkgs_dirs)

yield None
@pytest.fixture(scope="session")
def tmp_pkgs_dirs(tmp_path_factory: pytest.TempPathFactory, request) -> pathlib.Path:
"""A common package cache for mamba downloads.

The directory is not used automatically when calling this fixture.
"""
if (p := request.config.getoption("--mamba-pkgs-dir")) is not None:
p = pathlib.Path(p)
p.mkdir(parents=True, exist_ok=True)
return p

@pytest.fixture(params=[helpers.random_string, "long_prefix_" * 20])
def tmp_env_name(request) -> str:
"""Return the explicit or implicit parametrization."""
if callable(request.param):
return request.param()
return tmp_path_factory.mktemp("pkgs_dirs")


@pytest.fixture(params=[False])
def shared_pkgs_dirs(request) -> bool:
"""A dummy fixture to control the use of shared package dir."""
return request.param


@pytest.fixture
def tmp_root_prefix(
tmp_path: pathlib.Path, tmp_clean_env: None
request,
tmp_path_factory: pytest.TempPathFactory,
tmp_clean_env: None,
tmp_pkgs_dirs: pathlib.Path,
shared_pkgs_dirs: bool,
) -> Generator[pathlib.Path, None, None]:
"""Change the micromamba root directory to a tmp folder for the duration of a test."""
new_root_prefix = tmp_path / "mamba"
new_root_prefix = tmp_path_factory.mktemp("mamba")
new_root_prefix.mkdir(parents=True, exist_ok=True)
os.environ["MAMBA_ROOT_PREFIX"] = str(new_root_prefix)

if shared_pkgs_dirs:
os.environ["CONDA_PKGS_DIRS"] = str(tmp_pkgs_dirs)

yield new_root_prefix

# Pytest would clean it automatically but this can be large (0.5 Gb for repodata)
# We clean it explicitly
if not request.config.getoption("--no-eager-clean"):
helpers.rmtree(new_root_prefix)
# os.environ restored by tmp_clean_env and tmp_environ


@pytest.fixture(params=[helpers.random_string, "long_prefix_" * 20])
def tmp_env_name(request) -> str:
"""Return the explicit or implicit parametrization."""
if callable(request.param):
return request.param()
return request.param


@pytest.fixture
def tmp_empty_env(
tmp_root_prefix: pathlib.Path, tmp_env_name: str
) -> Generator[pathlib.Path, None, None]:
"""An empty envirnment created under a temporary root prefix."""
"""An empty environment created under a temporary root prefix."""
helpers.create("-n", tmp_env_name, no_dry_run=True)
yield tmp_root_prefix / "envs" / tmp_env_name

Expand All @@ -147,3 +169,10 @@ def tmp_prefix(tmp_empty_env: pathlib.Path) -> Generator[pathlib.Path, None, Non
os.environ["CONDA_PREFIX"] = str(tmp_empty_env)
yield tmp_empty_env
# os.environ restored by tmp_environ through tmp_root_prefix


@pytest.fixture
def tmp_xtensor_env(tmp_prefix: pathlib.Path) -> Generator[pathlib.Path, None, None]:
"""An activated environment with Xtensor installed."""
helpers.install("-c", "conda-forge", "--json", "xtensor", no_dry_run=True)
yield tmp_prefix
16 changes: 10 additions & 6 deletions micromamba/tests/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,12 +52,16 @@ class DryRun(Enum):
MAMBA_NOT_ALLOW_NOT_ENV_PREFIX = 0
MAMBA_NOT_EXPECT_EXISTING_PREFIX = 0

if platform.system() == "Windows":
xtensor_hpp = "Library/include/xtensor/xtensor.hpp"
xsimd_hpp = "Library/include/xsimd/xsimd.hpp"
else:
xtensor_hpp = "include/xtensor/xtensor.hpp"
xsimd_hpp = "include/xsimd/xsimd.hpp"

def lib_prefix() -> Path:
"""A potential prefix used for library in Conda environments."""
if platform.system() == "Windows":
return Path("Library")
return Path("")


xtensor_hpp = lib_prefix() / "include/xtensor/xtensor.hpp"
xsimd_hpp = lib_prefix() / "include/xsimd/xsimd.hpp"


def get_umamba(cwd=os.getcwd()):
Expand Down
2 changes: 1 addition & 1 deletion micromamba/tests/test_activation.py
Original file line number Diff line number Diff line change
Expand Up @@ -960,7 +960,7 @@ def test_self_update(
else:
print(mamba_exe)
extra_start_code = [
"source ~/.bash_profile",
f"source {PurePosixPath(tmp_home)}/.bash_profile", # HOME from os.environ not acknowledged
"micromamba info",
"echo $MAMBA_ROOT_PREFIX",
"echo $HOME",
Expand Down
Loading