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