Skip to content

Commit

Permalink
Merge pull request conda#768 from romain-intel/fix/transitive_deps
Browse files Browse the repository at this point in the history
Fix an issue that caused transitive dependencies to not have categories
  • Loading branch information
maresb authored Feb 2, 2025
2 parents 306e074 + 3089a39 commit 15841fc
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 4 deletions.
7 changes: 6 additions & 1 deletion conda_lock/lockfile/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,12 @@ def dep_name(*, manager: str, dep: str, mapping_url: str) -> str:
# `dask-core` as packages that are planned to be installed.
planned_items = extract_planned_items(_seperator_munge_get(planned, item))

if item != name:
# Add item to deps *after* extracting dependencies otherwise we do not
# properly mark all transitive dependencies as part of the same
# category.
deps.add(item)

for planned_item in planned_items:
todo.extend(
dep_name(
Expand All @@ -135,7 +141,6 @@ def dep_name(*, manager: str, dep: str, mapping_url: str) -> str:
)
if todo:
item = todo.pop(0)
deps.add(item)
else:
break

Expand Down
69 changes: 66 additions & 3 deletions tests/test_conda_lock.py
Original file line number Diff line number Diff line change
Expand Up @@ -2061,6 +2061,69 @@ def test_solve_arch_multiple_categories():
assert numpy_deps[0].categories == {"test", "dev"}


def test_solve_arch_transitive_deps():
_conda_exe = determine_conda_executable(None, mamba=False, micromamba=False)
channels = [Channel.from_string("conda-forge")]

with tempfile.NamedTemporaryFile(dir=".") as tf:
spec = LockSpecification(
dependencies={
"linux-64": [
VersionedDependency(
name="python",
version="=3.10.9",
manager="conda",
category="main",
extras=[],
),
VersionedDependency(
name="pip",
version="=24.2",
manager="conda",
category="main",
extras=[],
),
VersionedDependency(
name="jupyter",
version="=1.1.1",
manager="pip",
category="main",
extras=[],
),
],
},
channels=channels,
# NB: this file must exist for relative path resolution to work
# in create_lockfile_from_spec
sources=[Path(tf.name)],
)

vpr = default_virtual_package_repodata()
with vpr:
locked_deps = _solve_for_arch(
conda=_conda_exe,
spec=spec,
platform="linux-64",
channels=channels,
pip_repositories=[],
virtual_package_repo=vpr,
mapping_url=DEFAULT_MAPPING_URL,
)
python_deps = [dep for dep in locked_deps if dep.name == "python"]
assert len(python_deps) == 1
assert python_deps[0].categories == {"main"}

jupyter_deps = [dep for dep in locked_deps if dep.name == "jupyter"]
assert len(jupyter_deps) == 1
assert jupyter_deps[0].categories == {"main"}

# ipython is a transitive dependency of jupyter
ipython_deps = [dep for dep in locked_deps if dep.name == "ipython"]
assert len(ipython_deps) == 1
# Ensure that transitive dependencies are also properly tagged
assert ipython_deps[0].categories == {"main"}


def _check_package_installed(package: str, prefix: str, subdir: Optional[str] = None):
files = list(glob(f"{prefix}/conda-meta/{package}-*.json"))
assert len(files) >= 1
Expand Down Expand Up @@ -2895,9 +2958,9 @@ def test_get_pkgs_dirs_mocked_output(info_file: str, expected: Optional[List[Pat

with mock.patch("subprocess.check_output", return_value=command_output):
# If expected is None, we expect a ValueError to be raised
with pytest.raises(
ValueError
) if expected is None else contextlib.nullcontext():
with (
pytest.raises(ValueError) if expected is None else contextlib.nullcontext()
):
result = _get_pkgs_dirs(conda=conda, platform="linux-64", method=method)
assert result == expected

Expand Down

0 comments on commit 15841fc

Please sign in to comment.