1 module(enum
) ## needed in guile atm
4 from types
import MappingProxyType
, DynamicClassAttribute
5 from functools
import reduce
6 from operator
import or_
as _or_
8 # try _collections first to reduce startup cost
10 from _collections
import OrderedDict
12 from collections
import OrderedDict
16 'Enum', 'IntEnum', 'Flag', 'IntFlag',
21 def _is_descriptor(obj
):
22 """Returns True if obj is a descriptor, False otherwise."""
24 hasattr(obj
, '__get__') or
25 hasattr(obj
, '__set__') or
26 hasattr(obj
, '__delete__'))
30 """Returns True if a __dunder__ name, False otherwise."""
31 return (name
[:2] == name
[-2:] == '__' and
33 name
[-3:-2] != '_' and
38 """Returns True if a _sunder_ name, False otherwise."""
39 return (name
[0] == name
[-1] == '_' and
41 name
[-2:-1] != '_' and
44 def _make_class_unpicklable(cls
):
45 """Make the given class un-picklable."""
46 def _break_on_call_reduce(self
, proto
):
47 raise TypeError('%r cannot be pickled' % self
)
48 cls
.__reduce
_ex
__ = _break_on_call_reduce
49 cls
.__module
__ = '<unknown>'
56 Instances are replaced with an appropriate value in Enum class suites.
61 class _EnumDict(dict):
62 """Track enum member order and ensure member names are not reused.
64 EnumMeta will use the names found in self._member_names as the
65 enumeration member names.
70 self
._member
_names
= []
71 self
._last
_values
= []
73 def __setitem__(self
, key
, value
):
74 """Changes anything not dundered or not a descriptor.
76 If an enum member name is used twice, an error is raised; duplicate
77 values are not checked for.
79 Single underscore (sunder) names are reserved.
84 '_order_', '_create_pseudo_member_',
85 '_generate_next_value_', '_missing_',
87 raise ValueError('_names_ are reserved for future Enum use')
88 if key
== '_generate_next_value_':
89 setattr(self
, '_generate_next_value', value
)
91 if key
== '__order__':
93 elif key
in self
._member
_names
:
94 # descriptor overwriting an enum?
95 raise TypeError('Attempted to reuse key: %r' % key
)
96 elif not _is_descriptor(value
):
98 # enum overwriting a descriptor?
99 raise TypeError('%r already defined as: %r' % (key
, self
[key
]))
100 if isinstance(value
, auto
):
101 if value
.value
== _auto_null
:
102 value
.value
= self
._generate
_next
_value
(key
, 1, len(self
._member
_names
), self
._last
_values
[:])
104 self
._member
_names
.append(key
)
105 self
._last
_values
.append(value
)
106 super().__setitem
__(key
, value
)
109 # Dummy value for Enum as EnumMeta explicitly checks for it, but of course
110 # until EnumMeta finishes running the first time the Enum class doesn't exist.
111 # This is also why there are checks in EnumMeta like `if Enum is not None`
115 class EnumMeta(type):
116 """Metaclass for Enum"""
118 def __prepare__(metacls
, cls
, bases
):
119 # create the namespace dict
120 enum_dict
= _EnumDict()
123 # inherit previous flags and _generate_next_value_ function
124 member_type
, first_enum
= metacls
._get
_mixins
_(bases
)
126 if first_enum
is not None:
127 enum_dict
['_generate_next_value_'] = getattr(first_enum
, '_generate_next_value_', None)
131 def __new__(metacls
, cls
, bases
, classdict
):
132 # an Enum class is final once enumeration items have been defined; it
133 # cannot be mixed with other types (int, float, etc.) if it has an
134 # inherited __new__ unless a new __new__ is defined (or the resulting
137 member_type
, first_enum
= metacls
._get
_mixins
_(bases
)
138 __new__
, save_new
, use_args
= metacls
._find
_new
_(classdict
, member_type
,
141 # save enum items into separate mapping so they don't get baked into
143 enum_members
= {k
: classdict
[k
] for k
in classdict
._member
_names
}
144 for name
in classdict
._member
_names
:
148 _order_
= classdict
.pop('_order_', None)
150 # check for illegal enum names (any others?)
151 invalid_names
= set(enum_members
) & {'mro', }
153 raise ValueError('Invalid enum member name: {0}'.format(
154 ','.join(invalid_names
)))
156 # create a default docstring if one has not been provided
157 if '__doc__' not in classdict
:
158 classdict
['__doc__'] = 'An enumeration.'
160 # create our new Enum type
161 enum_class
= super().__new
__(metacls
, cls
, bases
, classdict
)
163 enum_class
._member
_names
_ = [] # names in definition order
164 enum_class
._member
_map
_ = OrderedDict() # name->value map
165 enum_class
._member
_type
_ = member_type
167 # save attributes from super classes so we know if we can take
168 # the shortcut of storing members in the class dict
170 base_attributes
= {a
for b
in enum_class
.mro() for a
in b
.__dict
__}
172 # Reverse value->name map for hashable values.
173 enum_class
._value
2member
_map
_ = {}
175 # If a custom type is mixed into the Enum, and it does not know how
176 # to pickle itself, pickle.dumps will succeed but pickle.loads will
177 # fail. Rather than have the error show up later and possibly far
178 # from the source, sabotage the pickle protocol for this class so
179 # that pickle.dumps also fails.
181 # However, if the new class implements its own __reduce_ex__, do not
182 # sabotage -- it's on them to make sure it works correctly. We use
183 # __reduce_ex__ instead of any of the others as it is preferred by
184 # pickle over __reduce__, and it handles all pickle protocols.
185 if '__reduce_ex__' not in classdict
:
186 if member_type
is not object:
187 methods
= ('__getnewargs_ex__', '__getnewargs__',
188 '__reduce_ex__', '__reduce__')
189 if not any(m
in member_type
.__dict
__ for m
in methods
):
190 _make_class_unpicklable(enum_class
)
192 # instantiate them, checking for duplicates as we go
193 # we instantiate first instead of checking for duplicates first in case
194 # a custom __new__ is doing something funky with the values -- such as
196 for member_name
in classdict
._member
_names
:
197 value
= enum_members
[member_name
]
198 if not isinstance(value
, tuple):
202 if member_type
is tuple: # special case for tuple enums
203 args
= (args
, ) # wrap it one more time
205 enum_member
= __new__(enum_class
)
206 if not hasattr(enum_member
, '_value_'):
207 enum_member
._value
_ = value
209 enum_member
= __new__(enum_class
, *args
)
210 if not hasattr(enum_member
, '_value_'):
211 if member_type
is object:
212 enum_member
._value
_ = value
214 enum_member
._value
_ = member_type(*args
)
215 value
= enum_member
._value
_
216 enum_member
._name
_ = member_name
217 enum_member
.__objclass
__ = enum_class
218 enum_member
.__init
__(*args
)
219 # If another member with the same value was already defined, the
220 # new member becomes an alias to the existing one.
221 for name
, canonical_member
in enum_class
._member
_map
_.items():
222 if canonical_member
._value
_ == enum_member
._value
_:
223 enum_member
= canonical_member
226 # Aliases don't appear in member names (only in __members__).
227 enum_class
._member
_names
_.append(member_name
)
228 # performance boost for any member that would not shadow
229 # a DynamicClassAttribute
230 if member_name
not in base_attributes
:
231 setattr(enum_class
, member_name
, enum_member
)
232 # now add to _member_map_
233 enum_class
._member
_map
_[member_name
] = enum_member
235 # This may fail if value is not hashable. We can't add the value
236 # to the map, and by-value lookups for this value will be
238 enum_class
._value
2member
_map
_[value
] = enum_member
242 # double check that repr and friends are not the mixin's or various
243 # things break (such as pickle)
244 for name
in ('__repr__', '__str__', '__format__', '__reduce_ex__'):
245 class_method
= getattr(enum_class
, name
)
246 obj_method
= getattr(member_type
, name
, None)
247 enum_method
= getattr(first_enum
, name
, None)
248 if obj_method
is not None and obj_method
is class_method
:
249 setattr(enum_class
, name
, enum_method
)
251 # replace any other __new__ with our own (as long as Enum is not None,
252 # anyway) -- again, this is to support pickle
254 # if the user defined their own __new__, save it before it gets
255 # clobbered in case they subclass later
257 enum_class
.__new
_member
__ = __new__
258 enum_class
.__new
__ = Enum
.__new
__
260 # py3 support for definition order (helps keep py2/py3 code in sync)
261 if _order_
is not None:
262 if isinstance(_order_
, str):
263 _order_
= _order_
.replace(',', ' ').split()
264 if _order_
!= enum_class
._member
_names
_:
265 raise TypeError('member order does not match _order_')
271 classes/types should always be True.
275 def __call__(cls
, value
, names
=None, *, module
=None, qualname
=None, type=None, start
=1):
276 """Either returns an existing member, or creates a new enum class.
278 This method is used both when an enum class is given a value to match
279 to an enumeration member (i.e. Color(3)) and for the functional API
280 (i.e. Color = Enum('Color', names='RED GREEN BLUE')).
282 When used for the functional API:
284 `value` will be the name of the new class.
286 `names` should be either a string of white-space/comma delimited names
287 (values will start at `start`), or an iterator/mapping of name, value pairs.
289 `module` should be set to the module this class is being created in;
290 if it is not set, an attempt to find that module will be made, but if
291 it fails the class will not be picklable.
293 `qualname` should be set to the actual location this class can be found
294 at in its module; by default it is set to the global scope. If this is
295 not correct, unpickling will fail in some circumstances.
297 `type`, if set, will be mixed in as the first base class.
300 if names
is None: # simple value lookup
301 return cls
.__new
__(cls
, value
)
302 # otherwise, functional API: we're creating a new Enum type
303 return cls
._create
_(value
, names
, module
=module
, qualname
=qualname
, type=type, start
=start
)
305 def __contains__(cls
, member
):
306 return isinstance(member
, cls
) and member
._name
_ in cls
._member
_map
_
308 def __delattr__(cls
, attr
):
309 # nicer error message when someone tries to delete an attribute
311 if attr
in cls
._member
_map
_:
312 raise AttributeError(
313 "%s: cannot delete Enum member." % cls
.__name
__)
314 super().__delattr
__(attr
)
317 return (['__class__', '__doc__', '__members__', '__module__'] +
320 def __getattr__(cls
, name
):
321 """Return the enum member matching `name`
323 We use __getattr__ instead of descriptors or inserting into the enum
324 class' __dict__ in order to support `name` and `value` being both
325 properties for enum members (which live in the class' __dict__) and
326 enum members themselves.
330 raise AttributeError(name
)
332 return cls
._member
_map
_[name
]
334 raise AttributeError(name
) from None
336 def __getitem__(cls
, name
):
337 return cls
._member
_map
_[name
]
340 return (cls
._member
_map
_[name
] for name
in cls
._member
_names
_)
343 return len(cls
._member
_names
_)
346 def __members__(cls
):
347 """Returns a mapping of member name->value.
349 This mapping lists all enum members, including aliases. Note that this
350 is a read-only view of the internal mapping.
353 return MappingProxyType(cls
._member
_map
_)
356 return "<enum %r>" % cls
.__name
__
358 def __reversed__(cls
):
359 return (cls
._member
_map
_[name
] for name
in reversed(cls
._member
_names
_))
361 def __setattr__(cls
, name
, value
):
362 """Block attempts to reassign Enum members.
364 A simple assignment to the class namespace only changes one of the
365 several possible ways to get an Enum member from the Enum class,
366 resulting in an inconsistent Enumeration.
369 member_map
= cls
.__dict
__.get('_member_map_', {})
370 if name
in member_map
:
371 raise AttributeError('Cannot reassign members.')
372 super().__setattr
__(name
, value
)
374 def _create_(cls
, class_name
, names
=None, *, module
=None, qualname
=None, type=None, start
=1):
375 """Convenience method to create a new Enum class.
379 * A string containing member names, separated either with spaces or
380 commas. Values are incremented by 1 from `start`.
381 * An iterable of member names. Values are incremented by 1 from `start`.
382 * An iterable of (member name, value) pairs.
383 * A mapping of member name -> value pairs.
386 metacls
= cls
.__class
__
387 bases
= (cls
, ) if type is None else (type, cls
)
388 _
, first_enum
= cls
._get
_mixins
_(bases
)
389 classdict
= metacls
.__prepare
__(class_name
, bases
)
391 # special processing needed for names?
392 if isinstance(names
, str):
393 names
= names
.replace(',', ' ').split()
394 if isinstance(names
, (tuple, list)) and names
and isinstance(names
[0], str):
395 original_names
, names
= names
, []
397 for count
, name
in enumerate(original_names
):
398 value
= first_enum
._generate
_next
_value
_(name
, start
, count
, last_values
[:])
399 last_values
.append(value
)
400 names
.append((name
, value
))
402 # Here, names is either an iterable of (name, value) or a mapping.
404 if isinstance(item
, str):
405 member_name
, member_value
= item
, names
[item
]
407 member_name
, member_value
= item
408 classdict
[member_name
] = member_value
409 enum_class
= metacls
.__new
__(metacls
, class_name
, bases
, classdict
)
411 # TODO: replace the frame hack if a blessed way to know the calling
412 # module is ever developed
415 module
= sys
._getframe
(2).f_globals
['__name__']
416 except (AttributeError, ValueError) as exc
:
419 _make_class_unpicklable(enum_class
)
421 enum_class
.__module
__ = module
422 if qualname
is not None:
423 enum_class
.__qualname
__ = qualname
428 def _get_mixins_(bases
):
429 """Returns the type for creating enum members, and the first inherited
432 bases: the tuple of bases that was given to __new__
439 # double check that we are not subclassing a class with existing
440 # enumeration members; while we're at it, see if any other data
441 # type has been mixed in so we can use the correct __new__
442 member_type
= first_enum
= None
444 if (base
is not Enum
and
445 issubclass(base
, Enum
) and
446 base
._member
_names
_):
447 raise TypeError("Cannot extend enumerations")
451 # base is now the last base in bases
452 if not issubclass(base
, Enum
):
453 raise TypeError("new enumerations must be created as "
454 "`ClassName([mixin_type,] enum_type)`")
456 # get correct mix-in type (either mix-in type of Enum subclass, or
457 # first base if last base is Enum)
458 if not issubclass(bases
[0], Enum
):
459 member_type
= bases
[0] # first data type
460 first_enum
= bases
[-1] # enum type
462 for base
in bases
[0].__mro
__:
463 # most common: (IntEnum, int, Enum, object)
464 # possible: (<Enum 'AutoIntEnum'>, <Enum 'IntEnum'>,
465 # <class 'int'>, <Enum 'Enum'>,
467 if issubclass(base
, Enum
):
468 if first_enum
is None:
471 if member_type
is None:
474 return member_type
, first_enum
477 def _find_new_(classdict
, member_type
, first_enum
):
478 """Returns the __new__ to be used for creating the enum members.
480 classdict: the class dictionary given to __new__
481 member_type: the data type whose __new__ will be used by default
482 first_enum: enumeration to check for an overriding __new__
485 # now find the correct __new__, checking to see of one was defined
486 # by the user; also check earlier enum classes in case a __new__ was
487 # saved as __new_member__
489 __new__
= classdict
.get('__new__', None)
491 # should __new__ be saved as __new_member__ later?
492 save_new
= __new__
is not None
495 # check all possibles for __new_member__ before falling back to
497 for method
in ('__new_member__', '__new__'):
498 for possible
in (member_type
, first_enum
):
499 target
= getattr(possible
, method
, None)
508 if __new__
is not None:
511 __new__
= object.__new
__
513 # if a non-object.__new__ is used then whatever value/tuple was
514 # assigned to the enum member name will be passed to __new__ and to the
515 # new enum member's __init__
516 if __new__
is object.__new
__:
521 return __new__
, save_new
, use_args
523 class Enum(metaclass
=EnumMeta
):
524 """Generic enumeration.
526 Derive from this class to define new enumerations.
529 def __new__(cls
, value
):
530 # all enum instances are actually created during class construction
531 # without calling this method; this method is called by the metaclass'
532 # __call__ (i.e. Color(3) ), and by pickle
533 if type(value
) is cls
:
534 # For lookups like Color(Color.RED)
536 # by-value search for a matching enum member
537 # see if it's in the reverse mapping (for hashable values)
539 if value
in cls
._value
2member
_map
_:
540 return cls
._value
2member
_map
_[value
]
542 # not there, now do long search -- O(n) behavior
543 for member
in cls
._member
_map
_.values():
544 if member
._value
_ == value
:
546 # still not found -- try _missing_ hook
547 return cls
._missing
_(value
)
549 def _generate_next_value_(name
, start
, count
, last_values
):
550 for last_value
in reversed(last_values
):
552 return last_value
+ 1
559 def _missing_(cls
, value
):
560 raise ValueError("%r is not a valid %s" % (value
, cls
.__name
__))
563 return "<%s.%s: %r>" % (
564 self
.__class
__.__name
__, self
._name
_, self
._value
_)
567 return "%s.%s" % (self
.__class
__.__name
__, self
._name
_)
572 for cls
in self
.__class
__.mro()
573 for m
in cls
.__dict
__
574 if m
[0] != '_' and m
not in self
._member
_map
_
576 return (['__class__', '__doc__', '__module__'] + added_behavior
)
578 def __format__(self
, format_spec
):
579 # mixed-in Enums should use the mixed-in type's __format__, otherwise
580 # we can get strange results with the Enum name showing up instead of
584 if self
._member
_type
_ is object:
589 cls
= self
._member
_type
_
591 return cls
.__format
__(val
, format_spec
)
594 return hash(self
._name
_)
596 def __reduce_ex__(self
, proto
):
597 return self
.__class
__, (self
._value
_, )
599 # DynamicClassAttribute is used to provide access to the `name` and
600 # `value` properties of enum members while keeping some measure of
601 # protection from modification, while still allowing for an enumeration
602 # to have members named `name` and `value`. This works because enumeration
603 # members are not set directly on the enum class -- __getattr__ is
604 # used to look them up.
606 @DynamicClassAttribute
608 """The name of the Enum member."""
611 @DynamicClassAttribute
613 """The value of the Enum member."""
617 def _convert(cls
, name
, module
, filter, source
=None):
619 Create a new Enum subclass that replaces a collection of global constants
621 # convert all constants from source (or module) that pass filter() to
622 # a new Enum called name, and export the enum and its members back to
624 # also, replace the __reduce_ex__ method so unpickling works in
625 # previous Python versions
626 module_globals
= vars(sys
.modules
[module
])
628 source
= vars(source
)
630 source
= module_globals
631 # We use an OrderedDict of sorted source keys so that the
632 # _value2member_map is populated in the same order every time
633 # for a consistent reverse mapping of number to name when there
634 # are multiple names for the same number rather than varying
635 # between runs due to hash randomization of the module dictionary.
638 for name
in source
.keys()
642 members
.sort(key
=lambda t
: (t
[1], t
[0]))
644 # unless some values aren't comparable, in which case sort by name
645 members
.sort(key
=lambda t
: t
[0])
646 cls
= cls(name
, members
, module
=module
)
647 cls
.__reduce
_ex
__ = _reduce_ex_by_name
648 module_globals
.update(cls
.__members
__)
649 module_globals
[name
] = cls
654 class IntEnum(int, Enum
):
655 """Enum where members are also (and must be) ints"""
658 def _reduce_ex_by_name(self
, proto
):
662 """Support for flags"""
664 def _generate_next_value_(name
, start
, count
, last_values
):
666 Generate the next value when not given.
668 name: the name of the member
669 start: the initital start value or None
670 count: the number of existing members
671 last_value: the last value assigned or None
674 return start
if start
is not None else 1
675 for last_value
in reversed(last_values
):
677 high_bit
= _high_bit(last_value
)
680 raise TypeError('Invalid Flag value: %r' % last_value
) from None
681 return 2 ** (high_bit
+1)
684 def _missing_(cls
, value
):
685 original_value
= value
688 possible_member
= cls
._create
_pseudo
_member
_(value
)
689 if original_value
< 0:
690 possible_member
= ~possible_member
691 return possible_member
694 def _create_pseudo_member_(cls
, value
):
696 Create a composite member iff value contains only members.
698 pseudo_member
= cls
._value
2member
_map
_.get(value
, None)
699 if pseudo_member
is None:
700 # verify all bits are accounted for
701 _
, extra_flags
= _decompose(cls
, value
)
703 raise ValueError("%r is not a valid %s" % (value
, cls
.__name
__))
704 # construct a singleton enum pseudo-member
705 pseudo_member
= object.__new
__(cls
)
706 pseudo_member
._name
_ = None
707 pseudo_member
._value
_ = value
708 # use setdefault in case another thread already created a composite
710 pseudo_member
= cls
._value
2member
_map
_.setdefault(value
, pseudo_member
)
713 def __contains__(self
, other
):
714 if not isinstance(other
, self
.__class
__):
715 return NotImplemented
716 return other
._value
_ & self
._value
_ == other
._value
_
720 if self
._name
_ is not None:
721 return '<%s.%s: %r>' % (cls
.__name
__, self
._name
_, self
._value
_)
722 members
, uncovered
= _decompose(cls
, self
._value
_)
723 return '<%s.%s: %r>' % (
725 '|'.join([str(m
._name
_ or m
._value
_) for m
in members
]),
731 if self
._name
_ is not None:
732 return '%s.%s' % (cls
.__name
__, self
._name
_)
733 members
, uncovered
= _decompose(cls
, self
._value
_)
734 if len(members
) == 1 and members
[0]._name
_ is None:
735 return '%s.%r' % (cls
.__name
__, members
[0]._value
_)
739 '|'.join([str(m
._name
_ or m
._value
_) for m
in members
]),
743 return bool(self
._value
_)
745 def __or__(self
, other
):
746 if not isinstance(other
, self
.__class
__):
747 return NotImplemented
748 return self
.__class
__(self
._value
_ | other
._value
_)
750 def __and__(self
, other
):
751 if not isinstance(other
, self
.__class
__):
752 return NotImplemented
753 return self
.__class
__(self
._value
_ & other
._value
_)
755 def __xor__(self
, other
):
756 if not isinstance(other
, self
.__class
__):
757 return NotImplemented
758 return self
.__class
__(self
._value
_ ^ other
._value
_)
760 def __invert__(self
):
761 members
, uncovered
= _decompose(self
.__class
__, self
._value
_)
763 m
for m
in self
.__class
__
764 if m
not in members
and not m
._value
_ & self
._value
_
766 inverted
= reduce(_or_
, inverted_members
, self
.__class
__(0))
767 return self
.__class
__(inverted
)
770 class IntFlag(int, Flag
):
771 """Support for integer-based Flags"""
774 def _missing_(cls
, value
):
775 if not isinstance(value
, int):
776 raise ValueError("%r is not a valid %s" % (value
, cls
.__name
__))
777 new_member
= cls
._create
_pseudo
_member
_(value
)
781 def _create_pseudo_member_(cls
, value
):
782 pseudo_member
= cls
._value
2member
_map
_.get(value
, None)
783 if pseudo_member
is None:
784 need_to_create
= [value
]
785 # get unaccounted for bits
786 _
, extra_flags
= _decompose(cls
, value
)
790 bit
= _high_bit(extra_flags
)
791 flag_value
= 2 ** bit
792 if (flag_value
not in cls
._value
2member
_map
_ and
793 flag_value
not in need_to_create
795 need_to_create
.append(flag_value
)
796 if extra_flags
== -flag_value
:
799 extra_flags ^
= flag_value
800 for value
in reversed(need_to_create
):
801 # construct singleton pseudo-members
802 pseudo_member
= int.__new
__(cls
, value
)
803 pseudo_member
._name
_ = None
804 pseudo_member
._value
_ = value
805 # use setdefault in case another thread already created a composite
807 pseudo_member
= cls
._value
2member
_map
_.setdefault(value
, pseudo_member
)
810 def __or__(self
, other
):
811 if not isinstance(other
, (self
.__class
__, int)):
812 return NotImplemented
813 result
= self
.__class
__(self
._value
_ | self
.__class
__(other
)._value
_)
816 def __and__(self
, other
):
817 if not isinstance(other
, (self
.__class
__, int)):
818 return NotImplemented
819 return self
.__class
__(self
._value
_ & self
.__class
__(other
)._value
_)
821 def __xor__(self
, other
):
822 if not isinstance(other
, (self
.__class
__, int)):
823 return NotImplemented
824 return self
.__class
__(self
._value
_ ^ self
.__class
__(other
)._value
_)
830 def __invert__(self
):
831 result
= self
.__class
__(~self
._value
_)
835 def _high_bit(value
):
836 """returns index of highest bit, or -1 if value is zero or negative"""
837 return value
.bit_length() - 1
839 def unique(enumeration
):
840 """Class decorator for enumerations ensuring unique member values."""
842 for name
, member
in enumeration
.__members
__.items():
843 if name
!= member
.name
:
844 duplicates
.append((name
, member
.name
))
846 alias_details
= ', '.join(
847 ["%s -> %s" % (alias
, name
) for (alias
, name
) in duplicates
])
848 raise ValueError('duplicate values found in %r: %s' %
849 (enumeration
, alias_details
))
852 def _decompose(flag
, value
):
853 """Extract all members from the value."""
854 # _decompose is only called if the value is not named
857 # issue29167: wrap accesses to _value2member_map_ in a list to avoid race
858 # conditions between iterating over it and having more psuedo-
859 # members added to it
861 # only check for named flags
864 for v
, m
in list(flag
._value
2member
_map
_.items())
865 if m
.name
is not None
868 # check for named flags and powers-of-two flags
871 for v
, m
in list(flag
._value
2member
_map
_.items())
872 if m
.name
is not None or _power_of_two(v
)
875 for member
, member_value
in flags_to_check
:
876 if member_value
and member_value
& value
== member_value
:
877 members
.append(member
)
878 not_covered
&= ~member_value
879 if not members
and value
in flag
._value
2member
_map
_:
880 members
.append(flag
._value
2member
_map
_[value
])
881 members
.sort(key
=lambda m
: m
._value
_, reverse
=True)
882 if len(members
) > 1 and members
[0].value
== value
:
883 # we have the breakdown, don't need the value member itself
885 return members
, not_covered
887 def _power_of_two(value
):
890 return value
== 2 ** _high_bit(value
)