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>'
55 Instances are replaced with an appropriate value in Enum class suites.
59 class _EnumDict(dict):
60 """Track enum member order and ensure member names are not reused.
62 EnumMeta will use the names found in self._member_names as the
63 enumeration member names.
68 self
._member
_names
= []
69 self
._last
_values
= []
71 def __setitem__(self
, key
, value
):
72 """Changes anything not dundered or not a descriptor.
74 If an enum member name is used twice, an error is raised; duplicate
75 values are not checked for.
77 Single underscore (sunder) names are reserved.
82 '_order_', '_create_pseudo_member_',
83 '_generate_next_value_', '_missing_',
85 raise ValueError('_names_ are reserved for future Enum use')
86 if key
== '_generate_next_value_':
87 setattr(self
, '_generate_next_value', value
)
89 if key
== '__order__':
91 elif (key
in self
._member
_names
):
92 # descriptor overwriting an enum?
93 raise TypeError('Attempted to reuse key: %r' % key
)
94 elif (not _is_descriptor(value
)):
96 # enum overwriting a descriptor?
97 raise TypeError('%r already defined as: %r' % (key
, self
[key
]))
98 if isinstance(value
, auto
):
99 if value
.value
== _auto_null
:
100 value
.value
= self
._generate
_next
_value
(key
, 1, len(self
._member
_names
), self
._last
_values
[:])
102 self
._member
_names
.append(key
)
103 self
._last
_values
.append(value
)
104 super().__setitem
__(key
, value
)
106 # Dummy value for Enum as EnumMeta explicitly checks for it, but of course
107 # until EnumMeta finishes running the first time the Enum class doesn't exist.
108 # This is also why there are checks in EnumMeta like `if Enum is not None`
111 class EnumMeta(type):
112 """Metaclass for Enum"""
114 def __prepare__(metacls
, cls
, bases
):
115 # create the namespace dict
116 enum_dict
= _EnumDict()
118 # inherit previous flags and _generate_next_value_ function
119 member_type
, first_enum
= metacls
._get
_mixins
_(bases
)
121 if first_enum
is not None:
122 enum_dict
['_generate_next_value_'] = getattr(first_enum
, '_generate_next_value_', None)
126 def __new__(metacls
, cls
, bases
, classdict
):
127 # an Enum class is final once enumeration items have been defined; it
128 # cannot be mixed with other types (int, float, etc.) if it has an
129 # inherited __new__ unless a new __new__ is defined (or the resulting
131 member_type
, first_enum
= metacls
._get
_mixins
_(bases
)
133 new
, save_new
, use_args
= metacls
._find
_new
_(classdict
, member_type
,
135 # save enum items into separate mapping so they don't get baked into
137 enum_members
= {k
: classdict
[k
] for k
in classdict
._member
_names
}
139 for name
in classdict
._member
_names
:
143 _order_
= classdict
.pop('_order_', None)
145 # check for illegal enum names (any others?)
146 invalid_names
= set(enum_members
) & {'mro', }
148 raise ValueError('Invalid enum member name: {0}'.format(
149 ','.join(invalid_names
)))
151 # create a default docstring if one has not been provided
152 if '__doc__' not in classdict
:
153 classdict
['__doc__'] = 'An enumeration.'
155 # create our new Enum type
156 enum_class
= super().__new
__(metacls
, cls
, bases
, classdict
)
157 enum_class
._member
_names
_ = [] # names in definition order
158 enum_class
._member
_map
_ = OrderedDict() # name->value map
159 enum_class
._member
_type
_ = member_type
161 # save attributes from super classes so we know if we can take
162 # the shortcut of storing members in the class dict
163 base_attributes
= {a
for b
in enum_class
.mro() for a
in b
.__dict
__}
165 # Reverse value->name map for hashable values.
166 enum_class
._value
2member
_map
_ = {}
168 # If a custom type is mixed into the Enum, and it does not know how
169 # to pickle itself, pickle.dumps will succeed but pickle.loads will
170 # fail. Rather than have the error show up later and possibly far
171 # from the source, sabotage the pickle protocol for this class so
172 # that pickle.dumps also fails.
174 # However, if the new class implements its own __reduce_ex__, do not
175 # sabotage -- it's on them to make sure it works correctly. We use
176 # __reduce_ex__ instead of any of the others as it is preferred by
177 # pickle over __reduce__, and it handles all pickle protocols.
178 if '__reduce_ex__' not in classdict
:
179 if member_type
is not object:
180 methods
= ('__getnewargs_ex__', '__getnewargs__',
181 '__reduce_ex__', '__reduce__')
182 if not any(m
in member_type
.__dict
__ for m
in methods
):
183 _make_class_unpicklable(enum_class
)
185 # instantiate them, checking for duplicates as we go
186 # we instantiate first instead of checking for duplicates first in case
187 # a custom __new__ is doing something funky with the values -- such as
189 for member_name
in classdict
._member
_names
:
190 value
= enum_members
[member_name
]
191 if not isinstance(value
, tuple):
196 if member_type
is tuple: # special case for tuple enums
197 args
= (args
, ) # wrap it one more time
200 enum_member
= new(enum_class
)
201 if not hasattr(enum_member
, '_value_'):
202 enum_member
._value
_ = value
204 enum_member
= new(enum_class
, *args
)
205 if not hasattr(enum_member
, '_value_'):
206 if member_type
is object:
207 enum_member
._value
_ = value
209 enum_member
._value
_ = member_type(*args
)
210 value
= enum_member
._value
_
211 enum_member
._name
_ = member_name
212 enum_member
.__objclass
__ = enum_class
213 enum_member
.__init
__(*args
)
215 # If another member with the same value was already defined, the
216 # new member becomes an alias to the existing one.
217 for name
, canonical_member
in enum_class
._member
_map
_.items():
218 if canonical_member
._value
_ == enum_member
._value
_:
219 enum_member
= canonical_member
222 # Aliases don't appear in member names (only in __members__).
223 enum_class
._member
_names
_.append(member_name
)
225 # performance boost for any member that would not shadow
226 # a DynamicClassAttribute
227 if member_name
not in base_attributes
:
228 setattr(enum_class
, member_name
, enum_member
)
229 # now add to _member_map_
231 enum_class
._member
_map
_[member_name
] = enum_member
233 # This may fail if value is not hashable. We can't add the value
234 # to the map, and by-value lookups for this value will be
236 enum_class
._value
2member
_map
_[value
] = enum_member
240 # double check that repr and friends are not the mixin's or various
241 # things break (such as pickle)
242 for name
in ('__repr__', '__str__', '__format__', '__reduce_ex__'):
243 class_method
= getattr(enum_class
, name
)
244 obj_method
= getattr(member_type
, name
, None)
245 enum_method
= getattr(first_enum
, name
, None)
246 if obj_method
is not None and obj_method
is class_method
:
247 setattr(enum_class
, name
, enum_method
)
249 # replace any other __new__ with our own (as long as Enum is not None,
250 # anyway) -- again, this is to support pickle
252 # if the user defined their own __new__, save it before it gets
253 # clobbered in case they subclass later
255 enum_class
.__new
_member
__ = __new__
256 enum_class
.__new
__ = Enum
.__new
__
258 # py3 support for definition order (helps keep py2/py3 code in sync)
259 if _order_
is not None:
260 if isinstance(_order_
, str):
261 _order_
= _order_
.replace(',', ' ').split()
262 if _order_
!= enum_class
._member
_names
_:
263 raise TypeError('member order does not match _order_')
269 classes/types should always be True.
273 def __call__(cls
, value
, names
=None, *, module
=None, qualname
=None, type=None, start
=1):
274 """Either returns an existing member, or creates a new enum class.
276 This method is used both when an enum class is given a value to match
277 to an enumeration member (i.e. Color(3)) and for the functional API
278 (i.e. Color = Enum('Color', names='RED GREEN BLUE')).
280 When used for the functional API:
282 `value` will be the name of the new class.
284 `names` should be either a string of white-space/comma delimited names
285 (values will start at `start`), or an iterator/mapping of name, value pairs.
287 `module` should be set to the module this class is being created in;
288 if it is not set, an attempt to find that module will be made, but if
289 it fails the class will not be picklable.
291 `qualname` should be set to the actual location this class can be found
292 at in its module; by default it is set to the global scope. If this is
293 not correct, unpickling will fail in some circumstances.
295 `type`, if set, will be mixed in as the first base class.
298 if names
is None: # simple value lookup
299 return cls
.__new
__(cls
, value
)
300 # otherwise, functional API: we're creating a new Enum type
301 return cls
._create
_(value
, names
, module
=module
, qualname
=qualname
, type=type, start
=start
)
303 def __contains__(cls
, member
):
304 return isinstance(member
, cls
) and member
._name
_ in cls
._member
_map
_
306 def __delattr__(cls
, attr
):
307 # nicer error message when someone tries to delete an attribute
309 if attr
in cls
._member
_map
_:
310 raise AttributeError(
311 "%s: cannot delete Enum member." % cls
.__name
__)
312 super().__delattr
__(attr
)
315 return (['__class__', '__doc__', '__members__', '__module__'] +
318 def __getattr__(cls
, name
):
319 """Return the enum member matching `name`
321 We use __getattr__ instead of descriptors or inserting into the enum
322 class' __dict__ in order to support `name` and `value` being both
323 properties for enum members (which live in the class' __dict__) and
324 enum members themselves.
328 raise AttributeError(name
)
330 return cls
._member
_map
_[name
]
332 raise AttributeError(name
) from None
334 def __getitem__(cls
, name
):
335 return cls
._member
_map
_[name
]
338 return (cls
._member
_map
_[name
] for name
in cls
._member
_names
_)
341 return len(cls
._member
_names
_)
344 def __members__(cls
):
345 """Returns a mapping of member name->value.
347 This mapping lists all enum members, including aliases. Note that this
348 is a read-only view of the internal mapping.
351 return MappingProxyType(cls
._member
_map
_)
354 return "<enum %r>" % cls
.__name
__
356 def __reversed__(cls
):
357 return (cls
._member
_map
_[name
] for name
in reversed(cls
._member
_names
_))
359 def __setattr__(cls
, name
, value
):
360 """Block attempts to reassign Enum members.
362 A simple assignment to the class namespace only changes one of the
363 several possible ways to get an Enum member from the Enum class,
364 resulting in an inconsistent Enumeration.
368 member_map
= cls
.__dict
__.get('_member_map_', {})
370 if name
in member_map
:
371 raise AttributeError('Cannot reassign members.')
373 super().__setattr
__(name
, value
)
376 def _create_(cls
, class_name
, names
=None, *, module
=None, qualname
=None, type=None, start
=1):
377 """Convenience method to create a new Enum class.
381 * A string containing member names, separated either with spaces or
382 commas. Values are incremented by 1 from `start`.
383 * An iterable of member names. Values are incremented by 1 from `start`.
384 * An iterable of (member name, value) pairs.
385 * A mapping of member name -> value pairs.
388 metacls
= cls
.__class
__
389 bases
= (cls
, ) if type is None else (type, cls
)
390 _
, first_enum
= cls
._get
_mixins
_(bases
)
391 classdict
= metacls
.__prepare
__(class_name
, bases
)
393 # special processing needed for names?
394 if isinstance(names
, str):
395 names
= names
.replace(',', ' ').split()
396 if isinstance(names
, (tuple, list)) and names
and isinstance(names
[0], str):
397 original_names
, names
= names
, []
399 for count
, name
in enumerate(original_names
):
400 value
= first_enum
._generate
_next
_value
_(name
, start
, count
, last_values
[:])
401 last_values
.append(value
)
402 names
.append((name
, value
))
404 # Here, names is either an iterable of (name, value) or a mapping.
406 if isinstance(item
, str):
407 member_name
, member_value
= item
, names
[item
]
409 member_name
, member_value
= item
410 classdict
[member_name
] = member_value
411 enum_class
= metacls
.__new
__(metacls
, class_name
, bases
, classdict
)
413 # TODO: replace the frame hack if a blessed way to know the calling
414 # module is ever developed
417 module
= sys
._getframe
(2).f_globals
['__name__']
418 except (AttributeError, ValueError) as exc
:
421 _make_class_unpicklable(enum_class
)
423 enum_class
.__module
__ = module
424 if qualname
is not None:
425 enum_class
.__qualname
__ = qualname
430 def _get_mixins_(bases
):
431 """Returns the type for creating enum members, and the first inherited
434 bases: the tuple of bases that was given to __new__
441 # double check that we are not subclassing a class with existing
442 # enumeration members; while we're at it, see if any other data
443 # type has been mixed in so we can use the correct __new__
444 member_type
= first_enum
= None
446 if (base
is not Enum
and
447 issubclass(base
, Enum
) and
448 base
._member
_names
_):
449 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
524 class Enum(metaclass
=EnumMeta
):
525 """Generic enumeration.
527 Derive from this class to define new enumerations.
531 def __new__(cls
, value
):
532 # all enum instances are actually created during class construction
533 # without calling this method; this method is called by the metaclass'
534 # __call__ (i.e. Color(3) ), and by pickle
535 if type(value
) is cls
:
536 # For lookups like Color(Color.RED)
538 # by-value search for a matching enum member
539 # see if it's in the reverse mapping (for hashable values)
541 if value
in cls
._value
2member
_map
_:
542 return cls
._value
2member
_map
_[value
]
544 # not there, now do long search -- O(n) behavior
545 for member
in cls
._member
_map
_.values():
546 if member
._value
_ == value
:
548 # still not found -- try _missing_ hook
549 return cls
._missing
_(value
)
551 def _generate_next_value_(name
, start
, count
, last_values
):
552 for last_value
in reversed(last_values
):
554 return last_value
+ 1
561 def _missing_(cls
, value
):
562 raise ValueError("%r is not a valid %s" % (value
, cls
.__name
__))
565 return "<%s.%s: %r>" % (
566 self
.__class
__.__name
__, self
._name
_, self
._value
_)
569 return "%s.%s" % (self
.__class
__.__name
__, self
._name
_)
574 for cls
in self
.__class
__.mro()
575 for m
in cls
.__dict
__
576 if m
[0] != '_' and m
not in self
._member
_map
_
578 return (['__class__', '__doc__', '__module__'] + added_behavior
)
580 def __format__(self
, format_spec
):
581 # mixed-in Enums should use the mixed-in type's __format__, otherwise
582 # we can get strange results with the Enum name showing up instead of
586 if self
._member
_type
_ is object:
591 cls
= self
._member
_type
_
593 return cls
.__format
__(val
, format_spec
)
596 return hash(self
._name
_)
598 def __reduce_ex__(self
, proto
):
599 return self
.__class
__, (self
._value
_, )
601 # DynamicClassAttribute is used to provide access to the `name` and
602 # `value` properties of enum members while keeping some measure of
603 # protection from modification, while still allowing for an enumeration
604 # to have members named `name` and `value`. This works because enumeration
605 # members are not set directly on the enum class -- __getattr__ is
606 # used to look them up.
608 @DynamicClassAttribute
610 """The name of the Enum member."""
613 @DynamicClassAttribute
615 """The value of the Enum member."""
619 def _convert(cls
, name
, module
, filter, source
=None):
621 Create a new Enum subclass that replaces a collection of global constants
623 # convert all constants from source (or module) that pass filter() to
624 # a new Enum called name, and export the enum and its members back to
626 # also, replace the __reduce_ex__ method so unpickling works in
627 # previous Python versions
628 module_globals
= vars(sys
.modules
[module
])
630 source
= vars(source
)
632 source
= module_globals
633 # We use an OrderedDict of sorted source keys so that the
634 # _value2member_map is populated in the same order every time
635 # for a consistent reverse mapping of number to name when there
636 # are multiple names for the same number rather than varying
637 # between runs due to hash randomization of the module dictionary.
640 for name
in source
.keys()
644 members
.sort(key
=lambda t
: (t
[1], t
[0]))
646 # unless some values aren't comparable, in which case sort by name
647 members
.sort(key
=lambda t
: t
[0])
648 cls
= cls(name
, members
, module
=module
)
649 cls
.__reduce
_ex
__ = _reduce_ex_by_name
650 module_globals
.update(cls
.__members
__)
651 module_globals
[name
] = cls
655 class IntEnum(int, Enum
):
656 """Enum where members are also (and must be) ints"""
659 def _reduce_ex_by_name(self
, proto
):
663 """Support for flags"""
665 def _generate_next_value_(name
, start
, count
, last_values
):
667 Generate the next value when not given.
669 name: the name of the member
670 start: the initital start value or None
671 count: the number of existing members
672 last_value: the last value assigned or None
675 return start
if start
is not None else 1
676 for last_value
in reversed(last_values
):
678 high_bit
= _high_bit(last_value
)
681 raise TypeError('Invalid Flag value: %r' % last_value
) from None
682 return 2 ** (high_bit
+1)
685 def _missing_(cls
, value
):
686 original_value
= value
689 possible_member
= cls
._create
_pseudo
_member
_(value
)
690 if original_value
< 0:
691 possible_member
= ~possible_member
692 return possible_member
695 def _create_pseudo_member_(cls
, value
):
697 Create a composite member iff value contains only members.
699 pseudo_member
= cls
._value
2member
_map
_.get(value
, None)
700 if pseudo_member
is None:
701 # verify all bits are accounted for
702 _
, extra_flags
= _decompose(cls
, value
)
704 raise ValueError("%r is not a valid %s" % (value
, cls
.__name
__))
705 # construct a singleton enum pseudo-member
706 pseudo_member
= object.__new
__(cls
)
707 pseudo_member
._name
_ = None
708 pseudo_member
._value
_ = value
709 # use setdefault in case another thread already created a composite
711 pseudo_member
= cls
._value
2member
_map
_.setdefault(value
, pseudo_member
)
714 def __contains__(self
, other
):
715 if not isinstance(other
, self
.__class
__):
716 return NotImplemented
717 return other
._value
_ & self
._value
_ == other
._value
_
721 if self
._name
_ is not None:
722 return '<%s.%s: %r>' % (cls
.__name
__, self
._name
_, self
._value
_)
723 members
, uncovered
= _decompose(cls
, self
._value
_)
724 return '<%s.%s: %r>' % (
726 '|'.join([str(m
._name
_ or m
._value
_) for m
in members
]),
732 if self
._name
_ is not None:
733 return '%s.%s' % (cls
.__name
__, self
._name
_)
734 members
, uncovered
= _decompose(cls
, self
._value
_)
735 if len(members
) == 1 and members
[0]._name
_ is None:
736 return '%s.%r' % (cls
.__name
__, members
[0]._value
_)
740 '|'.join([str(m
._name
_ or m
._value
_) for m
in members
]),
744 return bool(self
._value
_)
746 def __or__(self
, other
):
747 if not isinstance(other
, self
.__class
__):
748 return NotImplemented
749 return self
.__class
__(self
._value
_ | other
._value
_)
751 def __and__(self
, other
):
752 if not isinstance(other
, self
.__class
__):
753 return NotImplemented
754 return self
.__class
__(self
._value
_ & other
._value
_)
756 def __xor__(self
, other
):
757 if not isinstance(other
, self
.__class
__):
758 return NotImplemented
759 return self
.__class
__(self
._value
_ ^ other
._value
_)
761 def __invert__(self
):
762 members
, uncovered
= _decompose(self
.__class
__, self
._value
_)
764 m
for m
in self
.__class
__
765 if m
not in members
and not m
._value
_ & self
._value
_
767 inverted
= reduce(_or_
, inverted_members
, self
.__class
__(0))
768 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
_)
834 def _high_bit(value
):
835 """returns index of highest bit, or -1 if value is zero or negative"""
836 return value
.bit_length() - 1
838 def unique(enumeration
):
839 """Class decorator for enumerations ensuring unique member values."""
841 for name
, member
in enumeration
.__members
__.items():
842 if name
!= member
.name
:
843 duplicates
.append((name
, member
.name
))
845 alias_details
= ', '.join(
846 ["%s -> %s" % (alias
, name
) for (alias
, name
) in duplicates
])
847 raise ValueError('duplicate values found in %r: %s' %
848 (enumeration
, alias_details
))
851 def _decompose(flag
, value
):
852 """Extract all members from the value."""
853 # _decompose is only called if the value is not named
856 # issue29167: wrap accesses to _value2member_map_ in a list to avoid race
857 # conditions between iterating over it and having more psuedo-
858 # members added to it
860 # only check for named flags
863 for v
, m
in list(flag
._value
2member
_map
_.items())
864 if m
.name
is not None
867 # check for named flags and powers-of-two flags
870 for v
, m
in list(flag
._value
2member
_map
_.items())
871 if m
.name
is not None or _power_of_two(v
)
874 for member
, member_value
in flags_to_check
:
875 if member_value
and member_value
& value
== member_value
:
876 members
.append(member
)
877 not_covered
&= ~member_value
878 if not members
and value
in flag
._value
2member
_map
_:
879 members
.append(flag
._value
2member
_map
_[value
])
880 members
.sort(key
=lambda m
: m
._value
_, reverse
=True)
881 if len(members
) > 1 and members
[0].value
== value
:
882 # we have the breakdown, don't need the value member itself
884 return members
, not_covered
886 def _power_of_two(value
):
889 return value
== 2 ** _high_bit(value
)