mirror of
https://github.com/python/cpython.git
synced 2025-08-04 00:48:58 +00:00
bpo-29577: Enum: mixin classes don't mix well with already mixed Enums (GH-9328)
* bpo-29577: allow multiple mixin classes
This commit is contained in:
parent
fd97d1f1af
commit
5bdab641da
4 changed files with 228 additions and 33 deletions
|
@ -122,6 +122,22 @@ class TestHelpers(unittest.TestCase):
|
|||
'__', '___', '____', '_____',):
|
||||
self.assertFalse(enum._is_dunder(s))
|
||||
|
||||
# for subclassing tests
|
||||
|
||||
class classproperty:
|
||||
|
||||
def __init__(self, fget=None, fset=None, fdel=None, doc=None):
|
||||
self.fget = fget
|
||||
self.fset = fset
|
||||
self.fdel = fdel
|
||||
if doc is None and fget is not None:
|
||||
doc = fget.__doc__
|
||||
self.__doc__ = doc
|
||||
|
||||
def __get__(self, instance, ownerclass):
|
||||
return self.fget(ownerclass)
|
||||
|
||||
|
||||
# tests
|
||||
|
||||
class TestEnum(unittest.TestCase):
|
||||
|
@ -1730,6 +1746,102 @@ class TestEnum(unittest.TestCase):
|
|||
else:
|
||||
raise Exception('Exception not raised.')
|
||||
|
||||
def test_multiple_mixin(self):
|
||||
class MaxMixin:
|
||||
@classproperty
|
||||
def MAX(cls):
|
||||
max = len(cls)
|
||||
cls.MAX = max
|
||||
return max
|
||||
class StrMixin:
|
||||
def __str__(self):
|
||||
return self._name_.lower()
|
||||
class SomeEnum(Enum):
|
||||
def behavior(self):
|
||||
return 'booyah'
|
||||
class AnotherEnum(Enum):
|
||||
def behavior(self):
|
||||
return 'nuhuh!'
|
||||
def social(self):
|
||||
return "what's up?"
|
||||
class Color(MaxMixin, Enum):
|
||||
RED = auto()
|
||||
GREEN = auto()
|
||||
BLUE = auto()
|
||||
self.assertEqual(Color.RED.value, 1)
|
||||
self.assertEqual(Color.GREEN.value, 2)
|
||||
self.assertEqual(Color.BLUE.value, 3)
|
||||
self.assertEqual(Color.MAX, 3)
|
||||
self.assertEqual(str(Color.BLUE), 'Color.BLUE')
|
||||
class Color(MaxMixin, StrMixin, Enum):
|
||||
RED = auto()
|
||||
GREEN = auto()
|
||||
BLUE = auto()
|
||||
self.assertEqual(Color.RED.value, 1)
|
||||
self.assertEqual(Color.GREEN.value, 2)
|
||||
self.assertEqual(Color.BLUE.value, 3)
|
||||
self.assertEqual(Color.MAX, 3)
|
||||
self.assertEqual(str(Color.BLUE), 'blue')
|
||||
class Color(StrMixin, MaxMixin, Enum):
|
||||
RED = auto()
|
||||
GREEN = auto()
|
||||
BLUE = auto()
|
||||
self.assertEqual(Color.RED.value, 1)
|
||||
self.assertEqual(Color.GREEN.value, 2)
|
||||
self.assertEqual(Color.BLUE.value, 3)
|
||||
self.assertEqual(Color.MAX, 3)
|
||||
self.assertEqual(str(Color.BLUE), 'blue')
|
||||
class CoolColor(StrMixin, SomeEnum, Enum):
|
||||
RED = auto()
|
||||
GREEN = auto()
|
||||
BLUE = auto()
|
||||
self.assertEqual(CoolColor.RED.value, 1)
|
||||
self.assertEqual(CoolColor.GREEN.value, 2)
|
||||
self.assertEqual(CoolColor.BLUE.value, 3)
|
||||
self.assertEqual(str(CoolColor.BLUE), 'blue')
|
||||
self.assertEqual(CoolColor.RED.behavior(), 'booyah')
|
||||
class CoolerColor(StrMixin, AnotherEnum, Enum):
|
||||
RED = auto()
|
||||
GREEN = auto()
|
||||
BLUE = auto()
|
||||
self.assertEqual(CoolerColor.RED.value, 1)
|
||||
self.assertEqual(CoolerColor.GREEN.value, 2)
|
||||
self.assertEqual(CoolerColor.BLUE.value, 3)
|
||||
self.assertEqual(str(CoolerColor.BLUE), 'blue')
|
||||
self.assertEqual(CoolerColor.RED.behavior(), 'nuhuh!')
|
||||
self.assertEqual(CoolerColor.RED.social(), "what's up?")
|
||||
class CoolestColor(StrMixin, SomeEnum, AnotherEnum):
|
||||
RED = auto()
|
||||
GREEN = auto()
|
||||
BLUE = auto()
|
||||
self.assertEqual(CoolestColor.RED.value, 1)
|
||||
self.assertEqual(CoolestColor.GREEN.value, 2)
|
||||
self.assertEqual(CoolestColor.BLUE.value, 3)
|
||||
self.assertEqual(str(CoolestColor.BLUE), 'blue')
|
||||
self.assertEqual(CoolestColor.RED.behavior(), 'booyah')
|
||||
self.assertEqual(CoolestColor.RED.social(), "what's up?")
|
||||
class ConfusedColor(StrMixin, AnotherEnum, SomeEnum):
|
||||
RED = auto()
|
||||
GREEN = auto()
|
||||
BLUE = auto()
|
||||
self.assertEqual(ConfusedColor.RED.value, 1)
|
||||
self.assertEqual(ConfusedColor.GREEN.value, 2)
|
||||
self.assertEqual(ConfusedColor.BLUE.value, 3)
|
||||
self.assertEqual(str(ConfusedColor.BLUE), 'blue')
|
||||
self.assertEqual(ConfusedColor.RED.behavior(), 'nuhuh!')
|
||||
self.assertEqual(ConfusedColor.RED.social(), "what's up?")
|
||||
class ReformedColor(StrMixin, IntEnum, SomeEnum, AnotherEnum):
|
||||
RED = auto()
|
||||
GREEN = auto()
|
||||
BLUE = auto()
|
||||
self.assertEqual(ReformedColor.RED.value, 1)
|
||||
self.assertEqual(ReformedColor.GREEN.value, 2)
|
||||
self.assertEqual(ReformedColor.BLUE.value, 3)
|
||||
self.assertEqual(str(ReformedColor.BLUE), 'blue')
|
||||
self.assertEqual(ReformedColor.RED.behavior(), 'booyah')
|
||||
self.assertEqual(ConfusedColor.RED.social(), "what's up?")
|
||||
self.assertTrue(issubclass(ReformedColor, int))
|
||||
|
||||
|
||||
class TestOrder(unittest.TestCase):
|
||||
|
||||
|
@ -2093,6 +2205,49 @@ class TestFlag(unittest.TestCase):
|
|||
d = 6
|
||||
self.assertEqual(repr(Bizarre(7)), '<Bizarre.d|c|b: 7>')
|
||||
|
||||
def test_multiple_mixin(self):
|
||||
class AllMixin:
|
||||
@classproperty
|
||||
def ALL(cls):
|
||||
members = list(cls)
|
||||
all_value = None
|
||||
if members:
|
||||
all_value = members[0]
|
||||
for member in members[1:]:
|
||||
all_value |= member
|
||||
cls.ALL = all_value
|
||||
return all_value
|
||||
class StrMixin:
|
||||
def __str__(self):
|
||||
return self._name_.lower()
|
||||
class Color(AllMixin, Flag):
|
||||
RED = auto()
|
||||
GREEN = auto()
|
||||
BLUE = auto()
|
||||
self.assertEqual(Color.RED.value, 1)
|
||||
self.assertEqual(Color.GREEN.value, 2)
|
||||
self.assertEqual(Color.BLUE.value, 4)
|
||||
self.assertEqual(Color.ALL.value, 7)
|
||||
self.assertEqual(str(Color.BLUE), 'Color.BLUE')
|
||||
class Color(AllMixin, StrMixin, Flag):
|
||||
RED = auto()
|
||||
GREEN = auto()
|
||||
BLUE = auto()
|
||||
self.assertEqual(Color.RED.value, 1)
|
||||
self.assertEqual(Color.GREEN.value, 2)
|
||||
self.assertEqual(Color.BLUE.value, 4)
|
||||
self.assertEqual(Color.ALL.value, 7)
|
||||
self.assertEqual(str(Color.BLUE), 'blue')
|
||||
class Color(StrMixin, AllMixin, Flag):
|
||||
RED = auto()
|
||||
GREEN = auto()
|
||||
BLUE = auto()
|
||||
self.assertEqual(Color.RED.value, 1)
|
||||
self.assertEqual(Color.GREEN.value, 2)
|
||||
self.assertEqual(Color.BLUE.value, 4)
|
||||
self.assertEqual(Color.ALL.value, 7)
|
||||
self.assertEqual(str(Color.BLUE), 'blue')
|
||||
|
||||
@support.reap_threads
|
||||
def test_unique_composite(self):
|
||||
# override __eq__ to be identity only
|
||||
|
@ -2468,6 +2623,49 @@ class TestIntFlag(unittest.TestCase):
|
|||
for f in Open:
|
||||
self.assertEqual(bool(f.value), bool(f))
|
||||
|
||||
def test_multiple_mixin(self):
|
||||
class AllMixin:
|
||||
@classproperty
|
||||
def ALL(cls):
|
||||
members = list(cls)
|
||||
all_value = None
|
||||
if members:
|
||||
all_value = members[0]
|
||||
for member in members[1:]:
|
||||
all_value |= member
|
||||
cls.ALL = all_value
|
||||
return all_value
|
||||
class StrMixin:
|
||||
def __str__(self):
|
||||
return self._name_.lower()
|
||||
class Color(AllMixin, IntFlag):
|
||||
RED = auto()
|
||||
GREEN = auto()
|
||||
BLUE = auto()
|
||||
self.assertEqual(Color.RED.value, 1)
|
||||
self.assertEqual(Color.GREEN.value, 2)
|
||||
self.assertEqual(Color.BLUE.value, 4)
|
||||
self.assertEqual(Color.ALL.value, 7)
|
||||
self.assertEqual(str(Color.BLUE), 'Color.BLUE')
|
||||
class Color(AllMixin, StrMixin, IntFlag):
|
||||
RED = auto()
|
||||
GREEN = auto()
|
||||
BLUE = auto()
|
||||
self.assertEqual(Color.RED.value, 1)
|
||||
self.assertEqual(Color.GREEN.value, 2)
|
||||
self.assertEqual(Color.BLUE.value, 4)
|
||||
self.assertEqual(Color.ALL.value, 7)
|
||||
self.assertEqual(str(Color.BLUE), 'blue')
|
||||
class Color(StrMixin, AllMixin, IntFlag):
|
||||
RED = auto()
|
||||
GREEN = auto()
|
||||
BLUE = auto()
|
||||
self.assertEqual(Color.RED.value, 1)
|
||||
self.assertEqual(Color.GREEN.value, 2)
|
||||
self.assertEqual(Color.BLUE.value, 4)
|
||||
self.assertEqual(Color.ALL.value, 7)
|
||||
self.assertEqual(str(Color.BLUE), 'blue')
|
||||
|
||||
@support.reap_threads
|
||||
def test_unique_composite(self):
|
||||
# override __eq__ to be identity only
|
||||
|
@ -2553,6 +2751,7 @@ class TestUnique(unittest.TestCase):
|
|||
value = 4
|
||||
|
||||
|
||||
|
||||
expected_help_output_with_docs = """\
|
||||
Help on class Color in module %s:
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue