summaryrefslogtreecommitdiffstats
path: root/Lib/enum.py
diff options
context:
space:
mode:
authorEthan Furman <ethan@stoneleaf.us>2018-09-22 02:03:09 (GMT)
committerGitHub <noreply@github.com>2018-09-22 02:03:09 (GMT)
commit5bdab641da0afd8aa581dfbde4f82d88d337c4b5 (patch)
tree492ee0a5d87717eeeb8abc992d71af18746f40c7 /Lib/enum.py
parentfd97d1f1af910a6222ea12aec42c456b64f9aee4 (diff)
downloadcpython-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.py50
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