Skip to content

Commit 51accd3

Browse files
authored
Do not conflate extra markers and extra dependencies (#2605)
Resolves #2603
1 parent 529c2a1 commit 51accd3

File tree

3 files changed

+16
-16
lines changed

3 files changed

+16
-16
lines changed

docs/changelog/2603.bugfix.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fix extras not being kept for install dependencies - by :user:`gaborbernat`.

src/tox/tox_env/python/virtual_env/package/util.py

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,20 +7,18 @@
77

88

99
def dependencies_with_extras(deps: list[Requirement], extras: set[str], package_name: str) -> list[Requirement]:
10-
deps = _normalize_req(deps)
10+
deps_with_markers = extract_extra_markers(deps)
1111
result: list[Requirement] = []
1212
found: set[str] = set()
1313
todo: set[str | None] = extras | {None}
1414
visited: set[str | None] = set()
1515
while todo:
1616
new_extras: set[str | None] = set()
17-
for req in deps:
18-
if todo & (req.extras or {None}): # type: ignore[arg-type]
17+
for req, extra_markers in deps_with_markers:
18+
if todo & extra_markers:
1919
if req.name == package_name: # support for recursive extras
2020
new_extras.update(req.extras or set())
2121
else:
22-
req = deepcopy(req)
23-
req.extras.clear() # strip the extra part as the installation will invoke it without
2422
req_str = str(req)
2523
if req_str not in found:
2624
found.add(req_str)
@@ -30,26 +28,27 @@ def dependencies_with_extras(deps: list[Requirement], extras: set[str], package_
3028
return result
3129

3230

33-
def _normalize_req(deps: list[Requirement]) -> list[Requirement]:
31+
def extract_extra_markers(deps: list[Requirement]) -> list[tuple[Requirement, set[str | None]]]:
3432
# extras might show up as markers, move them into extras property
35-
result: list[Requirement] = []
33+
result: list[tuple[Requirement, set[str | None]]] = []
3634
for req in deps:
3735
req = deepcopy(req)
3836
markers: list[str | tuple[Variable, Variable, Variable]] = getattr(req.marker, "_markers", []) or []
3937
_at: int | None = None
38+
extra_markers = set()
4039
for _at, (marker_key, op, marker_value) in (
4140
(_at_marker, marker)
4241
for _at_marker, marker in enumerate(markers)
4342
if isinstance(marker, tuple) and len(marker) == 3
4443
):
4544
if marker_key.value == "extra" and op.value == "==": # pragma: no branch
46-
req.extras.add(marker_value.value)
45+
extra_markers.add(marker_value.value)
4746
del markers[_at]
4847
_at -= 1
4948
if _at > 0 and (isinstance(markers[_at], str) and markers[_at] in ("and", "or")):
5049
del markers[_at]
5150
if len(markers) == 0:
5251
req.marker = None
5352
break
54-
result.append(req)
53+
result.append((req, extra_markers or {None}))
5554
return result

tests/tox_env/python/virtual_env/package/test_python_package_util.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -50,12 +50,12 @@ def test_load_dependency_many_extra(pkg_with_extras: PathDistribution) -> None:
5050
def test_loads_deps_recursive_extras() -> None:
5151
requires = [
5252
Requirement("no-extra"),
53-
Requirement("dep1[dev]"),
54-
Requirement("dep1[test]"),
55-
Requirement("dep2[test]"),
56-
Requirement("dep3[docs]"),
57-
Requirement("name[dev]"),
58-
Requirement("name[test,dev]"),
53+
Requirement('dep1[magic]; extra=="dev"'),
54+
Requirement('dep1; extra=="test"'),
55+
Requirement('dep2[a,b]; extra=="test"'),
56+
Requirement('dep3; extra=="docs"'),
57+
Requirement('name; extra=="dev"'),
58+
Requirement('name[test]; extra=="dev"'),
5959
]
6060
result = dependencies_with_extras(requires, {"dev"}, "name")
61-
assert [str(i) for i in result] == ["no-extra", "dep1", "dep2"]
61+
assert [str(i) for i in result] == ["no-extra", "dep1[magic]", "dep1", "dep2[a,b]"]

0 commit comments

Comments
 (0)