@@ -328,6 +328,8 @@ def __set_name__(self, enum_class, member_name):
328
328
# to the map, and by-value lookups for this value will be
329
329
# linear.
330
330
enum_class ._value2member_map_ .setdefault (value , enum_member )
331
+ if value not in enum_class ._hashable_values_ :
332
+ enum_class ._hashable_values_ .append (value )
331
333
except TypeError :
332
334
# keep track of the value in a list so containment checks are quick
333
335
enum_class ._unhashable_values_ .append (value )
@@ -545,7 +547,8 @@ def __new__(metacls, cls, bases, classdict, *, boundary=None, _simple=False, **k
545
547
classdict ['_member_names_' ] = []
546
548
classdict ['_member_map_' ] = {}
547
549
classdict ['_value2member_map_' ] = {}
548
- classdict ['_unhashable_values_' ] = []
550
+ classdict ['_hashable_values_' ] = [] # for comparing with non-hashable types
551
+ classdict ['_unhashable_values_' ] = [] # e.g. frozenset() with set()
549
552
classdict ['_unhashable_values_map_' ] = {}
550
553
classdict ['_member_type_' ] = member_type
551
554
# now set the __repr__ for the value
@@ -755,7 +758,10 @@ def __contains__(cls, value):
755
758
try :
756
759
return value in cls ._value2member_map_
757
760
except TypeError :
758
- return value in cls ._unhashable_values_
761
+ return (
762
+ value in cls ._unhashable_values_ # both structures are lists
763
+ or value in cls ._hashable_values_
764
+ )
759
765
760
766
def __delattr__ (cls , attr ):
761
767
# nicer error message when someone tries to delete an attribute
@@ -1165,8 +1171,11 @@ def __new__(cls, value):
1165
1171
pass
1166
1172
except TypeError :
1167
1173
# not there, now do long search -- O(n) behavior
1168
- for name , values in cls ._unhashable_values_map_ .items ():
1169
- if value in values :
1174
+ for name , unhashable_values in cls ._unhashable_values_map_ .items ():
1175
+ if value in unhashable_values :
1176
+ return cls [name ]
1177
+ for name , member in cls ._member_map_ .items ():
1178
+ if value == member ._value_ :
1170
1179
return cls [name ]
1171
1180
# still not found -- verify that members exist, in-case somebody got here mistakenly
1172
1181
# (such as via super when trying to override __new__)
@@ -1232,6 +1241,7 @@ def _add_value_alias_(self, value):
1232
1241
# to the map, and by-value lookups for this value will be
1233
1242
# linear.
1234
1243
cls ._value2member_map_ .setdefault (value , self )
1244
+ cls ._hashable_values_ .append (value )
1235
1245
except TypeError :
1236
1246
# keep track of the value in a list so containment checks are quick
1237
1247
cls ._unhashable_values_ .append (value )
@@ -1762,6 +1772,7 @@ def convert_class(cls):
1762
1772
body ['_member_names_' ] = member_names = []
1763
1773
body ['_member_map_' ] = member_map = {}
1764
1774
body ['_value2member_map_' ] = value2member_map = {}
1775
+ body ['_hashable_values_' ] = hashable_values = []
1765
1776
body ['_unhashable_values_' ] = unhashable_values = []
1766
1777
body ['_unhashable_values_map_' ] = {}
1767
1778
body ['_member_type_' ] = member_type = etype ._member_type_
@@ -1825,7 +1836,7 @@ def convert_class(cls):
1825
1836
contained = value2member_map .get (member ._value_ )
1826
1837
except TypeError :
1827
1838
contained = None
1828
- if member ._value_ in unhashable_values :
1839
+ if member ._value_ in unhashable_values or member . value in hashable_values :
1829
1840
for m in enum_class :
1830
1841
if m ._value_ == member ._value_ :
1831
1842
contained = m
@@ -1845,6 +1856,7 @@ def convert_class(cls):
1845
1856
else :
1846
1857
enum_class ._add_member_ (name , member )
1847
1858
value2member_map [value ] = member
1859
+ hashable_values .append (value )
1848
1860
if _is_single_bit (value ):
1849
1861
# not a multi-bit alias, record in _member_names_ and _flag_mask_
1850
1862
member_names .append (name )
@@ -1881,7 +1893,7 @@ def convert_class(cls):
1881
1893
contained = value2member_map .get (member ._value_ )
1882
1894
except TypeError :
1883
1895
contained = None
1884
- if member ._value_ in unhashable_values :
1896
+ if member ._value_ in unhashable_values or member . _value_ in hashable_values :
1885
1897
for m in enum_class :
1886
1898
if m ._value_ == member ._value_ :
1887
1899
contained = m
@@ -1907,6 +1919,8 @@ def convert_class(cls):
1907
1919
# to the map, and by-value lookups for this value will be
1908
1920
# linear.
1909
1921
enum_class ._value2member_map_ .setdefault (value , member )
1922
+ if value not in hashable_values :
1923
+ hashable_values .append (value )
1910
1924
except TypeError :
1911
1925
# keep track of the value in a list so containment checks are quick
1912
1926
enum_class ._unhashable_values_ .append (value )
0 commit comments