blob: 6a1899941f7226f663fab6463c1ac02da98e7cf0 [file] [log] [blame]
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001import sys
Ethan Furmane03ea372013-09-25 07:14:41 -07002from types import MappingProxyType, DynamicClassAttribute
Ethan Furmanee47e5c2016-08-31 00:12:15 -07003from functools import reduce
4from operator import or_ as _or_
Ethan Furman6b3d64a2013-06-14 16:55:46 -07005
Ethan Furmanc7915072015-09-17 22:55:40 -07006# try _collections first to reduce startup cost
Ethan Furmane5754ab2015-09-17 22:03:52 -07007try:
8 from _collections import OrderedDict
9except ImportError:
10 from collections import OrderedDict
11
12
Ethan Furman65a5a472016-09-01 23:55:19 -070013__all__ = ['EnumMeta', 'Enum', 'IntEnum', 'Flag', 'IntFlag', 'unique']
Ethan Furman6b3d64a2013-06-14 16:55:46 -070014
15
Ethan Furman101e0742013-09-15 12:34:36 -070016def _is_descriptor(obj):
17 """Returns True if obj is a descriptor, False otherwise."""
18 return (
19 hasattr(obj, '__get__') or
20 hasattr(obj, '__set__') or
21 hasattr(obj, '__delete__'))
22
23
Ethan Furman6b3d64a2013-06-14 16:55:46 -070024def _is_dunder(name):
25 """Returns True if a __dunder__ name, False otherwise."""
26 return (name[:2] == name[-2:] == '__' and
27 name[2:3] != '_' and
Ethan Furman648f8602013-10-06 17:19:54 -070028 name[-3:-2] != '_' and
29 len(name) > 4)
Ethan Furman6b3d64a2013-06-14 16:55:46 -070030
31
32def _is_sunder(name):
33 """Returns True if a _sunder_ name, False otherwise."""
34 return (name[0] == name[-1] == '_' and
35 name[1:2] != '_' and
Ethan Furman648f8602013-10-06 17:19:54 -070036 name[-2:-1] != '_' and
37 len(name) > 2)
Ethan Furman6b3d64a2013-06-14 16:55:46 -070038
39
40def _make_class_unpicklable(cls):
41 """Make the given class un-picklable."""
Ethan Furmanca1b7942014-02-08 11:36:27 -080042 def _break_on_call_reduce(self, proto):
Ethan Furman6b3d64a2013-06-14 16:55:46 -070043 raise TypeError('%r cannot be pickled' % self)
Ethan Furmanca1b7942014-02-08 11:36:27 -080044 cls.__reduce_ex__ = _break_on_call_reduce
Ethan Furman6b3d64a2013-06-14 16:55:46 -070045 cls.__module__ = '<unknown>'
46
Ethan Furman101e0742013-09-15 12:34:36 -070047
Ethan Furman6b3d64a2013-06-14 16:55:46 -070048class _EnumDict(dict):
Ethan Furman101e0742013-09-15 12:34:36 -070049 """Track enum member order and ensure member names are not reused.
Ethan Furman6b3d64a2013-06-14 16:55:46 -070050
51 EnumMeta will use the names found in self._member_names as the
52 enumeration member names.
53
54 """
55 def __init__(self):
56 super().__init__()
57 self._member_names = []
58
59 def __setitem__(self, key, value):
Ethan Furman101e0742013-09-15 12:34:36 -070060 """Changes anything not dundered or not a descriptor.
Ethan Furman6b3d64a2013-06-14 16:55:46 -070061
62 If an enum member name is used twice, an error is raised; duplicate
63 values are not checked for.
64
65 Single underscore (sunder) names are reserved.
66
67 """
68 if _is_sunder(key):
Ethan Furmanee47e5c2016-08-31 00:12:15 -070069 if key not in (
70 '_order_', '_create_pseudo_member_', '_decompose_',
71 '_generate_next_value_', '_missing_',
72 ):
Ethan Furmane8e61272016-08-20 07:19:31 -070073 raise ValueError('_names_ are reserved for future Enum use')
Ethan Furman101e0742013-09-15 12:34:36 -070074 elif _is_dunder(key):
Ethan Furmane8e61272016-08-20 07:19:31 -070075 if key == '__order__':
76 key = '_order_'
Ethan Furman101e0742013-09-15 12:34:36 -070077 elif key in self._member_names:
78 # descriptor overwriting an enum?
79 raise TypeError('Attempted to reuse key: %r' % key)
80 elif not _is_descriptor(value):
81 if key in self:
82 # enum overwriting a descriptor?
Ethan Furmanee47e5c2016-08-31 00:12:15 -070083 raise TypeError('%r already defined as: %r' % (key, self[key]))
Ethan Furman6b3d64a2013-06-14 16:55:46 -070084 self._member_names.append(key)
85 super().__setitem__(key, value)
86
87
Ethan Furman101e0742013-09-15 12:34:36 -070088
Ezio Melotti9a3777e2013-08-17 15:53:55 +030089# Dummy value for Enum as EnumMeta explicitly checks for it, but of course
90# until EnumMeta finishes running the first time the Enum class doesn't exist.
91# This is also why there are checks in EnumMeta like `if Enum is not None`
Ethan Furman6b3d64a2013-06-14 16:55:46 -070092Enum = None
93
Ethan Furman332dbc72016-08-20 00:00:52 -070094
Ethan Furman6b3d64a2013-06-14 16:55:46 -070095class EnumMeta(type):
96 """Metaclass for Enum"""
97 @classmethod
Ethan Furman332dbc72016-08-20 00:00:52 -070098 def __prepare__(metacls, cls, bases):
Ethan Furmanee47e5c2016-08-31 00:12:15 -070099 # create the namespace dict
100 enum_dict = _EnumDict()
101 # inherit previous flags and _generate_next_value_ function
102 member_type, first_enum = metacls._get_mixins_(bases)
103 if first_enum is not None:
104 enum_dict['_generate_next_value_'] = getattr(first_enum, '_generate_next_value_', None)
105 return enum_dict
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700106
Ethan Furman65a5a472016-09-01 23:55:19 -0700107 def __new__(metacls, cls, bases, classdict):
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700108 # an Enum class is final once enumeration items have been defined; it
109 # cannot be mixed with other types (int, float, etc.) if it has an
110 # inherited __new__ unless a new __new__ is defined (or the resulting
111 # class will fail).
112 member_type, first_enum = metacls._get_mixins_(bases)
113 __new__, save_new, use_args = metacls._find_new_(classdict, member_type,
114 first_enum)
115
116 # save enum items into separate mapping so they don't get baked into
117 # the new class
Ethan Furmanee47e5c2016-08-31 00:12:15 -0700118 enum_members = {k: classdict[k] for k in classdict._member_names}
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700119 for name in classdict._member_names:
120 del classdict[name]
121
Ethan Furmane8e61272016-08-20 07:19:31 -0700122 # adjust the sunders
123 _order_ = classdict.pop('_order_', None)
124
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700125 # check for illegal enum names (any others?)
Ethan Furmanee47e5c2016-08-31 00:12:15 -0700126 invalid_names = set(enum_members) & {'mro', }
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700127 if invalid_names:
128 raise ValueError('Invalid enum member name: {0}'.format(
129 ','.join(invalid_names)))
130
Ethan Furman48a724f2015-04-11 23:23:06 -0700131 # create a default docstring if one has not been provided
132 if '__doc__' not in classdict:
133 classdict['__doc__'] = 'An enumeration.'
134
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700135 # create our new Enum type
136 enum_class = super().__new__(metacls, cls, bases, classdict)
Ethan Furman520ad572013-07-19 19:47:21 -0700137 enum_class._member_names_ = [] # names in definition order
138 enum_class._member_map_ = OrderedDict() # name->value map
Ethan Furman5e5a8232013-08-04 08:42:23 -0700139 enum_class._member_type_ = member_type
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700140
Ethan Furman354ecf12015-03-11 08:43:12 -0700141 # save attributes from super classes so we know if we can take
142 # the shortcut of storing members in the class dict
Ethan Furman3803ad42016-05-01 10:03:53 -0700143 base_attributes = {a for b in enum_class.mro() for a in b.__dict__}
Ethan Furman354ecf12015-03-11 08:43:12 -0700144
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700145 # Reverse value->name map for hashable values.
Ethan Furman520ad572013-07-19 19:47:21 -0700146 enum_class._value2member_map_ = {}
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700147
Ethan Furman2da95042014-03-03 12:42:52 -0800148 # If a custom type is mixed into the Enum, and it does not know how
149 # to pickle itself, pickle.dumps will succeed but pickle.loads will
150 # fail. Rather than have the error show up later and possibly far
151 # from the source, sabotage the pickle protocol for this class so
152 # that pickle.dumps also fails.
153 #
154 # However, if the new class implements its own __reduce_ex__, do not
155 # sabotage -- it's on them to make sure it works correctly. We use
156 # __reduce_ex__ instead of any of the others as it is preferred by
157 # pickle over __reduce__, and it handles all pickle protocols.
158 if '__reduce_ex__' not in classdict:
Ethan Furmandc870522014-02-18 12:37:12 -0800159 if member_type is not object:
160 methods = ('__getnewargs_ex__', '__getnewargs__',
161 '__reduce_ex__', '__reduce__')
Ethan Furman2da95042014-03-03 12:42:52 -0800162 if not any(m in member_type.__dict__ for m in methods):
Ethan Furmandc870522014-02-18 12:37:12 -0800163 _make_class_unpicklable(enum_class)
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700164
165 # instantiate them, checking for duplicates as we go
166 # we instantiate first instead of checking for duplicates first in case
167 # a custom __new__ is doing something funky with the values -- such as
168 # auto-numbering ;)
169 for member_name in classdict._member_names:
Ethan Furmanee47e5c2016-08-31 00:12:15 -0700170 value = enum_members[member_name]
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700171 if not isinstance(value, tuple):
172 args = (value, )
173 else:
174 args = value
175 if member_type is tuple: # special case for tuple enums
176 args = (args, ) # wrap it one more time
177 if not use_args:
178 enum_member = __new__(enum_class)
Ethan Furmanb41803e2013-07-25 13:50:45 -0700179 if not hasattr(enum_member, '_value_'):
180 enum_member._value_ = value
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700181 else:
182 enum_member = __new__(enum_class, *args)
Ethan Furmanb41803e2013-07-25 13:50:45 -0700183 if not hasattr(enum_member, '_value_'):
Ethan Furmanee47e5c2016-08-31 00:12:15 -0700184 if member_type is object:
185 enum_member._value_ = value
186 else:
187 enum_member._value_ = member_type(*args)
Ethan Furman520ad572013-07-19 19:47:21 -0700188 value = enum_member._value_
Ethan Furman520ad572013-07-19 19:47:21 -0700189 enum_member._name_ = member_name
Ethan Furmanc850f342013-09-15 16:59:35 -0700190 enum_member.__objclass__ = enum_class
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700191 enum_member.__init__(*args)
192 # If another member with the same value was already defined, the
193 # new member becomes an alias to the existing one.
Ethan Furman520ad572013-07-19 19:47:21 -0700194 for name, canonical_member in enum_class._member_map_.items():
Ethan Furman0081f232014-09-16 17:31:23 -0700195 if canonical_member._value_ == enum_member._value_:
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700196 enum_member = canonical_member
197 break
198 else:
199 # Aliases don't appear in member names (only in __members__).
Ethan Furman520ad572013-07-19 19:47:21 -0700200 enum_class._member_names_.append(member_name)
Ethan Furman354ecf12015-03-11 08:43:12 -0700201 # performance boost for any member that would not shadow
202 # a DynamicClassAttribute
203 if member_name not in base_attributes:
204 setattr(enum_class, member_name, enum_member)
205 # now add to _member_map_
Ethan Furman520ad572013-07-19 19:47:21 -0700206 enum_class._member_map_[member_name] = enum_member
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700207 try:
208 # This may fail if value is not hashable. We can't add the value
209 # to the map, and by-value lookups for this value will be
210 # linear.
Ethan Furman520ad572013-07-19 19:47:21 -0700211 enum_class._value2member_map_[value] = enum_member
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700212 except TypeError:
213 pass
214
215 # double check that repr and friends are not the mixin's or various
216 # things break (such as pickle)
Ethan Furmandc870522014-02-18 12:37:12 -0800217 for name in ('__repr__', '__str__', '__format__', '__reduce_ex__'):
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700218 class_method = getattr(enum_class, name)
219 obj_method = getattr(member_type, name, None)
220 enum_method = getattr(first_enum, name, None)
221 if obj_method is not None and obj_method is class_method:
222 setattr(enum_class, name, enum_method)
223
224 # replace any other __new__ with our own (as long as Enum is not None,
225 # anyway) -- again, this is to support pickle
226 if Enum is not None:
227 # if the user defined their own __new__, save it before it gets
228 # clobbered in case they subclass later
229 if save_new:
230 enum_class.__new_member__ = __new__
231 enum_class.__new__ = Enum.__new__
Ethan Furmane8e61272016-08-20 07:19:31 -0700232
233 # py3 support for definition order (helps keep py2/py3 code in sync)
234 if _order_ is not None:
235 if isinstance(_order_, str):
236 _order_ = _order_.replace(',', ' ').split()
237 if _order_ != enum_class._member_names_:
238 raise TypeError('member order does not match _order_')
239
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700240 return enum_class
241
Ethan Furman5de67b12016-04-13 23:52:09 -0700242 def __bool__(self):
243 """
244 classes/types should always be True.
245 """
246 return True
247
Ethan Furmand9925a12014-09-16 20:35:55 -0700248 def __call__(cls, value, names=None, *, module=None, qualname=None, type=None, start=1):
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700249 """Either returns an existing member, or creates a new enum class.
250
251 This method is used both when an enum class is given a value to match
252 to an enumeration member (i.e. Color(3)) and for the functional API
253 (i.e. Color = Enum('Color', names='red green blue')).
254
Ethan Furman2da95042014-03-03 12:42:52 -0800255 When used for the functional API:
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700256
Ethan Furman2da95042014-03-03 12:42:52 -0800257 `value` will be the name of the new class.
258
259 `names` should be either a string of white-space/comma delimited names
Ethan Furmand9925a12014-09-16 20:35:55 -0700260 (values will start at `start`), or an iterator/mapping of name, value pairs.
Ethan Furman2da95042014-03-03 12:42:52 -0800261
262 `module` should be set to the module this class is being created in;
263 if it is not set, an attempt to find that module will be made, but if
264 it fails the class will not be picklable.
265
266 `qualname` should be set to the actual location this class can be found
267 at in its module; by default it is set to the global scope. If this is
268 not correct, unpickling will fail in some circumstances.
269
270 `type`, if set, will be mixed in as the first base class.
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700271
272 """
273 if names is None: # simple value lookup
274 return cls.__new__(cls, value)
275 # otherwise, functional API: we're creating a new Enum type
Ethan Furmand9925a12014-09-16 20:35:55 -0700276 return cls._create_(value, names, module=module, qualname=qualname, type=type, start=start)
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700277
278 def __contains__(cls, member):
Ethan Furman0081f232014-09-16 17:31:23 -0700279 return isinstance(member, cls) and member._name_ in cls._member_map_
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700280
Ethan Furman64a99722013-09-22 16:18:19 -0700281 def __delattr__(cls, attr):
282 # nicer error message when someone tries to delete an attribute
283 # (see issue19025).
284 if attr in cls._member_map_:
285 raise AttributeError(
286 "%s: cannot delete Enum member." % cls.__name__)
287 super().__delattr__(attr)
288
Ethan Furman388a3922013-08-12 06:51:41 -0700289 def __dir__(self):
Ethan Furman64a99722013-09-22 16:18:19 -0700290 return (['__class__', '__doc__', '__members__', '__module__'] +
291 self._member_names_)
Ethan Furman388a3922013-08-12 06:51:41 -0700292
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700293 def __getattr__(cls, name):
294 """Return the enum member matching `name`
295
296 We use __getattr__ instead of descriptors or inserting into the enum
297 class' __dict__ in order to support `name` and `value` being both
298 properties for enum members (which live in the class' __dict__) and
299 enum members themselves.
300
301 """
302 if _is_dunder(name):
303 raise AttributeError(name)
304 try:
Ethan Furman520ad572013-07-19 19:47:21 -0700305 return cls._member_map_[name]
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700306 except KeyError:
307 raise AttributeError(name) from None
308
309 def __getitem__(cls, name):
Ethan Furman520ad572013-07-19 19:47:21 -0700310 return cls._member_map_[name]
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700311
312 def __iter__(cls):
Ethan Furman520ad572013-07-19 19:47:21 -0700313 return (cls._member_map_[name] for name in cls._member_names_)
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700314
315 def __len__(cls):
Ethan Furman520ad572013-07-19 19:47:21 -0700316 return len(cls._member_names_)
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700317
Ethan Furman2131a4a2013-09-14 18:11:24 -0700318 @property
319 def __members__(cls):
320 """Returns a mapping of member name->value.
321
322 This mapping lists all enum members, including aliases. Note that this
323 is a read-only view of the internal mapping.
324
325 """
326 return MappingProxyType(cls._member_map_)
327
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700328 def __repr__(cls):
329 return "<enum %r>" % cls.__name__
330
Ethan Furman2131a4a2013-09-14 18:11:24 -0700331 def __reversed__(cls):
332 return (cls._member_map_[name] for name in reversed(cls._member_names_))
333
Ethan Furmanf203f2d2013-09-06 07:16:48 -0700334 def __setattr__(cls, name, value):
335 """Block attempts to reassign Enum members.
336
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 """
342 member_map = cls.__dict__.get('_member_map_', {})
343 if name in member_map:
344 raise AttributeError('Cannot reassign members.')
345 super().__setattr__(name, value)
346
Ethan Furmand9925a12014-09-16 20:35:55 -0700347 def _create_(cls, class_name, names=None, *, module=None, qualname=None, type=None, start=1):
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700348 """Convenience method to create a new Enum class.
349
350 `names` can be:
351
352 * A string containing member names, separated either with spaces or
Ethan Furmand9925a12014-09-16 20:35:55 -0700353 commas. Values are incremented by 1 from `start`.
354 * An iterable of member names. Values are incremented by 1 from `start`.
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700355 * An iterable of (member name, value) pairs.
Ethan Furmand9925a12014-09-16 20:35:55 -0700356 * A mapping of member name -> value pairs.
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700357
358 """
359 metacls = cls.__class__
360 bases = (cls, ) if type is None else (type, cls)
Ethan Furmanee47e5c2016-08-31 00:12:15 -0700361 _, first_enum = cls._get_mixins_(bases)
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700362 classdict = metacls.__prepare__(class_name, bases)
363
364 # special processing needed for names?
365 if isinstance(names, str):
366 names = names.replace(',', ' ').split()
367 if isinstance(names, (tuple, list)) and isinstance(names[0], str):
Ethan Furmanee47e5c2016-08-31 00:12:15 -0700368 original_names, names = names, []
369 last_value = None
370 for count, name in enumerate(original_names):
371 last_value = first_enum._generate_next_value_(name, start, count, last_value)
372 names.append((name, last_value))
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700373
374 # Here, names is either an iterable of (name, value) or a mapping.
375 for item in names:
376 if isinstance(item, str):
377 member_name, member_value = item, names[item]
378 else:
379 member_name, member_value = item
380 classdict[member_name] = member_value
381 enum_class = metacls.__new__(metacls, class_name, bases, classdict)
382
383 # TODO: replace the frame hack if a blessed way to know the calling
384 # module is ever developed
385 if module is None:
386 try:
387 module = sys._getframe(2).f_globals['__name__']
388 except (AttributeError, ValueError) as exc:
389 pass
390 if module is None:
391 _make_class_unpicklable(enum_class)
392 else:
393 enum_class.__module__ = module
Ethan Furmanca1b7942014-02-08 11:36:27 -0800394 if qualname is not None:
395 enum_class.__qualname__ = qualname
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700396
397 return enum_class
398
399 @staticmethod
400 def _get_mixins_(bases):
401 """Returns the type for creating enum members, and the first inherited
402 enum class.
403
404 bases: the tuple of bases that was given to __new__
405
406 """
407 if not bases:
408 return object, Enum
409
410 # double check that we are not subclassing a class with existing
411 # enumeration members; while we're at it, see if any other data
412 # type has been mixed in so we can use the correct __new__
413 member_type = first_enum = None
414 for base in bases:
415 if (base is not Enum and
416 issubclass(base, Enum) and
Ethan Furman520ad572013-07-19 19:47:21 -0700417 base._member_names_):
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700418 raise TypeError("Cannot extend enumerations")
419 # base is now the last base in bases
420 if not issubclass(base, Enum):
421 raise TypeError("new enumerations must be created as "
422 "`ClassName([mixin_type,] enum_type)`")
423
424 # get correct mix-in type (either mix-in type of Enum subclass, or
425 # first base if last base is Enum)
426 if not issubclass(bases[0], Enum):
427 member_type = bases[0] # first data type
428 first_enum = bases[-1] # enum type
429 else:
430 for base in bases[0].__mro__:
431 # most common: (IntEnum, int, Enum, object)
432 # possible: (<Enum 'AutoIntEnum'>, <Enum 'IntEnum'>,
433 # <class 'int'>, <Enum 'Enum'>,
434 # <class 'object'>)
435 if issubclass(base, Enum):
436 if first_enum is None:
437 first_enum = base
438 else:
439 if member_type is None:
440 member_type = base
441
442 return member_type, first_enum
443
444 @staticmethod
445 def _find_new_(classdict, member_type, first_enum):
446 """Returns the __new__ to be used for creating the enum members.
447
448 classdict: the class dictionary given to __new__
449 member_type: the data type whose __new__ will be used by default
450 first_enum: enumeration to check for an overriding __new__
451
452 """
453 # now find the correct __new__, checking to see of one was defined
454 # by the user; also check earlier enum classes in case a __new__ was
455 # saved as __new_member__
456 __new__ = classdict.get('__new__', None)
457
458 # should __new__ be saved as __new_member__ later?
459 save_new = __new__ is not None
460
461 if __new__ is None:
462 # check all possibles for __new_member__ before falling back to
463 # __new__
464 for method in ('__new_member__', '__new__'):
465 for possible in (member_type, first_enum):
466 target = getattr(possible, method, None)
467 if target not in {
468 None,
469 None.__new__,
470 object.__new__,
471 Enum.__new__,
472 }:
473 __new__ = target
474 break
475 if __new__ is not None:
476 break
477 else:
478 __new__ = object.__new__
479
480 # if a non-object.__new__ is used then whatever value/tuple was
481 # assigned to the enum member name will be passed to __new__ and to the
482 # new enum member's __init__
483 if __new__ is object.__new__:
484 use_args = False
485 else:
486 use_args = True
487
488 return __new__, save_new, use_args
489
490
491class Enum(metaclass=EnumMeta):
492 """Generic enumeration.
493
494 Derive from this class to define new enumerations.
495
496 """
497 def __new__(cls, value):
498 # all enum instances are actually created during class construction
499 # without calling this method; this method is called by the metaclass'
500 # __call__ (i.e. Color(3) ), and by pickle
501 if type(value) is cls:
502 # For lookups like Color(Color.red)
503 return value
504 # by-value search for a matching enum member
505 # see if it's in the reverse mapping (for hashable values)
Ethan Furman2aa27322013-07-19 19:35:56 -0700506 try:
Ethan Furman520ad572013-07-19 19:47:21 -0700507 if value in cls._value2member_map_:
508 return cls._value2member_map_[value]
Ethan Furman2aa27322013-07-19 19:35:56 -0700509 except TypeError:
510 # not there, now do long search -- O(n) behavior
Ethan Furman520ad572013-07-19 19:47:21 -0700511 for member in cls._member_map_.values():
Ethan Furman0081f232014-09-16 17:31:23 -0700512 if member._value_ == value:
Ethan Furman2aa27322013-07-19 19:35:56 -0700513 return member
Ethan Furmanee47e5c2016-08-31 00:12:15 -0700514 # still not found -- try _missing_ hook
515 return cls._missing_(value)
516
517 @staticmethod
518 def _generate_next_value_(name, start, count, last_value):
519 if not count:
520 return start
521 return last_value + 1
522 @classmethod
523 def _missing_(cls, value):
Ethan Furman0081f232014-09-16 17:31:23 -0700524 raise ValueError("%r is not a valid %s" % (value, cls.__name__))
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700525
526 def __repr__(self):
527 return "<%s.%s: %r>" % (
Ethan Furman520ad572013-07-19 19:47:21 -0700528 self.__class__.__name__, self._name_, self._value_)
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700529
530 def __str__(self):
Ethan Furman520ad572013-07-19 19:47:21 -0700531 return "%s.%s" % (self.__class__.__name__, self._name_)
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700532
Ethan Furman388a3922013-08-12 06:51:41 -0700533 def __dir__(self):
Ethan Furman0ae550b2014-10-14 08:58:32 -0700534 added_behavior = [
535 m
536 for cls in self.__class__.mro()
537 for m in cls.__dict__
Ethan Furman354ecf12015-03-11 08:43:12 -0700538 if m[0] != '_' and m not in self._member_map_
Ethan Furman0ae550b2014-10-14 08:58:32 -0700539 ]
Ethan Furmanec5f8eb2014-10-21 13:40:35 -0700540 return (['__class__', '__doc__', '__module__'] + added_behavior)
Ethan Furman388a3922013-08-12 06:51:41 -0700541
Ethan Furmanec15a822013-08-31 19:17:41 -0700542 def __format__(self, format_spec):
543 # mixed-in Enums should use the mixed-in type's __format__, otherwise
544 # we can get strange results with the Enum name showing up instead of
545 # the value
546
547 # pure Enum branch
548 if self._member_type_ is object:
549 cls = str
550 val = str(self)
551 # mix-in branch
552 else:
553 cls = self._member_type_
Ethan Furman0081f232014-09-16 17:31:23 -0700554 val = self._value_
Ethan Furmanec15a822013-08-31 19:17:41 -0700555 return cls.__format__(val, format_spec)
556
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700557 def __hash__(self):
Ethan Furman520ad572013-07-19 19:47:21 -0700558 return hash(self._name_)
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700559
Ethan Furmanca1b7942014-02-08 11:36:27 -0800560 def __reduce_ex__(self, proto):
Ethan Furmandc870522014-02-18 12:37:12 -0800561 return self.__class__, (self._value_, )
Ethan Furmanca1b7942014-02-08 11:36:27 -0800562
Ethan Furman33918c12013-09-27 23:02:02 -0700563 # DynamicClassAttribute is used to provide access to the `name` and
564 # `value` properties of enum members while keeping some measure of
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700565 # protection from modification, while still allowing for an enumeration
566 # to have members named `name` and `value`. This works because enumeration
567 # members are not set directly on the enum class -- __getattr__ is
568 # used to look them up.
569
Ethan Furmane03ea372013-09-25 07:14:41 -0700570 @DynamicClassAttribute
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700571 def name(self):
Ethan Furmanc850f342013-09-15 16:59:35 -0700572 """The name of the Enum member."""
Ethan Furman520ad572013-07-19 19:47:21 -0700573 return self._name_
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700574
Ethan Furmane03ea372013-09-25 07:14:41 -0700575 @DynamicClassAttribute
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700576 def value(self):
Ethan Furmanc850f342013-09-15 16:59:35 -0700577 """The value of the Enum member."""
Ethan Furman520ad572013-07-19 19:47:21 -0700578 return self._value_
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700579
Ethan Furman24e837f2015-03-18 17:27:57 -0700580 @classmethod
581 def _convert(cls, name, module, filter, source=None):
582 """
583 Create a new Enum subclass that replaces a collection of global constants
584 """
585 # convert all constants from source (or module) that pass filter() to
586 # a new Enum called name, and export the enum and its members back to
587 # module;
588 # also, replace the __reduce_ex__ method so unpickling works in
589 # previous Python versions
590 module_globals = vars(sys.modules[module])
591 if source:
592 source = vars(source)
593 else:
594 source = module_globals
Gregory P. Smith ext:(%20%5BGoogle%20Inc.%5D)6f20bd62016-06-03 19:14:52 +0000595 # We use an OrderedDict of sorted source keys so that the
596 # _value2member_map is populated in the same order every time
597 # for a consistent reverse mapping of number to name when there
598 # are multiple names for the same number rather than varying
599 # between runs due to hash randomization of the module dictionary.
600 members = OrderedDict((name, source[name])
601 for name in sorted(source.keys())
602 if filter(name))
Ethan Furman24e837f2015-03-18 17:27:57 -0700603 cls = cls(name, members, module=module)
604 cls.__reduce_ex__ = _reduce_ex_by_name
605 module_globals.update(cls.__members__)
606 module_globals[name] = cls
607 return cls
608
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700609
610class IntEnum(int, Enum):
611 """Enum where members are also (and must be) ints"""
Ethan Furmanf24bb352013-07-18 17:05:39 -0700612
613
Ethan Furman24e837f2015-03-18 17:27:57 -0700614def _reduce_ex_by_name(self, proto):
615 return self.name
616
Ethan Furman65a5a472016-09-01 23:55:19 -0700617class Flag(Enum):
Ethan Furmanee47e5c2016-08-31 00:12:15 -0700618 """Support for flags"""
619 @staticmethod
620 def _generate_next_value_(name, start, count, last_value):
621 """
622 Generate the next value when not given.
623
624 name: the name of the member
625 start: the initital start value or None
626 count: the number of existing members
627 last_value: the last value assigned or None
628 """
629 if not count:
630 return start if start is not None else 1
631 high_bit = _high_bit(last_value)
632 return 2 ** (high_bit+1)
633
634 @classmethod
635 def _missing_(cls, value):
636 original_value = value
637 if value < 0:
638 value = ~value
639 possible_member = cls._create_pseudo_member_(value)
640 for member in possible_member._decompose_():
641 if member._name_ is None and member._value_ != 0:
642 raise ValueError('%r is not a valid %s' % (original_value, cls.__name__))
643 if original_value < 0:
644 possible_member = ~possible_member
645 return possible_member
646
647 @classmethod
648 def _create_pseudo_member_(cls, value):
649 pseudo_member = cls._value2member_map_.get(value, None)
650 if pseudo_member is None:
651 # construct a non-singleton enum pseudo-member
652 pseudo_member = object.__new__(cls)
653 pseudo_member._name_ = None
654 pseudo_member._value_ = value
655 cls._value2member_map_[value] = pseudo_member
656 return pseudo_member
657
658 def _decompose_(self):
659 """Extract all members from the value."""
660 value = self._value_
661 members = []
662 cls = self.__class__
663 for member in sorted(cls, key=lambda m: m._value_, reverse=True):
664 while _high_bit(value) > _high_bit(member._value_):
665 unknown = self._create_pseudo_member_(2 ** _high_bit(value))
666 members.append(unknown)
667 value &= ~unknown._value_
668 if (
669 (value & member._value_ == member._value_)
670 and (member._value_ or not members)
671 ):
672 value &= ~member._value_
673 members.append(member)
674 if not members or value:
675 members.append(self._create_pseudo_member_(value))
676 members = list(members)
677 return members
678
679 def __contains__(self, other):
680 if not isinstance(other, self.__class__):
681 return NotImplemented
682 return other._value_ & self._value_ == other._value_
683
684 def __iter__(self):
685 if self.value == 0:
686 return iter([])
687 else:
688 return iter(self._decompose_())
689
690 def __repr__(self):
691 cls = self.__class__
692 if self._name_ is not None:
693 return '<%s.%s: %r>' % (cls.__name__, self._name_, self._value_)
694 members = self._decompose_()
Ethan Furman27682d22016-09-04 11:39:01 -0700695 return '<%s.%s: %r>' % (
696 cls.__name__,
697 '|'.join([str(m._name_ or m._value_) for m in members]),
698 self._value_,
699 )
Ethan Furmanee47e5c2016-08-31 00:12:15 -0700700
701 def __str__(self):
702 cls = self.__class__
703 if self._name_ is not None:
704 return '%s.%s' % (cls.__name__, self._name_)
705 members = self._decompose_()
706 if len(members) == 1 and members[0]._name_ is None:
707 return '%s.%r' % (cls.__name__, members[0]._value_)
708 else:
709 return '%s.%s' % (
710 cls.__name__,
711 '|'.join([str(m._name_ or m._value_) for m in members]),
712 )
713
Ethan Furman25d94bb2016-09-02 16:32:32 -0700714 def __bool__(self):
715 return bool(self._value_)
716
Ethan Furmanee47e5c2016-08-31 00:12:15 -0700717 def __or__(self, other):
718 if not isinstance(other, self.__class__):
719 return NotImplemented
720 return self.__class__(self._value_ | other._value_)
721
722 def __and__(self, other):
723 if not isinstance(other, self.__class__):
724 return NotImplemented
725 return self.__class__(self._value_ & other._value_)
726
727 def __xor__(self, other):
728 if not isinstance(other, self.__class__):
729 return NotImplemented
730 return self.__class__(self._value_ ^ other._value_)
731
732 def __invert__(self):
733 members = self._decompose_()
734 inverted_members = [m for m in self.__class__ if m not in members and not m._value_ & self._value_]
735 inverted = reduce(_or_, inverted_members, self.__class__(0))
736 return self.__class__(inverted)
737
738
Ethan Furman65a5a472016-09-01 23:55:19 -0700739class IntFlag(int, Flag):
Ethan Furmanee47e5c2016-08-31 00:12:15 -0700740 """Support for integer-based Flags"""
741
742 @classmethod
743 def _create_pseudo_member_(cls, value):
744 pseudo_member = cls._value2member_map_.get(value, None)
745 if pseudo_member is None:
746 # construct a non-singleton enum pseudo-member
747 pseudo_member = int.__new__(cls, value)
748 pseudo_member._name_ = None
749 pseudo_member._value_ = value
750 cls._value2member_map_[value] = pseudo_member
751 return pseudo_member
752
753 @classmethod
754 def _missing_(cls, value):
755 possible_member = cls._create_pseudo_member_(value)
756 return possible_member
757
758 def __or__(self, other):
759 if not isinstance(other, (self.__class__, int)):
760 return NotImplemented
761 return self.__class__(self._value_ | self.__class__(other)._value_)
762
763 def __and__(self, other):
764 if not isinstance(other, (self.__class__, int)):
765 return NotImplemented
766 return self.__class__(self._value_ & self.__class__(other)._value_)
767
768 def __xor__(self, other):
769 if not isinstance(other, (self.__class__, int)):
770 return NotImplemented
771 return self.__class__(self._value_ ^ self.__class__(other)._value_)
772
773 __ror__ = __or__
774 __rand__ = __and__
775 __rxor__ = __xor__
776
777 def __invert__(self):
778 # members = self._decompose_()
779 # inverted_members = [m for m in self.__class__ if m not in members and not m._value_ & self._value_]
780 # inverted = reduce(_or_, inverted_members, self.__class__(0))
781 return self.__class__(~self._value_)
782
783
784
785
786def _high_bit(value):
Ethan Furman04439532016-09-02 15:50:21 -0700787 """returns index of highest bit, or -1 if value is zero or negative"""
788 return value.bit_length() - 1 if value > 0 else -1
Ethan Furmanee47e5c2016-08-31 00:12:15 -0700789
Ethan Furmanf24bb352013-07-18 17:05:39 -0700790def unique(enumeration):
791 """Class decorator for enumerations ensuring unique member values."""
792 duplicates = []
793 for name, member in enumeration.__members__.items():
794 if name != member.name:
795 duplicates.append((name, member.name))
796 if duplicates:
797 alias_details = ', '.join(
798 ["%s -> %s" % (alias, name) for (alias, name) in duplicates])
799 raise ValueError('duplicate values found in %r: %s' %
800 (enumeration, alias_details))
801 return enumeration