Skip to content

Commit e44c0ca

Browse files
committed
gh-158856: Fix enum membership for values of a different hashability
Since _hashable_values_ became a set, `value in EnumClass` missed values equal to a member value but of a different hashability, including a set member's own value. Check the unhashable values on a miss and compare against the hashable values on TypeError.
1 parent 7dd8b47 commit e44c0ca

2 files changed

Lines changed: 24 additions & 2 deletions

File tree

‎Lib/enum.py‎

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -777,9 +777,14 @@ def __contains__(cls, value):
777777
except ValueError:
778778
pass
779779
try:
780-
return value in cls._hashable_values_ # a set
780+
if value in cls._hashable_values_: # a set
781+
return True
781782
except TypeError:
782-
return value in cls._unhashable_values_ # a list
783+
# an unhashable value can equal a hashable one, e.g. bytearray
784+
for v in cls._hashable_values_:
785+
if v == value:
786+
return True
787+
return value in cls._unhashable_values_ # a list
783788

784789
def __delattr__(cls, attr):
785790
# nicer error message when someone tries to delete an attribute

‎Lib/test/test_enum.py‎

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3530,6 +3530,23 @@ class Directions(Enum):
35303530
UNRESTRICTED = frozenset({"sc", "cs"})
35313531
self.assertIs(Directions({"sc"}), Directions.DOWN_ONLY)
35323532

3533+
def test_contains_equal_value_of_other_hashability(self):
3534+
class Sets(Enum):
3535+
A = {1, 2}
3536+
class Magic(Enum):
3537+
PNG = b'\x89PNG'
3538+
class BytesMagic(bytes, Enum):
3539+
PNG = b'\x89PNG'
3540+
self.assertIn(Sets.A.value, Sets)
3541+
self.assertIn({1, 2}, Sets)
3542+
self.assertIn(frozenset({1, 2}), Sets)
3543+
self.assertNotIn({1, 3}, Sets)
3544+
self.assertNotIn(frozenset({1, 3}), Sets)
3545+
for enum_class in Magic, BytesMagic:
3546+
self.assertIn(bytearray(b'\x89PNG'), enum_class)
3547+
self.assertNotIn(bytearray(b'GIF8'), enum_class)
3548+
self.assertIs(enum_class(bytearray(b'\x89PNG')), enum_class.PNG)
3549+
35333550

35343551
class TestOrder(unittest.TestCase):
35353552
"test usage of the `_order_` attribute"

0 commit comments

Comments
 (0)