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