blob: ebadd9f662a13894013c29c2c0abfb1759c811d8 [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 Furman6b3d64a2013-06-14 16:55:46 -07003
Ethan Furmane5754ab2015-09-17 22:03:52 -07004
Ethan Furmanc16595e2016-09-10 23:36:59 -07005__all__ = [
6 'EnumMeta',
7 'Enum', 'IntEnum', 'Flag', 'IntFlag',
8 'auto', 'unique',
9 ]
Ethan Furman6b3d64a2013-06-14 16:55:46 -070010
11
Ethan Furman101e0742013-09-15 12:34:36 -070012def _is_descriptor(obj):
13 """Returns True if obj is a descriptor, False otherwise."""
14 return (
15 hasattr(obj, '__get__') or
16 hasattr(obj, '__set__') or
17 hasattr(obj, '__delete__'))
18
19
Ethan Furman6b3d64a2013-06-14 16:55:46 -070020def _is_dunder(name):
21 """Returns True if a __dunder__ name, False otherwise."""
Brennan D Baraban8b914d22019-03-03 14:09:11 -080022 return (len(name) > 4 and
23 name[:2] == name[-2:] == '__' and
24 name[2] != '_' and
25 name[-3] != '_')
Ethan Furman6b3d64a2013-06-14 16:55:46 -070026
27
28def _is_sunder(name):
29 """Returns True if a _sunder_ name, False otherwise."""
Brennan D Baraban8b914d22019-03-03 14:09:11 -080030 return (len(name) > 2 and
31 name[0] == name[-1] == '_' and
Ethan Furman6b3d64a2013-06-14 16:55:46 -070032 name[1:2] != '_' and
Brennan D Baraban8b914d22019-03-03 14:09:11 -080033 name[-2:-1] != '_')
34
Ethan Furman6b3d64a2013-06-14 16:55:46 -070035
Ethan Furman6b3d64a2013-06-14 16:55:46 -070036def _make_class_unpicklable(cls):
37 """Make the given class un-picklable."""
Ethan Furmanca1b7942014-02-08 11:36:27 -080038 def _break_on_call_reduce(self, proto):
Ethan Furman6b3d64a2013-06-14 16:55:46 -070039 raise TypeError('%r cannot be pickled' % self)
Ethan Furmanca1b7942014-02-08 11:36:27 -080040 cls.__reduce_ex__ = _break_on_call_reduce
Ethan Furman6b3d64a2013-06-14 16:55:46 -070041 cls.__module__ = '<unknown>'
42
Ethan Furman3515dcc2016-09-18 13:15:41 -070043_auto_null = object()
Ethan Furmanc16595e2016-09-10 23:36:59 -070044class auto:
45 """
46 Instances are replaced with an appropriate value in Enum class suites.
47 """
Ethan Furman3515dcc2016-09-18 13:15:41 -070048 value = _auto_null
Ethan Furmanc16595e2016-09-10 23:36:59 -070049
Ethan Furman101e0742013-09-15 12:34:36 -070050
Ethan Furman6b3d64a2013-06-14 16:55:46 -070051class _EnumDict(dict):
Ethan Furman101e0742013-09-15 12:34:36 -070052 """Track enum member order and ensure member names are not reused.
Ethan Furman6b3d64a2013-06-14 16:55:46 -070053
54 EnumMeta will use the names found in self._member_names as the
55 enumeration member names.
56
57 """
58 def __init__(self):
59 super().__init__()
60 self._member_names = []
Ethan Furmanc16595e2016-09-10 23:36:59 -070061 self._last_values = []
Ethan Furmana4b1bb42018-01-22 07:56:37 -080062 self._ignore = []
Ethan Onstottd9a43e22020-04-28 13:20:55 -040063 self._auto_called = False
Ethan Furman6b3d64a2013-06-14 16:55:46 -070064
65 def __setitem__(self, key, value):
Ethan Furman101e0742013-09-15 12:34:36 -070066 """Changes anything not dundered or not a descriptor.
Ethan Furman6b3d64a2013-06-14 16:55:46 -070067
68 If an enum member name is used twice, an error is raised; duplicate
69 values are not checked for.
70
71 Single underscore (sunder) names are reserved.
72
73 """
74 if _is_sunder(key):
Ethan Furmanee47e5c2016-08-31 00:12:15 -070075 if key not in (
Ethan Furman3515dcc2016-09-18 13:15:41 -070076 '_order_', '_create_pseudo_member_',
Ethan Furmana4b1bb42018-01-22 07:56:37 -080077 '_generate_next_value_', '_missing_', '_ignore_',
Ethan Furmanee47e5c2016-08-31 00:12:15 -070078 ):
Ethan Furmane8e61272016-08-20 07:19:31 -070079 raise ValueError('_names_ are reserved for future Enum use')
Ethan Furmanc16595e2016-09-10 23:36:59 -070080 if key == '_generate_next_value_':
Ethan Onstottd9a43e22020-04-28 13:20:55 -040081 # check if members already defined as auto()
82 if self._auto_called:
83 raise TypeError("_generate_next_value_ must be defined before members")
Ethan Furmanc16595e2016-09-10 23:36:59 -070084 setattr(self, '_generate_next_value', value)
Ethan Furmana4b1bb42018-01-22 07:56:37 -080085 elif key == '_ignore_':
86 if isinstance(value, str):
87 value = value.replace(',',' ').split()
88 else:
89 value = list(value)
90 self._ignore = value
91 already = set(value) & set(self._member_names)
92 if already:
93 raise ValueError('_ignore_ cannot specify already set names: %r' % (already, ))
Ethan Furman101e0742013-09-15 12:34:36 -070094 elif _is_dunder(key):
Ethan Furmane8e61272016-08-20 07:19:31 -070095 if key == '__order__':
96 key = '_order_'
Ethan Furman101e0742013-09-15 12:34:36 -070097 elif key in self._member_names:
98 # descriptor overwriting an enum?
99 raise TypeError('Attempted to reuse key: %r' % key)
Ethan Furmana4b1bb42018-01-22 07:56:37 -0800100 elif key in self._ignore:
101 pass
Ethan Furman101e0742013-09-15 12:34:36 -0700102 elif not _is_descriptor(value):
103 if key in self:
104 # enum overwriting a descriptor?
Ethan Furmanee47e5c2016-08-31 00:12:15 -0700105 raise TypeError('%r already defined as: %r' % (key, self[key]))
Ethan Furmanc16595e2016-09-10 23:36:59 -0700106 if isinstance(value, auto):
Ethan Furman3515dcc2016-09-18 13:15:41 -0700107 if value.value == _auto_null:
108 value.value = self._generate_next_value(key, 1, len(self._member_names), self._last_values[:])
Miss Islington (bot)4465df62020-09-16 17:27:09 -0700109 self._auto_called = True
Ethan Furman3515dcc2016-09-18 13:15:41 -0700110 value = value.value
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700111 self._member_names.append(key)
Ethan Furmanc16595e2016-09-10 23:36:59 -0700112 self._last_values.append(value)
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700113 super().__setitem__(key, value)
114
115
Ezio Melotti9a3777e2013-08-17 15:53:55 +0300116# Dummy value for Enum as EnumMeta explicitly checks for it, but of course
117# until EnumMeta finishes running the first time the Enum class doesn't exist.
118# This is also why there are checks in EnumMeta like `if Enum is not None`
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700119Enum = None
120
Ethan Furman332dbc72016-08-20 00:00:52 -0700121
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700122class EnumMeta(type):
123 """Metaclass for Enum"""
124 @classmethod
Ethan Furman332dbc72016-08-20 00:00:52 -0700125 def __prepare__(metacls, cls, bases):
Miss Islington (bot)48f99252020-09-16 07:35:14 -0700126 # check that previous enum members do not exist
127 metacls._check_for_existing_members(cls, bases)
Ethan Furmanee47e5c2016-08-31 00:12:15 -0700128 # create the namespace dict
129 enum_dict = _EnumDict()
130 # inherit previous flags and _generate_next_value_ function
Miss Islington (bot)48f99252020-09-16 07:35:14 -0700131 member_type, first_enum = metacls._get_mixins_(cls, bases)
Ethan Furmanee47e5c2016-08-31 00:12:15 -0700132 if first_enum is not None:
133 enum_dict['_generate_next_value_'] = getattr(first_enum, '_generate_next_value_', None)
134 return enum_dict
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700135
Ethan Furman65a5a472016-09-01 23:55:19 -0700136 def __new__(metacls, cls, bases, classdict):
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700137 # an Enum class is final once enumeration items have been defined; it
138 # cannot be mixed with other types (int, float, etc.) if it has an
139 # inherited __new__ unless a new __new__ is defined (or the resulting
140 # class will fail).
Ethan Furmana4b1bb42018-01-22 07:56:37 -0800141 #
142 # remove any keys listed in _ignore_
143 classdict.setdefault('_ignore_', []).append('_ignore_')
144 ignore = classdict['_ignore_']
145 for key in ignore:
146 classdict.pop(key, None)
Miss Islington (bot)48f99252020-09-16 07:35:14 -0700147 member_type, first_enum = metacls._get_mixins_(cls, bases)
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700148 __new__, save_new, use_args = metacls._find_new_(classdict, member_type,
149 first_enum)
150
151 # save enum items into separate mapping so they don't get baked into
152 # the new class
Ethan Furmanee47e5c2016-08-31 00:12:15 -0700153 enum_members = {k: classdict[k] for k in classdict._member_names}
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700154 for name in classdict._member_names:
155 del classdict[name]
156
Ethan Furmane8e61272016-08-20 07:19:31 -0700157 # adjust the sunders
158 _order_ = classdict.pop('_order_', None)
159
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700160 # check for illegal enum names (any others?)
Brennan D Baraban8b914d22019-03-03 14:09:11 -0800161 invalid_names = set(enum_members) & {'mro', ''}
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700162 if invalid_names:
163 raise ValueError('Invalid enum member name: {0}'.format(
164 ','.join(invalid_names)))
165
Ethan Furman48a724f2015-04-11 23:23:06 -0700166 # create a default docstring if one has not been provided
167 if '__doc__' not in classdict:
168 classdict['__doc__'] = 'An enumeration.'
169
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700170 # create our new Enum type
171 enum_class = super().__new__(metacls, cls, bases, classdict)
Ethan Furman520ad572013-07-19 19:47:21 -0700172 enum_class._member_names_ = [] # names in definition order
INADA Naokie57f91a2018-06-19 01:14:26 +0900173 enum_class._member_map_ = {} # name->value map
Ethan Furman5e5a8232013-08-04 08:42:23 -0700174 enum_class._member_type_ = member_type
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700175
orlnub1230fb9fad2018-09-12 20:28:53 +0300176 # save DynamicClassAttribute attributes from super classes so we know
177 # if we can take the shortcut of storing members in the class dict
178 dynamic_attributes = {k for c in enum_class.mro()
179 for k, v in c.__dict__.items()
180 if isinstance(v, DynamicClassAttribute)}
Ethan Furman354ecf12015-03-11 08:43:12 -0700181
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700182 # Reverse value->name map for hashable values.
Ethan Furman520ad572013-07-19 19:47:21 -0700183 enum_class._value2member_map_ = {}
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700184
Ethan Furman2da95042014-03-03 12:42:52 -0800185 # If a custom type is mixed into the Enum, and it does not know how
186 # to pickle itself, pickle.dumps will succeed but pickle.loads will
187 # fail. Rather than have the error show up later and possibly far
188 # from the source, sabotage the pickle protocol for this class so
189 # that pickle.dumps also fails.
190 #
191 # However, if the new class implements its own __reduce_ex__, do not
192 # sabotage -- it's on them to make sure it works correctly. We use
193 # __reduce_ex__ instead of any of the others as it is preferred by
194 # pickle over __reduce__, and it handles all pickle protocols.
195 if '__reduce_ex__' not in classdict:
Ethan Furmandc870522014-02-18 12:37:12 -0800196 if member_type is not object:
197 methods = ('__getnewargs_ex__', '__getnewargs__',
198 '__reduce_ex__', '__reduce__')
Ethan Furman2da95042014-03-03 12:42:52 -0800199 if not any(m in member_type.__dict__ for m in methods):
Ethan Furmandc870522014-02-18 12:37:12 -0800200 _make_class_unpicklable(enum_class)
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700201
202 # instantiate them, checking for duplicates as we go
203 # we instantiate first instead of checking for duplicates first in case
204 # a custom __new__ is doing something funky with the values -- such as
205 # auto-numbering ;)
206 for member_name in classdict._member_names:
Ethan Furmanee47e5c2016-08-31 00:12:15 -0700207 value = enum_members[member_name]
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700208 if not isinstance(value, tuple):
209 args = (value, )
210 else:
211 args = value
212 if member_type is tuple: # special case for tuple enums
213 args = (args, ) # wrap it one more time
214 if not use_args:
215 enum_member = __new__(enum_class)
Ethan Furmanb41803e2013-07-25 13:50:45 -0700216 if not hasattr(enum_member, '_value_'):
217 enum_member._value_ = value
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700218 else:
219 enum_member = __new__(enum_class, *args)
Ethan Furmanb41803e2013-07-25 13:50:45 -0700220 if not hasattr(enum_member, '_value_'):
Ethan Furmanee47e5c2016-08-31 00:12:15 -0700221 if member_type is object:
222 enum_member._value_ = value
223 else:
224 enum_member._value_ = member_type(*args)
Ethan Furman520ad572013-07-19 19:47:21 -0700225 value = enum_member._value_
Ethan Furman520ad572013-07-19 19:47:21 -0700226 enum_member._name_ = member_name
Ethan Furmanc850f342013-09-15 16:59:35 -0700227 enum_member.__objclass__ = enum_class
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700228 enum_member.__init__(*args)
229 # If another member with the same value was already defined, the
230 # new member becomes an alias to the existing one.
Ethan Furman520ad572013-07-19 19:47:21 -0700231 for name, canonical_member in enum_class._member_map_.items():
Ethan Furman0081f232014-09-16 17:31:23 -0700232 if canonical_member._value_ == enum_member._value_:
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700233 enum_member = canonical_member
234 break
235 else:
236 # Aliases don't appear in member names (only in __members__).
Ethan Furman520ad572013-07-19 19:47:21 -0700237 enum_class._member_names_.append(member_name)
Ethan Furman354ecf12015-03-11 08:43:12 -0700238 # performance boost for any member that would not shadow
239 # a DynamicClassAttribute
orlnub1230fb9fad2018-09-12 20:28:53 +0300240 if member_name not in dynamic_attributes:
Ethan Furman354ecf12015-03-11 08:43:12 -0700241 setattr(enum_class, member_name, enum_member)
242 # now add to _member_map_
Ethan Furman520ad572013-07-19 19:47:21 -0700243 enum_class._member_map_[member_name] = enum_member
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700244 try:
245 # This may fail if value is not hashable. We can't add the value
246 # to the map, and by-value lookups for this value will be
247 # linear.
Ethan Furman520ad572013-07-19 19:47:21 -0700248 enum_class._value2member_map_[value] = enum_member
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700249 except TypeError:
250 pass
251
252 # double check that repr and friends are not the mixin's or various
253 # things break (such as pickle)
Ethan Furmana4677062020-09-16 03:58:33 -0700254 # however, if the method is defined in the Enum itself, don't replace
255 # it
Ethan Furmandc870522014-02-18 12:37:12 -0800256 for name in ('__repr__', '__str__', '__format__', '__reduce_ex__'):
Ethan Furmana4677062020-09-16 03:58:33 -0700257 if name in classdict:
258 continue
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700259 class_method = getattr(enum_class, name)
260 obj_method = getattr(member_type, name, None)
261 enum_method = getattr(first_enum, name, None)
262 if obj_method is not None and obj_method is class_method:
263 setattr(enum_class, name, enum_method)
264
265 # replace any other __new__ with our own (as long as Enum is not None,
266 # anyway) -- again, this is to support pickle
267 if Enum is not None:
268 # if the user defined their own __new__, save it before it gets
269 # clobbered in case they subclass later
270 if save_new:
271 enum_class.__new_member__ = __new__
272 enum_class.__new__ = Enum.__new__
Ethan Furmane8e61272016-08-20 07:19:31 -0700273
274 # py3 support for definition order (helps keep py2/py3 code in sync)
275 if _order_ is not None:
276 if isinstance(_order_, str):
277 _order_ = _order_.replace(',', ' ').split()
278 if _order_ != enum_class._member_names_:
279 raise TypeError('member order does not match _order_')
280
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700281 return enum_class
282
Ethan Furman5de67b12016-04-13 23:52:09 -0700283 def __bool__(self):
284 """
285 classes/types should always be True.
286 """
287 return True
288
Ethan Furmand9925a12014-09-16 20:35:55 -0700289 def __call__(cls, value, names=None, *, module=None, qualname=None, type=None, start=1):
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700290 """Either returns an existing member, or creates a new enum class.
291
292 This method is used both when an enum class is given a value to match
293 to an enumeration member (i.e. Color(3)) and for the functional API
Ethan Furman23bb6f42016-11-21 09:22:05 -0800294 (i.e. Color = Enum('Color', names='RED GREEN BLUE')).
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700295
Ethan Furman2da95042014-03-03 12:42:52 -0800296 When used for the functional API:
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700297
Ethan Furman2da95042014-03-03 12:42:52 -0800298 `value` will be the name of the new class.
299
300 `names` should be either a string of white-space/comma delimited names
Ethan Furmand9925a12014-09-16 20:35:55 -0700301 (values will start at `start`), or an iterator/mapping of name, value pairs.
Ethan Furman2da95042014-03-03 12:42:52 -0800302
303 `module` should be set to the module this class is being created in;
304 if it is not set, an attempt to find that module will be made, but if
305 it fails the class will not be picklable.
306
307 `qualname` should be set to the actual location this class can be found
308 at in its module; by default it is set to the global scope. If this is
309 not correct, unpickling will fail in some circumstances.
310
311 `type`, if set, will be mixed in as the first base class.
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700312
313 """
314 if names is None: # simple value lookup
315 return cls.__new__(cls, value)
316 # otherwise, functional API: we're creating a new Enum type
Ethan Furmand9925a12014-09-16 20:35:55 -0700317 return cls._create_(value, names, module=module, qualname=qualname, type=type, start=start)
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700318
319 def __contains__(cls, member):
Rahul Jha94306522018-09-10 23:51:04 +0530320 if not isinstance(member, Enum):
321 raise TypeError(
322 "unsupported operand type(s) for 'in': '%s' and '%s'" % (
323 type(member).__qualname__, cls.__class__.__qualname__))
Ethan Furman0081f232014-09-16 17:31:23 -0700324 return isinstance(member, cls) and member._name_ in cls._member_map_
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700325
Ethan Furman64a99722013-09-22 16:18:19 -0700326 def __delattr__(cls, attr):
327 # nicer error message when someone tries to delete an attribute
328 # (see issue19025).
329 if attr in cls._member_map_:
330 raise AttributeError(
331 "%s: cannot delete Enum member." % cls.__name__)
332 super().__delattr__(attr)
333
Ethan Furman388a3922013-08-12 06:51:41 -0700334 def __dir__(self):
Ethan Furman64a99722013-09-22 16:18:19 -0700335 return (['__class__', '__doc__', '__members__', '__module__'] +
336 self._member_names_)
Ethan Furman388a3922013-08-12 06:51:41 -0700337
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700338 def __getattr__(cls, name):
339 """Return the enum member matching `name`
340
341 We use __getattr__ instead of descriptors or inserting into the enum
342 class' __dict__ in order to support `name` and `value` being both
343 properties for enum members (which live in the class' __dict__) and
344 enum members themselves.
345
346 """
347 if _is_dunder(name):
348 raise AttributeError(name)
349 try:
Ethan Furman520ad572013-07-19 19:47:21 -0700350 return cls._member_map_[name]
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700351 except KeyError:
352 raise AttributeError(name) from None
353
354 def __getitem__(cls, name):
Ethan Furman520ad572013-07-19 19:47:21 -0700355 return cls._member_map_[name]
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700356
357 def __iter__(cls):
Ethan Furman520ad572013-07-19 19:47:21 -0700358 return (cls._member_map_[name] for name in cls._member_names_)
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700359
360 def __len__(cls):
Ethan Furman520ad572013-07-19 19:47:21 -0700361 return len(cls._member_names_)
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700362
Ethan Furman2131a4a2013-09-14 18:11:24 -0700363 @property
364 def __members__(cls):
365 """Returns a mapping of member name->value.
366
367 This mapping lists all enum members, including aliases. Note that this
368 is a read-only view of the internal mapping.
369
370 """
371 return MappingProxyType(cls._member_map_)
372
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700373 def __repr__(cls):
374 return "<enum %r>" % cls.__name__
375
Ethan Furman2131a4a2013-09-14 18:11:24 -0700376 def __reversed__(cls):
377 return (cls._member_map_[name] for name in reversed(cls._member_names_))
378
Ethan Furmanf203f2d2013-09-06 07:16:48 -0700379 def __setattr__(cls, name, value):
380 """Block attempts to reassign Enum members.
381
382 A simple assignment to the class namespace only changes one of the
383 several possible ways to get an Enum member from the Enum class,
384 resulting in an inconsistent Enumeration.
385
386 """
387 member_map = cls.__dict__.get('_member_map_', {})
388 if name in member_map:
389 raise AttributeError('Cannot reassign members.')
390 super().__setattr__(name, value)
391
anentropicb8e21f12018-04-16 04:40:35 +0100392 def _create_(cls, class_name, names, *, module=None, qualname=None, type=None, start=1):
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700393 """Convenience method to create a new Enum class.
394
395 `names` can be:
396
397 * A string containing member names, separated either with spaces or
Ethan Furmand9925a12014-09-16 20:35:55 -0700398 commas. Values are incremented by 1 from `start`.
399 * An iterable of member names. Values are incremented by 1 from `start`.
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700400 * An iterable of (member name, value) pairs.
Ethan Furmand9925a12014-09-16 20:35:55 -0700401 * A mapping of member name -> value pairs.
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700402
403 """
404 metacls = cls.__class__
405 bases = (cls, ) if type is None else (type, cls)
Miss Islington (bot)48f99252020-09-16 07:35:14 -0700406 _, first_enum = cls._get_mixins_(cls, bases)
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700407 classdict = metacls.__prepare__(class_name, bases)
408
409 # special processing needed for names?
410 if isinstance(names, str):
411 names = names.replace(',', ' ').split()
Dong-hee Nadcc8ce42017-06-22 01:52:32 +0900412 if isinstance(names, (tuple, list)) and names and isinstance(names[0], str):
Ethan Furmanee47e5c2016-08-31 00:12:15 -0700413 original_names, names = names, []
Ethan Furmanc16595e2016-09-10 23:36:59 -0700414 last_values = []
Ethan Furmanee47e5c2016-08-31 00:12:15 -0700415 for count, name in enumerate(original_names):
Ethan Furmanc16595e2016-09-10 23:36:59 -0700416 value = first_enum._generate_next_value_(name, start, count, last_values[:])
417 last_values.append(value)
418 names.append((name, value))
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700419
420 # Here, names is either an iterable of (name, value) or a mapping.
421 for item in names:
422 if isinstance(item, str):
423 member_name, member_value = item, names[item]
424 else:
425 member_name, member_value = item
426 classdict[member_name] = member_value
427 enum_class = metacls.__new__(metacls, class_name, bases, classdict)
428
429 # TODO: replace the frame hack if a blessed way to know the calling
430 # module is ever developed
431 if module is None:
432 try:
433 module = sys._getframe(2).f_globals['__name__']
Pablo Galindo293dd232019-11-19 21:34:03 +0000434 except (AttributeError, ValueError, KeyError):
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700435 pass
436 if module is None:
437 _make_class_unpicklable(enum_class)
438 else:
439 enum_class.__module__ = module
Ethan Furmanca1b7942014-02-08 11:36:27 -0800440 if qualname is not None:
441 enum_class.__qualname__ = qualname
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700442
443 return enum_class
444
orlnub1230fb9fad2018-09-12 20:28:53 +0300445 def _convert_(cls, name, module, filter, source=None):
446 """
447 Create a new Enum subclass that replaces a collection of global constants
448 """
449 # convert all constants from source (or module) that pass filter() to
450 # a new Enum called name, and export the enum and its members back to
451 # module;
452 # also, replace the __reduce_ex__ method so unpickling works in
453 # previous Python versions
454 module_globals = vars(sys.modules[module])
455 if source:
456 source = vars(source)
457 else:
458 source = module_globals
459 # _value2member_map_ is populated in the same order every time
460 # for a consistent reverse mapping of number to name when there
461 # are multiple names for the same number.
462 members = [
463 (name, value)
464 for name, value in source.items()
465 if filter(name)]
466 try:
467 # sort by value
468 members.sort(key=lambda t: (t[1], t[0]))
469 except TypeError:
470 # unless some values aren't comparable, in which case sort by name
471 members.sort(key=lambda t: t[0])
472 cls = cls(name, members, module=module)
473 cls.__reduce_ex__ = _reduce_ex_by_name
474 module_globals.update(cls.__members__)
475 module_globals[name] = cls
476 return cls
477
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700478 @staticmethod
Miss Islington (bot)48f99252020-09-16 07:35:14 -0700479 def _check_for_existing_members(class_name, bases):
480 for chain in bases:
481 for base in chain.__mro__:
482 if issubclass(base, Enum) and base._member_names_:
483 raise TypeError("%s: cannot extend enumeration %r" % (class_name, base.__name__))
484
485 @staticmethod
486 def _get_mixins_(class_name, bases):
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700487 """Returns the type for creating enum members, and the first inherited
488 enum class.
489
490 bases: the tuple of bases that was given to __new__
491
492 """
493 if not bases:
494 return object, Enum
495
Ethan Furman5bdab642018-09-21 19:03:09 -0700496 def _find_data_type(bases):
Miss Islington (bot)95b81e22020-09-15 16:59:48 -0700497 data_types = []
Ethan Furman5bdab642018-09-21 19:03:09 -0700498 for chain in bases:
Miss Islington (bot)95b81e22020-09-15 16:59:48 -0700499 candidate = None
Ethan Furman5bdab642018-09-21 19:03:09 -0700500 for base in chain.__mro__:
501 if base is object:
502 continue
503 elif '__new__' in base.__dict__:
Ethan Furmancd453852018-10-05 23:29:36 -0700504 if issubclass(base, Enum):
Ethan Furman5bdab642018-09-21 19:03:09 -0700505 continue
Miss Islington (bot)95b81e22020-09-15 16:59:48 -0700506 data_types.append(candidate or base)
507 break
508 elif not issubclass(base, Enum):
509 candidate = base
510 if len(data_types) > 1:
Miss Islington (bot)48f99252020-09-16 07:35:14 -0700511 raise TypeError('%r: too many data types: %r' % (class_name, data_types))
Miss Islington (bot)95b81e22020-09-15 16:59:48 -0700512 elif data_types:
513 return data_types[0]
514 else:
515 return None
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700516
Ethan Furman5bdab642018-09-21 19:03:09 -0700517 # ensure final parent class is an Enum derivative, find any concrete
518 # data type, and check that Enum has no members
519 first_enum = bases[-1]
520 if not issubclass(first_enum, Enum):
521 raise TypeError("new enumerations should be created as "
522 "`EnumName([mixin_type, ...] [data_type,] enum_type)`")
523 member_type = _find_data_type(bases) or object
524 if first_enum._member_names_:
525 raise TypeError("Cannot extend enumerations")
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700526 return member_type, first_enum
527
528 @staticmethod
529 def _find_new_(classdict, member_type, first_enum):
530 """Returns the __new__ to be used for creating the enum members.
531
532 classdict: the class dictionary given to __new__
533 member_type: the data type whose __new__ will be used by default
534 first_enum: enumeration to check for an overriding __new__
535
536 """
537 # now find the correct __new__, checking to see of one was defined
538 # by the user; also check earlier enum classes in case a __new__ was
539 # saved as __new_member__
540 __new__ = classdict.get('__new__', None)
541
542 # should __new__ be saved as __new_member__ later?
543 save_new = __new__ is not None
544
545 if __new__ is None:
546 # check all possibles for __new_member__ before falling back to
547 # __new__
548 for method in ('__new_member__', '__new__'):
549 for possible in (member_type, first_enum):
550 target = getattr(possible, method, None)
551 if target not in {
552 None,
553 None.__new__,
554 object.__new__,
555 Enum.__new__,
556 }:
557 __new__ = target
558 break
559 if __new__ is not None:
560 break
561 else:
562 __new__ = object.__new__
563
564 # if a non-object.__new__ is used then whatever value/tuple was
565 # assigned to the enum member name will be passed to __new__ and to the
566 # new enum member's __init__
567 if __new__ is object.__new__:
568 use_args = False
569 else:
570 use_args = True
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700571 return __new__, save_new, use_args
572
573
574class Enum(metaclass=EnumMeta):
575 """Generic enumeration.
576
577 Derive from this class to define new enumerations.
578
579 """
580 def __new__(cls, value):
581 # all enum instances are actually created during class construction
582 # without calling this method; this method is called by the metaclass'
583 # __call__ (i.e. Color(3) ), and by pickle
584 if type(value) is cls:
Ethan Furman23bb6f42016-11-21 09:22:05 -0800585 # For lookups like Color(Color.RED)
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700586 return value
587 # by-value search for a matching enum member
588 # see if it's in the reverse mapping (for hashable values)
Ethan Furman2aa27322013-07-19 19:35:56 -0700589 try:
Andrew Svetlov34ae04f2018-12-26 20:45:33 +0200590 return cls._value2member_map_[value]
591 except KeyError:
592 # Not found, no need to do long O(n) search
593 pass
Ethan Furman2aa27322013-07-19 19:35:56 -0700594 except TypeError:
595 # not there, now do long search -- O(n) behavior
Ethan Furman520ad572013-07-19 19:47:21 -0700596 for member in cls._member_map_.values():
Ethan Furman0081f232014-09-16 17:31:23 -0700597 if member._value_ == value:
Ethan Furman2aa27322013-07-19 19:35:56 -0700598 return member
Ethan Furmanee47e5c2016-08-31 00:12:15 -0700599 # still not found -- try _missing_ hook
Ethan Furman019f0a02018-09-12 11:43:34 -0700600 try:
601 exc = None
602 result = cls._missing_(value)
603 except Exception as e:
604 exc = e
605 result = None
606 if isinstance(result, cls):
607 return result
608 else:
Walter Dörwald323842c2019-07-18 20:37:13 +0200609 ve_exc = ValueError("%r is not a valid %s" % (value, cls.__qualname__))
Ethan Furman019f0a02018-09-12 11:43:34 -0700610 if result is None and exc is None:
611 raise ve_exc
612 elif exc is None:
613 exc = TypeError(
614 'error in %s._missing_: returned %r instead of None or a valid member'
615 % (cls.__name__, result)
616 )
617 exc.__context__ = ve_exc
618 raise exc
Ethan Furmanee47e5c2016-08-31 00:12:15 -0700619
Ethan Furmanc16595e2016-09-10 23:36:59 -0700620 def _generate_next_value_(name, start, count, last_values):
621 for last_value in reversed(last_values):
622 try:
623 return last_value + 1
624 except TypeError:
625 pass
626 else:
Ethan Furmanee47e5c2016-08-31 00:12:15 -0700627 return start
Ethan Furmanc16595e2016-09-10 23:36:59 -0700628
Ethan Furmanee47e5c2016-08-31 00:12:15 -0700629 @classmethod
630 def _missing_(cls, value):
Ethan Furmana9ba8ba2020-09-16 17:37:51 -0700631 return None
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700632
633 def __repr__(self):
634 return "<%s.%s: %r>" % (
Ethan Furman520ad572013-07-19 19:47:21 -0700635 self.__class__.__name__, self._name_, self._value_)
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700636
637 def __str__(self):
Ethan Furman520ad572013-07-19 19:47:21 -0700638 return "%s.%s" % (self.__class__.__name__, self._name_)
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700639
Ethan Furman388a3922013-08-12 06:51:41 -0700640 def __dir__(self):
Ethan Furman0ae550b2014-10-14 08:58:32 -0700641 added_behavior = [
642 m
643 for cls in self.__class__.mro()
644 for m in cls.__dict__
Ethan Furman354ecf12015-03-11 08:43:12 -0700645 if m[0] != '_' and m not in self._member_map_
Ethan Furman0ae550b2014-10-14 08:58:32 -0700646 ]
Ethan Furmanec5f8eb2014-10-21 13:40:35 -0700647 return (['__class__', '__doc__', '__module__'] + added_behavior)
Ethan Furman388a3922013-08-12 06:51:41 -0700648
Ethan Furmanec15a822013-08-31 19:17:41 -0700649 def __format__(self, format_spec):
650 # mixed-in Enums should use the mixed-in type's __format__, otherwise
651 # we can get strange results with the Enum name showing up instead of
652 # the value
653
thatneat2f19e822019-07-04 11:28:37 -0700654 # pure Enum branch, or branch with __str__ explicitly overridden
655 str_overridden = type(self).__str__ != Enum.__str__
656 if self._member_type_ is object or str_overridden:
Ethan Furmanec15a822013-08-31 19:17:41 -0700657 cls = str
658 val = str(self)
659 # mix-in branch
660 else:
661 cls = self._member_type_
Ethan Furman0081f232014-09-16 17:31:23 -0700662 val = self._value_
Ethan Furmanec15a822013-08-31 19:17:41 -0700663 return cls.__format__(val, format_spec)
664
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700665 def __hash__(self):
Ethan Furman520ad572013-07-19 19:47:21 -0700666 return hash(self._name_)
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700667
Ethan Furmanca1b7942014-02-08 11:36:27 -0800668 def __reduce_ex__(self, proto):
Ethan Furmandc870522014-02-18 12:37:12 -0800669 return self.__class__, (self._value_, )
Ethan Furmanca1b7942014-02-08 11:36:27 -0800670
Ethan Furman33918c12013-09-27 23:02:02 -0700671 # DynamicClassAttribute is used to provide access to the `name` and
672 # `value` properties of enum members while keeping some measure of
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700673 # protection from modification, while still allowing for an enumeration
674 # to have members named `name` and `value`. This works because enumeration
675 # members are not set directly on the enum class -- __getattr__ is
676 # used to look them up.
677
Ethan Furmane03ea372013-09-25 07:14:41 -0700678 @DynamicClassAttribute
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700679 def name(self):
Ethan Furmanc850f342013-09-15 16:59:35 -0700680 """The name of the Enum member."""
Ethan Furman520ad572013-07-19 19:47:21 -0700681 return self._name_
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700682
Ethan Furmane03ea372013-09-25 07:14:41 -0700683 @DynamicClassAttribute
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700684 def value(self):
Ethan Furmanc850f342013-09-15 16:59:35 -0700685 """The value of the Enum member."""
Ethan Furman520ad572013-07-19 19:47:21 -0700686 return self._value_
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700687
688
689class IntEnum(int, Enum):
690 """Enum where members are also (and must be) ints"""
Ethan Furmanf24bb352013-07-18 17:05:39 -0700691
692
Ethan Furman24e837f2015-03-18 17:27:57 -0700693def _reduce_ex_by_name(self, proto):
694 return self.name
695
Ethan Furman65a5a472016-09-01 23:55:19 -0700696class Flag(Enum):
Ethan Furmanee47e5c2016-08-31 00:12:15 -0700697 """Support for flags"""
Ethan Furmanc16595e2016-09-10 23:36:59 -0700698
699 def _generate_next_value_(name, start, count, last_values):
Ethan Furmanee47e5c2016-08-31 00:12:15 -0700700 """
701 Generate the next value when not given.
702
703 name: the name of the member
HongWeipengbb16fb22019-09-21 13:22:54 +0800704 start: the initial start value or None
Ethan Furmanee47e5c2016-08-31 00:12:15 -0700705 count: the number of existing members
706 last_value: the last value assigned or None
707 """
708 if not count:
709 return start if start is not None else 1
Ethan Furmanc16595e2016-09-10 23:36:59 -0700710 for last_value in reversed(last_values):
711 try:
712 high_bit = _high_bit(last_value)
713 break
Ethan Furman3515dcc2016-09-18 13:15:41 -0700714 except Exception:
Ethan Furmanc16595e2016-09-10 23:36:59 -0700715 raise TypeError('Invalid Flag value: %r' % last_value) from None
Ethan Furmanee47e5c2016-08-31 00:12:15 -0700716 return 2 ** (high_bit+1)
717
718 @classmethod
719 def _missing_(cls, value):
720 original_value = value
721 if value < 0:
722 value = ~value
723 possible_member = cls._create_pseudo_member_(value)
Ethan Furmanee47e5c2016-08-31 00:12:15 -0700724 if original_value < 0:
725 possible_member = ~possible_member
726 return possible_member
727
728 @classmethod
729 def _create_pseudo_member_(cls, value):
Ethan Furman3515dcc2016-09-18 13:15:41 -0700730 """
731 Create a composite member iff value contains only members.
732 """
Ethan Furmanee47e5c2016-08-31 00:12:15 -0700733 pseudo_member = cls._value2member_map_.get(value, None)
734 if pseudo_member is None:
Ethan Furman3515dcc2016-09-18 13:15:41 -0700735 # verify all bits are accounted for
736 _, extra_flags = _decompose(cls, value)
737 if extra_flags:
Walter Dörwald323842c2019-07-18 20:37:13 +0200738 raise ValueError("%r is not a valid %s" % (value, cls.__qualname__))
Ethan Furman3515dcc2016-09-18 13:15:41 -0700739 # construct a singleton enum pseudo-member
Ethan Furmanee47e5c2016-08-31 00:12:15 -0700740 pseudo_member = object.__new__(cls)
741 pseudo_member._name_ = None
742 pseudo_member._value_ = value
Ethan Furman28cf6632017-01-24 12:12:06 -0800743 # use setdefault in case another thread already created a composite
744 # with this value
745 pseudo_member = cls._value2member_map_.setdefault(value, pseudo_member)
Ethan Furmanee47e5c2016-08-31 00:12:15 -0700746 return pseudo_member
747
Ethan Furmanee47e5c2016-08-31 00:12:15 -0700748 def __contains__(self, other):
749 if not isinstance(other, self.__class__):
Rahul Jha94306522018-09-10 23:51:04 +0530750 raise TypeError(
751 "unsupported operand type(s) for 'in': '%s' and '%s'" % (
752 type(other).__qualname__, self.__class__.__qualname__))
Ethan Furmanee47e5c2016-08-31 00:12:15 -0700753 return other._value_ & self._value_ == other._value_
754
Ethan Furmanee47e5c2016-08-31 00:12:15 -0700755 def __repr__(self):
756 cls = self.__class__
757 if self._name_ is not None:
758 return '<%s.%s: %r>' % (cls.__name__, self._name_, self._value_)
Ethan Furman3515dcc2016-09-18 13:15:41 -0700759 members, uncovered = _decompose(cls, self._value_)
Ethan Furman27682d22016-09-04 11:39:01 -0700760 return '<%s.%s: %r>' % (
761 cls.__name__,
762 '|'.join([str(m._name_ or m._value_) for m in members]),
763 self._value_,
764 )
Ethan Furmanee47e5c2016-08-31 00:12:15 -0700765
766 def __str__(self):
767 cls = self.__class__
768 if self._name_ is not None:
769 return '%s.%s' % (cls.__name__, self._name_)
Ethan Furman3515dcc2016-09-18 13:15:41 -0700770 members, uncovered = _decompose(cls, self._value_)
Ethan Furmanee47e5c2016-08-31 00:12:15 -0700771 if len(members) == 1 and members[0]._name_ is None:
772 return '%s.%r' % (cls.__name__, members[0]._value_)
773 else:
774 return '%s.%s' % (
775 cls.__name__,
776 '|'.join([str(m._name_ or m._value_) for m in members]),
777 )
778
Ethan Furman25d94bb2016-09-02 16:32:32 -0700779 def __bool__(self):
780 return bool(self._value_)
781
Ethan Furmanee47e5c2016-08-31 00:12:15 -0700782 def __or__(self, other):
783 if not isinstance(other, self.__class__):
784 return NotImplemented
785 return self.__class__(self._value_ | other._value_)
786
787 def __and__(self, other):
788 if not isinstance(other, self.__class__):
789 return NotImplemented
790 return self.__class__(self._value_ & other._value_)
791
792 def __xor__(self, other):
793 if not isinstance(other, self.__class__):
794 return NotImplemented
795 return self.__class__(self._value_ ^ other._value_)
796
797 def __invert__(self):
Ethan Furman3515dcc2016-09-18 13:15:41 -0700798 members, uncovered = _decompose(self.__class__, self._value_)
Serhiy Storchaka81108372017-09-26 00:55:55 +0300799 inverted = self.__class__(0)
800 for m in self.__class__:
801 if m not in members and not (m._value_ & self._value_):
802 inverted = inverted | m
Ethan Furmanee47e5c2016-08-31 00:12:15 -0700803 return self.__class__(inverted)
804
805
Ethan Furman65a5a472016-09-01 23:55:19 -0700806class IntFlag(int, Flag):
Ethan Furmanee47e5c2016-08-31 00:12:15 -0700807 """Support for integer-based Flags"""
808
809 @classmethod
Ethan Furman3515dcc2016-09-18 13:15:41 -0700810 def _missing_(cls, value):
811 if not isinstance(value, int):
Walter Dörwald323842c2019-07-18 20:37:13 +0200812 raise ValueError("%r is not a valid %s" % (value, cls.__qualname__))
Ethan Furman3515dcc2016-09-18 13:15:41 -0700813 new_member = cls._create_pseudo_member_(value)
814 return new_member
815
816 @classmethod
Ethan Furmanee47e5c2016-08-31 00:12:15 -0700817 def _create_pseudo_member_(cls, value):
818 pseudo_member = cls._value2member_map_.get(value, None)
819 if pseudo_member is None:
Ethan Furman3515dcc2016-09-18 13:15:41 -0700820 need_to_create = [value]
821 # get unaccounted for bits
822 _, extra_flags = _decompose(cls, value)
823 # timer = 10
824 while extra_flags:
825 # timer -= 1
826 bit = _high_bit(extra_flags)
827 flag_value = 2 ** bit
828 if (flag_value not in cls._value2member_map_ and
829 flag_value not in need_to_create
830 ):
831 need_to_create.append(flag_value)
832 if extra_flags == -flag_value:
833 extra_flags = 0
834 else:
835 extra_flags ^= flag_value
836 for value in reversed(need_to_create):
837 # construct singleton pseudo-members
838 pseudo_member = int.__new__(cls, value)
839 pseudo_member._name_ = None
840 pseudo_member._value_ = value
Ethan Furman28cf6632017-01-24 12:12:06 -0800841 # use setdefault in case another thread already created a composite
842 # with this value
843 pseudo_member = cls._value2member_map_.setdefault(value, pseudo_member)
Ethan Furmanee47e5c2016-08-31 00:12:15 -0700844 return pseudo_member
845
Ethan Furmanee47e5c2016-08-31 00:12:15 -0700846 def __or__(self, other):
847 if not isinstance(other, (self.__class__, int)):
848 return NotImplemented
Ethan Furman3515dcc2016-09-18 13:15:41 -0700849 result = self.__class__(self._value_ | self.__class__(other)._value_)
850 return result
Ethan Furmanee47e5c2016-08-31 00:12:15 -0700851
852 def __and__(self, other):
853 if not isinstance(other, (self.__class__, int)):
854 return NotImplemented
855 return self.__class__(self._value_ & self.__class__(other)._value_)
856
857 def __xor__(self, other):
858 if not isinstance(other, (self.__class__, int)):
859 return NotImplemented
860 return self.__class__(self._value_ ^ self.__class__(other)._value_)
861
862 __ror__ = __or__
863 __rand__ = __and__
864 __rxor__ = __xor__
865
866 def __invert__(self):
Ethan Furman3515dcc2016-09-18 13:15:41 -0700867 result = self.__class__(~self._value_)
868 return result
Ethan Furmanee47e5c2016-08-31 00:12:15 -0700869
870
871def _high_bit(value):
Ethan Furman04439532016-09-02 15:50:21 -0700872 """returns index of highest bit, or -1 if value is zero or negative"""
Ethan Furman3515dcc2016-09-18 13:15:41 -0700873 return value.bit_length() - 1
Ethan Furmanee47e5c2016-08-31 00:12:15 -0700874
Ethan Furmanf24bb352013-07-18 17:05:39 -0700875def unique(enumeration):
876 """Class decorator for enumerations ensuring unique member values."""
877 duplicates = []
878 for name, member in enumeration.__members__.items():
879 if name != member.name:
880 duplicates.append((name, member.name))
881 if duplicates:
882 alias_details = ', '.join(
883 ["%s -> %s" % (alias, name) for (alias, name) in duplicates])
884 raise ValueError('duplicate values found in %r: %s' %
885 (enumeration, alias_details))
886 return enumeration
Ethan Furman3515dcc2016-09-18 13:15:41 -0700887
888def _decompose(flag, value):
889 """Extract all members from the value."""
890 # _decompose is only called if the value is not named
891 not_covered = value
892 negative = value < 0
Ethan Furman3515dcc2016-09-18 13:15:41 -0700893 members = []
HongWeipeng0b41a922019-11-27 06:36:02 +0800894 for member in flag:
895 member_value = member.value
Ethan Furman3515dcc2016-09-18 13:15:41 -0700896 if member_value and member_value & value == member_value:
897 members.append(member)
898 not_covered &= ~member_value
HongWeipeng0b41a922019-11-27 06:36:02 +0800899 if not negative:
900 tmp = not_covered
901 while tmp:
902 flag_value = 2 ** _high_bit(tmp)
903 if flag_value in flag._value2member_map_:
904 members.append(flag._value2member_map_[flag_value])
905 not_covered &= ~flag_value
906 tmp &= ~flag_value
Ethan Furman3515dcc2016-09-18 13:15:41 -0700907 if not members and value in flag._value2member_map_:
908 members.append(flag._value2member_map_[value])
909 members.sort(key=lambda m: m._value_, reverse=True)
910 if len(members) > 1 and members[0].value == value:
911 # we have the breakdown, don't need the value member itself
912 members.pop(0)
913 return members, not_covered