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