1import sys 2from types import MappingProxyType, DynamicClassAttribute 3 4 5__all__ = [ 6 'EnumMeta', 7 'Enum', 'IntEnum', 'Flag', 'IntFlag', 8 'auto', 'unique', 9 ] 10 11 12def _is_descriptor(obj): 13 """ 14 Returns True if obj is a descriptor, False otherwise. 15 """ 16 return ( 17 hasattr(obj, '__get__') or 18 hasattr(obj, '__set__') or 19 hasattr(obj, '__delete__') 20 ) 21 22def _is_dunder(name): 23 """ 24 Returns True if a __dunder__ name, False otherwise. 25 """ 26 return ( 27 len(name) > 4 and 28 name[:2] == name[-2:] == '__' and 29 name[2] != '_' and 30 name[-3] != '_' 31 ) 32 33def _is_sunder(name): 34 """ 35 Returns True if a _sunder_ name, False otherwise. 36 """ 37 return ( 38 len(name) > 2 and 39 name[0] == name[-1] == '_' and 40 name[1:2] != '_' and 41 name[-2:-1] != '_' 42 ) 43 44def _is_private(cls_name, name): 45 # do not use `re` as `re` imports `enum` 46 pattern = '_%s__' % (cls_name, ) 47 pat_len = len(pattern) 48 if ( 49 len(name) > pat_len 50 and name.startswith(pattern) 51 and name[pat_len:pat_len+1] != ['_'] 52 and (name[-1] != '_' or name[-2] != '_') 53 ): 54 return True 55 else: 56 return False 57 58def _make_class_unpicklable(cls): 59 """ 60 Make the given class un-picklable. 61 """ 62 def _break_on_call_reduce(self, proto): 63 raise TypeError('%r cannot be pickled' % self) 64 cls.__reduce_ex__ = _break_on_call_reduce 65 cls.__module__ = '<unknown>' 66 67_auto_null = object() 68class auto: 69 """ 70 Instances are replaced with an appropriate value in Enum class suites. 71 """ 72 value = _auto_null 73 74 75class _EnumDict(dict): 76 """ 77 Track enum member order and ensure member names are not reused. 78 79 EnumMeta will use the names found in self._member_names as the 80 enumeration member names. 81 """ 82 def __init__(self): 83 super().__init__() 84 self._member_names = [] 85 self._last_values = [] 86 self._ignore = [] 87 self._auto_called = False 88 89 def __setitem__(self, key, value): 90 """ 91 Changes anything not dundered or not a descriptor. 92 93 If an enum member name is used twice, an error is raised; duplicate 94 values are not checked for. 95 96 Single underscore (sunder) names are reserved. 97 """ 98 if _is_private(self._cls_name, key): 99 import warnings 100 warnings.warn( 101 "private variables, such as %r, will be normal attributes in 3.11" 102 % (key, ), 103 DeprecationWarning, 104 stacklevel=2, 105 ) 106 if _is_sunder(key): 107 if key not in ( 108 '_order_', '_create_pseudo_member_', 109 '_generate_next_value_', '_missing_', '_ignore_', 110 ): 111 raise ValueError('_names_ are reserved for future Enum use') 112 if key == '_generate_next_value_': 113 # check if members already defined as auto() 114 if self._auto_called: 115 raise TypeError("_generate_next_value_ must be defined before members") 116 setattr(self, '_generate_next_value', value) 117 elif key == '_ignore_': 118 if isinstance(value, str): 119 value = value.replace(',',' ').split() 120 else: 121 value = list(value) 122 self._ignore = value 123 already = set(value) & set(self._member_names) 124 if already: 125 raise ValueError( 126 '_ignore_ cannot specify already set names: %r' 127 % (already, ) 128 ) 129 elif _is_dunder(key): 130 if key == '__order__': 131 key = '_order_' 132 elif key in self._member_names: 133 # descriptor overwriting an enum? 134 raise TypeError('Attempted to reuse key: %r' % key) 135 elif key in self._ignore: 136 pass 137 elif not _is_descriptor(value): 138 if key in self: 139 # enum overwriting a descriptor? 140 raise TypeError('%r already defined as: %r' % (key, self[key])) 141 if isinstance(value, auto): 142 if value.value == _auto_null: 143 value.value = self._generate_next_value( 144 key, 145 1, 146 len(self._member_names), 147 self._last_values[:], 148 ) 149 self._auto_called = True 150 value = value.value 151 self._member_names.append(key) 152 self._last_values.append(value) 153 super().__setitem__(key, value) 154 155 156# Dummy value for Enum as EnumMeta explicitly checks for it, but of course 157# until EnumMeta finishes running the first time the Enum class doesn't exist. 158# This is also why there are checks in EnumMeta like `if Enum is not None` 159Enum = None 160 161class EnumMeta(type): 162 """ 163 Metaclass for Enum 164 """ 165 @classmethod 166 def __prepare__(metacls, cls, bases, **kwds): 167 # check that previous enum members do not exist 168 metacls._check_for_existing_members(cls, bases) 169 # create the namespace dict 170 enum_dict = _EnumDict() 171 enum_dict._cls_name = cls 172 # inherit previous flags and _generate_next_value_ function 173 member_type, first_enum = metacls._get_mixins_(cls, bases) 174 if first_enum is not None: 175 enum_dict['_generate_next_value_'] = getattr( 176 first_enum, '_generate_next_value_', None, 177 ) 178 return enum_dict 179 180 def __new__(metacls, cls, bases, classdict, **kwds): 181 # an Enum class is final once enumeration items have been defined; it 182 # cannot be mixed with other types (int, float, etc.) if it has an 183 # inherited __new__ unless a new __new__ is defined (or the resulting 184 # class will fail). 185 # 186 # remove any keys listed in _ignore_ 187 classdict.setdefault('_ignore_', []).append('_ignore_') 188 ignore = classdict['_ignore_'] 189 for key in ignore: 190 classdict.pop(key, None) 191 member_type, first_enum = metacls._get_mixins_(cls, bases) 192 __new__, save_new, use_args = metacls._find_new_( 193 classdict, member_type, first_enum, 194 ) 195 196 # save enum items into separate mapping so they don't get baked into 197 # the new class 198 enum_members = {k: classdict[k] for k in classdict._member_names} 199 for name in classdict._member_names: 200 del classdict[name] 201 202 # adjust the sunders 203 _order_ = classdict.pop('_order_', None) 204 205 # check for illegal enum names (any others?) 206 invalid_names = set(enum_members) & {'mro', ''} 207 if invalid_names: 208 raise ValueError('Invalid enum member name: {0}'.format( 209 ','.join(invalid_names))) 210 211 # create a default docstring if one has not been provided 212 if '__doc__' not in classdict: 213 classdict['__doc__'] = 'An enumeration.' 214 215 enum_class = super().__new__(metacls, cls, bases, classdict, **kwds) 216 enum_class._member_names_ = [] # names in definition order 217 enum_class._member_map_ = {} # name->value map 218 enum_class._member_type_ = member_type 219 220 # save DynamicClassAttribute attributes from super classes so we know 221 # if we can take the shortcut of storing members in the class dict 222 dynamic_attributes = { 223 k for c in enum_class.mro() 224 for k, v in c.__dict__.items() 225 if isinstance(v, DynamicClassAttribute) 226 } 227 228 # Reverse value->name map for hashable values. 229 enum_class._value2member_map_ = {} 230 231 # If a custom type is mixed into the Enum, and it does not know how 232 # to pickle itself, pickle.dumps will succeed but pickle.loads will 233 # fail. Rather than have the error show up later and possibly far 234 # from the source, sabotage the pickle protocol for this class so 235 # that pickle.dumps also fails. 236 # 237 # However, if the new class implements its own __reduce_ex__, do not 238 # sabotage -- it's on them to make sure it works correctly. We use 239 # __reduce_ex__ instead of any of the others as it is preferred by 240 # pickle over __reduce__, and it handles all pickle protocols. 241 if '__reduce_ex__' not in classdict: 242 if member_type is not object: 243 methods = ('__getnewargs_ex__', '__getnewargs__', 244 '__reduce_ex__', '__reduce__') 245 if not any(m in member_type.__dict__ for m in methods): 246 if '__new__' in classdict: 247 # too late, sabotage 248 _make_class_unpicklable(enum_class) 249 else: 250 # final attempt to verify that pickling would work: 251 # travel mro until __new__ is found, checking for 252 # __reduce__ and friends along the way -- if any of them 253 # are found before/when __new__ is found, pickling should 254 # work 255 sabotage = None 256 for chain in bases: 257 for base in chain.__mro__: 258 if base is object: 259 continue 260 elif any(m in base.__dict__ for m in methods): 261 # found one, we're good 262 sabotage = False 263 break 264 elif '__new__' in base.__dict__: 265 # not good 266 sabotage = True 267 break 268 if sabotage is not None: 269 break 270 if sabotage: 271 _make_class_unpicklable(enum_class) 272 # instantiate them, checking for duplicates as we go 273 # we instantiate first instead of checking for duplicates first in case 274 # a custom __new__ is doing something funky with the values -- such as 275 # auto-numbering ;) 276 for member_name in classdict._member_names: 277 value = enum_members[member_name] 278 if not isinstance(value, tuple): 279 args = (value, ) 280 else: 281 args = value 282 if member_type is tuple: # special case for tuple enums 283 args = (args, ) # wrap it one more time 284 if not use_args: 285 enum_member = __new__(enum_class) 286 if not hasattr(enum_member, '_value_'): 287 enum_member._value_ = value 288 else: 289 enum_member = __new__(enum_class, *args) 290 if not hasattr(enum_member, '_value_'): 291 if member_type is object: 292 enum_member._value_ = value 293 else: 294 enum_member._value_ = member_type(*args) 295 value = enum_member._value_ 296 enum_member._name_ = member_name 297 enum_member.__objclass__ = enum_class 298 enum_member.__init__(*args) 299 # If another member with the same value was already defined, the 300 # new member becomes an alias to the existing one. 301 for name, canonical_member in enum_class._member_map_.items(): 302 if canonical_member._value_ == enum_member._value_: 303 enum_member = canonical_member 304 break 305 else: 306 # Aliases don't appear in member names (only in __members__). 307 enum_class._member_names_.append(member_name) 308 # performance boost for any member that would not shadow 309 # a DynamicClassAttribute 310 if member_name not in dynamic_attributes: 311 setattr(enum_class, member_name, enum_member) 312 # now add to _member_map_ 313 enum_class._member_map_[member_name] = enum_member 314 try: 315 # This may fail if value is not hashable. We can't add the value 316 # to the map, and by-value lookups for this value will be 317 # linear. 318 enum_class._value2member_map_[value] = enum_member 319 except TypeError: 320 pass 321 322 # double check that repr and friends are not the mixin's or various 323 # things break (such as pickle) 324 # however, if the method is defined in the Enum itself, don't replace 325 # it 326 for name in ('__repr__', '__str__', '__format__', '__reduce_ex__'): 327 if name in classdict: 328 continue 329 class_method = getattr(enum_class, name) 330 obj_method = getattr(member_type, name, None) 331 enum_method = getattr(first_enum, name, None) 332 if obj_method is not None and obj_method is class_method: 333 setattr(enum_class, name, enum_method) 334 335 # replace any other __new__ with our own (as long as Enum is not None, 336 # anyway) -- again, this is to support pickle 337 if Enum is not None: 338 # if the user defined their own __new__, save it before it gets 339 # clobbered in case they subclass later 340 if save_new: 341 enum_class.__new_member__ = __new__ 342 enum_class.__new__ = Enum.__new__ 343 344 # py3 support for definition order (helps keep py2/py3 code in sync) 345 if _order_ is not None: 346 if isinstance(_order_, str): 347 _order_ = _order_.replace(',', ' ').split() 348 if _order_ != enum_class._member_names_: 349 raise TypeError('member order does not match _order_') 350 351 return enum_class 352 353 def __bool__(self): 354 """ 355 classes/types should always be True. 356 """ 357 return True 358 359 def __call__(cls, value, names=None, *, module=None, qualname=None, type=None, start=1): 360 """ 361 Either returns an existing member, or creates a new enum class. 362 363 This method is used both when an enum class is given a value to match 364 to an enumeration member (i.e. Color(3)) and for the functional API 365 (i.e. Color = Enum('Color', names='RED GREEN BLUE')). 366 367 When used for the functional API: 368 369 `value` will be the name of the new class. 370 371 `names` should be either a string of white-space/comma delimited names 372 (values will start at `start`), or an iterator/mapping of name, value pairs. 373 374 `module` should be set to the module this class is being created in; 375 if it is not set, an attempt to find that module will be made, but if 376 it fails the class will not be picklable. 377 378 `qualname` should be set to the actual location this class can be found 379 at in its module; by default it is set to the global scope. If this is 380 not correct, unpickling will fail in some circumstances. 381 382 `type`, if set, will be mixed in as the first base class. 383 """ 384 if names is None: # simple value lookup 385 return cls.__new__(cls, value) 386 # otherwise, functional API: we're creating a new Enum type 387 return cls._create_( 388 value, 389 names, 390 module=module, 391 qualname=qualname, 392 type=type, 393 start=start, 394 ) 395 396 def __contains__(cls, obj): 397 if not isinstance(obj, Enum): 398 import warnings 399 warnings.warn( 400 "in 3.12 __contains__ will no longer raise TypeError, but will return True if\n" 401 "obj is a member or a member's value", 402 DeprecationWarning, 403 stacklevel=2, 404 ) 405 raise TypeError( 406 "unsupported operand type(s) for 'in': '%s' and '%s'" % ( 407 type(obj).__qualname__, cls.__class__.__qualname__)) 408 return isinstance(obj, cls) and obj._name_ in cls._member_map_ 409 410 def __delattr__(cls, attr): 411 # nicer error message when someone tries to delete an attribute 412 # (see issue19025). 413 if attr in cls._member_map_: 414 raise AttributeError("%s: cannot delete Enum member." % cls.__name__) 415 super().__delattr__(attr) 416 417 def __dir__(self): 418 return ( 419 ['__class__', '__doc__', '__members__', '__module__'] 420 + self._member_names_ 421 ) 422 423 def __getattr__(cls, name): 424 """ 425 Return the enum member matching `name` 426 427 We use __getattr__ instead of descriptors or inserting into the enum 428 class' __dict__ in order to support `name` and `value` being both 429 properties for enum members (which live in the class' __dict__) and 430 enum members themselves. 431 """ 432 if _is_dunder(name): 433 raise AttributeError(name) 434 try: 435 return cls._member_map_[name] 436 except KeyError: 437 raise AttributeError(name) from None 438 439 def __getitem__(cls, name): 440 return cls._member_map_[name] 441 442 def __iter__(cls): 443 """ 444 Returns members in definition order. 445 """ 446 return (cls._member_map_[name] for name in cls._member_names_) 447 448 def __len__(cls): 449 return len(cls._member_names_) 450 451 @property 452 def __members__(cls): 453 """ 454 Returns a mapping of member name->value. 455 456 This mapping lists all enum members, including aliases. Note that this 457 is a read-only view of the internal mapping. 458 """ 459 return MappingProxyType(cls._member_map_) 460 461 def __repr__(cls): 462 return "<enum %r>" % cls.__name__ 463 464 def __reversed__(cls): 465 """ 466 Returns members in reverse definition order. 467 """ 468 return (cls._member_map_[name] for name in reversed(cls._member_names_)) 469 470 def __setattr__(cls, name, value): 471 """ 472 Block attempts to reassign Enum members. 473 474 A simple assignment to the class namespace only changes one of the 475 several possible ways to get an Enum member from the Enum class, 476 resulting in an inconsistent Enumeration. 477 """ 478 member_map = cls.__dict__.get('_member_map_', {}) 479 if name in member_map: 480 raise AttributeError('Cannot reassign members.') 481 super().__setattr__(name, value) 482 483 def _create_(cls, class_name, names, *, module=None, qualname=None, type=None, start=1): 484 """ 485 Convenience method to create a new Enum class. 486 487 `names` can be: 488 489 * A string containing member names, separated either with spaces or 490 commas. Values are incremented by 1 from `start`. 491 * An iterable of member names. Values are incremented by 1 from `start`. 492 * An iterable of (member name, value) pairs. 493 * A mapping of member name -> value pairs. 494 """ 495 metacls = cls.__class__ 496 bases = (cls, ) if type is None else (type, cls) 497 _, first_enum = cls._get_mixins_(cls, bases) 498 classdict = metacls.__prepare__(class_name, bases) 499 500 # special processing needed for names? 501 if isinstance(names, str): 502 names = names.replace(',', ' ').split() 503 if isinstance(names, (tuple, list)) and names and isinstance(names[0], str): 504 original_names, names = names, [] 505 last_values = [] 506 for count, name in enumerate(original_names): 507 value = first_enum._generate_next_value_(name, start, count, last_values[:]) 508 last_values.append(value) 509 names.append((name, value)) 510 511 # Here, names is either an iterable of (name, value) or a mapping. 512 for item in names: 513 if isinstance(item, str): 514 member_name, member_value = item, names[item] 515 else: 516 member_name, member_value = item 517 classdict[member_name] = member_value 518 enum_class = metacls.__new__(metacls, class_name, bases, classdict) 519 520 # TODO: replace the frame hack if a blessed way to know the calling 521 # module is ever developed 522 if module is None: 523 try: 524 module = sys._getframe(2).f_globals['__name__'] 525 except (AttributeError, ValueError, KeyError): 526 pass 527 if module is None: 528 _make_class_unpicklable(enum_class) 529 else: 530 enum_class.__module__ = module 531 if qualname is not None: 532 enum_class.__qualname__ = qualname 533 534 return enum_class 535 536 def _convert_(cls, name, module, filter, source=None): 537 """ 538 Create a new Enum subclass that replaces a collection of global constants 539 """ 540 # convert all constants from source (or module) that pass filter() to 541 # a new Enum called name, and export the enum and its members back to 542 # module; 543 # also, replace the __reduce_ex__ method so unpickling works in 544 # previous Python versions 545 module_globals = vars(sys.modules[module]) 546 if source: 547 source = vars(source) 548 else: 549 source = module_globals 550 # _value2member_map_ is populated in the same order every time 551 # for a consistent reverse mapping of number to name when there 552 # are multiple names for the same number. 553 members = [ 554 (name, value) 555 for name, value in source.items() 556 if filter(name)] 557 try: 558 # sort by value 559 members.sort(key=lambda t: (t[1], t[0])) 560 except TypeError: 561 # unless some values aren't comparable, in which case sort by name 562 members.sort(key=lambda t: t[0]) 563 cls = cls(name, members, module=module) 564 cls.__reduce_ex__ = _reduce_ex_by_name 565 module_globals.update(cls.__members__) 566 module_globals[name] = cls 567 return cls 568 569 @staticmethod 570 def _check_for_existing_members(class_name, bases): 571 for chain in bases: 572 for base in chain.__mro__: 573 if issubclass(base, Enum) and base._member_names_: 574 raise TypeError( 575 "%s: cannot extend enumeration %r" 576 % (class_name, base.__name__) 577 ) 578 579 @staticmethod 580 def _get_mixins_(class_name, bases): 581 """ 582 Returns the type for creating enum members, and the first inherited 583 enum class. 584 585 bases: the tuple of bases that was given to __new__ 586 """ 587 if not bases: 588 return object, Enum 589 590 def _find_data_type(bases): 591 data_types = set() 592 for chain in bases: 593 candidate = None 594 for base in chain.__mro__: 595 if base is object: 596 continue 597 elif issubclass(base, Enum): 598 if base._member_type_ is not object: 599 data_types.add(base._member_type_) 600 break 601 elif '__new__' in base.__dict__: 602 if issubclass(base, Enum): 603 continue 604 data_types.add(candidate or base) 605 break 606 else: 607 candidate = candidate or base 608 if len(data_types) > 1: 609 raise TypeError('%r: too many data types: %r' % (class_name, data_types)) 610 elif data_types: 611 return data_types.pop() 612 else: 613 return None 614 615 # ensure final parent class is an Enum derivative, find any concrete 616 # data type, and check that Enum has no members 617 first_enum = bases[-1] 618 if not issubclass(first_enum, Enum): 619 raise TypeError("new enumerations should be created as " 620 "`EnumName([mixin_type, ...] [data_type,] enum_type)`") 621 member_type = _find_data_type(bases) or object 622 if first_enum._member_names_: 623 raise TypeError("Cannot extend enumerations") 624 return member_type, first_enum 625 626 @staticmethod 627 def _find_new_(classdict, member_type, first_enum): 628 """ 629 Returns the __new__ to be used for creating the enum members. 630 631 classdict: the class dictionary given to __new__ 632 member_type: the data type whose __new__ will be used by default 633 first_enum: enumeration to check for an overriding __new__ 634 """ 635 # now find the correct __new__, checking to see of one was defined 636 # by the user; also check earlier enum classes in case a __new__ was 637 # saved as __new_member__ 638 __new__ = classdict.get('__new__', None) 639 640 # should __new__ be saved as __new_member__ later? 641 save_new = __new__ is not None 642 643 if __new__ is None: 644 # check all possibles for __new_member__ before falling back to 645 # __new__ 646 for method in ('__new_member__', '__new__'): 647 for possible in (member_type, first_enum): 648 target = getattr(possible, method, None) 649 if target not in { 650 None, 651 None.__new__, 652 object.__new__, 653 Enum.__new__, 654 }: 655 __new__ = target 656 break 657 if __new__ is not None: 658 break 659 else: 660 __new__ = object.__new__ 661 662 # if a non-object.__new__ is used then whatever value/tuple was 663 # assigned to the enum member name will be passed to __new__ and to the 664 # new enum member's __init__ 665 if __new__ is object.__new__: 666 use_args = False 667 else: 668 use_args = True 669 return __new__, save_new, use_args 670 671 672class Enum(metaclass=EnumMeta): 673 """ 674 Generic enumeration. 675 676 Derive from this class to define new enumerations. 677 """ 678 def __new__(cls, value): 679 # all enum instances are actually created during class construction 680 # without calling this method; this method is called by the metaclass' 681 # __call__ (i.e. Color(3) ), and by pickle 682 if type(value) is cls: 683 # For lookups like Color(Color.RED) 684 return value 685 # by-value search for a matching enum member 686 # see if it's in the reverse mapping (for hashable values) 687 try: 688 return cls._value2member_map_[value] 689 except KeyError: 690 # Not found, no need to do long O(n) search 691 pass 692 except TypeError: 693 # not there, now do long search -- O(n) behavior 694 for member in cls._member_map_.values(): 695 if member._value_ == value: 696 return member 697 # still not found -- try _missing_ hook 698 try: 699 exc = None 700 result = cls._missing_(value) 701 except Exception as e: 702 exc = e 703 result = None 704 try: 705 if isinstance(result, cls): 706 return result 707 else: 708 ve_exc = ValueError("%r is not a valid %s" % (value, cls.__qualname__)) 709 if result is None and exc is None: 710 raise ve_exc 711 elif exc is None: 712 exc = TypeError( 713 'error in %s._missing_: returned %r instead of None or a valid member' 714 % (cls.__name__, result) 715 ) 716 if not isinstance(exc, ValueError): 717 exc.__context__ = ve_exc 718 raise exc 719 finally: 720 # ensure all variables that could hold an exception are destroyed 721 exc = None 722 ve_exc = None 723 724 def _generate_next_value_(name, start, count, last_values): 725 """ 726 Generate the next value when not given. 727 728 name: the name of the member 729 start: the initial start value or None 730 count: the number of existing members 731 last_value: the last value assigned or None 732 """ 733 for last_value in reversed(last_values): 734 try: 735 return last_value + 1 736 except TypeError: 737 pass 738 else: 739 return start 740 741 @classmethod 742 def _missing_(cls, value): 743 return None 744 745 def __repr__(self): 746 return "<%s.%s: %r>" % ( 747 self.__class__.__name__, self._name_, self._value_) 748 749 def __str__(self): 750 return "%s.%s" % (self.__class__.__name__, self._name_) 751 752 def __dir__(self): 753 """ 754 Returns all members and all public methods 755 """ 756 added_behavior = [ 757 m 758 for cls in self.__class__.mro() 759 for m in cls.__dict__ 760 if m[0] != '_' and m not in self._member_map_ 761 ] + [m for m in self.__dict__ if m[0] != '_'] 762 return (['__class__', '__doc__', '__module__'] + added_behavior) 763 764 def __format__(self, format_spec): 765 """ 766 Returns format using actual value type unless __str__ has been overridden. 767 """ 768 # mixed-in Enums should use the mixed-in type's __format__, otherwise 769 # we can get strange results with the Enum name showing up instead of 770 # the value 771 772 # pure Enum branch, or branch with __str__ explicitly overridden 773 str_overridden = type(self).__str__ not in (Enum.__str__, Flag.__str__) 774 if self._member_type_ is object or str_overridden: 775 cls = str 776 val = str(self) 777 # mix-in branch 778 else: 779 cls = self._member_type_ 780 val = self._value_ 781 return cls.__format__(val, format_spec) 782 783 def __hash__(self): 784 return hash(self._name_) 785 786 def __reduce_ex__(self, proto): 787 return self.__class__, (self._value_, ) 788 789 # DynamicClassAttribute is used to provide access to the `name` and 790 # `value` properties of enum members while keeping some measure of 791 # protection from modification, while still allowing for an enumeration 792 # to have members named `name` and `value`. This works because enumeration 793 # members are not set directly on the enum class -- __getattr__ is 794 # used to look them up. 795 796 @DynamicClassAttribute 797 def name(self): 798 """The name of the Enum member.""" 799 return self._name_ 800 801 @DynamicClassAttribute 802 def value(self): 803 """The value of the Enum member.""" 804 return self._value_ 805 806 807class IntEnum(int, Enum): 808 """Enum where members are also (and must be) ints""" 809 810 811def _reduce_ex_by_name(self, proto): 812 return self.name 813 814class Flag(Enum): 815 """ 816 Support for flags 817 """ 818 819 def _generate_next_value_(name, start, count, last_values): 820 """ 821 Generate the next value when not given. 822 823 name: the name of the member 824 start: the initial start value or None 825 count: the number of existing members 826 last_value: the last value assigned or None 827 """ 828 if not count: 829 return start if start is not None else 1 830 for last_value in reversed(last_values): 831 try: 832 high_bit = _high_bit(last_value) 833 break 834 except Exception: 835 raise TypeError('Invalid Flag value: %r' % last_value) from None 836 return 2 ** (high_bit+1) 837 838 @classmethod 839 def _missing_(cls, value): 840 """ 841 Returns member (possibly creating it) if one can be found for value. 842 """ 843 original_value = value 844 if value < 0: 845 value = ~value 846 possible_member = cls._create_pseudo_member_(value) 847 if original_value < 0: 848 possible_member = ~possible_member 849 return possible_member 850 851 @classmethod 852 def _create_pseudo_member_(cls, value): 853 """ 854 Create a composite member iff value contains only members. 855 """ 856 pseudo_member = cls._value2member_map_.get(value, None) 857 if pseudo_member is None: 858 # verify all bits are accounted for 859 _, extra_flags = _decompose(cls, value) 860 if extra_flags: 861 raise ValueError("%r is not a valid %s" % (value, cls.__qualname__)) 862 # construct a singleton enum pseudo-member 863 pseudo_member = object.__new__(cls) 864 pseudo_member._name_ = None 865 pseudo_member._value_ = value 866 # use setdefault in case another thread already created a composite 867 # with this value 868 pseudo_member = cls._value2member_map_.setdefault(value, pseudo_member) 869 return pseudo_member 870 871 def __contains__(self, other): 872 """ 873 Returns True if self has at least the same flags set as other. 874 """ 875 if not isinstance(other, self.__class__): 876 raise TypeError( 877 "unsupported operand type(s) for 'in': '%s' and '%s'" % ( 878 type(other).__qualname__, self.__class__.__qualname__)) 879 return other._value_ & self._value_ == other._value_ 880 881 def __repr__(self): 882 cls = self.__class__ 883 if self._name_ is not None: 884 return '<%s.%s: %r>' % (cls.__name__, self._name_, self._value_) 885 members, uncovered = _decompose(cls, self._value_) 886 return '<%s.%s: %r>' % ( 887 cls.__name__, 888 '|'.join([str(m._name_ or m._value_) for m in members]), 889 self._value_, 890 ) 891 892 def __str__(self): 893 cls = self.__class__ 894 if self._name_ is not None: 895 return '%s.%s' % (cls.__name__, self._name_) 896 members, uncovered = _decompose(cls, self._value_) 897 if len(members) == 1 and members[0]._name_ is None: 898 return '%s.%r' % (cls.__name__, members[0]._value_) 899 else: 900 return '%s.%s' % ( 901 cls.__name__, 902 '|'.join([str(m._name_ or m._value_) for m in members]), 903 ) 904 905 def __bool__(self): 906 return bool(self._value_) 907 908 def __or__(self, other): 909 if not isinstance(other, self.__class__): 910 return NotImplemented 911 return self.__class__(self._value_ | other._value_) 912 913 def __and__(self, other): 914 if not isinstance(other, self.__class__): 915 return NotImplemented 916 return self.__class__(self._value_ & other._value_) 917 918 def __xor__(self, other): 919 if not isinstance(other, self.__class__): 920 return NotImplemented 921 return self.__class__(self._value_ ^ other._value_) 922 923 def __invert__(self): 924 members, uncovered = _decompose(self.__class__, self._value_) 925 inverted = self.__class__(0) 926 for m in self.__class__: 927 if m not in members and not (m._value_ & self._value_): 928 inverted = inverted | m 929 return self.__class__(inverted) 930 931 932class IntFlag(int, Flag): 933 """ 934 Support for integer-based Flags 935 """ 936 937 @classmethod 938 def _missing_(cls, value): 939 """ 940 Returns member (possibly creating it) if one can be found for value. 941 """ 942 if not isinstance(value, int): 943 raise ValueError("%r is not a valid %s" % (value, cls.__qualname__)) 944 new_member = cls._create_pseudo_member_(value) 945 return new_member 946 947 @classmethod 948 def _create_pseudo_member_(cls, value): 949 """ 950 Create a composite member iff value contains only members. 951 """ 952 pseudo_member = cls._value2member_map_.get(value, None) 953 if pseudo_member is None: 954 need_to_create = [value] 955 # get unaccounted for bits 956 _, extra_flags = _decompose(cls, value) 957 # timer = 10 958 while extra_flags: 959 # timer -= 1 960 bit = _high_bit(extra_flags) 961 flag_value = 2 ** bit 962 if (flag_value not in cls._value2member_map_ and 963 flag_value not in need_to_create 964 ): 965 need_to_create.append(flag_value) 966 if extra_flags == -flag_value: 967 extra_flags = 0 968 else: 969 extra_flags ^= flag_value 970 for value in reversed(need_to_create): 971 # construct singleton pseudo-members 972 pseudo_member = int.__new__(cls, value) 973 pseudo_member._name_ = None 974 pseudo_member._value_ = value 975 # use setdefault in case another thread already created a composite 976 # with this value 977 pseudo_member = cls._value2member_map_.setdefault(value, pseudo_member) 978 return pseudo_member 979 980 def __or__(self, other): 981 if not isinstance(other, (self.__class__, int)): 982 return NotImplemented 983 result = self.__class__(self._value_ | self.__class__(other)._value_) 984 return result 985 986 def __and__(self, other): 987 if not isinstance(other, (self.__class__, int)): 988 return NotImplemented 989 return self.__class__(self._value_ & self.__class__(other)._value_) 990 991 def __xor__(self, other): 992 if not isinstance(other, (self.__class__, int)): 993 return NotImplemented 994 return self.__class__(self._value_ ^ self.__class__(other)._value_) 995 996 __ror__ = __or__ 997 __rand__ = __and__ 998 __rxor__ = __xor__ 999 1000 def __invert__(self): 1001 result = self.__class__(~self._value_) 1002 return result 1003 1004 1005def _high_bit(value): 1006 """ 1007 returns index of highest bit, or -1 if value is zero or negative 1008 """ 1009 return value.bit_length() - 1 1010 1011def unique(enumeration): 1012 """ 1013 Class decorator for enumerations ensuring unique member values. 1014 """ 1015 duplicates = [] 1016 for name, member in enumeration.__members__.items(): 1017 if name != member.name: 1018 duplicates.append((name, member.name)) 1019 if duplicates: 1020 alias_details = ', '.join( 1021 ["%s -> %s" % (alias, name) for (alias, name) in duplicates]) 1022 raise ValueError('duplicate values found in %r: %s' % 1023 (enumeration, alias_details)) 1024 return enumeration 1025 1026def _decompose(flag, value): 1027 """ 1028 Extract all members from the value. 1029 """ 1030 # _decompose is only called if the value is not named 1031 not_covered = value 1032 negative = value < 0 1033 members = [] 1034 for member in flag: 1035 member_value = member.value 1036 if member_value and member_value & value == member_value: 1037 members.append(member) 1038 not_covered &= ~member_value 1039 if not negative: 1040 tmp = not_covered 1041 while tmp: 1042 flag_value = 2 ** _high_bit(tmp) 1043 if flag_value in flag._value2member_map_: 1044 members.append(flag._value2member_map_[flag_value]) 1045 not_covered &= ~flag_value 1046 tmp &= ~flag_value 1047 if not members and value in flag._value2member_map_: 1048 members.append(flag._value2member_map_[value]) 1049 members.sort(key=lambda m: m._value_, reverse=True) 1050 if len(members) > 1 and members[0].value == value: 1051 # we have the breakdown, don't need the value member itself 1052 members.pop(0) 1053 return members, not_covered 1054