1"""Python Enumerations""" 2 3import sys as _sys 4 5__all__ = ['Enum', 'IntEnum', 'unique'] 6 7version = 1, 1, 6 8 9pyver = float('%s.%s' % _sys.version_info[:2]) 10 11try: 12 any 13except NameError: 14 def any(iterable): 15 for element in iterable: 16 if element: 17 return True 18 return False 19 20try: 21 from collections import OrderedDict 22except ImportError: 23 OrderedDict = None 24 25try: 26 basestring 27except NameError: 28 # In Python 2 basestring is the ancestor of both str and unicode 29 # in Python 3 it's just str, but was missing in 3.1 30 basestring = str 31 32try: 33 unicode 34except NameError: 35 # In Python 3 unicode no longer exists (it's just str) 36 unicode = str 37 38class _RouteClassAttributeToGetattr(object): 39 """Route attribute access on a class to __getattr__. 40 41 This is a descriptor, used to define attributes that act differently when 42 accessed through an instance and through a class. Instance access remains 43 normal, but access to an attribute through a class will be routed to the 44 class's __getattr__ method; this is done by raising AttributeError. 45 46 """ 47 def __init__(self, fget=None): 48 self.fget = fget 49 50 def __get__(self, instance, ownerclass=None): 51 if instance is None: 52 raise AttributeError() 53 return self.fget(instance) 54 55 def __set__(self, instance, value): 56 raise AttributeError("can't set attribute") 57 58 def __delete__(self, instance): 59 raise AttributeError("can't delete attribute") 60 61 62def _is_descriptor(obj): 63 """Returns True if obj is a descriptor, False otherwise.""" 64 return ( 65 hasattr(obj, '__get__') or 66 hasattr(obj, '__set__') or 67 hasattr(obj, '__delete__')) 68 69 70def _is_dunder(name): 71 """Returns True if a __dunder__ name, False otherwise.""" 72 return (name[:2] == name[-2:] == '__' and 73 name[2:3] != '_' and 74 name[-3:-2] != '_' and 75 len(name) > 4) 76 77 78def _is_sunder(name): 79 """Returns True if a _sunder_ name, False otherwise.""" 80 return (name[0] == name[-1] == '_' and 81 name[1:2] != '_' and 82 name[-2:-1] != '_' and 83 len(name) > 2) 84 85 86def _make_class_unpicklable(cls): 87 """Make the given class un-picklable.""" 88 def _break_on_call_reduce(self, protocol=None): 89 raise TypeError('%r cannot be pickled' % self) 90 cls.__reduce_ex__ = _break_on_call_reduce 91 cls.__module__ = '<unknown>' 92 93 94class _EnumDict(dict): 95 """Track enum member order and ensure member names are not reused. 96 97 EnumMeta will use the names found in self._member_names as the 98 enumeration member names. 99 100 """ 101 def __init__(self): 102 super(_EnumDict, self).__init__() 103 self._member_names = [] 104 105 def __setitem__(self, key, value): 106 """Changes anything not dundered or not a descriptor. 107 108 If a descriptor is added with the same name as an enum member, the name 109 is removed from _member_names (this may leave a hole in the numerical 110 sequence of values). 111 112 If an enum member name is used twice, an error is raised; duplicate 113 values are not checked for. 114 115 Single underscore (sunder) names are reserved. 116 117 Note: in 3.x __order__ is simply discarded as a not necessary piece 118 leftover from 2.x 119 120 """ 121 if pyver >= 3.0 and key in ('_order_', '__order__'): 122 return 123 elif key == '__order__': 124 key = '_order_' 125 if _is_sunder(key): 126 if key != '_order_': 127 raise ValueError('_names_ are reserved for future Enum use') 128 elif _is_dunder(key): 129 pass 130 elif key in self._member_names: 131 # descriptor overwriting an enum? 132 raise TypeError('Attempted to reuse key: %r' % key) 133 elif not _is_descriptor(value): 134 if key in self: 135 # enum overwriting a descriptor? 136 raise TypeError('Key already defined as: %r' % self[key]) 137 self._member_names.append(key) 138 super(_EnumDict, self).__setitem__(key, value) 139 140 141# Dummy value for Enum as EnumMeta explicity checks for it, but of course until 142# EnumMeta finishes running the first time the Enum class doesn't exist. This 143# is also why there are checks in EnumMeta like `if Enum is not None` 144Enum = None 145 146 147class EnumMeta(type): 148 """Metaclass for Enum""" 149 @classmethod 150 def __prepare__(metacls, cls, bases): 151 return _EnumDict() 152 153 def __new__(metacls, cls, bases, classdict): 154 # an Enum class is final once enumeration items have been defined; it 155 # cannot be mixed with other types (int, float, etc.) if it has an 156 # inherited __new__ unless a new __new__ is defined (or the resulting 157 # class will fail). 158 if type(classdict) is dict: 159 original_dict = classdict 160 classdict = _EnumDict() 161 for k, v in original_dict.items(): 162 classdict[k] = v 163 164 member_type, first_enum = metacls._get_mixins_(bases) 165 __new__, save_new, use_args = metacls._find_new_(classdict, member_type, 166 first_enum) 167 # save enum items into separate mapping so they don't get baked into 168 # the new class 169 members = dict((k, classdict[k]) for k in classdict._member_names) 170 for name in classdict._member_names: 171 del classdict[name] 172 173 # py2 support for definition order 174 _order_ = classdict.get('_order_') 175 if _order_ is None: 176 if pyver < 3.0: 177 try: 178 _order_ = [name for (name, value) in sorted(members.items(), key=lambda item: item[1])] 179 except TypeError: 180 _order_ = [name for name in sorted(members.keys())] 181 else: 182 _order_ = classdict._member_names 183 else: 184 del classdict['_order_'] 185 if pyver < 3.0: 186 _order_ = _order_.replace(',', ' ').split() 187 aliases = [name for name in members if name not in _order_] 188 _order_ += aliases 189 190 # check for illegal enum names (any others?) 191 invalid_names = set(members) & set(['mro']) 192 if invalid_names: 193 raise ValueError('Invalid enum member name(s): %s' % ( 194 ', '.join(invalid_names), )) 195 196 # save attributes from super classes so we know if we can take 197 # the shortcut of storing members in the class dict 198 base_attributes = set([a for b in bases for a in b.__dict__]) 199 # create our new Enum type 200 enum_class = super(EnumMeta, metacls).__new__(metacls, cls, bases, classdict) 201 enum_class._member_names_ = [] # names in random order 202 if OrderedDict is not None: 203 enum_class._member_map_ = OrderedDict() 204 else: 205 enum_class._member_map_ = {} # name->value map 206 enum_class._member_type_ = member_type 207 208 # Reverse value->name map for hashable values. 209 enum_class._value2member_map_ = {} 210 211 # instantiate them, checking for duplicates as we go 212 # we instantiate first instead of checking for duplicates first in case 213 # a custom __new__ is doing something funky with the values -- such as 214 # auto-numbering ;) 215 if __new__ is None: 216 __new__ = enum_class.__new__ 217 for member_name in _order_: 218 value = members[member_name] 219 if not isinstance(value, tuple): 220 args = (value, ) 221 else: 222 args = value 223 if member_type is tuple: # special case for tuple enums 224 args = (args, ) # wrap it one more time 225 if not use_args or not args: 226 enum_member = __new__(enum_class) 227 if not hasattr(enum_member, '_value_'): 228 enum_member._value_ = value 229 else: 230 enum_member = __new__(enum_class, *args) 231 if not hasattr(enum_member, '_value_'): 232 enum_member._value_ = member_type(*args) 233 value = enum_member._value_ 234 enum_member._name_ = member_name 235 enum_member.__objclass__ = enum_class 236 enum_member.__init__(*args) 237 # If another member with the same value was already defined, the 238 # new member becomes an alias to the existing one. 239 for name, canonical_member in enum_class._member_map_.items(): 240 if canonical_member.value == enum_member._value_: 241 enum_member = canonical_member 242 break 243 else: 244 # Aliases don't appear in member names (only in __members__). 245 enum_class._member_names_.append(member_name) 246 # performance boost for any member that would not shadow 247 # a DynamicClassAttribute (aka _RouteClassAttributeToGetattr) 248 if member_name not in base_attributes: 249 setattr(enum_class, member_name, enum_member) 250 # now add to _member_map_ 251 enum_class._member_map_[member_name] = enum_member 252 try: 253 # This may fail if value is not hashable. We can't add the value 254 # to the map, and by-value lookups for this value will be 255 # linear. 256 enum_class._value2member_map_[value] = enum_member 257 except TypeError: 258 pass 259 260 261 # If a custom type is mixed into the Enum, and it does not know how 262 # to pickle itself, pickle.dumps will succeed but pickle.loads will 263 # fail. Rather than have the error show up later and possibly far 264 # from the source, sabotage the pickle protocol for this class so 265 # that pickle.dumps also fails. 266 # 267 # However, if the new class implements its own __reduce_ex__, do not 268 # sabotage -- it's on them to make sure it works correctly. We use 269 # __reduce_ex__ instead of any of the others as it is preferred by 270 # pickle over __reduce__, and it handles all pickle protocols. 271 unpicklable = False 272 if '__reduce_ex__' not in classdict: 273 if member_type is not object: 274 methods = ('__getnewargs_ex__', '__getnewargs__', 275 '__reduce_ex__', '__reduce__') 276 if not any(m in member_type.__dict__ for m in methods): 277 _make_class_unpicklable(enum_class) 278 unpicklable = True 279 280 281 # double check that repr and friends are not the mixin's or various 282 # things break (such as pickle) 283 for name in ('__repr__', '__str__', '__format__', '__reduce_ex__'): 284 class_method = getattr(enum_class, name) 285 obj_method = getattr(member_type, name, None) 286 enum_method = getattr(first_enum, name, None) 287 if name not in classdict and class_method is not enum_method: 288 if name == '__reduce_ex__' and unpicklable: 289 continue 290 setattr(enum_class, name, enum_method) 291 292 # method resolution and int's are not playing nice 293 # Python's less than 2.6 use __cmp__ 294 295 if pyver < 2.6: 296 297 if issubclass(enum_class, int): 298 setattr(enum_class, '__cmp__', getattr(int, '__cmp__')) 299 300 elif pyver < 3.0: 301 302 if issubclass(enum_class, int): 303 for method in ( 304 '__le__', 305 '__lt__', 306 '__gt__', 307 '__ge__', 308 '__eq__', 309 '__ne__', 310 '__hash__', 311 ): 312 setattr(enum_class, method, getattr(int, method)) 313 314 # replace any other __new__ with our own (as long as Enum is not None, 315 # anyway) -- again, this is to support pickle 316 if Enum is not None: 317 # if the user defined their own __new__, save it before it gets 318 # clobbered in case they subclass later 319 if save_new: 320 setattr(enum_class, '__member_new__', enum_class.__dict__['__new__']) 321 setattr(enum_class, '__new__', Enum.__dict__['__new__']) 322 return enum_class 323 324 def __bool__(cls): 325 """ 326 classes/types should always be True. 327 """ 328 return True 329 330 def __call__(cls, value, names=None, module=None, type=None, start=1): 331 """Either returns an existing member, or creates a new enum class. 332 333 This method is used both when an enum class is given a value to match 334 to an enumeration member (i.e. Color(3)) and for the functional API 335 (i.e. Color = Enum('Color', names='red green blue')). 336 337 When used for the functional API: `module`, if set, will be stored in 338 the new class' __module__ attribute; `type`, if set, will be mixed in 339 as the first base class. 340 341 Note: if `module` is not set this routine will attempt to discover the 342 calling module by walking the frame stack; if this is unsuccessful 343 the resulting class will not be pickleable. 344 345 """ 346 if names is None: # simple value lookup 347 return cls.__new__(cls, value) 348 # otherwise, functional API: we're creating a new Enum type 349 return cls._create_(value, names, module=module, type=type, start=start) 350 351 def __contains__(cls, member): 352 return isinstance(member, cls) and member.name in cls._member_map_ 353 354 def __delattr__(cls, attr): 355 # nicer error message when someone tries to delete an attribute 356 # (see issue19025). 357 if attr in cls._member_map_: 358 raise AttributeError( 359 "%s: cannot delete Enum member." % cls.__name__) 360 super(EnumMeta, cls).__delattr__(attr) 361 362 def __dir__(self): 363 return (['__class__', '__doc__', '__members__', '__module__'] + 364 self._member_names_) 365 366 @property 367 def __members__(cls): 368 """Returns a mapping of member name->value. 369 370 This mapping lists all enum members, including aliases. Note that this 371 is a copy of the internal mapping. 372 373 """ 374 return cls._member_map_.copy() 375 376 def __getattr__(cls, name): 377 """Return the enum member matching `name` 378 379 We use __getattr__ instead of descriptors or inserting into the enum 380 class' __dict__ in order to support `name` and `value` being both 381 properties for enum members (which live in the class' __dict__) and 382 enum members themselves. 383 384 """ 385 if _is_dunder(name): 386 raise AttributeError(name) 387 try: 388 return cls._member_map_[name] 389 except KeyError: 390 raise AttributeError(name) 391 392 def __getitem__(cls, name): 393 return cls._member_map_[name] 394 395 def __iter__(cls): 396 return (cls._member_map_[name] for name in cls._member_names_) 397 398 def __reversed__(cls): 399 return (cls._member_map_[name] for name in reversed(cls._member_names_)) 400 401 def __len__(cls): 402 return len(cls._member_names_) 403 404 __nonzero__ = __bool__ 405 406 def __repr__(cls): 407 return "<enum %r>" % cls.__name__ 408 409 def __setattr__(cls, name, value): 410 """Block attempts to reassign Enum members. 411 412 A simple assignment to the class namespace only changes one of the 413 several possible ways to get an Enum member from the Enum class, 414 resulting in an inconsistent Enumeration. 415 416 """ 417 member_map = cls.__dict__.get('_member_map_', {}) 418 if name in member_map: 419 raise AttributeError('Cannot reassign members.') 420 super(EnumMeta, cls).__setattr__(name, value) 421 422 def _create_(cls, class_name, names=None, module=None, type=None, start=1): 423 """Convenience method to create a new Enum class. 424 425 `names` can be: 426 427 * A string containing member names, separated either with spaces or 428 commas. Values are auto-numbered from 1. 429 * An iterable of member names. Values are auto-numbered from 1. 430 * An iterable of (member name, value) pairs. 431 * A mapping of member name -> value. 432 433 """ 434 if pyver < 3.0: 435 # if class_name is unicode, attempt a conversion to ASCII 436 if isinstance(class_name, unicode): 437 try: 438 class_name = class_name.encode('ascii') 439 except UnicodeEncodeError: 440 raise TypeError('%r is not representable in ASCII' % class_name) 441 metacls = cls.__class__ 442 if type is None: 443 bases = (cls, ) 444 else: 445 bases = (type, cls) 446 classdict = metacls.__prepare__(class_name, bases) 447 _order_ = [] 448 449 # special processing needed for names? 450 if isinstance(names, basestring): 451 names = names.replace(',', ' ').split() 452 if isinstance(names, (tuple, list)) and isinstance(names[0], basestring): 453 names = [(e, i+start) for (i, e) in enumerate(names)] 454 455 # Here, names is either an iterable of (name, value) or a mapping. 456 item = None # in case names is empty 457 for item in names: 458 if isinstance(item, basestring): 459 member_name, member_value = item, names[item] 460 else: 461 member_name, member_value = item 462 classdict[member_name] = member_value 463 _order_.append(member_name) 464 # only set _order_ in classdict if name/value was not from a mapping 465 if not isinstance(item, basestring): 466 classdict['_order_'] = ' '.join(_order_) 467 enum_class = metacls.__new__(metacls, class_name, bases, classdict) 468 469 # TODO: replace the frame hack if a blessed way to know the calling 470 # module is ever developed 471 if module is None: 472 try: 473 module = _sys._getframe(2).f_globals['__name__'] 474 except (AttributeError, ValueError): 475 pass 476 if module is None: 477 _make_class_unpicklable(enum_class) 478 else: 479 enum_class.__module__ = module 480 481 return enum_class 482 483 @staticmethod 484 def _get_mixins_(bases): 485 """Returns the type for creating enum members, and the first inherited 486 enum class. 487 488 bases: the tuple of bases that was given to __new__ 489 490 """ 491 if not bases or Enum is None: 492 return object, Enum 493 494 495 # double check that we are not subclassing a class with existing 496 # enumeration members; while we're at it, see if any other data 497 # type has been mixed in so we can use the correct __new__ 498 member_type = first_enum = None 499 for base in bases: 500 if (base is not Enum and 501 issubclass(base, Enum) and 502 base._member_names_): 503 raise TypeError("Cannot extend enumerations") 504 # base is now the last base in bases 505 if not issubclass(base, Enum): 506 raise TypeError("new enumerations must be created as " 507 "`ClassName([mixin_type,] enum_type)`") 508 509 # get correct mix-in type (either mix-in type of Enum subclass, or 510 # first base if last base is Enum) 511 if not issubclass(bases[0], Enum): 512 member_type = bases[0] # first data type 513 first_enum = bases[-1] # enum type 514 else: 515 for base in bases[0].__mro__: 516 # most common: (IntEnum, int, Enum, object) 517 # possible: (<Enum 'AutoIntEnum'>, <Enum 'IntEnum'>, 518 # <class 'int'>, <Enum 'Enum'>, 519 # <class 'object'>) 520 if issubclass(base, Enum): 521 if first_enum is None: 522 first_enum = base 523 else: 524 if member_type is None: 525 member_type = base 526 527 return member_type, first_enum 528 529 if pyver < 3.0: 530 @staticmethod 531 def _find_new_(classdict, member_type, first_enum): 532 """Returns the __new__ to be used for creating the enum members. 533 534 classdict: the class dictionary given to __new__ 535 member_type: the data type whose __new__ will be used by default 536 first_enum: enumeration to check for an overriding __new__ 537 538 """ 539 # now find the correct __new__, checking to see of one was defined 540 # by the user; also check earlier enum classes in case a __new__ was 541 # saved as __member_new__ 542 __new__ = classdict.get('__new__', None) 543 if __new__: 544 return None, True, True # __new__, save_new, use_args 545 546 N__new__ = getattr(None, '__new__') 547 O__new__ = getattr(object, '__new__') 548 if Enum is None: 549 E__new__ = N__new__ 550 else: 551 E__new__ = Enum.__dict__['__new__'] 552 # check all possibles for __member_new__ before falling back to 553 # __new__ 554 for method in ('__member_new__', '__new__'): 555 for possible in (member_type, first_enum): 556 try: 557 target = possible.__dict__[method] 558 except (AttributeError, KeyError): 559 target = getattr(possible, method, None) 560 if target not in [ 561 None, 562 N__new__, 563 O__new__, 564 E__new__, 565 ]: 566 if method == '__member_new__': 567 classdict['__new__'] = target 568 return None, False, True 569 if isinstance(target, staticmethod): 570 target = target.__get__(member_type) 571 __new__ = target 572 break 573 if __new__ is not None: 574 break 575 else: 576 __new__ = object.__new__ 577 578 # if a non-object.__new__ is used then whatever value/tuple was 579 # assigned to the enum member name will be passed to __new__ and to the 580 # new enum member's __init__ 581 if __new__ is object.__new__: 582 use_args = False 583 else: 584 use_args = True 585 586 return __new__, False, use_args 587 else: 588 @staticmethod 589 def _find_new_(classdict, member_type, first_enum): 590 """Returns the __new__ to be used for creating the enum members. 591 592 classdict: the class dictionary given to __new__ 593 member_type: the data type whose __new__ will be used by default 594 first_enum: enumeration to check for an overriding __new__ 595 596 """ 597 # now find the correct __new__, checking to see of one was defined 598 # by the user; also check earlier enum classes in case a __new__ was 599 # saved as __member_new__ 600 __new__ = classdict.get('__new__', None) 601 602 # should __new__ be saved as __member_new__ later? 603 save_new = __new__ is not None 604 605 if __new__ is None: 606 # check all possibles for __member_new__ before falling back to 607 # __new__ 608 for method in ('__member_new__', '__new__'): 609 for possible in (member_type, first_enum): 610 target = getattr(possible, method, None) 611 if target not in ( 612 None, 613 None.__new__, 614 object.__new__, 615 Enum.__new__, 616 ): 617 __new__ = target 618 break 619 if __new__ is not None: 620 break 621 else: 622 __new__ = object.__new__ 623 624 # if a non-object.__new__ is used then whatever value/tuple was 625 # assigned to the enum member name will be passed to __new__ and to the 626 # new enum member's __init__ 627 if __new__ is object.__new__: 628 use_args = False 629 else: 630 use_args = True 631 632 return __new__, save_new, use_args 633 634 635######################################################## 636# In order to support Python 2 and 3 with a single 637# codebase we have to create the Enum methods separately 638# and then use the `type(name, bases, dict)` method to 639# create the class. 640######################################################## 641temp_enum_dict = {} 642temp_enum_dict['__doc__'] = "Generic enumeration.\n\n Derive from this class to define new enumerations.\n\n" 643 644def __new__(cls, value): 645 # all enum instances are actually created during class construction 646 # without calling this method; this method is called by the metaclass' 647 # __call__ (i.e. Color(3) ), and by pickle 648 if type(value) is cls: 649 # For lookups like Color(Color.red) 650 value = value.value 651 #return value 652 # by-value search for a matching enum member 653 # see if it's in the reverse mapping (for hashable values) 654 try: 655 if value in cls._value2member_map_: 656 return cls._value2member_map_[value] 657 except TypeError: 658 # not there, now do long search -- O(n) behavior 659 for member in cls._member_map_.values(): 660 if member.value == value: 661 return member 662 raise ValueError("%s is not a valid %s" % (value, cls.__name__)) 663temp_enum_dict['__new__'] = __new__ 664del __new__ 665 666def __repr__(self): 667 return "<%s.%s: %r>" % ( 668 self.__class__.__name__, self._name_, self._value_) 669temp_enum_dict['__repr__'] = __repr__ 670del __repr__ 671 672def __str__(self): 673 return "%s.%s" % (self.__class__.__name__, self._name_) 674temp_enum_dict['__str__'] = __str__ 675del __str__ 676 677if pyver >= 3.0: 678 def __dir__(self): 679 added_behavior = [ 680 m 681 for cls in self.__class__.mro() 682 for m in cls.__dict__ 683 if m[0] != '_' and m not in self._member_map_ 684 ] 685 return (['__class__', '__doc__', '__module__', ] + added_behavior) 686 temp_enum_dict['__dir__'] = __dir__ 687 del __dir__ 688 689def __format__(self, format_spec): 690 # mixed-in Enums should use the mixed-in type's __format__, otherwise 691 # we can get strange results with the Enum name showing up instead of 692 # the value 693 694 # pure Enum branch 695 if self._member_type_ is object: 696 cls = str 697 val = str(self) 698 # mix-in branch 699 else: 700 cls = self._member_type_ 701 val = self.value 702 return cls.__format__(val, format_spec) 703temp_enum_dict['__format__'] = __format__ 704del __format__ 705 706 707#################################### 708# Python's less than 2.6 use __cmp__ 709 710if pyver < 2.6: 711 712 def __cmp__(self, other): 713 if type(other) is self.__class__: 714 if self is other: 715 return 0 716 return -1 717 return NotImplemented 718 raise TypeError("unorderable types: %s() and %s()" % (self.__class__.__name__, other.__class__.__name__)) 719 temp_enum_dict['__cmp__'] = __cmp__ 720 del __cmp__ 721 722else: 723 724 def __le__(self, other): 725 raise TypeError("unorderable types: %s() <= %s()" % (self.__class__.__name__, other.__class__.__name__)) 726 temp_enum_dict['__le__'] = __le__ 727 del __le__ 728 729 def __lt__(self, other): 730 raise TypeError("unorderable types: %s() < %s()" % (self.__class__.__name__, other.__class__.__name__)) 731 temp_enum_dict['__lt__'] = __lt__ 732 del __lt__ 733 734 def __ge__(self, other): 735 raise TypeError("unorderable types: %s() >= %s()" % (self.__class__.__name__, other.__class__.__name__)) 736 temp_enum_dict['__ge__'] = __ge__ 737 del __ge__ 738 739 def __gt__(self, other): 740 raise TypeError("unorderable types: %s() > %s()" % (self.__class__.__name__, other.__class__.__name__)) 741 temp_enum_dict['__gt__'] = __gt__ 742 del __gt__ 743 744 745def __eq__(self, other): 746 if type(other) is self.__class__: 747 return self is other 748 return NotImplemented 749temp_enum_dict['__eq__'] = __eq__ 750del __eq__ 751 752def __ne__(self, other): 753 if type(other) is self.__class__: 754 return self is not other 755 return NotImplemented 756temp_enum_dict['__ne__'] = __ne__ 757del __ne__ 758 759def __hash__(self): 760 return hash(self._name_) 761temp_enum_dict['__hash__'] = __hash__ 762del __hash__ 763 764def __reduce_ex__(self, proto): 765 return self.__class__, (self._value_, ) 766temp_enum_dict['__reduce_ex__'] = __reduce_ex__ 767del __reduce_ex__ 768 769# _RouteClassAttributeToGetattr is used to provide access to the `name` 770# and `value` properties of enum members while keeping some measure of 771# protection from modification, while still allowing for an enumeration 772# to have members named `name` and `value`. This works because enumeration 773# members are not set directly on the enum class -- __getattr__ is 774# used to look them up. 775 776@_RouteClassAttributeToGetattr 777def name(self): 778 return self._name_ 779temp_enum_dict['name'] = name 780del name 781 782@_RouteClassAttributeToGetattr 783def value(self): 784 return self._value_ 785temp_enum_dict['value'] = value 786del value 787 788@classmethod 789def _convert(cls, name, module, filter, source=None): 790 """ 791 Create a new Enum subclass that replaces a collection of global constants 792 """ 793 # convert all constants from source (or module) that pass filter() to 794 # a new Enum called name, and export the enum and its members back to 795 # module; 796 # also, replace the __reduce_ex__ method so unpickling works in 797 # previous Python versions 798 module_globals = vars(_sys.modules[module]) 799 if source: 800 source = vars(source) 801 else: 802 source = module_globals 803 members = dict((name, value) for name, value in source.items() if filter(name)) 804 cls = cls(name, members, module=module) 805 cls.__reduce_ex__ = _reduce_ex_by_name 806 module_globals.update(cls.__members__) 807 module_globals[name] = cls 808 return cls 809temp_enum_dict['_convert'] = _convert 810del _convert 811 812Enum = EnumMeta('Enum', (object, ), temp_enum_dict) 813del temp_enum_dict 814 815# Enum has now been created 816########################### 817 818class IntEnum(int, Enum): 819 """Enum where members are also (and must be) ints""" 820 821def _reduce_ex_by_name(self, proto): 822 return self.name 823 824def unique(enumeration): 825 """Class decorator that ensures only unique members exist in an enumeration.""" 826 duplicates = [] 827 for name, member in enumeration.__members__.items(): 828 if name != member.name: 829 duplicates.append((name, member.name)) 830 if duplicates: 831 duplicate_names = ', '.join( 832 ["%s -> %s" % (alias, name) for (alias, name) in duplicates] 833 ) 834 raise ValueError('duplicate names found in %r: %s' % 835 (enumeration, duplicate_names) 836 ) 837 return enumeration 838