__init__.py 31 KB

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