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