bpo-44356: [Enum] allow multiple data-type mixins if they are all the same (GH-26649) (GH-26653)

This enables, for example, two base Enums to both inherit from `str`, and then both be mixed into the same final Enum:

    class Str1Enum(str, Enum):
        GH- some behavior here

    class Str2Enum(str, Enum):
        GH- some more behavior here

    class FinalStrEnum(Str1Enum, Str2Enum):
        GH- this now works
(cherry picked from commit 8a4f0850d75747af8c96ca0e7eef1f5c1abfba25)

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

Co-authored-by: Ethan Furman <ethan@stoneleaf.us>
diff --git a/Lib/test/test_enum.py b/Lib/test/test_enum.py
index 34b190b..40794e3 100644
--- a/Lib/test/test_enum.py
+++ b/Lib/test/test_enum.py
@@ -2144,6 +2144,53 @@ def __new__(cls, value):
                 return member
         self.assertEqual(Fee.TEST, 2)
 
+    def test_miltuple_mixin_with_common_data_type(self):
+        class CaseInsensitiveStrEnum(str, Enum):
+            @classmethod
+            def _missing_(cls, value):
+                for member in cls._member_map_.values():
+                    if member._value_.lower() == value.lower():
+                        return member
+                return super()._missing_(value)
+        #
+        class LenientStrEnum(str, Enum):
+            def __init__(self, *args):
+                self._valid = True
+            @classmethod
+            def _missing_(cls, value):
+                # encountered an unknown value!
+                # Luckily I'm a LenientStrEnum, so I won't crash just yet.
+                # You might want to add a new case though.
+                unknown = cls._member_type_.__new__(cls, value)
+                unknown._valid = False
+                unknown._name_ = value.upper()
+                unknown._value_ = value
+                cls._member_map_[value] = unknown
+                return unknown
+            @property
+            def valid(self):
+                return self._valid
+        #
+        class JobStatus(CaseInsensitiveStrEnum, LenientStrEnum):
+            ACTIVE = "active"
+            PENDING = "pending"
+            TERMINATED = "terminated"
+        #
+        JS = JobStatus
+        self.assertEqual(list(JobStatus), [JS.ACTIVE, JS.PENDING, JS.TERMINATED])
+        self.assertEqual(JS.ACTIVE, 'active')
+        self.assertEqual(JS.ACTIVE.value, 'active')
+        self.assertIs(JS('Active'), JS.ACTIVE)
+        self.assertTrue(JS.ACTIVE.valid)
+        missing = JS('missing')
+        self.assertEqual(list(JobStatus), [JS.ACTIVE, JS.PENDING, JS.TERMINATED])
+        self.assertEqual(JS.ACTIVE, 'active')
+        self.assertEqual(JS.ACTIVE.value, 'active')
+        self.assertIs(JS('Active'), JS.ACTIVE)
+        self.assertTrue(JS.ACTIVE.valid)
+        self.assertTrue(isinstance(missing, JS))
+        self.assertFalse(missing.valid)
+
     def test_empty_globals(self):
         # bpo-35717: sys._getframe(2).f_globals['__name__'] fails with KeyError
         # when using compile and exec because f_globals is empty