Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

markers: avoid combinatorial explosion in certain cases #568

Merged
merged 2 commits into from
Mar 31, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
markers: avoid combinatorial explosion by replacing compatible MultiM…
…arker/MarkerUnion with AtomicMultiMarker/AtomicMarkerUnion
  • Loading branch information
radoering committed Mar 25, 2023
commit e06ae6fb27089d6a12bf73cdace6fc40c0e0aa26
23 changes: 17 additions & 6 deletions src/poetry/core/constraints/generic/union_constraint.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
from __future__ import annotations

import itertools

from poetry.core.constraints.generic import AnyConstraint
from poetry.core.constraints.generic.base_constraint import BaseConstraint
from poetry.core.constraints.generic.constraint import Constraint
Expand Down Expand Up @@ -132,19 +134,28 @@ def union(self, other: BaseConstraint) -> BaseConstraint:
new_constraints: list[BaseConstraint] = []
if isinstance(other, UnionConstraint):
# (A or B) or (C or D) => A or B or C or D
our_new_constraints: list[BaseConstraint] = []
their_new_constraints: list[BaseConstraint] = []
merged_new_constraints: list[BaseConstraint] = []
for our_constraint in self._constraints:
for their_constraint in other.constraints:
union = our_constraint.union(their_constraint)
if union.is_any():
return AnyConstraint()
if isinstance(union, Constraint):
if union not in new_constraints:
new_constraints.append(union)
if union not in merged_new_constraints:
merged_new_constraints.append(union)
else:
if our_constraint not in new_constraints:
new_constraints.append(our_constraint)
if their_constraint not in new_constraints:
new_constraints.append(their_constraint)
if our_constraint not in our_new_constraints:
our_new_constraints.append(our_constraint)
if their_constraint not in their_new_constraints:
their_new_constraints.append(their_constraint)
new_constraints = our_new_constraints
for constraint in itertools.chain(
their_new_constraints, merged_new_constraints
):
if constraint not in new_constraints:
new_constraints.append(constraint)

else:
assert isinstance(other, MultiConstraint)
Expand Down
8 changes: 6 additions & 2 deletions src/poetry/core/packages/dependency.py
Original file line number Diff line number Diff line change
Expand Up @@ -176,8 +176,12 @@ def marker(self, marker: str | BaseMarker) -> None:
self.deactivate()

for or_ in markers["extra"]:
for _, extra in or_:
self.in_extras.append(canonicalize_name(extra))
for op, extra in or_:
if op == "==":
self.in_extras.append(canonicalize_name(extra))
elif op == "" and "||" in extra:
for _extra in extra.split(" || "):
self.in_extras.append(canonicalize_name(_extra))

# Recalculate python versions.
self._python_versions = "*"
Expand Down
17 changes: 13 additions & 4 deletions src/poetry/core/packages/utils/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
from poetry.core.constraints.version import VersionRange
from poetry.core.constraints.version import parse_constraint
from poetry.core.pyproject.toml import PyProjectTOML
from poetry.core.version.markers import SingleMarkerLike
from poetry.core.version.markers import dnf


Expand Down Expand Up @@ -179,10 +180,18 @@ def add_constraint(
for i, sub_marker in enumerate(conjunctions):
if isinstance(sub_marker, MultiMarker):
for m in sub_marker.markers:
assert isinstance(m, SingleMarker)
add_constraint(m.name, (m.operator, m.value), i)
elif isinstance(sub_marker, SingleMarker):
add_constraint(sub_marker.name, (sub_marker.operator, sub_marker.value), i)
assert isinstance(m, SingleMarkerLike)
if isinstance(m, SingleMarker):
add_constraint(m.name, (m.operator, m.value), i)
else:
add_constraint(m.name, ("", str(m.constraint)), i)
elif isinstance(sub_marker, SingleMarkerLike):
if isinstance(sub_marker, SingleMarker):
add_constraint(
sub_marker.name, (sub_marker.operator, sub_marker.value), i
)
else:
add_constraint(sub_marker.name, ("", str(sub_marker.constraint)), i)

for group_name in requirements:
# remove duplicates
Expand Down
Loading