mirror of
https://github.com/python/cpython.git
synced 2025-10-07 07:31:46 +00:00
bpo-29577: Enum: mixin classes don't mix well with already mixed Enums (GH-9328)
* bpo-29577: allow multiple mixin classes
This commit is contained in:
parent
fd97d1f1af
commit
5bdab641da
4 changed files with 228 additions and 33 deletions
48
Lib/enum.py
48
Lib/enum.py
|
@ -480,37 +480,25 @@ class EnumMeta(type):
|
|||
if not bases:
|
||||
return object, Enum
|
||||
|
||||
# double check that we are not subclassing a class with existing
|
||||
# enumeration members; while we're at it, see if any other data
|
||||
# type has been mixed in so we can use the correct __new__
|
||||
member_type = first_enum = None
|
||||
for base in bases:
|
||||
if (base is not Enum and
|
||||
issubclass(base, Enum) and
|
||||
base._member_names_):
|
||||
raise TypeError("Cannot extend enumerations")
|
||||
# base is now the last base in bases
|
||||
if not issubclass(base, Enum):
|
||||
raise TypeError("new enumerations must be created as "
|
||||
"`ClassName([mixin_type,] enum_type)`")
|
||||
def _find_data_type(bases):
|
||||
for chain in bases:
|
||||
for base in chain.__mro__:
|
||||
if base is object:
|
||||
continue
|
||||
elif '__new__' in base.__dict__:
|
||||
if issubclass(base, Enum) and not hasattr(base, '__new_member__'):
|
||||
continue
|
||||
return base
|
||||
|
||||
# get correct mix-in type (either mix-in type of Enum subclass, or
|
||||
# first base if last base is Enum)
|
||||
if not issubclass(bases[0], Enum):
|
||||
member_type = bases[0] # first data type
|
||||
first_enum = bases[-1] # enum type
|
||||
else:
|
||||
for base in bases[0].__mro__:
|
||||
# most common: (IntEnum, int, Enum, object)
|
||||
# possible: (<Enum 'AutoIntEnum'>, <Enum 'IntEnum'>,
|
||||
# <class 'int'>, <Enum 'Enum'>,
|
||||
# <class 'object'>)
|
||||
if issubclass(base, Enum):
|
||||
if first_enum is None:
|
||||
first_enum = base
|
||||
else:
|
||||
if member_type is None:
|
||||
member_type = base
|
||||
# ensure final parent class is an Enum derivative, find any concrete
|
||||
# data type, and check that Enum has no members
|
||||
first_enum = bases[-1]
|
||||
if not issubclass(first_enum, Enum):
|
||||
raise TypeError("new enumerations should be created as "
|
||||
"`EnumName([mixin_type, ...] [data_type,] enum_type)`")
|
||||
member_type = _find_data_type(bases) or object
|
||||
if first_enum._member_names_:
|
||||
raise TypeError("Cannot extend enumerations")
|
||||
|
||||
return member_type, first_enum
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue