ยปCore Development>Code coverage>Lib/enum.py

Python code coverage for Lib/enum.py

#countcontent
1n/aimport sys
2n/afrom types import MappingProxyType, DynamicClassAttribute
3n/afrom functools import reduce
4n/afrom operator import or_ as _or_
5n/a
6n/a# try _collections first to reduce startup cost
7n/atry:
8n/a from _collections import OrderedDict
9n/aexcept ImportError:
10n/a from collections import OrderedDict
11n/a
12n/a
13n/a__all__ = [
14n/a 'EnumMeta',
15n/a 'Enum', 'IntEnum', 'Flag', 'IntFlag',
16n/a 'auto', 'unique',
17n/a ]
18n/a
19n/a
20n/adef _is_descriptor(obj):
21n/a """Returns True if obj is a descriptor, False otherwise."""
22n/a return (
23n/a hasattr(obj, '__get__') or
24n/a hasattr(obj, '__set__') or
25n/a hasattr(obj, '__delete__'))
26n/a
27n/a
28n/adef _is_dunder(name):
29n/a """Returns True if a __dunder__ name, False otherwise."""
30n/a return (name[:2] == name[-2:] == '__' and
31n/a name[2:3] != '_' and
32n/a name[-3:-2] != '_' and
33n/a len(name) > 4)
34n/a
35n/a
36n/adef _is_sunder(name):
37n/a """Returns True if a _sunder_ name, False otherwise."""
38n/a return (name[0] == name[-1] == '_' and
39n/a name[1:2] != '_' and
40n/a name[-2:-1] != '_' and
41n/a len(name) > 2)
42n/a
43n/adef _make_class_unpicklable(cls):
44n/a """Make the given class un-picklable."""
45n/a def _break_on_call_reduce(self, proto):
46n/a raise TypeError('%r cannot be pickled' % self)
47n/a cls.__reduce_ex__ = _break_on_call_reduce
48n/a cls.__module__ = '<unknown>'
49n/a
50n/a_auto_null = object()
51n/aclass auto:
52n/a """
53n/a Instances are replaced with an appropriate value in Enum class suites.
54n/a """
55n/a value = _auto_null
56n/a
57n/a
58n/aclass _EnumDict(dict):
59n/a """Track enum member order and ensure member names are not reused.
60n/a
61n/a EnumMeta will use the names found in self._member_names as the
62n/a enumeration member names.
63n/a
64n/a """
65n/a def __init__(self):
66n/a super().__init__()
67n/a self._member_names = []
68n/a self._last_values = []
69n/a
70n/a def __setitem__(self, key, value):
71n/a """Changes anything not dundered or not a descriptor.
72n/a
73n/a If an enum member name is used twice, an error is raised; duplicate
74n/a values are not checked for.
75n/a
76n/a Single underscore (sunder) names are reserved.
77n/a
78n/a """
79n/a if _is_sunder(key):
80n/a if key not in (
81n/a '_order_', '_create_pseudo_member_',
82n/a '_generate_next_value_', '_missing_',
83n/a ):
84n/a raise ValueError('_names_ are reserved for future Enum use')
85n/a if key == '_generate_next_value_':
86n/a setattr(self, '_generate_next_value', value)
87n/a elif _is_dunder(key):
88n/a if key == '__order__':
89n/a key = '_order_'
90n/a elif key in self._member_names:
91n/a # descriptor overwriting an enum?
92n/a raise TypeError('Attempted to reuse key: %r' % key)
93n/a elif not _is_descriptor(value):
94n/a if key in self:
95n/a # enum overwriting a descriptor?
96n/a raise TypeError('%r already defined as: %r' % (key, self[key]))
97n/a if isinstance(value, auto):
98n/a if value.value == _auto_null:
99n/a value.value = self._generate_next_value(key, 1, len(self._member_names), self._last_values[:])
100n/a value = value.value
101n/a self._member_names.append(key)
102n/a self._last_values.append(value)
103n/a super().__setitem__(key, value)
104n/a
105n/a
106n/a# Dummy value for Enum as EnumMeta explicitly checks for it, but of course
107n/a# until EnumMeta finishes running the first time the Enum class doesn't exist.
108n/a# This is also why there are checks in EnumMeta like `if Enum is not None`
109n/aEnum = None
110n/a
111n/a
112n/aclass EnumMeta(type):
113n/a """Metaclass for Enum"""
114n/a @classmethod
115n/a def __prepare__(metacls, cls, bases):
116n/a # create the namespace dict
117n/a enum_dict = _EnumDict()
118n/a # inherit previous flags and _generate_next_value_ function
119n/a member_type, first_enum = metacls._get_mixins_(bases)
120n/a if first_enum is not None:
121n/a enum_dict['_generate_next_value_'] = getattr(first_enum, '_generate_next_value_', None)
122n/a return enum_dict
123n/a
124n/a def __new__(metacls, cls, bases, classdict):
125n/a # an Enum class is final once enumeration items have been defined; it
126n/a # cannot be mixed with other types (int, float, etc.) if it has an
127n/a # inherited __new__ unless a new __new__ is defined (or the resulting
128n/a # class will fail).
129n/a member_type, first_enum = metacls._get_mixins_(bases)
130n/a __new__, save_new, use_args = metacls._find_new_(classdict, member_type,
131n/a first_enum)
132n/a
133n/a # save enum items into separate mapping so they don't get baked into
134n/a # the new class
135n/a enum_members = {k: classdict[k] for k in classdict._member_names}
136n/a for name in classdict._member_names:
137n/a del classdict[name]
138n/a
139n/a # adjust the sunders
140n/a _order_ = classdict.pop('_order_', None)
141n/a
142n/a # check for illegal enum names (any others?)
143n/a invalid_names = set(enum_members) & {'mro', }
144n/a if invalid_names:
145n/a raise ValueError('Invalid enum member name: {0}'.format(
146n/a ','.join(invalid_names)))
147n/a
148n/a # create a default docstring if one has not been provided
149n/a if '__doc__' not in classdict:
150n/a classdict['__doc__'] = 'An enumeration.'
151n/a
152n/a # create our new Enum type
153n/a enum_class = super().__new__(metacls, cls, bases, classdict)
154n/a enum_class._member_names_ = [] # names in definition order
155n/a enum_class._member_map_ = OrderedDict() # name->value map
156n/a enum_class._member_type_ = member_type
157n/a
158n/a # save attributes from super classes so we know if we can take
159n/a # the shortcut of storing members in the class dict
160n/a base_attributes = {a for b in enum_class.mro() for a in b.__dict__}
161n/a
162n/a # Reverse value->name map for hashable values.
163n/a enum_class._value2member_map_ = {}
164n/a
165n/a # If a custom type is mixed into the Enum, and it does not know how
166n/a # to pickle itself, pickle.dumps will succeed but pickle.loads will
167n/a # fail. Rather than have the error show up later and possibly far
168n/a # from the source, sabotage the pickle protocol for this class so
169n/a # that pickle.dumps also fails.
170n/a #
171n/a # However, if the new class implements its own __reduce_ex__, do not
172n/a # sabotage -- it's on them to make sure it works correctly. We use
173n/a # __reduce_ex__ instead of any of the others as it is preferred by
174n/a # pickle over __reduce__, and it handles all pickle protocols.
175n/a if '__reduce_ex__' not in classdict:
176n/a if member_type is not object:
177n/a methods = ('__getnewargs_ex__', '__getnewargs__',
178n/a '__reduce_ex__', '__reduce__')
179n/a if not any(m in member_type.__dict__ for m in methods):
180n/a _make_class_unpicklable(enum_class)
181n/a
182n/a # instantiate them, checking for duplicates as we go
183n/a # we instantiate first instead of checking for duplicates first in case
184n/a # a custom __new__ is doing something funky with the values -- such as
185n/a # auto-numbering ;)
186n/a for member_name in classdict._member_names:
187n/a value = enum_members[member_name]
188n/a if not isinstance(value, tuple):
189n/a args = (value, )
190n/a else:
191n/a args = value
192n/a if member_type is tuple: # special case for tuple enums
193n/a args = (args, ) # wrap it one more time
194n/a if not use_args:
195n/a enum_member = __new__(enum_class)
196n/a if not hasattr(enum_member, '_value_'):
197n/a enum_member._value_ = value
198n/a else:
199n/a enum_member = __new__(enum_class, *args)
200n/a if not hasattr(enum_member, '_value_'):
201n/a if member_type is object:
202n/a enum_member._value_ = value
203n/a else:
204n/a enum_member._value_ = member_type(*args)
205n/a value = enum_member._value_
206n/a enum_member._name_ = member_name
207n/a enum_member.__objclass__ = enum_class
208n/a enum_member.__init__(*args)
209n/a # If another member with the same value was already defined, the
210n/a # new member becomes an alias to the existing one.
211n/a for name, canonical_member in enum_class._member_map_.items():
212n/a if canonical_member._value_ == enum_member._value_:
213n/a enum_member = canonical_member
214n/a break
215n/a else:
216n/a # Aliases don't appear in member names (only in __members__).
217n/a enum_class._member_names_.append(member_name)
218n/a # performance boost for any member that would not shadow
219n/a # a DynamicClassAttribute
220n/a if member_name not in base_attributes:
221n/a setattr(enum_class, member_name, enum_member)
222n/a # now add to _member_map_
223n/a enum_class._member_map_[member_name] = enum_member
224n/a try:
225n/a # This may fail if value is not hashable. We can't add the value
226n/a # to the map, and by-value lookups for this value will be
227n/a # linear.
228n/a enum_class._value2member_map_[value] = enum_member
229n/a except TypeError:
230n/a pass
231n/a
232n/a # double check that repr and friends are not the mixin's or various
233n/a # things break (such as pickle)
234n/a for name in ('__repr__', '__str__', '__format__', '__reduce_ex__'):
235n/a class_method = getattr(enum_class, name)
236n/a obj_method = getattr(member_type, name, None)
237n/a enum_method = getattr(first_enum, name, None)
238n/a if obj_method is not None and obj_method is class_method:
239n/a setattr(enum_class, name, enum_method)
240n/a
241n/a # replace any other __new__ with our own (as long as Enum is not None,
242n/a # anyway) -- again, this is to support pickle
243n/a if Enum is not None:
244n/a # if the user defined their own __new__, save it before it gets
245n/a # clobbered in case they subclass later
246n/a if save_new:
247n/a enum_class.__new_member__ = __new__
248n/a enum_class.__new__ = Enum.__new__
249n/a
250n/a # py3 support for definition order (helps keep py2/py3 code in sync)
251n/a if _order_ is not None:
252n/a if isinstance(_order_, str):
253n/a _order_ = _order_.replace(',', ' ').split()
254n/a if _order_ != enum_class._member_names_:
255n/a raise TypeError('member order does not match _order_')
256n/a
257n/a return enum_class
258n/a
259n/a def __bool__(self):
260n/a """
261n/a classes/types should always be True.
262n/a """
263n/a return True
264n/a
265n/a def __call__(cls, value, names=None, *, module=None, qualname=None, type=None, start=1):
266n/a """Either returns an existing member, or creates a new enum class.
267n/a
268n/a This method is used both when an enum class is given a value to match
269n/a to an enumeration member (i.e. Color(3)) and for the functional API
270n/a (i.e. Color = Enum('Color', names='RED GREEN BLUE')).
271n/a
272n/a When used for the functional API:
273n/a
274n/a `value` will be the name of the new class.
275n/a
276n/a `names` should be either a string of white-space/comma delimited names
277n/a (values will start at `start`), or an iterator/mapping of name, value pairs.
278n/a
279n/a `module` should be set to the module this class is being created in;
280n/a if it is not set, an attempt to find that module will be made, but if
281n/a it fails the class will not be picklable.
282n/a
283n/a `qualname` should be set to the actual location this class can be found
284n/a at in its module; by default it is set to the global scope. If this is
285n/a not correct, unpickling will fail in some circumstances.
286n/a
287n/a `type`, if set, will be mixed in as the first base class.
288n/a
289n/a """
290n/a if names is None: # simple value lookup
291n/a return cls.__new__(cls, value)
292n/a # otherwise, functional API: we're creating a new Enum type
293n/a return cls._create_(value, names, module=module, qualname=qualname, type=type, start=start)
294n/a
295n/a def __contains__(cls, member):
296n/a return isinstance(member, cls) and member._name_ in cls._member_map_
297n/a
298n/a def __delattr__(cls, attr):
299n/a # nicer error message when someone tries to delete an attribute
300n/a # (see issue19025).
301n/a if attr in cls._member_map_:
302n/a raise AttributeError(
303n/a "%s: cannot delete Enum member." % cls.__name__)
304n/a super().__delattr__(attr)
305n/a
306n/a def __dir__(self):
307n/a return (['__class__', '__doc__', '__members__', '__module__'] +
308n/a self._member_names_)
309n/a
310n/a def __getattr__(cls, name):
311n/a """Return the enum member matching `name`
312n/a
313n/a We use __getattr__ instead of descriptors or inserting into the enum
314n/a class' __dict__ in order to support `name` and `value` being both
315n/a properties for enum members (which live in the class' __dict__) and
316n/a enum members themselves.
317n/a
318n/a """
319n/a if _is_dunder(name):
320n/a raise AttributeError(name)
321n/a try:
322n/a return cls._member_map_[name]
323n/a except KeyError:
324n/a raise AttributeError(name) from None
325n/a
326n/a def __getitem__(cls, name):
327n/a return cls._member_map_[name]
328n/a
329n/a def __iter__(cls):
330n/a return (cls._member_map_[name] for name in cls._member_names_)
331n/a
332n/a def __len__(cls):
333n/a return len(cls._member_names_)
334n/a
335n/a @property
336n/a def __members__(cls):
337n/a """Returns a mapping of member name->value.
338n/a
339n/a This mapping lists all enum members, including aliases. Note that this
340n/a is a read-only view of the internal mapping.
341n/a
342n/a """
343n/a return MappingProxyType(cls._member_map_)
344n/a
345n/a def __repr__(cls):
346n/a return "<enum %r>" % cls.__name__
347n/a
348n/a def __reversed__(cls):
349n/a return (cls._member_map_[name] for name in reversed(cls._member_names_))
350n/a
351n/a def __setattr__(cls, name, value):
352n/a """Block attempts to reassign Enum members.
353n/a
354n/a A simple assignment to the class namespace only changes one of the
355n/a several possible ways to get an Enum member from the Enum class,
356n/a resulting in an inconsistent Enumeration.
357n/a
358n/a """
359n/a member_map = cls.__dict__.get('_member_map_', {})
360n/a if name in member_map:
361n/a raise AttributeError('Cannot reassign members.')
362n/a super().__setattr__(name, value)
363n/a
364n/a def _create_(cls, class_name, names=None, *, module=None, qualname=None, type=None, start=1):
365n/a """Convenience method to create a new Enum class.
366n/a
367n/a `names` can be:
368n/a
369n/a * A string containing member names, separated either with spaces or
370n/a commas. Values are incremented by 1 from `start`.
371n/a * An iterable of member names. Values are incremented by 1 from `start`.
372n/a * An iterable of (member name, value) pairs.
373n/a * A mapping of member name -> value pairs.
374n/a
375n/a """
376n/a metacls = cls.__class__
377n/a bases = (cls, ) if type is None else (type, cls)
378n/a _, first_enum = cls._get_mixins_(bases)
379n/a classdict = metacls.__prepare__(class_name, bases)
380n/a
381n/a # special processing needed for names?
382n/a if isinstance(names, str):
383n/a names = names.replace(',', ' ').split()
384n/a if isinstance(names, (tuple, list)) and isinstance(names[0], str):
385n/a original_names, names = names, []
386n/a last_values = []
387n/a for count, name in enumerate(original_names):
388n/a value = first_enum._generate_next_value_(name, start, count, last_values[:])
389n/a last_values.append(value)
390n/a names.append((name, value))
391n/a
392n/a # Here, names is either an iterable of (name, value) or a mapping.
393n/a for item in names:
394n/a if isinstance(item, str):
395n/a member_name, member_value = item, names[item]
396n/a else:
397n/a member_name, member_value = item
398n/a classdict[member_name] = member_value
399n/a enum_class = metacls.__new__(metacls, class_name, bases, classdict)
400n/a
401n/a # TODO: replace the frame hack if a blessed way to know the calling
402n/a # module is ever developed
403n/a if module is None:
404n/a try:
405n/a module = sys._getframe(2).f_globals['__name__']
406n/a except (AttributeError, ValueError) as exc:
407n/a pass
408n/a if module is None:
409n/a _make_class_unpicklable(enum_class)
410n/a else:
411n/a enum_class.__module__ = module
412n/a if qualname is not None:
413n/a enum_class.__qualname__ = qualname
414n/a
415n/a return enum_class
416n/a
417n/a @staticmethod
418n/a def _get_mixins_(bases):
419n/a """Returns the type for creating enum members, and the first inherited
420n/a enum class.
421n/a
422n/a bases: the tuple of bases that was given to __new__
423n/a
424n/a """
425n/a if not bases:
426n/a return object, Enum
427n/a
428n/a # double check that we are not subclassing a class with existing
429n/a # enumeration members; while we're at it, see if any other data
430n/a # type has been mixed in so we can use the correct __new__
431n/a member_type = first_enum = None
432n/a for base in bases:
433n/a if (base is not Enum and
434n/a issubclass(base, Enum) and
435n/a base._member_names_):
436n/a raise TypeError("Cannot extend enumerations")
437n/a # base is now the last base in bases
438n/a if not issubclass(base, Enum):
439n/a raise TypeError("new enumerations must be created as "
440n/a "`ClassName([mixin_type,] enum_type)`")
441n/a
442n/a # get correct mix-in type (either mix-in type of Enum subclass, or
443n/a # first base if last base is Enum)
444n/a if not issubclass(bases[0], Enum):
445n/a member_type = bases[0] # first data type
446n/a first_enum = bases[-1] # enum type
447n/a else:
448n/a for base in bases[0].__mro__:
449n/a # most common: (IntEnum, int, Enum, object)
450n/a # possible: (<Enum 'AutoIntEnum'>, <Enum 'IntEnum'>,
451n/a # <class 'int'>, <Enum 'Enum'>,
452n/a # <class 'object'>)
453n/a if issubclass(base, Enum):
454n/a if first_enum is None:
455n/a first_enum = base
456n/a else:
457n/a if member_type is None:
458n/a member_type = base
459n/a
460n/a return member_type, first_enum
461n/a
462n/a @staticmethod
463n/a def _find_new_(classdict, member_type, first_enum):
464n/a """Returns the __new__ to be used for creating the enum members.
465n/a
466n/a classdict: the class dictionary given to __new__
467n/a member_type: the data type whose __new__ will be used by default
468n/a first_enum: enumeration to check for an overriding __new__
469n/a
470n/a """
471n/a # now find the correct __new__, checking to see of one was defined
472n/a # by the user; also check earlier enum classes in case a __new__ was
473n/a # saved as __new_member__
474n/a __new__ = classdict.get('__new__', None)
475n/a
476n/a # should __new__ be saved as __new_member__ later?
477n/a save_new = __new__ is not None
478n/a
479n/a if __new__ is None:
480n/a # check all possibles for __new_member__ before falling back to
481n/a # __new__
482n/a for method in ('__new_member__', '__new__'):
483n/a for possible in (member_type, first_enum):
484n/a target = getattr(possible, method, None)
485n/a if target not in {
486n/a None,
487n/a None.__new__,
488n/a object.__new__,
489n/a Enum.__new__,
490n/a }:
491n/a __new__ = target
492n/a break
493n/a if __new__ is not None:
494n/a break
495n/a else:
496n/a __new__ = object.__new__
497n/a
498n/a # if a non-object.__new__ is used then whatever value/tuple was
499n/a # assigned to the enum member name will be passed to __new__ and to the
500n/a # new enum member's __init__
501n/a if __new__ is object.__new__:
502n/a use_args = False
503n/a else:
504n/a use_args = True
505n/a
506n/a return __new__, save_new, use_args
507n/a
508n/a
509n/aclass Enum(metaclass=EnumMeta):
510n/a """Generic enumeration.
511n/a
512n/a Derive from this class to define new enumerations.
513n/a
514n/a """
515n/a def __new__(cls, value):
516n/a # all enum instances are actually created during class construction
517n/a # without calling this method; this method is called by the metaclass'
518n/a # __call__ (i.e. Color(3) ), and by pickle
519n/a if type(value) is cls:
520n/a # For lookups like Color(Color.RED)
521n/a return value
522n/a # by-value search for a matching enum member
523n/a # see if it's in the reverse mapping (for hashable values)
524n/a try:
525n/a if value in cls._value2member_map_:
526n/a return cls._value2member_map_[value]
527n/a except TypeError:
528n/a # not there, now do long search -- O(n) behavior
529n/a for member in cls._member_map_.values():
530n/a if member._value_ == value:
531n/a return member
532n/a # still not found -- try _missing_ hook
533n/a return cls._missing_(value)
534n/a
535n/a def _generate_next_value_(name, start, count, last_values):
536n/a for last_value in reversed(last_values):
537n/a try:
538n/a return last_value + 1
539n/a except TypeError:
540n/a pass
541n/a else:
542n/a return start
543n/a
544n/a @classmethod
545n/a def _missing_(cls, value):
546n/a raise ValueError("%r is not a valid %s" % (value, cls.__name__))
547n/a
548n/a def __repr__(self):
549n/a return "<%s.%s: %r>" % (
550n/a self.__class__.__name__, self._name_, self._value_)
551n/a
552n/a def __str__(self):
553n/a return "%s.%s" % (self.__class__.__name__, self._name_)
554n/a
555n/a def __dir__(self):
556n/a added_behavior = [
557n/a m
558n/a for cls in self.__class__.mro()
559n/a for m in cls.__dict__
560n/a if m[0] != '_' and m not in self._member_map_
561n/a ]
562n/a return (['__class__', '__doc__', '__module__'] + added_behavior)
563n/a
564n/a def __format__(self, format_spec):
565n/a # mixed-in Enums should use the mixed-in type's __format__, otherwise
566n/a # we can get strange results with the Enum name showing up instead of
567n/a # the value
568n/a
569n/a # pure Enum branch
570n/a if self._member_type_ is object:
571n/a cls = str
572n/a val = str(self)
573n/a # mix-in branch
574n/a else:
575n/a cls = self._member_type_
576n/a val = self._value_
577n/a return cls.__format__(val, format_spec)
578n/a
579n/a def __hash__(self):
580n/a return hash(self._name_)
581n/a
582n/a def __reduce_ex__(self, proto):
583n/a return self.__class__, (self._value_, )
584n/a
585n/a # DynamicClassAttribute is used to provide access to the `name` and
586n/a # `value` properties of enum members while keeping some measure of
587n/a # protection from modification, while still allowing for an enumeration
588n/a # to have members named `name` and `value`. This works because enumeration
589n/a # members are not set directly on the enum class -- __getattr__ is
590n/a # used to look them up.
591n/a
592n/a @DynamicClassAttribute
593n/a def name(self):
594n/a """The name of the Enum member."""
595n/a return self._name_
596n/a
597n/a @DynamicClassAttribute
598n/a def value(self):
599n/a """The value of the Enum member."""
600n/a return self._value_
601n/a
602n/a @classmethod
603n/a def _convert(cls, name, module, filter, source=None):
604n/a """
605n/a Create a new Enum subclass that replaces a collection of global constants
606n/a """
607n/a # convert all constants from source (or module) that pass filter() to
608n/a # a new Enum called name, and export the enum and its members back to
609n/a # module;
610n/a # also, replace the __reduce_ex__ method so unpickling works in
611n/a # previous Python versions
612n/a module_globals = vars(sys.modules[module])
613n/a if source:
614n/a source = vars(source)
615n/a else:
616n/a source = module_globals
617n/a # We use an OrderedDict of sorted source keys so that the
618n/a # _value2member_map is populated in the same order every time
619n/a # for a consistent reverse mapping of number to name when there
620n/a # are multiple names for the same number rather than varying
621n/a # between runs due to hash randomization of the module dictionary.
622n/a members = [
623n/a (name, source[name])
624n/a for name in source.keys()
625n/a if filter(name)]
626n/a try:
627n/a # sort by value
628n/a members.sort(key=lambda t: (t[1], t[0]))
629n/a except TypeError:
630n/a # unless some values aren't comparable, in which case sort by name
631n/a members.sort(key=lambda t: t[0])
632n/a cls = cls(name, members, module=module)
633n/a cls.__reduce_ex__ = _reduce_ex_by_name
634n/a module_globals.update(cls.__members__)
635n/a module_globals[name] = cls
636n/a return cls
637n/a
638n/a
639n/aclass IntEnum(int, Enum):
640n/a """Enum where members are also (and must be) ints"""
641n/a
642n/a
643n/adef _reduce_ex_by_name(self, proto):
644n/a return self.name
645n/a
646n/aclass Flag(Enum):
647n/a """Support for flags"""
648n/a
649n/a def _generate_next_value_(name, start, count, last_values):
650n/a """
651n/a Generate the next value when not given.
652n/a
653n/a name: the name of the member
654n/a start: the initital start value or None
655n/a count: the number of existing members
656n/a last_value: the last value assigned or None
657n/a """
658n/a if not count:
659n/a return start if start is not None else 1
660n/a for last_value in reversed(last_values):
661n/a try:
662n/a high_bit = _high_bit(last_value)
663n/a break
664n/a except Exception:
665n/a raise TypeError('Invalid Flag value: %r' % last_value) from None
666n/a return 2 ** (high_bit+1)
667n/a
668n/a @classmethod
669n/a def _missing_(cls, value):
670n/a original_value = value
671n/a if value < 0:
672n/a value = ~value
673n/a possible_member = cls._create_pseudo_member_(value)
674n/a if original_value < 0:
675n/a possible_member = ~possible_member
676n/a return possible_member
677n/a
678n/a @classmethod
679n/a def _create_pseudo_member_(cls, value):
680n/a """
681n/a Create a composite member iff value contains only members.
682n/a """
683n/a pseudo_member = cls._value2member_map_.get(value, None)
684n/a if pseudo_member is None:
685n/a # verify all bits are accounted for
686n/a _, extra_flags = _decompose(cls, value)
687n/a if extra_flags:
688n/a raise ValueError("%r is not a valid %s" % (value, cls.__name__))
689n/a # construct a singleton enum pseudo-member
690n/a pseudo_member = object.__new__(cls)
691n/a pseudo_member._name_ = None
692n/a pseudo_member._value_ = value
693n/a # use setdefault in case another thread already created a composite
694n/a # with this value
695n/a pseudo_member = cls._value2member_map_.setdefault(value, pseudo_member)
696n/a return pseudo_member
697n/a
698n/a def __contains__(self, other):
699n/a if not isinstance(other, self.__class__):
700n/a return NotImplemented
701n/a return other._value_ & self._value_ == other._value_
702n/a
703n/a def __repr__(self):
704n/a cls = self.__class__
705n/a if self._name_ is not None:
706n/a return '<%s.%s: %r>' % (cls.__name__, self._name_, self._value_)
707n/a members, uncovered = _decompose(cls, self._value_)
708n/a return '<%s.%s: %r>' % (
709n/a cls.__name__,
710n/a '|'.join([str(m._name_ or m._value_) for m in members]),
711n/a self._value_,
712n/a )
713n/a
714n/a def __str__(self):
715n/a cls = self.__class__
716n/a if self._name_ is not None:
717n/a return '%s.%s' % (cls.__name__, self._name_)
718n/a members, uncovered = _decompose(cls, self._value_)
719n/a if len(members) == 1 and members[0]._name_ is None:
720n/a return '%s.%r' % (cls.__name__, members[0]._value_)
721n/a else:
722n/a return '%s.%s' % (
723n/a cls.__name__,
724n/a '|'.join([str(m._name_ or m._value_) for m in members]),
725n/a )
726n/a
727n/a def __bool__(self):
728n/a return bool(self._value_)
729n/a
730n/a def __or__(self, other):
731n/a if not isinstance(other, self.__class__):
732n/a return NotImplemented
733n/a return self.__class__(self._value_ | other._value_)
734n/a
735n/a def __and__(self, other):
736n/a if not isinstance(other, self.__class__):
737n/a return NotImplemented
738n/a return self.__class__(self._value_ & other._value_)
739n/a
740n/a def __xor__(self, other):
741n/a if not isinstance(other, self.__class__):
742n/a return NotImplemented
743n/a return self.__class__(self._value_ ^ other._value_)
744n/a
745n/a def __invert__(self):
746n/a members, uncovered = _decompose(self.__class__, self._value_)
747n/a inverted_members = [
748n/a m for m in self.__class__
749n/a if m not in members and not m._value_ & self._value_
750n/a ]
751n/a inverted = reduce(_or_, inverted_members, self.__class__(0))
752n/a return self.__class__(inverted)
753n/a
754n/a
755n/aclass IntFlag(int, Flag):
756n/a """Support for integer-based Flags"""
757n/a
758n/a @classmethod
759n/a def _missing_(cls, value):
760n/a if not isinstance(value, int):
761n/a raise ValueError("%r is not a valid %s" % (value, cls.__name__))
762n/a new_member = cls._create_pseudo_member_(value)
763n/a return new_member
764n/a
765n/a @classmethod
766n/a def _create_pseudo_member_(cls, value):
767n/a pseudo_member = cls._value2member_map_.get(value, None)
768n/a if pseudo_member is None:
769n/a need_to_create = [value]
770n/a # get unaccounted for bits
771n/a _, extra_flags = _decompose(cls, value)
772n/a # timer = 10
773n/a while extra_flags:
774n/a # timer -= 1
775n/a bit = _high_bit(extra_flags)
776n/a flag_value = 2 ** bit
777n/a if (flag_value not in cls._value2member_map_ and
778n/a flag_value not in need_to_create
779n/a ):
780n/a need_to_create.append(flag_value)
781n/a if extra_flags == -flag_value:
782n/a extra_flags = 0
783n/a else:
784n/a extra_flags ^= flag_value
785n/a for value in reversed(need_to_create):
786n/a # construct singleton pseudo-members
787n/a pseudo_member = int.__new__(cls, value)
788n/a pseudo_member._name_ = None
789n/a pseudo_member._value_ = value
790n/a # use setdefault in case another thread already created a composite
791n/a # with this value
792n/a pseudo_member = cls._value2member_map_.setdefault(value, pseudo_member)
793n/a return pseudo_member
794n/a
795n/a def __or__(self, other):
796n/a if not isinstance(other, (self.__class__, int)):
797n/a return NotImplemented
798n/a result = self.__class__(self._value_ | self.__class__(other)._value_)
799n/a return result
800n/a
801n/a def __and__(self, other):
802n/a if not isinstance(other, (self.__class__, int)):
803n/a return NotImplemented
804n/a return self.__class__(self._value_ & self.__class__(other)._value_)
805n/a
806n/a def __xor__(self, other):
807n/a if not isinstance(other, (self.__class__, int)):
808n/a return NotImplemented
809n/a return self.__class__(self._value_ ^ self.__class__(other)._value_)
810n/a
811n/a __ror__ = __or__
812n/a __rand__ = __and__
813n/a __rxor__ = __xor__
814n/a
815n/a def __invert__(self):
816n/a result = self.__class__(~self._value_)
817n/a return result
818n/a
819n/a
820n/adef _high_bit(value):
821n/a """returns index of highest bit, or -1 if value is zero or negative"""
822n/a return value.bit_length() - 1
823n/a
824n/adef unique(enumeration):
825n/a """Class decorator for enumerations ensuring unique member values."""
826n/a duplicates = []
827n/a for name, member in enumeration.__members__.items():
828n/a if name != member.name:
829n/a duplicates.append((name, member.name))
830n/a if duplicates:
831n/a alias_details = ', '.join(
832n/a ["%s -> %s" % (alias, name) for (alias, name) in duplicates])
833n/a raise ValueError('duplicate values found in %r: %s' %
834n/a (enumeration, alias_details))
835n/a return enumeration
836n/a
837n/adef _decompose(flag, value):
838n/a """Extract all members from the value."""
839n/a # _decompose is only called if the value is not named
840n/a not_covered = value
841n/a negative = value < 0
842n/a # issue29167: wrap accesses to _value2member_map_ in a list to avoid race
843n/a # conditions between iterating over it and having more psuedo-
844n/a # members added to it
845n/a if negative:
846n/a # only check for named flags
847n/a flags_to_check = [
848n/a (m, v)
849n/a for v, m in list(flag._value2member_map_.items())
850n/a if m.name is not None
851n/a ]
852n/a else:
853n/a # check for named flags and powers-of-two flags
854n/a flags_to_check = [
855n/a (m, v)
856n/a for v, m in list(flag._value2member_map_.items())
857n/a if m.name is not None or _power_of_two(v)
858n/a ]
859n/a members = []
860n/a for member, member_value in flags_to_check:
861n/a if member_value and member_value & value == member_value:
862n/a members.append(member)
863n/a not_covered &= ~member_value
864n/a if not members and value in flag._value2member_map_:
865n/a members.append(flag._value2member_map_[value])
866n/a members.sort(key=lambda m: m._value_, reverse=True)
867n/a if len(members) > 1 and members[0].value == value:
868n/a # we have the breakdown, don't need the value member itself
869n/a members.pop(0)
870n/a return members, not_covered
871n/a
872n/adef _power_of_two(value):
873n/a if value < 1:
874n/a return False
875n/a return value == 2 ** _high_bit(value)