__init__.py 30 KB

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