Skip to content

Commit fe11966

Browse files
committed
allow enum classes as mixins
1 parent bfe0b9a commit fe11966

File tree

2 files changed

+65
-31
lines changed

2 files changed

+65
-31
lines changed

Lib/enum.py

Lines changed: 7 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -490,37 +490,13 @@ def _find_data_type(bases):
490490
continue
491491
return base
492492

493-
# check that zero or one concrete data type has been used, and only one
494-
# Enum type has been used, and that that Enum has no members
495-
member_type = first_enum = None
496-
if len(bases) == 1:
497-
member_type = _find_data_type(bases) or object
498-
first_enum = bases[0]
499-
elif len(bases) == 2:
500-
mixin, first_enum = bases
501-
if not issubclass(first_enum, Enum) or issubclass(mixin, Enum):
502-
raise TypeError("new enumerations must be created as "
503-
"`EnumName([mixin_type, ...] [data_type,] enum_type)`")
504-
# search for a concrete data type in mixin or first_enum
505-
member_type = _find_data_type(bases) or object
506-
else:
507-
# more than two bases
508-
*mixins, first_enum = bases
509-
if (not issubclass(first_enum, Enum)
510-
or any([issubclass(m, Enum) for m in mixins])
511-
):
512-
raise TypeError("new enumerations must be created as "
513-
"`EnumName([mixin_type, ...] [data_type,] enum_type)`")
514-
*mixins, data_type = mixins
515-
# verify that none of the mixins are a data type
516-
if _find_data_type(mixins):
517-
raise TypeError("new enumerations must be created as "
518-
"`EnumName([mixin_type, ...] [data_type,] enum_type)`")
519-
# check if data type is one, or base Enum has one
520-
member_type = _find_data_type(bases[-2:]) or object
521-
522-
# finally, double check that we are not subclassing a class with existing
523-
# enumeration members
493+
# ensure final parent class is an Enum derivative, find any concrete
494+
# data type, and check that Enum has no members
495+
first_enum = bases[-1]
496+
if not issubclass(first_enum, Enum):
497+
raise TypeError("new enumerations should be created as "
498+
"`EnumName([mixin_type, ...] [data_type,] enum_type)`")
499+
member_type = _find_data_type(bases) or object
524500
if first_enum._member_names_:
525501
raise TypeError("Cannot extend enumerations")
526502

Lib/test/test_enum.py

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1756,6 +1756,14 @@ def MAX(cls):
17561756
class StrMixin:
17571757
def __str__(self):
17581758
return self._name_.lower()
1759+
class SomeEnum(Enum):
1760+
def behavior(self):
1761+
return 'booyah'
1762+
class AnotherEnum(Enum):
1763+
def behavior(self):
1764+
return 'nuhuh!'
1765+
def social(self):
1766+
return "what's up?"
17591767
class Color(MaxMixin, Enum):
17601768
RED = auto()
17611769
GREEN = auto()
@@ -1783,6 +1791,56 @@ class Color(StrMixin, MaxMixin, Enum):
17831791
self.assertEqual(Color.BLUE.value, 3)
17841792
self.assertEqual(Color.MAX, 3)
17851793
self.assertEqual(str(Color.BLUE), 'blue')
1794+
class CoolColor(StrMixin, SomeEnum, Enum):
1795+
RED = auto()
1796+
GREEN = auto()
1797+
BLUE = auto()
1798+
self.assertEqual(CoolColor.RED.value, 1)
1799+
self.assertEqual(CoolColor.GREEN.value, 2)
1800+
self.assertEqual(CoolColor.BLUE.value, 3)
1801+
self.assertEqual(str(CoolColor.BLUE), 'blue')
1802+
self.assertEqual(CoolColor.RED.behavior(), 'booyah')
1803+
class CoolerColor(StrMixin, AnotherEnum, Enum):
1804+
RED = auto()
1805+
GREEN = auto()
1806+
BLUE = auto()
1807+
self.assertEqual(CoolerColor.RED.value, 1)
1808+
self.assertEqual(CoolerColor.GREEN.value, 2)
1809+
self.assertEqual(CoolerColor.BLUE.value, 3)
1810+
self.assertEqual(str(CoolerColor.BLUE), 'blue')
1811+
self.assertEqual(CoolerColor.RED.behavior(), 'nuhuh!')
1812+
self.assertEqual(CoolerColor.RED.social(), "what's up?")
1813+
class CoolestColor(StrMixin, SomeEnum, AnotherEnum):
1814+
RED = auto()
1815+
GREEN = auto()
1816+
BLUE = auto()
1817+
self.assertEqual(CoolestColor.RED.value, 1)
1818+
self.assertEqual(CoolestColor.GREEN.value, 2)
1819+
self.assertEqual(CoolestColor.BLUE.value, 3)
1820+
self.assertEqual(str(CoolestColor.BLUE), 'blue')
1821+
self.assertEqual(CoolestColor.RED.behavior(), 'booyah')
1822+
self.assertEqual(CoolestColor.RED.social(), "what's up?")
1823+
class ConfusedColor(StrMixin, AnotherEnum, SomeEnum):
1824+
RED = auto()
1825+
GREEN = auto()
1826+
BLUE = auto()
1827+
self.assertEqual(ConfusedColor.RED.value, 1)
1828+
self.assertEqual(ConfusedColor.GREEN.value, 2)
1829+
self.assertEqual(ConfusedColor.BLUE.value, 3)
1830+
self.assertEqual(str(ConfusedColor.BLUE), 'blue')
1831+
self.assertEqual(ConfusedColor.RED.behavior(), 'nuhuh!')
1832+
self.assertEqual(ConfusedColor.RED.social(), "what's up?")
1833+
class ReformedColor(StrMixin, IntEnum, SomeEnum, AnotherEnum):
1834+
RED = auto()
1835+
GREEN = auto()
1836+
BLUE = auto()
1837+
self.assertEqual(ReformedColor.RED.value, 1)
1838+
self.assertEqual(ReformedColor.GREEN.value, 2)
1839+
self.assertEqual(ReformedColor.BLUE.value, 3)
1840+
self.assertEqual(str(ReformedColor.BLUE), 'blue')
1841+
self.assertEqual(ReformedColor.RED.behavior(), 'booyah')
1842+
self.assertEqual(ConfusedColor.RED.social(), "what's up?")
1843+
self.assertTrue(issubclass(ReformedColor, int))
17861844

17871845

17881846
class TestOrder(unittest.TestCase):

0 commit comments

Comments
 (0)