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