diff options
author | ThereforeGames <95403634+ThereforeGames@users.noreply.github.com> | 2022-12-11 23:06:22 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-12-11 23:06:22 +0000 |
commit | 9170224d230fb22387e955d0b40ceda116f688b6 (patch) | |
tree | bc8ce7cce49f40b433e90a0fe790eda1b70389f4 /venv/Lib/site-packages/aenum/__init__.py | |
parent | 2e8b5418e3cd4e9212f2fcdb36305d7a40f97916 (diff) | |
download | stable-diffusion-webui-gfx803-9170224d230fb22387e955d0b40ceda116f688b6.tar.gz stable-diffusion-webui-gfx803-9170224d230fb22387e955d0b40ceda116f688b6.tar.bz2 stable-diffusion-webui-gfx803-9170224d230fb22387e955d0b40ceda116f688b6.zip |
Delete venv/Lib/site-packages directory
Diffstat (limited to 'venv/Lib/site-packages/aenum/__init__.py')
-rw-r--r-- | venv/Lib/site-packages/aenum/__init__.py | 4111 |
1 files changed, 0 insertions, 4111 deletions
diff --git a/venv/Lib/site-packages/aenum/__init__.py b/venv/Lib/site-packages/aenum/__init__.py deleted file mode 100644 index 26c504cc..00000000 --- a/venv/Lib/site-packages/aenum/__init__.py +++ /dev/null @@ -1,4111 +0,0 @@ -"""Python Advanced Enumerations & NameTuples""" -from __future__ import print_function - -# imports -import sys as _sys -pyver = _sys.version_info[:2] -PY2 = pyver < (3, ) -PY3 = pyver >= (3, ) -PY2_6 = (2, 6) -PY3_3 = (3, 3) -PY3_4 = (3, 4) -PY3_5 = (3, 5) -PY3_6 = (3, 6) -PY3_11 = (3, 11) - -import re - -_bltin_property = property -_bltin_bin = bin - -try: - from collections import OrderedDict -except ImportError: - OrderedDict = dict -from collections import defaultdict -try: - import sqlite3 -except ImportError: - sqlite3 = None - -try: - RecursionError -except NameError: - # python3.4 - RecursionError = RuntimeError - -from operator import or_ as _or_, and_ as _and_, xor as _xor_, inv as _inv_ -from operator import abs as _abs_, add as _add_, floordiv as _floordiv_ -from operator import lshift as _lshift_, rshift as _rshift_, mod as _mod_ -from operator import mul as _mul_, neg as _neg_, pos as _pos_, pow as _pow_ -from operator import truediv as _truediv_, sub as _sub_ - -if PY2: - from ._py2 import * -if PY3: - from ._py3 import * - -obj_type = type - -__all__ = [ - 'NamedConstant', 'constant', 'skip', 'nonmember', 'member', 'no_arg', - 'Enum', 'IntEnum', 'AutoNumberEnum', 'OrderedEnum', 'UniqueEnum', - 'StrEnum', 'UpperStrEnum', 'LowerStrEnum', - 'Flag', 'IntFlag', - 'AddValue', 'MagicValue', 'MultiValue', 'NoAlias', 'Unique', - 'AddValueEnum', 'MultiValueEnum', 'NoAliasEnum', - 'enum', 'extend_enum', 'unique', 'property', - 'NamedTuple', 'SqliteEnum', - 'FlagBoundary', 'STRICT', 'CONFORM', 'EJECT', 'KEEP', - 'add_stdlib_integration', 'remove_stdlib_integration' - ] - -if sqlite3 is None: - __all__.remove('SqliteEnum') - -version = 3, 1, 12, 1 - -# shims -try: - any -except NameError: - def any(iterable): - for element in iterable: - if element: - return True - return False - -try: - unicode - unicode = unicode -except NameError: - # In Python 3 unicode no longer exists (it's just str) - unicode = str - -try: - basestring - basestring = bytes, unicode -except NameError: - # In Python 2 basestring is the ancestor of both str and unicode - # in Python 3 it's just str, but was missing in 3.1 - basestring = str, - -try: - long - baseinteger = int, long -except NameError: - baseinteger = int, - long = int -# deprecated -baseint = baseinteger - -try: - NoneType -except NameError: - NoneType = type(None) - -try: - # derive from stdlib enum if possible - import enum - if hasattr(enum, 'version'): - raise ImportError('wrong version') - else: - from enum import EnumMeta as StdlibEnumMeta, Enum as StdlibEnum, IntEnum as StdlibIntEnum - StdlibFlag = StdlibIntFlag = StdlibStrEnum = StdlibReprEnum = None -except ImportError: - StdlibEnumMeta = StdlibEnum = StdlibIntEnum = StdlibIntFlag = StdlibFlag = StdlibStrEnum = None - -if StdlibEnum: - try: - from enum import IntFlag as StdlibIntFlag, Flag as StdlibFlag - except ImportError: - pass - try: - from enum import StrEnum as StdlibStrEnum - except ImportError: - pass - try: - from enum import ReprEnum as StdlibReprEnum - except ImportError: - pass - - - - -# helpers -# will be exported later -MagicValue = AddValue = MultiValue = NoAlias = Unique = None - -def _bit_count(num): - """ - return number of set bits - - Counting bits set, Brian Kernighan's way* - - unsigned int v; // count the number of bits set in v - unsigned int c; // c accumulates the total bits set in v - for (c = 0; v; c++) - { v &= v - 1; } //clear the least significant bit set - - This method goes through as many iterations as there are set bits. So if we - have a 32-bit word with only the high bit set, then it will only go once - through the loop. - - * The C Programming Language 2nd Ed., Kernighan & Ritchie, 1988. - - This works because each subtraction "borrows" from the lowest 1-bit. For - example: - - loop pass 1 loop pass 2 - ----------- ----------- - 101000 100000 - - 1 - 1 - = 100111 = 011111 - & 101000 & 100000 - = 100000 = 0 - - It is an excellent technique for Python, since the size of the integer need - not be determined beforehand. - - (from https://wiki.python.org/moin/BitManipulation) - """ - count = 0 - while num: - num &= num - 1 - count += 1 - return count - -def _is_single_bit(value): - """ - True if only one bit set in value (should be an int) - """ - if value == 0: - return False - value &= value - 1 - return value == 0 - -def _iter_bits_lsb(value): - """ - Return each bit value one at a time. - - >>> list(_iter_bits_lsb(6)) - [2, 4] - """ - - while value: - bit = value & (~value + 1) - yield bit - value ^= bit - -def bin(value, max_bits=None): - """ - Like built-in bin(), except negative values are represented in - twos-compliment, and the leading bit always indicates sign - (0=positive, 1=negative). - - >>> bin(10) - '0b0 1010' - >>> bin(~10) # ~10 is -11 - '0b1 0101' - """ - - ceiling = 2 ** (value).bit_length() - if value >= 0: - s = _bltin_bin(value + ceiling).replace('1', '0', 1) - else: - s = _bltin_bin(~value ^ (ceiling - 1) + ceiling) - sign = s[:3] - digits = s[3:] - if max_bits is not None: - if len(digits) < max_bits: - digits = (sign[-1] * max_bits + digits)[-max_bits:] - return "%s %s" % (sign, digits) - - -try: - from types import DynamicClassAttribute - base = DynamicClassAttribute -except ImportError: - base = object - DynamicClassAttribute = None - -class property(base): - """ - This is a descriptor, used to define attributes that act differently - when accessed through an enum member and through an enum class. - Instance access is the same as property(), but access to an attribute - through the enum class will look in the class' _member_map_. - """ - - # inherit from DynamicClassAttribute if we can in order to get `inspect` - # support - - def __init__(self, fget=None, fset=None, fdel=None, doc=None): - self.fget = fget - self.fset = fset - self.fdel = fdel - # next two lines make property act the same as _bltin_property - self.__doc__ = doc or fget.__doc__ - self.overwrite_doc = doc is None - # support for abstract methods - self.__isabstractmethod__ = bool(getattr(fget, '__isabstractmethod__', False)) - # names, if possible - - def getter(self, fget): - fdoc = fget.__doc__ if self.overwrite_doc else None - result = type(self)(fget, self.fset, self.fdel, fdoc or self.__doc__) - result.overwrite_doc = self.__doc__ is None - return result - - def setter(self, fset): - fdoc = fget.__doc__ if self.overwrite_doc else None - result = type(self)(self.fget, fset, self.fdel, self.__doc__) - result.overwrite_doc = self.__doc__ is None - return result - - def deleter(self, fdel): - fdoc = fget.__doc__ if self.overwrite_doc else None - result = type(self)(self.fget, self.fset, fdel, self.__doc__) - result.overwrite_doc = self.__doc__ is None - return result - - def __repr__(self): - member = self.ownerclass._member_map_.get(self.name) - func = self.fget or self.fset or self.fdel - strings = [] - if member: - strings.append('%r' % member) - if func: - strings.append('function=%s' % func.__name__) - return 'property(%s)' % ', '.join(strings) - - def __get__(self, instance, ownerclass=None): - if instance is None: - try: - return ownerclass._member_map_[self.name] - except KeyError: - raise AttributeError( - '%r has no attribute %r' % (ownerclass, self.name) - ) - else: - if self.fget is not None: - return self.fget(instance) - else: - if self.fset is not None: - raise AttributeError( - 'cannot read attribute %r on %r' % (self.name, ownerclass) - ) - else: - try: - return instance.__dict__[self.name] - except KeyError: - raise AttributeError( - '%r member has no attribute %r' % (ownerclass, self.name) - ) - - def __set__(self, instance, value): - if self.fset is None: - if self.fget is not None: - raise AttributeError( - "cannot set attribute %r on <aenum %r>" % (self.name, self.clsname) - ) - else: - instance.__dict__[self.name] = value - else: - return self.fset(instance, value) - - def __delete__(self, instance): - if self.fdel is None: - if self.fget or self.fset: - raise AttributeError( - "cannot delete attribute %r on <aenum %r>" % (self.name, self.clsname) - ) - elif self.name in instance.__dict__: - del instance.__dict__[self.name] - else: - raise AttributeError( - "no attribute %r on <aenum %r> member" % (self.name, self.clsname) - ) - else: - return self.fdel(instance) - - def __set_name__(self, ownerclass, name): - self.name = name - self.clsname = ownerclass.__name__ - self.ownerclass = ownerclass - -_RouteClassAttributeToGetattr = property -if DynamicClassAttribute is None: - DynamicClassAttribute = property -# deprecated -enum_property = property - -class NonMember(object): - """ - Protects item from becaming an Enum member during class creation. - """ - def __init__(self, value): - self.value = value - - def __get__(self, instance, ownerclass=None): - return self.value -skip = nonmember = NonMember - -class Member(object): - """ - Forces item to became an Enum member during class creation. - """ - def __init__(self, value): - self.value = value -member = Member - -class SentinelType(type): - def __repr__(cls): - return '<%s>' % cls.__name__ -Sentinel = SentinelType('Sentinel', (object, ), {}) - -def _is_descriptor(obj): - """Returns True if obj is a descriptor, False otherwise.""" - return ( - hasattr(obj, '__get__') or - hasattr(obj, '__set__') or - hasattr(obj, '__delete__')) - - -def _is_dunder(name): - """Returns True if a __dunder__ name, False otherwise.""" - return (len(name) > 4 and - name[:2] == name[-2:] == '__' and - name[2] != '_' and - name[-3] != '_') - - -def _is_sunder(name): - """Returns True if a _sunder_ name, False otherwise.""" - return (len(name) > 2 and - name[0] == name[-1] == '_' and - name[1] != '_' and - name[-2] != '_') - -def _is_internal_class(cls_name, obj): - # only 3.3 and up, always return False in 3.2 and below - if pyver < PY3_3: - return False - else: - qualname = getattr(obj, '__qualname__', False) - return not _is_descriptor(obj) and qualname and re.search(r"\.?%s\.\w+$" % cls_name, qualname) - -def _is_private_name(cls_name, name): - pattern = r'^_%s__\w+[^_]_?$' % (cls_name, ) - return re.search(pattern, name) - -def _power_of_two(value): - if value < 1: - return False - return value == 2 ** _high_bit(value) - -def bits(num): - if num in (0, 1): - return str(num) - negative = False - if num < 0: - negative = True - num = ~num - result = bits(num>>1) + str(num&1) - if negative: - result = '1' + ''.join(['10'[d=='1'] for d in result]) - return result - - -def bit_count(num): - """ - return number of set bits - - Counting bits set, Brian Kernighan's way* - - unsigned int v; // count the number of bits set in v - unsigned int c; // c accumulates the total bits set in v - for (c = 0; v; c++) - { v &= v - 1; } //clear the least significant bit set - - This method goes through as many iterations as there are set bits. So if we - have a 32-bit word with only the high bit set, then it will only go once - through the loop. - - * The C Programming Language 2nd Ed., Kernighan & Ritchie, 1988. - - This works because each subtraction "borrows" from the lowest 1-bit. For example: - - loop pass 1 loop pass 2 - ----------- ----------- - 101000 100000 - - 1 - 1 - = 100111 = 011111 - & 101000 & 100000 - = 100000 = 0 - - It is an excellent technique for Python, since the size of the integer need not - be determined beforehand. - """ - count = 0 - while(num): - num &= num - 1 - count += 1 - return(count) - -def bit_len(num): - length = 0 - while num: - length += 1 - num >>= 1 - return length - -def is_single_bit(num): - """ - True if only one bit set in num (should be an int) - """ - num &= num - 1 - return num == 0 - -def _make_class_unpicklable(obj): - """ - Make the given obj un-picklable. - - obj should be either a dictionary, on an Enum - """ - def _break_on_call_reduce(self, proto): - raise TypeError('%r cannot be pickled' % self) - if isinstance(obj, dict): - obj['__reduce_ex__'] = _break_on_call_reduce - obj['__module__'] = '<unknown>' - else: - setattr(obj, '__reduce_ex__', _break_on_call_reduce) - setattr(obj, '__module__', '<unknown>') - -def _check_auto_args(method): - """check if new generate method supports *args and **kwds""" - if isinstance(method, staticmethod): - method = method.__get__(type) - method = getattr(method, 'im_func', method) - args, varargs, keywords, defaults = getargspec(method) - return varargs is not None and keywords is not None - -def _get_attr_from_chain(cls, attr): - sentinel = object() - for basecls in cls.mro(): - obj = basecls.__dict__.get(attr, sentinel) - if obj is not sentinel: - return obj - -def _value(obj): - if isinstance(obj, (auto, constant)): - return obj.value - else: - return obj - -def enumsort(things): - """ - sorts things by value if all same type; otherwise by name - """ - if not things: - return things - sort_type = type(things[0]) - if not issubclass(sort_type, tuple): - # direct sort or type error - if not all((type(v) is sort_type) for v in things[1:]): - raise TypeError('cannot sort items of different types') - return sorted(things) - else: - # expecting list of (name, value) tuples - sort_type = type(things[0][1]) - try: - if all((type(v[1]) is sort_type) for v in things[1:]): - return sorted(things, key=lambda i: i[1]) - else: - raise TypeError('try name sort instead') - except TypeError: - return sorted(things, key=lambda i: i[0]) - -def export(collection, namespace=None): - """ - export([collection,] namespace) -> Export members to target namespace. - - If collection is not given, act as a decorator. - """ - if namespace is None: - namespace = collection - def export_decorator(collection): - return export(collection, namespace) - return export_decorator - elif issubclass(collection, NamedConstant): - for n, c in collection.__dict__.items(): - if isinstance(c, NamedConstant): - namespace[n] = c - elif issubclass(collection, Enum): - data = collection.__members__.items() - for n, m in data: - namespace[n] = m - else: - raise TypeError('%r is not a supported collection' % (collection,) ) - return collection - -class _Addendum(object): - def __init__(self, dict, doc, ns): - # dict is the dict to update with functions - # doc is the docstring to put in the dict - # ns is the namespace to remove the function names from - self.dict = dict - self.ns = ns - self.added = set() - def __call__(self, func): - if isinstance(func, (staticmethod, classmethod)): - name = func.__func__.__name__ - elif isinstance(func, (property, _bltin_property)): - name = (func.fget or func.fset or func.fdel).__name__ - else: - name = func.__name__ - self.dict[name] = func - self.added.add(name) - def resolve(self): - ns = self.ns - for name in self.added: - del ns[name] - return self.dict - -# Constant / NamedConstant - -class constant(object): - ''' - Simple constant descriptor for NamedConstant and Enum use. - ''' - def __init__(self, value, doc=None): - self.value = value - self.__doc__ = doc - - def __get__(self, *args): - return self.value - - def __repr__(self): - return '%s(%r)' % (self.__class__.__name__, self.value) - - def __and__(self, other): - return _and_(self.value, _value(other)) - - def __rand__(self, other): - return _and_(_value(other), self.value) - - def __invert__(self): - return _inv_(self.value) - - def __or__(self, other): - return _or_(self.value, _value(other)) - - def __ror__(self, other): - return _or_(_value(other), self.value) - - def __xor__(self, other): - return _xor_(self.value, _value(other)) - - def __rxor__(self, other): - return _xor_(_value(other), self.value) - - def __abs__(self): - return _abs_(self.value) - - def __add__(self, other): - return _add_(self.value, _value(other)) - - def __radd__(self, other): - return _add_(_value(other), self.value) - - def __neg__(self): - return _neg_(self.value) - - def __pos__(self): - return _pos_(self.value) - - if PY2: - def __div__(self, other): - return _div_(self.value, _value(other)) - - def __rdiv__(self, other): - return _div_(_value(other), (self.value)) - - def __floordiv__(self, other): - return _floordiv_(self.value, _value(other)) - - def __rfloordiv__(self, other): - return _floordiv_(_value(other), self.value) - - def __truediv__(self, other): - return _truediv_(self.value, _value(other)) - - def __rtruediv__(self, other): - return _truediv_(_value(other), self.value) - - def __lshift__(self, other): - return _lshift_(self.value, _value(other)) - - def __rlshift__(self, other): - return _lshift_(_value(other), self.value) - - def __rshift__(self, other): - return _rshift_(self.value, _value(other)) - - def __rrshift__(self, other): - return _rshift_(_value(other), self.value) - - def __mod__(self, other): - return _mod_(self.value, _value(other)) - - def __rmod__(self, other): - return _mod_(_value(other), self.value) - - def __mul__(self, other): - return _mul_(self.value, _value(other)) - - def __rmul__(self, other): - return _mul_(_value(other), self.value) - - def __pow__(self, other): - return _pow_(self.value, _value(other)) - - def __rpow__(self, other): - return _pow_(_value(other), self.value) - - def __sub__(self, other): - return _sub_(self.value, _value(other)) - - def __rsub__(self, other): - return _sub_(_value(other), self.value) - - def __set_name__(self, ownerclass, name): - self.name = name - self.clsname = ownerclass.__name__ - - -NamedConstant = None - -class _NamedConstantDict(dict): - """Track constant order and ensure names are not reused. - - NamedConstantMeta will use the names found in self._names as the - Constant names. - """ - def __init__(self): - super(_NamedConstantDict, self).__init__() - self._names = [] - - def __setitem__(self, key, value): - """Changes anything not dundered or not a constant descriptor. - - If an constant name is used twice, an error is raised; duplicate - values are not checked for. - - Single underscore (sunder) names are reserved. - """ - if _is_sunder(key): - raise ValueError( - '_sunder_ names, such as %r, are reserved for future NamedConstant use' - % (key, ) - ) - elif _is_dunder(key): - pass - elif key in self._names: - # overwriting an existing constant? - raise TypeError('attempt to reuse name: %r' % (key, )) - elif isinstance(value, constant) or not _is_descriptor(value): - if key in self: - # overwriting a descriptor? - raise TypeError('%s already defined as: %r' % (key, self[key])) - self._names.append(key) - super(_NamedConstantDict, self).__setitem__(key, value) - - -class NamedConstantMeta(type): - """ - Block attempts to reassign NamedConstant attributes. - """ - - @classmethod - def __prepare__(metacls, cls, bases, **kwds): - return _NamedConstantDict() - - def __new__(metacls, cls, bases, clsdict): - if type(clsdict) is dict: - original_dict = clsdict - clsdict = _NamedConstantDict() - for k, v in original_dict.items(): - clsdict[k] = v - newdict = {} - constants = {} - for name, obj in clsdict.items(): - if name in clsdict._names: - constants[name] = obj - continue - elif isinstance(obj, nonmember): - obj = obj.value - newdict[name] = obj - newcls = super(NamedConstantMeta, metacls).__new__(metacls, cls, bases, newdict) - newcls._named_constant_cache_ = {} - newcls._members_ = {} - for name, obj in constants.items(): - new_k = newcls.__new__(newcls, name, obj) - newcls._members_[name] = new_k - return newcls - - def __bool__(cls): - return True - - def __delattr__(cls, attr): - cur_obj = cls.__dict__.get(attr) - if NamedConstant is not None and isinstance(cur_obj, NamedConstant): - raise AttributeError('cannot delete constant <%s.%s>' % (cur_obj.__class__.__name__, cur_obj._name_)) - super(NamedConstantMeta, cls).__delattr__(attr) - - def __iter__(cls): - return (k for k in cls._members_.values()) - - def __reversed__(cls): - return (k for k in reversed(cls._members_.values())) - - def __len__(cls): - return len(cls._members_) - - __nonzero__ = __bool__ - - def __setattr__(cls, name, value): - """Block attempts to reassign NamedConstants. - """ - cur_obj = cls.__dict__.get(name) - if NamedConstant is not None and isinstance(cur_obj, NamedConstant): - raise AttributeError('cannot rebind constant <%s.%s>' % (cur_obj.__class__.__name__, cur_obj._name_)) - super(NamedConstantMeta, cls).__setattr__(name, value) - -constant_dict = _Addendum( - dict=NamedConstantMeta.__prepare__('NamedConstant', (object, )), - doc="NamedConstants protection.\n\n Derive from this class to lock NamedConstants.\n\n", - ns=globals(), - ) - -@constant_dict -def __new__(cls, name, value=None, doc=None): - if value is None: - # lookup, name is value - value = name - for name, obj in cls.__dict__.items(): - if isinstance(obj, cls) and obj._value_ == value: - return obj - else: - raise ValueError('%r does not exist in %r' % (value, cls.__name__)) - cur_obj = cls.__dict__.get(name) - if isinstance(cur_obj, NamedConstant): - raise AttributeError('cannot rebind constant <%s.%s>' % (cur_obj.__class__.__name__, cur_obj._name_)) - elif isinstance(value, constant): - doc = doc or value.__doc__ - value = value.value - metacls = cls.__class__ - if isinstance(value, NamedConstant): - # constants from other classes are reduced to their actual value - value = value._value_ - actual_type = type(value) - value_type = cls._named_constant_cache_.get(actual_type) - if value_type is None: - value_type = type(cls.__name__, (cls, type(value)), {}) - cls._named_constant_cache_[type(value)] = value_type - obj = actual_type.__new__(value_type, value) - obj._name_ = name - obj._value_ = value - obj.__doc__ = doc - cls._members_[name] = obj - metacls.__setattr__(cls, name, obj) - return obj - -@constant_dict -def __repr__(self): - return "<%s.%s: %r>" % ( - self.__class__.__name__, self._name_, self._value_) - -@constant_dict -def __reduce_ex__(self, proto): - return getattr, (self.__class__, self._name_) - -NamedConstant = NamedConstantMeta('NamedConstant', (object, ), constant_dict.resolve()) -Constant = NamedConstant -del constant_dict - -# NamedTuple - -class _NamedTupleDict(OrderedDict): - """Track field order and ensure field names are not reused. - - NamedTupleMeta will use the names found in self._field_names to translate - to indices. - """ - def __init__(self, *args, **kwds): - self._field_names = [] - super(_NamedTupleDict, self).__init__(*args, **kwds) - - def __setitem__(self, key, value): - """Records anything not dundered or not a descriptor. - - If a field name is used twice, an error is raised. - - Single underscore (sunder) names are reserved. - """ - if _is_sunder(key): - if key not in ('_size_', '_order_', '_fields_'): - raise ValueError( - '_sunder_ names, such as %r, are reserved for future NamedTuple use' - % (key, ) - ) - elif _is_dunder(key): - if key == '__order__': - key = '_order_' - elif key in self._field_names: - # overwriting a field? - raise TypeError('attempt to reuse field name: %r' % (key, )) - elif not _is_descriptor(value): - if key in self: - # field overwriting a descriptor? - raise TypeError('%s already defined as: %r' % (key, self[key])) - self._field_names.append(key) - super(_NamedTupleDict, self).__setitem__(key, value) - - -class _TupleAttributeAtIndex(object): - - def __init__(self, name, index, doc, default): - self.name = name - self.index = index - if doc is undefined: - doc = None - self.__doc__ = doc - self.default = default - - def __get__(self, instance, owner): - if instance is None: - return self - if len(instance) <= self.index: - raise AttributeError('%s instance has no value for %s' % (instance.__class__.__name__, self.name)) - return instance[self.index] - - def __repr__(self): - return '%s(%d)' % (self.__class__.__name__, self.index) - - -class undefined(object): - def __repr__(self): - return 'undefined' - def __bool__(self): - return False - __nonzero__ = __bool__ -undefined = undefined() - - -class TupleSize(NamedConstant): - fixed = constant('fixed', 'tuple length is static') - minimum = constant('minimum', 'tuple must be at least x long (x is calculated during creation') - variable = constant('variable', 'tuple length can be anything') - -class NamedTupleMeta(type): - """Metaclass for NamedTuple""" - - @classmethod - def __prepare__(metacls, cls, bases, size=undefined, **kwds): - return _NamedTupleDict() - - def __init__(cls, *args , **kwds): - super(NamedTupleMeta, cls).__init__(*args) - - def __new__(metacls, cls, bases, clsdict, size=undefined, **kwds): - if bases == (object, ): - bases = (tuple, object) - elif tuple not in bases: - if object in bases: - index = bases.index(object) - bases = bases[:index] + (tuple, ) + bases[index:] - else: - bases = bases + (tuple, ) - # include any fields from base classes - base_dict = _NamedTupleDict() - namedtuple_bases = [] - for base in bases: - if isinstance(base, NamedTupleMeta): - namedtuple_bases.append(base) - i = 0 - if namedtuple_bases: - for name, index, doc, default in metacls._convert_fields(*namedtuple_bases): - base_dict[name] = index, doc, default - i = max(i, index) - # construct properly ordered dict with normalized indexes - for k, v in clsdict.items(): - base_dict[k] = v - original_dict = base_dict - if size is not undefined and '_size_' in original_dict: - raise TypeError('_size_ cannot be set if "size" is passed in header') - add_order = isinstance(clsdict, _NamedTupleDict) - clsdict = _NamedTupleDict() - clsdict.setdefault('_size_', size or TupleSize.fixed) - unnumbered = OrderedDict() - numbered = OrderedDict() - _order_ = original_dict.pop('_order_', []) - if _order_ : - _order_ = _order_.replace(',',' ').split() - add_order = False - # and process this class - for k, v in original_dict.items(): - if k not in original_dict._field_names: - clsdict[k] = v - else: - # TODO:normalize v here - if isinstance(v, baseinteger): - # assume an offset - v = v, undefined, undefined - i = v[0] + 1 - target = numbered - elif isinstance(v, basestring): - # assume a docstring - if add_order: - v = i, v, undefined - i += 1 - target = numbered - else: - v = undefined, v, undefined - target = unnumbered - elif isinstance(v, tuple) and len(v) in (2, 3) and isinstance(v[0], baseinteger) and isinstance(v[1], (basestring, NoneType)): - # assume an offset, a docstring, and (maybe) a default - if len(v) == 2: - v = v + (undefined, ) - v = v - i = v[0] + 1 - target = numbered - elif isinstance(v, tuple) and len(v) in (1, 2) and isinstance(v[0], (basestring, NoneType)): - # assume a docstring, and (maybe) a default - if len(v) == 1: - v = v + (undefined, ) - if add_order: - v = (i, ) + v - i += 1 - target = numbered - else: - v = (undefined, ) + v - target = unnumbered - else: - # refuse to guess further - raise ValueError('not sure what to do with %s=%r (should be OFFSET [, DOC [, DEFAULT]])' % (k, v)) - target[k] = v - # all index values have been normalized - # deal with _order_ (or lack thereof) - fields = [] - aliases = [] - seen = set() - max_len = 0 - if not _order_: - if unnumbered: - raise ValueError("_order_ not specified and OFFSETs not declared for %r" % (unnumbered.keys(), )) - for name, (index, doc, default) in sorted(numbered.items(), key=lambda nv: (nv[1][0], nv[0])): - if index in seen: - aliases.append(name) - else: - fields.append(name) - seen.add(index) - max_len = max(max_len, index + 1) - offsets = numbered - else: - # check if any unnumbered not in _order_ - missing = set(unnumbered) - set(_order_) - if missing: - raise ValueError("unable to order fields: %s (use _order_ or specify OFFSET" % missing) - offsets = OrderedDict() - # if any unnumbered, number them from their position in _order_ - i = 0 - for k in _order_: - try: - index, doc, default = unnumbered.pop(k, None) or numbered.pop(k) - except IndexError: - raise ValueError('%s (from _order_) not found in %s' % (k, cls)) - if index is not undefined: - i = index - if i in seen: - aliases.append(k) - else: - fields.append(k) - seen.add(i) - offsets[k] = i, doc, default - i += 1 - max_len = max(max_len, i) - # now handle anything in numbered - for k, (index, doc, default) in sorted(numbered.items(), key=lambda nv: (nv[1][0], nv[0])): - if index in seen: - aliases.append(k) - else: - fields.append(k) - seen.add(index) - offsets[k] = index, doc, default - max_len = max(max_len, index+1) - - # at this point fields and aliases should be ordered lists, offsets should be an - # OrdededDict with each value an int, str or None or undefined, default or None or undefined - assert len(fields) + len(aliases) == len(offsets), "number of fields + aliases != number of offsets" - assert set(fields) & set(offsets) == set(fields), "some fields are not in offsets: %s" % set(fields) & set(offsets) - assert set(aliases) & set(offsets) == set(aliases), "some aliases are not in offsets: %s" % set(aliases) & set(offsets) - for name, (index, doc, default) in offsets.items(): - assert isinstance(index, baseinteger), "index for %s is not an int (%s:%r)" % (name, type(index), index) - assert isinstance(doc, (basestring, NoneType)) or doc is undefined, "doc is not a str, None, nor undefined (%s:%r)" % (name, type(doc), doc) - - # create descriptors for fields - for name, (index, doc, default) in offsets.items(): - clsdict[name] = _TupleAttributeAtIndex(name, index, doc, default) - clsdict['__slots__'] = () - - # create our new NamedTuple type - namedtuple_class = super(NamedTupleMeta, metacls).__new__(metacls, cls, bases, clsdict) - namedtuple_class._fields_ = fields - namedtuple_class._aliases_ = aliases - namedtuple_class._defined_len_ = max_len - return namedtuple_class - - @staticmethod - def _convert_fields(*namedtuples): - "create list of index, doc, default triplets for cls in namedtuples" - all_fields = [] - for cls in namedtuples: - base = len(all_fields) - for field in cls._fields_: - desc = getattr(cls, field) - all_fields.append((field, base+desc.index, desc.__doc__, desc.default)) - return all_fields - - def __add__(cls, other): - "A new NamedTuple is created by concatenating the _fields_ and adjusting the descriptors" - if not isinstance(other, NamedTupleMeta): - return NotImplemented - return NamedTupleMeta('%s%s' % (cls.__name__, other.__name__), (cls, other), {}) - - def __call__(cls, *args, **kwds): - """Creates a new NamedTuple class or an instance of a NamedTuple subclass. - - NamedTuple should have args of (class_name, names, module) - - `names` can be: - - * A string containing member names, separated either with spaces or - commas. Values are auto-numbered from 1. - * An iterable of member names. Values are auto-numbered from 1. - * An iterable of (member name, value) pairs. - * A mapping of member name -> value. - - `module`, if set, will be stored in the new class' __module__ attribute; - - Note: if `module` is not set this routine will attempt to discover the - calling module by walking the frame stack; if this is unsuccessful - the resulting class will not be pickleable. - - subclass should have whatever arguments and/or keywords will be used to create an - instance of the subclass - """ - if cls is NamedTuple: - original_args = args - original_kwds = kwds.copy() - # create a new subclass - try: - if 'class_name' in kwds: - class_name = kwds.pop('class_name') - else: - class_name, args = args[0], args[1:] - if 'names' in kwds: - names = kwds.pop('names') - else: - names, args = args[0], args[1:] - if 'module' in kwds: - module = kwds.pop('module') - elif args: - module, args = args[0], args[1:] - else: - module = None - if 'type' in kwds: - type = kwds.pop('type') - elif args: - type, args = args[0], args[1:] - else: - type = None - - except IndexError: - raise TypeError('too few arguments to NamedTuple: %s, %s' % (original_args, original_kwds)) - if args or kwds: - raise TypeError('too many arguments to NamedTuple: %s, %s' % (original_args, original_kwds)) - if PY2: - # if class_name is unicode, attempt a conversion to ASCII - if isinstance(class_name, unicode): - try: - class_name = class_name.encode('ascii') - except UnicodeEncodeError: - raise TypeError('%r is not representable in ASCII' % (class_name, )) - # quick exit if names is a NamedTuple - if isinstance(names, NamedTupleMeta): - names.__name__ = class_name - if type is not None and type not in names.__bases__: - names.__bases__ = (type, ) + names.__bases__ - return names - - metacls = cls.__class__ - bases = (cls, ) - clsdict = metacls.__prepare__(class_name, bases) - - # special processing needed for names? - if isinstance(names, basestring): - names = names.replace(',', ' ').split() - if isinstance(names, (tuple, list)) and isinstance(names[0], basestring): - names = [(e, i) for (i, e) in enumerate(names)] - # Here, names is either an iterable of (name, index) or (name, index, doc, default) or a mapping. - item = None # in case names is empty - for item in names: - if isinstance(item, basestring): - # mapping - field_name, field_index = item, names[item] - else: - # non-mapping - if len(item) == 2: - field_name, field_index = item - else: - field_name, field_index = item[0], item[1:] - clsdict[field_name] = field_index - if type is not None: - if not isinstance(type, tuple): - type = (type, ) - bases = type + bases - namedtuple_class = metacls.__new__(metacls, class_name, bases, clsdict) - - # TODO: replace the frame hack if a blessed way to know the calling - # module is ever developed - if module is None: - try: - module = _sys._getframe(1).f_globals['__name__'] - except (AttributeError, ValueError, KeyError): - pass - if module is None: - _make_class_unpicklable(namedtuple_class) - else: - namedtuple_class.__module__ = module - - return namedtuple_class - else: - # instantiate a subclass - namedtuple_instance = cls.__new__(cls, *args, **kwds) - if isinstance(namedtuple_instance, cls): - namedtuple_instance.__init__(*args, **kwds) - return namedtuple_instance - - @_bltin_property - def __fields__(cls): - return list(cls._fields_) - # collections.namedtuple compatibility - _fields = __fields__ - - @_bltin_property - def __aliases__(cls): - return list(cls._aliases_) - - def __repr__(cls): - return "<NamedTuple %r>" % (cls.__name__, ) - -namedtuple_dict = _Addendum( - dict=NamedTupleMeta.__prepare__('NamedTuple', (object, )), - doc="NamedTuple base class.\n\n Derive from this class to define new NamedTuples.\n\n", - ns=globals(), - ) - -@namedtuple_dict -def __new__(cls, *args, **kwds): - if cls._size_ is TupleSize.fixed and len(args) > cls._defined_len_: - raise TypeError('%d fields expected, %d received' % (cls._defined_len_, len(args))) - unknown = set(kwds) - set(cls._fields_) - set(cls._aliases_) - if unknown: - raise TypeError('unknown fields: %r' % (unknown, )) - final_args = list(args) + [undefined] * (len(cls.__fields__) - len(args)) - for field, value in kwds.items(): - index = getattr(cls, field).index - if final_args[index] != undefined: - raise TypeError('field %s specified more than once' % field) - final_args[index] = value - missing = [] - for index, value in enumerate(final_args): - if value is undefined: - # look for default values - name = cls.__fields__[index] - default = getattr(cls, name).default - if default is undefined: - missing.append(name) - else: - final_args[index] = default - if missing: - if cls._size_ in (TupleSize.fixed, TupleSize.minimum): - raise TypeError('values not provided for field(s): %s' % ', '.join(missing)) - while final_args and final_args[-1] is undefined: - final_args.pop() - missing.pop() - if cls._size_ is not TupleSize.variable or undefined in final_args: - raise TypeError('values not provided for field(s): %s' % ', '.join(missing)) - return tuple.__new__(cls, tuple(final_args)) - -@namedtuple_dict -def __reduce_ex__(self, proto): - return self.__class__, tuple(getattr(self, f) for f in self._fields_) - -@namedtuple_dict -def __repr__(self): - if len(self) == len(self._fields_): - return "%s(%s)" % ( - self.__class__.__name__, ', '.join(['%s=%r' % (f, o) for f, o in zip(self._fields_, self)]) - ) - else: - return '%s(%s)' % (self.__class__.__name__, ', '.join([repr(o) for o in self])) - -@namedtuple_dict -def __str__(self): - return "%s(%s)" % ( - self.__class__.__name__, ', '.join(['%r' % (getattr(self, f), ) for f in self._fields_]) - ) - -@namedtuple_dict -@_bltin_property -def _fields_(self): - return list(self.__class__._fields_) - - # compatibility methods with stdlib namedtuple -@namedtuple_dict -@_bltin_property -def __aliases__(self): - return list(self.__class__._aliases_) - -@namedtuple_dict -@_bltin_property -def _fields(self): - return list(self.__class__._fields_) - -@namedtuple_dict -@classmethod -def _make(cls, iterable, new=None, len=None): - return cls.__new__(cls, *iterable) - -@namedtuple_dict -def _asdict(self): - return OrderedDict(zip(self._fields_, self)) - -@namedtuple_dict -def _replace(self, **kwds): - current = self._asdict() - current.update(kwds) - return self.__class__(**current) - -NamedTuple = NamedTupleMeta('NamedTuple', (object, ), namedtuple_dict.resolve()) -del namedtuple_dict - - -# Enum - - # _init_ and value and AddValue - # ----------------------------- - # by default, when defining a member everything after the = is "the value", everything is - # passed to __new__, everything is passed to __init__ - # - # if _init_ is present then - # if `value` is not in _init_, everything is "the value", defaults apply - # if `value` is in _init_, only the first thing after the = is the value, and the rest will - # be passed to __init__ - # if fewer values are present for member assignment than _init_ calls for, _generate_next_value_ - # will be called in an attempt to generate them - # - # if AddValue is present then - # _generate_next_value_ is always called, and any generated values are prepended to provided - # values (custom _gnv_s can change that) - # default _init_ rules apply - - - # Constants used in Enum - -@export(globals()) -class EnumConstants(NamedConstant): - AddValue = constant('addvalue', 'prepends value(s) from _generate_next_value_ to each member') - MagicValue = constant('magicvalue', 'calls _generate_next_value_ when no arguments are given') - MultiValue = constant('multivalue', 'each member can have several values') - NoAlias = constant('noalias', 'duplicate valued members are distinct, not aliased') - Unique = constant('unique', 'duplicate valued members are not allowed') - def __repr__(self): - return self._name_ - - - # Dummy value for Enum as EnumType explicity checks for it, but of course until - # EnumType finishes running the first time the Enum class doesn't exist. This - # is also why there are checks in EnumType like `if Enum is not None`. - # - # Ditto for Flag. - -Enum = ReprEnum = IntEnum = StrEnum = Flag = IntFlag = EJECT = KEEP = None - -class enum(object): - """ - Helper class to track args, kwds. - """ - def __init__(self, *args, **kwds): - self._args = args - self._kwds = dict(kwds.items()) - self._hash = hash(args) - self.name = None - - @_bltin_property - def args(self): - return self._args - - @_bltin_property - def kwds(self): - return self._kwds.copy() - - def __hash__(self): - return self._hash - - def __eq__(self, other): - if not isinstance(other, self.__class__): - return NotImplemented - return self.args == other.args and self.kwds == other.kwds - - def __ne__(self, other): - if not isinstance(other, self.__class__): - return NotImplemented - return self.args != other.args or self.kwds != other.kwds - - def __repr__(self): - final = [] - args = ', '.join(['%r' % (a, ) for a in self.args]) - if args: - final.append(args) - kwds = ', '.join([('%s=%r') % (k, v) for k, v in enumsort(list(self.kwds.items()))]) - if kwds: - final.append(kwds) - return '%s(%s)' % (self.__class__.__name__, ', '.join(final)) - -_auto_null = SentinelType('no_value', (object, ), {}) -class auto(enum): - """ - Instances are replaced with an appropriate value in Enum class suites. - """ - enum_member = _auto_null - _value = _auto_null - _operations = [] - - def __and__(self, other): - new_auto = self.__class__() - new_auto._operations = self._operations[:] - new_auto._operations.append((_and_, (self, other))) - return new_auto - - def __rand__(self, other): - new_auto = self.__class__() - new_auto._operations = self._operations[:] - new_auto._operations.append((_and_, (other, self))) - return new_auto - - def __invert__(self): - new_auto = self.__class__() - new_auto._operations = self._operations[:] - new_auto._operations.append((_inv_, (self,))) - return new_auto - - def __or__(self, other): - new_auto = self.__class__() - new_auto._operations = self._operations[:] - new_auto._operations.append((_or_, (self, other))) - return new_auto - - def __ror__(self, other): - new_auto = self.__class__() - new_auto._operations = self._operations[:] - new_auto._operations.append((_or_, (other, self))) - return new_auto - - def __xor__(self, other): - new_auto = self.__class__() - new_auto._operations = self._operations[:] - new_auto._operations.append((_xor_, (self, other))) - return new_auto - - def __rxor__(self, other): - new_auto = self.__class__() - new_auto._operations = self._operations[:] - new_auto._operations.append((_xor_, (other, self))) - return new_auto - - def __abs__(self): - new_auto = self.__class__() - new_auto._operations = self._operations[:] - new_auto._operations.append((_abs_, (self, ))) - return new_auto - - def __add__(self, other): - new_auto = self.__class__() - new_auto._operations = self._operations[:] - new_auto._operations.append((_add_, (self, other))) - return new_auto - - def __radd__(self, other): - new_auto = self.__class__() - new_auto._operations = self._operations[:] - new_auto._operations.append((_add_, (other, self))) - return new_auto - - def __neg__(self): - new_auto = self.__class__() - new_auto._operations = self._operations[:] - new_auto._operations.append((_neg_, (self, ))) - return new_auto - - def __pos__(self): - new_auto = self.__class__() - new_auto._operations = self._operations[:] - new_auto._operations.append((_pos_, (self, ))) - return new_auto - - if PY2: - def __div__(self, other): - new_auto = self.__class__() - new_auto._operations = self._operations[:] - new_auto._operations.append((_div_, (self, other))) - return new_auto - - def __rdiv__(self, other): - new_auto = self.__class__() - new_auto._operations = self._operations[:] - new_auto._operations.append((_div_, (other, self))) - return new_auto - - def __floordiv__(self, other): - new_auto = self.__class__() - new_auto._operations = self._operations[:] - new_auto._operations.append((_floordiv_, (self, other))) - return new_auto - - def __rfloordiv__(self, other): - new_auto = self.__class__() - new_auto._operations = self._operations[:] - new_auto._operations.append((_floordiv_, (other, self))) - return new_auto - - def __truediv__(self, other): - new_auto = self.__class__() - new_auto._operations = self._operations[:] - new_auto._operations.append((_truediv_, (self, other))) - return new_auto - - def __rtruediv__(self, other): - new_auto = self.__class__() - new_auto._operations = self._operations[:] - new_auto._operations.append((_truediv_, (other, self))) - return new_auto - - def __lshift__(self, other): - new_auto = self.__class__() - new_auto._operations = self._operations[:] - new_auto._operations.append((_lshift_, (self, other))) - return new_auto - - def __rlshift__(self, other): - new_auto = self.__class__() - new_auto._operations = self._operations[:] - new_auto._operations.append((_lshift_, (other, self))) - return new_auto - - def __rshift__(self, other): - new_auto = self.__class__() - new_auto._operations = self._operations[:] - new_auto._operations.append((_rshift_, (self, other))) - return new_auto - - def __rrshift__(self, other): - new_auto = self.__class__() - new_auto._operations = self._operations[:] - new_auto._operations.append((_rshift_, (other, self))) - return new_auto - - def __mod__(self, other): - new_auto = self.__class__() - new_auto._operations = self._operations[:] - new_auto._operations.append((_mod_, (self, other))) - return new_auto - - def __rmod__(self, other): - new_auto = self.__class__() - new_auto._operations = self._operations[:] - new_auto._operations.append((_mod_, (other, self))) - return new_auto - - def __mul__(self, other): - new_auto = self.__class__() - new_auto._operations = self._operations[:] - new_auto._operations.append((_mul_, (self, other))) - return new_auto - - def __rmul__(self, other): - new_auto = self.__class__() - new_auto._operations = self._operations[:] - new_auto._operations.append((_mul_, (other, self))) - return new_auto - - def __pow__(self, other): - new_auto = self.__class__() - new_auto._operations = self._operations[:] - new_auto._operations.append((_pow_, (self, other))) - return new_auto - - def __rpow__(self, other): - new_auto = self.__class__() - new_auto._operations = self._operations[:] - new_auto._operations.append((_pow_, (other, self))) - return new_auto - - def __sub__(self, other): - new_auto = self.__class__() - new_auto._operations = self._operations[:] - new_auto._operations.append((_sub_, (self, other))) - return new_auto - - def __rsub__(self, other): - new_auto = self.__class__() - new_auto._operations = self._operations[:] - new_auto._operations.append((_sub_, (other, self))) - return new_auto - - def __repr__(self): - if self._operations: - return 'auto(...)' - else: - return 'auto(%r, *%r, **%r)' % (self._value, self._args, self._kwds) - - @_bltin_property - def value(self): - if self._value is not _auto_null and self._operations: - raise TypeError('auto() object out of sync') - elif self._value is _auto_null and not self._operations: - return self._value - elif self._value is not _auto_null: - return self._value - else: - return self._resolve() - - @value.setter - def value(self, value): - if self._operations: - value = self._resolve(value) - self._value = value - - def _resolve(self, base_value=None): - cls = self.__class__ - for op, params in self._operations: - values = [] - for param in params: - if isinstance(param, cls): - if param.value is _auto_null: - if base_value is None: - return _auto_null - else: - values.append(base_value) - else: - values.append(param.value) - else: - values.append(param) - value = op(*values) - self._operations[:] = [] - self._value = value - return value - - -class _EnumArgSpec(NamedTuple): - args = 0, 'all args except *args and **kwds' - varargs = 1, 'the name of the *args variable' - keywords = 2, 'the name of the **kwds variable' - defaults = 3, 'any default values' - required = 4, 'number of required values (no default available)' - - def __new__(cls, _new_func): - argspec = getargspec(_new_func) - args, varargs, keywords, defaults = argspec - if defaults: - reqs = args[1:-len(defaults)] - else: - reqs = args[1:] - return tuple.__new__(_EnumArgSpec, (args, varargs, keywords, defaults, reqs)) - - -class _proto_member: - """ - intermediate step for enum members between class execution and final creation - """ - - def __init__(self, value): - self.value = value - - def __set_name__(self, enum_class, member_name): - """ - convert each quasi-member into an instance of the new enum class - """ - # first step: remove ourself from enum_class - delattr(enum_class, member_name) - # second step: create member based on enum_class - value = self.value - kwds = {} - args = () - init_args = () - extra_mv_args = () - multivalue = None - if isinstance(value, tuple) and value and isinstance(value[0], auto): - multivalue = value - value = value[0] - if isinstance(value, auto) and value.value is _auto_null: - args = value.args - kwds = value.kwds - elif isinstance(value, auto): - kwds = value.kwds - args = (value.value, ) + value.args - value = value.value - elif isinstance(value, enum): - args = value.args - kwds = value.kwds - elif isinstance(value, Member): - value = value.value - args = (value, ) - elif not isinstance(value, tuple): - args = (value, ) - else: - args = value - if multivalue is not None: - value = (value, ) + multivalue[1:] - kwds = {} - args = value - del multivalue - # possibilities - # - # - no init, multivalue -> __new__[0], __init__(*[:]), extra=[1:] - # - init w/o value, multivalue -> __new__[0], __init__(*[:]), extra=[1:] - # - # - init w/value, multivalue -> __new__[0], __init__(*[1:]), extra=[1:] - # - # - init w/value, no multivalue -> __new__[0], __init__(*[1:]), extra=[] - # - # - init w/o value, no multivalue -> __new__[:], __init__(*[:]), extra=[] - # - no init, no multivalue -> __new__[:], __init__(*[:]), extra=[] - if enum_class._multivalue_ or 'value' in enum_class._creating_init_: - if enum_class._multivalue_: - # when multivalue is True, creating_init can be anything - mv_arg = args[0] - extra_mv_args = args[1:] - if 'value' in enum_class._creating_init_: - init_args = args[1:] - else: - init_args = args - args = args[0:1] - value = args[0] - else: - # 'value' is definitely in creating_init - if enum_class._auto_init_ and enum_class._new_args_: - # we have a custom __new__ and an auto __init__ - # divvy up according to number of params in each - init_args = args[-len(enum_class._creating_init_)+1:] - if not enum_class._auto_args_: - args = args[:len(enum_class._new_args_.args)] - value = args[0] - elif enum_class._auto_init_: - # don't pass in value - init_args = args[1:] - args = args[0:1] - value = args[0] - elif enum_class._new_args_: - # do not modify args - value = args[0] - else: - # keep all args for user-defined __init__ - # keep value as-is - init_args = args - else: - # either no creating_init, or it doesn't have 'value' - init_args = args - if enum_class._member_type_ is tuple: # special case for tuple enums - args = (args, ) # wrap it one more time - if not enum_class._use_args_: - enum_member = enum_class._new_member_(enum_class) - if not hasattr(enum_member, '_value_'): - enum_member._value_ = value - else: - enum_member = enum_class._new_member_(enum_class, *args, **kwds) - if not hasattr(enum_member, '_value_'): - if enum_class._member_type_ is object: - enum_member._value_ = value - else: - try: - enum_member._value_ = enum_class._member_type_(*args, **kwds) - except Exception: - te = TypeError('_value_ not set in __new__, unable to create it') - te.__cause__ = None - raise te - value = enum_member._value_ - enum_member._name_ = member_name - enum_member.__objclass__ = enum_class - enum_member.__init__(*init_args, **kwds) - enum_member._sort_order_ = len(enum_class._member_names_) - # If another member with the same value was already defined, the - # new member becomes an alias to the existing one. - if enum_class._noalias_: - # unless NoAlias was specified - enum_class._member_names_.append(member_name) - else: - nonunique = defaultdict(list) - try: - try: - # try to do a fast lookup to avoid the quadratic loop - enum_member = enum_class._value2member_map_[value] - if enum_class._unique_: - nonunique[enum_member.name].append(member_name) - except TypeError: - # unhashable members are stored elsewhere - for unhashable_value, canonical_member in enum_class._value2member_seq_: - name = canonical_member.name - if unhashable_value == enum_member._value_: - if enum_class._unique_: - nonunique[name].append(member_name) - enum_member = canonical_member - break - else: - raise KeyError - except KeyError: - # this could still be an alias if the value is multi-bit and the - # class is a flag class - if ( - Flag is None - or not issubclass(enum_class, Flag) - ): - # no other instances found, record this member in _member_names_ - enum_class._member_names_.append(member_name) - elif ( - Flag is not None - and issubclass(enum_class, Flag) - and _is_single_bit(value) - ): - # no other instances found, record this member in _member_names_ - enum_class._member_names_.append(member_name) - if nonunique: - # duplicates not allowed if Unique specified - message = [] - for name, aliases in nonunique.items(): - bad_aliases = ','.join(aliases) - message.append('%s --> %s [%r]' % (name, bad_aliases, enum_class[name].value)) - raise ValueError( - '%s: duplicate names found: %s' % - (enum_class.__name__, '; '.join(message)) - ) - # if self.value is an `auto()`, replace the value attribute with the new enum member - if isinstance(self.value, auto): - self.value.enum_member = enum_member - # get redirect in place before adding to _member_map_ - # but check for other instances in parent classes first - need_override = False - descriptor = None - descriptor_property = None - for base in enum_class.__mro__[1:]: - descriptor = base.__dict__.get(member_name) - if descriptor is not None: - if isinstance(descriptor, (property, DynamicClassAttribute)): - break - else: - need_override = True - if isinstance(descriptor, _bltin_property) and descriptor_property is None: - descriptor_property = descriptor - # keep looking for an enum.property - descriptor = descriptor or descriptor_property - if descriptor and not need_override: - # previous enum.property found, no further action needed - pass - else: - redirect = property() - redirect.__set_name__(enum_class, member_name) - if descriptor and need_override: - # previous enum.property found, but some other inherited - # attribute is in the way; copy fget, fset, fdel to this one - redirect.fget = descriptor.fget - redirect.fset = descriptor.fset - redirect.fdel = descriptor.fdel - setattr(enum_class, member_name, redirect) - # now add to _member_map_ (even aliases) - enum_class._member_map_[member_name] = enum_member - # - # process (possible) MultiValues - values = (value, ) + extra_mv_args - if enum_class._multivalue_ and mv_arg not in values: - values += (mv_arg, ) - enum_member._values_ = values - for value in values: - # first check if value has already been used - if enum_class._multivalue_ and ( - value in enum_class._value2member_map_ - or any(v == value for (v, m) in enum_class._value2member_seq_) - ): - raise ValueError('%r has already been used' % (value, )) - try: - # This may fail if value is not hashable. We can't add the value - # to the map, and by-value lookups for this value will be - # linear. - if enum_class._noalias_: - raise TypeError('cannot use dict to store value') - enum_class._value2member_map_[value] = enum_member - except TypeError: - enum_class._value2member_seq_ += ((value, enum_member), ) - - -class _EnumDict(dict): - """Track enum member order and ensure member names are not reused. - - EnumType will use the names found in self._member_names as the - enumeration member names. - """ - def __init__(self, cls_name, settings, start, constructor_init, constructor_start, constructor_boundary): - super(_EnumDict, self).__init__() - self._cls_name = cls_name - self._constructor_init = constructor_init - self._constructor_start = constructor_start - self._constructor_boundary = constructor_boundary - self._generate_next_value = None - self._member_names = [] - self._member_names_set = set() - self._settings = settings - self._addvalue = addvalue = AddValue in settings - self._magicvalue = MagicValue in settings - self._multivalue = MultiValue in settings - if self._addvalue and self._magicvalue: - raise TypeError('%r: AddValue and MagicValue are mutually exclusive' % cls_name) - if self._multivalue and self._magicvalue: - raise TypeError('%r: MultiValue and MagicValue are mutually exclusive' % cls_name) - self._start = start - self._addvalue_value = start - self._new_args = () - self._auto_args = False - # when the magic turns off - self._locked = MagicValue not in settings - # if init fields are specified - self._init = [] - # list of temporary names - self._ignore = [] - if self._magicvalue: - self._ignore = ['property', 'staticmethod', 'classmethod'] - self._ignore_init_done = False - # if _sunder_ values can be changed via the class body - self._allow_init = True - self._last_values = [] - - def __getitem__(self, key): - if key == self._cls_name and self._cls_name not in self: - return enum - elif ( - self._locked - or key in self - or key in self._ignore - or _is_sunder(key) - or _is_dunder(key) - ): - return super(_EnumDict, self).__getitem__(key) - elif self._magicvalue: - value = self._generate_next_value(key, self._start, len(self._member_names), self._last_values[:]) - self.__setitem__(key, value) - return value - else: - raise Exception('Magic is not set -- why am I here?') - - def __setitem__(self, key, value): - """Changes anything not sundured, dundered, nor a descriptor. - - If an enum member name is used twice, an error is raised; duplicate - values are not checked for. - - Single underscore (sunder) names are reserved. - """ - # Flag classes that have MagicValue and __new__ will get a generated _gnv_ - if _is_internal_class(self._cls_name, value): - pass - elif _is_private_name(self._cls_name, key): - pass - elif _is_sunder(key): - if key not in ( - '_init_', '_settings_', '_order_', '_ignore_', '_start_', - '_create_pseudo_member_', '_create_pseudo_member_values_', - '_generate_next_value_', '_boundary_', '_numeric_repr_', - '_missing_', '_missing_value_', '_missing_name_', - '_iter_member_', '_iter_member_by_value_', '_iter_member_by_def_', - ): - raise ValueError('%r: _sunder_ names, such as %r, are reserved for future Enum use' - % (self._cls_name, key) - ) - elif not self._allow_init and key not in ( - 'create_pseudo_member_', '_missing_', '_missing_value_', '_missing_name_', - ): - # sunder is used during creation, must be specified first - raise ValueError('%r: cannot set %r after init phase' % (self._cls_name, key)) - elif key == '_ignore_': - if self._ignore_init_done: - raise TypeError('%r: ignore can only be specified once' % self._cls_name) - if isinstance(value, basestring): - value = value.split() - else: - value = list(value) - self._ignore = value - already = set(value) & self._member_names_set - if already: - raise ValueError('%r: _ignore_ cannot specify already set names %s' % ( - self._cls_name, - ', '.join(repr(a) for a in already) - )) - self._ignore_init_done = True - elif key == '_boundary_': - if self._constructor_boundary: - raise TypeError('%r: boundary specified in constructor and class body' % self._cls_name) - elif key == '_start_': - if self._constructor_start: - raise TypeError('%r: start specified in constructor and class body' % self._cls_name) - self._start = value - elif key == '_settings_': - if not isinstance(value, (set, tuple)): - value = (value, ) - if not isinstance(value, set): - value = set(value) - self._settings |= value - if NoAlias in value and Unique in value: - raise TypeError('%r: NoAlias and Unique are mutually exclusive' % self._cls_name) - elif MultiValue in value and NoAlias in value: - raise TypeError('cannot specify both MultiValue and NoAlias' % self._cls_name) - allowed_settings = dict.fromkeys(['addvalue', 'magicvalue', 'noalias', 'unique', 'multivalue']) - for arg in self._settings: - if arg not in allowed_settings: - raise TypeError('%r: unknown qualifier %r (from %r)' % (self._cls_name, arg, value)) - allowed_settings[arg] = True - self._multivalue = allowed_settings['multivalue'] - self._addvalue = allowed_settings['addvalue'] - self._magicvalue = allowed_settings['magicvalue'] - self._locked = not self._magicvalue - if self._magicvalue and not self._ignore_init_done: - self._ignore = ['property', 'classmethod', 'staticmethod'] - if self._addvalue and self._init and 'value' not in self._init: - self._init.insert(0, 'value') - value = tuple(self._settings) - elif key == '_init_': - if self._constructor_init: - raise TypeError('%r: init specified in constructor and in class body' % self._cls_name) - _init_ = value - if isinstance(_init_, basestring): - _init_ = _init_.replace(',',' ').split() - if self._addvalue and 'value' not in self._init: - self._init.insert(0, 'value') - if self._magicvalue: - raise TypeError("%r: _init_ and MagicValue are mutually exclusive" % self._cls_name) - self._init = _init_ - value = _init_ - elif key == '_generate_next_value_': - gnv = value - if value is not None: - if isinstance(value, staticmethod): - gnv = value.__func__ - elif isinstance(value, classmethod): - raise TypeError('%r: _generate_next_value must be a staticmethod, not a classmethod' % self._cls_name) - else: - gnv = value - value = staticmethod(value) - self._auto_args = _check_auto_args(value) - setattr(self, '_generate_next_value', gnv) - elif _is_dunder(key): - if key == '__order__': - key = '_order_' - if not self._allow_init: - # _order_ is used during creation, must be specified first - raise ValueError('%r: cannot set %r after init phase' % (self._cls_name, key)) - elif key == '__new__': # and self._new_to_init: - if isinstance(value, staticmethod): - value = value.__func__ - self._new_args = _EnumArgSpec(value) - elif key == '__init_subclass__': - if not isinstance(value, classmethod): - value = classmethod(value) - if _is_descriptor(value): - self._locked = True - elif key in self._member_names_set: - # descriptor overwriting an enum? - raise TypeError('%r: attempt to reuse name: %r' % (self._cls_name, key)) - elif key in self._ignore: - pass - elif not _is_descriptor(value): - self._allow_init = False - if key in self: - # enum overwriting a descriptor? - raise TypeError('%r: %s already defined as %r' % (self._cls_name, key, self[key])) - if type(value) is enum: - value.name = key - if self._addvalue: - raise TypeError('%r: enum() and AddValue are incompatible' % self._cls_name) - elif self._addvalue and not self._multivalue: - # generate a value - value = self._gnv(key, value) - elif self._multivalue: - # make sure it's a tuple - if not isinstance(value, tuple): - value = (value, ) - if isinstance(value[0], auto): - value = (self._convert_auto(key, value[0]), ) + value[1:] - if self._addvalue: - value = self._gnv(key, value) - elif isinstance(value, auto): - value = self._convert_auto(key, value) - elif isinstance(value, tuple) and value and isinstance(value[0], auto): - value = (self._convert_auto(key, value[0]), ) + value[1:] - elif not isinstance(value, auto): - # call generate maybe if - # - init is specified; or - # - __new__ is specified; - # and either of them call for more values than are present - new_args = () or self._new_args and self._new_args.required - target_len = len(self._init or new_args) - if isinstance(value, tuple): - source_len = len(value) - else: - source_len = 1 - multi_args = len(self._init) > 1 or new_args - if source_len < target_len : - value = self._gnv(key, value) - else: - pass - if self._init: - if isinstance(value, auto): - test_value = value.args - elif not isinstance(value, tuple): - test_value = (value, ) - else: - test_value = value - if len(self._init) != len(test_value): - raise TypeError( - '%s.%s: number of fields provided do not match init [%r != %r]' - % (self._cls_name, key, self._init, test_value) - ) - self._member_names.append(key) - self._member_names_set.add(key) - else: - # not a new member, turn off the autoassign magic - self._locked = True - self._allow_init = False - if not (_is_sunder(key) or _is_dunder(key) or _is_private_name(self._cls_name, key) or _is_descriptor(value)): - if isinstance(value, auto): - self._last_values.append(value.value) - elif isinstance(value, tuple) and value and isinstance(value[0], auto): - self._last_values.append(value[0].value) - elif isinstance(value, tuple): - if value: - self._last_values.append(value[0]) - else: - self._last_values.append(value) - super(_EnumDict, self).__setitem__(key, value) - - def _convert_auto(self, key, value): - # if auto.args or auto.kwds, compare to _init_ and __new__ -- if lacking, call gnv - # if not auto.args|kwds but auto.value is _auto_null -- call gnv - if value.args or value.kwds or value.value is _auto_null: - if value.args or value.kwds: - values = value.args - else: - values = () - new_args = () or self._new_args and self._new_args.required - target_len = len(self._init or new_args) or 1 - if isinstance(values, tuple): - source_len = len(values) - else: - source_len = 1 - multi_args = len(self._init) > 1 or new_args - if source_len < target_len : - values = self._gnv(key, values) - if value.args: - value._args = values - else: - value.value = values - return value - - def _gnv(self, key, value): - # generate a value - if self._auto_args: - if not isinstance(value, tuple): - value = (value, ) - value = self._generate_next_value(key, self._start, len(self._member_names), self._last_values[:], *value) - else: - value = self._generate_next_value(key, self._start, len(self._member_names), self._last_values[:]) - if isinstance(value, tuple) and len(value) == 1: - value = value[0] - return value - - -no_arg = SentinelType('no_arg', (object, ), {}) -class EnumType(type): - """Metaclass for Enum""" - - @classmethod - def __prepare__(metacls, cls, bases, init=None, start=None, settings=(), boundary=None, **kwds): - metacls._check_for_existing_members_(cls, bases) - if Flag is None and cls == 'Flag': - initial_flag = True - else: - initial_flag = False - # settings are a combination of current and all past settings - constructor_init = init is not None - constructor_start = start is not None - constructor_boundary = boundary is not None - if not isinstance(settings, tuple): - settings = settings, - settings = set(settings) - generate = None - order = None - # inherit previous flags - member_type, first_enum = metacls._get_mixins_(cls, bases) - if first_enum is not None: - generate = getattr(first_enum, '_generate_next_value_', None) - generate = getattr(generate, 'im_func', generate) - settings |= metacls._get_settings_(bases) - init = init or first_enum._auto_init_[:] - order = first_enum._order_function_ - if start is None: - start = first_enum._start_ - else: - # first time through -- creating Enum itself - start = 1 - # check for custom settings - if AddValue in settings and init and 'value' not in init: - if isinstance(init, list): - init.insert(0, 'value') - else: - init = 'value ' + init - if NoAlias in settings and Unique in settings: - raise TypeError('%r: NoAlias and Unique are mutually exclusive' % cls) - if MultiValue in settings and NoAlias in settings: - raise TypeError('%r: MultiValue and NoAlias are mutually exclusive' % cls) - allowed_settings = dict.fromkeys(['addvalue', 'magicvalue', 'noalias', 'unique', 'multivalue']) - for arg in settings: - if arg not in allowed_settings: - raise TypeError('%r: unknown qualifier %r' % (cls, arg)) - enum_dict = _EnumDict(cls_name=cls, settings=settings, start=start, constructor_init=constructor_init, constructor_start=constructor_start, constructor_boundary=constructor_boundary) - enum_dict._member_type = member_type - enum_dict._base_type = ('enum', 'flag')[ - Flag is None and cls == 'Flag' - or - Flag is not None and any(issubclass(b, Flag) for b in bases) - ] - if Flag is not None and any(b is Flag for b in bases) and member_type not in (baseinteger + (object, )): - if Flag in bases: - # when a non-int data type is mixed in with Flag, we end up - # needing two values for two `__new__`s: - # - the integer value for the Flag itself; and - # - the mix-in value for the mix-in - # - # we provide a default `_generate_next_value_` to supply the int - # argument, and a default `__new__` to keep the two straight - def _generate_next_value_(name, start, count, values, *args, **kwds): - return (2 ** count, ) + args - enum_dict['_generate_next_value_'] = staticmethod(_generate_next_value_) - def __new__(cls, flag_value, type_value): - obj = member_type.__new__(cls, type_value) - obj._value_ = flag_value - return obj - enum_dict['__new__'] = __new__ - else: - try: - enum_dict._new_args = _EnumArgSpec(first_enum.__new_member__) - except TypeError: - pass - elif not initial_flag: - if hasattr(first_enum, '__new_member__'): - enum_dict._new_args = _EnumArgSpec(first_enum.__new_member__) - if generate: - enum_dict['_generate_next_value_'] = generate - enum_dict._inherited_gnv = True - if init is not None: - if isinstance(init, basestring): - init = init.replace(',',' ').split() - enum_dict._init = init - elif hasattr(first_enum, '__new_member__'): - enum_dict._new_args = _EnumArgSpec(first_enum.__new_member__) - if order is not None: - enum_dict['_order_'] = staticmethod(order) - return enum_dict - - def __init__(cls, *args , **kwds): - pass - - def __new__(metacls, cls, bases, clsdict, init=None, start=None, settings=(), boundary=None, **kwds): - # handle py2 case first - if type(clsdict) is not _EnumDict: - # py2 and/or functional API gyrations - init = clsdict.pop('_init_', None) - start = clsdict.pop('_start_', None) - settings = clsdict.pop('_settings_', ()) - _order_ = clsdict.pop('_order_', clsdict.pop('__order__', None)) - _ignore_ = clsdict.pop('_ignore_', None) - _create_pseudo_member_ = clsdict.pop('_create_pseudo_member_', None) - _create_pseudo_member_values_ = clsdict.pop('_create_pseudo_member_values_', None) - _generate_next_value_ = clsdict.pop('_generate_next_value_', None) - _missing_ = clsdict.pop('_missing_', None) - _missing_value_ = clsdict.pop('_missing_value_', None) - _missing_name_ = clsdict.pop('_missing_name_', None) - _boundary_ = clsdict.pop('_boundary_', None) - _iter_member_ = clsdict.pop('_iter_member_', None) - _iter_member_by_value_ = clsdict.pop('_iter_member_by_value_', None) - _iter_member_by_def_ = clsdict.pop('_iter_member_by_def_', None) - __new__ = clsdict.pop('__new__', None) - __new__ = getattr(__new__, 'im_func', __new__) - __new__ = getattr(__new__, '__func__', __new__) - enum_members = dict([ - (k, v) for (k, v) in clsdict.items() - if not (_is_sunder(k) or _is_dunder(k) or _is_private_name(cls, k) or _is_descriptor(v)) - ]) - original_dict = clsdict - clsdict = metacls.__prepare__(cls, bases, init=init, start=start) - if settings: - clsdict['_settings_'] = settings - init = init or clsdict._init - if _order_ is None: - _order_ = clsdict.get('_order_') - if _order_ is not None: - _order_ = _order_.__get__(cls) - if isinstance(original_dict, OrderedDict): - calced_order = original_dict - elif _order_ is None: - calced_order = [name for (name, value) in enumsort(list(enum_members.items()))] - elif isinstance(_order_, basestring): - calced_order = _order_ = _order_.replace(',', ' ').split() - elif callable(_order_): - if init: - if not isinstance(init, basestring): - init = ' '.join(init) - member = NamedTuple('member', init and 'name ' + init or ['name', 'value']) - calced_order = [] - for name, value in enum_members.items(): - if init: - if not isinstance(value, tuple): - value = (value, ) - name_value = (name, ) + value - else: - name_value = tuple((name, value)) - if member._defined_len_ != len(name_value): - raise TypeError('%d values expected (%s), %d received (%s)' % ( - member._defined_len_, - ', '.join(member._fields_), - len(name_value), - ', '.join([repr(v) for v in name_value]), - )) - calced_order.append(member(*name_value)) - calced_order = [m.name for m in sorted(calced_order, key=_order_)] - else: - calced_order = _order_ - for name in ( - '_missing_', '_missing_value_', '_missing_name_', - '_ignore_', '_create_pseudo_member_', '_create_pseudo_member_values_', - '_generate_next_value_', '_order_', '__new__', - '_missing_', '_missing_value_', '_missing_name_', - '_boundary_', - '_iter_member_', '_iter_member_by_value_', '_iter_member_by_def_', - ): - attr = locals()[name] - if attr is not None: - clsdict[name] = attr - # now add members - for k in calced_order: - try: - clsdict[k] = original_dict[k] - except KeyError: - # this error will be handled when _order_ is checked - pass - for k, v in original_dict.items(): - if k not in calced_order: - clsdict[k] = v - del _order_, _ignore_, _create_pseudo_member_, _create_pseudo_member_values_, - del _generate_next_value_, _missing_, _missing_value_, _missing_name_ - # - # resume normal path - clsdict._locked = True - # - # check for illegal enum names (any others?) - member_names = clsdict._member_names - invalid_names = set(member_names) & set(['mro', '']) - if invalid_names: - raise ValueError('invalid enum member name(s): %s' % ( - ', '.join(invalid_names), )) - _order_ = clsdict.pop('_order_', None) - if isinstance(_order_, basestring): - _order_ = _order_.replace(',',' ').split() - init = clsdict._init - start = clsdict._start - settings = clsdict._settings - creating_init = [] - new_args = clsdict._new_args - auto_args = clsdict._auto_args - auto_init = False - if init is not None: - auto_init = True - creating_init = init[:] - if 'value' in creating_init and creating_init[0] != 'value': - raise TypeError("'value', if specified, must be the first item in 'init'") - magicvalue = MagicValue in settings - multivalue = MultiValue in settings - noalias = NoAlias in settings - unique = Unique in settings - # an Enum class cannot be mixed with other types (int, float, etc.) if - # it has an inherited __new__ unless a new __new__ is defined (or - # the resulting class will fail). - # an Enum class is final once enumeration items have been defined; - # - # remove any keys listed in _ignore_ - clsdict.setdefault('_ignore_', []).append('_ignore_') - ignore = clsdict['_ignore_'] - for key in ignore: - clsdict.pop(key, None) - # - boundary = boundary or clsdict.pop('_boundary_', None) - # convert to regular dict - clsdict = dict(clsdict.items()) - member_type, first_enum = metacls._get_mixins_(cls, bases) - # get the method to create enum members - __new__, save_new, new_uses_args = metacls._find_new_( - clsdict, - member_type, - first_enum, - ) - clsdict['_new_member_'] = staticmethod(__new__) - clsdict['_use_args_'] = new_uses_args - # - # convert future enum members into temporary _proto_members - # and record integer values in case this will be a Flag - flag_mask = 0 - for name in member_names: - value = test_value = clsdict[name] - if isinstance(value, auto) and value.value is not _auto_null: - test_value = value.value - if isinstance(test_value, baseinteger): - flag_mask |= test_value - if isinstance(test_value, tuple) and test_value and isinstance(test_value[0], baseinteger): - flag_mask |= test_value[0] - clsdict[name] = _proto_member(value) - # - # temp stuff - clsdict['_creating_init_'] = creating_init - clsdict['_multivalue_'] = multivalue - clsdict['_magicvalue_'] = magicvalue - clsdict['_noalias_'] = noalias - clsdict['_unique_'] = unique - # - # house-keeping structures - clsdict['_member_names_'] = [] - clsdict['_member_map_'] = OrderedDict() - clsdict['_member_type_'] = member_type - clsdict['_value2member_map_'] = {} - clsdict['_value2member_seq_'] = () - clsdict['_settings_'] = settings - clsdict['_start_'] = start - clsdict['_auto_init_'] = init - clsdict['_new_args_'] = new_args - clsdict['_auto_args_'] = auto_args - clsdict['_order_function_'] = None - # now set the __repr__ for the value - clsdict['_value_repr_'] = metacls._find_data_repr_(cls, bases) - # - # Flag structures (will be removed if final class is not a Flag - clsdict['_boundary_'] = ( - boundary - or getattr(first_enum, '_boundary_', None) - ) - clsdict['_flag_mask_'] = flag_mask - clsdict['_all_bits_'] = 2 ** ((flag_mask).bit_length()) - 1 - clsdict['_inverted_'] = None - # - # move skipped values out of the descriptor - for name, obj in clsdict.items(): - if isinstance(obj, nonmember): - clsdict[name] = obj.value - # - # If a custom type is mixed into the Enum, and it does not know how - # to pickle itself, pickle.dumps will succeed but pickle.loads will - # fail. Rather than have the error show up later and possibly far - # from the source, sabotage the pickle protocol for this class so - # that pickle.dumps also fails. - # - # However, if the new class implements its own __reduce_ex__, do not - # sabotage -- it's on them to make sure it works correctly. We use - # __reduce_ex__ instead of any of the others as it is preferred by - # pickle over __reduce__, and it handles all pickle protocols. - unpicklable = False - if '__reduce_ex__' not in clsdict: - if member_type is not object: - methods = ('__getnewargs_ex__', '__getnewargs__', - '__reduce_ex__', '__reduce__') - if not any(m in member_type.__dict__ for m in methods): - _make_class_unpicklable(clsdict) - unpicklable = True - # - # create a default docstring if one has not been provided - if '__doc__' not in clsdict: - clsdict['__doc__'] = 'An enumeration.' - # - # create our new Enum type - try: - exc = None - enum_class = type.__new__(metacls, cls, bases, clsdict) - except RuntimeError as e: - # any exceptions raised by _proto_member (aka member.__new__) will get converted to - # a RuntimeError, so get that original exception back and raise - # it instead - exc = e.__cause__ or e - if exc is not None: - raise exc - # - # if Python 3.5 or ealier, implement the __set_name__ and - # __init_subclass__ protocols - if pyver < PY3_6: - for name in member_names: - enum_class.__dict__[name].__set_name__(enum_class, name) - for name, obj in enum_class.__dict__.items(): - if name in member_names: - continue - if hasattr(obj, '__set_name__'): - obj.__set_name__(enum_class, name) - if Enum is not None: - super(enum_class, enum_class).__init_subclass__() - # - # double check that repr and friends are not the mixin's or various - # things break (such as pickle) - # - # Also, special handling for ReprEnum - if ReprEnum is not None and ReprEnum in bases: - if member_type is object: - raise TypeError( - 'ReprEnum subclasses must be mixed with a data type (i.e.' - ' int, str, float, etc.)' - ) - if '__format__' not in clsdict: - enum_class.__format__ = member_type.__format__ - clsdict['__format__'] = enum_class.__format__ - if '__str__' not in clsdict: - method = member_type.__str__ - if method is object.__str__: - # if member_type does not define __str__, object.__str__ will use - # its __repr__ instead, so we'll also use its __repr__ - method = member_type.__repr__ - enum_class.__str__ = method - clsdict['__str__'] = enum_class.__str__ - - for name in ('__repr__', '__str__', '__format__', '__reduce_ex__'): - if name in clsdict: - # class has defined/imported/copied the method - continue - class_method = getattr(enum_class, name) - obj_method = getattr(member_type, name, None) - enum_method = getattr(first_enum, name, None) - if obj_method is not None and obj_method == class_method: - if name == '__reduce_ex__' and unpicklable: - continue - setattr(enum_class, name, enum_method) - clsdict[name] = enum_method - # - # for Flag, add __or__, __and__, __xor__, and __invert__ - if Flag is not None and issubclass(enum_class, Flag): - for name in ( - '__or__', '__and__', '__xor__', - '__ror__', '__rand__', '__rxor__', - '__invert__' - ): - if name not in clsdict: - setattr(enum_class, name, getattr(Flag, name)) - clsdict[name] = enum_method - # - # method resolution and int's are not playing nice - # Python's less than 2.6 use __cmp__ - if pyver < PY2_6: - # - if issubclass(enum_class, int): - setattr(enum_class, '__cmp__', getattr(int, '__cmp__')) - # - elif PY2: - # - if issubclass(enum_class, int): - for method in ( - '__le__', - '__lt__', - '__gt__', - '__ge__', - '__eq__', - '__ne__', - '__hash__', - ): - setattr(enum_class, method, getattr(int, method)) - # - # replace any other __new__ with our own (as long as Enum is not None, - # anyway) -- again, this is to support pickle - if Enum is not None: - # if the user defined their own __new__, save it before it gets - # clobbered in case they subclass later - if save_new: - setattr(enum_class, '__new_member__', enum_class.__dict__['__new__']) - setattr(enum_class, '__new__', Enum.__dict__['__new__']) - # - # _order_ checking is spread out into three/four steps - # - ensure _order_ is a list, not a string nor a function - # - if enum_class is a Flag: - # - remove any non-single-bit flags from _order_ - # - remove any aliases from _order_ - # - check that _order_ and _member_names_ match - # - # _order_ step 1: ensure _order_ is a list - if _order_: - if isinstance(_order_, staticmethod): - _order_ = _order_.__func__ - if callable(_order_): - # save order for future subclasses - enum_class._order_function_ = staticmethod(_order_) - # create ordered list for comparison - _order_ = [m.name for m in sorted(enum_class, key=_order_)] - # - # remove Flag structures if final class is not a Flag - if ( - Flag is None and cls != 'Flag' - or Flag is not None and not issubclass(enum_class, Flag) - ): - delattr(enum_class, '_boundary_') - delattr(enum_class, '_flag_mask_') - delattr(enum_class, '_all_bits_') - delattr(enum_class, '_inverted_') - elif Flag is not None and issubclass(enum_class, Flag): - # ensure _all_bits_ is correct and there are no missing flags - single_bit_total = 0 - multi_bit_total = 0 - for flag in enum_class._member_map_.values(): - if _is_single_bit(flag._value_): - single_bit_total |= flag._value_ - else: - # multi-bit flags are considered aliases - multi_bit_total |= flag._value_ - if enum_class._boundary_ is not KEEP: - missed = list(_iter_bits_lsb(multi_bit_total & ~single_bit_total)) - if missed: - raise TypeError( - 'invalid Flag %r -- missing values: %s' - % (cls, ', '.join((str(i) for i in missed))) - ) - enum_class._flag_mask_ = single_bit_total - enum_class._all_bits_ = 2 ** ((single_bit_total).bit_length()) - 1 - # - # set correct __iter__ - if [m._value_ for m in enum_class] != sorted([m._value_ for m in enum_class]): - enum_class._iter_member_ = enum_class._iter_member_by_def_ - if _order_: - # _order_ step 2: remove any items from _order_ that are not single-bit - _order_ = [ - o - for o in _order_ - if o not in enum_class._member_map_ or _is_single_bit(enum_class[o]._value_) - ] - # - # check for constants with auto() values - for k, v in enum_class.__dict__.items(): - if isinstance(v, constant) and isinstance(v.value, auto): - v.value = enum_class(v.value.value) - # - if _order_: - # _order_ step 3: remove aliases from _order_ - _order_ = [ - o - for o in _order_ - if ( - o not in enum_class._member_map_ - or - (o in enum_class._member_map_ and o in enum_class._member_names_) - )] - # _order_ step 4: verify that _order_ and _member_names_ match - if _order_ != enum_class._member_names_: - raise TypeError( - 'member order does not match _order_:\n%r\n%r' - % (enum_class._member_names_, _order_) - ) - return enum_class - - def __bool__(cls): - """ - classes/types should always be True. - """ - return True - - def __call__(cls, value=no_arg, names=None, module=None, qualname=None, type=None, start=1, boundary=None): - """Either returns an existing member, or creates a new enum class. - - This method is used both when an enum class is given a value to match - to an enumeration member (i.e. Color(3)) and for the functional API - (i.e. Color = Enum('Color', names='red green blue')). - - When used for the functional API: `module`, if set, will be stored in - the new class' __module__ attribute; `type`, if set, will be mixed in - as the first base class. - - Note: if `module` is not set this routine will attempt to discover the - calling module by walking the frame stack; if this is unsuccessful - the resulting class will not be pickleable. - """ - if names is None: # simple value lookup - return cls.__new__(cls, value) - # otherwise, functional API: we're creating a new Enum type - return cls._create_(value, names, module=module, qualname=qualname, type=type, start=start, boundary=boundary) - - def __contains__(cls, member): - if not isinstance(member, Enum): - raise TypeError("%r (%r) is not an <aenum 'Enum'>" % (member, type(member))) - if not isinstance(member, cls): - return False - return True - - def __delattr__(cls, attr): - # nicer error message when someone tries to delete an attribute - # (see issue19025). - if attr in cls._member_map_: - raise AttributeError( - "%s: cannot delete Enum member %r." % (cls.__name__, attr), - ) - found_attr = _get_attr_from_chain(cls, attr) - if isinstance(found_attr, constant): - raise AttributeError( - "%s: cannot delete constant %r" % (cls.__name__, attr), - ) - elif isinstance(found_attr, property): - raise AttributeError( - "%s: cannot delete property %r" % (cls.__name__, attr), - ) - super(EnumType, cls).__delattr__(attr) - - def __dir__(cls): - interesting = set(cls._member_names_ + [ - '__class__', '__contains__', '__doc__', '__getitem__', - '__iter__', '__len__', '__members__', '__module__', - '__name__', - ]) - if cls._new_member_ is not object.__new__: - interesting.add('__new__') - if cls.__init_subclass__ is not Enum.__init_subclass__: - interesting.add('__init_subclass__') - if hasattr(object, '__qualname__'): - interesting.add('__qualname__') - for method in ('__init__', '__format__', '__repr__', '__str__'): - if getattr(cls, method) not in (getattr(Enum, method), getattr(Flag, method)): - interesting.add(method) - if cls._member_type_ is object: - return sorted(interesting) - else: - # return whatever mixed-in data type has - return sorted(set(dir(cls._member_type_)) | interesting) - - @_bltin_property - def __members__(cls): - """Returns a mapping of member name->value. - - This mapping lists all enum members, including aliases. Note that this - is a copy of the internal mapping. - """ - return cls._member_map_.copy() - - def __getitem__(cls, name): - try: - return cls._member_map_[name] - except KeyError: - exc = _sys.exc_info()[1] - if Flag is not None and issubclass(cls, Flag) and '|' in name: - try: - # may be an __or__ed name - result = cls(0) - for n in name.split('|'): - result |= cls[n] - return result - except KeyError: - raise exc - result = cls._missing_name_(name) - if isinstance(result, cls): - return result - else: - raise exc - - def __iter__(cls): - return (cls._member_map_[name] for name in cls._member_names_) - - def __reversed__(cls): - return (cls._member_map_[name] for name in reversed(cls._member_names_)) - - def __len__(cls): - return len(cls._member_names_) - - __nonzero__ = __bool__ - - def __repr__(cls): - return "<aenum %r>" % (cls.__name__, ) - - def __setattr__(cls, name, value): - """Block attempts to reassign Enum members/constants. - - A simple assignment to the class namespace only changes one of the - several possible ways to get an Enum member from the Enum class, - resulting in an inconsistent Enumeration. - """ - member_map = cls.__dict__.get('_member_map_', {}) - if name in member_map: - raise AttributeError( - '%s: cannot rebind member %r.' % (cls.__name__, name), - ) - found_attr = _get_attr_from_chain(cls, name) - if isinstance(found_attr, constant): - raise AttributeError( - "%s: cannot rebind constant %r" % (cls.__name__, name), - ) - elif isinstance(found_attr, property): - raise AttributeError( - "%s: cannot rebind property %r" % (cls.__name__, name), - ) - super(EnumType, cls).__setattr__(name, value) - - def _convert(cls, *args, **kwds): - import warnings - warnings.warn("_convert is deprecated and will be removed, use" - " _convert_ instead.", DeprecationWarning, stacklevel=2) - return cls._convert_(*args, **kwds) - - def _convert_(cls, name, module, filter, source=None, boundary=None, as_global=False): - """ - Create a new Enum subclass that replaces a collection of global constants - """ - # convert all constants from source (or module) that pass filter() to - # a new Enum called name, and export the enum and its members back to - # module; - # also, replace the __reduce_ex__ method so unpickling works in - # previous Python versions - module_globals = vars(_sys.modules[module]) - if source: - source = vars(source) - else: - source = module_globals - members = [(key, source[key]) for key in source.keys() if filter(key)] - try: - # sort by value, name - members.sort(key=lambda t: (t[1], t[0])) - except TypeError: - # unless some values aren't comparable, in which case sort by just name - members.sort(key=lambda t: t[0]) - cls = cls(name, members, module=module, boundary=boundary or KEEP) - cls.__reduce_ex__ = _reduce_ex_by_name - if as_global: - global_enum(cls) - else: - module_globals.update(cls.__members__) - module_globals[name] = cls - return cls - - def _create_(cls, class_name, names, module=None, qualname=None, type=None, start=1, boundary=None): - """Convenience method to create a new Enum class. - - `names` can be: - - * A string containing member names, separated either with spaces or - commas. Values are auto-numbered from 1. - * An iterable of member names. Values are auto-numbered from 1. - * An iterable of (member name, value) pairs. - * A mapping of member name -> value. - """ - if PY2: - # if class_name is unicode, attempt a conversion to ASCII - if isinstance(class_name, unicode): - try: - class_name = class_name.encode('ascii') - except UnicodeEncodeError: - raise TypeError('%r is not representable in ASCII' % (class_name, )) - metacls = cls.__class__ - if type is None: - bases = (cls, ) - else: - bases = (type, cls) - _, first_enum = cls._get_mixins_(class_name, bases) - generate = getattr(first_enum, '_generate_next_value_', None) - generate = getattr(generate, 'im_func', generate) - # special processing needed for names? - if isinstance(names, basestring): - names = names.replace(',', ' ').split() - if isinstance(names, (tuple, list)) and names and isinstance(names[0], basestring): - original_names, names = names, [] - last_values = [] - for count, name in enumerate(original_names): - value = generate(name, start, count, last_values[:]) - last_values.append(value) - names.append((name, value)) - # Here, names is either an iterable of (name, value) or a mapping. - item = None # in case names is empty - clsdict = None - for item in names: - if clsdict is None: - # first time initialization - if isinstance(item, basestring): - clsdict = {} - else: - # remember the order - clsdict = metacls.__prepare__(class_name, bases) - if isinstance(item, basestring): - member_name, member_value = item, names[item] - else: - member_name, member_value = item - clsdict[member_name] = member_value - if clsdict is None: - # in case names was empty - clsdict = metacls.__prepare__(class_name, bases) - enum_class = metacls.__new__(metacls, class_name, bases, clsdict, boundary=boundary) - # TODO: replace the frame hack if a blessed way to know the calling - # module is ever developed - if module is None: - try: - module = _sys._getframe(2).f_globals['__name__'] - except (AttributeError, KeyError): - pass - if module is None: - _make_class_unpicklable(enum_class) - else: - enum_class.__module__ = module - if qualname is not None: - enum_class.__qualname__ = qualname - return enum_class - - @classmethod - def _check_for_existing_members_(mcls, class_name, bases): - if Enum is None: - return - for chain in bases: - for base in chain.__mro__: - if issubclass(base, Enum) and base._member_names_: - raise TypeError( - "<aenum %r> cannot extend %r" - % (class_name, base) - ) - @classmethod - def _get_mixins_(mcls, class_name, bases): - """Returns the type for creating enum members, and the first inherited - enum class. - - bases: the tuple of bases that was given to __new__ - """ - if not bases or Enum is None: - return object, Enum - - mcls._check_for_existing_members_(class_name, bases) - - # ensure final parent class is an Enum derivative, find any concrete - # data type, and check that Enum has no members - first_enum = bases[-1] - if not issubclass(first_enum, Enum): - raise TypeError("new enumerations should be created as " - "`EnumName([mixin_type, ...] [data_type,] enum_type)`") - member_type = mcls._find_data_type_(class_name, bases) or object - if first_enum._member_names_: - raise TypeError("cannot extend enumerations via subclassing") - # - return member_type, first_enum - - @classmethod - def _find_data_repr_(mcls, class_name, bases): - for chain in bases: - for base in chain.__mro__: - if base is object: - continue - elif issubclass(base, Enum): - # if we hit an Enum, use it's _value_repr_ - return base._value_repr_ - elif '__repr__' in base.__dict__: - # this is our data repr - return base.__dict__['__repr__'] - return None - - @classmethod - def _find_data_type_(mcls, class_name, bases): - data_types = set() - for chain in bases: - candidate = None - for base in chain.__mro__: - if base is object or base is StdlibEnum or base is StdlibFlag: - continue - elif issubclass(base, Enum): - if base._member_type_ is not object: - data_types.add(base._member_type_) - elif '__new__' in base.__dict__: - if issubclass(base, Enum): - continue - elif StdlibFlag is not None and issubclass(base, StdlibFlag): - continue - data_types.add(candidate or base) - break - else: - candidate = candidate or base - if len(data_types) > 1: - raise TypeError('%r: too many data types: %r' % (class_name, data_types)) - elif data_types: - return data_types.pop() - else: - return None - - @staticmethod - def _get_settings_(bases): - """Returns the combined _settings_ of all Enum base classes - - bases: the tuple of bases given to __new__ - """ - settings = set() - for chain in bases: - for base in chain.__mro__: - if issubclass(base, Enum): - for s in base._settings_: - settings.add(s) - return settings - - @classmethod - def _find_new_(mcls, clsdict, member_type, first_enum): - """Returns the __new__ to be used for creating the enum members. - - clsdict: the class dictionary given to __new__ - member_type: the data type whose __new__ will be used by default - first_enum: enumeration to check for an overriding __new__ - """ - # now find the correct __new__, checking to see of one was defined - # by the user; also check earlier enum classes in case a __new__ was - # saved as __new_member__ - __new__ = clsdict.get('__new__', None) - # - # should __new__ be saved as __new_member__ later? - save_new = first_enum is not None and __new__ is not None - # - if __new__ is None: - # check all possibles for __new_member__ before falling back to - # __new__ - for method in ('__new_member__', '__new__'): - for possible in (member_type, first_enum): - target = getattr(possible, method, None) - if target not in ( - None, - None.__new__, - object.__new__, - Enum.__new__, - StdlibEnum.__new__, - ): - __new__ = target - break - if __new__ is not None: - break - else: - __new__ = object.__new__ - # if a non-object.__new__ is used then whatever value/tuple was - # assigned to the enum member name will be passed to __new__ and to the - # new enum member's __init__ - if __new__ is object.__new__: - new_uses_args = False - else: - new_uses_args = True - # - return __new__, save_new, new_uses_args - - - # In order to support Python 2 and 3 with a single - # codebase we have to create the Enum methods separately - # and then use the `type(name, bases, dict)` method to - # create the class. - -EnumMeta = EnumType - -enum_dict = _Addendum( - dict=EnumType.__prepare__('Enum', (object, )), - doc="Generic enumeration.\n\n Derive from this class to define new enumerations.\n\n", - ns=globals(), - ) - -@enum_dict -def __init__(self, *args, **kwds): - # auto-init method - _auto_init_ = self._auto_init_ - if _auto_init_ is None: - return - if 'value' in _auto_init_: - # remove 'value' from _auto_init_ as it has already been handled - _auto_init_ = _auto_init_[1:] - if _auto_init_: - if len(_auto_init_) < len(args): - raise TypeError('%d arguments expected (%s), %d received (%s)' - % (len(_auto_init_), _auto_init_, len(args), args)) - for name, arg in zip(_auto_init_, args): - setattr(self, name, arg) - if len(args) < len(_auto_init_): - remaining_args = _auto_init_[len(args):] - for name in remaining_args: - value = kwds.pop(name, undefined) - if value is undefined: - raise TypeError('missing value for: %r' % (name, )) - setattr(self, name, value) - if kwds: - # too many keyword arguments - raise TypeError('invalid keyword(s): %s' % ', '.join(kwds.keys())) - -@enum_dict -def __new__(cls, value): - # all enum instances are actually created during class construction - # without calling this method; this method is called by the metaclass' - # __call__ (i.e. Color(3) ), and by pickle - if NoAlias in cls._settings_: - raise TypeError('NoAlias enumerations cannot be looked up by value') - if type(value) is cls: - # For lookups like Color(Color.red) - # value = value.value - return value - # by-value search for a matching enum member - # see if it's in the reverse mapping (for hashable values) - try: - if value in cls._value2member_map_: - return cls._value2member_map_[value] - except TypeError: - # not there, now do long search -- O(n) behavior - for name, member in cls._value2member_seq_: - if name == value: - return member - # still not found -- try _missing_ hook - try: - exc = None - result = cls._missing_value_(value) - except Exception as e: - exc = e - result = None - if isinstance(result, cls) or getattr(cls, '_boundary_', None) is EJECT: - return result - else: - if value is no_arg: - ve_exc = ValueError('%s() should be called with a value' % (cls.__name__, )) - else: - ve_exc = ValueError("%r is not a valid %s" % (value, cls.__name__)) - if result is None and exc is None: - raise ve_exc - elif exc is None: - exc = TypeError( - 'error in %s._missing_: returned %r instead of None or a valid member' - % (cls.__name__, result) - ) - if not isinstance(exc, ValueError): - exc.__cause__ = ve_exc - raise exc - -@enum_dict -@classmethod -def __init_subclass__(cls, **kwds): - if pyver < PY3_6: - # end of the line - if kwds: - raise TypeError('unconsumed keyword arguments: %r' % (kwds, )) - else: - super(Enum, cls).__init_subclass__(**kwds) - -@enum_dict -@staticmethod -def _generate_next_value_(name, start, count, last_values, *args, **kwds): - for last_value in reversed(last_values): - try: - new_value = last_value + 1 - break - except TypeError: - pass - else: - new_value = start - if args: - return (new_value, ) + args - else: - return new_value - -@enum_dict -@classmethod -def _missing_(cls, value): - "deprecated, use _missing_value_ instead" - return None - -@enum_dict -@classmethod -def _missing_value_(cls, value): - "used for failed value access" - return cls._missing_(value) - -@enum_dict -@classmethod -def _missing_name_(cls, name): - "used for failed item access" - return None - -@enum_dict -def __repr__(self): - v_repr = self.__class__._value_repr_ or self._value_.__class__.__repr__ - return "<%s.%s: %s>" % (self.__class__.__name__, self._name_, v_repr(self._value_)) - -@enum_dict -def __str__(self): - return "%s.%s" % (self.__class__.__name__, self._name_) - -if PY3: - @enum_dict - def __dir__(self): - """ - Returns all members and all public methods - """ - if self.__class__._member_type_ is object: - interesting = set(['__class__', '__doc__', '__eq__', '__hash__', '__module__', 'name', 'value']) - else: - interesting = set(object.__dir__(self)) - for name in getattr(self, '__dict__', []): - if name[0] != '_': - interesting.add(name) - for cls in self.__class__.mro(): - for name, obj in cls.__dict__.items(): - if name[0] == '_': - continue - if isinstance(obj, property): - # that's an enum.property - if obj.fget is not None or name not in self._member_map_: - interesting.add(name) - else: - # in case it was added by `dir(self)` - interesting.discard(name) - else: - interesting.add(name) - return sorted(interesting) - -@enum_dict -def __format__(self, format_spec): - # mixed-in Enums should use the mixed-in type's __format__, otherwise - # we can get strange results with the Enum name showing up instead of - # the value - - # pure Enum branch / overridden __str__ branch - overridden_str = self.__class__.__str__ != Enum.__str__ - if self._member_type_ is object or overridden_str: - cls = str - val = str(self) - # mix-in branch - else: - cls = self._member_type_ - val = self.value - return cls.__format__(val, format_spec) - -@enum_dict -def __hash__(self): - return hash(self._name_) - -@enum_dict -def __reduce_ex__(self, proto): - return self.__class__, (self._value_, ) - - -#################################### -# Python's less than 2.6 use __cmp__ - -if pyver < PY2_6: - - @enum_dict - def __cmp__(self, other): - if type(other) is self.__class__: - if self is other: - return 0 - return -1 - return NotImplemented - raise TypeError("unorderable types: %s() and %s()" % (self.__class__.__name__, other.__class__.__name__)) - -else: - - @enum_dict - def __le__(self, other): - raise TypeError("unorderable types: %s() <= %s()" % (self.__class__.__name__, other.__class__.__name__)) - - @enum_dict - def __lt__(self, other): - raise TypeError("unorderable types: %s() < %s()" % (self.__class__.__name__, other.__class__.__name__)) - - @enum_dict - def __ge__(self, other): - raise TypeError("unorderable types: %s() >= %s()" % (self.__class__.__name__, other.__class__.__name__)) - - @enum_dict - def __gt__(self, other): - raise TypeError("unorderable types: %s() > %s()" % (self.__class__.__name__, other.__class__.__name__)) - - -@enum_dict -def __eq__(self, other): - if type(other) is self.__class__: - return self is other - return NotImplemented - -@enum_dict -def __ne__(self, other): - if type(other) is self.__class__: - return self is not other - return NotImplemented - -@enum_dict -def __hash__(self): - return hash(self._name_) - -@enum_dict -def __reduce_ex__(self, proto): - return self.__class__, (self._value_, ) - - -# enum.property is used to provide access to the `name`, `value', etc., -# properties of enum members while keeping some measure of protection -# from modification, while still allowing for an enumeration to have -# members named `name`, `value`, etc.. This works because enumeration -# members are not set directly on the enum class -- enum.property will -# look them up in _member_map_. - -@enum_dict -@property -def name(self): - return self._name_ - -@enum_dict -@property -def value(self): - return self._value_ - -@enum_dict -@property -def values(self): - return self._values_ - -def _reduce_ex_by_name(self, proto): - return self.name - -Enum = EnumType('Enum', (object, ), enum_dict.resolve()) -del enum_dict - - # Enum has now been created - -class ReprEnum(Enum): - """ - Only changes the repr(), leaving str() and format() to the mixed-in type. - """ - - -class IntEnum(int, ReprEnum): - """ - Enum where members are also (and must be) ints - """ - - -class StrEnum(str, ReprEnum): - """ - Enum where members are also (and must already be) strings - - default value is member name, lower-cased - """ - - def __new__(cls, *values, **kwds): - if kwds: - raise TypeError('%r: keyword arguments not supported' % (cls.__name__)) - if values: - if not isinstance(values[0], str): - raise TypeError('%s: values must be str [%r is a %r]' % (cls.__name__, values[0], type(values[0]))) - value = str(*values) - member = str.__new__(cls, value) - member._value_ = value - return member - - __str__ = str.__str__ - - def _generate_next_value_(name, start, count, last_values): - """ - Return the lower-cased version of the member name. - """ - return name.lower() - - -class LowerStrEnum(StrEnum): - """ - Enum where members are also (and must already be) lower-case strings - - default value is member name, lower-cased - """ - - def __new__(cls, value, *args, **kwds): - obj = StrEnum.__new_member__(cls, value, *args, **kwds) - if value != value.lower(): - raise ValueError('%r is not lower-case' % value) - return obj - - -class UpperStrEnum(StrEnum): - """ - Enum where members are also (and must already be) upper-case strings - - default value is member name, upper-cased - """ - - def __new__(cls, value, *args, **kwds): - obj = StrEnum.__new_member__(cls, value, *args, **kwds) - if value != value.upper(): - raise ValueError('%r is not upper-case' % value) - return obj - - def _generate_next_value_(name, start, count, last_values, *args, **kwds): - return name.upper() - - -if PY3: - class AutoEnum(Enum): - """ - automatically use _generate_next_value_ when values are missing (Python 3 only) - """ - _settings_ = MagicValue - - -class AutoNumberEnum(Enum): - """ - Automatically assign increasing values to members. - - Py3: numbers match creation order - Py2: numbers are assigned alphabetically by member name - (unless `_order_` is specified) - """ - - def __new__(cls, *args, **kwds): - value = len(cls.__members__) + 1 - if cls._member_type_ is int: - obj = int.__new__(cls, value) - elif cls._member_type_ is long: - obj = long.__new__(cls, value) - else: - obj = object.__new__(cls) - obj._value_ = value - return obj - - -class AddValueEnum(Enum): - _settings_ = AddValue - - -class MultiValueEnum(Enum): - """ - Multiple values can map to each member. - """ - _settings_ = MultiValue - - -class NoAliasEnum(Enum): - """ - Duplicate value members are distinct, but cannot be looked up by value. - """ - _settings_ = NoAlias - - -class OrderedEnum(Enum): - """ - Add ordering based on values of Enum members. - """ - - def __ge__(self, other): - if self.__class__ is other.__class__: - return self._value_ >= other._value_ - return NotImplemented - - def __gt__(self, other): - if self.__class__ is other.__class__: - return self._value_ > other._value_ - return NotImplemented - - def __le__(self, other): - if self.__class__ is other.__class__: - return self._value_ <= other._value_ - return NotImplemented - - def __lt__(self, other): - if self.__class__ is other.__class__: - return self._value_ < other._value_ - return NotImplemented - - -if sqlite3: - class SqliteEnum(Enum): - def __conform__(self, protocol): - if protocol is sqlite3.PrepareProtocol: - return self.name - - -class UniqueEnum(Enum): - """ - Ensure no duplicate values exist. - """ - _settings_ = Unique - - -def convert(enum, name, module, filter, source=None): - """ - Create a new Enum subclass that replaces a collection of global constants - - enum: Enum, IntEnum, ... - name: name of new Enum - module: name of module (__name__ in global context) - filter: function that returns True if name should be converted to Enum member - source: namespace to check (defaults to 'module') - """ - # convert all constants from source (or module) that pass filter() to - # a new Enum called name, and export the enum and its members back to - # module; - # also, replace the __reduce_ex__ method so unpickling works in - # previous Python versions - module_globals = vars(_sys.modules[module]) - if source: - source = vars(source) - else: - source = module_globals - members = dict((name, value) for name, value in source.items() if filter(name)) - enum = enum(name, members, module=module) - enum.__reduce_ex__ = _reduce_ex_by_name - module_globals.update(enum.__members__) - module_globals[name] = enum - -def extend_enum(enumeration, name, *args, **kwds): - """ - Add a new member to an existing Enum. - """ - # there are four possibilities: - # - extending an aenum Enum or 3.11+ enum Enum - # - extending an aenum Flag or 3.11+ enum Flag - # - extending a pre-3.11 stdlib Enum Flag - # - extending a 3.11+ stdlib Flag - # - # fail early if name is already in the enumeration - if ( - name in enumeration.__dict__ - or name in enumeration._member_map_ - or name in [t[1] for t in getattr(enumeration, '_value2member_seq_', ())] - ): - raise TypeError('%r already in use as %r' % (name, enumeration.__dict__.get(name, enumeration[name]))) - # and check for other instances in parent classes - descriptor = None - for base in enumeration.__mro__[1:]: - descriptor = base.__dict__.get(name) - if descriptor is not None: - if isinstance(descriptor, (property, DynamicClassAttribute)): - break - else: - raise TypeError('%r already in use in superclass %r' % (name, base.__name__)) - try: - _member_map_ = enumeration._member_map_ - _member_names_ = enumeration._member_names_ - _member_type_ = enumeration._member_type_ - _value2member_map_ = enumeration._value2member_map_ - base_attributes = set([a for b in enumeration.mro() for a in b.__dict__]) - except AttributeError: - raise TypeError('%r is not a supported Enum' % (enumeration, )) - try: - _value2member_seq_ = enumeration._value2member_seq_ - _multi_value_ = MultiValue in enumeration._settings_ - _no_alias_ = NoAlias in enumeration._settings_ - _unique_ = Unique in enumeration._settings_ - _auto_init_ = enumeration._auto_init_ or [] - except AttributeError: - # standard Enum - _value2member_seq_ = [] - _multi_value_ = False - _no_alias_ = False - _unique_ = False - _auto_init_ = [] - if _multi_value_ and not args: - # must specify values for multivalue enums - raise ValueError('no values specified for MultiValue enum %r' % enumeration.__name__) - mt_new = _member_type_.__new__ - _new = getattr(enumeration, '__new_member__', mt_new) - if not args: - last_values = [m.value for m in enumeration] - count = len(enumeration) - start = getattr(enumeration, '_start_', None) - if start is None: - start = last_values and (last_values[-1] + 1) or 1 - _gnv = getattr(enumeration, '_generate_next_value_', None) - if _gnv is not None: - args = ( _gnv(name, start, count, last_values), ) - else: - # must be a 3.4 or 3.5 Enum - args = (start, ) - if _new is object.__new__: - new_uses_args = False - else: - new_uses_args = True - if len(args) == 1: - [value] = args - else: - value = args - more_values = () - kwds = {} - if isinstance(value, enum): - args = value.args - kwds = value.kwds - if not isinstance(value, tuple): - args = (value, ) - else: - args = value - # tease value out of auto-init if specified - if 'value' in _auto_init_: - if 'value' in kwds: - value = kwds.pop('value') - else: - value, args = args[0], args[1:] - elif _multi_value_: - value, more_values, args = args[0], args[1:], () - if new_uses_args: - args = (value, ) - if _member_type_ is tuple: - args = (args, ) - if not new_uses_args: - new_member = _new(enumeration) - if not hasattr(new_member, '_value_'): - new_member._value_ = value - else: - new_member = _new(enumeration, *args, **kwds) - if not hasattr(new_member, '_value_'): - new_member._value_ = _member_type_(*args) - value = new_member._value_ - if _multi_value_: - if 'value' in _auto_init_: - args = more_values - else: - # put all the values back into args for the init call - args = (value, ) + more_values - new_member._name_ = name - new_member.__objclass__ = enumeration.__class__ - new_member.__init__(*args) - new_member._values_ = (value, ) + more_values - # do final checks before modifying enum structures: - # - is new member a flag? - # - does the new member fit in the enum's declared _boundary_? - # - is new member an alias? - # - _all_bits_ = _flag_mask_ = None - if hasattr(enumeration, '_all_bits_'): - _all_bits_ = enumeration._all_bits_ | value - _flag_mask_ = enumeration._flag_mask_ | value - if enumeration._boundary_ != 'keep': - missed = list(_iter_bits_lsb(_flag_mask_ & ~_all_bits_)) - if missed: - raise TypeError( - 'invalid Flag %r -- missing values: %s' - % (cls, ', '.join((str(i) for i in missed))) - ) - # If another member with the same value was already defined, the - # new member becomes an alias to the existing one. - if _no_alias_: - # unless NoAlias was specified - return _finalize_extend_enum(enumeration, new_member, bits=_all_bits_, mask=_flag_mask_) - else: - # handle "normal" aliases - new_values = new_member._values_ - for canonical_member in _member_map_.values(): - canonical_values_ = getattr(canonical_member, '_values_', [canonical_member._value_]) - for canonical_value in canonical_values_: - for new_value in new_values: - if canonical_value == new_value: - # name is an alias - if _unique_ or _multi_value_: - # aliases not allowed in Unique and MultiValue enums - raise ValueError('%r is a duplicate of %r' % (new_member, canonical_member)) - else: - # aliased name can be added, remaining checks irrelevant - # aliases don't appear in member names (only in __members__ and _member_map_). - return _finalize_extend_enum(enumeration, canonical_member, name=name, bits=_all_bits_, mask=_flag_mask_, is_alias=True) - # not a standard alias, but maybe a flag alias - if pyver < PY3_6: - flag_bases = Flag, - else: - flag_bases = Flag, StdlibFlag - if issubclass(enumeration, flag_bases) and hasattr(enumeration, '_all_bits_'): - # handle the new flag type - if _is_single_bit(value): - # a new member! (an aliase would have been discovered in the previous loop) - return _finalize_extend_enum(enumeration, new_member, bits=_all_bits_, mask=_flag_mask_) - else: - # might be an 3.11 Flag alias - if value & enumeration._flag_mask_ == value and _value2member_map_.get(value) is not None: - # yup, it's an alias to existing members... and its an alias of an alias - canonical = _value2member_map_.get(value) - return _finalize_extend_enum(enumeration, canonical, name=name, bits=_all_bits_, mask=_flag_mask_, is_alias=True) - else: - return _finalize_extend_enum(enumeration, new_member, bits=_all_bits_, mask=_flag_mask_, is_alias=True) - else: - # if we get here, we have a brand new member - return _finalize_extend_enum(enumeration, new_member) - -def _finalize_extend_enum(enumeration, new_member, name=None, bits=None, mask=None, is_alias=False): - name = name or new_member.name - descriptor = None - for base in enumeration.__mro__[1:]: - descriptor = base.__dict__.get(name) - if descriptor is not None: - if isinstance(descriptor, (property, DynamicClassAttribute)): - break - else: - raise TypeError('%r already in use in superclass %r' % (name, base.__name__)) - if not descriptor: - # get redirect in place before adding to _member_map_ - redirect = property() - redirect.__set_name__(enumeration, name) - setattr(enumeration, name, redirect) - if not is_alias: - enumeration._member_names_.append(name) - enumeration._member_map_[name] = new_member - for v in getattr(new_member, '_values_', [new_member._value_]): - try: - enumeration._value2member_map_[v] = new_member - except TypeError: - enumeration._value2member_seq_ += ((v, new_member), ) - if bits: - enumeration._all_bits_ = bits - enumeration._flag_mask_ = mask - return new_member - -def unique(enumeration): - """ - Class decorator that ensures only unique members exist in an enumeration. - """ - duplicates = [] - for name, member in enumeration.__members__.items(): - if name != member.name: - duplicates.append((name, member.name)) - if duplicates: - duplicate_names = ', '.join( - ["%s -> %s" % (alias, name) for (alias, name) in duplicates] - ) - raise ValueError('duplicate names found in %r: %s' % - (enumeration, duplicate_names) - ) - return enumeration - -# Flag - -@export(globals()) -class FlagBoundary(StrEnum): - """ - control how out of range values are handled - "strict" -> error is raised [default] - "conform" -> extra bits are discarded - "eject" -> lose flag status (becomes a normal integer) - """ - STRICT = auto() - CONFORM = auto() - EJECT = auto() - KEEP = auto() -assert FlagBoundary.STRICT == 'strict', (FlagBoundary.STRICT, FlagBoundary.CONFORM) - -class Flag(Enum): - """ - Generic flag enumeration. - - Derive from this class to define new flag enumerations. - """ - - _boundary_ = STRICT - _numeric_repr_ = repr - - - def _generate_next_value_(name, start, count, last_values, *args, **kwds): - """ - Generate the next value when not given. - - name: the name of the member - start: the initital start value or None - count: the number of existing members - last_value: the last value assigned or None - """ - if not count: - if args: - return ((1, start)[start is not None], ) + args - else: - return (1, start)[start is not None] - else: - last_value = max(last_values) - try: - high_bit = _high_bit(last_value) - result = 2 ** (high_bit+1) - if args: - return (result,) + args - else: - return result - except Exception: - pass - raise TypeError('invalid Flag value: %r' % last_value) - - @classmethod - def _iter_member_by_value_(cls, value): - """ - Extract all members from the value in definition (i.e. increasing value) order. - """ - for val in _iter_bits_lsb(value & cls._flag_mask_): - yield cls._value2member_map_.get(val) - - _iter_member_ = _iter_member_by_value_ - - @classmethod - def _iter_member_by_def_(cls, value): - """ - Extract all members from the value in definition order. - """ - members = list(cls._iter_member_by_value_(value)) - members.sort(key=lambda m: m._sort_order_) - for member in members: - yield member - - @classmethod - def _missing_(cls, value): - """ - return a member matching the given value, or None - """ - return cls._create_pseudo_member_(value) - - @classmethod - def _create_pseudo_member_(cls, *values): - """ - Create a composite member. - """ - value = values[0] - if not isinstance(value, baseinteger): - raise ValueError( - "%r is not a valid %s" % (value, getattr(cls, '__qualname__', cls.__name__)) - ) - # check boundaries - # - value must be in range (e.g. -16 <-> +15, i.e. ~15 <-> 15) - # - value must not include any skipped flags (e.g. if bit 2 is not - # defined, then 0d10 is invalid) - neg_value = None - if ( - not ~cls._all_bits_ <= value <= cls._all_bits_ - or value & (cls._all_bits_ ^ cls._flag_mask_) - ): - if cls._boundary_ is STRICT: - max_bits = max(value.bit_length(), cls._flag_mask_.bit_length()) - raise ValueError( - "%s: invalid value: %r\n given %s\n allowed %s" - % (cls.__name__, value, bin(value, max_bits), bin(cls._flag_mask_, max_bits)) - ) - elif cls._boundary_ is CONFORM: - value = value & cls._flag_mask_ - elif cls._boundary_ is EJECT: - return value - elif cls._boundary_ is KEEP: - if value < 0: - value = ( - max(cls._all_bits_+1, 2**(value.bit_length())) - + value - ) - else: - raise ValueError( - 'unknown flag boundary: %r' % (cls._boundary_, ) - ) - if value < 0: - neg_value = value - value = cls._all_bits_ + 1 + value - # get members and unknown - unknown = value & ~cls._flag_mask_ - members = list(cls._iter_member_(value)) - if unknown and cls._boundary_ is not KEEP: - raise ValueError( - '%s(%r) --> unknown values %r [%s]' - % (cls.__name__, value, unknown, bin(unknown)) - ) - # let class adjust values - values = cls._create_pseudo_member_values_(members, *values) - __new__ = getattr(cls, '__new_member__', None) - if cls._member_type_ is object and not __new__: - # construct a singleton enum pseudo-member - pseudo_member = object.__new__(cls) - else: - pseudo_member = (__new__ or cls._member_type_.__new__)(cls, *values) - if not hasattr(pseudo_member, 'value'): - pseudo_member._value_ = value - if members: - pseudo_member._name_ = '|'.join([m._name_ for m in members]) - if unknown: - pseudo_member._name_ += '|%s' % cls._numeric_repr_(unknown) - else: - pseudo_member._name_ = None - # use setdefault in case another thread already created a composite - # with this value, but only if all members are known - # note: zero is a special case -- add it - if not unknown: - pseudo_member = cls._value2member_map_.setdefault(value, pseudo_member) - if neg_value is not None: - cls._value2member_map_[neg_value] = pseudo_member - return pseudo_member - - - @classmethod - def _create_pseudo_member_values_(cls, members, *values): - """ - Return values to be fed to __new__ to create new member. - """ - if cls._member_type_ in (baseinteger + (object, )): - return values - elif len(values) < 2: - return values + (cls._member_type_(), ) - else: - return values - - def __contains__(self, other): - """ - Returns True if self has at least the same flags set as other. - """ - if not isinstance(other, self.__class__): - raise TypeError( - "unsupported operand type(s) for 'in': '%s' and '%s'" % ( - type(other).__name__, self.__class__.__name__)) - if other._value_ == 0 or self._value_ == 0: - return False - return other._value_ & self._value_ == other._value_ - - def __iter__(self): - """ - Returns flags in definition order. - """ - for member in self._iter_member_(self._value_): - yield member - - def __len__(self): - return _bit_count(self._value_) - - def __repr__(self): - cls = self.__class__ - if self._name_ is None: - # only zero is unnamed by default - return '<%s: %r>' % (cls.__name__, self._value_) - else: - return '<%s.%s: %r>' % (cls.__name__, self._name_, self._value_) - - def __str__(self): - cls = self.__class__ - if self._name_ is None: - return '%s(%s)' % (cls.__name__, self._value_) - else: - return '%s.%s' % (cls.__name__, self._name_) - - if PY2: - def __nonzero__(self): - return bool(self._value_) - else: - def __bool__(self): - return bool(self._value_) - - def __or__(self, other): - if isinstance(other, self.__class__): - other_value = other._value_ - elif self._member_type_ is not object and isinstance(other, self._member_type_): - other_value = other - else: - return NotImplemented - return self.__class__(self._value_ | other_value) - - def __and__(self, other): - if isinstance(other, self.__class__): - other_value = other._value_ - elif self._member_type_ is not object and isinstance(other, self._member_type_): - other_value = other - else: - return NotImplemented - return self.__class__(self._value_ & other_value) - - def __xor__(self, other): - if isinstance(other, self.__class__): - other_value = other._value_ - elif self._member_type_ is not object and isinstance(other, self._member_type_): - other_value = other - else: - return NotImplemented - return self.__class__(self._value_ ^ other_value) - - def __invert__(self): - if self._inverted_ is None: - if self._boundary_ is KEEP: - # use all bits - self._inverted_ = self.__class__(~self._value_) - else: - # calculate flags not in this member - self._inverted_ = self.__class__(self._flag_mask_ ^ self._value_) - self._inverted_._inverted_ = self - return self._inverted_ - - __ror__ = __or__ - __rand__ = __and__ - __rxor__ = __xor__ - - - -class IntFlag(int, ReprEnum, Flag): - """Support for integer-based Flags""" - - _boundary_ = EJECT - - -def _high_bit(value): - """returns index of highest bit, or -1 if value is zero or negative""" - return value.bit_length() - 1 - -def global_enum_repr(self): - """ - use module.enum_name instead of class.enum_name - - the module is the last module in case of a multi-module name - """ - module = self.__class__.__module__.split('.')[-1] - return '%s.%s' % (module, self._name_) - -def global_flag_repr(self): - """ - use module.flag_name instead of class.flag_name - - the module is the last module in case of a multi-module name - """ - module = self.__class__.__module__.split('.')[-1] - cls_name = self.__class__.__name__ - if self._name_ is None: - return "%s.%s(%r)" % (module, cls_name, self._value_) - if _is_single_bit(self): - return '%s.%s' % (module, self._name_) - if self._boundary_ is not FlagBoundary.KEEP: - return '|'.join(['%s.%s' % (module, name) for name in self.name.split('|')]) - else: - name = [] - for n in self._name_.split('|'): - if n[0].isdigit(): - name.append(n) - else: - name.append('%s.%s' % (module, n)) - return '|'.join(name) - -def global_str(self): - """ - use enum_name instead of class.enum_name - """ - if self._name_ is None: - return "%s(%r)" % (cls_name, self._value_) - else: - return self._name_ - -def global_enum(cls, update_str=False): - """ - decorator that makes the repr() of an enum member reference its module - instead of its class; also exports all members to the enum's module's - global namespace - """ - if issubclass(cls, Flag): - cls.__repr__ = global_flag_repr - else: - cls.__repr__ = global_enum_repr - if not issubclass(cls, ReprEnum) or update_str: - cls.__str__ = global_str - _sys.modules[cls.__module__].__dict__.update(cls.__members__) - return cls - - -class module(object): - - def __init__(self, cls, *args): - self.__name__ = cls.__name__ - self._parent_module = cls.__module__ - self.__all__ = [] - all_objects = cls.__dict__ - if not args: - args = [k for k, v in all_objects.items() if isinstance(v, (NamedConstant, Enum))] - for name in args: - self.__dict__[name] = all_objects[name] - self.__all__.append(name) - - def register(self): - _sys.modules["%s.%s" % (self._parent_module, self.__name__)] = self - -if StdlibEnumMeta: - - from _weakrefset import WeakSet - - def __subclasscheck__(cls, subclass): - """ - Override for issubclass(subclass, cls). - """ - if not isinstance(subclass, type): - raise TypeError('issubclass() arg 1 must be a class (got %r)' % (subclass, )) - # Check cache - try: - cls.__dict__['_subclass_cache_'] - except KeyError: - cls._subclass_cache_ = WeakSet() - cls._subclass_negative_cache_ = WeakSet() - except RecursionError: - import sys - exc, cls, tb = sys.exc_info() - exc = RecursionError('possible causes for endless recursion:\n - __getattribute__ is not ignoring __dunder__ attibutes\n - __instancecheck__ and/or __subclasscheck_ are (mutually) recursive\n see `aenum.remove_stdlib_integration` for temporary work-around') - raise_from_none(exc) - if subclass in cls._subclass_cache_: - return True - # Check negative cache - elif subclass in cls._subclass_negative_cache_: - return False - if cls is subclass: - cls._subclass_cache_.add(subclass) - return True - # Check if it's a direct subclass - if cls in getattr(subclass, '__mro__', ()): - cls._subclass_cache_.add(subclass) - return True - # Check if it's an aenum.Enum|IntEnum|IntFlag|Flag subclass - if cls is StdlibIntFlag and issubclass(subclass, IntFlag): - cls._subclass_cache_.add(subclass) - return True - elif cls is StdlibFlag and issubclass(subclass, Flag): - cls._subclass_cache_.add(subclass) - return True - elif cls is StdlibIntEnum and issubclass(subclass, IntEnum): - cls._subclass_cache_.add(subclass) - return True - if cls is StdlibEnum and issubclass(subclass, Enum): - cls._subclass_cache_.add(subclass) - return True - # No dice; update negative cache - cls._subclass_negative_cache_.add(subclass) - return False - - def __instancecheck__(cls, instance): - subclass = instance.__class__ - try: - return cls.__subclasscheck__(subclass) - except RecursionError: - import sys - exc, cls, tb = sys.exc_info() - exc = RecursionError('possible causes for endless recursion:\n - __getattribute__ is not ignoring __dunder__ attibutes\n - __instancecheck__ and/or __subclasscheck_ are (mutually) recursive\n see `aenum.remove_stdlib_integration` for temporary work-around') - raise_from_none(exc) - - StdlibEnumMeta.__subclasscheck__ = __subclasscheck__ - StdlibEnumMeta.__instancecheck__ = __instancecheck__ - -def add_stdlib_integration(): - if StdlibEnum: - StdlibEnumMeta.__subclasscheck__ = __subclasscheck__ - StdlibEnumMeta.__instancecheck__ = __instancecheck__ - -def remove_stdlib_integration(): - """ - Remove the __instancecheck__ and __subclasscheck__ overrides from the stdlib Enum. - - Those overrides are in place so that code detecting stdlib enums will also detect - aenum enums. If a buggy __getattribute__, __instancecheck__, or __subclasscheck__ - is defined on a custom EnumMeta then RecursionErrors can result; using this - function after importing aenum will solve that problem, but the better solution is - to fix the buggy method. - """ - if StdlibEnum: - del StdlibEnumMeta.__instancecheck__ - del StdlibEnumMeta.__subclasscheck__ - |