eefc1b50bf3a024910e52560a77ad9a6f98cc477
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()
122 # inherit previous flags and _generate_next_value_ function
123 member_type
, first_enum
= metacls
._get
_mixins
_(bases
)
125 if first_enum
is not None:
126 enum_dict
['_generate_next_value_'] = getattr(first_enum
, '_generate_next_value_', None)
130 def __new__(metacls
, cls
, bases
, classdict
):
131 # an Enum class is final once enumeration items have been defined; it
132 # cannot be mixed with other types (int, float, etc.) if it has an
133 # inherited __new__ unless a new __new__ is defined (or the resulting
135 member_type
, first_enum
= metacls
._get
_mixins
_(bases
)
136 __new__
, save_new
, use_args
= metacls
._find
_new
_(classdict
, member_type
,
139 # save enum items into separate mapping so they don't get baked into
141 enum_members
= {k
: classdict
[k
] for k
in classdict
._member
_names
}
142 for name
in classdict
._member
_names
:
146 _order_
= classdict
.pop('_order_', None)
148 # check for illegal enum names (any others?)
149 invalid_names
= set(enum_members
) & {'mro', }
151 raise ValueError('Invalid enum member name: {0}'.format(
152 ','.join(invalid_names
)))
154 # create a default docstring if one has not been provided
155 if '__doc__' not in classdict
:
156 classdict
['__doc__'] = 'An enumeration.'
158 # create our new Enum type
159 enum_class
= super().__new
__(metacls
, cls
, bases
, classdict
)
161 enum_class
._member
_names
_ = [] # names in definition order
162 enum_class
._member
_map
_ = OrderedDict() # name->value map
163 enum_class
._member
_type
_ = member_type
165 # save attributes from super classes so we know if we can take
166 # the shortcut of storing members in the class dict
168 base_attributes
= {a
for b
in enum_class
.mro() for a
in b
.__dict
__}
170 # Reverse value->name map for hashable values.
171 enum_class
._value
2member
_map
_ = {}
173 # If a custom type is mixed into the Enum, and it does not know how
174 # to pickle itself, pickle.dumps will succeed but pickle.loads will
175 # fail. Rather than have the error show up later and possibly far
176 # from the source, sabotage the pickle protocol for this class so
177 # that pickle.dumps also fails.
179 # However, if the new class implements its own __reduce_ex__, do not
180 # sabotage -- it's on them to make sure it works correctly. We use
181 # __reduce_ex__ instead of any of the others as it is preferred by
182 # pickle over __reduce__, and it handles all pickle protocols.
183 if '__reduce_ex__' not in classdict
:
184 if member_type
is not object:
185 methods
= ('__getnewargs_ex__', '__getnewargs__',
186 '__reduce_ex__', '__reduce__')
187 if not any(m
in member_type
.__dict
__ for m
in methods
):
188 _make_class_unpicklable(enum_class
)
190 # instantiate them, checking for duplicates as we go
191 # we instantiate first instead of checking for duplicates first in case
192 # a custom __new__ is doing something funky with the values -- such as
194 for member_name
in classdict
._member
_names
:
195 value
= enum_members
[member_name
]
196 if not isinstance(value
, tuple):
200 if member_type
is tuple: # special case for tuple enums
201 args
= (args
, ) # wrap it one more time
203 enum_member
= __new__(enum_class
)
204 if not hasattr(enum_member
, '_value_'):
205 enum_member
._value
_ = value
207 enum_member
= __new__(enum_class
, *args
)
208 if not hasattr(enum_member
, '_value_'):
209 if member_type
is object:
210 enum_member
._value
_ = value
212 enum_member
._value
_ = member_type(*args
)
213 value
= enum_member
._value
_
214 enum_member
._name
_ = member_name
215 enum_member
.__objclass
__ = enum_class
216 enum_member
.__init
__(*args
)
217 # If another member with the same value was already defined, the
218 # new member becomes an alias to the existing one.
219 for name
, canonical_member
in enum_class
._member
_map
_.items():
220 if canonical_member
._value
_ == enum_member
._value
_:
221 enum_member
= canonical_member
224 # Aliases don't appear in member names (only in __members__).
225 enum_class
._member
_names
_.append(member_name
)
226 # performance boost for any member that would not shadow
227 # a DynamicClassAttribute
228 if member_name
not in base_attributes
:
229 setattr(enum_class
, member_name
, enum_member
)
230 # 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_')
264 pk('enum class fom new',enum_class
)
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.
367 member_map
= cls
.__dict
__.get('_member_map_', {})
368 if name
in member_map
:
369 raise AttributeError('Cannot reassign members.')
370 super().__setattr
__(name
, value
)
372 def _create_(cls
, class_name
, names
=None, *, module
=None, qualname
=None, type=None, start
=1):
373 """Convenience method to create a new Enum class.
377 * A string containing member names, separated either with spaces or
378 commas. Values are incremented by 1 from `start`.
379 * An iterable of member names. Values are incremented by 1 from `start`.
380 * An iterable of (member name, value) pairs.
381 * A mapping of member name -> value pairs.
384 metacls
= cls
.__class
__
385 bases
= (cls
, ) if type is None else (type, cls
)
386 _
, first_enum
= cls
._get
_mixins
_(bases
)
387 classdict
= metacls
.__prepare
__(class_name
, bases
)
389 # special processing needed for names?
390 if isinstance(names
, str):
391 names
= names
.replace(',', ' ').split()
392 if isinstance(names
, (tuple, list)) and names
and isinstance(names
[0], str):
393 original_names
, names
= names
, []
395 for count
, name
in enumerate(original_names
):
396 value
= first_enum
._generate
_next
_value
_(name
, start
, count
, last_values
[:])
397 last_values
.append(value
)
398 names
.append((name
, value
))
400 # Here, names is either an iterable of (name, value) or a mapping.
402 if isinstance(item
, str):
403 member_name
, member_value
= item
, names
[item
]
405 member_name
, member_value
= item
406 classdict
[member_name
] = member_value
407 enum_class
= metacls
.__new
__(metacls
, class_name
, bases
, classdict
)
409 # TODO: replace the frame hack if a blessed way to know the calling
410 # module is ever developed
413 module
= sys
._getframe
(2).f_globals
['__name__']
414 except (AttributeError, ValueError) as exc
:
417 _make_class_unpicklable(enum_class
)
419 enum_class
.__module
__ = module
420 if qualname
is not None:
421 enum_class
.__qualname
__ = qualname
426 def _get_mixins_(bases
):
427 """Returns the type for creating enum members, and the first inherited
430 bases: the tuple of bases that was given to __new__
437 # double check that we are not subclassing a class with existing
438 # enumeration members; while we're at it, see if any other data
439 # type has been mixed in so we can use the correct __new__
440 member_type
= first_enum
= None
442 if (base
is not Enum
and
443 issubclass(base
, Enum
) and
444 base
._member
_names
_):
445 raise TypeError("Cannot extend enumerations")
447 # base is now the last base in bases
448 if not issubclass(base
, Enum
):
449 raise TypeError("new enumerations must be created as "
450 "`ClassName([mixin_type,] enum_type)`")
452 # get correct mix-in type (either mix-in type of Enum subclass, or
453 # first base if last base is Enum)
454 if not issubclass(bases
[0], Enum
):
455 member_type
= bases
[0] # first data type
456 first_enum
= bases
[-1] # enum type
458 for base
in bases
[0].__mro
__:
459 # most common: (IntEnum, int, Enum, object)
460 # possible: (<Enum 'AutoIntEnum'>, <Enum 'IntEnum'>,
461 # <class 'int'>, <Enum 'Enum'>,
463 if issubclass(base
, Enum
):
464 if first_enum
is None:
467 if member_type
is None:
470 return member_type
, first_enum
473 def _find_new_(classdict
, member_type
, first_enum
):
474 """Returns the __new__ to be used for creating the enum members.
476 classdict: the class dictionary given to __new__
477 member_type: the data type whose __new__ will be used by default
478 first_enum: enumeration to check for an overriding __new__
481 # now find the correct __new__, checking to see of one was defined
482 # by the user; also check earlier enum classes in case a __new__ was
483 # saved as __new_member__
485 __new__
= classdict
.get('__new__', None)
487 # should __new__ be saved as __new_member__ later?
488 save_new
= __new__
is not None
491 # check all possibles for __new_member__ before falling back to
493 for method
in ('__new_member__', '__new__'):
494 for possible
in (member_type
, first_enum
):
495 target
= getattr(possible
, method
, None)
504 if __new__
is not None:
507 __new__
= object.__new
__
509 # if a non-object.__new__ is used then whatever value/tuple was
510 # assigned to the enum member name will be passed to __new__ and to the
511 # new enum member's __init__
512 if __new__
is object.__new
__:
517 return __new__
, save_new
, use_args
520 class Enum(metaclass
=EnumMeta
):
521 """Generic enumeration.
523 Derive from this class to define new enumerations.
526 def __new__(cls
, value
):
527 # all enum instances are actually created during class construction
528 # without calling this method; this method is called by the metaclass'
529 # __call__ (i.e. Color(3) ), and by pickle
530 if type(value
) is cls
:
531 # For lookups like Color(Color.RED)
533 # by-value search for a matching enum member
534 # see if it's in the reverse mapping (for hashable values)
536 if value
in cls
._value
2member
_map
_:
537 return cls
._value
2member
_map
_[value
]
539 # not there, now do long search -- O(n) behavior
540 for member
in cls
._member
_map
_.values():
541 if member
._value
_ == value
:
543 # still not found -- try _missing_ hook
544 return cls
._missing
_(value
)
546 def _generate_next_value_(name
, start
, count
, last_values
):
547 for last_value
in reversed(last_values
):
549 return last_value
+ 1
556 def _missing_(cls
, value
):
557 raise ValueError("%r is not a valid %s" % (value
, cls
.__name
__))
560 return "<%s.%s: %r>" % (
561 self
.__class
__.__name
__, self
._name
_, self
._value
_)
564 return "%s.%s" % (self
.__class
__.__name
__, self
._name
_)
569 for cls
in self
.__class
__.mro()
570 for m
in cls
.__dict
__
571 if m
[0] != '_' and m
not in self
._member
_map
_
573 return (['__class__', '__doc__', '__module__'] + added_behavior
)
575 def __format__(self
, format_spec
):
576 # mixed-in Enums should use the mixed-in type's __format__, otherwise
577 # we can get strange results with the Enum name showing up instead of
581 if self
._member
_type
_ is object:
586 cls
= self
._member
_type
_
588 return cls
.__format
__(val
, format_spec
)
591 return hash(self
._name
_)
593 def __reduce_ex__(self
, proto
):
594 return self
.__class
__, (self
._value
_, )
596 # DynamicClassAttribute is used to provide access to the `name` and
597 # `value` properties of enum members while keeping some measure of
598 # protection from modification, while still allowing for an enumeration
599 # to have members named `name` and `value`. This works because enumeration
600 # members are not set directly on the enum class -- __getattr__ is
601 # used to look them up.
603 @DynamicClassAttribute
605 """The name of the Enum member."""
608 @DynamicClassAttribute
610 """The value of the Enum member."""
614 def _convert(cls
, name
, module
, filter, source
=None):
616 Create a new Enum subclass that replaces a collection of global constants
618 # convert all constants from source (or module) that pass filter() to
619 # a new Enum called name, and export the enum and its members back to
621 # also, replace the __reduce_ex__ method so unpickling works in
622 # previous Python versions
623 module_globals
= vars(sys
.modules
[module
])
625 source
= vars(source
)
627 source
= module_globals
628 # We use an OrderedDict of sorted source keys so that the
629 # _value2member_map is populated in the same order every time
630 # for a consistent reverse mapping of number to name when there
631 # are multiple names for the same number rather than varying
632 # between runs due to hash randomization of the module dictionary.
635 for name
in source
.keys()
639 members
.sort(key
=lambda t
: (t
[1], t
[0]))
641 # unless some values aren't comparable, in which case sort by name
642 members
.sort(key
=lambda t
: t
[0])
643 cls
= cls(name
, members
, module
=module
)
644 cls
.__reduce
_ex
__ = _reduce_ex_by_name
645 module_globals
.update(cls
.__members
__)
646 module_globals
[name
] = cls
651 class IntEnum(int, Enum
):
652 """Enum where members are also (and must be) ints"""
655 def _reduce_ex_by_name(self
, proto
):
659 """Support for flags"""
661 def _generate_next_value_(name
, start
, count
, last_values
):
663 Generate the next value when not given.
665 name: the name of the member
666 start: the initital start value or None
667 count: the number of existing members
668 last_value: the last value assigned or None
671 return start
if start
is not None else 1
672 for last_value
in reversed(last_values
):
674 high_bit
= _high_bit(last_value
)
677 raise TypeError('Invalid Flag value: %r' % last_value
) from None
678 return 2 ** (high_bit
+1)
681 def _missing_(cls
, value
):
682 original_value
= value
685 possible_member
= cls
._create
_pseudo
_member
_(value
)
686 if original_value
< 0:
687 possible_member
= ~possible_member
688 return possible_member
691 def _create_pseudo_member_(cls
, value
):
693 Create a composite member iff value contains only members.
695 pseudo_member
= cls
._value
2member
_map
_.get(value
, None)
696 if pseudo_member
is None:
697 # verify all bits are accounted for
698 _
, extra_flags
= _decompose(cls
, value
)
700 raise ValueError("%r is not a valid %s" % (value
, cls
.__name
__))
701 # construct a singleton enum pseudo-member
702 pseudo_member
= object.__new
__(cls
)
703 pseudo_member
._name
_ = None
704 pseudo_member
._value
_ = value
705 # use setdefault in case another thread already created a composite
707 pseudo_member
= cls
._value
2member
_map
_.setdefault(value
, pseudo_member
)
710 def __contains__(self
, other
):
711 if not isinstance(other
, self
.__class
__):
712 return NotImplemented
713 return other
._value
_ & self
._value
_ == other
._value
_
717 if self
._name
_ is not None:
718 return '<%s.%s: %r>' % (cls
.__name
__, self
._name
_, self
._value
_)
719 members
, uncovered
= _decompose(cls
, self
._value
_)
720 return '<%s.%s: %r>' % (
722 '|'.join([str(m
._name
_ or m
._value
_) for m
in members
]),
728 if self
._name
_ is not None:
729 return '%s.%s' % (cls
.__name
__, self
._name
_)
730 members
, uncovered
= _decompose(cls
, self
._value
_)
731 if len(members
) == 1 and members
[0]._name
_ is None:
732 return '%s.%r' % (cls
.__name
__, members
[0]._value
_)
736 '|'.join([str(m
._name
_ or m
._value
_) for m
in members
]),
740 return bool(self
._value
_)
742 def __or__(self
, other
):
743 if not isinstance(other
, self
.__class
__):
744 return NotImplemented
745 return self
.__class
__(self
._value
_ | other
._value
_)
747 def __and__(self
, other
):
748 if not isinstance(other
, self
.__class
__):
749 return NotImplemented
750 return self
.__class
__(self
._value
_ & other
._value
_)
752 def __xor__(self
, other
):
753 if not isinstance(other
, self
.__class
__):
754 return NotImplemented
755 return self
.__class
__(self
._value
_ ^ other
._value
_)
757 def __invert__(self
):
758 members
, uncovered
= _decompose(self
.__class
__, self
._value
_)
760 m
for m
in self
.__class
__
761 if m
not in members
and not m
._value
_ & self
._value
_
763 inverted
= reduce(_or_
, inverted_members
, self
.__class
__(0))
764 return self
.__class
__(inverted
)
767 class IntFlag(int, Flag
):
768 """Support for integer-based Flags"""
771 def _missing_(cls
, value
):
772 if not isinstance(value
, int):
773 raise ValueError("%r is not a valid %s" % (value
, cls
.__name
__))
774 new_member
= cls
._create
_pseudo
_member
_(value
)
778 def _create_pseudo_member_(cls
, value
):
779 pseudo_member
= cls
._value
2member
_map
_.get(value
, None)
780 if pseudo_member
is None:
781 need_to_create
= [value
]
782 # get unaccounted for bits
783 _
, extra_flags
= _decompose(cls
, value
)
787 bit
= _high_bit(extra_flags
)
788 flag_value
= 2 ** bit
789 if (flag_value
not in cls
._value
2member
_map
_ and
790 flag_value
not in need_to_create
792 need_to_create
.append(flag_value
)
793 if extra_flags
== -flag_value
:
796 extra_flags ^
= flag_value
797 for value
in reversed(need_to_create
):
798 # construct singleton pseudo-members
799 pseudo_member
= int.__new
__(cls
, value
)
800 pseudo_member
._name
_ = None
801 pseudo_member
._value
_ = value
802 # use setdefault in case another thread already created a composite
804 pseudo_member
= cls
._value
2member
_map
_.setdefault(value
, pseudo_member
)
807 def __or__(self
, other
):
808 if not isinstance(other
, (self
.__class
__, int)):
809 return NotImplemented
810 result
= self
.__class
__(self
._value
_ | self
.__class
__(other
)._value
_)
813 def __and__(self
, other
):
814 if not isinstance(other
, (self
.__class
__, int)):
815 return NotImplemented
816 return self
.__class
__(self
._value
_ & self
.__class
__(other
)._value
_)
818 def __xor__(self
, other
):
819 if not isinstance(other
, (self
.__class
__, int)):
820 return NotImplemented
821 return self
.__class
__(self
._value
_ ^ self
.__class
__(other
)._value
_)
827 def __invert__(self
):
828 result
= self
.__class
__(~self
._value
_)
832 def _high_bit(value
):
833 """returns index of highest bit, or -1 if value is zero or negative"""
834 return value
.bit_length() - 1
836 def unique(enumeration
):
837 """Class decorator for enumerations ensuring unique member values."""
839 for name
, member
in enumeration
.__members
__.items():
840 if name
!= member
.name
:
841 duplicates
.append((name
, member
.name
))
843 alias_details
= ', '.join(
844 ["%s -> %s" % (alias
, name
) for (alias
, name
) in duplicates
])
845 raise ValueError('duplicate values found in %r: %s' %
846 (enumeration
, alias_details
))
849 def _decompose(flag
, value
):
850 """Extract all members from the value."""
851 # _decompose is only called if the value is not named
854 # issue29167: wrap accesses to _value2member_map_ in a list to avoid race
855 # conditions between iterating over it and having more psuedo-
856 # members added to it
858 # only check for named flags
861 for v
, m
in list(flag
._value
2member
_map
_.items())
862 if m
.name
is not None
865 # check for named flags and powers-of-two flags
868 for v
, m
in list(flag
._value
2member
_map
_.items())
869 if m
.name
is not None or _power_of_two(v
)
872 for member
, member_value
in flags_to_check
:
873 if member_value
and member_value
& value
== member_value
:
874 members
.append(member
)
875 not_covered
&= ~member_value
876 if not members
and value
in flag
._value
2member
_map
_:
877 members
.append(flag
._value
2member
_map
_[value
])
878 members
.sort(key
=lambda m
: m
._value
_, reverse
=True)
879 if len(members
) > 1 and members
[0].value
== value
:
880 # we have the breakdown, don't need the value member itself
882 return members
, not_covered
884 def _power_of_two(value
):
887 return value
== 2 ** _high_bit(value
)