Skip to content

Commit a20e333

Browse files
committed
mixology: choose direct ref deps when merging
1 parent dea91b7 commit a20e333

File tree

2 files changed

+34
-6
lines changed

2 files changed

+34
-6
lines changed

src/poetry/mixology/term.py

+29-5
Original file line numberDiff line numberDiff line change
@@ -127,17 +127,17 @@ def intersect(self, other: Term) -> Term | None:
127127
negative = other if self.is_positive() else self
128128

129129
return self._non_empty_term(
130-
positive.constraint.difference(negative.constraint), True
130+
positive.constraint.difference(negative.constraint), True, other
131131
)
132132
elif self.is_positive():
133133
# foo ^1.0.0 ∩ foo >=1.5.0 <3.0.0 → foo ^1.5.0
134134
return self._non_empty_term(
135-
self.constraint.intersect(other.constraint), True
135+
self.constraint.intersect(other.constraint), True, other
136136
)
137137
else:
138138
# not foo ^1.0.0 ∩ not foo >=1.5.0 <3.0.0 → not foo >=1.0.0 <3.0.0
139139
return self._non_empty_term(
140-
self.constraint.union(other.constraint), False
140+
self.constraint.union(other.constraint), False, other
141141
)
142142
elif self.is_positive() != other.is_positive():
143143
return self if self.is_positive() else other
@@ -151,21 +151,45 @@ def difference(self, other: Term) -> Term | None:
151151
"""
152152
return self.intersect(other.inverse)
153153

154+
@staticmethod
155+
def _is_direct_reference(dependency: Dependency) -> bool:
156+
return dependency.source_type in ["directory", "file", "url", "git"]
157+
154158
def _compatible_dependency(self, other: Dependency) -> bool:
155159
compatible: bool = (
156160
self.dependency.is_root
157161
or other.is_root
158162
or other.is_same_package_as(self.dependency)
159163
)
164+
165+
if (
166+
not compatible
167+
and not self._is_direct_reference(self.dependency)
168+
and self._is_direct_reference(other)
169+
):
170+
# we do this here to indicate direct reference dependencies are compatible
171+
# with NVR dependencies
172+
return (
173+
self.dependency.complete_name == other.complete_name
174+
and self.dependency.constraint.allows_all(other.constraint)
175+
)
176+
160177
return compatible
161178

162179
def _non_empty_term(
163-
self, constraint: VersionConstraint, is_positive: bool
180+
self, constraint: VersionConstraint, is_positive: bool, other: Term
164181
) -> Term | None:
165182
if constraint.is_empty():
166183
return None
167184

168-
return Term(self.dependency.with_constraint(constraint), is_positive)
185+
# when creating a new term prefer direct-reference dependencies
186+
dependency = (
187+
other.dependency
188+
if not self._is_direct_reference(self.dependency)
189+
and self._is_direct_reference(other.dependency)
190+
else self.dependency
191+
)
192+
return Term(dependency.with_constraint(constraint), is_positive)
169193

170194
def __str__(self) -> str:
171195
prefix = "not " if not self.is_positive() else ""

tests/puzzle/test_solver.py

+5-1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
from poetry.repositories.pool import Pool
2323
from poetry.repositories.repository import Repository
2424
from poetry.utils.env import MockEnv
25+
from tests.compat import is_poetry_core_1_1_0a7_compat
2526
from tests.helpers import get_dependency
2627
from tests.helpers import get_package
2728
from tests.repositories.test_legacy_repository import (
@@ -1383,7 +1384,10 @@ def test_solver_duplicate_dependencies_different_sources_types_are_preserved(
13831384

13841385
assert len(complete_package.all_requires) == 2
13851386

1386-
pypi, git = complete_package.all_requires
1387+
if is_poetry_core_1_1_0a7_compat:
1388+
pypi, git = complete_package.all_requires
1389+
else:
1390+
git, pypi = complete_package.all_requires
13871391

13881392
assert isinstance(pypi, Dependency)
13891393
assert pypi == dependency_pypi

0 commit comments

Comments
 (0)