@@ -34,6 +34,16 @@ class member(object):
3434 def __init__ (self , value ):
3535 self .value = value
3636
37+ def _hashable (obj ):
38+ """
39+ Returns True if obj is hashable, False otherwise.
40+ """
41+ try :
42+ hash (obj )
43+ return True
44+ except TypeError :
45+ return False
46+
3747def _is_descriptor (obj ):
3848 """
3949 Returns True if obj is a descriptor, False otherwise.
@@ -313,14 +323,13 @@ def __set_name__(self, enum_class, member_name):
313323
314324 enum_class ._add_member_ (member_name , enum_member )
315325 try :
316- # This may fail if value is not hashable. We can't add the value
317- # to the map, and by-value lookups for this value will be
318- # linear.
326+ # This may fail if value is not hashable.
319327 enum_class ._value2member_map_ .setdefault (value , enum_member )
320- if value not in enum_class ._hashable_values_ :
321- enum_class ._hashable_values_ .append (value )
328+ enum_class ._hashable_values_ .add (value )
322329 except TypeError :
323- # keep track of the value in a list so containment checks are quick
330+ # We can't add the value to the map; by-value lookups for this
331+ # value will be linear. keep track of the value in a list so
332+ # containment checks are quicker
324333 enum_class ._unhashable_values_ .append (value )
325334 enum_class ._unhashable_values_map_ .setdefault (member_name , []).append (value )
326335
@@ -530,7 +539,7 @@ def __new__(metacls, cls, bases, classdict, *, boundary=None, _simple=False, **k
530539 classdict ['_member_names_' ] = []
531540 classdict ['_member_map_' ] = {}
532541 classdict ['_value2member_map_' ] = {}
533- classdict ['_hashable_values_' ] = [] # for comparing with non-hashable types
542+ classdict ['_hashable_values_' ] = set () # for comparing with non-hashable types
534543 classdict ['_unhashable_values_' ] = [] # e.g. frozenset() with set()
535544 classdict ['_unhashable_values_map_' ] = {}
536545 classdict ['_member_type_' ] = member_type
@@ -767,10 +776,10 @@ def __contains__(cls, value):
767776 return isinstance (result , cls )
768777 except ValueError :
769778 pass
770- return (
771- value in cls ._unhashable_values_ # both structures are lists
772- or value in cls . _hashable_values_
773- )
779+ try :
780+ return value in cls ._hashable_values_ # a set
781+ except TypeError :
782+ return value in cls . _unhashable_values_ # a list
774783
775784 def __delattr__ (cls , attr ):
776785 # nicer error message when someone tries to delete an attribute
@@ -1261,7 +1270,7 @@ def _add_value_alias_(self, value):
12611270 # to the map, and by-value lookups for this value will be
12621271 # linear.
12631272 cls ._value2member_map_ .setdefault (value , self )
1264- cls ._hashable_values_ .append (value )
1273+ cls ._hashable_values_ .add (value )
12651274 except TypeError :
12661275 # keep track of the value in a list so containment checks are quick
12671276 cls ._unhashable_values_ .append (value )
@@ -1802,7 +1811,7 @@ def convert_class(cls):
18021811 body ['_member_names_' ] = member_names = []
18031812 body ['_member_map_' ] = member_map = {}
18041813 body ['_value2member_map_' ] = value2member_map = {}
1805- body ['_hashable_values_' ] = hashable_values = []
1814+ body ['_hashable_values_' ] = hashable_values = set ()
18061815 body ['_unhashable_values_' ] = unhashable_values = []
18071816 body ['_unhashable_values_map_' ] = {}
18081817 body ['_member_type_' ] = member_type = etype ._member_type_
@@ -1866,7 +1875,7 @@ def convert_class(cls):
18661875 contained = value2member_map .get (member ._value_ )
18671876 except TypeError :
18681877 contained = None
1869- if member ._value_ in unhashable_values or member .value in hashable_values :
1878+ if member ._value_ in hashable_values or member .value in unhashable_values :
18701879 for m in enum_class :
18711880 if m ._value_ == member ._value_ :
18721881 contained = m
@@ -1886,7 +1895,7 @@ def convert_class(cls):
18861895 else :
18871896 enum_class ._add_member_ (name , member )
18881897 value2member_map [value ] = member
1889- hashable_values .append (value )
1898+ hashable_values .add (value )
18901899 if _is_single_bit (value ):
18911900 # not a multi-bit alias, record in _member_names_ and _flag_mask_
18921901 member_names .append (name )
@@ -1923,7 +1932,9 @@ def convert_class(cls):
19231932 contained = value2member_map .get (member ._value_ )
19241933 except TypeError :
19251934 contained = None
1926- if member ._value_ in unhashable_values or member ._value_ in hashable_values :
1935+ if (_hashable (member ._value_ ) and member ._value_ in hashable_values
1936+ or member ._value_ in unhashable_values
1937+ ):
19271938 for m in enum_class :
19281939 if m ._value_ == member ._value_ :
19291940 contained = m
@@ -1949,8 +1960,7 @@ def convert_class(cls):
19491960 # to the map, and by-value lookups for this value will be
19501961 # linear.
19511962 enum_class ._value2member_map_ .setdefault (value , member )
1952- if value not in hashable_values :
1953- hashable_values .append (value )
1963+ hashable_values .add (value )
19541964 except TypeError :
19551965 # keep track of the value in a list so containment checks are quick
19561966 enum_class ._unhashable_values_ .append (value )
0 commit comments