blob: 84c7b0dc2afbef7ce40632ab4fa42e8040bc41e6 [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 Furman7aaeb2a2021-01-25 14:26:19 -08003from builtins import property as _bltin_property, bin as _bltin_bin
Ethan Furman6b3d64a2013-06-14 16:55:46 -07004
Ethan Furmane5754ab2015-09-17 22:03:52 -07005
Ethan Furmanc16595e2016-09-10 23:36:59 -07006__all__ = [
7 'EnumMeta',
Ethan Furman0063ff42020-09-21 17:23:13 -07008 'Enum', 'IntEnum', 'StrEnum', 'Flag', 'IntFlag',
Ethan Furmanc16595e2016-09-10 23:36:59 -07009 'auto', 'unique',
Ethan Furmanc314e602021-01-12 23:47:57 -080010 'property',
Ethan Furman7aaeb2a2021-01-25 14:26:19 -080011 'FlagBoundary', 'STRICT', 'CONFORM', 'EJECT', 'KEEP',
Ethan Furmanc16595e2016-09-10 23:36:59 -070012 ]
Ethan Furman6b3d64a2013-06-14 16:55:46 -070013
14
Ethan Furman7aaeb2a2021-01-25 14:26:19 -080015# Dummy value for Enum and Flag as there are explicit checks for them
16# before they have been created.
17# This is also why there are checks in EnumMeta like `if Enum is not None`
18Enum = Flag = EJECT = None
19
Ethan Furman101e0742013-09-15 12:34:36 -070020def _is_descriptor(obj):
Ethan Furman6d3dfee2020-12-08 12:26:56 -080021 """
22 Returns True if obj is a descriptor, False otherwise.
23 """
Ethan Furman101e0742013-09-15 12:34:36 -070024 return (
25 hasattr(obj, '__get__') or
26 hasattr(obj, '__set__') or
Ethan Furman6d3dfee2020-12-08 12:26:56 -080027 hasattr(obj, '__delete__')
28 )
Ethan Furman101e0742013-09-15 12:34:36 -070029
Ethan Furman6b3d64a2013-06-14 16:55:46 -070030def _is_dunder(name):
Ethan Furman6d3dfee2020-12-08 12:26:56 -080031 """
32 Returns True if a __dunder__ name, False otherwise.
33 """
34 return (
35 len(name) > 4 and
Brennan D Baraban8b914d22019-03-03 14:09:11 -080036 name[:2] == name[-2:] == '__' and
37 name[2] != '_' and
Ethan Furman6d3dfee2020-12-08 12:26:56 -080038 name[-3] != '_'
39 )
Ethan Furman6b3d64a2013-06-14 16:55:46 -070040
41def _is_sunder(name):
Ethan Furman6d3dfee2020-12-08 12:26:56 -080042 """
43 Returns True if a _sunder_ name, False otherwise.
44 """
45 return (
46 len(name) > 2 and
Brennan D Baraban8b914d22019-03-03 14:09:11 -080047 name[0] == name[-1] == '_' and
Ethan Furman6b3d64a2013-06-14 16:55:46 -070048 name[1:2] != '_' and
Ethan Furman6d3dfee2020-12-08 12:26:56 -080049 name[-2:-1] != '_'
50 )
Ethan Furman6b3d64a2013-06-14 16:55:46 -070051
Ethan Furman7cf0aad2020-12-09 17:12:11 -080052def _is_private(cls_name, name):
53 # do not use `re` as `re` imports `enum`
54 pattern = '_%s__' % (cls_name, )
55 if (
56 len(name) >= 5
57 and name.startswith(pattern)
58 and name[len(pattern)] != '_'
59 and (name[-1] != '_' or name[-2] != '_')
60 ):
61 return True
62 else:
63 return False
64
Ethan Furman7aaeb2a2021-01-25 14:26:19 -080065def _is_single_bit(num):
66 """
67 True if only one bit set in num (should be an int)
68 """
69 if num == 0:
70 return False
71 num &= num - 1
72 return num == 0
73
Ethan Furmanc314e602021-01-12 23:47:57 -080074def _make_class_unpicklable(obj):
Ethan Furman6d3dfee2020-12-08 12:26:56 -080075 """
Ethan Furmanc314e602021-01-12 23:47:57 -080076 Make the given obj un-picklable.
77
78 obj should be either a dictionary, on an Enum
Ethan Furman6d3dfee2020-12-08 12:26:56 -080079 """
Ethan Furmanca1b7942014-02-08 11:36:27 -080080 def _break_on_call_reduce(self, proto):
Ethan Furman6b3d64a2013-06-14 16:55:46 -070081 raise TypeError('%r cannot be pickled' % self)
Ethan Furmanc314e602021-01-12 23:47:57 -080082 if isinstance(obj, dict):
83 obj['__reduce_ex__'] = _break_on_call_reduce
84 obj['__module__'] = '<unknown>'
85 else:
86 setattr(obj, '__reduce_ex__', _break_on_call_reduce)
87 setattr(obj, '__module__', '<unknown>')
Ethan Furman6b3d64a2013-06-14 16:55:46 -070088
Ethan Furman7aaeb2a2021-01-25 14:26:19 -080089def _iter_bits_lsb(num):
90 while num:
91 b = num & (~num + 1)
92 yield b
93 num ^= b
94
95def bin(num, max_bits=None):
96 """
97 Like built-in bin(), except negative values are represented in
98 twos-compliment, and the leading bit always indicates sign
99 (0=positive, 1=negative).
100
101 >>> bin(10)
102 '0b0 1010'
103 >>> bin(~10) # ~10 is -11
104 '0b1 0101'
105 """
106
107 ceiling = 2 ** (num).bit_length()
108 if num >= 0:
109 s = _bltin_bin(num + ceiling).replace('1', '0', 1)
110 else:
111 s = _bltin_bin(~num ^ (ceiling - 1) + ceiling)
112 sign = s[:3]
113 digits = s[3:]
114 if max_bits is not None:
115 if len(digits) < max_bits:
116 digits = (sign[-1] * max_bits + digits)[-max_bits:]
117 return "%s %s" % (sign, digits)
118
119
Ethan Furman3515dcc2016-09-18 13:15:41 -0700120_auto_null = object()
Ethan Furmanc16595e2016-09-10 23:36:59 -0700121class auto:
122 """
123 Instances are replaced with an appropriate value in Enum class suites.
124 """
Ethan Furman3515dcc2016-09-18 13:15:41 -0700125 value = _auto_null
Ethan Furmanc16595e2016-09-10 23:36:59 -0700126
Ethan Furmanc314e602021-01-12 23:47:57 -0800127class property(DynamicClassAttribute):
128 """
129 This is a descriptor, used to define attributes that act differently
130 when accessed through an enum member and through an enum class.
131 Instance access is the same as property(), but access to an attribute
132 through the enum class will instead look in the class' _member_map_ for
133 a corresponding enum member.
134 """
135
136 def __get__(self, instance, ownerclass=None):
137 if instance is None:
138 try:
139 return ownerclass._member_map_[self.name]
140 except KeyError:
Ethan Furman7aaeb2a2021-01-25 14:26:19 -0800141 raise AttributeError(
Ethan Furmand65b9032021-02-08 17:32:38 -0800142 '%s: no class attribute %r' % (ownerclass.__name__, self.name)
Ethan Furman7aaeb2a2021-01-25 14:26:19 -0800143 )
Ethan Furmanc314e602021-01-12 23:47:57 -0800144 else:
145 if self.fget is None:
Ethan Furmand65b9032021-02-08 17:32:38 -0800146 # check for member
147 if self.name in ownerclass._member_map_:
148 import warnings
149 warnings.warn(
150 "accessing one member from another is not supported, "
Ethan Furman44e580f2021-03-03 09:54:30 -0800151 " and will be disabled in 3.12",
Ethan Furmand65b9032021-02-08 17:32:38 -0800152 DeprecationWarning,
153 stacklevel=2,
154 )
155 return ownerclass._member_map_[self.name]
Ethan Furman7aaeb2a2021-01-25 14:26:19 -0800156 raise AttributeError(
Ethan Furmand65b9032021-02-08 17:32:38 -0800157 '%s: no instance attribute %r' % (ownerclass.__name__, self.name)
Ethan Furman7aaeb2a2021-01-25 14:26:19 -0800158 )
Ethan Furmanc314e602021-01-12 23:47:57 -0800159 else:
160 return self.fget(instance)
161
162 def __set__(self, instance, value):
163 if self.fset is None:
Ethan Furman7aaeb2a2021-01-25 14:26:19 -0800164 raise AttributeError(
Ethan Furmand65b9032021-02-08 17:32:38 -0800165 "%s: cannot set instance attribute %r" % (self.clsname, self.name)
Ethan Furman7aaeb2a2021-01-25 14:26:19 -0800166 )
Ethan Furmanc314e602021-01-12 23:47:57 -0800167 else:
168 return self.fset(instance, value)
169
170 def __delete__(self, instance):
171 if self.fdel is None:
Ethan Furman7aaeb2a2021-01-25 14:26:19 -0800172 raise AttributeError(
Ethan Furmand65b9032021-02-08 17:32:38 -0800173 "%s: cannot delete instance attribute %r" % (self.clsname, self.name)
Ethan Furman7aaeb2a2021-01-25 14:26:19 -0800174 )
Ethan Furmanc314e602021-01-12 23:47:57 -0800175 else:
176 return self.fdel(instance)
177
178 def __set_name__(self, ownerclass, name):
179 self.name = name
180 self.clsname = ownerclass.__name__
181
182
183class _proto_member:
184 """
185 intermediate step for enum members between class execution and final creation
186 """
187
188 def __init__(self, value):
189 self.value = value
190
191 def __set_name__(self, enum_class, member_name):
192 """
193 convert each quasi-member into an instance of the new enum class
194 """
195 # first step: remove ourself from enum_class
196 delattr(enum_class, member_name)
197 # second step: create member based on enum_class
198 value = self.value
199 if not isinstance(value, tuple):
200 args = (value, )
201 else:
202 args = value
203 if enum_class._member_type_ is tuple: # special case for tuple enums
204 args = (args, ) # wrap it one more time
205 if not enum_class._use_args_:
206 enum_member = enum_class._new_member_(enum_class)
207 if not hasattr(enum_member, '_value_'):
208 enum_member._value_ = value
209 else:
210 enum_member = enum_class._new_member_(enum_class, *args)
211 if not hasattr(enum_member, '_value_'):
212 if enum_class._member_type_ is object:
213 enum_member._value_ = value
214 else:
Ethan Furman7aaeb2a2021-01-25 14:26:19 -0800215 try:
216 enum_member._value_ = enum_class._member_type_(*args)
217 except Exception as exc:
218 raise TypeError(
219 '_value_ not set in __new__, unable to create it'
220 ) from None
Ethan Furmanc314e602021-01-12 23:47:57 -0800221 value = enum_member._value_
222 enum_member._name_ = member_name
223 enum_member.__objclass__ = enum_class
224 enum_member.__init__(*args)
Ethan Furman7aaeb2a2021-01-25 14:26:19 -0800225 enum_member._sort_order_ = len(enum_class._member_names_)
Ethan Furmanc314e602021-01-12 23:47:57 -0800226 # If another member with the same value was already defined, the
227 # new member becomes an alias to the existing one.
228 for name, canonical_member in enum_class._member_map_.items():
229 if canonical_member._value_ == enum_member._value_:
230 enum_member = canonical_member
231 break
232 else:
Ethan Furman7aaeb2a2021-01-25 14:26:19 -0800233 # this could still be an alias if the value is multi-bit and the
234 # class is a flag class
235 if (
236 Flag is None
237 or not issubclass(enum_class, Flag)
238 ):
239 # no other instances found, record this member in _member_names_
240 enum_class._member_names_.append(member_name)
241 elif (
242 Flag is not None
243 and issubclass(enum_class, Flag)
244 and _is_single_bit(value)
245 ):
246 # no other instances found, record this member in _member_names_
247 enum_class._member_names_.append(member_name)
Ethan Furmanc314e602021-01-12 23:47:57 -0800248 # get redirect in place before adding to _member_map_
249 # but check for other instances in parent classes first
250 need_override = False
251 descriptor = None
252 for base in enum_class.__mro__[1:]:
253 descriptor = base.__dict__.get(member_name)
254 if descriptor is not None:
255 if isinstance(descriptor, (property, DynamicClassAttribute)):
256 break
257 else:
258 need_override = True
259 # keep looking for an enum.property
260 if descriptor and not need_override:
261 # previous enum.property found, no further action needed
262 pass
263 else:
264 redirect = property()
265 redirect.__set_name__(enum_class, member_name)
266 if descriptor and need_override:
267 # previous enum.property found, but some other inherited attribute
268 # is in the way; copy fget, fset, fdel to this one
269 redirect.fget = descriptor.fget
270 redirect.fset = descriptor.fset
271 redirect.fdel = descriptor.fdel
272 setattr(enum_class, member_name, redirect)
273 # now add to _member_map_ (even aliases)
274 enum_class._member_map_[member_name] = enum_member
275 try:
276 # This may fail if value is not hashable. We can't add the value
277 # to the map, and by-value lookups for this value will be
278 # linear.
Ethan Furman7aaeb2a2021-01-25 14:26:19 -0800279 enum_class._value2member_map_.setdefault(value, enum_member)
Ethan Furmanc314e602021-01-12 23:47:57 -0800280 except TypeError:
281 pass
282
Ethan Furman101e0742013-09-15 12:34:36 -0700283
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700284class _EnumDict(dict):
Ethan Furman6d3dfee2020-12-08 12:26:56 -0800285 """
286 Track enum member order and ensure member names are not reused.
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700287
288 EnumMeta will use the names found in self._member_names as the
289 enumeration member names.
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700290 """
291 def __init__(self):
292 super().__init__()
293 self._member_names = []
Ethan Furmanc16595e2016-09-10 23:36:59 -0700294 self._last_values = []
Ethan Furmana4b1bb42018-01-22 07:56:37 -0800295 self._ignore = []
Ethan Onstottd9a43e22020-04-28 13:20:55 -0400296 self._auto_called = False
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700297
298 def __setitem__(self, key, value):
Ethan Furman6d3dfee2020-12-08 12:26:56 -0800299 """
300 Changes anything not dundered or not a descriptor.
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700301
302 If an enum member name is used twice, an error is raised; duplicate
303 values are not checked for.
304
305 Single underscore (sunder) names are reserved.
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700306 """
Ethan Furman7cf0aad2020-12-09 17:12:11 -0800307 if _is_private(self._cls_name, key):
308 # do nothing, name will be a normal attribute
309 pass
310 elif _is_sunder(key):
Ethan Furmanee47e5c2016-08-31 00:12:15 -0700311 if key not in (
Ethan Furman3515dcc2016-09-18 13:15:41 -0700312 '_order_', '_create_pseudo_member_',
Ethan Furmana4b1bb42018-01-22 07:56:37 -0800313 '_generate_next_value_', '_missing_', '_ignore_',
Ethan Furman7aaeb2a2021-01-25 14:26:19 -0800314 '_iter_member_', '_iter_member_by_value_', '_iter_member_by_def_',
Ethan Furmanee47e5c2016-08-31 00:12:15 -0700315 ):
Ethan Furman6d3dfee2020-12-08 12:26:56 -0800316 raise ValueError(
317 '_sunder_ names, such as %r, are reserved for future Enum use'
318 % (key, )
319 )
Ethan Furmanc16595e2016-09-10 23:36:59 -0700320 if key == '_generate_next_value_':
Ethan Onstottd9a43e22020-04-28 13:20:55 -0400321 # check if members already defined as auto()
322 if self._auto_called:
323 raise TypeError("_generate_next_value_ must be defined before members")
Ethan Furmanc16595e2016-09-10 23:36:59 -0700324 setattr(self, '_generate_next_value', value)
Ethan Furmana4b1bb42018-01-22 07:56:37 -0800325 elif key == '_ignore_':
326 if isinstance(value, str):
327 value = value.replace(',',' ').split()
328 else:
329 value = list(value)
330 self._ignore = value
331 already = set(value) & set(self._member_names)
332 if already:
Ethan Furman6d3dfee2020-12-08 12:26:56 -0800333 raise ValueError(
334 '_ignore_ cannot specify already set names: %r'
335 % (already, )
336 )
Ethan Furman101e0742013-09-15 12:34:36 -0700337 elif _is_dunder(key):
Ethan Furmane8e61272016-08-20 07:19:31 -0700338 if key == '__order__':
339 key = '_order_'
Ethan Furman101e0742013-09-15 12:34:36 -0700340 elif key in self._member_names:
341 # descriptor overwriting an enum?
Ethan Furmana6582872020-12-10 13:07:00 -0800342 raise TypeError('%r already defined as: %r' % (key, self[key]))
Ethan Furmana4b1bb42018-01-22 07:56:37 -0800343 elif key in self._ignore:
344 pass
Ethan Furman101e0742013-09-15 12:34:36 -0700345 elif not _is_descriptor(value):
346 if key in self:
347 # enum overwriting a descriptor?
Ethan Furmanee47e5c2016-08-31 00:12:15 -0700348 raise TypeError('%r already defined as: %r' % (key, self[key]))
Ethan Furmanc16595e2016-09-10 23:36:59 -0700349 if isinstance(value, auto):
Ethan Furman3515dcc2016-09-18 13:15:41 -0700350 if value.value == _auto_null:
Ethan Furman6d3dfee2020-12-08 12:26:56 -0800351 value.value = self._generate_next_value(
Ethan Furman7aaeb2a2021-01-25 14:26:19 -0800352 key, 1, len(self._member_names), self._last_values[:],
Ethan Furman6d3dfee2020-12-08 12:26:56 -0800353 )
Ethan Furmanfc23a942020-09-16 12:37:54 -0700354 self._auto_called = True
Ethan Furman3515dcc2016-09-18 13:15:41 -0700355 value = value.value
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700356 self._member_names.append(key)
Ethan Furmanc16595e2016-09-10 23:36:59 -0700357 self._last_values.append(value)
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700358 super().__setitem__(key, value)
359
Ethan Furmana6582872020-12-10 13:07:00 -0800360 def update(self, members, **more_members):
361 try:
362 for name in members.keys():
363 self[name] = members[name]
364 except AttributeError:
365 for name, value in members:
366 self[name] = value
367 for name, value in more_members.items():
368 self[name] = value
369
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700370
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700371class EnumMeta(type):
Ethan Furman6d3dfee2020-12-08 12:26:56 -0800372 """
373 Metaclass for Enum
374 """
Ethan Furman7aaeb2a2021-01-25 14:26:19 -0800375
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700376 @classmethod
Ethan Furman6ec0ade2020-12-24 10:05:02 -0800377 def __prepare__(metacls, cls, bases, **kwds):
Ethan Furman3064dbf2020-09-16 07:11:57 -0700378 # check that previous enum members do not exist
379 metacls._check_for_existing_members(cls, bases)
Ethan Furmanee47e5c2016-08-31 00:12:15 -0700380 # create the namespace dict
381 enum_dict = _EnumDict()
Ethan Furman7cf0aad2020-12-09 17:12:11 -0800382 enum_dict._cls_name = cls
Ethan Furmanee47e5c2016-08-31 00:12:15 -0700383 # inherit previous flags and _generate_next_value_ function
Ethan Furman3064dbf2020-09-16 07:11:57 -0700384 member_type, first_enum = metacls._get_mixins_(cls, bases)
Ethan Furmanee47e5c2016-08-31 00:12:15 -0700385 if first_enum is not None:
Ethan Furman6d3dfee2020-12-08 12:26:56 -0800386 enum_dict['_generate_next_value_'] = getattr(
387 first_enum, '_generate_next_value_', None,
388 )
Ethan Furmanee47e5c2016-08-31 00:12:15 -0700389 return enum_dict
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700390
Ethan Furman7aaeb2a2021-01-25 14:26:19 -0800391 def __new__(metacls, cls, bases, classdict, boundary=None, **kwds):
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700392 # an Enum class is final once enumeration items have been defined; it
393 # cannot be mixed with other types (int, float, etc.) if it has an
394 # inherited __new__ unless a new __new__ is defined (or the resulting
395 # class will fail).
Ethan Furmana4b1bb42018-01-22 07:56:37 -0800396 #
397 # remove any keys listed in _ignore_
398 classdict.setdefault('_ignore_', []).append('_ignore_')
399 ignore = classdict['_ignore_']
400 for key in ignore:
401 classdict.pop(key, None)
Ethan Furmanc314e602021-01-12 23:47:57 -0800402 #
403 # grab member names
404 member_names = classdict._member_names
405 #
406 # check for illegal enum names (any others?)
407 invalid_names = set(member_names) & {'mro', ''}
408 if invalid_names:
409 raise ValueError('Invalid enum member name: {0}'.format(
410 ','.join(invalid_names)))
411 #
412 # adjust the sunders
413 _order_ = classdict.pop('_order_', None)
414 # convert to normal dict
415 classdict = dict(classdict.items())
416 #
417 # data type of member and the controlling Enum class
Ethan Furman3064dbf2020-09-16 07:11:57 -0700418 member_type, first_enum = metacls._get_mixins_(cls, bases)
Ethan Furmanc2667362020-12-07 00:17:31 -0800419 __new__, save_new, use_args = metacls._find_new_(
420 classdict, member_type, first_enum,
421 )
Ethan Furmanc314e602021-01-12 23:47:57 -0800422 classdict['_new_member_'] = __new__
423 classdict['_use_args_'] = use_args
424 #
425 # convert future enum members into temporary _proto_members
Ethan Furman7aaeb2a2021-01-25 14:26:19 -0800426 # and record integer values in case this will be a Flag
427 flag_mask = 0
Ethan Furmanc314e602021-01-12 23:47:57 -0800428 for name in member_names:
Ethan Furman7aaeb2a2021-01-25 14:26:19 -0800429 value = classdict[name]
430 if isinstance(value, int):
431 flag_mask |= value
432 classdict[name] = _proto_member(value)
Ethan Furmanc314e602021-01-12 23:47:57 -0800433 #
Ethan Furman7aaeb2a2021-01-25 14:26:19 -0800434 # house-keeping structures
Ethan Furmanc314e602021-01-12 23:47:57 -0800435 classdict['_member_names_'] = []
436 classdict['_member_map_'] = {}
437 classdict['_value2member_map_'] = {}
438 classdict['_member_type_'] = member_type
439 #
Ethan Furman7aaeb2a2021-01-25 14:26:19 -0800440 # Flag structures (will be removed if final class is not a Flag
441 classdict['_boundary_'] = (
442 boundary
443 or getattr(first_enum, '_boundary_', None)
444 )
445 classdict['_flag_mask_'] = flag_mask
446 classdict['_all_bits_'] = 2 ** ((flag_mask).bit_length()) - 1
447 classdict['_inverted_'] = None
448 #
Ethan Furman2da95042014-03-03 12:42:52 -0800449 # If a custom type is mixed into the Enum, and it does not know how
450 # to pickle itself, pickle.dumps will succeed but pickle.loads will
451 # fail. Rather than have the error show up later and possibly far
452 # from the source, sabotage the pickle protocol for this class so
453 # that pickle.dumps also fails.
454 #
455 # However, if the new class implements its own __reduce_ex__, do not
456 # sabotage -- it's on them to make sure it works correctly. We use
457 # __reduce_ex__ instead of any of the others as it is preferred by
458 # pickle over __reduce__, and it handles all pickle protocols.
459 if '__reduce_ex__' not in classdict:
Ethan Furmandc870522014-02-18 12:37:12 -0800460 if member_type is not object:
461 methods = ('__getnewargs_ex__', '__getnewargs__',
462 '__reduce_ex__', '__reduce__')
Ethan Furman2da95042014-03-03 12:42:52 -0800463 if not any(m in member_type.__dict__ for m in methods):
Ethan Furmanc314e602021-01-12 23:47:57 -0800464 _make_class_unpicklable(classdict)
465 #
466 # create a default docstring if one has not been provided
467 if '__doc__' not in classdict:
468 classdict['__doc__'] = 'An enumeration.'
469 try:
470 exc = None
471 enum_class = super().__new__(metacls, cls, bases, classdict, **kwds)
472 except RuntimeError as e:
473 # any exceptions raised by member.__new__ will get converted to a
474 # RuntimeError, so get that original exception back and raise it instead
475 exc = e.__cause__ or e
476 if exc is not None:
477 raise exc
478 #
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700479 # double check that repr and friends are not the mixin's or various
480 # things break (such as pickle)
Ethan Furman22415ad2020-09-15 16:28:25 -0700481 # however, if the method is defined in the Enum itself, don't replace
482 # it
Ethan Furmandc870522014-02-18 12:37:12 -0800483 for name in ('__repr__', '__str__', '__format__', '__reduce_ex__'):
Ethan Furman22415ad2020-09-15 16:28:25 -0700484 if name in classdict:
485 continue
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700486 class_method = getattr(enum_class, name)
487 obj_method = getattr(member_type, name, None)
488 enum_method = getattr(first_enum, name, None)
489 if obj_method is not None and obj_method is class_method:
490 setattr(enum_class, name, enum_method)
Ethan Furmanc314e602021-01-12 23:47:57 -0800491 #
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700492 # replace any other __new__ with our own (as long as Enum is not None,
493 # anyway) -- again, this is to support pickle
494 if Enum is not None:
495 # if the user defined their own __new__, save it before it gets
496 # clobbered in case they subclass later
497 if save_new:
498 enum_class.__new_member__ = __new__
499 enum_class.__new__ = Enum.__new__
Ethan Furmanc314e602021-01-12 23:47:57 -0800500 #
Ethan Furmane8e61272016-08-20 07:19:31 -0700501 # py3 support for definition order (helps keep py2/py3 code in sync)
Ethan Furman7aaeb2a2021-01-25 14:26:19 -0800502 #
503 # _order_ checking is spread out into three/four steps
504 # - if enum_class is a Flag:
505 # - remove any non-single-bit flags from _order_
506 # - remove any aliases from _order_
507 # - check that _order_ and _member_names_ match
508 #
509 # step 1: ensure we have a list
Ethan Furmane8e61272016-08-20 07:19:31 -0700510 if _order_ is not None:
511 if isinstance(_order_, str):
512 _order_ = _order_.replace(',', ' ').split()
Ethan Furman7aaeb2a2021-01-25 14:26:19 -0800513 #
514 # remove Flag structures if final class is not a Flag
515 if (
516 Flag is None and cls != 'Flag'
517 or Flag is not None and not issubclass(enum_class, Flag)
518 ):
519 delattr(enum_class, '_boundary_')
520 delattr(enum_class, '_flag_mask_')
521 delattr(enum_class, '_all_bits_')
522 delattr(enum_class, '_inverted_')
523 elif Flag is not None and issubclass(enum_class, Flag):
524 # ensure _all_bits_ is correct and there are no missing flags
525 single_bit_total = 0
526 multi_bit_total = 0
527 for flag in enum_class._member_map_.values():
528 flag_value = flag._value_
529 if _is_single_bit(flag_value):
530 single_bit_total |= flag_value
531 else:
532 # multi-bit flags are considered aliases
533 multi_bit_total |= flag_value
534 if enum_class._boundary_ is not KEEP:
535 missed = list(_iter_bits_lsb(multi_bit_total & ~single_bit_total))
536 if missed:
537 raise TypeError(
538 'invalid Flag %r -- missing values: %s'
539 % (cls, ', '.join((str(i) for i in missed)))
540 )
541 enum_class._flag_mask_ = single_bit_total
542 #
543 # set correct __iter__
544 member_list = [m._value_ for m in enum_class]
545 if member_list != sorted(member_list):
546 enum_class._iter_member_ = enum_class._iter_member_by_def_
547 if _order_:
548 # _order_ step 2: remove any items from _order_ that are not single-bit
549 _order_ = [
550 o
551 for o in _order_
552 if o not in enum_class._member_map_ or _is_single_bit(enum_class[o]._value_)
553 ]
554 #
555 if _order_:
556 # _order_ step 3: remove aliases from _order_
557 _order_ = [
558 o
559 for o in _order_
560 if (
561 o not in enum_class._member_map_
562 or
563 (o in enum_class._member_map_ and o in enum_class._member_names_)
564 )]
565 # _order_ step 4: verify that _order_ and _member_names_ match
Ethan Furmane8e61272016-08-20 07:19:31 -0700566 if _order_ != enum_class._member_names_:
Ethan Furman7aaeb2a2021-01-25 14:26:19 -0800567 raise TypeError(
568 'member order does not match _order_:\n%r\n%r'
569 % (enum_class._member_names_, _order_)
570 )
Ethan Furmanc314e602021-01-12 23:47:57 -0800571 #
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700572 return enum_class
573
Ethan Furman5de67b12016-04-13 23:52:09 -0700574 def __bool__(self):
575 """
576 classes/types should always be True.
577 """
578 return True
579
Ethan Furman7aaeb2a2021-01-25 14:26:19 -0800580 def __call__(cls, value, names=None, *, module=None, qualname=None, type=None, start=1, boundary=None):
Ethan Furman6d3dfee2020-12-08 12:26:56 -0800581 """
582 Either returns an existing member, or creates a new enum class.
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700583
584 This method is used both when an enum class is given a value to match
585 to an enumeration member (i.e. Color(3)) and for the functional API
Ethan Furman23bb6f42016-11-21 09:22:05 -0800586 (i.e. Color = Enum('Color', names='RED GREEN BLUE')).
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700587
Ethan Furman2da95042014-03-03 12:42:52 -0800588 When used for the functional API:
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700589
Ethan Furman2da95042014-03-03 12:42:52 -0800590 `value` will be the name of the new class.
591
592 `names` should be either a string of white-space/comma delimited names
Ethan Furmand9925a12014-09-16 20:35:55 -0700593 (values will start at `start`), or an iterator/mapping of name, value pairs.
Ethan Furman2da95042014-03-03 12:42:52 -0800594
595 `module` should be set to the module this class is being created in;
596 if it is not set, an attempt to find that module will be made, but if
597 it fails the class will not be picklable.
598
599 `qualname` should be set to the actual location this class can be found
600 at in its module; by default it is set to the global scope. If this is
601 not correct, unpickling will fail in some circumstances.
602
603 `type`, if set, will be mixed in as the first base class.
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700604 """
605 if names is None: # simple value lookup
606 return cls.__new__(cls, value)
607 # otherwise, functional API: we're creating a new Enum type
Ethan Furman6d3dfee2020-12-08 12:26:56 -0800608 return cls._create_(
609 value,
610 names,
611 module=module,
612 qualname=qualname,
613 type=type,
614 start=start,
Ethan Furman7aaeb2a2021-01-25 14:26:19 -0800615 boundary=boundary,
Ethan Furman6d3dfee2020-12-08 12:26:56 -0800616 )
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700617
618 def __contains__(cls, member):
Rahul Jha94306522018-09-10 23:51:04 +0530619 if not isinstance(member, Enum):
620 raise TypeError(
621 "unsupported operand type(s) for 'in': '%s' and '%s'" % (
622 type(member).__qualname__, cls.__class__.__qualname__))
Ethan Furman0081f232014-09-16 17:31:23 -0700623 return isinstance(member, cls) and member._name_ in cls._member_map_
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700624
Ethan Furman64a99722013-09-22 16:18:19 -0700625 def __delattr__(cls, attr):
626 # nicer error message when someone tries to delete an attribute
627 # (see issue19025).
628 if attr in cls._member_map_:
Ethan Furman6d3dfee2020-12-08 12:26:56 -0800629 raise AttributeError("%s: cannot delete Enum member %r." % (cls.__name__, attr))
Ethan Furman64a99722013-09-22 16:18:19 -0700630 super().__delattr__(attr)
631
Ethan Furman388a3922013-08-12 06:51:41 -0700632 def __dir__(self):
Ethan Furman6d3dfee2020-12-08 12:26:56 -0800633 return (
634 ['__class__', '__doc__', '__members__', '__module__']
635 + self._member_names_
636 )
Ethan Furman388a3922013-08-12 06:51:41 -0700637
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700638 def __getattr__(cls, name):
Ethan Furman6d3dfee2020-12-08 12:26:56 -0800639 """
640 Return the enum member matching `name`
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700641
642 We use __getattr__ instead of descriptors or inserting into the enum
643 class' __dict__ in order to support `name` and `value` being both
644 properties for enum members (which live in the class' __dict__) and
645 enum members themselves.
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700646 """
647 if _is_dunder(name):
648 raise AttributeError(name)
649 try:
Ethan Furman520ad572013-07-19 19:47:21 -0700650 return cls._member_map_[name]
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700651 except KeyError:
652 raise AttributeError(name) from None
653
654 def __getitem__(cls, name):
Ethan Furman520ad572013-07-19 19:47:21 -0700655 return cls._member_map_[name]
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700656
657 def __iter__(cls):
Ethan Furman6d3dfee2020-12-08 12:26:56 -0800658 """
659 Returns members in definition order.
660 """
Ethan Furman520ad572013-07-19 19:47:21 -0700661 return (cls._member_map_[name] for name in cls._member_names_)
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700662
663 def __len__(cls):
Ethan Furman520ad572013-07-19 19:47:21 -0700664 return len(cls._member_names_)
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700665
Ethan Furmanc314e602021-01-12 23:47:57 -0800666 @_bltin_property
Ethan Furman2131a4a2013-09-14 18:11:24 -0700667 def __members__(cls):
Ethan Furman6d3dfee2020-12-08 12:26:56 -0800668 """
669 Returns a mapping of member name->value.
Ethan Furman2131a4a2013-09-14 18:11:24 -0700670
671 This mapping lists all enum members, including aliases. Note that this
672 is a read-only view of the internal mapping.
Ethan Furman2131a4a2013-09-14 18:11:24 -0700673 """
674 return MappingProxyType(cls._member_map_)
675
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700676 def __repr__(cls):
677 return "<enum %r>" % cls.__name__
678
Ethan Furman2131a4a2013-09-14 18:11:24 -0700679 def __reversed__(cls):
Ethan Furman6d3dfee2020-12-08 12:26:56 -0800680 """
681 Returns members in reverse definition order.
682 """
Ethan Furman2131a4a2013-09-14 18:11:24 -0700683 return (cls._member_map_[name] for name in reversed(cls._member_names_))
684
Ethan Furmanf203f2d2013-09-06 07:16:48 -0700685 def __setattr__(cls, name, value):
Ethan Furman6d3dfee2020-12-08 12:26:56 -0800686 """
687 Block attempts to reassign Enum members.
Ethan Furmanf203f2d2013-09-06 07:16:48 -0700688
689 A simple assignment to the class namespace only changes one of the
690 several possible ways to get an Enum member from the Enum class,
691 resulting in an inconsistent Enumeration.
Ethan Furmanf203f2d2013-09-06 07:16:48 -0700692 """
693 member_map = cls.__dict__.get('_member_map_', {})
694 if name in member_map:
695 raise AttributeError('Cannot reassign members.')
696 super().__setattr__(name, value)
697
Ethan Furman7aaeb2a2021-01-25 14:26:19 -0800698 def _create_(cls, class_name, names, *, module=None, qualname=None, type=None, start=1, boundary=None):
Ethan Furman6d3dfee2020-12-08 12:26:56 -0800699 """
700 Convenience method to create a new Enum class.
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700701
702 `names` can be:
703
704 * A string containing member names, separated either with spaces or
Ethan Furmand9925a12014-09-16 20:35:55 -0700705 commas. Values are incremented by 1 from `start`.
706 * An iterable of member names. Values are incremented by 1 from `start`.
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700707 * An iterable of (member name, value) pairs.
Ethan Furmand9925a12014-09-16 20:35:55 -0700708 * A mapping of member name -> value pairs.
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700709 """
710 metacls = cls.__class__
711 bases = (cls, ) if type is None else (type, cls)
Ethan Furman3064dbf2020-09-16 07:11:57 -0700712 _, first_enum = cls._get_mixins_(cls, bases)
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700713 classdict = metacls.__prepare__(class_name, bases)
714
715 # special processing needed for names?
716 if isinstance(names, str):
717 names = names.replace(',', ' ').split()
Dong-hee Nadcc8ce42017-06-22 01:52:32 +0900718 if isinstance(names, (tuple, list)) and names and isinstance(names[0], str):
Ethan Furmanee47e5c2016-08-31 00:12:15 -0700719 original_names, names = names, []
Ethan Furmanc16595e2016-09-10 23:36:59 -0700720 last_values = []
Ethan Furmanee47e5c2016-08-31 00:12:15 -0700721 for count, name in enumerate(original_names):
Ethan Furmanc16595e2016-09-10 23:36:59 -0700722 value = first_enum._generate_next_value_(name, start, count, last_values[:])
723 last_values.append(value)
724 names.append((name, value))
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700725
726 # Here, names is either an iterable of (name, value) or a mapping.
727 for item in names:
728 if isinstance(item, str):
729 member_name, member_value = item, names[item]
730 else:
731 member_name, member_value = item
732 classdict[member_name] = member_value
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700733
734 # TODO: replace the frame hack if a blessed way to know the calling
735 # module is ever developed
736 if module is None:
737 try:
738 module = sys._getframe(2).f_globals['__name__']
Pablo Galindo293dd232019-11-19 21:34:03 +0000739 except (AttributeError, ValueError, KeyError):
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700740 pass
741 if module is None:
Ethan Furmanc314e602021-01-12 23:47:57 -0800742 _make_class_unpicklable(classdict)
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700743 else:
Ethan Furmanc314e602021-01-12 23:47:57 -0800744 classdict['__module__'] = module
Ethan Furmanca1b7942014-02-08 11:36:27 -0800745 if qualname is not None:
Ethan Furmanc314e602021-01-12 23:47:57 -0800746 classdict['__qualname__'] = qualname
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700747
Ethan Furman7aaeb2a2021-01-25 14:26:19 -0800748 return metacls.__new__(metacls, class_name, bases, classdict, boundary=boundary)
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700749
Ethan Furman7aaeb2a2021-01-25 14:26:19 -0800750 def _convert_(cls, name, module, filter, source=None, boundary=None):
orlnub1230fb9fad2018-09-12 20:28:53 +0300751 """
752 Create a new Enum subclass that replaces a collection of global constants
753 """
754 # convert all constants from source (or module) that pass filter() to
755 # a new Enum called name, and export the enum and its members back to
756 # module;
757 # also, replace the __reduce_ex__ method so unpickling works in
758 # previous Python versions
759 module_globals = vars(sys.modules[module])
760 if source:
761 source = vars(source)
762 else:
763 source = module_globals
764 # _value2member_map_ is populated in the same order every time
765 # for a consistent reverse mapping of number to name when there
766 # are multiple names for the same number.
767 members = [
768 (name, value)
769 for name, value in source.items()
770 if filter(name)]
771 try:
772 # sort by value
773 members.sort(key=lambda t: (t[1], t[0]))
774 except TypeError:
775 # unless some values aren't comparable, in which case sort by name
776 members.sort(key=lambda t: t[0])
Ethan Furman7aaeb2a2021-01-25 14:26:19 -0800777 cls = cls(name, members, module=module, boundary=boundary or KEEP)
orlnub1230fb9fad2018-09-12 20:28:53 +0300778 cls.__reduce_ex__ = _reduce_ex_by_name
779 module_globals.update(cls.__members__)
780 module_globals[name] = cls
781 return cls
782
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700783 @staticmethod
Ethan Furman3064dbf2020-09-16 07:11:57 -0700784 def _check_for_existing_members(class_name, bases):
785 for chain in bases:
786 for base in chain.__mro__:
787 if issubclass(base, Enum) and base._member_names_:
Ethan Furman6d3dfee2020-12-08 12:26:56 -0800788 raise TypeError(
789 "%s: cannot extend enumeration %r"
790 % (class_name, base.__name__)
791 )
Ethan Furman3064dbf2020-09-16 07:11:57 -0700792
793 @staticmethod
794 def _get_mixins_(class_name, bases):
Ethan Furman6d3dfee2020-12-08 12:26:56 -0800795 """
796 Returns the type for creating enum members, and the first inherited
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700797 enum class.
798
799 bases: the tuple of bases that was given to __new__
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700800 """
801 if not bases:
802 return object, Enum
803
Ethan Furman5bdab642018-09-21 19:03:09 -0700804 def _find_data_type(bases):
Ethan Furmanbff01f32020-09-15 15:56:26 -0700805 data_types = []
Ethan Furman5bdab642018-09-21 19:03:09 -0700806 for chain in bases:
Ethan Furmanbff01f32020-09-15 15:56:26 -0700807 candidate = None
Ethan Furman5bdab642018-09-21 19:03:09 -0700808 for base in chain.__mro__:
809 if base is object:
810 continue
Ethan Furmanc2667362020-12-07 00:17:31 -0800811 elif issubclass(base, Enum):
812 if base._member_type_ is not object:
813 data_types.append(base._member_type_)
814 break
Ethan Furman5bdab642018-09-21 19:03:09 -0700815 elif '__new__' in base.__dict__:
Ethan Furmancd453852018-10-05 23:29:36 -0700816 if issubclass(base, Enum):
Ethan Furman5bdab642018-09-21 19:03:09 -0700817 continue
Ethan Furmanbff01f32020-09-15 15:56:26 -0700818 data_types.append(candidate or base)
819 break
Ethan Furmanc2667362020-12-07 00:17:31 -0800820 else:
Ethan Furmanbff01f32020-09-15 15:56:26 -0700821 candidate = base
822 if len(data_types) > 1:
Ethan Furman3064dbf2020-09-16 07:11:57 -0700823 raise TypeError('%r: too many data types: %r' % (class_name, data_types))
Ethan Furmanbff01f32020-09-15 15:56:26 -0700824 elif data_types:
825 return data_types[0]
826 else:
827 return None
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700828
Ethan Furman5bdab642018-09-21 19:03:09 -0700829 # ensure final parent class is an Enum derivative, find any concrete
830 # data type, and check that Enum has no members
831 first_enum = bases[-1]
832 if not issubclass(first_enum, Enum):
833 raise TypeError("new enumerations should be created as "
834 "`EnumName([mixin_type, ...] [data_type,] enum_type)`")
835 member_type = _find_data_type(bases) or object
836 if first_enum._member_names_:
837 raise TypeError("Cannot extend enumerations")
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700838 return member_type, first_enum
839
840 @staticmethod
841 def _find_new_(classdict, member_type, first_enum):
Ethan Furman6d3dfee2020-12-08 12:26:56 -0800842 """
843 Returns the __new__ to be used for creating the enum members.
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700844
845 classdict: the class dictionary given to __new__
846 member_type: the data type whose __new__ will be used by default
847 first_enum: enumeration to check for an overriding __new__
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700848 """
849 # now find the correct __new__, checking to see of one was defined
850 # by the user; also check earlier enum classes in case a __new__ was
851 # saved as __new_member__
852 __new__ = classdict.get('__new__', None)
853
854 # should __new__ be saved as __new_member__ later?
855 save_new = __new__ is not None
856
857 if __new__ is None:
858 # check all possibles for __new_member__ before falling back to
859 # __new__
860 for method in ('__new_member__', '__new__'):
861 for possible in (member_type, first_enum):
862 target = getattr(possible, method, None)
863 if target not in {
864 None,
865 None.__new__,
866 object.__new__,
867 Enum.__new__,
868 }:
869 __new__ = target
870 break
871 if __new__ is not None:
872 break
873 else:
874 __new__ = object.__new__
875
876 # if a non-object.__new__ is used then whatever value/tuple was
877 # assigned to the enum member name will be passed to __new__ and to the
878 # new enum member's __init__
879 if __new__ is object.__new__:
880 use_args = False
881 else:
882 use_args = True
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700883 return __new__, save_new, use_args
884
885
886class Enum(metaclass=EnumMeta):
Ethan Furman6d3dfee2020-12-08 12:26:56 -0800887 """
888 Generic enumeration.
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700889
890 Derive from this class to define new enumerations.
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700891 """
Ethan Furman7aaeb2a2021-01-25 14:26:19 -0800892
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700893 def __new__(cls, value):
894 # all enum instances are actually created during class construction
895 # without calling this method; this method is called by the metaclass'
896 # __call__ (i.e. Color(3) ), and by pickle
897 if type(value) is cls:
Ethan Furman23bb6f42016-11-21 09:22:05 -0800898 # For lookups like Color(Color.RED)
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700899 return value
900 # by-value search for a matching enum member
901 # see if it's in the reverse mapping (for hashable values)
Ethan Furman2aa27322013-07-19 19:35:56 -0700902 try:
Andrew Svetlov34ae04f2018-12-26 20:45:33 +0200903 return cls._value2member_map_[value]
904 except KeyError:
905 # Not found, no need to do long O(n) search
906 pass
Ethan Furman2aa27322013-07-19 19:35:56 -0700907 except TypeError:
908 # not there, now do long search -- O(n) behavior
Ethan Furman520ad572013-07-19 19:47:21 -0700909 for member in cls._member_map_.values():
Ethan Furman0081f232014-09-16 17:31:23 -0700910 if member._value_ == value:
Ethan Furman2aa27322013-07-19 19:35:56 -0700911 return member
Ethan Furmanee47e5c2016-08-31 00:12:15 -0700912 # still not found -- try _missing_ hook
Ethan Furman019f0a02018-09-12 11:43:34 -0700913 try:
914 exc = None
915 result = cls._missing_(value)
916 except Exception as e:
917 exc = e
918 result = None
919 if isinstance(result, cls):
920 return result
Ethan Furman7aaeb2a2021-01-25 14:26:19 -0800921 elif (
922 Flag is not None and issubclass(cls, Flag)
923 and cls._boundary_ is EJECT and isinstance(result, int)
924 ):
925 return result
Ethan Furman019f0a02018-09-12 11:43:34 -0700926 else:
Walter Dörwald323842c2019-07-18 20:37:13 +0200927 ve_exc = ValueError("%r is not a valid %s" % (value, cls.__qualname__))
Ethan Furman019f0a02018-09-12 11:43:34 -0700928 if result is None and exc is None:
929 raise ve_exc
930 elif exc is None:
931 exc = TypeError(
932 'error in %s._missing_: returned %r instead of None or a valid member'
933 % (cls.__name__, result)
934 )
Ethan Furman7aaeb2a2021-01-25 14:26:19 -0800935 if not isinstance(exc, ValueError):
936 exc.__context__ = ve_exc
Ethan Furman019f0a02018-09-12 11:43:34 -0700937 raise exc
Ethan Furmanee47e5c2016-08-31 00:12:15 -0700938
Ethan Furmanc16595e2016-09-10 23:36:59 -0700939 def _generate_next_value_(name, start, count, last_values):
Ethan Furman6d3dfee2020-12-08 12:26:56 -0800940 """
941 Generate the next value when not given.
942
943 name: the name of the member
944 start: the initial start value or None
945 count: the number of existing members
946 last_value: the last value assigned or None
947 """
Ethan Furmanc16595e2016-09-10 23:36:59 -0700948 for last_value in reversed(last_values):
949 try:
950 return last_value + 1
951 except TypeError:
952 pass
953 else:
Ethan Furmanee47e5c2016-08-31 00:12:15 -0700954 return start
Ethan Furmanc16595e2016-09-10 23:36:59 -0700955
Ethan Furmanee47e5c2016-08-31 00:12:15 -0700956 @classmethod
957 def _missing_(cls, value):
Ethan Furmanc95ad7a2020-09-16 10:26:50 -0700958 return None
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700959
960 def __repr__(self):
961 return "<%s.%s: %r>" % (
Ethan Furman520ad572013-07-19 19:47:21 -0700962 self.__class__.__name__, self._name_, self._value_)
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700963
964 def __str__(self):
Ethan Furman520ad572013-07-19 19:47:21 -0700965 return "%s.%s" % (self.__class__.__name__, self._name_)
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700966
Ethan Furman388a3922013-08-12 06:51:41 -0700967 def __dir__(self):
Ethan Furman6d3dfee2020-12-08 12:26:56 -0800968 """
969 Returns all members and all public methods
970 """
Ethan Furman0ae550b2014-10-14 08:58:32 -0700971 added_behavior = [
972 m
973 for cls in self.__class__.mro()
974 for m in cls.__dict__
Ethan Furman354ecf12015-03-11 08:43:12 -0700975 if m[0] != '_' and m not in self._member_map_
Angelin BOOZ68526fe2020-09-21 15:11:06 +0200976 ] + [m for m in self.__dict__ if m[0] != '_']
Ethan Furmanec5f8eb2014-10-21 13:40:35 -0700977 return (['__class__', '__doc__', '__module__'] + added_behavior)
Ethan Furman388a3922013-08-12 06:51:41 -0700978
Ethan Furmanec15a822013-08-31 19:17:41 -0700979 def __format__(self, format_spec):
Ethan Furman6d3dfee2020-12-08 12:26:56 -0800980 """
981 Returns format using actual value type unless __str__ has been overridden.
982 """
Ethan Furmanec15a822013-08-31 19:17:41 -0700983 # mixed-in Enums should use the mixed-in type's __format__, otherwise
984 # we can get strange results with the Enum name showing up instead of
985 # the value
986
thatneat2f19e822019-07-04 11:28:37 -0700987 # pure Enum branch, or branch with __str__ explicitly overridden
Ethan Furman37440ee2020-12-08 11:14:10 -0800988 str_overridden = type(self).__str__ not in (Enum.__str__, Flag.__str__)
thatneat2f19e822019-07-04 11:28:37 -0700989 if self._member_type_ is object or str_overridden:
Ethan Furmanec15a822013-08-31 19:17:41 -0700990 cls = str
991 val = str(self)
992 # mix-in branch
993 else:
994 cls = self._member_type_
Ethan Furman0081f232014-09-16 17:31:23 -0700995 val = self._value_
Ethan Furmanec15a822013-08-31 19:17:41 -0700996 return cls.__format__(val, format_spec)
997
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700998 def __hash__(self):
Ethan Furman520ad572013-07-19 19:47:21 -0700999 return hash(self._name_)
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001000
Ethan Furmanca1b7942014-02-08 11:36:27 -08001001 def __reduce_ex__(self, proto):
Ethan Furmandc870522014-02-18 12:37:12 -08001002 return self.__class__, (self._value_, )
Ethan Furmanca1b7942014-02-08 11:36:27 -08001003
Ethan Furmanc314e602021-01-12 23:47:57 -08001004 # enum.property is used to provide access to the `name` and
1005 # `value` attributes of enum members while keeping some measure of
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001006 # protection from modification, while still allowing for an enumeration
1007 # to have members named `name` and `value`. This works because enumeration
Ethan Furmanc314e602021-01-12 23:47:57 -08001008 # members are not set directly on the enum class; they are kept in a
1009 # separate structure, _member_map_, which is where enum.property looks for
1010 # them
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001011
Ethan Furmanc314e602021-01-12 23:47:57 -08001012 @property
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001013 def name(self):
Ethan Furmanc850f342013-09-15 16:59:35 -07001014 """The name of the Enum member."""
Ethan Furman520ad572013-07-19 19:47:21 -07001015 return self._name_
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001016
Ethan Furmanc314e602021-01-12 23:47:57 -08001017 @property
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001018 def value(self):
Ethan Furmanc850f342013-09-15 16:59:35 -07001019 """The value of the Enum member."""
Ethan Furman520ad572013-07-19 19:47:21 -07001020 return self._value_
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001021
1022
1023class IntEnum(int, Enum):
Ethan Furman0063ff42020-09-21 17:23:13 -07001024 """
1025 Enum where members are also (and must be) ints
1026 """
1027
1028
1029class StrEnum(str, Enum):
1030 """
1031 Enum where members are also (and must be) strings
1032 """
1033
1034 def __new__(cls, *values):
1035 if len(values) > 3:
1036 raise TypeError('too many arguments for str(): %r' % (values, ))
1037 if len(values) == 1:
1038 # it must be a string
1039 if not isinstance(values[0], str):
1040 raise TypeError('%r is not a string' % (values[0], ))
Ethan Furman7aaeb2a2021-01-25 14:26:19 -08001041 if len(values) >= 2:
Ethan Furman0063ff42020-09-21 17:23:13 -07001042 # check that encoding argument is a string
1043 if not isinstance(values[1], str):
1044 raise TypeError('encoding must be a string, not %r' % (values[1], ))
Ethan Furman7aaeb2a2021-01-25 14:26:19 -08001045 if len(values) == 3:
1046 # check that errors argument is a string
1047 if not isinstance(values[2], str):
1048 raise TypeError('errors must be a string, not %r' % (values[2]))
Ethan Furman0063ff42020-09-21 17:23:13 -07001049 value = str(*values)
1050 member = str.__new__(cls, value)
1051 member._value_ = value
1052 return member
Ethan Furmanf24bb352013-07-18 17:05:39 -07001053
Ethan Furmand986d162020-09-22 13:00:07 -07001054 __str__ = str.__str__
1055
Ethan Furmanefb13be2020-12-10 12:20:06 -08001056 def _generate_next_value_(name, start, count, last_values):
1057 """
1058 Return the lower-cased version of the member name.
1059 """
1060 return name.lower()
1061
Ethan Furmanf24bb352013-07-18 17:05:39 -07001062
Ethan Furman24e837f2015-03-18 17:27:57 -07001063def _reduce_ex_by_name(self, proto):
1064 return self.name
1065
Ethan Furman7aaeb2a2021-01-25 14:26:19 -08001066class FlagBoundary(StrEnum):
1067 """
1068 control how out of range values are handled
1069 "strict" -> error is raised [default for Flag]
1070 "conform" -> extra bits are discarded
1071 "eject" -> lose flag status [default for IntFlag]
1072 "keep" -> keep flag status and all bits
1073 """
1074 STRICT = auto()
1075 CONFORM = auto()
1076 EJECT = auto()
1077 KEEP = auto()
1078STRICT, CONFORM, EJECT, KEEP = FlagBoundary
1079
1080
1081class Flag(Enum, boundary=STRICT):
Ethan Furman6d3dfee2020-12-08 12:26:56 -08001082 """
1083 Support for flags
1084 """
Ethan Furmanc16595e2016-09-10 23:36:59 -07001085
1086 def _generate_next_value_(name, start, count, last_values):
Ethan Furmanee47e5c2016-08-31 00:12:15 -07001087 """
1088 Generate the next value when not given.
1089
1090 name: the name of the member
HongWeipengbb16fb22019-09-21 13:22:54 +08001091 start: the initial start value or None
Ethan Furmanee47e5c2016-08-31 00:12:15 -07001092 count: the number of existing members
1093 last_value: the last value assigned or None
1094 """
1095 if not count:
1096 return start if start is not None else 1
Ethan Furman7aaeb2a2021-01-25 14:26:19 -08001097 last_value = max(last_values)
1098 try:
1099 high_bit = _high_bit(last_value)
1100 except Exception:
1101 raise TypeError('Invalid Flag value: %r' % last_value) from None
Ethan Furmanee47e5c2016-08-31 00:12:15 -07001102 return 2 ** (high_bit+1)
1103
1104 @classmethod
Ethan Furman7aaeb2a2021-01-25 14:26:19 -08001105 def _iter_member_by_value_(cls, value):
1106 """
1107 Extract all members from the value in definition (i.e. increasing value) order.
1108 """
1109 for val in _iter_bits_lsb(value & cls._flag_mask_):
1110 yield cls._value2member_map_.get(val)
1111
1112 _iter_member_ = _iter_member_by_value_
1113
1114 @classmethod
1115 def _iter_member_by_def_(cls, value):
1116 """
1117 Extract all members from the value in definition order.
1118 """
1119 yield from sorted(
1120 cls._iter_member_by_value_(value),
1121 key=lambda m: m._sort_order_,
1122 )
1123
1124 @classmethod
Ethan Furmanee47e5c2016-08-31 00:12:15 -07001125 def _missing_(cls, value):
Ethan Furman6d3dfee2020-12-08 12:26:56 -08001126 """
Ethan Furman3515dcc2016-09-18 13:15:41 -07001127 Create a composite member iff value contains only members.
1128 """
Ethan Furman7aaeb2a2021-01-25 14:26:19 -08001129 if not isinstance(value, int):
1130 raise ValueError(
1131 "%r is not a valid %s" % (value, cls.__qualname__)
1132 )
1133 # check boundaries
1134 # - value must be in range (e.g. -16 <-> +15, i.e. ~15 <-> 15)
1135 # - value must not include any skipped flags (e.g. if bit 2 is not
1136 # defined, then 0d10 is invalid)
1137 flag_mask = cls._flag_mask_
1138 all_bits = cls._all_bits_
1139 neg_value = None
1140 if (
1141 not ~all_bits <= value <= all_bits
1142 or value & (all_bits ^ flag_mask)
1143 ):
1144 if cls._boundary_ is STRICT:
1145 max_bits = max(value.bit_length(), flag_mask.bit_length())
1146 raise ValueError(
1147 "%s: invalid value: %r\n given %s\n allowed %s" % (
1148 cls.__name__, value, bin(value, max_bits), bin(flag_mask, max_bits),
1149 ))
1150 elif cls._boundary_ is CONFORM:
1151 value = value & flag_mask
1152 elif cls._boundary_ is EJECT:
1153 return value
1154 elif cls._boundary_ is KEEP:
1155 if value < 0:
1156 value = (
1157 max(all_bits+1, 2**(value.bit_length()))
1158 + value
1159 )
1160 else:
1161 raise ValueError(
1162 'unknown flag boundary: %r' % (cls._boundary_, )
1163 )
1164 if value < 0:
1165 neg_value = value
1166 value = all_bits + 1 + value
1167 # get members and unknown
1168 unknown = value & ~flag_mask
1169 member_value = value & flag_mask
1170 if unknown and cls._boundary_ is not KEEP:
1171 raise ValueError(
1172 '%s(%r) --> unknown values %r [%s]'
1173 % (cls.__name__, value, unknown, bin(unknown))
1174 )
1175 # normal Flag?
1176 __new__ = getattr(cls, '__new_member__', None)
1177 if cls._member_type_ is object and not __new__:
Ethan Furman3515dcc2016-09-18 13:15:41 -07001178 # construct a singleton enum pseudo-member
Ethan Furmanee47e5c2016-08-31 00:12:15 -07001179 pseudo_member = object.__new__(cls)
Ethan Furman7aaeb2a2021-01-25 14:26:19 -08001180 else:
1181 pseudo_member = (__new__ or cls._member_type_.__new__)(cls, value)
1182 if not hasattr(pseudo_member, 'value'):
Ethan Furmanee47e5c2016-08-31 00:12:15 -07001183 pseudo_member._value_ = value
Ethan Furman7aaeb2a2021-01-25 14:26:19 -08001184 if member_value:
1185 pseudo_member._name_ = '|'.join([
1186 m._name_ for m in cls._iter_member_(member_value)
1187 ])
1188 if unknown:
1189 pseudo_member._name_ += '|0x%x' % unknown
1190 else:
1191 pseudo_member._name_ = None
1192 # use setdefault in case another thread already created a composite
1193 # with this value, but only if all members are known
1194 # note: zero is a special case -- add it
1195 if not unknown:
Ethan Furman28cf6632017-01-24 12:12:06 -08001196 pseudo_member = cls._value2member_map_.setdefault(value, pseudo_member)
Ethan Furman7aaeb2a2021-01-25 14:26:19 -08001197 if neg_value is not None:
1198 cls._value2member_map_[neg_value] = pseudo_member
Ethan Furmanee47e5c2016-08-31 00:12:15 -07001199 return pseudo_member
1200
Ethan Furmanee47e5c2016-08-31 00:12:15 -07001201 def __contains__(self, other):
Ethan Furman6d3dfee2020-12-08 12:26:56 -08001202 """
1203 Returns True if self has at least the same flags set as other.
1204 """
Ethan Furmanee47e5c2016-08-31 00:12:15 -07001205 if not isinstance(other, self.__class__):
Rahul Jha94306522018-09-10 23:51:04 +05301206 raise TypeError(
1207 "unsupported operand type(s) for 'in': '%s' and '%s'" % (
1208 type(other).__qualname__, self.__class__.__qualname__))
Ethan Furman7aaeb2a2021-01-25 14:26:19 -08001209 if other._value_ == 0 or self._value_ == 0:
1210 return False
Ethan Furmanee47e5c2016-08-31 00:12:15 -07001211 return other._value_ & self._value_ == other._value_
1212
Ethan Furman7219e272020-09-16 13:01:00 -07001213 def __iter__(self):
Ethan Furman6d3dfee2020-12-08 12:26:56 -08001214 """
Ethan Furman7aaeb2a2021-01-25 14:26:19 -08001215 Returns flags in definition order.
Ethan Furman6d3dfee2020-12-08 12:26:56 -08001216 """
Ethan Furman7aaeb2a2021-01-25 14:26:19 -08001217 yield from self._iter_member_(self._value_)
1218
1219 def __len__(self):
1220 return self._value_.bit_count()
Ethan Furman7219e272020-09-16 13:01:00 -07001221
Ethan Furmanee47e5c2016-08-31 00:12:15 -07001222 def __repr__(self):
1223 cls = self.__class__
1224 if self._name_ is not None:
1225 return '<%s.%s: %r>' % (cls.__name__, self._name_, self._value_)
Ethan Furman7aaeb2a2021-01-25 14:26:19 -08001226 else:
1227 # only zero is unnamed by default
1228 return '<%s: %r>' % (cls.__name__, self._value_)
Ethan Furmanee47e5c2016-08-31 00:12:15 -07001229
1230 def __str__(self):
1231 cls = self.__class__
1232 if self._name_ is not None:
1233 return '%s.%s' % (cls.__name__, self._name_)
Ethan Furmanee47e5c2016-08-31 00:12:15 -07001234 else:
Ethan Furman7aaeb2a2021-01-25 14:26:19 -08001235 return '%s(%s)' % (cls.__name__, self._value_)
Ethan Furmanee47e5c2016-08-31 00:12:15 -07001236
Ethan Furman25d94bb2016-09-02 16:32:32 -07001237 def __bool__(self):
1238 return bool(self._value_)
1239
Ethan Furmanee47e5c2016-08-31 00:12:15 -07001240 def __or__(self, other):
1241 if not isinstance(other, self.__class__):
1242 return NotImplemented
1243 return self.__class__(self._value_ | other._value_)
1244
1245 def __and__(self, other):
1246 if not isinstance(other, self.__class__):
1247 return NotImplemented
1248 return self.__class__(self._value_ & other._value_)
1249
1250 def __xor__(self, other):
1251 if not isinstance(other, self.__class__):
1252 return NotImplemented
1253 return self.__class__(self._value_ ^ other._value_)
1254
1255 def __invert__(self):
Ethan Furman7aaeb2a2021-01-25 14:26:19 -08001256 if self._inverted_ is None:
1257 if self._boundary_ is KEEP:
1258 # use all bits
1259 self._inverted_ = self.__class__(~self._value_)
1260 else:
1261 # calculate flags not in this member
1262 self._inverted_ = self.__class__(self._flag_mask_ ^ self._value_)
1263 self._inverted_._inverted_ = self
1264 return self._inverted_
Ethan Furmanee47e5c2016-08-31 00:12:15 -07001265
1266
Ethan Furman7aaeb2a2021-01-25 14:26:19 -08001267class IntFlag(int, Flag, boundary=EJECT):
Ethan Furman6d3dfee2020-12-08 12:26:56 -08001268 """
1269 Support for integer-based Flags
1270 """
Ethan Furmanee47e5c2016-08-31 00:12:15 -07001271
Ethan Furmanee47e5c2016-08-31 00:12:15 -07001272 def __or__(self, other):
Ethan Furman7aaeb2a2021-01-25 14:26:19 -08001273 if isinstance(other, self.__class__):
1274 other = other._value_
1275 elif isinstance(other, int):
1276 other = other
1277 else:
Ethan Furmanee47e5c2016-08-31 00:12:15 -07001278 return NotImplemented
Ethan Furman7aaeb2a2021-01-25 14:26:19 -08001279 value = self._value_
1280 return self.__class__(value | other)
Ethan Furmanee47e5c2016-08-31 00:12:15 -07001281
1282 def __and__(self, other):
Ethan Furman7aaeb2a2021-01-25 14:26:19 -08001283 if isinstance(other, self.__class__):
1284 other = other._value_
1285 elif isinstance(other, int):
1286 other = other
1287 else:
Ethan Furmanee47e5c2016-08-31 00:12:15 -07001288 return NotImplemented
Ethan Furman7aaeb2a2021-01-25 14:26:19 -08001289 value = self._value_
1290 return self.__class__(value & other)
Ethan Furmanee47e5c2016-08-31 00:12:15 -07001291
1292 def __xor__(self, other):
Ethan Furman7aaeb2a2021-01-25 14:26:19 -08001293 if isinstance(other, self.__class__):
1294 other = other._value_
1295 elif isinstance(other, int):
1296 other = other
1297 else:
Ethan Furmanee47e5c2016-08-31 00:12:15 -07001298 return NotImplemented
Ethan Furman7aaeb2a2021-01-25 14:26:19 -08001299 value = self._value_
1300 return self.__class__(value ^ other)
Ethan Furmanee47e5c2016-08-31 00:12:15 -07001301
1302 __ror__ = __or__
1303 __rand__ = __and__
1304 __rxor__ = __xor__
Ethan Furman7aaeb2a2021-01-25 14:26:19 -08001305 __invert__ = Flag.__invert__
Ethan Furmanee47e5c2016-08-31 00:12:15 -07001306
1307def _high_bit(value):
Ethan Furman6d3dfee2020-12-08 12:26:56 -08001308 """
1309 returns index of highest bit, or -1 if value is zero or negative
1310 """
Ethan Furman3515dcc2016-09-18 13:15:41 -07001311 return value.bit_length() - 1
Ethan Furmanee47e5c2016-08-31 00:12:15 -07001312
Ethan Furmanf24bb352013-07-18 17:05:39 -07001313def unique(enumeration):
Ethan Furman6d3dfee2020-12-08 12:26:56 -08001314 """
1315 Class decorator for enumerations ensuring unique member values.
1316 """
Ethan Furmanf24bb352013-07-18 17:05:39 -07001317 duplicates = []
1318 for name, member in enumeration.__members__.items():
1319 if name != member.name:
1320 duplicates.append((name, member.name))
1321 if duplicates:
1322 alias_details = ', '.join(
1323 ["%s -> %s" % (alias, name) for (alias, name) in duplicates])
1324 raise ValueError('duplicate values found in %r: %s' %
1325 (enumeration, alias_details))
1326 return enumeration
Ethan Furman3515dcc2016-09-18 13:15:41 -07001327
Ethan Furman7aaeb2a2021-01-25 14:26:19 -08001328def _power_of_two(value):
1329 if value < 1:
1330 return False
1331 return value == 2 ** _high_bit(value)