diff options
author | Ethan Furman <ethan@stoneleaf.us> | 2018-09-22 02:03:09 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-09-22 02:03:09 (GMT) |
commit | 5bdab641da0afd8aa581dfbde4f82d88d337c4b5 (patch) | |
tree | 492ee0a5d87717eeeb8abc992d71af18746f40c7 /Lib/enum.py | |
parent | fd97d1f1af910a6222ea12aec42c456b64f9aee4 (diff) | |
download | cpython-5bdab641da0afd8aa581dfbde4f82d88d337c4b5.zip cpython-5bdab641da0afd8aa581dfbde4f82d88d337c4b5.tar.gz cpython-5bdab641da0afd8aa581dfbde4f82d88d337c4b5.tar.bz2 |
bpo-29577: Enum: mixin classes don't mix well with already mixed Enums (GH-9328)
* bpo-29577: allow multiple mixin classes
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 02405c8..0ccb30d 100644 --- a/Lib/enum.py +++ b/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)`") - - # 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 |