summaryrefslogtreecommitdiffstats
path: root/Lib/enum.py
diff options
context:
space:
mode:
authorEthan Furman <ethan@stoneleaf.us>2018-09-22 05:26:32 (GMT)
committerGitHub <noreply@github.com>2018-09-22 05:26:32 (GMT)
commit0c076caaa82a9c6596e1fe1dbe6384d53f30a1a3 (patch)
tree0833bdc585503850fa766c962c340f3ef8b2752f /Lib/enum.py
parentc00f7037df3607c89323e68db3ab996b7df394de (diff)
downloadcpython-0c076caaa82a9c6596e1fe1dbe6384d53f30a1a3.zip
cpython-0c076caaa82a9c6596e1fe1dbe6384d53f30a1a3.tar.gz
cpython-0c076caaa82a9c6596e1fe1dbe6384d53f30a1a3.tar.bz2
[3.7] bpo-29577: Enum: mixin classes don't mix well with already mixed Enums (GH-9328) (GH-9486)
* 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 69b41fe..4e8a568 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