Skip to content

Commit

Permalink
mixology: choose direct ref deps when merging
Browse files Browse the repository at this point in the history
  • Loading branch information
abn committed May 20, 2022
1 parent dea91b7 commit a20e333
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 6 deletions.
34 changes: 29 additions & 5 deletions src/poetry/mixology/term.py
Original file line number Diff line number Diff line change
Expand Up @@ -127,17 +127,17 @@ def intersect(self, other: Term) -> Term | None:
negative = other if self.is_positive() else self

return self._non_empty_term(
positive.constraint.difference(negative.constraint), True
positive.constraint.difference(negative.constraint), True, other
)
elif self.is_positive():
# foo ^1.0.0 ∩ foo >=1.5.0 <3.0.0 → foo ^1.5.0
return self._non_empty_term(
self.constraint.intersect(other.constraint), True
self.constraint.intersect(other.constraint), True, other
)
else:
# not foo ^1.0.0 ∩ not foo >=1.5.0 <3.0.0 → not foo >=1.0.0 <3.0.0
return self._non_empty_term(
self.constraint.union(other.constraint), False
self.constraint.union(other.constraint), False, other
)
elif self.is_positive() != other.is_positive():
return self if self.is_positive() else other
Expand All @@ -151,21 +151,45 @@ def difference(self, other: Term) -> Term | None:
"""
return self.intersect(other.inverse)

@staticmethod
def _is_direct_reference(dependency: Dependency) -> bool:
return dependency.source_type in ["directory", "file", "url", "git"]

def _compatible_dependency(self, other: Dependency) -> bool:
compatible: bool = (
self.dependency.is_root
or other.is_root
or other.is_same_package_as(self.dependency)
)

if (
not compatible
and not self._is_direct_reference(self.dependency)
and self._is_direct_reference(other)
):
# we do this here to indicate direct reference dependencies are compatible
# with NVR dependencies
return (
self.dependency.complete_name == other.complete_name
and self.dependency.constraint.allows_all(other.constraint)
)

return compatible

def _non_empty_term(
self, constraint: VersionConstraint, is_positive: bool
self, constraint: VersionConstraint, is_positive: bool, other: Term
) -> Term | None:
if constraint.is_empty():
return None

return Term(self.dependency.with_constraint(constraint), is_positive)
# when creating a new term prefer direct-reference dependencies
dependency = (
other.dependency
if not self._is_direct_reference(self.dependency)
and self._is_direct_reference(other.dependency)
else self.dependency
)
return Term(dependency.with_constraint(constraint), is_positive)

def __str__(self) -> str:
prefix = "not " if not self.is_positive() else ""
Expand Down
6 changes: 5 additions & 1 deletion tests/puzzle/test_solver.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
from poetry.repositories.pool import Pool
from poetry.repositories.repository import Repository
from poetry.utils.env import MockEnv
from tests.compat import is_poetry_core_1_1_0a7_compat
from tests.helpers import get_dependency
from tests.helpers import get_package
from tests.repositories.test_legacy_repository import (
Expand Down Expand Up @@ -1383,7 +1384,10 @@ def test_solver_duplicate_dependencies_different_sources_types_are_preserved(

assert len(complete_package.all_requires) == 2

pypi, git = complete_package.all_requires
if is_poetry_core_1_1_0a7_compat:
pypi, git = complete_package.all_requires
else:
git, pypi = complete_package.all_requires

assert isinstance(pypi, Dependency)
assert pypi == dependency_pypi
Expand Down

0 comments on commit a20e333

Please sign in to comment.