m2m模型翻译
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

841 lines
30 KiB

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