Skip to content

Commit 95b81e2

Browse files
bpo-39587: Enum - use correct mixed-in data type (GH-22263) (GH-22266)
(cherry picked from commit bff01f3)
1 parent 49917d5 commit 95b81e2

3 files changed

Lines changed: 56 additions & 1 deletion

File tree

Lib/enum.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -481,14 +481,25 @@ def _get_mixins_(bases):
481481
return object, Enum
482482

483483
def _find_data_type(bases):
484+
data_types = []
484485
for chain in bases:
486+
candidate = None
485487
for base in chain.__mro__:
486488
if base is object:
487489
continue
488490
elif '__new__' in base.__dict__:
489491
if issubclass(base, Enum):
490492
continue
491-
return base
493+
data_types.append(candidate or base)
494+
break
495+
elif not issubclass(base, Enum):
496+
candidate = base
497+
if len(data_types) > 1:
498+
raise TypeError('too many data types: %r' % data_types)
499+
elif data_types:
500+
return data_types[0]
501+
else:
502+
return None
492503

493504
# ensure final parent class is an Enum derivative, find any concrete
494505
# data type, and check that Enum has no members

Lib/test/test_enum.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -552,6 +552,49 @@ def test_format_enum_str(self):
552552
self.assertFormatIsValue('{:>20}', Directional.WEST)
553553
self.assertFormatIsValue('{:<20}', Directional.WEST)
554554

555+
def test_enum_str_override(self):
556+
class MyStrEnum(Enum):
557+
def __str__(self):
558+
return 'MyStr'
559+
class MyMethodEnum(Enum):
560+
def hello(self):
561+
return 'Hello! My name is %s' % self.name
562+
class Test1Enum(MyMethodEnum, int, MyStrEnum):
563+
One = 1
564+
Two = 2
565+
self.assertEqual(str(Test1Enum.One), 'MyStr')
566+
#
567+
class Test2Enum(MyStrEnum, MyMethodEnum):
568+
One = 1
569+
Two = 2
570+
self.assertEqual(str(Test2Enum.One), 'MyStr')
571+
572+
def test_inherited_data_type(self):
573+
class HexInt(int):
574+
def __repr__(self):
575+
return hex(self)
576+
class MyEnum(HexInt, enum.Enum):
577+
A = 1
578+
B = 2
579+
C = 3
580+
self.assertEqual(repr(MyEnum.A), '<MyEnum.A: 0x1>')
581+
582+
def test_too_many_data_types(self):
583+
with self.assertRaisesRegex(TypeError, 'too many data types'):
584+
class Huh(str, int, Enum):
585+
One = 1
586+
587+
class MyStr(str):
588+
def hello(self):
589+
return 'hello, %s' % self
590+
class MyInt(int):
591+
def repr(self):
592+
return hex(self)
593+
with self.assertRaisesRegex(TypeError, 'too many data types'):
594+
class Huh(MyStr, MyInt, Enum):
595+
One = 1
596+
597+
555598
def test_hash(self):
556599
Season = self.Season
557600
dates = {}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
use the correct mix-in data type when constructing Enums

0 commit comments

Comments
 (0)