mirror of
https://github.com/python/cpython.git
synced 2025-12-15 21:44:50 +00:00
gh-117663: [Enum] fix _simple_enum's detection of aliases (GH-117664)
This commit is contained in:
parent
d5f1139c79
commit
e5521bcca9
3 changed files with 101 additions and 33 deletions
80
Lib/enum.py
80
Lib/enum.py
|
|
@ -1088,8 +1088,6 @@ class EnumType(type):
|
|||
setattr(cls, name, member)
|
||||
# now add to _member_map_ (even aliases)
|
||||
cls._member_map_[name] = member
|
||||
#
|
||||
cls._member_map_[name] = member
|
||||
|
||||
EnumMeta = EnumType # keep EnumMeta name for backwards compatibility
|
||||
|
||||
|
|
@ -1802,20 +1800,31 @@ def _simple_enum(etype=Enum, *, boundary=None, use_args=None):
|
|||
for name, value in attrs.items():
|
||||
if isinstance(value, auto) and auto.value is _auto_null:
|
||||
value = gnv(name, 1, len(member_names), gnv_last_values)
|
||||
if value in value2member_map or value in unhashable_values:
|
||||
# an alias to an existing member
|
||||
enum_class(value)._add_alias_(name)
|
||||
# create basic member (possibly isolate value for alias check)
|
||||
if use_args:
|
||||
if not isinstance(value, tuple):
|
||||
value = (value, )
|
||||
member = new_member(enum_class, *value)
|
||||
value = value[0]
|
||||
else:
|
||||
# create the member
|
||||
if use_args:
|
||||
if not isinstance(value, tuple):
|
||||
value = (value, )
|
||||
member = new_member(enum_class, *value)
|
||||
value = value[0]
|
||||
else:
|
||||
member = new_member(enum_class)
|
||||
if __new__ is None:
|
||||
member._value_ = value
|
||||
member = new_member(enum_class)
|
||||
if __new__ is None:
|
||||
member._value_ = value
|
||||
# now check if alias
|
||||
try:
|
||||
contained = value2member_map.get(member._value_)
|
||||
except TypeError:
|
||||
contained = None
|
||||
if member._value_ in unhashable_values:
|
||||
for m in enum_class:
|
||||
if m._value_ == member._value_:
|
||||
contained = m
|
||||
break
|
||||
if contained is not None:
|
||||
# an alias to an existing member
|
||||
contained._add_alias_(name)
|
||||
else:
|
||||
# finish creating member
|
||||
member._name_ = name
|
||||
member.__objclass__ = enum_class
|
||||
member.__init__(value)
|
||||
|
|
@ -1847,24 +1856,31 @@ def _simple_enum(etype=Enum, *, boundary=None, use_args=None):
|
|||
if value.value is _auto_null:
|
||||
value.value = gnv(name, 1, len(member_names), gnv_last_values)
|
||||
value = value.value
|
||||
try:
|
||||
contained = value in value2member_map
|
||||
except TypeError:
|
||||
contained = value in unhashable_values
|
||||
if contained:
|
||||
# an alias to an existing member
|
||||
enum_class(value)._add_alias_(name)
|
||||
# create basic member (possibly isolate value for alias check)
|
||||
if use_args:
|
||||
if not isinstance(value, tuple):
|
||||
value = (value, )
|
||||
member = new_member(enum_class, *value)
|
||||
value = value[0]
|
||||
else:
|
||||
# create the member
|
||||
if use_args:
|
||||
if not isinstance(value, tuple):
|
||||
value = (value, )
|
||||
member = new_member(enum_class, *value)
|
||||
value = value[0]
|
||||
else:
|
||||
member = new_member(enum_class)
|
||||
if __new__ is None:
|
||||
member._value_ = value
|
||||
member = new_member(enum_class)
|
||||
if __new__ is None:
|
||||
member._value_ = value
|
||||
# now check if alias
|
||||
try:
|
||||
contained = value2member_map.get(member._value_)
|
||||
except TypeError:
|
||||
contained = None
|
||||
if member._value_ in unhashable_values:
|
||||
for m in enum_class:
|
||||
if m._value_ == member._value_:
|
||||
contained = m
|
||||
break
|
||||
if contained is not None:
|
||||
# an alias to an existing member
|
||||
contained._add_alias_(name)
|
||||
else:
|
||||
# finish creating member
|
||||
member._name_ = name
|
||||
member.__objclass__ = enum_class
|
||||
member.__init__(value)
|
||||
|
|
|
|||
|
|
@ -5170,7 +5170,57 @@ class TestStdLib(unittest.TestCase):
|
|||
self.assertIn('python', Unhashable)
|
||||
self.assertEqual(Unhashable.name.value, 'python')
|
||||
self.assertEqual(Unhashable.name.name, 'name')
|
||||
_test_simple_enum(Unhashable, Unhashable)
|
||||
_test_simple_enum(CheckedUnhashable, Unhashable)
|
||||
##
|
||||
class CheckedComplexStatus(IntEnum):
|
||||
def __new__(cls, value, phrase, description=''):
|
||||
obj = int.__new__(cls, value)
|
||||
obj._value_ = value
|
||||
obj.phrase = phrase
|
||||
obj.description = description
|
||||
return obj
|
||||
CONTINUE = 100, 'Continue', 'Request received, please continue'
|
||||
PROCESSING = 102, 'Processing'
|
||||
EARLY_HINTS = 103, 'Early Hints'
|
||||
SOME_HINTS = 103, 'Some Early Hints'
|
||||
#
|
||||
@_simple_enum(IntEnum)
|
||||
class ComplexStatus:
|
||||
def __new__(cls, value, phrase, description=''):
|
||||
obj = int.__new__(cls, value)
|
||||
obj._value_ = value
|
||||
obj.phrase = phrase
|
||||
obj.description = description
|
||||
return obj
|
||||
CONTINUE = 100, 'Continue', 'Request received, please continue'
|
||||
PROCESSING = 102, 'Processing'
|
||||
EARLY_HINTS = 103, 'Early Hints'
|
||||
SOME_HINTS = 103, 'Some Early Hints'
|
||||
_test_simple_enum(CheckedComplexStatus, ComplexStatus)
|
||||
#
|
||||
#
|
||||
class CheckedComplexFlag(IntFlag):
|
||||
def __new__(cls, value, label):
|
||||
obj = int.__new__(cls, value)
|
||||
obj._value_ = value
|
||||
obj.label = label
|
||||
return obj
|
||||
SHIRT = 1, 'upper half'
|
||||
VEST = 1, 'outer upper half'
|
||||
PANTS = 2, 'lower half'
|
||||
self.assertIs(CheckedComplexFlag.SHIRT, CheckedComplexFlag.VEST)
|
||||
#
|
||||
@_simple_enum(IntFlag)
|
||||
class ComplexFlag:
|
||||
def __new__(cls, value, label):
|
||||
obj = int.__new__(cls, value)
|
||||
obj._value_ = value
|
||||
obj.label = label
|
||||
return obj
|
||||
SHIRT = 1, 'upper half'
|
||||
VEST = 1, 'uppert half'
|
||||
PANTS = 2, 'lower half'
|
||||
_test_simple_enum(CheckedComplexFlag, ComplexFlag)
|
||||
|
||||
|
||||
class MiscTestCase(unittest.TestCase):
|
||||
|
|
|
|||
|
|
@ -0,0 +1,2 @@
|
|||
Fix ``_simple_enum`` to detect aliases when multiple arguments are present
|
||||
but only one is the member value.
|
||||
Loading…
Add table
Add a link
Reference in a new issue