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