diff --git a/src/poetry/core/packages/dependency_group.py b/src/poetry/core/packages/dependency_group.py index e5e95b0b9..9401d1485 100644 --- a/src/poetry/core/packages/dependency_group.py +++ b/src/poetry/core/packages/dependency_group.py @@ -3,12 +3,13 @@ from collections import defaultdict from typing import TYPE_CHECKING +from poetry.core.version.markers import parse_marker + if TYPE_CHECKING: from poetry.core.packages.dependency import Dependency from poetry.core.version.markers import BaseMarker - MAIN_GROUP = "main" @@ -42,9 +43,20 @@ def dependencies_for_locking(self) -> list[Dependency]: for dep in self._dependencies: if dep.name in poetry_dependencies_by_name: enriched = False + dep_marker = dep.marker + if dep.in_extras: + dep_marker = dep.marker.intersect( + parse_marker( + " or ".join( + f"extra == '{extra}'" for extra in dep.in_extras + ) + ) + ) for poetry_dep in poetry_dependencies_by_name[dep.name]: - marker = dep.marker.intersect(poetry_dep.marker) + marker = dep_marker.intersect(poetry_dep.marker) if not marker.is_empty(): + if marker == dep_marker: + marker = dep.marker enriched = True dependencies.append(_enrich_dependency(dep, poetry_dep, marker)) if not enriched: diff --git a/tests/packages/test_dependency_group.py b/tests/packages/test_dependency_group.py index 002bb0d09..b6f189f16 100644 --- a/tests/packages/test_dependency_group.py +++ b/tests/packages/test_dependency_group.py @@ -4,6 +4,8 @@ import pytest +from packaging.utils import canonicalize_name + from poetry.core.packages.dependency import Dependency from poetry.core.packages.dependency_group import DependencyGroup from poetry.core.packages.directory_dependency import DirectoryDependency @@ -15,6 +17,7 @@ def create_dependency( constraint: str = "*", *, extras: tuple[str, ...] = (), + in_extras: tuple[str, ...] = (), allows_prereleases: bool | None = None, develop: bool = False, source_name: str | None = None, @@ -26,6 +29,8 @@ def create_dependency( extras=extras, allows_prereleases=allows_prereleases, ) + if in_extras: + dep._in_extras = [canonicalize_name(extra) for extra in in_extras] if develop: dep._develop = develop if source_name: @@ -260,6 +265,88 @@ def test_remove_dependency_removes_from_both_lists() -> None: [create_dependency("foo", source_name="src")], [create_dependency("foo", source_name="src", marker="extra == 'extra1'")], ), + # extras - special + # root extras do not have an extra marker, they just have set _in_extras! + ( + [ + Dependency.create_from_pep_508("foo;extra!='extra1'"), + create_dependency("foo", in_extras=("extra1",)), + ], + [ + create_dependency("foo", marker="extra!='extra1'", source_name="src1"), + create_dependency("foo", marker="extra=='extra1'", source_name="src2"), + ], + [ + create_dependency("foo", source_name="src1", marker="extra!='extra1'"), + create_dependency("foo", source_name="src2", in_extras=("extra1",)), + ], + ), + ( + [ + Dependency.create_from_pep_508( + "foo;extra!='extra1' and extra!='extra2'" + ), + create_dependency("foo", in_extras=("extra1", "extra2")), + ], + [ + create_dependency( + "foo", + marker="extra!='extra1' and extra!='extra2'", + source_name="src1", + ), + create_dependency( + "foo", + marker="extra=='extra1' or extra=='extra2'", + source_name="src2", + ), + ], + [ + create_dependency( + "foo", + source_name="src1", + marker="extra!='extra1' and extra!='extra2'", + ), + create_dependency( + "foo", source_name="src2", in_extras=("extra1", "extra2") + ), + ], + ), + ( + [ + create_dependency( + "foo", marker="extra!='extra2'", in_extras=("extra1",) + ), + create_dependency( + "foo", marker="extra!='extra1'", in_extras=("extra2",) + ), + ], + [ + create_dependency( + "foo", + marker="extra!='extra2' and extra=='extra1'", + source_name="src1", + ), + create_dependency( + "foo", + marker="extra!='extra1' and extra=='extra2'", + source_name="src2", + ), + ], + [ + create_dependency( + "foo", + source_name="src1", + marker="extra!='extra2'", + in_extras=("extra1",), + ), + create_dependency( + "foo", + source_name="src2", + marker="extra!='extra1'", + in_extras=("extra2",), + ), + ], + ), ], ) def test_dependencies_for_locking( @@ -285,6 +372,9 @@ def test_dependencies_for_locking( assert [d._develop for d in group.dependencies_for_locking] == [ d._develop for d in expected_dependencies ] + assert [d.in_extras for d in group.dependencies_for_locking] == [ + d.in_extras for d in expected_dependencies + ] @pytest.mark.parametrize(