From 0a1d5f194b1a7b6a11624ec6548ba0d8aa2e52bc Mon Sep 17 00:00:00 2001 From: David Hotham Date: Tue, 6 Sep 2022 18:58:57 +0100 Subject: [PATCH] make constraints hashable --- .../packages/constraints/any_constraint.py | 3 +++ .../packages/constraints/base_constraint.py | 3 +++ .../packages/constraints/empty_constraint.py | 3 +++ .../packages/constraints/multi_constraint.py | 7 +++++++ .../packages/constraints/union_constraint.py | 7 +++++++ tests/packages/constraints/test_constraint.py | 18 ++++++++++++++++++ 6 files changed, 41 insertions(+) diff --git a/src/poetry/core/packages/constraints/any_constraint.py b/src/poetry/core/packages/constraints/any_constraint.py index 348e4d1d8..7bbea514f 100644 --- a/src/poetry/core/packages/constraints/any_constraint.py +++ b/src/poetry/core/packages/constraints/any_constraint.py @@ -37,3 +37,6 @@ def __str__(self) -> str: def __eq__(self, other: object) -> bool: return isinstance(other, BaseConstraint) and other.is_any() + + def __hash__(self) -> int: + return hash("any") diff --git a/src/poetry/core/packages/constraints/base_constraint.py b/src/poetry/core/packages/constraints/base_constraint.py index 7f580c5e1..73f44cab7 100644 --- a/src/poetry/core/packages/constraints/base_constraint.py +++ b/src/poetry/core/packages/constraints/base_constraint.py @@ -29,5 +29,8 @@ def is_empty(self) -> bool: def __repr__(self) -> str: return f"<{self.__class__.__name__} {str(self)}>" + def __hash__(self) -> int: + raise NotImplementedError() + def __eq__(self, other: object) -> bool: raise NotImplementedError() diff --git a/src/poetry/core/packages/constraints/empty_constraint.py b/src/poetry/core/packages/constraints/empty_constraint.py index 2e703d624..147c43707 100644 --- a/src/poetry/core/packages/constraints/empty_constraint.py +++ b/src/poetry/core/packages/constraints/empty_constraint.py @@ -33,5 +33,8 @@ def __eq__(self, other: object) -> bool: return other.is_empty() + def __hash__(self) -> int: + return hash("empty") + def __str__(self) -> str: return "" diff --git a/src/poetry/core/packages/constraints/multi_constraint.py b/src/poetry/core/packages/constraints/multi_constraint.py index abeeb9c44..b62c5876e 100644 --- a/src/poetry/core/packages/constraints/multi_constraint.py +++ b/src/poetry/core/packages/constraints/multi_constraint.py @@ -81,6 +81,13 @@ def __eq__(self, other: object) -> bool: return set(self._constraints) == set(other._constraints) + def __hash__(self) -> int: + h = hash("multi") + for constraint in self._constraints: + h ^= hash(constraint) + + return h + def __str__(self) -> str: constraints = [] for constraint in self._constraints: diff --git a/src/poetry/core/packages/constraints/union_constraint.py b/src/poetry/core/packages/constraints/union_constraint.py index 65651509b..5ca46c00e 100644 --- a/src/poetry/core/packages/constraints/union_constraint.py +++ b/src/poetry/core/packages/constraints/union_constraint.py @@ -133,6 +133,13 @@ def __eq__(self, other: object) -> bool: return set(self._constraints) == set(other._constraints) + def __hash__(self) -> int: + h = hash("union") + for constraint in self._constraints: + h ^= hash(constraint) + + return h + def __str__(self) -> str: constraints = [] for constraint in self._constraints: diff --git a/tests/packages/constraints/test_constraint.py b/tests/packages/constraints/test_constraint.py index b93497d10..27d3c089e 100644 --- a/tests/packages/constraints/test_constraint.py +++ b/tests/packages/constraints/test_constraint.py @@ -167,3 +167,21 @@ def test_difference() -> None: assert c.difference(Constraint("win32")).is_empty() assert c.difference(Constraint("linux")) == c + + +@pytest.mark.parametrize( + "constraint", + [ + (EmptyConstraint()), + (AnyConstraint()), + (Constraint("win32")), + (UnionConstraint(Constraint("win32"), Constraint("linux"))), + (MultiConstraint(Constraint("win32", "!="), Constraint("linux", "!="))), + ], +) +def test_constraints_are_hashable( + constraint: BaseConstraint, +) -> None: + # We're just testing that constraints are hashable, there's nothing much to say + # about the result. + hash(constraint)