Skip to content

Commit

Permalink
Drop classic solver workaround if conda-libmamba-solver is at least 24.1
Browse files Browse the repository at this point in the history
Fixes #118
  • Loading branch information
analog-cbarber committed Apr 13, 2024
1 parent 7d4131c commit e040d7e
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 17 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
# whl2conda changes

## [24.4.0] - *in progress*
### Changes
* Only use classic installer in `whl2conda install` environments if
`conda-libmamba-solver` in base environment has version less than 24.1.0 (see #118)

### Bug fixes
* Transfer executable file permissions from wheel (#135)
* Correct typos in documentation.
Expand Down
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ ruff:
check-format:
$(CONDA_RUN) ruff format --check src test

.PHONY: test
test: pytest

coverage:
Expand Down
27 changes: 18 additions & 9 deletions src/whl2conda/cli/install.py
Original file line number Diff line number Diff line change
Expand Up @@ -286,17 +286,26 @@ def conda_env_install(parsed: InstallArgs, dependencies: list[str]):
else:
subprocess.check_call(install_pkg_cmd)

# Workaround for https://github.com/conda/conda/issues/13479
# If a package is installed directly from file, then set solver to classic
set_solver_cmd = (
["conda", "run"]
+ env_opts
+ ["conda", "config", "--env", "--set", "solver", "classic"]
)
check_libmamba_cmd = "conda list -n base conda-libmamba-solver --json".split()
if parsed.dry_run:
print("Running ", set_solver_cmd)
print("running ", check_libmamba_cmd)
else:
subprocess.check_call(set_solver_cmd)
jsonstr = subprocess.check_output(check_libmamba_cmd, encoding="utf-8")
jobj = json.loads(jsonstr)
version_str = jobj and jobj[0].get("version")
version = tuple(int(s) for s in version_str.split("."))
if version < (24, 1, 0):
# Workaround for https://github.com/conda/conda/issues/13479
# If a package is installed directly from file, then set solver to classic
set_solver_cmd = (
["conda", "run"]
+ env_opts
+ ["conda", "config", "--env", "--set", "solver", "classic"]
)
if parsed.dry_run:
print("Running ", set_solver_cmd)

Check warning on line 306 in src/whl2conda/cli/install.py

View check run for this annotation

Codecov / codecov/patch

src/whl2conda/cli/install.py#L306

Added line #L306 was not covered by tests
else:
subprocess.check_call(set_solver_cmd)


conda_depend_re = re.compile(r"\s*(?P<name>[\w\d.-]+)\s*(?P<version>.*)")
Expand Down
64 changes: 56 additions & 8 deletions test/cli/test_install.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

import re
from pathlib import Path
from textwrap import dedent
from typing import Any, Sequence

import pytest
Expand Down Expand Up @@ -187,13 +188,6 @@ def test_env_install(
assert "quaternion" in packages_by_name
assert "simple" in packages_by_name

# solver should be set to classic to avoid https://github.com/conda/conda/issues/13479
d = conda_json(
"run", "-p", str(prefix), "conda", "config", "--json", "--show", "solver"
)
assert d["solver"] == "classic"

conda_output("create", "-n", "test-env", "python=3.9")
assert test_env.is_dir()

main([
Expand Down Expand Up @@ -223,9 +217,36 @@ def test_env_install_whitebox(
prefix = tmp_path.joinpath("prefix")

call_args: list[list[str]] = []
fake_call_results: list[Any] = [
None,
None,
dedent(
"""
[
{
"base_url": "https://conda.anaconda.org/conda-forge",
"build_number": 0,
"build_string": "pyhd8ed1ab_0",
"channel": "conda-forge",
"dist_name": "conda-libmamba-solver-24.1.0-pyhd8ed1ab_0",
"name": "conda-libmamba-solver",
"platform": "noarch",
"version": "24.1.0"
}
]
"""
),
]

def fake_call(cmd: Sequence[str]) -> Any:
def fake_call(cmd: Sequence[str], encoding=None) -> Any:
if encoding:
assert encoding == "utf-8"
i = len(call_args)
call_args.append(list(cmd))
if len(fake_call_results) > i:
return fake_call_results[i]
else:
return None

monkeypatch.setattr("subprocess.check_call", fake_call)
monkeypatch.setattr("subprocess.check_output", fake_call)
Expand Down Expand Up @@ -283,6 +304,33 @@ def fake_call(cmd: Sequence[str]) -> Any:
out, err = capsys.readouterr()
assert "Running" in out

# Test for presence of conda solver workaround for conda-libmamba-solver < 24.1
call_args.clear()
fake_call_results[2] = dedent(
"""
[
{
"base_url": "https://conda.anaconda.org/conda-forge",
"build_number": 0,
"build_string": "pyhd8ed1ab_0",
"channel": "conda-forge",
"dist_name": "conda-libmamba-solver-23.12.0-pyhd8ed1ab_0",
"name": "conda-libmamba-solver",
"platform": "noarch",
"version": "23.12.0"
}
]
"""
)

main(cmd_start + ["--name", "test-env", "--create", "--mamba"])
assert len(call_args) == 4
call4 = call_args[3]
assert call4[:4] == "conda run --name test-env".split()
assert call4[4:6] == "conda config".split()
assert "--set solver classic" in " ".join(call4)
assert "--env" in call4


def test_prune_dependencies() -> None:
"""Unit test for internal _prune_dependencies function"""
Expand Down

0 comments on commit e040d7e

Please sign in to comment.