[3.10] bpo-44559: [Enum] revert enum module to 3.9 (GH-27010)

* [Enum] revert enum module to 3.9
diff --git a/Lib/enum.py b/Lib/enum.py
index 84e3cc1..db79e66 100644
--- a/Lib/enum.py
+++ b/Lib/enum.py
@@ -1,25 +1,14 @@
 import sys
 from types import MappingProxyType, DynamicClassAttribute
-from operator import or_ as _or_
-from functools import reduce
-from builtins import property as _bltin_property, bin as _bltin_bin
 
 
 __all__ = [
-        'EnumType', 'EnumMeta',
-        'Enum', 'IntEnum', 'StrEnum', 'Flag', 'IntFlag',
-        'auto', 'unique', 'property', 'verify',
-        'FlagBoundary', 'STRICT', 'CONFORM', 'EJECT', 'KEEP',
-        'global_flag_repr', 'global_enum_repr', 'global_enum',
-        'EnumCheck', 'CONTINUOUS', 'NAMED_FLAGS', 'UNIQUE',
+        'EnumMeta',
+        'Enum', 'IntEnum', 'Flag', 'IntFlag',
+        'auto', 'unique',
         ]
 
 
-# Dummy value for Enum and Flag as there are explicit checks for them
-# before they have been created.
-# This is also why there are checks in EnumType like `if Enum is not None`
-Enum = Flag = EJECT = None
-
 def _is_descriptor(obj):
     """
     Returns True if obj is a descriptor, False otherwise.
@@ -55,77 +44,24 @@ def _is_sunder(name):
 def _is_private(cls_name, name):
     # do not use `re` as `re` imports `enum`
     pattern = '_%s__' % (cls_name, )
-    pat_len = len(pattern)
     if (
-            len(name) > pat_len
+            len(name) >= 5
             and name.startswith(pattern)
-            and name[pat_len:pat_len+1] != ['_']
+            and name[len(pattern)] != '_'
             and (name[-1] != '_' or name[-2] != '_')
         ):
         return True
     else:
         return False
 
-def _is_single_bit(num):
+def _make_class_unpicklable(cls):
     """
-    True if only one bit set in num (should be an int)
-    """
-    if num == 0:
-        return False
-    num &= num - 1
-    return num == 0
-
-def _make_class_unpicklable(obj):
-    """
-    Make the given obj un-picklable.
-
-    obj should be either a dictionary, or an Enum
+    Make the given class un-picklable.
     """
     def _break_on_call_reduce(self, proto):
         raise TypeError('%r cannot be pickled' % self)
-    if isinstance(obj, dict):
-        obj['__reduce_ex__'] = _break_on_call_reduce
-        obj['__module__'] = '<unknown>'
-    else:
-        setattr(obj, '__reduce_ex__', _break_on_call_reduce)
-        setattr(obj, '__module__', '<unknown>')
-
-def _iter_bits_lsb(num):
-    # num must be an integer
-    if isinstance(num, Enum):
-        num = num.value
-    while num:
-        b = num & (~num + 1)
-        yield b
-        num ^= b
-
-def show_flag_values(value):
-    return list(_iter_bits_lsb(value))
-
-def bin(num, max_bits=None):
-    """
-    Like built-in bin(), except negative values are represented in
-    twos-compliment, and the leading bit always indicates sign
-    (0=positive, 1=negative).
-
-    >>> bin(10)
-    '0b0 1010'
-    >>> bin(~10)   # ~10 is -11
-    '0b1 0101'
-    """
-
-    ceiling = 2 ** (num).bit_length()
-    if num >= 0:
-        s = _bltin_bin(num + ceiling).replace('1', '0', 1)
-    else:
-        s = _bltin_bin(~num ^ (ceiling - 1) + ceiling)
-    sign = s[:3]
-    digits = s[3:]
-    if max_bits is not None:
-        if len(digits) < max_bits:
-            digits = (sign[-1] * max_bits + digits)[-max_bits:]
-    return "%s %s" % (sign, digits)
-
+    cls.__reduce_ex__ = _break_on_call_reduce
+    cls.__module__ = '<unknown>'
 
 _auto_null = object()
 class auto:
@@ -134,169 +70,12 @@ class auto:
     """
     value = _auto_null
 
-class property(DynamicClassAttribute):
-    """
-    This is a descriptor, used to define attributes that act differently
-    when accessed through an enum member and through an enum class.
-    Instance access is the same as property(), but access to an attribute
-    through the enum class will instead look in the class' _member_map_ for
-    a corresponding enum member.
-    """
-
-    def __get__(self, instance, ownerclass=None):
-        if instance is None:
-            try:
-                return ownerclass._member_map_[self.name]
-            except KeyError:
-                raise AttributeError(
-                        '%s: no class attribute %r' % (ownerclass.__name__, self.name)
-                        )
-        else:
-            if self.fget is None:
-                # check for member
-                if self.name in ownerclass._member_map_:
-                    import warnings
-                    warnings.warn(
-                            "accessing one member from another is not supported, "
-                            " and will be disabled in 3.12",
-                            DeprecationWarning,
-                            stacklevel=2,
-                            )
-                    return ownerclass._member_map_[self.name]
-                raise AttributeError(
-                        '%s: no instance attribute %r' % (ownerclass.__name__, self.name)
-                        )
-            else:
-                return self.fget(instance)
-
-    def __set__(self, instance, value):
-        if self.fset is None:
-            raise AttributeError(
-                    "%s: cannot set instance attribute %r" % (self.clsname, self.name)
-                    )
-        else:
-            return self.fset(instance, value)
-
-    def __delete__(self, instance):
-        if self.fdel is None:
-            raise AttributeError(
-                    "%s: cannot delete instance attribute %r" % (self.clsname, self.name)
-                    )
-        else:
-            return self.fdel(instance)
-
-    def __set_name__(self, ownerclass, name):
-        self.name = name
-        self.clsname = ownerclass.__name__
-
-
-class _proto_member:
-    """
-    intermediate step for enum members between class execution and final creation
-    """
-
-    def __init__(self, value):
-        self.value = value
-
-    def __set_name__(self, enum_class, member_name):
-        """
-        convert each quasi-member into an instance of the new enum class
-        """
-        # first step: remove ourself from enum_class
-        delattr(enum_class, member_name)
-        # second step: create member based on enum_class
-        value = self.value
-        if not isinstance(value, tuple):
-            args = (value, )
-        else:
-            args = value
-        if enum_class._member_type_ is tuple:   # special case for tuple enums
-            args = (args, )     # wrap it one more time
-        if not enum_class._use_args_:
-            enum_member = enum_class._new_member_(enum_class)
-            if not hasattr(enum_member, '_value_'):
-                enum_member._value_ = value
-        else:
-            enum_member = enum_class._new_member_(enum_class, *args)
-            if not hasattr(enum_member, '_value_'):
-                if enum_class._member_type_ is object:
-                    enum_member._value_ = value
-                else:
-                    try:
-                        enum_member._value_ = enum_class._member_type_(*args)
-                    except Exception as exc:
-                        raise TypeError(
-                                '_value_ not set in __new__, unable to create it'
-                                ) from None
-        value = enum_member._value_
-        enum_member._name_ = member_name
-        enum_member.__objclass__ = enum_class
-        enum_member.__init__(*args)
-        enum_member._sort_order_ = len(enum_class._member_names_)
-        # If another member with the same value was already defined, the
-        # new member becomes an alias to the existing one.
-        for name, canonical_member in enum_class._member_map_.items():
-            if canonical_member._value_ == enum_member._value_:
-                enum_member = canonical_member
-                break
-        else:
-            # this could still be an alias if the value is multi-bit and the
-            # class is a flag class
-            if (
-                    Flag is None
-                    or not issubclass(enum_class, Flag)
-                ):
-                # no other instances found, record this member in _member_names_
-                enum_class._member_names_.append(member_name)
-            elif (
-                    Flag is not None
-                    and issubclass(enum_class, Flag)
-                    and _is_single_bit(value)
-                ):
-                # no other instances found, record this member in _member_names_
-                enum_class._member_names_.append(member_name)
-        # get redirect in place before adding to _member_map_
-        # but check for other instances in parent classes first
-        need_override = False
-        descriptor = None
-        for base in enum_class.__mro__[1:]:
-            descriptor = base.__dict__.get(member_name)
-            if descriptor is not None:
-                if isinstance(descriptor, (property, DynamicClassAttribute)):
-                    break
-                else:
-                    need_override = True
-                    # keep looking for an enum.property
-        if descriptor and not need_override:
-            # previous enum.property found, no further action needed
-            pass
-        else:
-            redirect = property()
-            redirect.__set_name__(enum_class, member_name)
-            if descriptor and need_override:
-                # previous enum.property found, but some other inherited attribute
-                # is in the way; copy fget, fset, fdel to this one
-                redirect.fget = descriptor.fget
-                redirect.fset = descriptor.fset
-                redirect.fdel = descriptor.fdel
-            setattr(enum_class, member_name, redirect)
-        # now add to _member_map_ (even aliases)
-        enum_class._member_map_[member_name] = enum_member
-        try:
-            # This may fail if value is not hashable. We can't add the value
-            # to the map, and by-value lookups for this value will be
-            # linear.
-            enum_class._value2member_map_.setdefault(value, enum_member)
-        except TypeError:
-            # keep track of the value in a list so containment checks are quick
-            enum_class._unhashable_values_.append(value)
-
 
 class _EnumDict(dict):
     """
     Track enum member order and ensure member names are not reused.
 
-    EnumType will use the names found in self._member_names as the
+    EnumMeta will use the names found in self._member_names as the
     enumeration member names.
     """
     def __init__(self):
@@ -316,24 +95,24 @@ def __setitem__(self, key, value):
         Single underscore (sunder) names are reserved.
         """
         if _is_private(self._cls_name, key):
-            # do nothing, name will be a normal attribute
-            pass
-        elif _is_sunder(key):
+            import warnings
+            warnings.warn(
+                    "private variables, such as %r, will be normal attributes in 3.11"
+                        % (key, ),
+                    DeprecationWarning,
+                    stacklevel=2,
+                    )
+        if _is_sunder(key):
             if key not in (
-                    '_order_',
+                    '_order_', '_create_pseudo_member_',
                     '_generate_next_value_', '_missing_', '_ignore_',
-                    '_iter_member_', '_iter_member_by_value_', '_iter_member_by_def_',
                     ):
-                raise ValueError(
-                        '_sunder_ names, such as %r, are reserved for future Enum use'
-                        % (key, )
-                        )
+                raise ValueError('_names_ are reserved for future Enum use')
             if key == '_generate_next_value_':
                 # check if members already defined as auto()
                 if self._auto_called:
                     raise TypeError("_generate_next_value_ must be defined before members")
-                _gnv = value.__func__ if isinstance(value, staticmethod) else value
-                setattr(self, '_generate_next_value', _gnv)
+                setattr(self, '_generate_next_value', value)
             elif key == '_ignore_':
                 if isinstance(value, str):
                     value = value.replace(',',' ').split()
@@ -351,7 +130,7 @@ def __setitem__(self, key, value):
                 key = '_order_'
         elif key in self._member_names:
             # descriptor overwriting an enum?
-            raise TypeError('%r already defined as: %r' % (key, self[key]))
+            raise TypeError('Attempted to reuse key: %r' % key)
         elif key in self._ignore:
             pass
         elif not _is_descriptor(value):
@@ -361,7 +140,10 @@ def __setitem__(self, key, value):
             if isinstance(value, auto):
                 if value.value == _auto_null:
                     value.value = self._generate_next_value(
-                            key, 1, len(self._member_names), self._last_values[:],
+                            key,
+                            1,
+                            len(self._member_names),
+                            self._last_values[:],
                             )
                     self._auto_called = True
                 value = value.value
@@ -369,22 +151,16 @@ def __setitem__(self, key, value):
             self._last_values.append(value)
         super().__setitem__(key, value)
 
-    def update(self, members, **more_members):
-        try:
-            for name in members.keys():
-                self[name] = members[name]
-        except AttributeError:
-            for name, value in members:
-                self[name] = value
-        for name, value in more_members.items():
-            self[name] = value
 
+# Dummy value for Enum as EnumMeta explicitly checks for it, but of course
+# until EnumMeta finishes running the first time the Enum class doesn't exist.
+# This is also why there are checks in EnumMeta like `if Enum is not None`
+Enum = None
 
-class EnumType(type):
+class EnumMeta(type):
     """
     Metaclass for Enum
     """
-
     @classmethod
     def __prepare__(metacls, cls, bases, **kwds):
         # check that previous enum members do not exist
@@ -400,80 +176,148 @@ def __prepare__(metacls, cls, bases, **kwds):
                     )
         return enum_dict
 
-    def __new__(metacls, cls, bases, classdict, *, boundary=None, _simple=False, **kwds):
+    def __new__(metacls, cls, bases, classdict, **kwds):
         # an Enum class is final once enumeration items have been defined; it
         # cannot be mixed with other types (int, float, etc.) if it has an
         # inherited __new__ unless a new __new__ is defined (or the resulting
         # class will fail).
         #
         # remove any keys listed in _ignore_
-        if _simple:
-            return super().__new__(metacls, cls, bases, classdict, **kwds)
         classdict.setdefault('_ignore_', []).append('_ignore_')
         ignore = classdict['_ignore_']
         for key in ignore:
             classdict.pop(key, None)
-        #
-        # grab member names
-        member_names = classdict._member_names
-        #
-        # check for illegal enum names (any others?)
-        invalid_names = set(member_names) & {'mro', ''}
-        if invalid_names:
-            raise ValueError('Invalid enum member name: {0}'.format(
-                ','.join(invalid_names)))
-        #
-        # adjust the sunders
-        _order_ = classdict.pop('_order_', None)
-        # convert to normal dict
-        classdict = dict(classdict.items())
-        #
-        # data type of member and the controlling Enum class
         member_type, first_enum = metacls._get_mixins_(cls, bases)
         __new__, save_new, use_args = metacls._find_new_(
                 classdict, member_type, first_enum,
                 )
-        classdict['_new_member_'] = __new__
-        classdict['_use_args_'] = use_args
-        #
-        # convert future enum members into temporary _proto_members
-        # and record integer values in case this will be a Flag
-        flag_mask = 0
-        for name in member_names:
-            value = classdict[name]
-            if isinstance(value, int):
-                flag_mask |= value
-            classdict[name] = _proto_member(value)
-        #
-        # house-keeping structures
-        classdict['_member_names_'] = []
-        classdict['_member_map_'] = {}
-        classdict['_value2member_map_'] = {}
-        classdict['_unhashable_values_'] = []
-        classdict['_member_type_'] = member_type
-        #
-        # Flag structures (will be removed if final class is not a Flag
-        classdict['_boundary_'] = (
-                boundary
-                or getattr(first_enum, '_boundary_', None)
-                )
-        classdict['_flag_mask_'] = flag_mask
-        classdict['_all_bits_'] = 2 ** ((flag_mask).bit_length()) - 1
-        classdict['_inverted_'] = None
-        #
+
+        # save enum items into separate mapping so they don't get baked into
+        # the new class
+        enum_members = {k: classdict[k] for k in classdict._member_names}
+        for name in classdict._member_names:
+            del classdict[name]
+
+        # adjust the sunders
+        _order_ = classdict.pop('_order_', None)
+
+        # check for illegal enum names (any others?)
+        invalid_names = set(enum_members) & {'mro', ''}
+        if invalid_names:
+            raise ValueError('Invalid enum member name: {0}'.format(
+                ','.join(invalid_names)))
+
         # create a default docstring if one has not been provided
         if '__doc__' not in classdict:
             classdict['__doc__'] = 'An enumeration.'
-        try:
-            exc = None
-            enum_class = super().__new__(metacls, cls, bases, classdict, **kwds)
-        except RuntimeError as e:
-            # any exceptions raised by member.__new__ will get converted to a
-            # RuntimeError, so get that original exception back and raise it instead
-            exc = e.__cause__ or e
-        if exc is not None:
-            raise exc
+
+        enum_class = super().__new__(metacls, cls, bases, classdict, **kwds)
+        enum_class._member_names_ = []               # names in definition order
+        enum_class._member_map_ = {}                 # name->value map
+        enum_class._member_type_ = member_type
+
+        # save DynamicClassAttribute attributes from super classes so we know
+        # if we can take the shortcut of storing members in the class dict
+        dynamic_attributes = {
+                k for c in enum_class.mro()
+                for k, v in c.__dict__.items()
+                if isinstance(v, DynamicClassAttribute)
+                }
+
+        # Reverse value->name map for hashable values.
+        enum_class._value2member_map_ = {}
+
+        # If a custom type is mixed into the Enum, and it does not know how
+        # to pickle itself, pickle.dumps will succeed but pickle.loads will
+        # fail.  Rather than have the error show up later and possibly far
+        # from the source, sabotage the pickle protocol for this class so
+        # that pickle.dumps also fails.
         #
+        # However, if the new class implements its own __reduce_ex__, do not
+        # sabotage -- it's on them to make sure it works correctly.  We use
+        # __reduce_ex__ instead of any of the others as it is preferred by
+        # pickle over __reduce__, and it handles all pickle protocols.
+        if '__reduce_ex__' not in classdict:
+            if member_type is not object:
+                methods = ('__getnewargs_ex__', '__getnewargs__',
+                        '__reduce_ex__', '__reduce__')
+                if not any(m in member_type.__dict__ for m in methods):
+                    if '__new__' in classdict:
+                        # too late, sabotage
+                        _make_class_unpicklable(enum_class)
+                    else:
+                        # final attempt to verify that pickling would work:
+                        # travel mro until __new__ is found, checking for
+                        # __reduce__ and friends along the way -- if any of them
+                        # are found before/when __new__ is found, pickling should
+                        # work
+                        sabotage = None
+                        for chain in bases:
+                            for base in chain.__mro__:
+                                if base is object:
+                                    continue
+                                elif any(m in base.__dict__ for m in methods):
+                                    # found one, we're good
+                                    sabotage = False
+                                    break
+                                elif '__new__' in base.__dict__:
+                                    # not good
+                                    sabotage = True
+                                    break
+                            if sabotage is not None:
+                                break
+                        if sabotage:
+                            _make_class_unpicklable(enum_class)
+        # instantiate them, checking for duplicates as we go
+        # we instantiate first instead of checking for duplicates first in case
+        # a custom __new__ is doing something funky with the values -- such as
+        # auto-numbering ;)
+        for member_name in classdict._member_names:
+            value = enum_members[member_name]
+            if not isinstance(value, tuple):
+                args = (value, )
+            else:
+                args = value
+            if member_type is tuple:   # special case for tuple enums
+                args = (args, )     # wrap it one more time
+            if not use_args:
+                enum_member = __new__(enum_class)
+                if not hasattr(enum_member, '_value_'):
+                    enum_member._value_ = value
+            else:
+                enum_member = __new__(enum_class, *args)
+                if not hasattr(enum_member, '_value_'):
+                    if member_type is object:
+                        enum_member._value_ = value
+                    else:
+                        enum_member._value_ = member_type(*args)
+            value = enum_member._value_
+            enum_member._name_ = member_name
+            enum_member.__objclass__ = enum_class
+            enum_member.__init__(*args)
+            # If another member with the same value was already defined, the
+            # new member becomes an alias to the existing one.
+            for name, canonical_member in enum_class._member_map_.items():
+                if canonical_member._value_ == enum_member._value_:
+                    enum_member = canonical_member
+                    break
+            else:
+                # Aliases don't appear in member names (only in __members__).
+                enum_class._member_names_.append(member_name)
+            # performance boost for any member that would not shadow
+            # a DynamicClassAttribute
+            if member_name not in dynamic_attributes:
+                setattr(enum_class, member_name, enum_member)
+            # now add to _member_map_
+            enum_class._member_map_[member_name] = enum_member
+            try:
+                # This may fail if value is not hashable. We can't add the value
+                # to the map, and by-value lookups for this value will be
+                # linear.
+                enum_class._value2member_map_[value] = enum_member
+            except TypeError:
+                pass
+
         # double check that repr and friends are not the mixin's or various
         # things break (such as pickle)
         # however, if the method is defined in the Enum itself, don't replace
@@ -486,7 +330,7 @@ def __new__(metacls, cls, bases, classdict, *, boundary=None, _simple=False, **k
             enum_method = getattr(first_enum, name, None)
             if obj_method is not None and obj_method is class_method:
                 setattr(enum_class, name, enum_method)
-        #
+
         # replace any other __new__ with our own (as long as Enum is not None,
         # anyway) -- again, this is to support pickle
         if Enum is not None:
@@ -495,71 +339,14 @@ def __new__(metacls, cls, bases, classdict, *, boundary=None, _simple=False, **k
             if save_new:
                 enum_class.__new_member__ = __new__
             enum_class.__new__ = Enum.__new__
-        #
+
         # py3 support for definition order (helps keep py2/py3 code in sync)
-        #
-        # _order_ checking is spread out into three/four steps
-        # - if enum_class is a Flag:
-        #   - remove any non-single-bit flags from _order_
-        # - remove any aliases from _order_
-        # - check that _order_ and _member_names_ match
-        #
-        # step 1: ensure we have a list
         if _order_ is not None:
             if isinstance(_order_, str):
                 _order_ = _order_.replace(',', ' ').split()
-        #
-        # remove Flag structures if final class is not a Flag
-        if (
-                Flag is None and cls != 'Flag'
-                or Flag is not None and not issubclass(enum_class, Flag)
-            ):
-            delattr(enum_class, '_boundary_')
-            delattr(enum_class, '_flag_mask_')
-            delattr(enum_class, '_all_bits_')
-            delattr(enum_class, '_inverted_')
-        elif Flag is not None and issubclass(enum_class, Flag):
-            # ensure _all_bits_ is correct and there are no missing flags
-            single_bit_total = 0
-            multi_bit_total = 0
-            for flag in enum_class._member_map_.values():
-                flag_value = flag._value_
-                if _is_single_bit(flag_value):
-                    single_bit_total |= flag_value
-                else:
-                    # multi-bit flags are considered aliases
-                    multi_bit_total |= flag_value
-            enum_class._flag_mask_ = single_bit_total
-            #
-            # set correct __iter__
-            member_list = [m._value_ for m in enum_class]
-            if member_list != sorted(member_list):
-                enum_class._iter_member_ = enum_class._iter_member_by_def_
-            if _order_:
-                # _order_ step 2: remove any items from _order_ that are not single-bit
-                _order_ = [
-                        o
-                        for o in _order_
-                        if o not in enum_class._member_map_ or _is_single_bit(enum_class[o]._value_)
-                        ]
-        #
-        if _order_:
-            # _order_ step 3: remove aliases from _order_
-            _order_ = [
-                    o
-                    for o in _order_
-                    if (
-                        o not in enum_class._member_map_
-                        or
-                        (o in enum_class._member_map_ and o in enum_class._member_names_)
-                        )]
-            # _order_ step 4: verify that _order_ and _member_names_ match
             if _order_ != enum_class._member_names_:
-                raise TypeError(
-                        'member order does not match _order_:\n%r\n%r'
-                        % (enum_class._member_names_, _order_)
-                        )
-        #
+                raise TypeError('member order does not match _order_')
+
         return enum_class
 
     def __bool__(self):
@@ -568,7 +355,7 @@ def __bool__(self):
         """
         return True
 
-    def __call__(cls, value, names=None, *, module=None, qualname=None, type=None, start=1, boundary=None):
+    def __call__(cls, value, names=None, *, module=None, qualname=None, type=None, start=1):
         """
         Either returns an existing member, or creates a new enum class.
 
@@ -603,18 +390,10 @@ def __call__(cls, value, names=None, *, module=None, qualname=None, type=None, s
                 qualname=qualname,
                 type=type,
                 start=start,
-                boundary=boundary,
                 )
 
     def __contains__(cls, member):
         if not isinstance(member, Enum):
-            import warnings
-            warnings.warn(
-                    "in 3.12 __contains__ will no longer raise TypeError, but will return True or\n"
-                    "False depending on whether the value is a member or the value of a member",
-                    DeprecationWarning,
-                    stacklevel=2,
-                    )
             raise TypeError(
                 "unsupported operand type(s) for 'in': '%s' and '%s'" % (
                     type(member).__qualname__, cls.__class__.__qualname__))
@@ -624,7 +403,7 @@ def __delattr__(cls, attr):
         # nicer error message when someone tries to delete an attribute
         # (see issue19025).
         if attr in cls._member_map_:
-            raise AttributeError("%s: cannot delete Enum member %r." % (cls.__name__, attr))
+            raise AttributeError("%s: cannot delete Enum member." % cls.__name__)
         super().__delattr__(attr)
 
     def __dir__(self):
@@ -661,7 +440,7 @@ def __iter__(cls):
     def __len__(cls):
         return len(cls._member_names_)
 
-    @_bltin_property
+    @property
     def __members__(cls):
         """
         Returns a mapping of member name->value.
@@ -672,10 +451,7 @@ def __members__(cls):
         return MappingProxyType(cls._member_map_)
 
     def __repr__(cls):
-        if Flag is not None and issubclass(cls, Flag):
-            return "<flag %r>" % cls.__name__
-        else:
-            return "<enum %r>" % cls.__name__
+        return "<enum %r>" % cls.__name__
 
     def __reversed__(cls):
         """
@@ -693,10 +469,10 @@ def __setattr__(cls, name, value):
         """
         member_map = cls.__dict__.get('_member_map_', {})
         if name in member_map:
-            raise AttributeError('Cannot reassign member %r.' % (name, ))
+            raise AttributeError('Cannot reassign members.')
         super().__setattr__(name, value)
 
-    def _create_(cls, class_name, names, *, module=None, qualname=None, type=None, start=1, boundary=None):
+    def _create_(cls, class_name, names, *, module=None, qualname=None, type=None, start=1):
         """
         Convenience method to create a new Enum class.
 
@@ -731,6 +507,7 @@ def _create_(cls, class_name, names, *, module=None, qualname=None, type=None, s
             else:
                 member_name, member_value = item
             classdict[member_name] = member_value
+        enum_class = metacls.__new__(metacls, class_name, bases, classdict)
 
         # TODO: replace the frame hack if a blessed way to know the calling
         # module is ever developed
@@ -740,16 +517,15 @@ def _create_(cls, class_name, names, *, module=None, qualname=None, type=None, s
             except (AttributeError, ValueError, KeyError):
                 pass
         if module is None:
-            _make_class_unpicklable(classdict)
+            _make_class_unpicklable(enum_class)
         else:
-            classdict['__module__'] = module
+            enum_class.__module__ = module
         if qualname is not None:
-            classdict['__qualname__'] = qualname
+            enum_class.__qualname__ = qualname
 
-        return metacls.__new__(metacls, class_name, bases, classdict, boundary=boundary)
+        return enum_class
 
-    def _convert_(cls, name, module, filter, source=None, *, boundary=None):
-
+    def _convert_(cls, name, module, filter, source=None):
         """
         Create a new Enum subclass that replaces a collection of global constants
         """
@@ -758,9 +534,9 @@ def _convert_(cls, name, module, filter, source=None, *, boundary=None):
         # module;
         # also, replace the __reduce_ex__ method so unpickling works in
         # previous Python versions
-        module_globals = sys.modules[module].__dict__
+        module_globals = vars(sys.modules[module])
         if source:
-            source = source.__dict__
+            source = vars(source)
         else:
             source = module_globals
         # _value2member_map_ is populated in the same order every time
@@ -776,12 +552,9 @@ def _convert_(cls, name, module, filter, source=None, *, boundary=None):
         except TypeError:
             # unless some values aren't comparable, in which case sort by name
             members.sort(key=lambda t: t[0])
-        body = {t[0]: t[1] for t in members}
-        body['__module__'] = module
-        tmp_cls = type(name, (object, ), body)
-        cls = _simple_enum(etype=cls, boundary=boundary or KEEP)(tmp_cls)
-        cls.__reduce_ex__ = _reduce_ex_by_global_name
-        global_enum(cls)
+        cls = cls(name, members, module=module)
+        cls.__reduce_ex__ = _reduce_ex_by_name
+        module_globals.update(cls.__members__)
         module_globals[name] = cls
         return cls
 
@@ -807,7 +580,7 @@ def _get_mixins_(class_name, bases):
             return object, Enum
 
         def _find_data_type(bases):
-            data_types = set()
+            data_types = []
             for chain in bases:
                 candidate = None
                 for base in chain.__mro__:
@@ -815,19 +588,19 @@ def _find_data_type(bases):
                         continue
                     elif issubclass(base, Enum):
                         if base._member_type_ is not object:
-                            data_types.add(base._member_type_)
+                            data_types.append(base._member_type_)
                             break
                     elif '__new__' in base.__dict__:
                         if issubclass(base, Enum):
                             continue
-                        data_types.add(candidate or base)
+                        data_types.append(candidate or base)
                         break
                     else:
                         candidate = candidate or base
             if len(data_types) > 1:
                 raise TypeError('%r: too many data types: %r' % (class_name, data_types))
             elif data_types:
-                return data_types.pop()
+                return data_types[0]
             else:
                 return None
 
@@ -857,7 +630,7 @@ def _find_new_(classdict, member_type, first_enum):
         __new__ = classdict.get('__new__', None)
 
         # should __new__ be saved as __new_member__ later?
-        save_new = first_enum is not None and __new__ is not None
+        save_new = __new__ is not None
 
         if __new__ is None:
             # check all possibles for __new_member__ before falling back to
@@ -881,21 +654,19 @@ def _find_new_(classdict, member_type, first_enum):
         # if a non-object.__new__ is used then whatever value/tuple was
         # assigned to the enum member name will be passed to __new__ and to the
         # new enum member's __init__
-        if first_enum is None or __new__ in (Enum.__new__, object.__new__):
+        if __new__ is object.__new__:
             use_args = False
         else:
             use_args = True
         return __new__, save_new, use_args
-EnumMeta = EnumType
 
 
-class Enum(metaclass=EnumType):
+class Enum(metaclass=EnumMeta):
     """
     Generic enumeration.
 
     Derive from this class to define new enumerations.
     """
-
     def __new__(cls, value):
         # all enum instances are actually created during class construction
         # without calling this method; this method is called by the metaclass'
@@ -922,30 +693,19 @@ def __new__(cls, value):
         except Exception as e:
             exc = e
             result = None
-        try:
-            if isinstance(result, cls):
-                return result
-            elif (
-                    Flag is not None and issubclass(cls, Flag)
-                    and cls._boundary_ is EJECT and isinstance(result, int)
-                ):
-                return result
-            else:
-                ve_exc = ValueError("%r is not a valid %s" % (value, cls.__qualname__))
-                if result is None and exc is None:
-                    raise ve_exc
-                elif exc is None:
-                    exc = TypeError(
-                            'error in %s._missing_: returned %r instead of None or a valid member'
-                            % (cls.__name__, result)
-                            )
-                if not isinstance(exc, ValueError):
-                    exc.__context__ = ve_exc
-                raise exc
-        finally:
-            # ensure all variables that could hold an exception are destroyed
-            exc = None
-            ve_exc = None
+        if isinstance(result, cls):
+            return result
+        else:
+            ve_exc = ValueError("%r is not a valid %s" % (value, cls.__qualname__))
+            if result is None and exc is None:
+                raise ve_exc
+            elif exc is None:
+                exc = TypeError(
+                        'error in %s._missing_: returned %r instead of None or a valid member'
+                        % (cls.__name__, result)
+                        )
+            exc.__context__ = ve_exc
+            raise exc
 
     def _generate_next_value_(name, start, count, last_values):
         """
@@ -969,10 +729,11 @@ def _missing_(cls, value):
         return None
 
     def __repr__(self):
-        return "%s.%s" % ( self.__class__.__name__, self._name_)
+        return "<%s.%s: %r>" % (
+                self.__class__.__name__, self._name_, self._value_)
 
     def __str__(self):
-        return "%s" % (self._name_, )
+        return "%s.%s" % (self.__class__.__name__, self._name_)
 
     def __dir__(self):
         """
@@ -993,23 +754,14 @@ def __format__(self, format_spec):
         # mixed-in Enums should use the mixed-in type's __format__, otherwise
         # we can get strange results with the Enum name showing up instead of
         # the value
-        #
+
         # pure Enum branch, or branch with __str__ explicitly overridden
-        str_overridden = type(self).__str__ not in (Enum.__str__, IntEnum.__str__, Flag.__str__)
+        str_overridden = type(self).__str__ not in (Enum.__str__, Flag.__str__)
         if self._member_type_ is object or str_overridden:
             cls = str
             val = str(self)
         # mix-in branch
         else:
-            if not format_spec or format_spec in ('{}','{:}'):
-                import warnings
-                warnings.warn(
-                        "in 3.12 format() will use the enum member, not the enum member's value;\n"
-                        "use a format specifier, such as :d for an integer-based Enum, to maintain "
-                        "the current display",
-                        DeprecationWarning,
-                        stacklevel=2,
-                        )
             cls = self._member_type_
             val = self._value_
         return cls.__format__(val, format_spec)
@@ -1018,104 +770,34 @@ def __hash__(self):
         return hash(self._name_)
 
     def __reduce_ex__(self, proto):
-        return getattr, (self.__class__, self._name_)
+        return self.__class__, (self._value_, )
 
-    # enum.property is used to provide access to the `name` and
-    # `value` attributes of enum members while keeping some measure of
+    # DynamicClassAttribute is used to provide access to the `name` and
+    # `value` properties of enum members while keeping some measure of
     # protection from modification, while still allowing for an enumeration
     # to have members named `name` and `value`.  This works because enumeration
-    # members are not set directly on the enum class; they are kept in a
-    # separate structure, _member_map_, which is where enum.property looks for
-    # them
+    # members are not set directly on the enum class -- __getattr__ is
+    # used to look them up.
 
-    @property
+    @DynamicClassAttribute
     def name(self):
         """The name of the Enum member."""
         return self._name_
 
-    @property
+    @DynamicClassAttribute
     def value(self):
         """The value of the Enum member."""
         return self._value_
 
 
 class IntEnum(int, Enum):
-    """
-    Enum where members are also (and must be) ints
-    """
-
-    def __str__(self):
-        return "%s" % (self._name_, )
-
-    def __format__(self, format_spec):
-        """
-        Returns format using actual value unless __str__ has been overridden.
-        """
-        str_overridden = type(self).__str__ != IntEnum.__str__
-        if str_overridden:
-            cls = str
-            val = str(self)
-        else:
-            cls = self._member_type_
-            val = self._value_
-        return cls.__format__(val, format_spec)
+    """Enum where members are also (and must be) ints"""
 
 
-class StrEnum(str, Enum):
-    """
-    Enum where members are also (and must be) strings
-    """
-
-    def __new__(cls, *values):
-        if len(values) > 3:
-            raise TypeError('too many arguments for str(): %r' % (values, ))
-        if len(values) == 1:
-            # it must be a string
-            if not isinstance(values[0], str):
-                raise TypeError('%r is not a string' % (values[0], ))
-        if len(values) >= 2:
-            # check that encoding argument is a string
-            if not isinstance(values[1], str):
-                raise TypeError('encoding must be a string, not %r' % (values[1], ))
-        if len(values) == 3:
-            # check that errors argument is a string
-            if not isinstance(values[2], str):
-                raise TypeError('errors must be a string, not %r' % (values[2]))
-        value = str(*values)
-        member = str.__new__(cls, value)
-        member._value_ = value
-        return member
-
-    __str__ = str.__str__
-
-    __format__ = str.__format__
-
-    def _generate_next_value_(name, start, count, last_values):
-        """
-        Return the lower-cased version of the member name.
-        """
-        return name.lower()
-
-
-def _reduce_ex_by_global_name(self, proto):
+def _reduce_ex_by_name(self, proto):
     return self.name
 
-class FlagBoundary(StrEnum):
-    """
-    control how out of range values are handled
-    "strict" -> error is raised  [default for Flag]
-    "conform" -> extra bits are discarded
-    "eject" -> lose flag status [default for IntFlag]
-    "keep" -> keep flag status and all bits
-    """
-    STRICT = auto()
-    CONFORM = auto()
-    EJECT = auto()
-    KEEP = auto()
-STRICT, CONFORM, EJECT, KEEP = FlagBoundary
-
-
-class Flag(Enum, boundary=STRICT):
+class Flag(Enum):
     """
     Support for flags
     """
@@ -1131,110 +813,45 @@ def _generate_next_value_(name, start, count, last_values):
         """
         if not count:
             return start if start is not None else 1
-        last_value = max(last_values)
-        try:
-            high_bit = _high_bit(last_value)
-        except Exception:
-            raise TypeError('Invalid Flag value: %r' % last_value) from None
+        for last_value in reversed(last_values):
+            try:
+                high_bit = _high_bit(last_value)
+                break
+            except Exception:
+                raise TypeError('Invalid Flag value: %r' % last_value) from None
         return 2 ** (high_bit+1)
 
     @classmethod
-    def _iter_member_by_value_(cls, value):
-        """
-        Extract all members from the value in definition (i.e. increasing value) order.
-        """
-        for val in _iter_bits_lsb(value & cls._flag_mask_):
-            yield cls._value2member_map_.get(val)
-
-    _iter_member_ = _iter_member_by_value_
-
-    @classmethod
-    def _iter_member_by_def_(cls, value):
-        """
-        Extract all members from the value in definition order.
-        """
-        yield from sorted(
-                cls._iter_member_by_value_(value),
-                key=lambda m: m._sort_order_,
-                )
-
-    @classmethod
     def _missing_(cls, value):
         """
-        Create a composite member containing all canonical members present in `value`.
-
-        If non-member values are present, result depends on `_boundary_` setting.
+        Returns member (possibly creating it) if one can be found for value.
         """
-        if not isinstance(value, int):
-            raise ValueError(
-                    "%r is not a valid %s" % (value, cls.__qualname__)
-                    )
-        # check boundaries
-        # - value must be in range (e.g. -16 <-> +15, i.e. ~15 <-> 15)
-        # - value must not include any skipped flags (e.g. if bit 2 is not
-        #   defined, then 0d10 is invalid)
-        flag_mask = cls._flag_mask_
-        all_bits = cls._all_bits_
-        neg_value = None
-        if (
-                not ~all_bits <= value <= all_bits
-                or value & (all_bits ^ flag_mask)
-            ):
-            if cls._boundary_ is STRICT:
-                max_bits = max(value.bit_length(), flag_mask.bit_length())
-                raise ValueError(
-                        "%s: invalid value: %r\n    given %s\n  allowed %s" % (
-                            cls.__name__, value, bin(value, max_bits), bin(flag_mask, max_bits),
-                            ))
-            elif cls._boundary_ is CONFORM:
-                value = value & flag_mask
-            elif cls._boundary_ is EJECT:
-                return value
-            elif cls._boundary_ is KEEP:
-                if value < 0:
-                    value = (
-                            max(all_bits+1, 2**(value.bit_length()))
-                            + value
-                            )
-            else:
-                raise ValueError(
-                        'unknown flag boundary: %r' % (cls._boundary_, )
-                        )
+        original_value = value
         if value < 0:
-            neg_value = value
-            value = all_bits + 1 + value
-        # get members and unknown
-        unknown = value & ~flag_mask
-        member_value = value & flag_mask
-        if unknown and cls._boundary_ is not KEEP:
-            raise ValueError(
-                    '%s(%r) -->  unknown values %r [%s]'
-                    % (cls.__name__, value, unknown, bin(unknown))
-                    )
-        # normal Flag?
-        __new__ = getattr(cls, '__new_member__', None)
-        if cls._member_type_ is object and not __new__:
+            value = ~value
+        possible_member = cls._create_pseudo_member_(value)
+        if original_value < 0:
+            possible_member = ~possible_member
+        return possible_member
+
+    @classmethod
+    def _create_pseudo_member_(cls, value):
+        """
+        Create a composite member iff value contains only members.
+        """
+        pseudo_member = cls._value2member_map_.get(value, None)
+        if pseudo_member is None:
+            # verify all bits are accounted for
+            _, extra_flags = _decompose(cls, value)
+            if extra_flags:
+                raise ValueError("%r is not a valid %s" % (value, cls.__qualname__))
             # construct a singleton enum pseudo-member
             pseudo_member = object.__new__(cls)
-        else:
-            pseudo_member = (__new__ or cls._member_type_.__new__)(cls, value)
-        if not hasattr(pseudo_member, '_value_'):
-            pseudo_member._value_ = value
-        if member_value:
-            pseudo_member._name_ = '|'.join([
-                m._name_ for m in cls._iter_member_(member_value)
-                ])
-            if unknown:
-                pseudo_member._name_ += '|0x%x' % unknown
-        else:
             pseudo_member._name_ = None
-        # use setdefault in case another thread already created a composite
-        # with this value, but only if all members are known
-        # note: zero is a special case -- add it
-        if not unknown:
+            pseudo_member._value_ = value
+            # use setdefault in case another thread already created a composite
+            # with this value
             pseudo_member = cls._value2member_map_.setdefault(value, pseudo_member)
-            if neg_value is not None:
-                cls._value2member_map_[neg_value] = pseudo_member
         return pseudo_member
 
     def __contains__(self, other):
@@ -1245,42 +862,31 @@ def __contains__(self, other):
             raise TypeError(
                 "unsupported operand type(s) for 'in': '%s' and '%s'" % (
                     type(other).__qualname__, self.__class__.__qualname__))
-        if other._value_ == 0 or self._value_ == 0:
-            return False
         return other._value_ & self._value_ == other._value_
 
-    def __iter__(self):
-        """
-        Returns flags in definition order.
-        """
-        yield from self._iter_member_(self._value_)
-
-    def __len__(self):
-        return self._value_.bit_count()
-
     def __repr__(self):
-        cls_name = self.__class__.__name__
-        if self._name_ is None:
-            return "0x%x" % (self._value_, )
-        if _is_single_bit(self._value_):
-            return '%s.%s' % (cls_name, self._name_)
-        if self._boundary_ is not FlagBoundary.KEEP:
-            return '%s.' % cls_name + ('|%s.' % cls_name).join(self.name.split('|'))
-        else:
-            name = []
-            for n in self._name_.split('|'):
-                if n.startswith('0'):
-                    name.append(n)
-                else:
-                    name.append('%s.%s' % (cls_name, n))
-            return '|'.join(name)
+        cls = self.__class__
+        if self._name_ is not None:
+            return '<%s.%s: %r>' % (cls.__name__, self._name_, self._value_)
+        members, uncovered = _decompose(cls, self._value_)
+        return '<%s.%s: %r>' % (
+                cls.__name__,
+                '|'.join([str(m._name_ or m._value_) for m in members]),
+                self._value_,
+                )
 
     def __str__(self):
         cls = self.__class__
-        if self._name_ is None:
-            return '%s(%x)' % (cls.__name__, self._value_)
+        if self._name_ is not None:
+            return '%s.%s' % (cls.__name__, self._name_)
+        members, uncovered = _decompose(cls, self._value_)
+        if len(members) == 1 and members[0]._name_ is None:
+            return '%s.%r' % (cls.__name__, members[0]._value_)
         else:
-            return self._name_
+            return '%s.%s' % (
+                    cls.__name__,
+                    '|'.join([str(m._name_ or m._value_) for m in members]),
+                    )
 
     def __bool__(self):
         return bool(self._value_)
@@ -1301,67 +907,86 @@ def __xor__(self, other):
         return self.__class__(self._value_ ^ other._value_)
 
     def __invert__(self):
-        if self._inverted_ is None:
-            if self._boundary_ is KEEP:
-                # use all bits
-                self._inverted_ = self.__class__(~self._value_)
-            else:
-                # calculate flags not in this member
-                self._inverted_ = self.__class__(self._flag_mask_ ^ self._value_)
-            if isinstance(self._inverted_, self.__class__):
-                self._inverted_._inverted_ = self
-        return self._inverted_
+        members, uncovered = _decompose(self.__class__, self._value_)
+        inverted = self.__class__(0)
+        for m in self.__class__:
+            if m not in members and not (m._value_ & self._value_):
+                inverted = inverted | m
+        return self.__class__(inverted)
 
 
-class IntFlag(int, Flag, boundary=EJECT):
+class IntFlag(int, Flag):
     """
     Support for integer-based Flags
     """
 
-    def __format__(self, format_spec):
+    @classmethod
+    def _missing_(cls, value):
         """
-        Returns format using actual value unless __str__ has been overridden.
+        Returns member (possibly creating it) if one can be found for value.
         """
-        str_overridden = type(self).__str__ != Flag.__str__
-        value = self
-        if not str_overridden:
-            value = self._value_
-        return int.__format__(value, format_spec)
+        if not isinstance(value, int):
+            raise ValueError("%r is not a valid %s" % (value, cls.__qualname__))
+        new_member = cls._create_pseudo_member_(value)
+        return new_member
+
+    @classmethod
+    def _create_pseudo_member_(cls, value):
+        """
+        Create a composite member iff value contains only members.
+        """
+        pseudo_member = cls._value2member_map_.get(value, None)
+        if pseudo_member is None:
+            need_to_create = [value]
+            # get unaccounted for bits
+            _, extra_flags = _decompose(cls, value)
+            # timer = 10
+            while extra_flags:
+                # timer -= 1
+                bit = _high_bit(extra_flags)
+                flag_value = 2 ** bit
+                if (flag_value not in cls._value2member_map_ and
+                        flag_value not in need_to_create
+                        ):
+                    need_to_create.append(flag_value)
+                if extra_flags == -flag_value:
+                    extra_flags = 0
+                else:
+                    extra_flags ^= flag_value
+            for value in reversed(need_to_create):
+                # construct singleton pseudo-members
+                pseudo_member = int.__new__(cls, value)
+                pseudo_member._name_ = None
+                pseudo_member._value_ = value
+                # use setdefault in case another thread already created a composite
+                # with this value
+                pseudo_member = cls._value2member_map_.setdefault(value, pseudo_member)
+        return pseudo_member
 
     def __or__(self, other):
-        if isinstance(other, self.__class__):
-            other = other._value_
-        elif isinstance(other, int):
-            other = other
-        else:
+        if not isinstance(other, (self.__class__, int)):
             return NotImplemented
-        value = self._value_
-        return self.__class__(value | other)
+        result = self.__class__(self._value_ | self.__class__(other)._value_)
+        return result
 
     def __and__(self, other):
-        if isinstance(other, self.__class__):
-            other = other._value_
-        elif isinstance(other, int):
-            other = other
-        else:
+        if not isinstance(other, (self.__class__, int)):
             return NotImplemented
-        value = self._value_
-        return self.__class__(value & other)
+        return self.__class__(self._value_ & self.__class__(other)._value_)
 
     def __xor__(self, other):
-        if isinstance(other, self.__class__):
-            other = other._value_
-        elif isinstance(other, int):
-            other = other
-        else:
+        if not isinstance(other, (self.__class__, int)):
             return NotImplemented
-        value = self._value_
-        return self.__class__(value ^ other)
+        return self.__class__(self._value_ ^ self.__class__(other)._value_)
 
     __ror__ = __or__
     __rand__ = __and__
     __rxor__ = __xor__
-    __invert__ = Flag.__invert__
+
+    def __invert__(self):
+        result = self.__class__(~self._value_)
+        return result
+
 
 def _high_bit(value):
     """
@@ -1384,441 +1009,31 @@ def unique(enumeration):
                 (enumeration, alias_details))
     return enumeration
 
-def _power_of_two(value):
-    if value < 1:
-        return False
-    return value == 2 ** _high_bit(value)
-
-def global_enum_repr(self):
-    return '%s.%s' % (self.__class__.__module__, self._name_)
-
-def global_flag_repr(self):
-    module = self.__class__.__module__
-    cls_name = self.__class__.__name__
-    if self._name_ is None:
-        return "%x" % (module, cls_name, self._value_)
-    if _is_single_bit(self):
-        return '%s.%s' % (module, self._name_)
-    if self._boundary_ is not FlagBoundary.KEEP:
-        return module + module.join(self.name.split('|'))
-    else:
-        name = []
-        for n in self._name_.split('|'):
-            if n.startswith('0'):
-                name.append(n)
-            else:
-                name.append('%s.%s' % (module, n))
-        return '|'.join(name)
-
-
-def global_enum(cls):
+def _decompose(flag, value):
     """
-    decorator that makes the repr() of an enum member reference its module
-    instead of its class; also exports all members to the enum's module's
-    global namespace
+    Extract all members from the value.
     """
-    if issubclass(cls, Flag):
-        cls.__repr__ = global_flag_repr
-    else:
-        cls.__repr__ = global_enum_repr
-    sys.modules[cls.__module__].__dict__.update(cls.__members__)
-    return cls
-
-def _simple_enum(etype=Enum, *, boundary=None, use_args=None):
-    """
-    Class decorator that converts a normal class into an :class:`Enum`.  No
-    safety checks are done, and some advanced behavior (such as
-    :func:`__init_subclass__`) is not available.  Enum creation can be faster
-    using :func:`simple_enum`.
-
-        >>> from enum import Enum, _simple_enum
-        >>> @_simple_enum(Enum)
-        ... class Color:
-        ...     RED = auto()
-        ...     GREEN = auto()
-        ...     BLUE = auto()
-        >>> Color
-        <enum 'Color'>
-    """
-    def convert_class(cls):
-        nonlocal use_args
-        cls_name = cls.__name__
-        if use_args is None:
-            use_args = etype._use_args_
-        __new__ = cls.__dict__.get('__new__')
-        if __new__ is not None:
-            new_member = __new__.__func__
-        else:
-            new_member = etype._member_type_.__new__
-        attrs = {}
-        body = {}
-        if __new__ is not None:
-            body['__new_member__'] = new_member
-        body['_new_member_'] = new_member
-        body['_use_args_'] = use_args
-        body['_generate_next_value_'] = gnv = etype._generate_next_value_
-        body['_member_names_'] = member_names = []
-        body['_member_map_'] = member_map = {}
-        body['_value2member_map_'] = value2member_map = {}
-        body['_unhashable_values_'] = []
-        body['_member_type_'] = member_type = etype._member_type_
-        if issubclass(etype, Flag):
-            body['_boundary_'] = boundary or etype._boundary_
-            body['_flag_mask_'] = None
-            body['_all_bits_'] = None
-            body['_inverted_'] = None
-        for name, obj in cls.__dict__.items():
-            if name in ('__dict__', '__weakref__'):
-                continue
-            if _is_dunder(name) or _is_private(cls_name, name) or _is_sunder(name) or _is_descriptor(obj):
-                body[name] = obj
-            else:
-                attrs[name] = obj
-        if cls.__dict__.get('__doc__') is None:
-            body['__doc__'] = 'An enumeration.'
-        #
-        # double check that repr and friends are not the mixin's or various
-        # things break (such as pickle)
-        # however, if the method is defined in the Enum itself, don't replace
-        # it
-        enum_class = type(cls_name, (etype, ), body, boundary=boundary, _simple=True)
-        for name in ('__repr__', '__str__', '__format__', '__reduce_ex__'):
-            if name in body:
-                continue
-            class_method = getattr(enum_class, name)
-            obj_method = getattr(member_type, name, None)
-            enum_method = getattr(etype, name, None)
-            if obj_method is not None and obj_method is class_method:
-                setattr(enum_class, name, enum_method)
-        gnv_last_values = []
-        if issubclass(enum_class, Flag):
-            # Flag / IntFlag
-            single_bits = multi_bits = 0
-            for name, value in attrs.items():
-                if isinstance(value, auto) and auto.value is _auto_null:
-                    value = gnv(name, 1, len(member_names), gnv_last_values)
-                if value in value2member_map:
-                    # an alias to an existing member
-                    redirect = property()
-                    redirect.__set_name__(enum_class, name)
-                    setattr(enum_class, name, redirect)
-                    member_map[name] = value2member_map[value]
-                else:
-                    # create the member
-                    if use_args:
-                        if not isinstance(value, tuple):
-                            value = (value, )
-                        member = new_member(enum_class, *value)
-                        value = value[0]
-                    else:
-                        member = new_member(enum_class)
-                    if __new__ is None:
-                        member._value_ = value
-                    member._name_ = name
-                    member.__objclass__ = enum_class
-                    member.__init__(value)
-                    redirect = property()
-                    redirect.__set_name__(enum_class, name)
-                    setattr(enum_class, name, redirect)
-                    member_map[name] = member
-                    member._sort_order_ = len(member_names)
-                    value2member_map[value] = member
-                    if _is_single_bit(value):
-                        # not a multi-bit alias, record in _member_names_ and _flag_mask_
-                        member_names.append(name)
-                        single_bits |= value
-                    else:
-                        multi_bits |= value
-                    gnv_last_values.append(value)
-            enum_class._flag_mask_ = single_bits
-            enum_class._all_bits_ = 2 ** ((single_bits|multi_bits).bit_length()) - 1
-            # set correct __iter__
-            member_list = [m._value_ for m in enum_class]
-            if member_list != sorted(member_list):
-                enum_class._iter_member_ = enum_class._iter_member_by_def_
-        else:
-            # Enum / IntEnum / StrEnum
-            for name, value in attrs.items():
-                if isinstance(value, auto):
-                    if value.value is _auto_null:
-                        value.value = gnv(name, 1, len(member_names), gnv_last_values)
-                    value = value.value
-                if value in value2member_map:
-                    # an alias to an existing member
-                    redirect = property()
-                    redirect.__set_name__(enum_class, name)
-                    setattr(enum_class, name, redirect)
-                    member_map[name] = value2member_map[value]
-                else:
-                    # create the member
-                    if use_args:
-                        if not isinstance(value, tuple):
-                            value = (value, )
-                        member = new_member(enum_class, *value)
-                        value = value[0]
-                    else:
-                        member = new_member(enum_class)
-                    if __new__ is None:
-                        member._value_ = value
-                    member._name_ = name
-                    member.__objclass__ = enum_class
-                    member.__init__(value)
-                    member._sort_order_ = len(member_names)
-                    redirect = property()
-                    redirect.__set_name__(enum_class, name)
-                    setattr(enum_class, name, redirect)
-                    member_map[name] = member
-                    value2member_map[value] = member
-                    member_names.append(name)
-                    gnv_last_values.append(value)
-        if '__new__' in body:
-            enum_class.__new_member__ = enum_class.__new__
-        enum_class.__new__ = Enum.__new__
-        return enum_class
-    return convert_class
-
-@_simple_enum(StrEnum)
-class EnumCheck:
-    """
-    various conditions to check an enumeration for
-    """
-    CONTINUOUS = "no skipped integer values"
-    NAMED_FLAGS = "multi-flag aliases may not contain unnamed flags"
-    UNIQUE = "one name per value"
-CONTINUOUS, NAMED_FLAGS, UNIQUE = EnumCheck
-
-
-class verify:
-    """
-    Check an enumeration for various constraints. (see EnumCheck)
-    """
-    def __init__(self, *checks):
-        self.checks = checks
-    def __call__(self, enumeration):
-        checks = self.checks
-        cls_name = enumeration.__name__
-        if Flag is not None and issubclass(enumeration, Flag):
-            enum_type = 'flag'
-        elif issubclass(enumeration, Enum):
-            enum_type = 'enum'
-        else:
-            raise TypeError("the 'verify' decorator only works with Enum and Flag")
-        for check in checks:
-            if check is UNIQUE:
-                # check for duplicate names
-                duplicates = []
-                for name, member in enumeration.__members__.items():
-                    if name != member.name:
-                        duplicates.append((name, member.name))
-                if duplicates:
-                    alias_details = ', '.join(
-                            ["%s -> %s" % (alias, name) for (alias, name) in duplicates])
-                    raise ValueError('aliases found in %r: %s' %
-                            (enumeration, alias_details))
-            elif check is CONTINUOUS:
-                values = set(e.value for e in enumeration)
-                if len(values) < 2:
-                    continue
-                low, high = min(values), max(values)
-                missing = []
-                if enum_type == 'flag':
-                    # check for powers of two
-                    for i in range(_high_bit(low)+1, _high_bit(high)):
-                        if 2**i not in values:
-                            missing.append(2**i)
-                elif enum_type == 'enum':
-                    # check for powers of one
-                    for i in range(low+1, high):
-                        if i not in values:
-                            missing.append(i)
-                else:
-                    raise Exception('verify: unknown type %r' % enum_type)
-                if missing:
-                    raise ValueError(('invalid %s %r: missing values %s' % (
-                            enum_type, cls_name, ', '.join((str(m) for m in missing)))
-                            )[:256])
-                            # limit max length to protect against DOS attacks
-            elif check is NAMED_FLAGS:
-                # examine each alias and check for unnamed flags
-                member_names = enumeration._member_names_
-                member_values = [m.value for m in enumeration]
-                missing_names = []
-                missing_value = 0
-                for name, alias in enumeration._member_map_.items():
-                    if name in member_names:
-                        # not an alias
-                        continue
-                    values = list(_iter_bits_lsb(alias.value))
-                    missed = [v for v in values if v not in member_values]
-                    if missed:
-                        missing_names.append(name)
-                        missing_value |= reduce(_or_, missed)
-                if missing_names:
-                    if len(missing_names) == 1:
-                        alias = 'alias %s is missing' % missing_names[0]
-                    else:
-                        alias = 'aliases %s and %s are missing' % (
-                                ', '.join(missing_names[:-1]), missing_names[-1]
-                                )
-                    if _is_single_bit(missing_value):
-                        value = 'value 0x%x' % missing_value
-                    else:
-                        value = 'combined values of 0x%x' % missing_value
-                    raise ValueError(
-                            'invalid Flag %r: %s %s [use enum.show_flag_values(value) for details]'
-                            % (cls_name, alias, value)
-                            )
-        return enumeration
-
-def _test_simple_enum(checked_enum, simple_enum):
-    """
-    A function that can be used to test an enum created with :func:`_simple_enum`
-    against the version created by subclassing :class:`Enum`::
-
-        >>> from enum import Enum, _simple_enum, _test_simple_enum
-        >>> @_simple_enum(Enum)
-        ... class Color:
-        ...     RED = auto()
-        ...     GREEN = auto()
-        ...     BLUE = auto()
-        >>> class CheckedColor(Enum):
-        ...     RED = auto()
-        ...     GREEN = auto()
-        ...     BLUE = auto()
-        >>> _test_simple_enum(CheckedColor, Color)
-
-    If differences are found, a :exc:`TypeError` is raised.
-    """
-    failed = []
-    if checked_enum.__dict__ != simple_enum.__dict__:
-        checked_dict = checked_enum.__dict__
-        checked_keys = list(checked_dict.keys())
-        simple_dict = simple_enum.__dict__
-        simple_keys = list(simple_dict.keys())
-        member_names = set(
-                list(checked_enum._member_map_.keys())
-                + list(simple_enum._member_map_.keys())
-                )
-        for key in set(checked_keys + simple_keys):
-            if key in ('__module__', '_member_map_', '_value2member_map_'):
-                # keys known to be different
-                continue
-            elif key in member_names:
-                # members are checked below
-                continue
-            elif key not in simple_keys:
-                failed.append("missing key: %r" % (key, ))
-            elif key not in checked_keys:
-                failed.append("extra key:   %r" % (key, ))
-            else:
-                checked_value = checked_dict[key]
-                simple_value = simple_dict[key]
-                if callable(checked_value):
-                    continue
-                if key == '__doc__':
-                    # remove all spaces/tabs
-                    compressed_checked_value = checked_value.replace(' ','').replace('\t','')
-                    compressed_simple_value = simple_value.replace(' ','').replace('\t','')
-                    if compressed_checked_value != compressed_simple_value:
-                        failed.append("%r:\n         %s\n         %s" % (
-                                key,
-                                "checked -> %r" % (checked_value, ),
-                                "simple  -> %r" % (simple_value, ),
-                                ))
-                elif checked_value != simple_value:
-                    failed.append("%r:\n         %s\n         %s" % (
-                            key,
-                            "checked -> %r" % (checked_value, ),
-                            "simple  -> %r" % (simple_value, ),
-                            ))
-        failed.sort()
-        for name in member_names:
-            failed_member = []
-            if name not in simple_keys:
-                failed.append('missing member from simple enum: %r' % name)
-            elif name not in checked_keys:
-                failed.append('extra member in simple enum: %r' % name)
-            else:
-                checked_member_dict = checked_enum[name].__dict__
-                checked_member_keys = list(checked_member_dict.keys())
-                simple_member_dict = simple_enum[name].__dict__
-                simple_member_keys = list(simple_member_dict.keys())
-                for key in set(checked_member_keys + simple_member_keys):
-                    if key in ('__module__', '__objclass__', '_inverted_'):
-                        # keys known to be different or absent
-                        continue
-                    elif key not in simple_member_keys:
-                        failed_member.append("missing key %r not in the simple enum member %r" % (key, name))
-                    elif key not in checked_member_keys:
-                        failed_member.append("extra key %r in simple enum member %r" % (key, name))
-                    else:
-                        checked_value = checked_member_dict[key]
-                        simple_value = simple_member_dict[key]
-                        if checked_value != simple_value:
-                            failed_member.append("%r:\n         %s\n         %s" % (
-                                    key,
-                                    "checked member -> %r" % (checked_value, ),
-                                    "simple member  -> %r" % (simple_value, ),
-                                    ))
-            if failed_member:
-                failed.append('%r member mismatch:\n      %s' % (
-                        name, '\n      '.join(failed_member),
-                        ))
-        for method in (
-                '__str__', '__repr__', '__reduce_ex__', '__format__',
-                '__getnewargs_ex__', '__getnewargs__', '__reduce_ex__', '__reduce__'
-            ):
-            if method in simple_keys and method in checked_keys:
-                # cannot compare functions, and it exists in both, so we're good
-                continue
-            elif method not in simple_keys and method not in checked_keys:
-                # method is inherited -- check it out
-                checked_method = getattr(checked_enum, method, None)
-                simple_method = getattr(simple_enum, method, None)
-                if hasattr(checked_method, '__func__'):
-                    checked_method = checked_method.__func__
-                    simple_method = simple_method.__func__
-                if checked_method != simple_method:
-                    failed.append("%r:  %-30s %s" % (
-                            method,
-                            "checked -> %r" % (checked_method, ),
-                            "simple -> %r" % (simple_method, ),
-                            ))
-            else:
-                # if the method existed in only one of the enums, it will have been caught
-                # in the first checks above
-                pass
-    if failed:
-        raise TypeError('enum mismatch:\n   %s' % '\n   '.join(failed))
-
-def _old_convert_(etype, name, module, filter, source=None, *, boundary=None):
-    """
-    Create a new Enum subclass that replaces a collection of global constants
-    """
-    # convert all constants from source (or module) that pass filter() to
-    # a new Enum called name, and export the enum and its members back to
-    # module;
-    # also, replace the __reduce_ex__ method so unpickling works in
-    # previous Python versions
-    module_globals = sys.modules[module].__dict__
-    if source:
-        source = source.__dict__
-    else:
-        source = module_globals
-    # _value2member_map_ is populated in the same order every time
-    # for a consistent reverse mapping of number to name when there
-    # are multiple names for the same number.
-    members = [
-            (name, value)
-            for name, value in source.items()
-            if filter(name)]
-    try:
-        # sort by value
-        members.sort(key=lambda t: (t[1], t[0]))
-    except TypeError:
-        # unless some values aren't comparable, in which case sort by name
-        members.sort(key=lambda t: t[0])
-    cls = etype(name, members, module=module, boundary=boundary or KEEP)
-    cls.__reduce_ex__ = _reduce_ex_by_global_name
-    cls.__repr__ = global_enum_repr
-    return cls
+    # _decompose is only called if the value is not named
+    not_covered = value
+    negative = value < 0
+    members = []
+    for member in flag:
+        member_value = member.value
+        if member_value and member_value & value == member_value:
+            members.append(member)
+            not_covered &= ~member_value
+    if not negative:
+        tmp = not_covered
+        while tmp:
+            flag_value = 2 ** _high_bit(tmp)
+            if flag_value in flag._value2member_map_:
+                members.append(flag._value2member_map_[flag_value])
+                not_covered &= ~flag_value
+            tmp &= ~flag_value
+    if not members and value in flag._value2member_map_:
+        members.append(flag._value2member_map_[value])
+    members.sort(key=lambda m: m._value_, reverse=True)
+    if len(members) > 1 and members[0].value == value:
+        # we have the breakdown, don't need the value member itself
+        members.pop(0)
+    return members, not_covered