diff options
author | Ethan Furman <ethan@stoneleaf.us> | 2018-09-21 19:03:09 -0700 |
---|---|---|
committer | Ethan Furman <ethan@stoneleaf.us> | 2018-09-21 19:09:16 -0700 |
commit | 13ba6d21f19b87f4768217d0989bea4885be0827 (patch) | |
tree | db67aad2c83c8258a1dba466412fc76a27177aa8 /Lib/enum.py | |
parent | e5fde1f992e94f166415ab96d874ed1d2e0c8004 (diff) | |
download | cpython-git-backport-5bdab64-3.7.tar.gz |
[3.7] bpo-29577: Enum: mixin classes don't mix well with already mixed Enums (GH-9328)backport-5bdab64-3.7
* bpo-29577: allow multiple mixin classes.
(cherry picked from commit 5bdab641da0afd8aa581dfbde4f82d88d337c4b5)
Co-authored-by: Ethan Furman <ethan@stoneleaf.us>
Diffstat (limited to 'Lib/enum.py')
-rw-r--r-- | Lib/enum.py | 50 |
1 files changed, 19 insertions, 31 deletions
diff --git a/Lib/enum.py b/Lib/enum.py index 69b41fe7cb..4e8a56818b 100644 --- a/Lib/enum.py +++ b/Lib/enum.py @@ -449,37 +449,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)`") - - # 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 + 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 + + # 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 |