xref: /aosp_15_r20/prebuilts/build-tools/common/py3-stdlib/enum.py (revision cda5da8d549138a6648c5ee6d7a49cf8f4a657be)
1*cda5da8dSAndroid Build Coastguard Workerimport sys
2*cda5da8dSAndroid Build Coastguard Workerimport builtins as bltns
3*cda5da8dSAndroid Build Coastguard Workerfrom types import MappingProxyType, DynamicClassAttribute
4*cda5da8dSAndroid Build Coastguard Workerfrom operator import or_ as _or_
5*cda5da8dSAndroid Build Coastguard Workerfrom functools import reduce
6*cda5da8dSAndroid Build Coastguard Worker
7*cda5da8dSAndroid Build Coastguard Worker
8*cda5da8dSAndroid Build Coastguard Worker__all__ = [
9*cda5da8dSAndroid Build Coastguard Worker        'EnumType', 'EnumMeta',
10*cda5da8dSAndroid Build Coastguard Worker        'Enum', 'IntEnum', 'StrEnum', 'Flag', 'IntFlag', 'ReprEnum',
11*cda5da8dSAndroid Build Coastguard Worker        'auto', 'unique', 'property', 'verify', 'member', 'nonmember',
12*cda5da8dSAndroid Build Coastguard Worker        'FlagBoundary', 'STRICT', 'CONFORM', 'EJECT', 'KEEP',
13*cda5da8dSAndroid Build Coastguard Worker        'global_flag_repr', 'global_enum_repr', 'global_str', 'global_enum',
14*cda5da8dSAndroid Build Coastguard Worker        'EnumCheck', 'CONTINUOUS', 'NAMED_FLAGS', 'UNIQUE',
15*cda5da8dSAndroid Build Coastguard Worker        ]
16*cda5da8dSAndroid Build Coastguard Worker
17*cda5da8dSAndroid Build Coastguard Worker
18*cda5da8dSAndroid Build Coastguard Worker# Dummy value for Enum and Flag as there are explicit checks for them
19*cda5da8dSAndroid Build Coastguard Worker# before they have been created.
20*cda5da8dSAndroid Build Coastguard Worker# This is also why there are checks in EnumType like `if Enum is not None`
21*cda5da8dSAndroid Build Coastguard WorkerEnum = Flag = EJECT = _stdlib_enums = ReprEnum = None
22*cda5da8dSAndroid Build Coastguard Worker
23*cda5da8dSAndroid Build Coastguard Workerclass nonmember(object):
24*cda5da8dSAndroid Build Coastguard Worker    """
25*cda5da8dSAndroid Build Coastguard Worker    Protects item from becoming an Enum member during class creation.
26*cda5da8dSAndroid Build Coastguard Worker    """
27*cda5da8dSAndroid Build Coastguard Worker    def __init__(self, value):
28*cda5da8dSAndroid Build Coastguard Worker        self.value = value
29*cda5da8dSAndroid Build Coastguard Worker
30*cda5da8dSAndroid Build Coastguard Workerclass member(object):
31*cda5da8dSAndroid Build Coastguard Worker    """
32*cda5da8dSAndroid Build Coastguard Worker    Forces item to become an Enum member during class creation.
33*cda5da8dSAndroid Build Coastguard Worker    """
34*cda5da8dSAndroid Build Coastguard Worker    def __init__(self, value):
35*cda5da8dSAndroid Build Coastguard Worker        self.value = value
36*cda5da8dSAndroid Build Coastguard Worker
37*cda5da8dSAndroid Build Coastguard Workerdef _is_descriptor(obj):
38*cda5da8dSAndroid Build Coastguard Worker    """
39*cda5da8dSAndroid Build Coastguard Worker    Returns True if obj is a descriptor, False otherwise.
40*cda5da8dSAndroid Build Coastguard Worker    """
41*cda5da8dSAndroid Build Coastguard Worker    return (
42*cda5da8dSAndroid Build Coastguard Worker            hasattr(obj, '__get__') or
43*cda5da8dSAndroid Build Coastguard Worker            hasattr(obj, '__set__') or
44*cda5da8dSAndroid Build Coastguard Worker            hasattr(obj, '__delete__')
45*cda5da8dSAndroid Build Coastguard Worker            )
46*cda5da8dSAndroid Build Coastguard Worker
47*cda5da8dSAndroid Build Coastguard Workerdef _is_dunder(name):
48*cda5da8dSAndroid Build Coastguard Worker    """
49*cda5da8dSAndroid Build Coastguard Worker    Returns True if a __dunder__ name, False otherwise.
50*cda5da8dSAndroid Build Coastguard Worker    """
51*cda5da8dSAndroid Build Coastguard Worker    return (
52*cda5da8dSAndroid Build Coastguard Worker            len(name) > 4 and
53*cda5da8dSAndroid Build Coastguard Worker            name[:2] == name[-2:] == '__' and
54*cda5da8dSAndroid Build Coastguard Worker            name[2] != '_' and
55*cda5da8dSAndroid Build Coastguard Worker            name[-3] != '_'
56*cda5da8dSAndroid Build Coastguard Worker            )
57*cda5da8dSAndroid Build Coastguard Worker
58*cda5da8dSAndroid Build Coastguard Workerdef _is_sunder(name):
59*cda5da8dSAndroid Build Coastguard Worker    """
60*cda5da8dSAndroid Build Coastguard Worker    Returns True if a _sunder_ name, False otherwise.
61*cda5da8dSAndroid Build Coastguard Worker    """
62*cda5da8dSAndroid Build Coastguard Worker    return (
63*cda5da8dSAndroid Build Coastguard Worker            len(name) > 2 and
64*cda5da8dSAndroid Build Coastguard Worker            name[0] == name[-1] == '_' and
65*cda5da8dSAndroid Build Coastguard Worker            name[1:2] != '_' and
66*cda5da8dSAndroid Build Coastguard Worker            name[-2:-1] != '_'
67*cda5da8dSAndroid Build Coastguard Worker            )
68*cda5da8dSAndroid Build Coastguard Worker
69*cda5da8dSAndroid Build Coastguard Workerdef _is_internal_class(cls_name, obj):
70*cda5da8dSAndroid Build Coastguard Worker    # do not use `re` as `re` imports `enum`
71*cda5da8dSAndroid Build Coastguard Worker    if not isinstance(obj, type):
72*cda5da8dSAndroid Build Coastguard Worker        return False
73*cda5da8dSAndroid Build Coastguard Worker    qualname = getattr(obj, '__qualname__', '')
74*cda5da8dSAndroid Build Coastguard Worker    s_pattern = cls_name + '.' + getattr(obj, '__name__', '')
75*cda5da8dSAndroid Build Coastguard Worker    e_pattern = '.' + s_pattern
76*cda5da8dSAndroid Build Coastguard Worker    return qualname == s_pattern or qualname.endswith(e_pattern)
77*cda5da8dSAndroid Build Coastguard Worker
78*cda5da8dSAndroid Build Coastguard Workerdef _is_private(cls_name, name):
79*cda5da8dSAndroid Build Coastguard Worker    # do not use `re` as `re` imports `enum`
80*cda5da8dSAndroid Build Coastguard Worker    pattern = '_%s__' % (cls_name, )
81*cda5da8dSAndroid Build Coastguard Worker    pat_len = len(pattern)
82*cda5da8dSAndroid Build Coastguard Worker    if (
83*cda5da8dSAndroid Build Coastguard Worker            len(name) > pat_len
84*cda5da8dSAndroid Build Coastguard Worker            and name.startswith(pattern)
85*cda5da8dSAndroid Build Coastguard Worker            and name[pat_len:pat_len+1] != ['_']
86*cda5da8dSAndroid Build Coastguard Worker            and (name[-1] != '_' or name[-2] != '_')
87*cda5da8dSAndroid Build Coastguard Worker        ):
88*cda5da8dSAndroid Build Coastguard Worker        return True
89*cda5da8dSAndroid Build Coastguard Worker    else:
90*cda5da8dSAndroid Build Coastguard Worker        return False
91*cda5da8dSAndroid Build Coastguard Worker
92*cda5da8dSAndroid Build Coastguard Workerdef _is_single_bit(num):
93*cda5da8dSAndroid Build Coastguard Worker    """
94*cda5da8dSAndroid Build Coastguard Worker    True if only one bit set in num (should be an int)
95*cda5da8dSAndroid Build Coastguard Worker    """
96*cda5da8dSAndroid Build Coastguard Worker    if num == 0:
97*cda5da8dSAndroid Build Coastguard Worker        return False
98*cda5da8dSAndroid Build Coastguard Worker    num &= num - 1
99*cda5da8dSAndroid Build Coastguard Worker    return num == 0
100*cda5da8dSAndroid Build Coastguard Worker
101*cda5da8dSAndroid Build Coastguard Workerdef _make_class_unpicklable(obj):
102*cda5da8dSAndroid Build Coastguard Worker    """
103*cda5da8dSAndroid Build Coastguard Worker    Make the given obj un-picklable.
104*cda5da8dSAndroid Build Coastguard Worker
105*cda5da8dSAndroid Build Coastguard Worker    obj should be either a dictionary, or an Enum
106*cda5da8dSAndroid Build Coastguard Worker    """
107*cda5da8dSAndroid Build Coastguard Worker    def _break_on_call_reduce(self, proto):
108*cda5da8dSAndroid Build Coastguard Worker        raise TypeError('%r cannot be pickled' % self)
109*cda5da8dSAndroid Build Coastguard Worker    if isinstance(obj, dict):
110*cda5da8dSAndroid Build Coastguard Worker        obj['__reduce_ex__'] = _break_on_call_reduce
111*cda5da8dSAndroid Build Coastguard Worker        obj['__module__'] = '<unknown>'
112*cda5da8dSAndroid Build Coastguard Worker    else:
113*cda5da8dSAndroid Build Coastguard Worker        setattr(obj, '__reduce_ex__', _break_on_call_reduce)
114*cda5da8dSAndroid Build Coastguard Worker        setattr(obj, '__module__', '<unknown>')
115*cda5da8dSAndroid Build Coastguard Worker
116*cda5da8dSAndroid Build Coastguard Workerdef _iter_bits_lsb(num):
117*cda5da8dSAndroid Build Coastguard Worker    # num must be a positive integer
118*cda5da8dSAndroid Build Coastguard Worker    original = num
119*cda5da8dSAndroid Build Coastguard Worker    if isinstance(num, Enum):
120*cda5da8dSAndroid Build Coastguard Worker        num = num.value
121*cda5da8dSAndroid Build Coastguard Worker    if num < 0:
122*cda5da8dSAndroid Build Coastguard Worker        raise ValueError('%r is not a positive integer' % original)
123*cda5da8dSAndroid Build Coastguard Worker    while num:
124*cda5da8dSAndroid Build Coastguard Worker        b = num & (~num + 1)
125*cda5da8dSAndroid Build Coastguard Worker        yield b
126*cda5da8dSAndroid Build Coastguard Worker        num ^= b
127*cda5da8dSAndroid Build Coastguard Worker
128*cda5da8dSAndroid Build Coastguard Workerdef show_flag_values(value):
129*cda5da8dSAndroid Build Coastguard Worker    return list(_iter_bits_lsb(value))
130*cda5da8dSAndroid Build Coastguard Worker
131*cda5da8dSAndroid Build Coastguard Workerdef bin(num, max_bits=None):
132*cda5da8dSAndroid Build Coastguard Worker    """
133*cda5da8dSAndroid Build Coastguard Worker    Like built-in bin(), except negative values are represented in
134*cda5da8dSAndroid Build Coastguard Worker    twos-compliment, and the leading bit always indicates sign
135*cda5da8dSAndroid Build Coastguard Worker    (0=positive, 1=negative).
136*cda5da8dSAndroid Build Coastguard Worker
137*cda5da8dSAndroid Build Coastguard Worker    >>> bin(10)
138*cda5da8dSAndroid Build Coastguard Worker    '0b0 1010'
139*cda5da8dSAndroid Build Coastguard Worker    >>> bin(~10)   # ~10 is -11
140*cda5da8dSAndroid Build Coastguard Worker    '0b1 0101'
141*cda5da8dSAndroid Build Coastguard Worker    """
142*cda5da8dSAndroid Build Coastguard Worker
143*cda5da8dSAndroid Build Coastguard Worker    ceiling = 2 ** (num).bit_length()
144*cda5da8dSAndroid Build Coastguard Worker    if num >= 0:
145*cda5da8dSAndroid Build Coastguard Worker        s = bltns.bin(num + ceiling).replace('1', '0', 1)
146*cda5da8dSAndroid Build Coastguard Worker    else:
147*cda5da8dSAndroid Build Coastguard Worker        s = bltns.bin(~num ^ (ceiling - 1) + ceiling)
148*cda5da8dSAndroid Build Coastguard Worker    sign = s[:3]
149*cda5da8dSAndroid Build Coastguard Worker    digits = s[3:]
150*cda5da8dSAndroid Build Coastguard Worker    if max_bits is not None:
151*cda5da8dSAndroid Build Coastguard Worker        if len(digits) < max_bits:
152*cda5da8dSAndroid Build Coastguard Worker            digits = (sign[-1] * max_bits + digits)[-max_bits:]
153*cda5da8dSAndroid Build Coastguard Worker    return "%s %s" % (sign, digits)
154*cda5da8dSAndroid Build Coastguard Worker
155*cda5da8dSAndroid Build Coastguard Workerdef _dedent(text):
156*cda5da8dSAndroid Build Coastguard Worker    """
157*cda5da8dSAndroid Build Coastguard Worker    Like textwrap.dedent.  Rewritten because we cannot import textwrap.
158*cda5da8dSAndroid Build Coastguard Worker    """
159*cda5da8dSAndroid Build Coastguard Worker    lines = text.split('\n')
160*cda5da8dSAndroid Build Coastguard Worker    blanks = 0
161*cda5da8dSAndroid Build Coastguard Worker    for i, ch in enumerate(lines[0]):
162*cda5da8dSAndroid Build Coastguard Worker        if ch != ' ':
163*cda5da8dSAndroid Build Coastguard Worker            break
164*cda5da8dSAndroid Build Coastguard Worker    for j, l in enumerate(lines):
165*cda5da8dSAndroid Build Coastguard Worker        lines[j] = l[i:]
166*cda5da8dSAndroid Build Coastguard Worker    return '\n'.join(lines)
167*cda5da8dSAndroid Build Coastguard Worker
168*cda5da8dSAndroid Build Coastguard Workerclass _auto_null:
169*cda5da8dSAndroid Build Coastguard Worker    def __repr__(self):
170*cda5da8dSAndroid Build Coastguard Worker        return '_auto_null'
171*cda5da8dSAndroid Build Coastguard Worker_auto_null = _auto_null()
172*cda5da8dSAndroid Build Coastguard Worker
173*cda5da8dSAndroid Build Coastguard Workerclass auto:
174*cda5da8dSAndroid Build Coastguard Worker    """
175*cda5da8dSAndroid Build Coastguard Worker    Instances are replaced with an appropriate value in Enum class suites.
176*cda5da8dSAndroid Build Coastguard Worker    """
177*cda5da8dSAndroid Build Coastguard Worker    def __init__(self, value=_auto_null):
178*cda5da8dSAndroid Build Coastguard Worker        self.value = value
179*cda5da8dSAndroid Build Coastguard Worker
180*cda5da8dSAndroid Build Coastguard Worker    def __repr__(self):
181*cda5da8dSAndroid Build Coastguard Worker        return "auto(%r)" % self.value
182*cda5da8dSAndroid Build Coastguard Worker
183*cda5da8dSAndroid Build Coastguard Workerclass property(DynamicClassAttribute):
184*cda5da8dSAndroid Build Coastguard Worker    """
185*cda5da8dSAndroid Build Coastguard Worker    This is a descriptor, used to define attributes that act differently
186*cda5da8dSAndroid Build Coastguard Worker    when accessed through an enum member and through an enum class.
187*cda5da8dSAndroid Build Coastguard Worker    Instance access is the same as property(), but access to an attribute
188*cda5da8dSAndroid Build Coastguard Worker    through the enum class will instead look in the class' _member_map_ for
189*cda5da8dSAndroid Build Coastguard Worker    a corresponding enum member.
190*cda5da8dSAndroid Build Coastguard Worker    """
191*cda5da8dSAndroid Build Coastguard Worker
192*cda5da8dSAndroid Build Coastguard Worker    def __get__(self, instance, ownerclass=None):
193*cda5da8dSAndroid Build Coastguard Worker        if instance is None:
194*cda5da8dSAndroid Build Coastguard Worker            try:
195*cda5da8dSAndroid Build Coastguard Worker                return ownerclass._member_map_[self.name]
196*cda5da8dSAndroid Build Coastguard Worker            except KeyError:
197*cda5da8dSAndroid Build Coastguard Worker                raise AttributeError(
198*cda5da8dSAndroid Build Coastguard Worker                        '%r has no attribute %r' % (ownerclass, self.name)
199*cda5da8dSAndroid Build Coastguard Worker                        )
200*cda5da8dSAndroid Build Coastguard Worker        else:
201*cda5da8dSAndroid Build Coastguard Worker            if self.fget is None:
202*cda5da8dSAndroid Build Coastguard Worker                # look for a member by this name.
203*cda5da8dSAndroid Build Coastguard Worker                try:
204*cda5da8dSAndroid Build Coastguard Worker                    return ownerclass._member_map_[self.name]
205*cda5da8dSAndroid Build Coastguard Worker                except KeyError:
206*cda5da8dSAndroid Build Coastguard Worker                    raise AttributeError(
207*cda5da8dSAndroid Build Coastguard Worker                            '%r has no attribute %r' % (ownerclass, self.name)
208*cda5da8dSAndroid Build Coastguard Worker                            ) from None
209*cda5da8dSAndroid Build Coastguard Worker            else:
210*cda5da8dSAndroid Build Coastguard Worker                return self.fget(instance)
211*cda5da8dSAndroid Build Coastguard Worker
212*cda5da8dSAndroid Build Coastguard Worker    def __set__(self, instance, value):
213*cda5da8dSAndroid Build Coastguard Worker        if self.fset is None:
214*cda5da8dSAndroid Build Coastguard Worker            raise AttributeError(
215*cda5da8dSAndroid Build Coastguard Worker                    "<enum %r> cannot set attribute %r" % (self.clsname, self.name)
216*cda5da8dSAndroid Build Coastguard Worker                    )
217*cda5da8dSAndroid Build Coastguard Worker        else:
218*cda5da8dSAndroid Build Coastguard Worker            return self.fset(instance, value)
219*cda5da8dSAndroid Build Coastguard Worker
220*cda5da8dSAndroid Build Coastguard Worker    def __delete__(self, instance):
221*cda5da8dSAndroid Build Coastguard Worker        if self.fdel is None:
222*cda5da8dSAndroid Build Coastguard Worker            raise AttributeError(
223*cda5da8dSAndroid Build Coastguard Worker                    "<enum %r> cannot delete attribute %r" % (self.clsname, self.name)
224*cda5da8dSAndroid Build Coastguard Worker                    )
225*cda5da8dSAndroid Build Coastguard Worker        else:
226*cda5da8dSAndroid Build Coastguard Worker            return self.fdel(instance)
227*cda5da8dSAndroid Build Coastguard Worker
228*cda5da8dSAndroid Build Coastguard Worker    def __set_name__(self, ownerclass, name):
229*cda5da8dSAndroid Build Coastguard Worker        self.name = name
230*cda5da8dSAndroid Build Coastguard Worker        self.clsname = ownerclass.__name__
231*cda5da8dSAndroid Build Coastguard Worker
232*cda5da8dSAndroid Build Coastguard Worker
233*cda5da8dSAndroid Build Coastguard Workerclass _proto_member:
234*cda5da8dSAndroid Build Coastguard Worker    """
235*cda5da8dSAndroid Build Coastguard Worker    intermediate step for enum members between class execution and final creation
236*cda5da8dSAndroid Build Coastguard Worker    """
237*cda5da8dSAndroid Build Coastguard Worker
238*cda5da8dSAndroid Build Coastguard Worker    def __init__(self, value):
239*cda5da8dSAndroid Build Coastguard Worker        self.value = value
240*cda5da8dSAndroid Build Coastguard Worker
241*cda5da8dSAndroid Build Coastguard Worker    def __set_name__(self, enum_class, member_name):
242*cda5da8dSAndroid Build Coastguard Worker        """
243*cda5da8dSAndroid Build Coastguard Worker        convert each quasi-member into an instance of the new enum class
244*cda5da8dSAndroid Build Coastguard Worker        """
245*cda5da8dSAndroid Build Coastguard Worker        # first step: remove ourself from enum_class
246*cda5da8dSAndroid Build Coastguard Worker        delattr(enum_class, member_name)
247*cda5da8dSAndroid Build Coastguard Worker        # second step: create member based on enum_class
248*cda5da8dSAndroid Build Coastguard Worker        value = self.value
249*cda5da8dSAndroid Build Coastguard Worker        if not isinstance(value, tuple):
250*cda5da8dSAndroid Build Coastguard Worker            args = (value, )
251*cda5da8dSAndroid Build Coastguard Worker        else:
252*cda5da8dSAndroid Build Coastguard Worker            args = value
253*cda5da8dSAndroid Build Coastguard Worker        if enum_class._member_type_ is tuple:   # special case for tuple enums
254*cda5da8dSAndroid Build Coastguard Worker            args = (args, )     # wrap it one more time
255*cda5da8dSAndroid Build Coastguard Worker        if not enum_class._use_args_:
256*cda5da8dSAndroid Build Coastguard Worker            enum_member = enum_class._new_member_(enum_class)
257*cda5da8dSAndroid Build Coastguard Worker        else:
258*cda5da8dSAndroid Build Coastguard Worker            enum_member = enum_class._new_member_(enum_class, *args)
259*cda5da8dSAndroid Build Coastguard Worker        if not hasattr(enum_member, '_value_'):
260*cda5da8dSAndroid Build Coastguard Worker            if enum_class._member_type_ is object:
261*cda5da8dSAndroid Build Coastguard Worker                enum_member._value_ = value
262*cda5da8dSAndroid Build Coastguard Worker            else:
263*cda5da8dSAndroid Build Coastguard Worker                try:
264*cda5da8dSAndroid Build Coastguard Worker                    enum_member._value_ = enum_class._member_type_(*args)
265*cda5da8dSAndroid Build Coastguard Worker                except Exception as exc:
266*cda5da8dSAndroid Build Coastguard Worker                    new_exc = TypeError(
267*cda5da8dSAndroid Build Coastguard Worker                            '_value_ not set in __new__, unable to create it'
268*cda5da8dSAndroid Build Coastguard Worker                            )
269*cda5da8dSAndroid Build Coastguard Worker                    new_exc.__cause__ = exc
270*cda5da8dSAndroid Build Coastguard Worker                    raise new_exc
271*cda5da8dSAndroid Build Coastguard Worker        value = enum_member._value_
272*cda5da8dSAndroid Build Coastguard Worker        enum_member._name_ = member_name
273*cda5da8dSAndroid Build Coastguard Worker        enum_member.__objclass__ = enum_class
274*cda5da8dSAndroid Build Coastguard Worker        enum_member.__init__(*args)
275*cda5da8dSAndroid Build Coastguard Worker        enum_member._sort_order_ = len(enum_class._member_names_)
276*cda5da8dSAndroid Build Coastguard Worker
277*cda5da8dSAndroid Build Coastguard Worker        if Flag is not None and issubclass(enum_class, Flag):
278*cda5da8dSAndroid Build Coastguard Worker            enum_class._flag_mask_ |= value
279*cda5da8dSAndroid Build Coastguard Worker            if _is_single_bit(value):
280*cda5da8dSAndroid Build Coastguard Worker                enum_class._singles_mask_ |= value
281*cda5da8dSAndroid Build Coastguard Worker            enum_class._all_bits_ = 2 ** ((enum_class._flag_mask_).bit_length()) - 1
282*cda5da8dSAndroid Build Coastguard Worker
283*cda5da8dSAndroid Build Coastguard Worker        # If another member with the same value was already defined, the
284*cda5da8dSAndroid Build Coastguard Worker        # new member becomes an alias to the existing one.
285*cda5da8dSAndroid Build Coastguard Worker        try:
286*cda5da8dSAndroid Build Coastguard Worker            try:
287*cda5da8dSAndroid Build Coastguard Worker                # try to do a fast lookup to avoid the quadratic loop
288*cda5da8dSAndroid Build Coastguard Worker                enum_member = enum_class._value2member_map_[value]
289*cda5da8dSAndroid Build Coastguard Worker            except TypeError:
290*cda5da8dSAndroid Build Coastguard Worker                for name, canonical_member in enum_class._member_map_.items():
291*cda5da8dSAndroid Build Coastguard Worker                    if canonical_member._value_ == value:
292*cda5da8dSAndroid Build Coastguard Worker                        enum_member = canonical_member
293*cda5da8dSAndroid Build Coastguard Worker                        break
294*cda5da8dSAndroid Build Coastguard Worker                else:
295*cda5da8dSAndroid Build Coastguard Worker                    raise KeyError
296*cda5da8dSAndroid Build Coastguard Worker        except KeyError:
297*cda5da8dSAndroid Build Coastguard Worker            # this could still be an alias if the value is multi-bit and the
298*cda5da8dSAndroid Build Coastguard Worker            # class is a flag class
299*cda5da8dSAndroid Build Coastguard Worker            if (
300*cda5da8dSAndroid Build Coastguard Worker                    Flag is None
301*cda5da8dSAndroid Build Coastguard Worker                    or not issubclass(enum_class, Flag)
302*cda5da8dSAndroid Build Coastguard Worker                ):
303*cda5da8dSAndroid Build Coastguard Worker                # no other instances found, record this member in _member_names_
304*cda5da8dSAndroid Build Coastguard Worker                enum_class._member_names_.append(member_name)
305*cda5da8dSAndroid Build Coastguard Worker            elif (
306*cda5da8dSAndroid Build Coastguard Worker                    Flag is not None
307*cda5da8dSAndroid Build Coastguard Worker                    and issubclass(enum_class, Flag)
308*cda5da8dSAndroid Build Coastguard Worker                    and _is_single_bit(value)
309*cda5da8dSAndroid Build Coastguard Worker                ):
310*cda5da8dSAndroid Build Coastguard Worker                # no other instances found, record this member in _member_names_
311*cda5da8dSAndroid Build Coastguard Worker                enum_class._member_names_.append(member_name)
312*cda5da8dSAndroid Build Coastguard Worker        # if necessary, get redirect in place and then add it to _member_map_
313*cda5da8dSAndroid Build Coastguard Worker        found_descriptor = None
314*cda5da8dSAndroid Build Coastguard Worker        for base in enum_class.__mro__[1:]:
315*cda5da8dSAndroid Build Coastguard Worker            descriptor = base.__dict__.get(member_name)
316*cda5da8dSAndroid Build Coastguard Worker            if descriptor is not None:
317*cda5da8dSAndroid Build Coastguard Worker                if isinstance(descriptor, (property, DynamicClassAttribute)):
318*cda5da8dSAndroid Build Coastguard Worker                    found_descriptor = descriptor
319*cda5da8dSAndroid Build Coastguard Worker                    break
320*cda5da8dSAndroid Build Coastguard Worker                elif (
321*cda5da8dSAndroid Build Coastguard Worker                        hasattr(descriptor, 'fget') and
322*cda5da8dSAndroid Build Coastguard Worker                        hasattr(descriptor, 'fset') and
323*cda5da8dSAndroid Build Coastguard Worker                        hasattr(descriptor, 'fdel')
324*cda5da8dSAndroid Build Coastguard Worker                    ):
325*cda5da8dSAndroid Build Coastguard Worker                    found_descriptor = descriptor
326*cda5da8dSAndroid Build Coastguard Worker                    continue
327*cda5da8dSAndroid Build Coastguard Worker        if found_descriptor:
328*cda5da8dSAndroid Build Coastguard Worker            redirect = property()
329*cda5da8dSAndroid Build Coastguard Worker            redirect.member = enum_member
330*cda5da8dSAndroid Build Coastguard Worker            redirect.__set_name__(enum_class, member_name)
331*cda5da8dSAndroid Build Coastguard Worker            # earlier descriptor found; copy fget, fset, fdel to this one.
332*cda5da8dSAndroid Build Coastguard Worker            redirect.fget = found_descriptor.fget
333*cda5da8dSAndroid Build Coastguard Worker            redirect.fset = found_descriptor.fset
334*cda5da8dSAndroid Build Coastguard Worker            redirect.fdel = found_descriptor.fdel
335*cda5da8dSAndroid Build Coastguard Worker            setattr(enum_class, member_name, redirect)
336*cda5da8dSAndroid Build Coastguard Worker        else:
337*cda5da8dSAndroid Build Coastguard Worker            setattr(enum_class, member_name, enum_member)
338*cda5da8dSAndroid Build Coastguard Worker        # now add to _member_map_ (even aliases)
339*cda5da8dSAndroid Build Coastguard Worker        enum_class._member_map_[member_name] = enum_member
340*cda5da8dSAndroid Build Coastguard Worker        try:
341*cda5da8dSAndroid Build Coastguard Worker            # This may fail if value is not hashable. We can't add the value
342*cda5da8dSAndroid Build Coastguard Worker            # to the map, and by-value lookups for this value will be
343*cda5da8dSAndroid Build Coastguard Worker            # linear.
344*cda5da8dSAndroid Build Coastguard Worker            enum_class._value2member_map_.setdefault(value, enum_member)
345*cda5da8dSAndroid Build Coastguard Worker        except TypeError:
346*cda5da8dSAndroid Build Coastguard Worker            # keep track of the value in a list so containment checks are quick
347*cda5da8dSAndroid Build Coastguard Worker            enum_class._unhashable_values_.append(value)
348*cda5da8dSAndroid Build Coastguard Worker
349*cda5da8dSAndroid Build Coastguard Worker
350*cda5da8dSAndroid Build Coastguard Workerclass _EnumDict(dict):
351*cda5da8dSAndroid Build Coastguard Worker    """
352*cda5da8dSAndroid Build Coastguard Worker    Track enum member order and ensure member names are not reused.
353*cda5da8dSAndroid Build Coastguard Worker
354*cda5da8dSAndroid Build Coastguard Worker    EnumType will use the names found in self._member_names as the
355*cda5da8dSAndroid Build Coastguard Worker    enumeration member names.
356*cda5da8dSAndroid Build Coastguard Worker    """
357*cda5da8dSAndroid Build Coastguard Worker    def __init__(self):
358*cda5da8dSAndroid Build Coastguard Worker        super().__init__()
359*cda5da8dSAndroid Build Coastguard Worker        self._member_names = {} # use a dict to keep insertion order
360*cda5da8dSAndroid Build Coastguard Worker        self._last_values = []
361*cda5da8dSAndroid Build Coastguard Worker        self._ignore = []
362*cda5da8dSAndroid Build Coastguard Worker        self._auto_called = False
363*cda5da8dSAndroid Build Coastguard Worker
364*cda5da8dSAndroid Build Coastguard Worker    def __setitem__(self, key, value):
365*cda5da8dSAndroid Build Coastguard Worker        """
366*cda5da8dSAndroid Build Coastguard Worker        Changes anything not dundered or not a descriptor.
367*cda5da8dSAndroid Build Coastguard Worker
368*cda5da8dSAndroid Build Coastguard Worker        If an enum member name is used twice, an error is raised; duplicate
369*cda5da8dSAndroid Build Coastguard Worker        values are not checked for.
370*cda5da8dSAndroid Build Coastguard Worker
371*cda5da8dSAndroid Build Coastguard Worker        Single underscore (sunder) names are reserved.
372*cda5da8dSAndroid Build Coastguard Worker        """
373*cda5da8dSAndroid Build Coastguard Worker        if _is_internal_class(self._cls_name, value):
374*cda5da8dSAndroid Build Coastguard Worker            import warnings
375*cda5da8dSAndroid Build Coastguard Worker            warnings.warn(
376*cda5da8dSAndroid Build Coastguard Worker                    "In 3.13 classes created inside an enum will not become a member.  "
377*cda5da8dSAndroid Build Coastguard Worker                    "Use the `member` decorator to keep the current behavior.",
378*cda5da8dSAndroid Build Coastguard Worker                    DeprecationWarning,
379*cda5da8dSAndroid Build Coastguard Worker                    stacklevel=2,
380*cda5da8dSAndroid Build Coastguard Worker                    )
381*cda5da8dSAndroid Build Coastguard Worker        if _is_private(self._cls_name, key):
382*cda5da8dSAndroid Build Coastguard Worker            # also do nothing, name will be a normal attribute
383*cda5da8dSAndroid Build Coastguard Worker            pass
384*cda5da8dSAndroid Build Coastguard Worker        elif _is_sunder(key):
385*cda5da8dSAndroid Build Coastguard Worker            if key not in (
386*cda5da8dSAndroid Build Coastguard Worker                    '_order_',
387*cda5da8dSAndroid Build Coastguard Worker                    '_generate_next_value_', '_numeric_repr_', '_missing_', '_ignore_',
388*cda5da8dSAndroid Build Coastguard Worker                    '_iter_member_', '_iter_member_by_value_', '_iter_member_by_def_',
389*cda5da8dSAndroid Build Coastguard Worker                    ):
390*cda5da8dSAndroid Build Coastguard Worker                raise ValueError(
391*cda5da8dSAndroid Build Coastguard Worker                        '_sunder_ names, such as %r, are reserved for future Enum use'
392*cda5da8dSAndroid Build Coastguard Worker                        % (key, )
393*cda5da8dSAndroid Build Coastguard Worker                        )
394*cda5da8dSAndroid Build Coastguard Worker            if key == '_generate_next_value_':
395*cda5da8dSAndroid Build Coastguard Worker                # check if members already defined as auto()
396*cda5da8dSAndroid Build Coastguard Worker                if self._auto_called:
397*cda5da8dSAndroid Build Coastguard Worker                    raise TypeError("_generate_next_value_ must be defined before members")
398*cda5da8dSAndroid Build Coastguard Worker                _gnv = value.__func__ if isinstance(value, staticmethod) else value
399*cda5da8dSAndroid Build Coastguard Worker                setattr(self, '_generate_next_value', _gnv)
400*cda5da8dSAndroid Build Coastguard Worker            elif key == '_ignore_':
401*cda5da8dSAndroid Build Coastguard Worker                if isinstance(value, str):
402*cda5da8dSAndroid Build Coastguard Worker                    value = value.replace(',',' ').split()
403*cda5da8dSAndroid Build Coastguard Worker                else:
404*cda5da8dSAndroid Build Coastguard Worker                    value = list(value)
405*cda5da8dSAndroid Build Coastguard Worker                self._ignore = value
406*cda5da8dSAndroid Build Coastguard Worker                already = set(value) & set(self._member_names)
407*cda5da8dSAndroid Build Coastguard Worker                if already:
408*cda5da8dSAndroid Build Coastguard Worker                    raise ValueError(
409*cda5da8dSAndroid Build Coastguard Worker                            '_ignore_ cannot specify already set names: %r'
410*cda5da8dSAndroid Build Coastguard Worker                            % (already, )
411*cda5da8dSAndroid Build Coastguard Worker                            )
412*cda5da8dSAndroid Build Coastguard Worker        elif _is_dunder(key):
413*cda5da8dSAndroid Build Coastguard Worker            if key == '__order__':
414*cda5da8dSAndroid Build Coastguard Worker                key = '_order_'
415*cda5da8dSAndroid Build Coastguard Worker        elif key in self._member_names:
416*cda5da8dSAndroid Build Coastguard Worker            # descriptor overwriting an enum?
417*cda5da8dSAndroid Build Coastguard Worker            raise TypeError('%r already defined as %r' % (key, self[key]))
418*cda5da8dSAndroid Build Coastguard Worker        elif key in self._ignore:
419*cda5da8dSAndroid Build Coastguard Worker            pass
420*cda5da8dSAndroid Build Coastguard Worker        elif isinstance(value, nonmember):
421*cda5da8dSAndroid Build Coastguard Worker            # unwrap value here; it won't be processed by the below `else`
422*cda5da8dSAndroid Build Coastguard Worker            value = value.value
423*cda5da8dSAndroid Build Coastguard Worker        elif _is_descriptor(value):
424*cda5da8dSAndroid Build Coastguard Worker            pass
425*cda5da8dSAndroid Build Coastguard Worker        # TODO: uncomment next three lines in 3.13
426*cda5da8dSAndroid Build Coastguard Worker        # elif _is_internal_class(self._cls_name, value):
427*cda5da8dSAndroid Build Coastguard Worker        #     # do nothing, name will be a normal attribute
428*cda5da8dSAndroid Build Coastguard Worker        #     pass
429*cda5da8dSAndroid Build Coastguard Worker        else:
430*cda5da8dSAndroid Build Coastguard Worker            if key in self:
431*cda5da8dSAndroid Build Coastguard Worker                # enum overwriting a descriptor?
432*cda5da8dSAndroid Build Coastguard Worker                raise TypeError('%r already defined as %r' % (key, self[key]))
433*cda5da8dSAndroid Build Coastguard Worker            elif isinstance(value, member):
434*cda5da8dSAndroid Build Coastguard Worker                # unwrap value here -- it will become a member
435*cda5da8dSAndroid Build Coastguard Worker                value = value.value
436*cda5da8dSAndroid Build Coastguard Worker            non_auto_store = True
437*cda5da8dSAndroid Build Coastguard Worker            single = False
438*cda5da8dSAndroid Build Coastguard Worker            if isinstance(value, auto):
439*cda5da8dSAndroid Build Coastguard Worker                single = True
440*cda5da8dSAndroid Build Coastguard Worker                value = (value, )
441*cda5da8dSAndroid Build Coastguard Worker            if type(value) is tuple and any(isinstance(v, auto) for v in value):
442*cda5da8dSAndroid Build Coastguard Worker                # insist on an actual tuple, no subclasses, in keeping with only supporting
443*cda5da8dSAndroid Build Coastguard Worker                # top-level auto() usage (not contained in any other data structure)
444*cda5da8dSAndroid Build Coastguard Worker                auto_valued = []
445*cda5da8dSAndroid Build Coastguard Worker                for v in value:
446*cda5da8dSAndroid Build Coastguard Worker                    if isinstance(v, auto):
447*cda5da8dSAndroid Build Coastguard Worker                        non_auto_store = False
448*cda5da8dSAndroid Build Coastguard Worker                        if v.value == _auto_null:
449*cda5da8dSAndroid Build Coastguard Worker                            v.value = self._generate_next_value(
450*cda5da8dSAndroid Build Coastguard Worker                                    key, 1, len(self._member_names), self._last_values[:],
451*cda5da8dSAndroid Build Coastguard Worker                                    )
452*cda5da8dSAndroid Build Coastguard Worker                            self._auto_called = True
453*cda5da8dSAndroid Build Coastguard Worker                        v = v.value
454*cda5da8dSAndroid Build Coastguard Worker                        self._last_values.append(v)
455*cda5da8dSAndroid Build Coastguard Worker                    auto_valued.append(v)
456*cda5da8dSAndroid Build Coastguard Worker                if single:
457*cda5da8dSAndroid Build Coastguard Worker                    value = auto_valued[0]
458*cda5da8dSAndroid Build Coastguard Worker                else:
459*cda5da8dSAndroid Build Coastguard Worker                    value = tuple(auto_valued)
460*cda5da8dSAndroid Build Coastguard Worker            self._member_names[key] = None
461*cda5da8dSAndroid Build Coastguard Worker            if non_auto_store:
462*cda5da8dSAndroid Build Coastguard Worker                self._last_values.append(value)
463*cda5da8dSAndroid Build Coastguard Worker        super().__setitem__(key, value)
464*cda5da8dSAndroid Build Coastguard Worker
465*cda5da8dSAndroid Build Coastguard Worker    def update(self, members, **more_members):
466*cda5da8dSAndroid Build Coastguard Worker        try:
467*cda5da8dSAndroid Build Coastguard Worker            for name in members.keys():
468*cda5da8dSAndroid Build Coastguard Worker                self[name] = members[name]
469*cda5da8dSAndroid Build Coastguard Worker        except AttributeError:
470*cda5da8dSAndroid Build Coastguard Worker            for name, value in members:
471*cda5da8dSAndroid Build Coastguard Worker                self[name] = value
472*cda5da8dSAndroid Build Coastguard Worker        for name, value in more_members.items():
473*cda5da8dSAndroid Build Coastguard Worker            self[name] = value
474*cda5da8dSAndroid Build Coastguard Worker
475*cda5da8dSAndroid Build Coastguard Worker
476*cda5da8dSAndroid Build Coastguard Workerclass EnumType(type):
477*cda5da8dSAndroid Build Coastguard Worker    """
478*cda5da8dSAndroid Build Coastguard Worker    Metaclass for Enum
479*cda5da8dSAndroid Build Coastguard Worker    """
480*cda5da8dSAndroid Build Coastguard Worker
481*cda5da8dSAndroid Build Coastguard Worker    @classmethod
482*cda5da8dSAndroid Build Coastguard Worker    def __prepare__(metacls, cls, bases, **kwds):
483*cda5da8dSAndroid Build Coastguard Worker        # check that previous enum members do not exist
484*cda5da8dSAndroid Build Coastguard Worker        metacls._check_for_existing_members_(cls, bases)
485*cda5da8dSAndroid Build Coastguard Worker        # create the namespace dict
486*cda5da8dSAndroid Build Coastguard Worker        enum_dict = _EnumDict()
487*cda5da8dSAndroid Build Coastguard Worker        enum_dict._cls_name = cls
488*cda5da8dSAndroid Build Coastguard Worker        # inherit previous flags and _generate_next_value_ function
489*cda5da8dSAndroid Build Coastguard Worker        member_type, first_enum = metacls._get_mixins_(cls, bases)
490*cda5da8dSAndroid Build Coastguard Worker        if first_enum is not None:
491*cda5da8dSAndroid Build Coastguard Worker            enum_dict['_generate_next_value_'] = getattr(
492*cda5da8dSAndroid Build Coastguard Worker                    first_enum, '_generate_next_value_', None,
493*cda5da8dSAndroid Build Coastguard Worker                    )
494*cda5da8dSAndroid Build Coastguard Worker        return enum_dict
495*cda5da8dSAndroid Build Coastguard Worker
496*cda5da8dSAndroid Build Coastguard Worker    def __new__(metacls, cls, bases, classdict, *, boundary=None, _simple=False, **kwds):
497*cda5da8dSAndroid Build Coastguard Worker        # an Enum class is final once enumeration items have been defined; it
498*cda5da8dSAndroid Build Coastguard Worker        # cannot be mixed with other types (int, float, etc.) if it has an
499*cda5da8dSAndroid Build Coastguard Worker        # inherited __new__ unless a new __new__ is defined (or the resulting
500*cda5da8dSAndroid Build Coastguard Worker        # class will fail).
501*cda5da8dSAndroid Build Coastguard Worker        #
502*cda5da8dSAndroid Build Coastguard Worker        if _simple:
503*cda5da8dSAndroid Build Coastguard Worker            return super().__new__(metacls, cls, bases, classdict, **kwds)
504*cda5da8dSAndroid Build Coastguard Worker        #
505*cda5da8dSAndroid Build Coastguard Worker        # remove any keys listed in _ignore_
506*cda5da8dSAndroid Build Coastguard Worker        classdict.setdefault('_ignore_', []).append('_ignore_')
507*cda5da8dSAndroid Build Coastguard Worker        ignore = classdict['_ignore_']
508*cda5da8dSAndroid Build Coastguard Worker        for key in ignore:
509*cda5da8dSAndroid Build Coastguard Worker            classdict.pop(key, None)
510*cda5da8dSAndroid Build Coastguard Worker        #
511*cda5da8dSAndroid Build Coastguard Worker        # grab member names
512*cda5da8dSAndroid Build Coastguard Worker        member_names = classdict._member_names
513*cda5da8dSAndroid Build Coastguard Worker        #
514*cda5da8dSAndroid Build Coastguard Worker        # check for illegal enum names (any others?)
515*cda5da8dSAndroid Build Coastguard Worker        invalid_names = set(member_names) & {'mro', ''}
516*cda5da8dSAndroid Build Coastguard Worker        if invalid_names:
517*cda5da8dSAndroid Build Coastguard Worker            raise ValueError('invalid enum member name(s) %s'  % (
518*cda5da8dSAndroid Build Coastguard Worker                    ','.join(repr(n) for n in invalid_names)
519*cda5da8dSAndroid Build Coastguard Worker                    ))
520*cda5da8dSAndroid Build Coastguard Worker        #
521*cda5da8dSAndroid Build Coastguard Worker        # adjust the sunders
522*cda5da8dSAndroid Build Coastguard Worker        _order_ = classdict.pop('_order_', None)
523*cda5da8dSAndroid Build Coastguard Worker        # convert to normal dict
524*cda5da8dSAndroid Build Coastguard Worker        classdict = dict(classdict.items())
525*cda5da8dSAndroid Build Coastguard Worker        #
526*cda5da8dSAndroid Build Coastguard Worker        # data type of member and the controlling Enum class
527*cda5da8dSAndroid Build Coastguard Worker        member_type, first_enum = metacls._get_mixins_(cls, bases)
528*cda5da8dSAndroid Build Coastguard Worker        __new__, save_new, use_args = metacls._find_new_(
529*cda5da8dSAndroid Build Coastguard Worker                classdict, member_type, first_enum,
530*cda5da8dSAndroid Build Coastguard Worker                )
531*cda5da8dSAndroid Build Coastguard Worker        classdict['_new_member_'] = __new__
532*cda5da8dSAndroid Build Coastguard Worker        classdict['_use_args_'] = use_args
533*cda5da8dSAndroid Build Coastguard Worker        #
534*cda5da8dSAndroid Build Coastguard Worker        # convert future enum members into temporary _proto_members
535*cda5da8dSAndroid Build Coastguard Worker        for name in member_names:
536*cda5da8dSAndroid Build Coastguard Worker            value = classdict[name]
537*cda5da8dSAndroid Build Coastguard Worker            classdict[name] = _proto_member(value)
538*cda5da8dSAndroid Build Coastguard Worker        #
539*cda5da8dSAndroid Build Coastguard Worker        # house-keeping structures
540*cda5da8dSAndroid Build Coastguard Worker        classdict['_member_names_'] = []
541*cda5da8dSAndroid Build Coastguard Worker        classdict['_member_map_'] = {}
542*cda5da8dSAndroid Build Coastguard Worker        classdict['_value2member_map_'] = {}
543*cda5da8dSAndroid Build Coastguard Worker        classdict['_unhashable_values_'] = []
544*cda5da8dSAndroid Build Coastguard Worker        classdict['_member_type_'] = member_type
545*cda5da8dSAndroid Build Coastguard Worker        # now set the __repr__ for the value
546*cda5da8dSAndroid Build Coastguard Worker        classdict['_value_repr_'] = metacls._find_data_repr_(cls, bases)
547*cda5da8dSAndroid Build Coastguard Worker        #
548*cda5da8dSAndroid Build Coastguard Worker        # Flag structures (will be removed if final class is not a Flag
549*cda5da8dSAndroid Build Coastguard Worker        classdict['_boundary_'] = (
550*cda5da8dSAndroid Build Coastguard Worker                boundary
551*cda5da8dSAndroid Build Coastguard Worker                or getattr(first_enum, '_boundary_', None)
552*cda5da8dSAndroid Build Coastguard Worker                )
553*cda5da8dSAndroid Build Coastguard Worker        classdict['_flag_mask_'] = 0
554*cda5da8dSAndroid Build Coastguard Worker        classdict['_singles_mask_'] = 0
555*cda5da8dSAndroid Build Coastguard Worker        classdict['_all_bits_'] = 0
556*cda5da8dSAndroid Build Coastguard Worker        classdict['_inverted_'] = None
557*cda5da8dSAndroid Build Coastguard Worker        try:
558*cda5da8dSAndroid Build Coastguard Worker            exc = None
559*cda5da8dSAndroid Build Coastguard Worker            enum_class = super().__new__(metacls, cls, bases, classdict, **kwds)
560*cda5da8dSAndroid Build Coastguard Worker        except RuntimeError as e:
561*cda5da8dSAndroid Build Coastguard Worker            # any exceptions raised by member.__new__ will get converted to a
562*cda5da8dSAndroid Build Coastguard Worker            # RuntimeError, so get that original exception back and raise it instead
563*cda5da8dSAndroid Build Coastguard Worker            exc = e.__cause__ or e
564*cda5da8dSAndroid Build Coastguard Worker        if exc is not None:
565*cda5da8dSAndroid Build Coastguard Worker            raise exc
566*cda5da8dSAndroid Build Coastguard Worker        #
567*cda5da8dSAndroid Build Coastguard Worker        # update classdict with any changes made by __init_subclass__
568*cda5da8dSAndroid Build Coastguard Worker        classdict.update(enum_class.__dict__)
569*cda5da8dSAndroid Build Coastguard Worker        #
570*cda5da8dSAndroid Build Coastguard Worker        # double check that repr and friends are not the mixin's or various
571*cda5da8dSAndroid Build Coastguard Worker        # things break (such as pickle)
572*cda5da8dSAndroid Build Coastguard Worker        # however, if the method is defined in the Enum itself, don't replace
573*cda5da8dSAndroid Build Coastguard Worker        # it
574*cda5da8dSAndroid Build Coastguard Worker        #
575*cda5da8dSAndroid Build Coastguard Worker        # Also, special handling for ReprEnum
576*cda5da8dSAndroid Build Coastguard Worker        if ReprEnum is not None and ReprEnum in bases:
577*cda5da8dSAndroid Build Coastguard Worker            if member_type is object:
578*cda5da8dSAndroid Build Coastguard Worker                raise TypeError(
579*cda5da8dSAndroid Build Coastguard Worker                        'ReprEnum subclasses must be mixed with a data type (i.e.'
580*cda5da8dSAndroid Build Coastguard Worker                        ' int, str, float, etc.)'
581*cda5da8dSAndroid Build Coastguard Worker                        )
582*cda5da8dSAndroid Build Coastguard Worker            if '__format__' not in classdict:
583*cda5da8dSAndroid Build Coastguard Worker                enum_class.__format__ = member_type.__format__
584*cda5da8dSAndroid Build Coastguard Worker                classdict['__format__'] = enum_class.__format__
585*cda5da8dSAndroid Build Coastguard Worker            if '__str__' not in classdict:
586*cda5da8dSAndroid Build Coastguard Worker                method = member_type.__str__
587*cda5da8dSAndroid Build Coastguard Worker                if method is object.__str__:
588*cda5da8dSAndroid Build Coastguard Worker                    # if member_type does not define __str__, object.__str__ will use
589*cda5da8dSAndroid Build Coastguard Worker                    # its __repr__ instead, so we'll also use its __repr__
590*cda5da8dSAndroid Build Coastguard Worker                    method = member_type.__repr__
591*cda5da8dSAndroid Build Coastguard Worker                enum_class.__str__ = method
592*cda5da8dSAndroid Build Coastguard Worker                classdict['__str__'] = enum_class.__str__
593*cda5da8dSAndroid Build Coastguard Worker        for name in ('__repr__', '__str__', '__format__', '__reduce_ex__'):
594*cda5da8dSAndroid Build Coastguard Worker            if name not in classdict:
595*cda5da8dSAndroid Build Coastguard Worker                # check for mixin overrides before replacing
596*cda5da8dSAndroid Build Coastguard Worker                enum_method = getattr(first_enum, name)
597*cda5da8dSAndroid Build Coastguard Worker                found_method = getattr(enum_class, name)
598*cda5da8dSAndroid Build Coastguard Worker                object_method = getattr(object, name)
599*cda5da8dSAndroid Build Coastguard Worker                data_type_method = getattr(member_type, name)
600*cda5da8dSAndroid Build Coastguard Worker                if found_method in (data_type_method, object_method):
601*cda5da8dSAndroid Build Coastguard Worker                    setattr(enum_class, name, enum_method)
602*cda5da8dSAndroid Build Coastguard Worker        #
603*cda5da8dSAndroid Build Coastguard Worker        # for Flag, add __or__, __and__, __xor__, and __invert__
604*cda5da8dSAndroid Build Coastguard Worker        if Flag is not None and issubclass(enum_class, Flag):
605*cda5da8dSAndroid Build Coastguard Worker            for name in (
606*cda5da8dSAndroid Build Coastguard Worker                    '__or__', '__and__', '__xor__',
607*cda5da8dSAndroid Build Coastguard Worker                    '__ror__', '__rand__', '__rxor__',
608*cda5da8dSAndroid Build Coastguard Worker                    '__invert__'
609*cda5da8dSAndroid Build Coastguard Worker                ):
610*cda5da8dSAndroid Build Coastguard Worker                if name not in classdict:
611*cda5da8dSAndroid Build Coastguard Worker                    enum_method = getattr(Flag, name)
612*cda5da8dSAndroid Build Coastguard Worker                    setattr(enum_class, name, enum_method)
613*cda5da8dSAndroid Build Coastguard Worker                    classdict[name] = enum_method
614*cda5da8dSAndroid Build Coastguard Worker        #
615*cda5da8dSAndroid Build Coastguard Worker        # replace any other __new__ with our own (as long as Enum is not None,
616*cda5da8dSAndroid Build Coastguard Worker        # anyway) -- again, this is to support pickle
617*cda5da8dSAndroid Build Coastguard Worker        if Enum is not None:
618*cda5da8dSAndroid Build Coastguard Worker            # if the user defined their own __new__, save it before it gets
619*cda5da8dSAndroid Build Coastguard Worker            # clobbered in case they subclass later
620*cda5da8dSAndroid Build Coastguard Worker            if save_new:
621*cda5da8dSAndroid Build Coastguard Worker                enum_class.__new_member__ = __new__
622*cda5da8dSAndroid Build Coastguard Worker            enum_class.__new__ = Enum.__new__
623*cda5da8dSAndroid Build Coastguard Worker        #
624*cda5da8dSAndroid Build Coastguard Worker        # py3 support for definition order (helps keep py2/py3 code in sync)
625*cda5da8dSAndroid Build Coastguard Worker        #
626*cda5da8dSAndroid Build Coastguard Worker        # _order_ checking is spread out into three/four steps
627*cda5da8dSAndroid Build Coastguard Worker        # - if enum_class is a Flag:
628*cda5da8dSAndroid Build Coastguard Worker        #   - remove any non-single-bit flags from _order_
629*cda5da8dSAndroid Build Coastguard Worker        # - remove any aliases from _order_
630*cda5da8dSAndroid Build Coastguard Worker        # - check that _order_ and _member_names_ match
631*cda5da8dSAndroid Build Coastguard Worker        #
632*cda5da8dSAndroid Build Coastguard Worker        # step 1: ensure we have a list
633*cda5da8dSAndroid Build Coastguard Worker        if _order_ is not None:
634*cda5da8dSAndroid Build Coastguard Worker            if isinstance(_order_, str):
635*cda5da8dSAndroid Build Coastguard Worker                _order_ = _order_.replace(',', ' ').split()
636*cda5da8dSAndroid Build Coastguard Worker        #
637*cda5da8dSAndroid Build Coastguard Worker        # remove Flag structures if final class is not a Flag
638*cda5da8dSAndroid Build Coastguard Worker        if (
639*cda5da8dSAndroid Build Coastguard Worker                Flag is None and cls != 'Flag'
640*cda5da8dSAndroid Build Coastguard Worker                or Flag is not None and not issubclass(enum_class, Flag)
641*cda5da8dSAndroid Build Coastguard Worker            ):
642*cda5da8dSAndroid Build Coastguard Worker            delattr(enum_class, '_boundary_')
643*cda5da8dSAndroid Build Coastguard Worker            delattr(enum_class, '_flag_mask_')
644*cda5da8dSAndroid Build Coastguard Worker            delattr(enum_class, '_singles_mask_')
645*cda5da8dSAndroid Build Coastguard Worker            delattr(enum_class, '_all_bits_')
646*cda5da8dSAndroid Build Coastguard Worker            delattr(enum_class, '_inverted_')
647*cda5da8dSAndroid Build Coastguard Worker        elif Flag is not None and issubclass(enum_class, Flag):
648*cda5da8dSAndroid Build Coastguard Worker            # set correct __iter__
649*cda5da8dSAndroid Build Coastguard Worker            member_list = [m._value_ for m in enum_class]
650*cda5da8dSAndroid Build Coastguard Worker            if member_list != sorted(member_list):
651*cda5da8dSAndroid Build Coastguard Worker                enum_class._iter_member_ = enum_class._iter_member_by_def_
652*cda5da8dSAndroid Build Coastguard Worker            if _order_:
653*cda5da8dSAndroid Build Coastguard Worker                # _order_ step 2: remove any items from _order_ that are not single-bit
654*cda5da8dSAndroid Build Coastguard Worker                _order_ = [
655*cda5da8dSAndroid Build Coastguard Worker                        o
656*cda5da8dSAndroid Build Coastguard Worker                        for o in _order_
657*cda5da8dSAndroid Build Coastguard Worker                        if o not in enum_class._member_map_ or _is_single_bit(enum_class[o]._value_)
658*cda5da8dSAndroid Build Coastguard Worker                        ]
659*cda5da8dSAndroid Build Coastguard Worker        #
660*cda5da8dSAndroid Build Coastguard Worker        if _order_:
661*cda5da8dSAndroid Build Coastguard Worker            # _order_ step 3: remove aliases from _order_
662*cda5da8dSAndroid Build Coastguard Worker            _order_ = [
663*cda5da8dSAndroid Build Coastguard Worker                    o
664*cda5da8dSAndroid Build Coastguard Worker                    for o in _order_
665*cda5da8dSAndroid Build Coastguard Worker                    if (
666*cda5da8dSAndroid Build Coastguard Worker                        o not in enum_class._member_map_
667*cda5da8dSAndroid Build Coastguard Worker                        or
668*cda5da8dSAndroid Build Coastguard Worker                        (o in enum_class._member_map_ and o in enum_class._member_names_)
669*cda5da8dSAndroid Build Coastguard Worker                        )]
670*cda5da8dSAndroid Build Coastguard Worker            # _order_ step 4: verify that _order_ and _member_names_ match
671*cda5da8dSAndroid Build Coastguard Worker            if _order_ != enum_class._member_names_:
672*cda5da8dSAndroid Build Coastguard Worker                raise TypeError(
673*cda5da8dSAndroid Build Coastguard Worker                        'member order does not match _order_:\n  %r\n  %r'
674*cda5da8dSAndroid Build Coastguard Worker                        % (enum_class._member_names_, _order_)
675*cda5da8dSAndroid Build Coastguard Worker                        )
676*cda5da8dSAndroid Build Coastguard Worker
677*cda5da8dSAndroid Build Coastguard Worker        return enum_class
678*cda5da8dSAndroid Build Coastguard Worker
679*cda5da8dSAndroid Build Coastguard Worker    def __bool__(cls):
680*cda5da8dSAndroid Build Coastguard Worker        """
681*cda5da8dSAndroid Build Coastguard Worker        classes/types should always be True.
682*cda5da8dSAndroid Build Coastguard Worker        """
683*cda5da8dSAndroid Build Coastguard Worker        return True
684*cda5da8dSAndroid Build Coastguard Worker
685*cda5da8dSAndroid Build Coastguard Worker    def __call__(cls, value, names=None, *, module=None, qualname=None, type=None, start=1, boundary=None):
686*cda5da8dSAndroid Build Coastguard Worker        """
687*cda5da8dSAndroid Build Coastguard Worker        Either returns an existing member, or creates a new enum class.
688*cda5da8dSAndroid Build Coastguard Worker
689*cda5da8dSAndroid Build Coastguard Worker        This method is used both when an enum class is given a value to match
690*cda5da8dSAndroid Build Coastguard Worker        to an enumeration member (i.e. Color(3)) and for the functional API
691*cda5da8dSAndroid Build Coastguard Worker        (i.e. Color = Enum('Color', names='RED GREEN BLUE')).
692*cda5da8dSAndroid Build Coastguard Worker
693*cda5da8dSAndroid Build Coastguard Worker        When used for the functional API:
694*cda5da8dSAndroid Build Coastguard Worker
695*cda5da8dSAndroid Build Coastguard Worker        `value` will be the name of the new class.
696*cda5da8dSAndroid Build Coastguard Worker
697*cda5da8dSAndroid Build Coastguard Worker        `names` should be either a string of white-space/comma delimited names
698*cda5da8dSAndroid Build Coastguard Worker        (values will start at `start`), or an iterator/mapping of name, value pairs.
699*cda5da8dSAndroid Build Coastguard Worker
700*cda5da8dSAndroid Build Coastguard Worker        `module` should be set to the module this class is being created in;
701*cda5da8dSAndroid Build Coastguard Worker        if it is not set, an attempt to find that module will be made, but if
702*cda5da8dSAndroid Build Coastguard Worker        it fails the class will not be picklable.
703*cda5da8dSAndroid Build Coastguard Worker
704*cda5da8dSAndroid Build Coastguard Worker        `qualname` should be set to the actual location this class can be found
705*cda5da8dSAndroid Build Coastguard Worker        at in its module; by default it is set to the global scope.  If this is
706*cda5da8dSAndroid Build Coastguard Worker        not correct, unpickling will fail in some circumstances.
707*cda5da8dSAndroid Build Coastguard Worker
708*cda5da8dSAndroid Build Coastguard Worker        `type`, if set, will be mixed in as the first base class.
709*cda5da8dSAndroid Build Coastguard Worker        """
710*cda5da8dSAndroid Build Coastguard Worker        if names is None:  # simple value lookup
711*cda5da8dSAndroid Build Coastguard Worker            return cls.__new__(cls, value)
712*cda5da8dSAndroid Build Coastguard Worker        # otherwise, functional API: we're creating a new Enum type
713*cda5da8dSAndroid Build Coastguard Worker        return cls._create_(
714*cda5da8dSAndroid Build Coastguard Worker                value,
715*cda5da8dSAndroid Build Coastguard Worker                names,
716*cda5da8dSAndroid Build Coastguard Worker                module=module,
717*cda5da8dSAndroid Build Coastguard Worker                qualname=qualname,
718*cda5da8dSAndroid Build Coastguard Worker                type=type,
719*cda5da8dSAndroid Build Coastguard Worker                start=start,
720*cda5da8dSAndroid Build Coastguard Worker                boundary=boundary,
721*cda5da8dSAndroid Build Coastguard Worker                )
722*cda5da8dSAndroid Build Coastguard Worker
723*cda5da8dSAndroid Build Coastguard Worker    def __contains__(cls, member):
724*cda5da8dSAndroid Build Coastguard Worker        """
725*cda5da8dSAndroid Build Coastguard Worker        Return True if member is a member of this enum
726*cda5da8dSAndroid Build Coastguard Worker        raises TypeError if member is not an enum member
727*cda5da8dSAndroid Build Coastguard Worker
728*cda5da8dSAndroid Build Coastguard Worker        note: in 3.12 TypeError will no longer be raised, and True will also be
729*cda5da8dSAndroid Build Coastguard Worker        returned if member is the value of a member in this enum
730*cda5da8dSAndroid Build Coastguard Worker        """
731*cda5da8dSAndroid Build Coastguard Worker        if not isinstance(member, Enum):
732*cda5da8dSAndroid Build Coastguard Worker            import warnings
733*cda5da8dSAndroid Build Coastguard Worker            warnings.warn(
734*cda5da8dSAndroid Build Coastguard Worker                    "in 3.12 __contains__ will no longer raise TypeError, but will return True or\n"
735*cda5da8dSAndroid Build Coastguard Worker                    "False depending on whether the value is a member or the value of a member",
736*cda5da8dSAndroid Build Coastguard Worker                    DeprecationWarning,
737*cda5da8dSAndroid Build Coastguard Worker                    stacklevel=2,
738*cda5da8dSAndroid Build Coastguard Worker                    )
739*cda5da8dSAndroid Build Coastguard Worker            raise TypeError(
740*cda5da8dSAndroid Build Coastguard Worker                "unsupported operand type(s) for 'in': '%s' and '%s'" % (
741*cda5da8dSAndroid Build Coastguard Worker                    type(member).__qualname__, cls.__class__.__qualname__))
742*cda5da8dSAndroid Build Coastguard Worker        return isinstance(member, cls) and member._name_ in cls._member_map_
743*cda5da8dSAndroid Build Coastguard Worker
744*cda5da8dSAndroid Build Coastguard Worker    def __delattr__(cls, attr):
745*cda5da8dSAndroid Build Coastguard Worker        # nicer error message when someone tries to delete an attribute
746*cda5da8dSAndroid Build Coastguard Worker        # (see issue19025).
747*cda5da8dSAndroid Build Coastguard Worker        if attr in cls._member_map_:
748*cda5da8dSAndroid Build Coastguard Worker            raise AttributeError("%r cannot delete member %r." % (cls.__name__, attr))
749*cda5da8dSAndroid Build Coastguard Worker        super().__delattr__(attr)
750*cda5da8dSAndroid Build Coastguard Worker
751*cda5da8dSAndroid Build Coastguard Worker    def __dir__(cls):
752*cda5da8dSAndroid Build Coastguard Worker        interesting = set([
753*cda5da8dSAndroid Build Coastguard Worker                '__class__', '__contains__', '__doc__', '__getitem__',
754*cda5da8dSAndroid Build Coastguard Worker                '__iter__', '__len__', '__members__', '__module__',
755*cda5da8dSAndroid Build Coastguard Worker                '__name__', '__qualname__',
756*cda5da8dSAndroid Build Coastguard Worker                ]
757*cda5da8dSAndroid Build Coastguard Worker                + cls._member_names_
758*cda5da8dSAndroid Build Coastguard Worker                )
759*cda5da8dSAndroid Build Coastguard Worker        if cls._new_member_ is not object.__new__:
760*cda5da8dSAndroid Build Coastguard Worker            interesting.add('__new__')
761*cda5da8dSAndroid Build Coastguard Worker        if cls.__init_subclass__ is not object.__init_subclass__:
762*cda5da8dSAndroid Build Coastguard Worker            interesting.add('__init_subclass__')
763*cda5da8dSAndroid Build Coastguard Worker        if cls._member_type_ is object:
764*cda5da8dSAndroid Build Coastguard Worker            return sorted(interesting)
765*cda5da8dSAndroid Build Coastguard Worker        else:
766*cda5da8dSAndroid Build Coastguard Worker            # return whatever mixed-in data type has
767*cda5da8dSAndroid Build Coastguard Worker            return sorted(set(dir(cls._member_type_)) | interesting)
768*cda5da8dSAndroid Build Coastguard Worker
769*cda5da8dSAndroid Build Coastguard Worker    def __getattr__(cls, name):
770*cda5da8dSAndroid Build Coastguard Worker        """
771*cda5da8dSAndroid Build Coastguard Worker        Return the enum member matching `name`
772*cda5da8dSAndroid Build Coastguard Worker
773*cda5da8dSAndroid Build Coastguard Worker        We use __getattr__ instead of descriptors or inserting into the enum
774*cda5da8dSAndroid Build Coastguard Worker        class' __dict__ in order to support `name` and `value` being both
775*cda5da8dSAndroid Build Coastguard Worker        properties for enum members (which live in the class' __dict__) and
776*cda5da8dSAndroid Build Coastguard Worker        enum members themselves.
777*cda5da8dSAndroid Build Coastguard Worker        """
778*cda5da8dSAndroid Build Coastguard Worker        if _is_dunder(name):
779*cda5da8dSAndroid Build Coastguard Worker            raise AttributeError(name)
780*cda5da8dSAndroid Build Coastguard Worker        try:
781*cda5da8dSAndroid Build Coastguard Worker            return cls._member_map_[name]
782*cda5da8dSAndroid Build Coastguard Worker        except KeyError:
783*cda5da8dSAndroid Build Coastguard Worker            raise AttributeError(name) from None
784*cda5da8dSAndroid Build Coastguard Worker
785*cda5da8dSAndroid Build Coastguard Worker    def __getitem__(cls, name):
786*cda5da8dSAndroid Build Coastguard Worker        """
787*cda5da8dSAndroid Build Coastguard Worker        Return the member matching `name`.
788*cda5da8dSAndroid Build Coastguard Worker        """
789*cda5da8dSAndroid Build Coastguard Worker        return cls._member_map_[name]
790*cda5da8dSAndroid Build Coastguard Worker
791*cda5da8dSAndroid Build Coastguard Worker    def __iter__(cls):
792*cda5da8dSAndroid Build Coastguard Worker        """
793*cda5da8dSAndroid Build Coastguard Worker        Return members in definition order.
794*cda5da8dSAndroid Build Coastguard Worker        """
795*cda5da8dSAndroid Build Coastguard Worker        return (cls._member_map_[name] for name in cls._member_names_)
796*cda5da8dSAndroid Build Coastguard Worker
797*cda5da8dSAndroid Build Coastguard Worker    def __len__(cls):
798*cda5da8dSAndroid Build Coastguard Worker        """
799*cda5da8dSAndroid Build Coastguard Worker        Return the number of members (no aliases)
800*cda5da8dSAndroid Build Coastguard Worker        """
801*cda5da8dSAndroid Build Coastguard Worker        return len(cls._member_names_)
802*cda5da8dSAndroid Build Coastguard Worker
803*cda5da8dSAndroid Build Coastguard Worker    @bltns.property
804*cda5da8dSAndroid Build Coastguard Worker    def __members__(cls):
805*cda5da8dSAndroid Build Coastguard Worker        """
806*cda5da8dSAndroid Build Coastguard Worker        Returns a mapping of member name->value.
807*cda5da8dSAndroid Build Coastguard Worker
808*cda5da8dSAndroid Build Coastguard Worker        This mapping lists all enum members, including aliases. Note that this
809*cda5da8dSAndroid Build Coastguard Worker        is a read-only view of the internal mapping.
810*cda5da8dSAndroid Build Coastguard Worker        """
811*cda5da8dSAndroid Build Coastguard Worker        return MappingProxyType(cls._member_map_)
812*cda5da8dSAndroid Build Coastguard Worker
813*cda5da8dSAndroid Build Coastguard Worker    def __repr__(cls):
814*cda5da8dSAndroid Build Coastguard Worker        if Flag is not None and issubclass(cls, Flag):
815*cda5da8dSAndroid Build Coastguard Worker            return "<flag %r>" % cls.__name__
816*cda5da8dSAndroid Build Coastguard Worker        else:
817*cda5da8dSAndroid Build Coastguard Worker            return "<enum %r>" % cls.__name__
818*cda5da8dSAndroid Build Coastguard Worker
819*cda5da8dSAndroid Build Coastguard Worker    def __reversed__(cls):
820*cda5da8dSAndroid Build Coastguard Worker        """
821*cda5da8dSAndroid Build Coastguard Worker        Return members in reverse definition order.
822*cda5da8dSAndroid Build Coastguard Worker        """
823*cda5da8dSAndroid Build Coastguard Worker        return (cls._member_map_[name] for name in reversed(cls._member_names_))
824*cda5da8dSAndroid Build Coastguard Worker
825*cda5da8dSAndroid Build Coastguard Worker    def __setattr__(cls, name, value):
826*cda5da8dSAndroid Build Coastguard Worker        """
827*cda5da8dSAndroid Build Coastguard Worker        Block attempts to reassign Enum members.
828*cda5da8dSAndroid Build Coastguard Worker
829*cda5da8dSAndroid Build Coastguard Worker        A simple assignment to the class namespace only changes one of the
830*cda5da8dSAndroid Build Coastguard Worker        several possible ways to get an Enum member from the Enum class,
831*cda5da8dSAndroid Build Coastguard Worker        resulting in an inconsistent Enumeration.
832*cda5da8dSAndroid Build Coastguard Worker        """
833*cda5da8dSAndroid Build Coastguard Worker        member_map = cls.__dict__.get('_member_map_', {})
834*cda5da8dSAndroid Build Coastguard Worker        if name in member_map:
835*cda5da8dSAndroid Build Coastguard Worker            raise AttributeError('cannot reassign member %r' % (name, ))
836*cda5da8dSAndroid Build Coastguard Worker        super().__setattr__(name, value)
837*cda5da8dSAndroid Build Coastguard Worker
838*cda5da8dSAndroid Build Coastguard Worker    def _create_(cls, class_name, names, *, module=None, qualname=None, type=None, start=1, boundary=None):
839*cda5da8dSAndroid Build Coastguard Worker        """
840*cda5da8dSAndroid Build Coastguard Worker        Convenience method to create a new Enum class.
841*cda5da8dSAndroid Build Coastguard Worker
842*cda5da8dSAndroid Build Coastguard Worker        `names` can be:
843*cda5da8dSAndroid Build Coastguard Worker
844*cda5da8dSAndroid Build Coastguard Worker        * A string containing member names, separated either with spaces or
845*cda5da8dSAndroid Build Coastguard Worker          commas.  Values are incremented by 1 from `start`.
846*cda5da8dSAndroid Build Coastguard Worker        * An iterable of member names.  Values are incremented by 1 from `start`.
847*cda5da8dSAndroid Build Coastguard Worker        * An iterable of (member name, value) pairs.
848*cda5da8dSAndroid Build Coastguard Worker        * A mapping of member name -> value pairs.
849*cda5da8dSAndroid Build Coastguard Worker        """
850*cda5da8dSAndroid Build Coastguard Worker        metacls = cls.__class__
851*cda5da8dSAndroid Build Coastguard Worker        bases = (cls, ) if type is None else (type, cls)
852*cda5da8dSAndroid Build Coastguard Worker        _, first_enum = cls._get_mixins_(class_name, bases)
853*cda5da8dSAndroid Build Coastguard Worker        classdict = metacls.__prepare__(class_name, bases)
854*cda5da8dSAndroid Build Coastguard Worker
855*cda5da8dSAndroid Build Coastguard Worker        # special processing needed for names?
856*cda5da8dSAndroid Build Coastguard Worker        if isinstance(names, str):
857*cda5da8dSAndroid Build Coastguard Worker            names = names.replace(',', ' ').split()
858*cda5da8dSAndroid Build Coastguard Worker        if isinstance(names, (tuple, list)) and names and isinstance(names[0], str):
859*cda5da8dSAndroid Build Coastguard Worker            original_names, names = names, []
860*cda5da8dSAndroid Build Coastguard Worker            last_values = []
861*cda5da8dSAndroid Build Coastguard Worker            for count, name in enumerate(original_names):
862*cda5da8dSAndroid Build Coastguard Worker                value = first_enum._generate_next_value_(name, start, count, last_values[:])
863*cda5da8dSAndroid Build Coastguard Worker                last_values.append(value)
864*cda5da8dSAndroid Build Coastguard Worker                names.append((name, value))
865*cda5da8dSAndroid Build Coastguard Worker
866*cda5da8dSAndroid Build Coastguard Worker        # Here, names is either an iterable of (name, value) or a mapping.
867*cda5da8dSAndroid Build Coastguard Worker        for item in names:
868*cda5da8dSAndroid Build Coastguard Worker            if isinstance(item, str):
869*cda5da8dSAndroid Build Coastguard Worker                member_name, member_value = item, names[item]
870*cda5da8dSAndroid Build Coastguard Worker            else:
871*cda5da8dSAndroid Build Coastguard Worker                member_name, member_value = item
872*cda5da8dSAndroid Build Coastguard Worker            classdict[member_name] = member_value
873*cda5da8dSAndroid Build Coastguard Worker
874*cda5da8dSAndroid Build Coastguard Worker        # TODO: replace the frame hack if a blessed way to know the calling
875*cda5da8dSAndroid Build Coastguard Worker        # module is ever developed
876*cda5da8dSAndroid Build Coastguard Worker        if module is None:
877*cda5da8dSAndroid Build Coastguard Worker            try:
878*cda5da8dSAndroid Build Coastguard Worker                module = sys._getframe(2).f_globals['__name__']
879*cda5da8dSAndroid Build Coastguard Worker            except (AttributeError, ValueError, KeyError):
880*cda5da8dSAndroid Build Coastguard Worker                pass
881*cda5da8dSAndroid Build Coastguard Worker        if module is None:
882*cda5da8dSAndroid Build Coastguard Worker            _make_class_unpicklable(classdict)
883*cda5da8dSAndroid Build Coastguard Worker        else:
884*cda5da8dSAndroid Build Coastguard Worker            classdict['__module__'] = module
885*cda5da8dSAndroid Build Coastguard Worker        if qualname is not None:
886*cda5da8dSAndroid Build Coastguard Worker            classdict['__qualname__'] = qualname
887*cda5da8dSAndroid Build Coastguard Worker
888*cda5da8dSAndroid Build Coastguard Worker        return metacls.__new__(metacls, class_name, bases, classdict, boundary=boundary)
889*cda5da8dSAndroid Build Coastguard Worker
890*cda5da8dSAndroid Build Coastguard Worker    def _convert_(cls, name, module, filter, source=None, *, boundary=None, as_global=False):
891*cda5da8dSAndroid Build Coastguard Worker        """
892*cda5da8dSAndroid Build Coastguard Worker        Create a new Enum subclass that replaces a collection of global constants
893*cda5da8dSAndroid Build Coastguard Worker        """
894*cda5da8dSAndroid Build Coastguard Worker        # convert all constants from source (or module) that pass filter() to
895*cda5da8dSAndroid Build Coastguard Worker        # a new Enum called name, and export the enum and its members back to
896*cda5da8dSAndroid Build Coastguard Worker        # module;
897*cda5da8dSAndroid Build Coastguard Worker        # also, replace the __reduce_ex__ method so unpickling works in
898*cda5da8dSAndroid Build Coastguard Worker        # previous Python versions
899*cda5da8dSAndroid Build Coastguard Worker        module_globals = sys.modules[module].__dict__
900*cda5da8dSAndroid Build Coastguard Worker        if source:
901*cda5da8dSAndroid Build Coastguard Worker            source = source.__dict__
902*cda5da8dSAndroid Build Coastguard Worker        else:
903*cda5da8dSAndroid Build Coastguard Worker            source = module_globals
904*cda5da8dSAndroid Build Coastguard Worker        # _value2member_map_ is populated in the same order every time
905*cda5da8dSAndroid Build Coastguard Worker        # for a consistent reverse mapping of number to name when there
906*cda5da8dSAndroid Build Coastguard Worker        # are multiple names for the same number.
907*cda5da8dSAndroid Build Coastguard Worker        members = [
908*cda5da8dSAndroid Build Coastguard Worker                (name, value)
909*cda5da8dSAndroid Build Coastguard Worker                for name, value in source.items()
910*cda5da8dSAndroid Build Coastguard Worker                if filter(name)]
911*cda5da8dSAndroid Build Coastguard Worker        try:
912*cda5da8dSAndroid Build Coastguard Worker            # sort by value
913*cda5da8dSAndroid Build Coastguard Worker            members.sort(key=lambda t: (t[1], t[0]))
914*cda5da8dSAndroid Build Coastguard Worker        except TypeError:
915*cda5da8dSAndroid Build Coastguard Worker            # unless some values aren't comparable, in which case sort by name
916*cda5da8dSAndroid Build Coastguard Worker            members.sort(key=lambda t: t[0])
917*cda5da8dSAndroid Build Coastguard Worker        body = {t[0]: t[1] for t in members}
918*cda5da8dSAndroid Build Coastguard Worker        body['__module__'] = module
919*cda5da8dSAndroid Build Coastguard Worker        tmp_cls = type(name, (object, ), body)
920*cda5da8dSAndroid Build Coastguard Worker        cls = _simple_enum(etype=cls, boundary=boundary or KEEP)(tmp_cls)
921*cda5da8dSAndroid Build Coastguard Worker        cls.__reduce_ex__ = _reduce_ex_by_global_name
922*cda5da8dSAndroid Build Coastguard Worker        if as_global:
923*cda5da8dSAndroid Build Coastguard Worker            global_enum(cls)
924*cda5da8dSAndroid Build Coastguard Worker        else:
925*cda5da8dSAndroid Build Coastguard Worker            sys.modules[cls.__module__].__dict__.update(cls.__members__)
926*cda5da8dSAndroid Build Coastguard Worker        module_globals[name] = cls
927*cda5da8dSAndroid Build Coastguard Worker        return cls
928*cda5da8dSAndroid Build Coastguard Worker
929*cda5da8dSAndroid Build Coastguard Worker    @classmethod
930*cda5da8dSAndroid Build Coastguard Worker    def _check_for_existing_members_(mcls, class_name, bases):
931*cda5da8dSAndroid Build Coastguard Worker        for chain in bases:
932*cda5da8dSAndroid Build Coastguard Worker            for base in chain.__mro__:
933*cda5da8dSAndroid Build Coastguard Worker                if isinstance(base, EnumType) and base._member_names_:
934*cda5da8dSAndroid Build Coastguard Worker                    raise TypeError(
935*cda5da8dSAndroid Build Coastguard Worker                            "<enum %r> cannot extend %r"
936*cda5da8dSAndroid Build Coastguard Worker                            % (class_name, base)
937*cda5da8dSAndroid Build Coastguard Worker                            )
938*cda5da8dSAndroid Build Coastguard Worker
939*cda5da8dSAndroid Build Coastguard Worker    @classmethod
940*cda5da8dSAndroid Build Coastguard Worker    def _get_mixins_(mcls, class_name, bases):
941*cda5da8dSAndroid Build Coastguard Worker        """
942*cda5da8dSAndroid Build Coastguard Worker        Returns the type for creating enum members, and the first inherited
943*cda5da8dSAndroid Build Coastguard Worker        enum class.
944*cda5da8dSAndroid Build Coastguard Worker
945*cda5da8dSAndroid Build Coastguard Worker        bases: the tuple of bases that was given to __new__
946*cda5da8dSAndroid Build Coastguard Worker        """
947*cda5da8dSAndroid Build Coastguard Worker        if not bases:
948*cda5da8dSAndroid Build Coastguard Worker            return object, Enum
949*cda5da8dSAndroid Build Coastguard Worker
950*cda5da8dSAndroid Build Coastguard Worker        mcls._check_for_existing_members_(class_name, bases)
951*cda5da8dSAndroid Build Coastguard Worker
952*cda5da8dSAndroid Build Coastguard Worker        # ensure final parent class is an Enum derivative, find any concrete
953*cda5da8dSAndroid Build Coastguard Worker        # data type, and check that Enum has no members
954*cda5da8dSAndroid Build Coastguard Worker        first_enum = bases[-1]
955*cda5da8dSAndroid Build Coastguard Worker        if not isinstance(first_enum, EnumType):
956*cda5da8dSAndroid Build Coastguard Worker            raise TypeError("new enumerations should be created as "
957*cda5da8dSAndroid Build Coastguard Worker                    "`EnumName([mixin_type, ...] [data_type,] enum_type)`")
958*cda5da8dSAndroid Build Coastguard Worker        member_type = mcls._find_data_type_(class_name, bases) or object
959*cda5da8dSAndroid Build Coastguard Worker        return member_type, first_enum
960*cda5da8dSAndroid Build Coastguard Worker
961*cda5da8dSAndroid Build Coastguard Worker    @classmethod
962*cda5da8dSAndroid Build Coastguard Worker    def _find_data_repr_(mcls, class_name, bases):
963*cda5da8dSAndroid Build Coastguard Worker        for chain in bases:
964*cda5da8dSAndroid Build Coastguard Worker            for base in chain.__mro__:
965*cda5da8dSAndroid Build Coastguard Worker                if base is object:
966*cda5da8dSAndroid Build Coastguard Worker                    continue
967*cda5da8dSAndroid Build Coastguard Worker                elif isinstance(base, EnumType):
968*cda5da8dSAndroid Build Coastguard Worker                    # if we hit an Enum, use it's _value_repr_
969*cda5da8dSAndroid Build Coastguard Worker                    return base._value_repr_
970*cda5da8dSAndroid Build Coastguard Worker                elif '__repr__' in base.__dict__:
971*cda5da8dSAndroid Build Coastguard Worker                    # this is our data repr
972*cda5da8dSAndroid Build Coastguard Worker                    return base.__dict__['__repr__']
973*cda5da8dSAndroid Build Coastguard Worker        return None
974*cda5da8dSAndroid Build Coastguard Worker
975*cda5da8dSAndroid Build Coastguard Worker    @classmethod
976*cda5da8dSAndroid Build Coastguard Worker    def _find_data_type_(mcls, class_name, bases):
977*cda5da8dSAndroid Build Coastguard Worker        # a datatype has a __new__ method
978*cda5da8dSAndroid Build Coastguard Worker        data_types = set()
979*cda5da8dSAndroid Build Coastguard Worker        base_chain = set()
980*cda5da8dSAndroid Build Coastguard Worker        for chain in bases:
981*cda5da8dSAndroid Build Coastguard Worker            candidate = None
982*cda5da8dSAndroid Build Coastguard Worker            for base in chain.__mro__:
983*cda5da8dSAndroid Build Coastguard Worker                base_chain.add(base)
984*cda5da8dSAndroid Build Coastguard Worker                if base is object:
985*cda5da8dSAndroid Build Coastguard Worker                    continue
986*cda5da8dSAndroid Build Coastguard Worker                elif isinstance(base, EnumType):
987*cda5da8dSAndroid Build Coastguard Worker                    if base._member_type_ is not object:
988*cda5da8dSAndroid Build Coastguard Worker                        data_types.add(base._member_type_)
989*cda5da8dSAndroid Build Coastguard Worker                        break
990*cda5da8dSAndroid Build Coastguard Worker                elif '__new__' in base.__dict__ or '__dataclass_fields__' in base.__dict__:
991*cda5da8dSAndroid Build Coastguard Worker                    if isinstance(base, EnumType):
992*cda5da8dSAndroid Build Coastguard Worker                        continue
993*cda5da8dSAndroid Build Coastguard Worker                    data_types.add(candidate or base)
994*cda5da8dSAndroid Build Coastguard Worker                    break
995*cda5da8dSAndroid Build Coastguard Worker                else:
996*cda5da8dSAndroid Build Coastguard Worker                    candidate = candidate or base
997*cda5da8dSAndroid Build Coastguard Worker        if len(data_types) > 1:
998*cda5da8dSAndroid Build Coastguard Worker            raise TypeError('too many data types for %r: %r' % (class_name, data_types))
999*cda5da8dSAndroid Build Coastguard Worker        elif data_types:
1000*cda5da8dSAndroid Build Coastguard Worker            return data_types.pop()
1001*cda5da8dSAndroid Build Coastguard Worker        else:
1002*cda5da8dSAndroid Build Coastguard Worker            return None
1003*cda5da8dSAndroid Build Coastguard Worker
1004*cda5da8dSAndroid Build Coastguard Worker    @classmethod
1005*cda5da8dSAndroid Build Coastguard Worker    def _find_new_(mcls, classdict, member_type, first_enum):
1006*cda5da8dSAndroid Build Coastguard Worker        """
1007*cda5da8dSAndroid Build Coastguard Worker        Returns the __new__ to be used for creating the enum members.
1008*cda5da8dSAndroid Build Coastguard Worker
1009*cda5da8dSAndroid Build Coastguard Worker        classdict: the class dictionary given to __new__
1010*cda5da8dSAndroid Build Coastguard Worker        member_type: the data type whose __new__ will be used by default
1011*cda5da8dSAndroid Build Coastguard Worker        first_enum: enumeration to check for an overriding __new__
1012*cda5da8dSAndroid Build Coastguard Worker        """
1013*cda5da8dSAndroid Build Coastguard Worker        # now find the correct __new__, checking to see of one was defined
1014*cda5da8dSAndroid Build Coastguard Worker        # by the user; also check earlier enum classes in case a __new__ was
1015*cda5da8dSAndroid Build Coastguard Worker        # saved as __new_member__
1016*cda5da8dSAndroid Build Coastguard Worker        __new__ = classdict.get('__new__', None)
1017*cda5da8dSAndroid Build Coastguard Worker
1018*cda5da8dSAndroid Build Coastguard Worker        # should __new__ be saved as __new_member__ later?
1019*cda5da8dSAndroid Build Coastguard Worker        save_new = first_enum is not None and __new__ is not None
1020*cda5da8dSAndroid Build Coastguard Worker
1021*cda5da8dSAndroid Build Coastguard Worker        if __new__ is None:
1022*cda5da8dSAndroid Build Coastguard Worker            # check all possibles for __new_member__ before falling back to
1023*cda5da8dSAndroid Build Coastguard Worker            # __new__
1024*cda5da8dSAndroid Build Coastguard Worker            for method in ('__new_member__', '__new__'):
1025*cda5da8dSAndroid Build Coastguard Worker                for possible in (member_type, first_enum):
1026*cda5da8dSAndroid Build Coastguard Worker                    target = getattr(possible, method, None)
1027*cda5da8dSAndroid Build Coastguard Worker                    if target not in {
1028*cda5da8dSAndroid Build Coastguard Worker                            None,
1029*cda5da8dSAndroid Build Coastguard Worker                            None.__new__,
1030*cda5da8dSAndroid Build Coastguard Worker                            object.__new__,
1031*cda5da8dSAndroid Build Coastguard Worker                            Enum.__new__,
1032*cda5da8dSAndroid Build Coastguard Worker                            }:
1033*cda5da8dSAndroid Build Coastguard Worker                        __new__ = target
1034*cda5da8dSAndroid Build Coastguard Worker                        break
1035*cda5da8dSAndroid Build Coastguard Worker                if __new__ is not None:
1036*cda5da8dSAndroid Build Coastguard Worker                    break
1037*cda5da8dSAndroid Build Coastguard Worker            else:
1038*cda5da8dSAndroid Build Coastguard Worker                __new__ = object.__new__
1039*cda5da8dSAndroid Build Coastguard Worker
1040*cda5da8dSAndroid Build Coastguard Worker        # if a non-object.__new__ is used then whatever value/tuple was
1041*cda5da8dSAndroid Build Coastguard Worker        # assigned to the enum member name will be passed to __new__ and to the
1042*cda5da8dSAndroid Build Coastguard Worker        # new enum member's __init__
1043*cda5da8dSAndroid Build Coastguard Worker        if first_enum is None or __new__ in (Enum.__new__, object.__new__):
1044*cda5da8dSAndroid Build Coastguard Worker            use_args = False
1045*cda5da8dSAndroid Build Coastguard Worker        else:
1046*cda5da8dSAndroid Build Coastguard Worker            use_args = True
1047*cda5da8dSAndroid Build Coastguard Worker        return __new__, save_new, use_args
1048*cda5da8dSAndroid Build Coastguard WorkerEnumMeta = EnumType
1049*cda5da8dSAndroid Build Coastguard Worker
1050*cda5da8dSAndroid Build Coastguard Worker
1051*cda5da8dSAndroid Build Coastguard Workerclass Enum(metaclass=EnumType):
1052*cda5da8dSAndroid Build Coastguard Worker    """
1053*cda5da8dSAndroid Build Coastguard Worker    Create a collection of name/value pairs.
1054*cda5da8dSAndroid Build Coastguard Worker
1055*cda5da8dSAndroid Build Coastguard Worker    Example enumeration:
1056*cda5da8dSAndroid Build Coastguard Worker
1057*cda5da8dSAndroid Build Coastguard Worker    >>> class Color(Enum):
1058*cda5da8dSAndroid Build Coastguard Worker    ...     RED = 1
1059*cda5da8dSAndroid Build Coastguard Worker    ...     BLUE = 2
1060*cda5da8dSAndroid Build Coastguard Worker    ...     GREEN = 3
1061*cda5da8dSAndroid Build Coastguard Worker
1062*cda5da8dSAndroid Build Coastguard Worker    Access them by:
1063*cda5da8dSAndroid Build Coastguard Worker
1064*cda5da8dSAndroid Build Coastguard Worker    - attribute access::
1065*cda5da8dSAndroid Build Coastguard Worker
1066*cda5da8dSAndroid Build Coastguard Worker    >>> Color.RED
1067*cda5da8dSAndroid Build Coastguard Worker    <Color.RED: 1>
1068*cda5da8dSAndroid Build Coastguard Worker
1069*cda5da8dSAndroid Build Coastguard Worker    - value lookup:
1070*cda5da8dSAndroid Build Coastguard Worker
1071*cda5da8dSAndroid Build Coastguard Worker    >>> Color(1)
1072*cda5da8dSAndroid Build Coastguard Worker    <Color.RED: 1>
1073*cda5da8dSAndroid Build Coastguard Worker
1074*cda5da8dSAndroid Build Coastguard Worker    - name lookup:
1075*cda5da8dSAndroid Build Coastguard Worker
1076*cda5da8dSAndroid Build Coastguard Worker    >>> Color['RED']
1077*cda5da8dSAndroid Build Coastguard Worker    <Color.RED: 1>
1078*cda5da8dSAndroid Build Coastguard Worker
1079*cda5da8dSAndroid Build Coastguard Worker    Enumerations can be iterated over, and know how many members they have:
1080*cda5da8dSAndroid Build Coastguard Worker
1081*cda5da8dSAndroid Build Coastguard Worker    >>> len(Color)
1082*cda5da8dSAndroid Build Coastguard Worker    3
1083*cda5da8dSAndroid Build Coastguard Worker
1084*cda5da8dSAndroid Build Coastguard Worker    >>> list(Color)
1085*cda5da8dSAndroid Build Coastguard Worker    [<Color.RED: 1>, <Color.BLUE: 2>, <Color.GREEN: 3>]
1086*cda5da8dSAndroid Build Coastguard Worker
1087*cda5da8dSAndroid Build Coastguard Worker    Methods can be added to enumerations, and members can have their own
1088*cda5da8dSAndroid Build Coastguard Worker    attributes -- see the documentation for details.
1089*cda5da8dSAndroid Build Coastguard Worker    """
1090*cda5da8dSAndroid Build Coastguard Worker
1091*cda5da8dSAndroid Build Coastguard Worker    def __new__(cls, value):
1092*cda5da8dSAndroid Build Coastguard Worker        # all enum instances are actually created during class construction
1093*cda5da8dSAndroid Build Coastguard Worker        # without calling this method; this method is called by the metaclass'
1094*cda5da8dSAndroid Build Coastguard Worker        # __call__ (i.e. Color(3) ), and by pickle
1095*cda5da8dSAndroid Build Coastguard Worker        if type(value) is cls:
1096*cda5da8dSAndroid Build Coastguard Worker            # For lookups like Color(Color.RED)
1097*cda5da8dSAndroid Build Coastguard Worker            return value
1098*cda5da8dSAndroid Build Coastguard Worker        # by-value search for a matching enum member
1099*cda5da8dSAndroid Build Coastguard Worker        # see if it's in the reverse mapping (for hashable values)
1100*cda5da8dSAndroid Build Coastguard Worker        try:
1101*cda5da8dSAndroid Build Coastguard Worker            return cls._value2member_map_[value]
1102*cda5da8dSAndroid Build Coastguard Worker        except KeyError:
1103*cda5da8dSAndroid Build Coastguard Worker            # Not found, no need to do long O(n) search
1104*cda5da8dSAndroid Build Coastguard Worker            pass
1105*cda5da8dSAndroid Build Coastguard Worker        except TypeError:
1106*cda5da8dSAndroid Build Coastguard Worker            # not there, now do long search -- O(n) behavior
1107*cda5da8dSAndroid Build Coastguard Worker            for member in cls._member_map_.values():
1108*cda5da8dSAndroid Build Coastguard Worker                if member._value_ == value:
1109*cda5da8dSAndroid Build Coastguard Worker                    return member
1110*cda5da8dSAndroid Build Coastguard Worker        # still not found -- try _missing_ hook
1111*cda5da8dSAndroid Build Coastguard Worker        try:
1112*cda5da8dSAndroid Build Coastguard Worker            exc = None
1113*cda5da8dSAndroid Build Coastguard Worker            result = cls._missing_(value)
1114*cda5da8dSAndroid Build Coastguard Worker        except Exception as e:
1115*cda5da8dSAndroid Build Coastguard Worker            exc = e
1116*cda5da8dSAndroid Build Coastguard Worker            result = None
1117*cda5da8dSAndroid Build Coastguard Worker        try:
1118*cda5da8dSAndroid Build Coastguard Worker            if isinstance(result, cls):
1119*cda5da8dSAndroid Build Coastguard Worker                return result
1120*cda5da8dSAndroid Build Coastguard Worker            elif (
1121*cda5da8dSAndroid Build Coastguard Worker                    Flag is not None and issubclass(cls, Flag)
1122*cda5da8dSAndroid Build Coastguard Worker                    and cls._boundary_ is EJECT and isinstance(result, int)
1123*cda5da8dSAndroid Build Coastguard Worker                ):
1124*cda5da8dSAndroid Build Coastguard Worker                return result
1125*cda5da8dSAndroid Build Coastguard Worker            else:
1126*cda5da8dSAndroid Build Coastguard Worker                ve_exc = ValueError("%r is not a valid %s" % (value, cls.__qualname__))
1127*cda5da8dSAndroid Build Coastguard Worker                if result is None and exc is None:
1128*cda5da8dSAndroid Build Coastguard Worker                    raise ve_exc
1129*cda5da8dSAndroid Build Coastguard Worker                elif exc is None:
1130*cda5da8dSAndroid Build Coastguard Worker                    exc = TypeError(
1131*cda5da8dSAndroid Build Coastguard Worker                            'error in %s._missing_: returned %r instead of None or a valid member'
1132*cda5da8dSAndroid Build Coastguard Worker                            % (cls.__name__, result)
1133*cda5da8dSAndroid Build Coastguard Worker                            )
1134*cda5da8dSAndroid Build Coastguard Worker                if not isinstance(exc, ValueError):
1135*cda5da8dSAndroid Build Coastguard Worker                    exc.__context__ = ve_exc
1136*cda5da8dSAndroid Build Coastguard Worker                raise exc
1137*cda5da8dSAndroid Build Coastguard Worker        finally:
1138*cda5da8dSAndroid Build Coastguard Worker            # ensure all variables that could hold an exception are destroyed
1139*cda5da8dSAndroid Build Coastguard Worker            exc = None
1140*cda5da8dSAndroid Build Coastguard Worker            ve_exc = None
1141*cda5da8dSAndroid Build Coastguard Worker
1142*cda5da8dSAndroid Build Coastguard Worker    def __init__(self, *args, **kwds):
1143*cda5da8dSAndroid Build Coastguard Worker        pass
1144*cda5da8dSAndroid Build Coastguard Worker
1145*cda5da8dSAndroid Build Coastguard Worker    def _generate_next_value_(name, start, count, last_values):
1146*cda5da8dSAndroid Build Coastguard Worker        """
1147*cda5da8dSAndroid Build Coastguard Worker        Generate the next value when not given.
1148*cda5da8dSAndroid Build Coastguard Worker
1149*cda5da8dSAndroid Build Coastguard Worker        name: the name of the member
1150*cda5da8dSAndroid Build Coastguard Worker        start: the initial start value or None
1151*cda5da8dSAndroid Build Coastguard Worker        count: the number of existing members
1152*cda5da8dSAndroid Build Coastguard Worker        last_values: the list of values assigned
1153*cda5da8dSAndroid Build Coastguard Worker        """
1154*cda5da8dSAndroid Build Coastguard Worker        if not last_values:
1155*cda5da8dSAndroid Build Coastguard Worker            return start
1156*cda5da8dSAndroid Build Coastguard Worker        try:
1157*cda5da8dSAndroid Build Coastguard Worker            last = last_values[-1]
1158*cda5da8dSAndroid Build Coastguard Worker            last_values.sort()
1159*cda5da8dSAndroid Build Coastguard Worker            if last == last_values[-1]:
1160*cda5da8dSAndroid Build Coastguard Worker                # no difference between old and new methods
1161*cda5da8dSAndroid Build Coastguard Worker                return last + 1
1162*cda5da8dSAndroid Build Coastguard Worker            else:
1163*cda5da8dSAndroid Build Coastguard Worker                # trigger old method (with warning)
1164*cda5da8dSAndroid Build Coastguard Worker                raise TypeError
1165*cda5da8dSAndroid Build Coastguard Worker        except TypeError:
1166*cda5da8dSAndroid Build Coastguard Worker            import warnings
1167*cda5da8dSAndroid Build Coastguard Worker            warnings.warn(
1168*cda5da8dSAndroid Build Coastguard Worker                    "In 3.13 the default `auto()`/`_generate_next_value_` will require all values to be sortable and support adding +1\n"
1169*cda5da8dSAndroid Build Coastguard Worker                    "and the value returned will be the largest value in the enum incremented by 1",
1170*cda5da8dSAndroid Build Coastguard Worker                    DeprecationWarning,
1171*cda5da8dSAndroid Build Coastguard Worker                    stacklevel=3,
1172*cda5da8dSAndroid Build Coastguard Worker                    )
1173*cda5da8dSAndroid Build Coastguard Worker            for v in reversed(last_values):
1174*cda5da8dSAndroid Build Coastguard Worker                try:
1175*cda5da8dSAndroid Build Coastguard Worker                    return v + 1
1176*cda5da8dSAndroid Build Coastguard Worker                except TypeError:
1177*cda5da8dSAndroid Build Coastguard Worker                    pass
1178*cda5da8dSAndroid Build Coastguard Worker            return start
1179*cda5da8dSAndroid Build Coastguard Worker
1180*cda5da8dSAndroid Build Coastguard Worker    @classmethod
1181*cda5da8dSAndroid Build Coastguard Worker    def _missing_(cls, value):
1182*cda5da8dSAndroid Build Coastguard Worker        return None
1183*cda5da8dSAndroid Build Coastguard Worker
1184*cda5da8dSAndroid Build Coastguard Worker    def __repr__(self):
1185*cda5da8dSAndroid Build Coastguard Worker        v_repr = self.__class__._value_repr_ or repr
1186*cda5da8dSAndroid Build Coastguard Worker        return "<%s.%s: %s>" % (self.__class__.__name__, self._name_, v_repr(self._value_))
1187*cda5da8dSAndroid Build Coastguard Worker
1188*cda5da8dSAndroid Build Coastguard Worker    def __str__(self):
1189*cda5da8dSAndroid Build Coastguard Worker        return "%s.%s" % (self.__class__.__name__, self._name_, )
1190*cda5da8dSAndroid Build Coastguard Worker
1191*cda5da8dSAndroid Build Coastguard Worker    def __dir__(self):
1192*cda5da8dSAndroid Build Coastguard Worker        """
1193*cda5da8dSAndroid Build Coastguard Worker        Returns all members and all public methods
1194*cda5da8dSAndroid Build Coastguard Worker        """
1195*cda5da8dSAndroid Build Coastguard Worker        if self.__class__._member_type_ is object:
1196*cda5da8dSAndroid Build Coastguard Worker            interesting = set(['__class__', '__doc__', '__eq__', '__hash__', '__module__', 'name', 'value'])
1197*cda5da8dSAndroid Build Coastguard Worker        else:
1198*cda5da8dSAndroid Build Coastguard Worker            interesting = set(object.__dir__(self))
1199*cda5da8dSAndroid Build Coastguard Worker        for name in getattr(self, '__dict__', []):
1200*cda5da8dSAndroid Build Coastguard Worker            if name[0] != '_':
1201*cda5da8dSAndroid Build Coastguard Worker                interesting.add(name)
1202*cda5da8dSAndroid Build Coastguard Worker        for cls in self.__class__.mro():
1203*cda5da8dSAndroid Build Coastguard Worker            for name, obj in cls.__dict__.items():
1204*cda5da8dSAndroid Build Coastguard Worker                if name[0] == '_':
1205*cda5da8dSAndroid Build Coastguard Worker                    continue
1206*cda5da8dSAndroid Build Coastguard Worker                if isinstance(obj, property):
1207*cda5da8dSAndroid Build Coastguard Worker                    # that's an enum.property
1208*cda5da8dSAndroid Build Coastguard Worker                    if obj.fget is not None or name not in self._member_map_:
1209*cda5da8dSAndroid Build Coastguard Worker                        interesting.add(name)
1210*cda5da8dSAndroid Build Coastguard Worker                    else:
1211*cda5da8dSAndroid Build Coastguard Worker                        # in case it was added by `dir(self)`
1212*cda5da8dSAndroid Build Coastguard Worker                        interesting.discard(name)
1213*cda5da8dSAndroid Build Coastguard Worker                else:
1214*cda5da8dSAndroid Build Coastguard Worker                    interesting.add(name)
1215*cda5da8dSAndroid Build Coastguard Worker        names = sorted(
1216*cda5da8dSAndroid Build Coastguard Worker                set(['__class__', '__doc__', '__eq__', '__hash__', '__module__'])
1217*cda5da8dSAndroid Build Coastguard Worker                | interesting
1218*cda5da8dSAndroid Build Coastguard Worker                )
1219*cda5da8dSAndroid Build Coastguard Worker        return names
1220*cda5da8dSAndroid Build Coastguard Worker
1221*cda5da8dSAndroid Build Coastguard Worker    def __format__(self, format_spec):
1222*cda5da8dSAndroid Build Coastguard Worker        return str.__format__(str(self), format_spec)
1223*cda5da8dSAndroid Build Coastguard Worker
1224*cda5da8dSAndroid Build Coastguard Worker    def __hash__(self):
1225*cda5da8dSAndroid Build Coastguard Worker        return hash(self._name_)
1226*cda5da8dSAndroid Build Coastguard Worker
1227*cda5da8dSAndroid Build Coastguard Worker    def __reduce_ex__(self, proto):
1228*cda5da8dSAndroid Build Coastguard Worker        return getattr, (self.__class__, self._name_)
1229*cda5da8dSAndroid Build Coastguard Worker
1230*cda5da8dSAndroid Build Coastguard Worker    # enum.property is used to provide access to the `name` and
1231*cda5da8dSAndroid Build Coastguard Worker    # `value` attributes of enum members while keeping some measure of
1232*cda5da8dSAndroid Build Coastguard Worker    # protection from modification, while still allowing for an enumeration
1233*cda5da8dSAndroid Build Coastguard Worker    # to have members named `name` and `value`.  This works because enumeration
1234*cda5da8dSAndroid Build Coastguard Worker    # members are not set directly on the enum class; they are kept in a
1235*cda5da8dSAndroid Build Coastguard Worker    # separate structure, _member_map_, which is where enum.property looks for
1236*cda5da8dSAndroid Build Coastguard Worker    # them
1237*cda5da8dSAndroid Build Coastguard Worker
1238*cda5da8dSAndroid Build Coastguard Worker    @property
1239*cda5da8dSAndroid Build Coastguard Worker    def name(self):
1240*cda5da8dSAndroid Build Coastguard Worker        """The name of the Enum member."""
1241*cda5da8dSAndroid Build Coastguard Worker        return self._name_
1242*cda5da8dSAndroid Build Coastguard Worker
1243*cda5da8dSAndroid Build Coastguard Worker    @property
1244*cda5da8dSAndroid Build Coastguard Worker    def value(self):
1245*cda5da8dSAndroid Build Coastguard Worker        """The value of the Enum member."""
1246*cda5da8dSAndroid Build Coastguard Worker        return self._value_
1247*cda5da8dSAndroid Build Coastguard Worker
1248*cda5da8dSAndroid Build Coastguard Worker
1249*cda5da8dSAndroid Build Coastguard Workerclass ReprEnum(Enum):
1250*cda5da8dSAndroid Build Coastguard Worker    """
1251*cda5da8dSAndroid Build Coastguard Worker    Only changes the repr(), leaving str() and format() to the mixed-in type.
1252*cda5da8dSAndroid Build Coastguard Worker    """
1253*cda5da8dSAndroid Build Coastguard Worker
1254*cda5da8dSAndroid Build Coastguard Worker
1255*cda5da8dSAndroid Build Coastguard Workerclass IntEnum(int, ReprEnum):
1256*cda5da8dSAndroid Build Coastguard Worker    """
1257*cda5da8dSAndroid Build Coastguard Worker    Enum where members are also (and must be) ints
1258*cda5da8dSAndroid Build Coastguard Worker    """
1259*cda5da8dSAndroid Build Coastguard Worker
1260*cda5da8dSAndroid Build Coastguard Worker
1261*cda5da8dSAndroid Build Coastguard Workerclass StrEnum(str, ReprEnum):
1262*cda5da8dSAndroid Build Coastguard Worker    """
1263*cda5da8dSAndroid Build Coastguard Worker    Enum where members are also (and must be) strings
1264*cda5da8dSAndroid Build Coastguard Worker    """
1265*cda5da8dSAndroid Build Coastguard Worker
1266*cda5da8dSAndroid Build Coastguard Worker    def __new__(cls, *values):
1267*cda5da8dSAndroid Build Coastguard Worker        "values must already be of type `str`"
1268*cda5da8dSAndroid Build Coastguard Worker        if len(values) > 3:
1269*cda5da8dSAndroid Build Coastguard Worker            raise TypeError('too many arguments for str(): %r' % (values, ))
1270*cda5da8dSAndroid Build Coastguard Worker        if len(values) == 1:
1271*cda5da8dSAndroid Build Coastguard Worker            # it must be a string
1272*cda5da8dSAndroid Build Coastguard Worker            if not isinstance(values[0], str):
1273*cda5da8dSAndroid Build Coastguard Worker                raise TypeError('%r is not a string' % (values[0], ))
1274*cda5da8dSAndroid Build Coastguard Worker        if len(values) >= 2:
1275*cda5da8dSAndroid Build Coastguard Worker            # check that encoding argument is a string
1276*cda5da8dSAndroid Build Coastguard Worker            if not isinstance(values[1], str):
1277*cda5da8dSAndroid Build Coastguard Worker                raise TypeError('encoding must be a string, not %r' % (values[1], ))
1278*cda5da8dSAndroid Build Coastguard Worker        if len(values) == 3:
1279*cda5da8dSAndroid Build Coastguard Worker            # check that errors argument is a string
1280*cda5da8dSAndroid Build Coastguard Worker            if not isinstance(values[2], str):
1281*cda5da8dSAndroid Build Coastguard Worker                raise TypeError('errors must be a string, not %r' % (values[2]))
1282*cda5da8dSAndroid Build Coastguard Worker        value = str(*values)
1283*cda5da8dSAndroid Build Coastguard Worker        member = str.__new__(cls, value)
1284*cda5da8dSAndroid Build Coastguard Worker        member._value_ = value
1285*cda5da8dSAndroid Build Coastguard Worker        return member
1286*cda5da8dSAndroid Build Coastguard Worker
1287*cda5da8dSAndroid Build Coastguard Worker    def _generate_next_value_(name, start, count, last_values):
1288*cda5da8dSAndroid Build Coastguard Worker        """
1289*cda5da8dSAndroid Build Coastguard Worker        Return the lower-cased version of the member name.
1290*cda5da8dSAndroid Build Coastguard Worker        """
1291*cda5da8dSAndroid Build Coastguard Worker        return name.lower()
1292*cda5da8dSAndroid Build Coastguard Worker
1293*cda5da8dSAndroid Build Coastguard Worker
1294*cda5da8dSAndroid Build Coastguard Workerdef _reduce_ex_by_global_name(self, proto):
1295*cda5da8dSAndroid Build Coastguard Worker    return self.name
1296*cda5da8dSAndroid Build Coastguard Worker
1297*cda5da8dSAndroid Build Coastguard Workerclass FlagBoundary(StrEnum):
1298*cda5da8dSAndroid Build Coastguard Worker    """
1299*cda5da8dSAndroid Build Coastguard Worker    control how out of range values are handled
1300*cda5da8dSAndroid Build Coastguard Worker    "strict" -> error is raised             [default for Flag]
1301*cda5da8dSAndroid Build Coastguard Worker    "conform" -> extra bits are discarded
1302*cda5da8dSAndroid Build Coastguard Worker    "eject" -> lose flag status
1303*cda5da8dSAndroid Build Coastguard Worker    "keep" -> keep flag status and all bits [default for IntFlag]
1304*cda5da8dSAndroid Build Coastguard Worker    """
1305*cda5da8dSAndroid Build Coastguard Worker    STRICT = auto()
1306*cda5da8dSAndroid Build Coastguard Worker    CONFORM = auto()
1307*cda5da8dSAndroid Build Coastguard Worker    EJECT = auto()
1308*cda5da8dSAndroid Build Coastguard Worker    KEEP = auto()
1309*cda5da8dSAndroid Build Coastguard WorkerSTRICT, CONFORM, EJECT, KEEP = FlagBoundary
1310*cda5da8dSAndroid Build Coastguard Worker
1311*cda5da8dSAndroid Build Coastguard Worker
1312*cda5da8dSAndroid Build Coastguard Workerclass Flag(Enum, boundary=STRICT):
1313*cda5da8dSAndroid Build Coastguard Worker    """
1314*cda5da8dSAndroid Build Coastguard Worker    Support for flags
1315*cda5da8dSAndroid Build Coastguard Worker    """
1316*cda5da8dSAndroid Build Coastguard Worker
1317*cda5da8dSAndroid Build Coastguard Worker    def __reduce_ex__(self, proto):
1318*cda5da8dSAndroid Build Coastguard Worker        cls = self.__class__
1319*cda5da8dSAndroid Build Coastguard Worker        unknown = self._value_ & ~cls._flag_mask_
1320*cda5da8dSAndroid Build Coastguard Worker        member_value = self._value_ & cls._flag_mask_
1321*cda5da8dSAndroid Build Coastguard Worker        if unknown and member_value:
1322*cda5da8dSAndroid Build Coastguard Worker            return _or_, (cls(member_value), unknown)
1323*cda5da8dSAndroid Build Coastguard Worker        for val in _iter_bits_lsb(member_value):
1324*cda5da8dSAndroid Build Coastguard Worker            rest = member_value & ~val
1325*cda5da8dSAndroid Build Coastguard Worker            if rest:
1326*cda5da8dSAndroid Build Coastguard Worker                return _or_, (cls(rest), cls._value2member_map_.get(val))
1327*cda5da8dSAndroid Build Coastguard Worker            else:
1328*cda5da8dSAndroid Build Coastguard Worker                break
1329*cda5da8dSAndroid Build Coastguard Worker        if self._name_ is None:
1330*cda5da8dSAndroid Build Coastguard Worker            return cls, (self._value_,)
1331*cda5da8dSAndroid Build Coastguard Worker        else:
1332*cda5da8dSAndroid Build Coastguard Worker            return getattr, (cls, self._name_)
1333*cda5da8dSAndroid Build Coastguard Worker
1334*cda5da8dSAndroid Build Coastguard Worker    _numeric_repr_ = repr
1335*cda5da8dSAndroid Build Coastguard Worker
1336*cda5da8dSAndroid Build Coastguard Worker    def _generate_next_value_(name, start, count, last_values):
1337*cda5da8dSAndroid Build Coastguard Worker        """
1338*cda5da8dSAndroid Build Coastguard Worker        Generate the next value when not given.
1339*cda5da8dSAndroid Build Coastguard Worker
1340*cda5da8dSAndroid Build Coastguard Worker        name: the name of the member
1341*cda5da8dSAndroid Build Coastguard Worker        start: the initial start value or None
1342*cda5da8dSAndroid Build Coastguard Worker        count: the number of existing members
1343*cda5da8dSAndroid Build Coastguard Worker        last_values: the last value assigned or None
1344*cda5da8dSAndroid Build Coastguard Worker        """
1345*cda5da8dSAndroid Build Coastguard Worker        if not count:
1346*cda5da8dSAndroid Build Coastguard Worker            return start if start is not None else 1
1347*cda5da8dSAndroid Build Coastguard Worker        last_value = max(last_values)
1348*cda5da8dSAndroid Build Coastguard Worker        try:
1349*cda5da8dSAndroid Build Coastguard Worker            high_bit = _high_bit(last_value)
1350*cda5da8dSAndroid Build Coastguard Worker        except Exception:
1351*cda5da8dSAndroid Build Coastguard Worker            raise TypeError('invalid flag value %r' % last_value) from None
1352*cda5da8dSAndroid Build Coastguard Worker        return 2 ** (high_bit+1)
1353*cda5da8dSAndroid Build Coastguard Worker
1354*cda5da8dSAndroid Build Coastguard Worker    @classmethod
1355*cda5da8dSAndroid Build Coastguard Worker    def _iter_member_by_value_(cls, value):
1356*cda5da8dSAndroid Build Coastguard Worker        """
1357*cda5da8dSAndroid Build Coastguard Worker        Extract all members from the value in definition (i.e. increasing value) order.
1358*cda5da8dSAndroid Build Coastguard Worker        """
1359*cda5da8dSAndroid Build Coastguard Worker        for val in _iter_bits_lsb(value & cls._flag_mask_):
1360*cda5da8dSAndroid Build Coastguard Worker            yield cls._value2member_map_.get(val)
1361*cda5da8dSAndroid Build Coastguard Worker
1362*cda5da8dSAndroid Build Coastguard Worker    _iter_member_ = _iter_member_by_value_
1363*cda5da8dSAndroid Build Coastguard Worker
1364*cda5da8dSAndroid Build Coastguard Worker    @classmethod
1365*cda5da8dSAndroid Build Coastguard Worker    def _iter_member_by_def_(cls, value):
1366*cda5da8dSAndroid Build Coastguard Worker        """
1367*cda5da8dSAndroid Build Coastguard Worker        Extract all members from the value in definition order.
1368*cda5da8dSAndroid Build Coastguard Worker        """
1369*cda5da8dSAndroid Build Coastguard Worker        yield from sorted(
1370*cda5da8dSAndroid Build Coastguard Worker                cls._iter_member_by_value_(value),
1371*cda5da8dSAndroid Build Coastguard Worker                key=lambda m: m._sort_order_,
1372*cda5da8dSAndroid Build Coastguard Worker                )
1373*cda5da8dSAndroid Build Coastguard Worker
1374*cda5da8dSAndroid Build Coastguard Worker    @classmethod
1375*cda5da8dSAndroid Build Coastguard Worker    def _missing_(cls, value):
1376*cda5da8dSAndroid Build Coastguard Worker        """
1377*cda5da8dSAndroid Build Coastguard Worker        Create a composite member containing all canonical members present in `value`.
1378*cda5da8dSAndroid Build Coastguard Worker
1379*cda5da8dSAndroid Build Coastguard Worker        If non-member values are present, result depends on `_boundary_` setting.
1380*cda5da8dSAndroid Build Coastguard Worker        """
1381*cda5da8dSAndroid Build Coastguard Worker        if not isinstance(value, int):
1382*cda5da8dSAndroid Build Coastguard Worker            raise ValueError(
1383*cda5da8dSAndroid Build Coastguard Worker                    "%r is not a valid %s" % (value, cls.__qualname__)
1384*cda5da8dSAndroid Build Coastguard Worker                    )
1385*cda5da8dSAndroid Build Coastguard Worker        # check boundaries
1386*cda5da8dSAndroid Build Coastguard Worker        # - value must be in range (e.g. -16 <-> +15, i.e. ~15 <-> 15)
1387*cda5da8dSAndroid Build Coastguard Worker        # - value must not include any skipped flags (e.g. if bit 2 is not
1388*cda5da8dSAndroid Build Coastguard Worker        #   defined, then 0d10 is invalid)
1389*cda5da8dSAndroid Build Coastguard Worker        flag_mask = cls._flag_mask_
1390*cda5da8dSAndroid Build Coastguard Worker        singles_mask = cls._singles_mask_
1391*cda5da8dSAndroid Build Coastguard Worker        all_bits = cls._all_bits_
1392*cda5da8dSAndroid Build Coastguard Worker        neg_value = None
1393*cda5da8dSAndroid Build Coastguard Worker        if (
1394*cda5da8dSAndroid Build Coastguard Worker                not ~all_bits <= value <= all_bits
1395*cda5da8dSAndroid Build Coastguard Worker                or value & (all_bits ^ flag_mask)
1396*cda5da8dSAndroid Build Coastguard Worker            ):
1397*cda5da8dSAndroid Build Coastguard Worker            if cls._boundary_ is STRICT:
1398*cda5da8dSAndroid Build Coastguard Worker                max_bits = max(value.bit_length(), flag_mask.bit_length())
1399*cda5da8dSAndroid Build Coastguard Worker                raise ValueError(
1400*cda5da8dSAndroid Build Coastguard Worker                        "%r invalid value %r\n    given %s\n  allowed %s" % (
1401*cda5da8dSAndroid Build Coastguard Worker                            cls, value, bin(value, max_bits), bin(flag_mask, max_bits),
1402*cda5da8dSAndroid Build Coastguard Worker                            ))
1403*cda5da8dSAndroid Build Coastguard Worker            elif cls._boundary_ is CONFORM:
1404*cda5da8dSAndroid Build Coastguard Worker                value = value & flag_mask
1405*cda5da8dSAndroid Build Coastguard Worker            elif cls._boundary_ is EJECT:
1406*cda5da8dSAndroid Build Coastguard Worker                return value
1407*cda5da8dSAndroid Build Coastguard Worker            elif cls._boundary_ is KEEP:
1408*cda5da8dSAndroid Build Coastguard Worker                if value < 0:
1409*cda5da8dSAndroid Build Coastguard Worker                    value = (
1410*cda5da8dSAndroid Build Coastguard Worker                            max(all_bits+1, 2**(value.bit_length()))
1411*cda5da8dSAndroid Build Coastguard Worker                            + value
1412*cda5da8dSAndroid Build Coastguard Worker                            )
1413*cda5da8dSAndroid Build Coastguard Worker            else:
1414*cda5da8dSAndroid Build Coastguard Worker                raise ValueError(
1415*cda5da8dSAndroid Build Coastguard Worker                        '%r unknown flag boundary %r' % (cls, cls._boundary_, )
1416*cda5da8dSAndroid Build Coastguard Worker                        )
1417*cda5da8dSAndroid Build Coastguard Worker        if value < 0:
1418*cda5da8dSAndroid Build Coastguard Worker            neg_value = value
1419*cda5da8dSAndroid Build Coastguard Worker            value = all_bits + 1 + value
1420*cda5da8dSAndroid Build Coastguard Worker        # get members and unknown
1421*cda5da8dSAndroid Build Coastguard Worker        unknown = value & ~flag_mask
1422*cda5da8dSAndroid Build Coastguard Worker        aliases = value & ~singles_mask
1423*cda5da8dSAndroid Build Coastguard Worker        member_value = value & singles_mask
1424*cda5da8dSAndroid Build Coastguard Worker        if unknown and cls._boundary_ is not KEEP:
1425*cda5da8dSAndroid Build Coastguard Worker            raise ValueError(
1426*cda5da8dSAndroid Build Coastguard Worker                    '%s(%r) -->  unknown values %r [%s]'
1427*cda5da8dSAndroid Build Coastguard Worker                    % (cls.__name__, value, unknown, bin(unknown))
1428*cda5da8dSAndroid Build Coastguard Worker                    )
1429*cda5da8dSAndroid Build Coastguard Worker        # normal Flag?
1430*cda5da8dSAndroid Build Coastguard Worker        if cls._member_type_ is object:
1431*cda5da8dSAndroid Build Coastguard Worker            # construct a singleton enum pseudo-member
1432*cda5da8dSAndroid Build Coastguard Worker            pseudo_member = object.__new__(cls)
1433*cda5da8dSAndroid Build Coastguard Worker        else:
1434*cda5da8dSAndroid Build Coastguard Worker            pseudo_member = cls._member_type_.__new__(cls, value)
1435*cda5da8dSAndroid Build Coastguard Worker        if not hasattr(pseudo_member, '_value_'):
1436*cda5da8dSAndroid Build Coastguard Worker            pseudo_member._value_ = value
1437*cda5da8dSAndroid Build Coastguard Worker        if member_value or aliases:
1438*cda5da8dSAndroid Build Coastguard Worker            members = []
1439*cda5da8dSAndroid Build Coastguard Worker            combined_value = 0
1440*cda5da8dSAndroid Build Coastguard Worker            for m in cls._iter_member_(member_value):
1441*cda5da8dSAndroid Build Coastguard Worker                members.append(m)
1442*cda5da8dSAndroid Build Coastguard Worker                combined_value |= m._value_
1443*cda5da8dSAndroid Build Coastguard Worker            if aliases:
1444*cda5da8dSAndroid Build Coastguard Worker                value = member_value | aliases
1445*cda5da8dSAndroid Build Coastguard Worker                for n, pm in cls._member_map_.items():
1446*cda5da8dSAndroid Build Coastguard Worker                    if pm not in members and pm._value_ and pm._value_ & value == pm._value_:
1447*cda5da8dSAndroid Build Coastguard Worker                        members.append(pm)
1448*cda5da8dSAndroid Build Coastguard Worker                        combined_value |= pm._value_
1449*cda5da8dSAndroid Build Coastguard Worker            unknown = value ^ combined_value
1450*cda5da8dSAndroid Build Coastguard Worker            pseudo_member._name_ = '|'.join([m._name_ for m in members])
1451*cda5da8dSAndroid Build Coastguard Worker            if not combined_value:
1452*cda5da8dSAndroid Build Coastguard Worker                pseudo_member._name_ = None
1453*cda5da8dSAndroid Build Coastguard Worker            elif unknown and cls._boundary_ is STRICT:
1454*cda5da8dSAndroid Build Coastguard Worker                raise ValueError('%r: no members with value %r' % (cls, unknown))
1455*cda5da8dSAndroid Build Coastguard Worker            elif unknown:
1456*cda5da8dSAndroid Build Coastguard Worker                pseudo_member._name_ += '|%s' % cls._numeric_repr_(unknown)
1457*cda5da8dSAndroid Build Coastguard Worker        else:
1458*cda5da8dSAndroid Build Coastguard Worker            pseudo_member._name_ = None
1459*cda5da8dSAndroid Build Coastguard Worker        # use setdefault in case another thread already created a composite
1460*cda5da8dSAndroid Build Coastguard Worker        # with this value, but only if all members are known
1461*cda5da8dSAndroid Build Coastguard Worker        # note: zero is a special case -- add it
1462*cda5da8dSAndroid Build Coastguard Worker        if not unknown:
1463*cda5da8dSAndroid Build Coastguard Worker            pseudo_member = cls._value2member_map_.setdefault(value, pseudo_member)
1464*cda5da8dSAndroid Build Coastguard Worker            if neg_value is not None:
1465*cda5da8dSAndroid Build Coastguard Worker                cls._value2member_map_[neg_value] = pseudo_member
1466*cda5da8dSAndroid Build Coastguard Worker        return pseudo_member
1467*cda5da8dSAndroid Build Coastguard Worker
1468*cda5da8dSAndroid Build Coastguard Worker    def __contains__(self, other):
1469*cda5da8dSAndroid Build Coastguard Worker        """
1470*cda5da8dSAndroid Build Coastguard Worker        Returns True if self has at least the same flags set as other.
1471*cda5da8dSAndroid Build Coastguard Worker        """
1472*cda5da8dSAndroid Build Coastguard Worker        if not isinstance(other, self.__class__):
1473*cda5da8dSAndroid Build Coastguard Worker            raise TypeError(
1474*cda5da8dSAndroid Build Coastguard Worker                "unsupported operand type(s) for 'in': %r and %r" % (
1475*cda5da8dSAndroid Build Coastguard Worker                    type(other).__qualname__, self.__class__.__qualname__))
1476*cda5da8dSAndroid Build Coastguard Worker        return other._value_ & self._value_ == other._value_
1477*cda5da8dSAndroid Build Coastguard Worker
1478*cda5da8dSAndroid Build Coastguard Worker    def __iter__(self):
1479*cda5da8dSAndroid Build Coastguard Worker        """
1480*cda5da8dSAndroid Build Coastguard Worker        Returns flags in definition order.
1481*cda5da8dSAndroid Build Coastguard Worker        """
1482*cda5da8dSAndroid Build Coastguard Worker        yield from self._iter_member_(self._value_)
1483*cda5da8dSAndroid Build Coastguard Worker
1484*cda5da8dSAndroid Build Coastguard Worker    def __len__(self):
1485*cda5da8dSAndroid Build Coastguard Worker        return self._value_.bit_count()
1486*cda5da8dSAndroid Build Coastguard Worker
1487*cda5da8dSAndroid Build Coastguard Worker    def __repr__(self):
1488*cda5da8dSAndroid Build Coastguard Worker        cls_name = self.__class__.__name__
1489*cda5da8dSAndroid Build Coastguard Worker        v_repr = self.__class__._value_repr_ or repr
1490*cda5da8dSAndroid Build Coastguard Worker        if self._name_ is None:
1491*cda5da8dSAndroid Build Coastguard Worker            return "<%s: %s>" % (cls_name, v_repr(self._value_))
1492*cda5da8dSAndroid Build Coastguard Worker        else:
1493*cda5da8dSAndroid Build Coastguard Worker            return "<%s.%s: %s>" % (cls_name, self._name_, v_repr(self._value_))
1494*cda5da8dSAndroid Build Coastguard Worker
1495*cda5da8dSAndroid Build Coastguard Worker    def __str__(self):
1496*cda5da8dSAndroid Build Coastguard Worker        cls_name = self.__class__.__name__
1497*cda5da8dSAndroid Build Coastguard Worker        if self._name_ is None:
1498*cda5da8dSAndroid Build Coastguard Worker            return '%s(%r)' % (cls_name, self._value_)
1499*cda5da8dSAndroid Build Coastguard Worker        else:
1500*cda5da8dSAndroid Build Coastguard Worker            return "%s.%s" % (cls_name, self._name_)
1501*cda5da8dSAndroid Build Coastguard Worker
1502*cda5da8dSAndroid Build Coastguard Worker    def __bool__(self):
1503*cda5da8dSAndroid Build Coastguard Worker        return bool(self._value_)
1504*cda5da8dSAndroid Build Coastguard Worker
1505*cda5da8dSAndroid Build Coastguard Worker    def __or__(self, other):
1506*cda5da8dSAndroid Build Coastguard Worker        if isinstance(other, self.__class__):
1507*cda5da8dSAndroid Build Coastguard Worker            other = other._value_
1508*cda5da8dSAndroid Build Coastguard Worker        elif self._member_type_ is not object and isinstance(other, self._member_type_):
1509*cda5da8dSAndroid Build Coastguard Worker            other = other
1510*cda5da8dSAndroid Build Coastguard Worker        else:
1511*cda5da8dSAndroid Build Coastguard Worker            return NotImplemented
1512*cda5da8dSAndroid Build Coastguard Worker        value = self._value_
1513*cda5da8dSAndroid Build Coastguard Worker        return self.__class__(value | other)
1514*cda5da8dSAndroid Build Coastguard Worker
1515*cda5da8dSAndroid Build Coastguard Worker    def __and__(self, other):
1516*cda5da8dSAndroid Build Coastguard Worker        if isinstance(other, self.__class__):
1517*cda5da8dSAndroid Build Coastguard Worker            other = other._value_
1518*cda5da8dSAndroid Build Coastguard Worker        elif self._member_type_ is not object and isinstance(other, self._member_type_):
1519*cda5da8dSAndroid Build Coastguard Worker            other = other
1520*cda5da8dSAndroid Build Coastguard Worker        else:
1521*cda5da8dSAndroid Build Coastguard Worker            return NotImplemented
1522*cda5da8dSAndroid Build Coastguard Worker        value = self._value_
1523*cda5da8dSAndroid Build Coastguard Worker        return self.__class__(value & other)
1524*cda5da8dSAndroid Build Coastguard Worker
1525*cda5da8dSAndroid Build Coastguard Worker    def __xor__(self, other):
1526*cda5da8dSAndroid Build Coastguard Worker        if isinstance(other, self.__class__):
1527*cda5da8dSAndroid Build Coastguard Worker            other = other._value_
1528*cda5da8dSAndroid Build Coastguard Worker        elif self._member_type_ is not object and isinstance(other, self._member_type_):
1529*cda5da8dSAndroid Build Coastguard Worker            other = other
1530*cda5da8dSAndroid Build Coastguard Worker        else:
1531*cda5da8dSAndroid Build Coastguard Worker            return NotImplemented
1532*cda5da8dSAndroid Build Coastguard Worker        value = self._value_
1533*cda5da8dSAndroid Build Coastguard Worker        return self.__class__(value ^ other)
1534*cda5da8dSAndroid Build Coastguard Worker
1535*cda5da8dSAndroid Build Coastguard Worker    def __invert__(self):
1536*cda5da8dSAndroid Build Coastguard Worker        if self._inverted_ is None:
1537*cda5da8dSAndroid Build Coastguard Worker            if self._boundary_ is KEEP:
1538*cda5da8dSAndroid Build Coastguard Worker                # use all bits
1539*cda5da8dSAndroid Build Coastguard Worker                self._inverted_ = self.__class__(~self._value_)
1540*cda5da8dSAndroid Build Coastguard Worker            else:
1541*cda5da8dSAndroid Build Coastguard Worker                # calculate flags not in this member
1542*cda5da8dSAndroid Build Coastguard Worker                self._inverted_ = self.__class__(self._flag_mask_ ^ self._value_)
1543*cda5da8dSAndroid Build Coastguard Worker            if isinstance(self._inverted_, self.__class__):
1544*cda5da8dSAndroid Build Coastguard Worker                self._inverted_._inverted_ = self
1545*cda5da8dSAndroid Build Coastguard Worker        return self._inverted_
1546*cda5da8dSAndroid Build Coastguard Worker
1547*cda5da8dSAndroid Build Coastguard Worker    __rand__ = __and__
1548*cda5da8dSAndroid Build Coastguard Worker    __ror__ = __or__
1549*cda5da8dSAndroid Build Coastguard Worker    __rxor__ = __xor__
1550*cda5da8dSAndroid Build Coastguard Worker
1551*cda5da8dSAndroid Build Coastguard Worker
1552*cda5da8dSAndroid Build Coastguard Workerclass IntFlag(int, ReprEnum, Flag, boundary=KEEP):
1553*cda5da8dSAndroid Build Coastguard Worker    """
1554*cda5da8dSAndroid Build Coastguard Worker    Support for integer-based Flags
1555*cda5da8dSAndroid Build Coastguard Worker    """
1556*cda5da8dSAndroid Build Coastguard Worker
1557*cda5da8dSAndroid Build Coastguard Worker
1558*cda5da8dSAndroid Build Coastguard Workerdef _high_bit(value):
1559*cda5da8dSAndroid Build Coastguard Worker    """
1560*cda5da8dSAndroid Build Coastguard Worker    returns index of highest bit, or -1 if value is zero or negative
1561*cda5da8dSAndroid Build Coastguard Worker    """
1562*cda5da8dSAndroid Build Coastguard Worker    return value.bit_length() - 1
1563*cda5da8dSAndroid Build Coastguard Worker
1564*cda5da8dSAndroid Build Coastguard Workerdef unique(enumeration):
1565*cda5da8dSAndroid Build Coastguard Worker    """
1566*cda5da8dSAndroid Build Coastguard Worker    Class decorator for enumerations ensuring unique member values.
1567*cda5da8dSAndroid Build Coastguard Worker    """
1568*cda5da8dSAndroid Build Coastguard Worker    duplicates = []
1569*cda5da8dSAndroid Build Coastguard Worker    for name, member in enumeration.__members__.items():
1570*cda5da8dSAndroid Build Coastguard Worker        if name != member.name:
1571*cda5da8dSAndroid Build Coastguard Worker            duplicates.append((name, member.name))
1572*cda5da8dSAndroid Build Coastguard Worker    if duplicates:
1573*cda5da8dSAndroid Build Coastguard Worker        alias_details = ', '.join(
1574*cda5da8dSAndroid Build Coastguard Worker                ["%s -> %s" % (alias, name) for (alias, name) in duplicates])
1575*cda5da8dSAndroid Build Coastguard Worker        raise ValueError('duplicate values found in %r: %s' %
1576*cda5da8dSAndroid Build Coastguard Worker                (enumeration, alias_details))
1577*cda5da8dSAndroid Build Coastguard Worker    return enumeration
1578*cda5da8dSAndroid Build Coastguard Worker
1579*cda5da8dSAndroid Build Coastguard Workerdef _power_of_two(value):
1580*cda5da8dSAndroid Build Coastguard Worker    if value < 1:
1581*cda5da8dSAndroid Build Coastguard Worker        return False
1582*cda5da8dSAndroid Build Coastguard Worker    return value == 2 ** _high_bit(value)
1583*cda5da8dSAndroid Build Coastguard Worker
1584*cda5da8dSAndroid Build Coastguard Workerdef global_enum_repr(self):
1585*cda5da8dSAndroid Build Coastguard Worker    """
1586*cda5da8dSAndroid Build Coastguard Worker    use module.enum_name instead of class.enum_name
1587*cda5da8dSAndroid Build Coastguard Worker
1588*cda5da8dSAndroid Build Coastguard Worker    the module is the last module in case of a multi-module name
1589*cda5da8dSAndroid Build Coastguard Worker    """
1590*cda5da8dSAndroid Build Coastguard Worker    module = self.__class__.__module__.split('.')[-1]
1591*cda5da8dSAndroid Build Coastguard Worker    return '%s.%s' % (module, self._name_)
1592*cda5da8dSAndroid Build Coastguard Worker
1593*cda5da8dSAndroid Build Coastguard Workerdef global_flag_repr(self):
1594*cda5da8dSAndroid Build Coastguard Worker    """
1595*cda5da8dSAndroid Build Coastguard Worker    use module.flag_name instead of class.flag_name
1596*cda5da8dSAndroid Build Coastguard Worker
1597*cda5da8dSAndroid Build Coastguard Worker    the module is the last module in case of a multi-module name
1598*cda5da8dSAndroid Build Coastguard Worker    """
1599*cda5da8dSAndroid Build Coastguard Worker    module = self.__class__.__module__.split('.')[-1]
1600*cda5da8dSAndroid Build Coastguard Worker    cls_name = self.__class__.__name__
1601*cda5da8dSAndroid Build Coastguard Worker    if self._name_ is None:
1602*cda5da8dSAndroid Build Coastguard Worker        return "%s.%s(%r)" % (module, cls_name, self._value_)
1603*cda5da8dSAndroid Build Coastguard Worker    if _is_single_bit(self):
1604*cda5da8dSAndroid Build Coastguard Worker        return '%s.%s' % (module, self._name_)
1605*cda5da8dSAndroid Build Coastguard Worker    if self._boundary_ is not FlagBoundary.KEEP:
1606*cda5da8dSAndroid Build Coastguard Worker        return '|'.join(['%s.%s' % (module, name) for name in self.name.split('|')])
1607*cda5da8dSAndroid Build Coastguard Worker    else:
1608*cda5da8dSAndroid Build Coastguard Worker        name = []
1609*cda5da8dSAndroid Build Coastguard Worker        for n in self._name_.split('|'):
1610*cda5da8dSAndroid Build Coastguard Worker            if n[0].isdigit():
1611*cda5da8dSAndroid Build Coastguard Worker                name.append(n)
1612*cda5da8dSAndroid Build Coastguard Worker            else:
1613*cda5da8dSAndroid Build Coastguard Worker                name.append('%s.%s' % (module, n))
1614*cda5da8dSAndroid Build Coastguard Worker        return '|'.join(name)
1615*cda5da8dSAndroid Build Coastguard Worker
1616*cda5da8dSAndroid Build Coastguard Workerdef global_str(self):
1617*cda5da8dSAndroid Build Coastguard Worker    """
1618*cda5da8dSAndroid Build Coastguard Worker    use enum_name instead of class.enum_name
1619*cda5da8dSAndroid Build Coastguard Worker    """
1620*cda5da8dSAndroid Build Coastguard Worker    if self._name_ is None:
1621*cda5da8dSAndroid Build Coastguard Worker        cls_name = self.__class__.__name__
1622*cda5da8dSAndroid Build Coastguard Worker        return "%s(%r)" % (cls_name, self._value_)
1623*cda5da8dSAndroid Build Coastguard Worker    else:
1624*cda5da8dSAndroid Build Coastguard Worker        return self._name_
1625*cda5da8dSAndroid Build Coastguard Worker
1626*cda5da8dSAndroid Build Coastguard Workerdef global_enum(cls, update_str=False):
1627*cda5da8dSAndroid Build Coastguard Worker    """
1628*cda5da8dSAndroid Build Coastguard Worker    decorator that makes the repr() of an enum member reference its module
1629*cda5da8dSAndroid Build Coastguard Worker    instead of its class; also exports all members to the enum's module's
1630*cda5da8dSAndroid Build Coastguard Worker    global namespace
1631*cda5da8dSAndroid Build Coastguard Worker    """
1632*cda5da8dSAndroid Build Coastguard Worker    if issubclass(cls, Flag):
1633*cda5da8dSAndroid Build Coastguard Worker        cls.__repr__ = global_flag_repr
1634*cda5da8dSAndroid Build Coastguard Worker    else:
1635*cda5da8dSAndroid Build Coastguard Worker        cls.__repr__ = global_enum_repr
1636*cda5da8dSAndroid Build Coastguard Worker    if not issubclass(cls, ReprEnum) or update_str:
1637*cda5da8dSAndroid Build Coastguard Worker        cls.__str__ = global_str
1638*cda5da8dSAndroid Build Coastguard Worker    sys.modules[cls.__module__].__dict__.update(cls.__members__)
1639*cda5da8dSAndroid Build Coastguard Worker    return cls
1640*cda5da8dSAndroid Build Coastguard Worker
1641*cda5da8dSAndroid Build Coastguard Workerdef _simple_enum(etype=Enum, *, boundary=None, use_args=None):
1642*cda5da8dSAndroid Build Coastguard Worker    """
1643*cda5da8dSAndroid Build Coastguard Worker    Class decorator that converts a normal class into an :class:`Enum`.  No
1644*cda5da8dSAndroid Build Coastguard Worker    safety checks are done, and some advanced behavior (such as
1645*cda5da8dSAndroid Build Coastguard Worker    :func:`__init_subclass__`) is not available.  Enum creation can be faster
1646*cda5da8dSAndroid Build Coastguard Worker    using :func:`simple_enum`.
1647*cda5da8dSAndroid Build Coastguard Worker
1648*cda5da8dSAndroid Build Coastguard Worker        >>> from enum import Enum, _simple_enum
1649*cda5da8dSAndroid Build Coastguard Worker        >>> @_simple_enum(Enum)
1650*cda5da8dSAndroid Build Coastguard Worker        ... class Color:
1651*cda5da8dSAndroid Build Coastguard Worker        ...     RED = auto()
1652*cda5da8dSAndroid Build Coastguard Worker        ...     GREEN = auto()
1653*cda5da8dSAndroid Build Coastguard Worker        ...     BLUE = auto()
1654*cda5da8dSAndroid Build Coastguard Worker        >>> Color
1655*cda5da8dSAndroid Build Coastguard Worker        <enum 'Color'>
1656*cda5da8dSAndroid Build Coastguard Worker    """
1657*cda5da8dSAndroid Build Coastguard Worker    def convert_class(cls):
1658*cda5da8dSAndroid Build Coastguard Worker        nonlocal use_args
1659*cda5da8dSAndroid Build Coastguard Worker        cls_name = cls.__name__
1660*cda5da8dSAndroid Build Coastguard Worker        if use_args is None:
1661*cda5da8dSAndroid Build Coastguard Worker            use_args = etype._use_args_
1662*cda5da8dSAndroid Build Coastguard Worker        __new__ = cls.__dict__.get('__new__')
1663*cda5da8dSAndroid Build Coastguard Worker        if __new__ is not None:
1664*cda5da8dSAndroid Build Coastguard Worker            new_member = __new__.__func__
1665*cda5da8dSAndroid Build Coastguard Worker        else:
1666*cda5da8dSAndroid Build Coastguard Worker            new_member = etype._member_type_.__new__
1667*cda5da8dSAndroid Build Coastguard Worker        attrs = {}
1668*cda5da8dSAndroid Build Coastguard Worker        body = {}
1669*cda5da8dSAndroid Build Coastguard Worker        if __new__ is not None:
1670*cda5da8dSAndroid Build Coastguard Worker            body['__new_member__'] = new_member
1671*cda5da8dSAndroid Build Coastguard Worker        body['_new_member_'] = new_member
1672*cda5da8dSAndroid Build Coastguard Worker        body['_use_args_'] = use_args
1673*cda5da8dSAndroid Build Coastguard Worker        body['_generate_next_value_'] = gnv = etype._generate_next_value_
1674*cda5da8dSAndroid Build Coastguard Worker        body['_member_names_'] = member_names = []
1675*cda5da8dSAndroid Build Coastguard Worker        body['_member_map_'] = member_map = {}
1676*cda5da8dSAndroid Build Coastguard Worker        body['_value2member_map_'] = value2member_map = {}
1677*cda5da8dSAndroid Build Coastguard Worker        body['_unhashable_values_'] = []
1678*cda5da8dSAndroid Build Coastguard Worker        body['_member_type_'] = member_type = etype._member_type_
1679*cda5da8dSAndroid Build Coastguard Worker        body['_value_repr_'] = etype._value_repr_
1680*cda5da8dSAndroid Build Coastguard Worker        if issubclass(etype, Flag):
1681*cda5da8dSAndroid Build Coastguard Worker            body['_boundary_'] = boundary or etype._boundary_
1682*cda5da8dSAndroid Build Coastguard Worker            body['_flag_mask_'] = None
1683*cda5da8dSAndroid Build Coastguard Worker            body['_all_bits_'] = None
1684*cda5da8dSAndroid Build Coastguard Worker            body['_singles_mask_'] = None
1685*cda5da8dSAndroid Build Coastguard Worker            body['_inverted_'] = None
1686*cda5da8dSAndroid Build Coastguard Worker            body['__or__'] = Flag.__or__
1687*cda5da8dSAndroid Build Coastguard Worker            body['__xor__'] = Flag.__xor__
1688*cda5da8dSAndroid Build Coastguard Worker            body['__and__'] = Flag.__and__
1689*cda5da8dSAndroid Build Coastguard Worker            body['__ror__'] = Flag.__ror__
1690*cda5da8dSAndroid Build Coastguard Worker            body['__rxor__'] = Flag.__rxor__
1691*cda5da8dSAndroid Build Coastguard Worker            body['__rand__'] = Flag.__rand__
1692*cda5da8dSAndroid Build Coastguard Worker            body['__invert__'] = Flag.__invert__
1693*cda5da8dSAndroid Build Coastguard Worker        for name, obj in cls.__dict__.items():
1694*cda5da8dSAndroid Build Coastguard Worker            if name in ('__dict__', '__weakref__'):
1695*cda5da8dSAndroid Build Coastguard Worker                continue
1696*cda5da8dSAndroid Build Coastguard Worker            if _is_dunder(name) or _is_private(cls_name, name) or _is_sunder(name) or _is_descriptor(obj):
1697*cda5da8dSAndroid Build Coastguard Worker                body[name] = obj
1698*cda5da8dSAndroid Build Coastguard Worker            else:
1699*cda5da8dSAndroid Build Coastguard Worker                attrs[name] = obj
1700*cda5da8dSAndroid Build Coastguard Worker        if cls.__dict__.get('__doc__') is None:
1701*cda5da8dSAndroid Build Coastguard Worker            body['__doc__'] = 'An enumeration.'
1702*cda5da8dSAndroid Build Coastguard Worker        #
1703*cda5da8dSAndroid Build Coastguard Worker        # double check that repr and friends are not the mixin's or various
1704*cda5da8dSAndroid Build Coastguard Worker        # things break (such as pickle)
1705*cda5da8dSAndroid Build Coastguard Worker        # however, if the method is defined in the Enum itself, don't replace
1706*cda5da8dSAndroid Build Coastguard Worker        # it
1707*cda5da8dSAndroid Build Coastguard Worker        enum_class = type(cls_name, (etype, ), body, boundary=boundary, _simple=True)
1708*cda5da8dSAndroid Build Coastguard Worker        for name in ('__repr__', '__str__', '__format__', '__reduce_ex__'):
1709*cda5da8dSAndroid Build Coastguard Worker            if name not in body:
1710*cda5da8dSAndroid Build Coastguard Worker                # check for mixin overrides before replacing
1711*cda5da8dSAndroid Build Coastguard Worker                enum_method = getattr(etype, name)
1712*cda5da8dSAndroid Build Coastguard Worker                found_method = getattr(enum_class, name)
1713*cda5da8dSAndroid Build Coastguard Worker                object_method = getattr(object, name)
1714*cda5da8dSAndroid Build Coastguard Worker                data_type_method = getattr(member_type, name)
1715*cda5da8dSAndroid Build Coastguard Worker                if found_method in (data_type_method, object_method):
1716*cda5da8dSAndroid Build Coastguard Worker                    setattr(enum_class, name, enum_method)
1717*cda5da8dSAndroid Build Coastguard Worker        gnv_last_values = []
1718*cda5da8dSAndroid Build Coastguard Worker        if issubclass(enum_class, Flag):
1719*cda5da8dSAndroid Build Coastguard Worker            # Flag / IntFlag
1720*cda5da8dSAndroid Build Coastguard Worker            single_bits = multi_bits = 0
1721*cda5da8dSAndroid Build Coastguard Worker            for name, value in attrs.items():
1722*cda5da8dSAndroid Build Coastguard Worker                if isinstance(value, auto) and auto.value is _auto_null:
1723*cda5da8dSAndroid Build Coastguard Worker                    value = gnv(name, 1, len(member_names), gnv_last_values)
1724*cda5da8dSAndroid Build Coastguard Worker                if value in value2member_map:
1725*cda5da8dSAndroid Build Coastguard Worker                    # an alias to an existing member
1726*cda5da8dSAndroid Build Coastguard Worker                    redirect = property()
1727*cda5da8dSAndroid Build Coastguard Worker                    redirect.__set_name__(enum_class, name)
1728*cda5da8dSAndroid Build Coastguard Worker                    setattr(enum_class, name, redirect)
1729*cda5da8dSAndroid Build Coastguard Worker                    member_map[name] = value2member_map[value]
1730*cda5da8dSAndroid Build Coastguard Worker                else:
1731*cda5da8dSAndroid Build Coastguard Worker                    # create the member
1732*cda5da8dSAndroid Build Coastguard Worker                    if use_args:
1733*cda5da8dSAndroid Build Coastguard Worker                        if not isinstance(value, tuple):
1734*cda5da8dSAndroid Build Coastguard Worker                            value = (value, )
1735*cda5da8dSAndroid Build Coastguard Worker                        member = new_member(enum_class, *value)
1736*cda5da8dSAndroid Build Coastguard Worker                        value = value[0]
1737*cda5da8dSAndroid Build Coastguard Worker                    else:
1738*cda5da8dSAndroid Build Coastguard Worker                        member = new_member(enum_class)
1739*cda5da8dSAndroid Build Coastguard Worker                    if __new__ is None:
1740*cda5da8dSAndroid Build Coastguard Worker                        member._value_ = value
1741*cda5da8dSAndroid Build Coastguard Worker                    member._name_ = name
1742*cda5da8dSAndroid Build Coastguard Worker                    member.__objclass__ = enum_class
1743*cda5da8dSAndroid Build Coastguard Worker                    member.__init__(value)
1744*cda5da8dSAndroid Build Coastguard Worker                    redirect = property()
1745*cda5da8dSAndroid Build Coastguard Worker                    redirect.__set_name__(enum_class, name)
1746*cda5da8dSAndroid Build Coastguard Worker                    setattr(enum_class, name, redirect)
1747*cda5da8dSAndroid Build Coastguard Worker                    member_map[name] = member
1748*cda5da8dSAndroid Build Coastguard Worker                    member._sort_order_ = len(member_names)
1749*cda5da8dSAndroid Build Coastguard Worker                    value2member_map[value] = member
1750*cda5da8dSAndroid Build Coastguard Worker                    if _is_single_bit(value):
1751*cda5da8dSAndroid Build Coastguard Worker                        # not a multi-bit alias, record in _member_names_ and _flag_mask_
1752*cda5da8dSAndroid Build Coastguard Worker                        member_names.append(name)
1753*cda5da8dSAndroid Build Coastguard Worker                        single_bits |= value
1754*cda5da8dSAndroid Build Coastguard Worker                    else:
1755*cda5da8dSAndroid Build Coastguard Worker                        multi_bits |= value
1756*cda5da8dSAndroid Build Coastguard Worker                    gnv_last_values.append(value)
1757*cda5da8dSAndroid Build Coastguard Worker            enum_class._flag_mask_ = single_bits | multi_bits
1758*cda5da8dSAndroid Build Coastguard Worker            enum_class._singles_mask_ = single_bits
1759*cda5da8dSAndroid Build Coastguard Worker            enum_class._all_bits_ = 2 ** ((single_bits|multi_bits).bit_length()) - 1
1760*cda5da8dSAndroid Build Coastguard Worker            # set correct __iter__
1761*cda5da8dSAndroid Build Coastguard Worker            member_list = [m._value_ for m in enum_class]
1762*cda5da8dSAndroid Build Coastguard Worker            if member_list != sorted(member_list):
1763*cda5da8dSAndroid Build Coastguard Worker                enum_class._iter_member_ = enum_class._iter_member_by_def_
1764*cda5da8dSAndroid Build Coastguard Worker        else:
1765*cda5da8dSAndroid Build Coastguard Worker            # Enum / IntEnum / StrEnum
1766*cda5da8dSAndroid Build Coastguard Worker            for name, value in attrs.items():
1767*cda5da8dSAndroid Build Coastguard Worker                if isinstance(value, auto):
1768*cda5da8dSAndroid Build Coastguard Worker                    if value.value is _auto_null:
1769*cda5da8dSAndroid Build Coastguard Worker                        value.value = gnv(name, 1, len(member_names), gnv_last_values)
1770*cda5da8dSAndroid Build Coastguard Worker                    value = value.value
1771*cda5da8dSAndroid Build Coastguard Worker                if value in value2member_map:
1772*cda5da8dSAndroid Build Coastguard Worker                    # an alias to an existing member
1773*cda5da8dSAndroid Build Coastguard Worker                    redirect = property()
1774*cda5da8dSAndroid Build Coastguard Worker                    redirect.__set_name__(enum_class, name)
1775*cda5da8dSAndroid Build Coastguard Worker                    setattr(enum_class, name, redirect)
1776*cda5da8dSAndroid Build Coastguard Worker                    member_map[name] = value2member_map[value]
1777*cda5da8dSAndroid Build Coastguard Worker                else:
1778*cda5da8dSAndroid Build Coastguard Worker                    # create the member
1779*cda5da8dSAndroid Build Coastguard Worker                    if use_args:
1780*cda5da8dSAndroid Build Coastguard Worker                        if not isinstance(value, tuple):
1781*cda5da8dSAndroid Build Coastguard Worker                            value = (value, )
1782*cda5da8dSAndroid Build Coastguard Worker                        member = new_member(enum_class, *value)
1783*cda5da8dSAndroid Build Coastguard Worker                        value = value[0]
1784*cda5da8dSAndroid Build Coastguard Worker                    else:
1785*cda5da8dSAndroid Build Coastguard Worker                        member = new_member(enum_class)
1786*cda5da8dSAndroid Build Coastguard Worker                    if __new__ is None:
1787*cda5da8dSAndroid Build Coastguard Worker                        member._value_ = value
1788*cda5da8dSAndroid Build Coastguard Worker                    member._name_ = name
1789*cda5da8dSAndroid Build Coastguard Worker                    member.__objclass__ = enum_class
1790*cda5da8dSAndroid Build Coastguard Worker                    member.__init__(value)
1791*cda5da8dSAndroid Build Coastguard Worker                    member._sort_order_ = len(member_names)
1792*cda5da8dSAndroid Build Coastguard Worker                    redirect = property()
1793*cda5da8dSAndroid Build Coastguard Worker                    redirect.__set_name__(enum_class, name)
1794*cda5da8dSAndroid Build Coastguard Worker                    setattr(enum_class, name, redirect)
1795*cda5da8dSAndroid Build Coastguard Worker                    member_map[name] = member
1796*cda5da8dSAndroid Build Coastguard Worker                    value2member_map[value] = member
1797*cda5da8dSAndroid Build Coastguard Worker                    member_names.append(name)
1798*cda5da8dSAndroid Build Coastguard Worker                    gnv_last_values.append(value)
1799*cda5da8dSAndroid Build Coastguard Worker        if '__new__' in body:
1800*cda5da8dSAndroid Build Coastguard Worker            enum_class.__new_member__ = enum_class.__new__
1801*cda5da8dSAndroid Build Coastguard Worker        enum_class.__new__ = Enum.__new__
1802*cda5da8dSAndroid Build Coastguard Worker        return enum_class
1803*cda5da8dSAndroid Build Coastguard Worker    return convert_class
1804*cda5da8dSAndroid Build Coastguard Worker
1805*cda5da8dSAndroid Build Coastguard Worker@_simple_enum(StrEnum)
1806*cda5da8dSAndroid Build Coastguard Workerclass EnumCheck:
1807*cda5da8dSAndroid Build Coastguard Worker    """
1808*cda5da8dSAndroid Build Coastguard Worker    various conditions to check an enumeration for
1809*cda5da8dSAndroid Build Coastguard Worker    """
1810*cda5da8dSAndroid Build Coastguard Worker    CONTINUOUS = "no skipped integer values"
1811*cda5da8dSAndroid Build Coastguard Worker    NAMED_FLAGS = "multi-flag aliases may not contain unnamed flags"
1812*cda5da8dSAndroid Build Coastguard Worker    UNIQUE = "one name per value"
1813*cda5da8dSAndroid Build Coastguard WorkerCONTINUOUS, NAMED_FLAGS, UNIQUE = EnumCheck
1814*cda5da8dSAndroid Build Coastguard Worker
1815*cda5da8dSAndroid Build Coastguard Worker
1816*cda5da8dSAndroid Build Coastguard Workerclass verify:
1817*cda5da8dSAndroid Build Coastguard Worker    """
1818*cda5da8dSAndroid Build Coastguard Worker    Check an enumeration for various constraints. (see EnumCheck)
1819*cda5da8dSAndroid Build Coastguard Worker    """
1820*cda5da8dSAndroid Build Coastguard Worker    def __init__(self, *checks):
1821*cda5da8dSAndroid Build Coastguard Worker        self.checks = checks
1822*cda5da8dSAndroid Build Coastguard Worker    def __call__(self, enumeration):
1823*cda5da8dSAndroid Build Coastguard Worker        checks = self.checks
1824*cda5da8dSAndroid Build Coastguard Worker        cls_name = enumeration.__name__
1825*cda5da8dSAndroid Build Coastguard Worker        if Flag is not None and issubclass(enumeration, Flag):
1826*cda5da8dSAndroid Build Coastguard Worker            enum_type = 'flag'
1827*cda5da8dSAndroid Build Coastguard Worker        elif issubclass(enumeration, Enum):
1828*cda5da8dSAndroid Build Coastguard Worker            enum_type = 'enum'
1829*cda5da8dSAndroid Build Coastguard Worker        else:
1830*cda5da8dSAndroid Build Coastguard Worker            raise TypeError("the 'verify' decorator only works with Enum and Flag")
1831*cda5da8dSAndroid Build Coastguard Worker        for check in checks:
1832*cda5da8dSAndroid Build Coastguard Worker            if check is UNIQUE:
1833*cda5da8dSAndroid Build Coastguard Worker                # check for duplicate names
1834*cda5da8dSAndroid Build Coastguard Worker                duplicates = []
1835*cda5da8dSAndroid Build Coastguard Worker                for name, member in enumeration.__members__.items():
1836*cda5da8dSAndroid Build Coastguard Worker                    if name != member.name:
1837*cda5da8dSAndroid Build Coastguard Worker                        duplicates.append((name, member.name))
1838*cda5da8dSAndroid Build Coastguard Worker                if duplicates:
1839*cda5da8dSAndroid Build Coastguard Worker                    alias_details = ', '.join(
1840*cda5da8dSAndroid Build Coastguard Worker                            ["%s -> %s" % (alias, name) for (alias, name) in duplicates])
1841*cda5da8dSAndroid Build Coastguard Worker                    raise ValueError('aliases found in %r: %s' %
1842*cda5da8dSAndroid Build Coastguard Worker                            (enumeration, alias_details))
1843*cda5da8dSAndroid Build Coastguard Worker            elif check is CONTINUOUS:
1844*cda5da8dSAndroid Build Coastguard Worker                values = set(e.value for e in enumeration)
1845*cda5da8dSAndroid Build Coastguard Worker                if len(values) < 2:
1846*cda5da8dSAndroid Build Coastguard Worker                    continue
1847*cda5da8dSAndroid Build Coastguard Worker                low, high = min(values), max(values)
1848*cda5da8dSAndroid Build Coastguard Worker                missing = []
1849*cda5da8dSAndroid Build Coastguard Worker                if enum_type == 'flag':
1850*cda5da8dSAndroid Build Coastguard Worker                    # check for powers of two
1851*cda5da8dSAndroid Build Coastguard Worker                    for i in range(_high_bit(low)+1, _high_bit(high)):
1852*cda5da8dSAndroid Build Coastguard Worker                        if 2**i not in values:
1853*cda5da8dSAndroid Build Coastguard Worker                            missing.append(2**i)
1854*cda5da8dSAndroid Build Coastguard Worker                elif enum_type == 'enum':
1855*cda5da8dSAndroid Build Coastguard Worker                    # check for powers of one
1856*cda5da8dSAndroid Build Coastguard Worker                    for i in range(low+1, high):
1857*cda5da8dSAndroid Build Coastguard Worker                        if i not in values:
1858*cda5da8dSAndroid Build Coastguard Worker                            missing.append(i)
1859*cda5da8dSAndroid Build Coastguard Worker                else:
1860*cda5da8dSAndroid Build Coastguard Worker                    raise Exception('verify: unknown type %r' % enum_type)
1861*cda5da8dSAndroid Build Coastguard Worker                if missing:
1862*cda5da8dSAndroid Build Coastguard Worker                    raise ValueError(('invalid %s %r: missing values %s' % (
1863*cda5da8dSAndroid Build Coastguard Worker                            enum_type, cls_name, ', '.join((str(m) for m in missing)))
1864*cda5da8dSAndroid Build Coastguard Worker                            )[:256])
1865*cda5da8dSAndroid Build Coastguard Worker                            # limit max length to protect against DOS attacks
1866*cda5da8dSAndroid Build Coastguard Worker            elif check is NAMED_FLAGS:
1867*cda5da8dSAndroid Build Coastguard Worker                # examine each alias and check for unnamed flags
1868*cda5da8dSAndroid Build Coastguard Worker                member_names = enumeration._member_names_
1869*cda5da8dSAndroid Build Coastguard Worker                member_values = [m.value for m in enumeration]
1870*cda5da8dSAndroid Build Coastguard Worker                missing_names = []
1871*cda5da8dSAndroid Build Coastguard Worker                missing_value = 0
1872*cda5da8dSAndroid Build Coastguard Worker                for name, alias in enumeration._member_map_.items():
1873*cda5da8dSAndroid Build Coastguard Worker                    if name in member_names:
1874*cda5da8dSAndroid Build Coastguard Worker                        # not an alias
1875*cda5da8dSAndroid Build Coastguard Worker                        continue
1876*cda5da8dSAndroid Build Coastguard Worker                    if alias.value < 0:
1877*cda5da8dSAndroid Build Coastguard Worker                        # negative numbers are not checked
1878*cda5da8dSAndroid Build Coastguard Worker                        continue
1879*cda5da8dSAndroid Build Coastguard Worker                    values = list(_iter_bits_lsb(alias.value))
1880*cda5da8dSAndroid Build Coastguard Worker                    missed = [v for v in values if v not in member_values]
1881*cda5da8dSAndroid Build Coastguard Worker                    if missed:
1882*cda5da8dSAndroid Build Coastguard Worker                        missing_names.append(name)
1883*cda5da8dSAndroid Build Coastguard Worker                        missing_value |= reduce(_or_, missed)
1884*cda5da8dSAndroid Build Coastguard Worker                if missing_names:
1885*cda5da8dSAndroid Build Coastguard Worker                    if len(missing_names) == 1:
1886*cda5da8dSAndroid Build Coastguard Worker                        alias = 'alias %s is missing' % missing_names[0]
1887*cda5da8dSAndroid Build Coastguard Worker                    else:
1888*cda5da8dSAndroid Build Coastguard Worker                        alias = 'aliases %s and %s are missing' % (
1889*cda5da8dSAndroid Build Coastguard Worker                                ', '.join(missing_names[:-1]), missing_names[-1]
1890*cda5da8dSAndroid Build Coastguard Worker                                )
1891*cda5da8dSAndroid Build Coastguard Worker                    if _is_single_bit(missing_value):
1892*cda5da8dSAndroid Build Coastguard Worker                        value = 'value 0x%x' % missing_value
1893*cda5da8dSAndroid Build Coastguard Worker                    else:
1894*cda5da8dSAndroid Build Coastguard Worker                        value = 'combined values of 0x%x' % missing_value
1895*cda5da8dSAndroid Build Coastguard Worker                    raise ValueError(
1896*cda5da8dSAndroid Build Coastguard Worker                            'invalid Flag %r: %s %s [use enum.show_flag_values(value) for details]'
1897*cda5da8dSAndroid Build Coastguard Worker                            % (cls_name, alias, value)
1898*cda5da8dSAndroid Build Coastguard Worker                            )
1899*cda5da8dSAndroid Build Coastguard Worker        return enumeration
1900*cda5da8dSAndroid Build Coastguard Worker
1901*cda5da8dSAndroid Build Coastguard Workerdef _test_simple_enum(checked_enum, simple_enum):
1902*cda5da8dSAndroid Build Coastguard Worker    """
1903*cda5da8dSAndroid Build Coastguard Worker    A function that can be used to test an enum created with :func:`_simple_enum`
1904*cda5da8dSAndroid Build Coastguard Worker    against the version created by subclassing :class:`Enum`::
1905*cda5da8dSAndroid Build Coastguard Worker
1906*cda5da8dSAndroid Build Coastguard Worker        >>> from enum import Enum, _simple_enum, _test_simple_enum
1907*cda5da8dSAndroid Build Coastguard Worker        >>> @_simple_enum(Enum)
1908*cda5da8dSAndroid Build Coastguard Worker        ... class Color:
1909*cda5da8dSAndroid Build Coastguard Worker        ...     RED = auto()
1910*cda5da8dSAndroid Build Coastguard Worker        ...     GREEN = auto()
1911*cda5da8dSAndroid Build Coastguard Worker        ...     BLUE = auto()
1912*cda5da8dSAndroid Build Coastguard Worker        >>> class CheckedColor(Enum):
1913*cda5da8dSAndroid Build Coastguard Worker        ...     RED = auto()
1914*cda5da8dSAndroid Build Coastguard Worker        ...     GREEN = auto()
1915*cda5da8dSAndroid Build Coastguard Worker        ...     BLUE = auto()
1916*cda5da8dSAndroid Build Coastguard Worker        >>> _test_simple_enum(CheckedColor, Color)
1917*cda5da8dSAndroid Build Coastguard Worker
1918*cda5da8dSAndroid Build Coastguard Worker    If differences are found, a :exc:`TypeError` is raised.
1919*cda5da8dSAndroid Build Coastguard Worker    """
1920*cda5da8dSAndroid Build Coastguard Worker    failed = []
1921*cda5da8dSAndroid Build Coastguard Worker    if checked_enum.__dict__ != simple_enum.__dict__:
1922*cda5da8dSAndroid Build Coastguard Worker        checked_dict = checked_enum.__dict__
1923*cda5da8dSAndroid Build Coastguard Worker        checked_keys = list(checked_dict.keys())
1924*cda5da8dSAndroid Build Coastguard Worker        simple_dict = simple_enum.__dict__
1925*cda5da8dSAndroid Build Coastguard Worker        simple_keys = list(simple_dict.keys())
1926*cda5da8dSAndroid Build Coastguard Worker        member_names = set(
1927*cda5da8dSAndroid Build Coastguard Worker                list(checked_enum._member_map_.keys())
1928*cda5da8dSAndroid Build Coastguard Worker                + list(simple_enum._member_map_.keys())
1929*cda5da8dSAndroid Build Coastguard Worker                )
1930*cda5da8dSAndroid Build Coastguard Worker        for key in set(checked_keys + simple_keys):
1931*cda5da8dSAndroid Build Coastguard Worker            if key in ('__module__', '_member_map_', '_value2member_map_', '__doc__'):
1932*cda5da8dSAndroid Build Coastguard Worker                # keys known to be different, or very long
1933*cda5da8dSAndroid Build Coastguard Worker                continue
1934*cda5da8dSAndroid Build Coastguard Worker            elif key in member_names:
1935*cda5da8dSAndroid Build Coastguard Worker                # members are checked below
1936*cda5da8dSAndroid Build Coastguard Worker                continue
1937*cda5da8dSAndroid Build Coastguard Worker            elif key not in simple_keys:
1938*cda5da8dSAndroid Build Coastguard Worker                failed.append("missing key: %r" % (key, ))
1939*cda5da8dSAndroid Build Coastguard Worker            elif key not in checked_keys:
1940*cda5da8dSAndroid Build Coastguard Worker                failed.append("extra key:   %r" % (key, ))
1941*cda5da8dSAndroid Build Coastguard Worker            else:
1942*cda5da8dSAndroid Build Coastguard Worker                checked_value = checked_dict[key]
1943*cda5da8dSAndroid Build Coastguard Worker                simple_value = simple_dict[key]
1944*cda5da8dSAndroid Build Coastguard Worker                if callable(checked_value) or isinstance(checked_value, bltns.property):
1945*cda5da8dSAndroid Build Coastguard Worker                    continue
1946*cda5da8dSAndroid Build Coastguard Worker                if key == '__doc__':
1947*cda5da8dSAndroid Build Coastguard Worker                    # remove all spaces/tabs
1948*cda5da8dSAndroid Build Coastguard Worker                    compressed_checked_value = checked_value.replace(' ','').replace('\t','')
1949*cda5da8dSAndroid Build Coastguard Worker                    compressed_simple_value = simple_value.replace(' ','').replace('\t','')
1950*cda5da8dSAndroid Build Coastguard Worker                    if compressed_checked_value != compressed_simple_value:
1951*cda5da8dSAndroid Build Coastguard Worker                        failed.append("%r:\n         %s\n         %s" % (
1952*cda5da8dSAndroid Build Coastguard Worker                                key,
1953*cda5da8dSAndroid Build Coastguard Worker                                "checked -> %r" % (checked_value, ),
1954*cda5da8dSAndroid Build Coastguard Worker                                "simple  -> %r" % (simple_value, ),
1955*cda5da8dSAndroid Build Coastguard Worker                                ))
1956*cda5da8dSAndroid Build Coastguard Worker                elif checked_value != simple_value:
1957*cda5da8dSAndroid Build Coastguard Worker                    failed.append("%r:\n         %s\n         %s" % (
1958*cda5da8dSAndroid Build Coastguard Worker                            key,
1959*cda5da8dSAndroid Build Coastguard Worker                            "checked -> %r" % (checked_value, ),
1960*cda5da8dSAndroid Build Coastguard Worker                            "simple  -> %r" % (simple_value, ),
1961*cda5da8dSAndroid Build Coastguard Worker                            ))
1962*cda5da8dSAndroid Build Coastguard Worker        failed.sort()
1963*cda5da8dSAndroid Build Coastguard Worker        for name in member_names:
1964*cda5da8dSAndroid Build Coastguard Worker            failed_member = []
1965*cda5da8dSAndroid Build Coastguard Worker            if name not in simple_keys:
1966*cda5da8dSAndroid Build Coastguard Worker                failed.append('missing member from simple enum: %r' % name)
1967*cda5da8dSAndroid Build Coastguard Worker            elif name not in checked_keys:
1968*cda5da8dSAndroid Build Coastguard Worker                failed.append('extra member in simple enum: %r' % name)
1969*cda5da8dSAndroid Build Coastguard Worker            else:
1970*cda5da8dSAndroid Build Coastguard Worker                checked_member_dict = checked_enum[name].__dict__
1971*cda5da8dSAndroid Build Coastguard Worker                checked_member_keys = list(checked_member_dict.keys())
1972*cda5da8dSAndroid Build Coastguard Worker                simple_member_dict = simple_enum[name].__dict__
1973*cda5da8dSAndroid Build Coastguard Worker                simple_member_keys = list(simple_member_dict.keys())
1974*cda5da8dSAndroid Build Coastguard Worker                for key in set(checked_member_keys + simple_member_keys):
1975*cda5da8dSAndroid Build Coastguard Worker                    if key in ('__module__', '__objclass__', '_inverted_'):
1976*cda5da8dSAndroid Build Coastguard Worker                        # keys known to be different or absent
1977*cda5da8dSAndroid Build Coastguard Worker                        continue
1978*cda5da8dSAndroid Build Coastguard Worker                    elif key not in simple_member_keys:
1979*cda5da8dSAndroid Build Coastguard Worker                        failed_member.append("missing key %r not in the simple enum member %r" % (key, name))
1980*cda5da8dSAndroid Build Coastguard Worker                    elif key not in checked_member_keys:
1981*cda5da8dSAndroid Build Coastguard Worker                        failed_member.append("extra key %r in simple enum member %r" % (key, name))
1982*cda5da8dSAndroid Build Coastguard Worker                    else:
1983*cda5da8dSAndroid Build Coastguard Worker                        checked_value = checked_member_dict[key]
1984*cda5da8dSAndroid Build Coastguard Worker                        simple_value = simple_member_dict[key]
1985*cda5da8dSAndroid Build Coastguard Worker                        if checked_value != simple_value:
1986*cda5da8dSAndroid Build Coastguard Worker                            failed_member.append("%r:\n         %s\n         %s" % (
1987*cda5da8dSAndroid Build Coastguard Worker                                    key,
1988*cda5da8dSAndroid Build Coastguard Worker                                    "checked member -> %r" % (checked_value, ),
1989*cda5da8dSAndroid Build Coastguard Worker                                    "simple member  -> %r" % (simple_value, ),
1990*cda5da8dSAndroid Build Coastguard Worker                                    ))
1991*cda5da8dSAndroid Build Coastguard Worker            if failed_member:
1992*cda5da8dSAndroid Build Coastguard Worker                failed.append('%r member mismatch:\n      %s' % (
1993*cda5da8dSAndroid Build Coastguard Worker                        name, '\n      '.join(failed_member),
1994*cda5da8dSAndroid Build Coastguard Worker                        ))
1995*cda5da8dSAndroid Build Coastguard Worker        for method in (
1996*cda5da8dSAndroid Build Coastguard Worker                '__str__', '__repr__', '__reduce_ex__', '__format__',
1997*cda5da8dSAndroid Build Coastguard Worker                '__getnewargs_ex__', '__getnewargs__', '__reduce_ex__', '__reduce__'
1998*cda5da8dSAndroid Build Coastguard Worker            ):
1999*cda5da8dSAndroid Build Coastguard Worker            if method in simple_keys and method in checked_keys:
2000*cda5da8dSAndroid Build Coastguard Worker                # cannot compare functions, and it exists in both, so we're good
2001*cda5da8dSAndroid Build Coastguard Worker                continue
2002*cda5da8dSAndroid Build Coastguard Worker            elif method not in simple_keys and method not in checked_keys:
2003*cda5da8dSAndroid Build Coastguard Worker                # method is inherited -- check it out
2004*cda5da8dSAndroid Build Coastguard Worker                checked_method = getattr(checked_enum, method, None)
2005*cda5da8dSAndroid Build Coastguard Worker                simple_method = getattr(simple_enum, method, None)
2006*cda5da8dSAndroid Build Coastguard Worker                if hasattr(checked_method, '__func__'):
2007*cda5da8dSAndroid Build Coastguard Worker                    checked_method = checked_method.__func__
2008*cda5da8dSAndroid Build Coastguard Worker                    simple_method = simple_method.__func__
2009*cda5da8dSAndroid Build Coastguard Worker                if checked_method != simple_method:
2010*cda5da8dSAndroid Build Coastguard Worker                    failed.append("%r:  %-30s %s" % (
2011*cda5da8dSAndroid Build Coastguard Worker                            method,
2012*cda5da8dSAndroid Build Coastguard Worker                            "checked -> %r" % (checked_method, ),
2013*cda5da8dSAndroid Build Coastguard Worker                            "simple -> %r" % (simple_method, ),
2014*cda5da8dSAndroid Build Coastguard Worker                            ))
2015*cda5da8dSAndroid Build Coastguard Worker            else:
2016*cda5da8dSAndroid Build Coastguard Worker                # if the method existed in only one of the enums, it will have been caught
2017*cda5da8dSAndroid Build Coastguard Worker                # in the first checks above
2018*cda5da8dSAndroid Build Coastguard Worker                pass
2019*cda5da8dSAndroid Build Coastguard Worker    if failed:
2020*cda5da8dSAndroid Build Coastguard Worker        raise TypeError('enum mismatch:\n   %s' % '\n   '.join(failed))
2021*cda5da8dSAndroid Build Coastguard Worker
2022*cda5da8dSAndroid Build Coastguard Workerdef _old_convert_(etype, name, module, filter, source=None, *, boundary=None):
2023*cda5da8dSAndroid Build Coastguard Worker    """
2024*cda5da8dSAndroid Build Coastguard Worker    Create a new Enum subclass that replaces a collection of global constants
2025*cda5da8dSAndroid Build Coastguard Worker    """
2026*cda5da8dSAndroid Build Coastguard Worker    # convert all constants from source (or module) that pass filter() to
2027*cda5da8dSAndroid Build Coastguard Worker    # a new Enum called name, and export the enum and its members back to
2028*cda5da8dSAndroid Build Coastguard Worker    # module;
2029*cda5da8dSAndroid Build Coastguard Worker    # also, replace the __reduce_ex__ method so unpickling works in
2030*cda5da8dSAndroid Build Coastguard Worker    # previous Python versions
2031*cda5da8dSAndroid Build Coastguard Worker    module_globals = sys.modules[module].__dict__
2032*cda5da8dSAndroid Build Coastguard Worker    if source:
2033*cda5da8dSAndroid Build Coastguard Worker        source = source.__dict__
2034*cda5da8dSAndroid Build Coastguard Worker    else:
2035*cda5da8dSAndroid Build Coastguard Worker        source = module_globals
2036*cda5da8dSAndroid Build Coastguard Worker    # _value2member_map_ is populated in the same order every time
2037*cda5da8dSAndroid Build Coastguard Worker    # for a consistent reverse mapping of number to name when there
2038*cda5da8dSAndroid Build Coastguard Worker    # are multiple names for the same number.
2039*cda5da8dSAndroid Build Coastguard Worker    members = [
2040*cda5da8dSAndroid Build Coastguard Worker            (name, value)
2041*cda5da8dSAndroid Build Coastguard Worker            for name, value in source.items()
2042*cda5da8dSAndroid Build Coastguard Worker            if filter(name)]
2043*cda5da8dSAndroid Build Coastguard Worker    try:
2044*cda5da8dSAndroid Build Coastguard Worker        # sort by value
2045*cda5da8dSAndroid Build Coastguard Worker        members.sort(key=lambda t: (t[1], t[0]))
2046*cda5da8dSAndroid Build Coastguard Worker    except TypeError:
2047*cda5da8dSAndroid Build Coastguard Worker        # unless some values aren't comparable, in which case sort by name
2048*cda5da8dSAndroid Build Coastguard Worker        members.sort(key=lambda t: t[0])
2049*cda5da8dSAndroid Build Coastguard Worker    cls = etype(name, members, module=module, boundary=boundary or KEEP)
2050*cda5da8dSAndroid Build Coastguard Worker    cls.__reduce_ex__ = _reduce_ex_by_global_name
2051*cda5da8dSAndroid Build Coastguard Worker    return cls
2052*cda5da8dSAndroid Build Coastguard Worker
2053*cda5da8dSAndroid Build Coastguard Worker_stdlib_enums = IntEnum, StrEnum, IntFlag
2054