Skip to content

Commit

Permalink
Fixed issue 119946 - Enum with ABC mixin
Browse files Browse the repository at this point in the history
  • Loading branch information
ygale committed Jun 2, 2024
1 parent f79ffc8 commit a141a73
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 4 deletions.
7 changes: 4 additions & 3 deletions Lib/enum.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import sys
import builtins as bltns
from types import MappingProxyType, DynamicClassAttribute
from abc import ABCMeta


__all__ = [
Expand Down Expand Up @@ -466,7 +467,7 @@ def update(self, members, **more_members):
_EnumDict = EnumDict # keep private name for backwards compatibility


class EnumType(type):
class EnumType(ABCMeta):
"""
Metaclass for Enum
"""
Expand Down Expand Up @@ -1773,7 +1774,7 @@ def convert_class(cls):
body['__rand__'] = Flag.__rand__
body['__invert__'] = Flag.__invert__
for name, obj in cls.__dict__.items():
if name in ('__dict__', '__weakref__'):
if name in ('__dict__', '__weakref__', '_abc_impl'):
continue
if _is_dunder(name) or _is_private(cls_name, name) or _is_sunder(name) or _is_descriptor(obj):
body[name] = obj
Expand Down Expand Up @@ -2038,7 +2039,7 @@ def _test_simple_enum(checked_enum, simple_enum):
)
for key in set(checked_keys + simple_keys):
if key in ('__module__', '_member_map_', '_value2member_map_', '__doc__',
'__static_attributes__', '__firstlineno__'):
'__static_attributes__', '__firstlineno__', '_abc_impl'):
# keys known to be different, or very long
continue
elif key in member_names:
Expand Down
46 changes: 45 additions & 1 deletion Lib/test/test_enum.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
from test.support import ALWAYS_EQ, REPO_ROOT
from test.support import threading_helper
from datetime import timedelta
from abc import ABC, abstractmethod

python_version = sys.version_info[:2]

Expand Down Expand Up @@ -3910,6 +3911,23 @@ class Color(StrMixin, AllMixin, Flag):
self.assertEqual(Color.ALL.value, 7)
self.assertEqual(str(Color.BLUE), 'blue')

def test_abstract_mixin(self):
class HasColor(ABC):
@abstractmethod
def color(self):
...
class Flowers(HasColor, Enum):
ROSES = 1
VIOLETS = 2
def color(self):
match self:
case self.ROSES:
return 'red'
case self.VIOLETS:
return 'blue'
self.assertEqual(Flowers.ROSES.color(), 'red')
self.assertEqual(Flowers.VIOLETS.color(), 'blue')

@threading_helper.reap_threads
@threading_helper.requires_working_threading()
def test_unique_composite(self):
Expand Down Expand Up @@ -5221,7 +5239,33 @@ def __new__(cls, value, label):
VEST = 1, 'uppert half'
PANTS = 2, 'lower half'
_test_simple_enum(CheckedComplexFlag, ComplexFlag)

#
#
class HasColor(ABC):
@abstractmethod
def color(self):
...
class CheckedABCMixin(HasColor, Enum):
ROSES = 1
VIOLETS = 2
def color(self):
match self:
case self.ROSES:
return 'red'
case self.VIOLETS:
return 'blue'
#
@_simple_enum(Enum)
class ABCMixin(HasColor):
ROSES = 1
VIOLETS = 2
def color(self):
match self:
case self.ROSES:
return 'red'
case self.VIOLETS:
return 'blue'
_test_simple_enum(CheckedABCMixin, ABCMixin)

class MiscTestCase(unittest.TestCase):

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Allow Enum classes to have mixins derived from an abstract base class (ABC).

0 comments on commit a141a73

Please sign in to comment.