[Python-checkins] bpo-39587: Enum - use correct mixed-in data type (GH-22263)

Miss Islington (bot) webhook-mailer at python.org
Tue Sep 15 19:24:09 EDT 2020


https://github.com/python/cpython/commit/8f8ebcca95d3b6ed0a522a9736ab53d6d4f0208c
commit: 8f8ebcca95d3b6ed0a522a9736ab53d6d4f0208c
branch: 3.8
author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com>
committer: GitHub <noreply at github.com>
date: 2020-09-15T16:23:57-07:00
summary:

bpo-39587: Enum - use correct mixed-in data type (GH-22263)

(cherry picked from commit bff01f3a3aac0c15fe8fbe8b2f561f7927d117a1)

Co-authored-by: Ethan Furman <ethan at stoneleaf.us>

files:
A Misc/NEWS.d/next/Library/2020-09-15-14-56-13.bpo-39587.69xzuh.rst
M Lib/enum.py
M Lib/test/test_enum.py

diff --git a/Lib/enum.py b/Lib/enum.py
index 16033b1c6fac5..dfde75048b0f0 100644
--- a/Lib/enum.py
+++ b/Lib/enum.py
@@ -487,14 +487,25 @@ def _get_mixins_(bases):
             return object, Enum
 
         def _find_data_type(bases):
+            data_types = []
             for chain in bases:
+                candidate = None
                 for base in chain.__mro__:
                     if base is object:
                         continue
                     elif '__new__' in base.__dict__:
                         if issubclass(base, Enum):
                             continue
-                        return base
+                        data_types.append(candidate or base)
+                        break
+                    elif not issubclass(base, Enum):
+                        candidate = base
+            if len(data_types) > 1:
+                raise TypeError('too many data types: %r' % data_types)
+            elif data_types:
+                return data_types[0]
+            else:
+                return None
 
         # ensure final parent class is an Enum derivative, find any concrete
         # data type, and check that Enum has no members
diff --git a/Lib/test/test_enum.py b/Lib/test/test_enum.py
index 0f91f00d92dd9..13f7ba4949fcc 100644
--- a/Lib/test/test_enum.py
+++ b/Lib/test/test_enum.py
@@ -551,6 +551,49 @@ def test_format_enum_str(self):
         self.assertFormatIsValue('{:>20}', Directional.WEST)
         self.assertFormatIsValue('{:<20}', Directional.WEST)
 
+    def test_enum_str_override(self):
+        class MyStrEnum(Enum):
+            def __str__(self):
+                return 'MyStr'
+        class MyMethodEnum(Enum):
+            def hello(self):
+                return 'Hello!  My name is %s' % self.name
+        class Test1Enum(MyMethodEnum, int, MyStrEnum):
+            One = 1
+            Two = 2
+        self.assertEqual(str(Test1Enum.One), 'MyStr')
+        #
+        class Test2Enum(MyStrEnum, MyMethodEnum):
+            One = 1
+            Two = 2
+        self.assertEqual(str(Test2Enum.One), 'MyStr')
+
+    def test_inherited_data_type(self):
+        class HexInt(int):
+            def __repr__(self):
+                return hex(self)
+        class MyEnum(HexInt, enum.Enum):
+            A = 1
+            B = 2
+            C = 3
+        self.assertEqual(repr(MyEnum.A), '<MyEnum.A: 0x1>')
+
+    def test_too_many_data_types(self):
+        with self.assertRaisesRegex(TypeError, 'too many data types'):
+            class Huh(str, int, Enum):
+                One = 1
+
+        class MyStr(str):
+            def hello(self):
+                return 'hello, %s' % self
+        class MyInt(int):
+            def repr(self):
+                return hex(self)
+        with self.assertRaisesRegex(TypeError, 'too many data types'):
+            class Huh(MyStr, MyInt, Enum):
+                One = 1
+
+
     def test_hash(self):
         Season = self.Season
         dates = {}
diff --git a/Misc/NEWS.d/next/Library/2020-09-15-14-56-13.bpo-39587.69xzuh.rst b/Misc/NEWS.d/next/Library/2020-09-15-14-56-13.bpo-39587.69xzuh.rst
new file mode 100644
index 0000000000000..e2f2b64867bed
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2020-09-15-14-56-13.bpo-39587.69xzuh.rst
@@ -0,0 +1 @@
+use the correct mix-in data type when constructing Enums



More information about the Python-checkins mailing list