From ab38697755f1fc23c3b487268fb8c6bc2a84521d Mon Sep 17 00:00:00 2001 From: David Hotham Date: Sat, 26 Feb 2022 20:04:06 +0000 Subject: [PATCH 1/3] simplify union constraint of length 1 --- src/poetry/core/packages/constraints/union_constraint.py | 3 +++ tests/packages/constraints/test_constraint.py | 5 +++++ 2 files changed, 8 insertions(+) diff --git a/src/poetry/core/packages/constraints/union_constraint.py b/src/poetry/core/packages/constraints/union_constraint.py index 03df0dbb8..7eb42893a 100644 --- a/src/poetry/core/packages/constraints/union_constraint.py +++ b/src/poetry/core/packages/constraints/union_constraint.py @@ -91,6 +91,9 @@ def intersect(self, other: "BaseConstraint") -> "BaseConstraint": if not new_constraints: return EmptyConstraint() + if len(new_constraints) == 1: + return new_constraints[0] + return UnionConstraint(*new_constraints) def union(self, other: BaseConstraint) -> "UnionConstraint": diff --git a/tests/packages/constraints/test_constraint.py b/tests/packages/constraints/test_constraint.py index 80c50c304..3c7166321 100644 --- a/tests/packages/constraints/test_constraint.py +++ b/tests/packages/constraints/test_constraint.py @@ -88,6 +88,11 @@ def test_allows_all(): Constraint("linux", "!="), MultiConstraint(Constraint("win32", "!="), Constraint("linux", "!=")), ), + ( + UnionConstraint(Constraint("win32"), Constraint("linux")), + UnionConstraint(Constraint("win32"), Constraint("darwin")), + Constraint("win32"), + ), ], ) def test_intersect( From c9c91e94b218acd7dcec26d1a349b779f3441589 Mon Sep 17 00:00:00 2001 From: David Hotham Date: Sat, 26 Feb 2022 20:15:59 +0000 Subject: [PATCH 2/3] fix a faulty constraint intersection --- .../packages/constraints/union_constraint.py | 30 +++++++++++++++---- tests/packages/constraints/test_constraint.py | 5 ++++ 2 files changed, 29 insertions(+), 6 deletions(-) diff --git a/src/poetry/core/packages/constraints/union_constraint.py b/src/poetry/core/packages/constraints/union_constraint.py index 7eb42893a..5e3bf7bb9 100644 --- a/src/poetry/core/packages/constraints/union_constraint.py +++ b/src/poetry/core/packages/constraints/union_constraint.py @@ -1,5 +1,4 @@ from typing import Tuple -from typing import Union from typing import cast from poetry.core.packages.constraints.base_constraint import BaseConstraint @@ -78,12 +77,31 @@ def intersect(self, other: "BaseConstraint") -> "BaseConstraint": return EmptyConstraint() - other = cast(Union[MultiConstraint, UnionConstraint], other) - + # Two remaining cases: an intersection with another union, or an intersection with a multi. + # + # In the first case: + # (A or B) and (C or D) => (A and C) or (A and D) or (B and C) or (B and D) + # + # In the second case: + # (A or B) and (C and D) => (A and C and D) or (B and C and D) new_constraints = [] - for our_constraint in self._constraints: - for their_constraint in other.constraints: - intersection = our_constraint.intersect(their_constraint) + if isinstance(other, UnionConstraint): + for our_constraint in self._constraints: + for their_constraint in other.constraints: + intersection = our_constraint.intersect(their_constraint) + + if ( + not intersection.is_empty() + and intersection not in new_constraints + ): + new_constraints.append(intersection) + + else: + other = cast(MultiConstraint, other) + + for intersection in self._constraints: + for their_constraint in other.constraints: + intersection = intersection.intersect(their_constraint) if not intersection.is_empty() and intersection not in new_constraints: new_constraints.append(intersection) diff --git a/tests/packages/constraints/test_constraint.py b/tests/packages/constraints/test_constraint.py index 3c7166321..e50d66d24 100644 --- a/tests/packages/constraints/test_constraint.py +++ b/tests/packages/constraints/test_constraint.py @@ -93,6 +93,11 @@ def test_allows_all(): UnionConstraint(Constraint("win32"), Constraint("darwin")), Constraint("win32"), ), + ( + UnionConstraint(Constraint("win32"), Constraint("linux")), + MultiConstraint(Constraint("win32", "!="), Constraint("darwin", "!=")), + Constraint("linux"), + ), ], ) def test_intersect( From 36b5c2e0eeb640c91b7fd49d373b0afde6834780 Mon Sep 17 00:00:00 2001 From: David Hotham Date: Sat, 26 Feb 2022 23:37:47 +0000 Subject: [PATCH 3/3] review markups --- src/poetry/core/packages/constraints/union_constraint.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/poetry/core/packages/constraints/union_constraint.py b/src/poetry/core/packages/constraints/union_constraint.py index 5e3bf7bb9..b9e598ed3 100644 --- a/src/poetry/core/packages/constraints/union_constraint.py +++ b/src/poetry/core/packages/constraints/union_constraint.py @@ -77,7 +77,8 @@ def intersect(self, other: "BaseConstraint") -> "BaseConstraint": return EmptyConstraint() - # Two remaining cases: an intersection with another union, or an intersection with a multi. + # Two remaining cases: an intersection with another union, or an intersection + # with a multi. # # In the first case: # (A or B) and (C or D) => (A and C) or (A and D) or (B and C) or (B and D) @@ -99,7 +100,8 @@ def intersect(self, other: "BaseConstraint") -> "BaseConstraint": else: other = cast(MultiConstraint, other) - for intersection in self._constraints: + for our_constraint in self._constraints: + intersection = our_constraint for their_constraint in other.constraints: intersection = intersection.intersect(their_constraint)