@@ -29,6 +29,14 @@ def __delete__(self, instance):
2929 raise AttributeError ("can't delete attribute" )
3030
3131
32+ def _is_descriptor (obj ):
33+ """Returns True if obj is a descriptor, False otherwise."""
34+ return (
35+ hasattr (obj , '__get__' ) or
36+ hasattr (obj , '__set__' ) or
37+ hasattr (obj , '__delete__' ))
38+
39+
3240def _is_dunder (name ):
3341 """Returns True if a __dunder__ name, False otherwise."""
3442 return (name [:2 ] == name [- 2 :] == '__' and
@@ -50,8 +58,9 @@ def _break_on_call_reduce(self):
5058 cls .__reduce__ = _break_on_call_reduce
5159 cls .__module__ = '<unknown>'
5260
61+
5362class _EnumDict (dict ):
54- """Keeps track of definition order of the enum items .
63+ """Track enum member order and ensure member names are not reused .
5564
5665 EnumMeta will use the names found in self._member_names as the
5766 enumeration member names.
@@ -62,11 +71,7 @@ def __init__(self):
6271 self ._member_names = []
6372
6473 def __setitem__ (self , key , value ):
65- """Changes anything not dundered or that doesn't have __get__.
66-
67- If a descriptor is added with the same name as an enum member, the name
68- is removed from _member_names (this may leave a hole in the numerical
69- sequence of values).
74+ """Changes anything not dundered or not a descriptor.
7075
7176 If an enum member name is used twice, an error is raised; duplicate
7277 values are not checked for.
@@ -76,19 +81,20 @@ def __setitem__(self, key, value):
7681 """
7782 if _is_sunder (key ):
7883 raise ValueError ('_names_ are reserved for future Enum use' )
79- elif _is_dunder (key ) or hasattr ( value , '__get__' ) :
80- if key in self . _member_names :
81- # overwriting an enum with a method? then remove the name from
82- # _member_names or it will become an enum anyway when the class
83- # is created
84- self . _member_names . remove ( key )
85- else :
86- if key in self . _member_names :
87- raise TypeError ('Attempted to reuse key : %r' % key )
84+ elif _is_dunder (key ):
85+ pass
86+ elif key in self . _member_names :
87+ # descriptor overwriting an enum?
88+ raise TypeError ( 'Attempted to reuse key: %r' % key )
89+ elif not _is_descriptor ( value ):
90+ if key in self :
91+ # enum overwriting a descriptor?
92+ raise TypeError ('Key already defined as : %r' % self [ key ] )
8893 self ._member_names .append (key )
8994 super ().__setitem__ (key , value )
9095
9196
97+
9298# Dummy value for Enum as EnumMeta explicitly checks for it, but of course
9399# until EnumMeta finishes running the first time the Enum class doesn't exist.
94100# This is also why there are checks in EnumMeta like `if Enum is not None`
0 commit comments