Skip to content

Commit

Permalink
Merge any marker constraints into constraints with specific markers
Browse files Browse the repository at this point in the history
  • Loading branch information
radoering authored and neersighted committed Nov 21, 2021
1 parent 7aefbd6 commit 07565b2
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 3 deletions.
21 changes: 18 additions & 3 deletions src/poetry/puzzle/provider.py
Original file line number Diff line number Diff line change
Expand Up @@ -665,6 +665,14 @@ def complete_package(self, package: DependencyPackage) -> DependencyPackage:
# - ipython (1.2.4) ; implementation_name == "pypy"
#
# the marker for `ipython` will become `implementation_name != "pypy"`.
#
# Further, we have to merge the constraints of the requirements
# without markers into the constraints of the requirements with markers.
# for instance, if we have the following dependencies:
# - foo (>= 1.2)
# - foo (!= 1.2.1) ; python == 3.10
#
# the constraint for the second entry will become (!= 1.2.1, >= 1.2)
any_markers_dependencies = [d for d in _deps if d.marker.is_any()]
other_markers_dependencies = [d for d in _deps if not d.marker.is_any()]

Expand All @@ -673,9 +681,16 @@ def complete_package(self, package: DependencyPackage) -> DependencyPackage:
for other_dep in other_markers_dependencies[1:]:
marker = marker.union(other_dep.marker)

for i, d in enumerate(_deps):
if d.marker.is_any():
_deps[i].marker = marker.invert()
inverted_marker = marker.invert()
for dep_any in any_markers_dependencies:
dep_any.marker = inverted_marker
for dep_other in other_markers_dependencies:
dep_other.set_constraint(
dep_other.constraint.intersect(dep_any.constraint)
)
# TODO: Setting _pretty_constraint can be removed once the following issue has been fixed
# https://github.com/python-poetry/poetry/issues/4589
dep_other._pretty_constraint = str(dep_other.constraint)

overrides = []
for _dep in _deps:
Expand Down
43 changes: 43 additions & 0 deletions tests/puzzle/test_solver.py
Original file line number Diff line number Diff line change
Expand Up @@ -1142,6 +1142,49 @@ def test_solver_duplicate_dependencies_different_constraints_same_requirements(
assert str(e.value) == expected


def test_solver_duplicate_dependencies_different_constraints_merge_no_markers(
solver, repo, package
):
package.add_dependency(Factory.create_dependency("A", "*"))
package.add_dependency(Factory.create_dependency("B", "1.0"))

package_a10 = get_package("A", "1.0")
package_a10.add_dependency(Factory.create_dependency("C", {"version": "^1.0"}))

package_a20 = get_package("A", "2.0")
package_a20.add_dependency(
Factory.create_dependency("C", {"version": "^2.0"}) # incompatible with B
)
package_a20.add_dependency(
Factory.create_dependency("C", {"version": "!=2.1", "python": "3.10"})
)

package_b = get_package("B", "1.0")
package_b.add_dependency(Factory.create_dependency("C", {"version": "<2.0"}))

package_c10 = get_package("C", "1.0")
package_c20 = get_package("C", "2.0")
package_c21 = get_package("C", "2.1")

repo.add_package(package_a10)
repo.add_package(package_a20)
repo.add_package(package_b)
repo.add_package(package_c10)
repo.add_package(package_c20)
repo.add_package(package_c21)

transaction = solver.solve()

check_solver_result(
transaction,
[
{"job": "install", "package": package_c10},
{"job": "install", "package": package_a10}, # only a10, not a20
{"job": "install", "package": package_b},
],
)


def test_solver_duplicate_dependencies_sub_dependencies(solver, repo, package):
package.add_dependency(Factory.create_dependency("A", "*"))

Expand Down

0 comments on commit 07565b2

Please sign in to comment.