aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--venv/Lib/site-packages/aenum/CHANGES489
-rw-r--r--venv/Lib/site-packages/aenum/LICENSE32
-rw-r--r--venv/Lib/site-packages/aenum/__init__.py4111
-rw-r--r--venv/Lib/site-packages/aenum/__pycache__/__init__.cpython-39.pycbin104964 -> 0 bytes
-rw-r--r--venv/Lib/site-packages/aenum/__pycache__/_py3.cpython-39.pycbin686 -> 0 bytes
-rw-r--r--venv/Lib/site-packages/aenum/_py2.py7
-rw-r--r--venv/Lib/site-packages/aenum/_py3.py12
-rw-r--r--venv/Lib/site-packages/aenum/doc/aenum.rst1568
-rw-r--r--venv/Lib/site-packages/aenum/test.py6832
-rw-r--r--venv/Lib/site-packages/aenum/test_v3.py1982
-rw-r--r--venv/Lib/site-packages/blendmodes/__init__.py2
-rw-r--r--venv/Lib/site-packages/blendmodes/__pycache__/__init__.cpython-39.pycbin285 -> 0 bytes
-rw-r--r--venv/Lib/site-packages/blendmodes/__pycache__/blend.cpython-39.pycbin13302 -> 0 bytes
-rw-r--r--venv/Lib/site-packages/blendmodes/__pycache__/blendtype.cpython-39.pycbin2850 -> 0 bytes
-rw-r--r--venv/Lib/site-packages/blendmodes/blend.py511
-rw-r--r--venv/Lib/site-packages/blendmodes/blendtype.py72
-rw-r--r--venv/Lib/site-packages/blendmodes/imagetools.py48
17 files changed, 0 insertions, 15666 deletions
diff --git a/venv/Lib/site-packages/aenum/CHANGES b/venv/Lib/site-packages/aenum/CHANGES
deleted file mode 100644
index e8799f6d..00000000
--- a/venv/Lib/site-packages/aenum/CHANGES
+++ /dev/null
@@ -1,489 +0,0 @@
-3.1.8
-=====
-
-recalculate bits used after all flags created (sometimes needed when a custom
-`__new__` is in place.
-
-
-3.1.7
-=====
-
-update flag creation to (possibly) add bitwise operator methods to newly
-created flags
-
-update extend_enum() to work with 3.11 flags
-
-
-3.1.6
-=====
-
-Update `dir()` on mixed enums to include mixed data type methods and
-attributes.
-
-Rename `enum_property` to `property` to match stdlib. Recommended usage is
-`aenum.property` (prefix with module name).
-
-Remove quadritic creation behavior.
-
-
-BREAKING CHANGE BUG FIX that won't affect most people
-
-Enums with a custom `__new__` that:
-
-- use the enum machinery to generate the values; AND
-- have keyword arguments set to a default (like `None`)
-
-will fail to generate a missing value. To fix: remove the default value and
-instead specify it on the member creation line.
-
-BREAKING CHANGE
-
-In Python 3.11 the `str()` of mixed enums will now match its `format()` which
-will be the normal `str()` of the data type -- so for an IntEnum you'll see
-`5` instead of `Perm.R|X`. This affects IntEnum, StrEnum, and IntFlag.
-
-
-3.1.5
-=====
-
-fix support of `auto()` kwds
-
-
-3.1.3
-=====
-
-rename `aenum.property` to `aenum.enum_property`
-
-fix `enum_property` to work with `_init_` attributes
-
-
-3.1.2
-=====
-
-fix `extend_enum()` for unhashable values
-
-
-3.1.1
-=====
-
-fix `extend_enum()` for most cases
-
-
-3.1.0
-=====
-
-AddValue is similar to the old AutoNumber: it will always activate, but
-uses _generate_next_value_ to get the next value (so the user has some
-control over the return data type instead of always getting an int).
-
-
-BREAKING CHANGES
-
-AutoValue is gone. It was superflous and its removal simplified the code.
-Simply put the fields needed in an `_init_` and `_generate_next_value_`
-will be called to supply the missing values (this is probably already what
-is happening).
-
-
-
-3.0.0
-=====
-
-standard Enum usage is unchanged
-
-BREAKING CHANGES
-
-Enum
-- the more esoteric method of creating Enums have been modified or removed
- - AutoNumber setting is gone, inherit from AutoNumberEnum instead
- - creating members without specifying anything is removed (if you don't
- know what this means, you weren't doing it)
-
-Flag
-- unique flags are canonical (i.e. flags with powers of two values such as
- 1, 2, 4, 8, 16, etc.)
-- non-unique flags are aliases (i.e. values such as 3 or 7)
-- iteration of Flag and flag members only uses canonical flags
-
-
-ENHANCEMENTS
-
-Member creation has been redone to match Python 3.10's methods. This also
-allows all supported Pythons (2.7, 3.3+) to use the __set_name__ and
-__init_subclass__ protocols (more robustly than in aenum 2.2.5)
-
-
-CHANGES
-
-enum_property() has been renamed to property() (old name still available, but
-deprecated).
-
-bin() replacement shows negative integers in twos-complement
-
-
-
-
-2.2.5
-=====
-
-call __init_subclass__ after members have been added, and in Pythons < 3.6
-call __set_name__ in Pythons < 3.6
-do not convert/disallow private names
-add iteration/len support to NamedConstant
-
-
-2.2.4
-=====
-
-add support to Constant to retrieve members by value
-
- --> class K(Constant):
- ... one = 1
- ... two = 2
-
- --> K.one
- <K.one: 1>
-
- --> K(1)
- <K.one: 1>
-
-add pickle/deepcopy support to Constant
-
-add support for Constant to use other Constant values
- (resulting members /are not/ the same)
-
- --> class C(Constant)
- ... one = K.one
- ... three = 3
-
- --> C.one == K.one
- True
-
- --> C.one is K.one
- False
-
-AutoNumber and auto() now work together
-
-Enum members are now added to the class as enum_property, which supports
-unshadowing of parent class attributes when called on an Enum member:
-
- --> class StrEnum(str, Enum):
- ... lower = 'lower'
- ... upper = 'upper'
- ... mixed = 'mixed'
-
- --> StrEnum.lower
- <StrEnum.lower: 'lower'>
-
- --> StrEnum.lower.upper()
- 'LOWER'
-
- --> StrEnum.upper
- <StrEnum.upper: 'upper'>
-
- --> StrEnum.upper.upper()
- 'UPPER'
-
-
-2.2.3
-=====
-
-use members' type's methods __str__, __repr__, __format__, and
-__reduce_ex__ if directly assigned in Enum class body; i.e.:
-
- --> class Color(str, Enum):
- ... red = 'red'
- ... green = 'green'
- ... blue = 'blue'
- ... __str__ = str.__str__
-
- --> print(repr(Color.green))
- <Color.green: 'green'>
-
- --> print(Color.green)
- green
-
-
-2.2.2
-=====
-
-replace _RouteClassAttributeToGetattr with enum_property (it is still
-available as an alias)
-
-support constant() and auto() being used together:
-
- --> class Fruit(Flag):
- ... _order_ = 'apple banana lemon orange'
- ... apple = auto()
- ... banana = auto()
- ... lemon = auto()
- ... orange = auto()
- ... CitrusTypes = constant(lemon | orange)
-
- --> list(Fruit)
- [Fruit.apple, Fruit.banana, Fruit.lemon, Fruit.orange]
-
- --> list(Fruit.CitrusTypes)
- [Fruit.orange, Fruit.lemon]
-
- --> Fruit.orange in Fruit.CitrusTypes
- True
-
-
-2.2.1
-=====
-
-allow Enums to be called without a value
-
- class Color(Enum):
- black = 0
- red = 1
- green = 2
- blue = 3
- #
- @classmethod
- def _missing_value_(cls, value):
- if value is no_arg:
- return cls.black
-
- >>> Color()
- <Color.black: 0>
-
-allow Enum name use while constructing Enum (Python 3.4+ only)
-
- --> class Color(Enum):
- ... _order_ = 'BLACK WHITE'
- ... BLACK = Color('black', '#000')
- ... WHITE = Color('white', '#fff')
- ... #
- ... def __init__(self, label, hex):
- ... self.label = label
- ... self.hex = hex
-
-
-2.2.0
-=====
-
-BREAKING CHANGE
----------------
-In Python 3+ classes defined inside an Enum no longer become members by
-default; in Python 2 they still become members, but see below.
-
-For cross-compatibility and full control two decorators are provided:
-
-- @member --> forces item to become a member
-- @nonmember --> excludes item from becoming a member
-
-So to have an Enum that behaves the same in Python 2 and 3, use the
-decorators (and other compatibility shims):
-
- class Color(Enum):
-
- _order_ = 'red green blue'
-
- red = 1
- green = 2
- blue = 3
-
- @nonmember
- class Shades(Enum):
-
- _order_ = 'light medium dark'
-
- light = 1
- medium = 2
- dark = 3
-
-
-2.1.4
-=====
-
-EnumMeta:
-- change __member_new__ to __new_member__ (as the stdlib enum does)
-- assign member name to enum() instances (an Enum helper for defining members)
-- handle empty iterables when using functional API
-- make auto() work with previous enum members
-- keep searching mixins until base class is found
-
-Enum:
-- fix bug in Flag checks (ensure it is a Flag before checking the name)
-- add multiple mixin support
-- do not allow blank names (functional API)
-- raise TypeError if _missing_* returns wrong type
-- fix __format__ to honor custom __str__
-
-extend_enum:
-- support stdlib Enums
-- use _generate_next_value_ if value not provided
-
-general:
-- standardize exception formatting
-- use getfullargspec() in Python 3 (avoids deprecation warnings)
-
-
-2.1.2
-=====
-
-when order is callable, save it for subclass use
-
-
-2.1.1
-=====
-
-correctly raise TypeError for non-Enum containment checks
-support combining names with | for Flag key access
-support _order_ being a callable
-
-
-2.1.0
-=====
-
-support Flags being combined with other data types:
-- add _create_pseudo_member_values_
-- add default __new__ and temporary _init_
-
-
-2.0.10
-======
-
-ensure _ignore_ is set when _settings_ specified in body which includes
-AutoValue
-
-make Flag members iterable
-
-
-2.0.9
-=====
-
-fix missing comma in __all__
-fix extend_enum with custom __new__ methods
-fix MultiValue with AutoNumber without _init_
-
-
-2.0.8
-=====
-
-extend_enum now handles aliases and multivalues correctly
-
-
-2.0.7
-=====
-
-support mixin types with extend_enum
-init and AutoNumber can now work together
-add test for new Enum using EnumMeta
-add tests for variations of multivalue and init
-prevent deletion of NamedConstant.constant
-
-
-2.0.6
-=====
-
-constants cannot be deleted (they already couldn't be changed)
-constants can be used to define other constants
-
-
-2.0.5
-=====
-
-_init_ and MultiValue can now work together
-
-
-2.0.4
-=====
-
-_init_ and AutoValue (and _generate_next_value_) can now work together to
-supply missing values even when some of the required values per member are
-absent
-
-
-2.0.3
-=====
-
-add _missing_value_ and _missing_name_ methods, deprecate _missing_
-make enum instances comparable
-
-
-2.0.2
-=====
-
-both EnumMeta.__getattr__ and Enum.__new__ fall back to _missing_
-
-
-2.0.1
-=====
-
-auto() now works with other data types
-AutoNumber supports legacy Enums (fixed regression)
-
-
-2.0.0
-=====
-
-Flag and IntFlag added.
-
-
-1.4.7
-=====
-
-fix %-interpolation bug
-defined SqlLiteEnum only if sqlite exists
-support pyflakes
-
-
-1.4.6
-=====
-
-version numbering error
-
-
-1.4.5
-=====
-
-revert AutoNumberEnum to custom __new__ instead of AutoNumber
-use _ignore_ to shield against AutoNumber magic
-inherit start and init settings from base Enums
-
-
-1.4.4
-=====
-
-enabled export as a decorator
-enabled _order_ to replace __order__
-enabled python2 support for settings, init, and start
-
-
-1.4.3
-=====
-
-support _ignore_ for dynamically creating class bodies
-
-
-1.4.2
-=====
-
-MultiValue, NoAlias, Unique, and init now work with Python 2
-
-
-1.4.1
-=====
-
-Py3: added Enum creation flags: Auto, MultiValue, NoAlias, Unique
-
-fixed extend_enum to honor Enum flags
-
-
-1.4.0
-=====
-
-When possible aenum inherits from Python's own enum.
-
-Breaking change: enum members now default to evaluating as True to maintain
-compatibility with the stdlib.
-
-Add your own __bool__ (__nonzero__ in Python 2) if need this behavior:
-
- def __bool__(self):
- return bool(self.value)
- __nonzero__ = __bool__
-
diff --git a/venv/Lib/site-packages/aenum/LICENSE b/venv/Lib/site-packages/aenum/LICENSE
deleted file mode 100644
index b20361ce..00000000
--- a/venv/Lib/site-packages/aenum/LICENSE
+++ /dev/null
@@ -1,32 +0,0 @@
-Copyright (c) 2015, 2016, 2017, 2018 Ethan Furman.
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-
- Redistributions of source code must retain the above
- copyright notice, this list of conditions and the
- following disclaimer.
-
- Redistributions in binary form must reproduce the above
- copyright notice, this list of conditions and the following
- disclaimer in the documentation and/or other materials
- provided with the distribution.
-
- Neither the name Ethan Furman nor the names of any
- contributors may be used to endorse or promote products
- derived from this software without specific prior written
- permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
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__
-
diff --git a/venv/Lib/site-packages/aenum/__pycache__/__init__.cpython-39.pyc b/venv/Lib/site-packages/aenum/__pycache__/__init__.cpython-39.pyc
deleted file mode 100644
index 176f78e2..00000000
--- a/venv/Lib/site-packages/aenum/__pycache__/__init__.cpython-39.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/Lib/site-packages/aenum/__pycache__/_py3.cpython-39.pyc b/venv/Lib/site-packages/aenum/__pycache__/_py3.cpython-39.pyc
deleted file mode 100644
index c289c1bf..00000000
--- a/venv/Lib/site-packages/aenum/__pycache__/_py3.cpython-39.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/Lib/site-packages/aenum/_py2.py b/venv/Lib/site-packages/aenum/_py2.py
deleted file mode 100644
index a6e7b290..00000000
--- a/venv/Lib/site-packages/aenum/_py2.py
+++ /dev/null
@@ -1,7 +0,0 @@
-from operator import div as _div_
-from inspect import getargspec
-
-def raise_with_traceback(exc, tb):
- raise exc, None, tb
-
-__all__ = ['_div_', 'getargspec', 'raise_with_traceback']
diff --git a/venv/Lib/site-packages/aenum/_py3.py b/venv/Lib/site-packages/aenum/_py3.py
deleted file mode 100644
index 2edeefdf..00000000
--- a/venv/Lib/site-packages/aenum/_py3.py
+++ /dev/null
@@ -1,12 +0,0 @@
-from inspect import getfullargspec as _getfullargspec
-
-def getargspec(method):
- args, varargs, keywords, defaults, _, _, _ = _getfullargspec(method)
- return args, varargs, keywords, defaults
-
-def raise_with_traceback(exc, tb):
- raise exc.with_traceback(tb)
-
-def raise_from_none(exc):
- raise exc from None
-
diff --git a/venv/Lib/site-packages/aenum/doc/aenum.rst b/venv/Lib/site-packages/aenum/doc/aenum.rst
deleted file mode 100644
index 42ef0d3c..00000000
--- a/venv/Lib/site-packages/aenum/doc/aenum.rst
+++ /dev/null
@@ -1,1568 +0,0 @@
-``aenum`` --- support for advanced enumerations, namedtuples, and constants
-===========================================================================
-
-.. :synopsis:: enumerations are sets of symbolic names bound to unique,
- constant values; namedtuples are fixed- or variable-length
- tuples with the positions addressable by field name as well as by index;
- constants are classes of named constants that cannot be rebound.
-.. :moduleauthor:: Ethan Furman <ethan@stoneleaf.us>
-
-----------------
-
-An ``Enum`` is a set of symbolic names (members) bound to unique, constant
-values. Within an enumeration, the members can be compared by identity, and
-the enumeration itself can be iterated over.
-
-A ``NamedTuple`` is a class-based, fixed-length tuple with a name for each
-possible position accessible using attribute-access notation.
-
-A ``NamedConstant`` is a class whose members cannot be rebound; it lacks all
-other ``Enum`` capabilities, however; consequently, it can have duplicate
-values. There is also a ``module`` function that can insert the
-``NamedConstant`` class into ``sys.modules`` where it will appear to be a
-module whose top-level names cannot be rebound.
-
-.. note::
- ``constant`` refers to names not being rebound; mutable objects can be
- mutated.
-
-
-Module Contents
----------------
-
-This module defines five enumeration classes that can be used to define unique
-sets of names and values, one ``Enum`` class decorator, one ``NamedTuple``
-class, one ``NamedConstant`` class, and several helpers.
-
-``NamedConstant``
-
-NamedConstant class for creating groups of constants. These names cannot be
-rebound to other values.
-
-``Enum``
-
-Base class for creating enumerated constants. See section `Enum Functional API`_
-for an alternate construction syntax.
-
-``AddValue``
-
-Flag specifying that ``_generate_next_value_`` should always be called to
-provide the initial value for an enum member.
-
-``MultiValue``
-
-Flag specifying that each item of tuple value is a separate value for that
-member; the first tuple item is the canonical one.
-
-``NoAlias``
-
-Flag specifying that duplicate valued members are distinct and not aliases;
-by-value lookups are disabled.
-
-``Unique``
-
-Flag specifying that duplicate valued members are not allowed.
-
-.. note::
- The flags are inherited by the enumeration's subclasses. To use them in
- Python 2 assign to ``_settings_`` in the class body.
-
-``IntEnum``
-
-Base class for creating enumerated constants that are also subclasses of ``int``.
-
-``AutoNumberEnum``
-
-Derived class that automatically assigns an ``int`` value to each member.
-
-``OrderedEnum``
-
-Derived class that adds ``<``, ``<=``, ``>=``, and ``>`` methods to an ``Enum``.
-
-``UniqueEnum``
-
-Derived class that ensures only one name is bound to any one value.
-
-``unique``
-
-Enum class decorator that ensures only one name is bound to any one value.
-
-.. note::
-
- the ``UniqueEnum`` class, the ``unique`` decorator, and the Unique
- flag all do the same thing; you do not need to use more than one of
- them at the same time.
-
-``NamedTuple``
-
-Base class for `creating NamedTuples`_, either by subclassing or via it's
-functional API.
-
-``constant``
-
-Descriptor to add constant values to an ``Enum``, or advanced constants to
-``NamedConstant``.
-
-``convert``
-
-Helper to transform target global variables into an ``Enum``.
-
-``enum``
-
-Helper for specifying keyword arguments when creating ``Enum`` members.
-
-``export``
-
-Helper for inserting ``Enum`` members and ``NamedConstant`` constants into a
-namespace (usually ``globals()``.
-
-``extend_enum``
-
-Helper for adding new ``Enum`` members, both stdlib and aenum.
-
-``module``
-
-Function to take a ``NamedConstant`` or ``Enum`` class and insert it into
-``sys.modules`` with the affect of a module whose top-level constant and
-member names cannot be rebound.
-
-``skip``
-
-Descriptor to add a normal (non-``Enum`` member) attribute to an ``Enum``
-or ``NamedConstant``.
-
-
-Creating an Enum
-----------------
-
-Enumerations are created using the ``class`` syntax, which makes them
-easy to read and write. An alternative creation method is described in
-`Enum Functional API`_. To define an enumeration, subclass ``Enum`` as
-follows::
-
- >>> from aenum import Enum
- >>> class Color(Enum):
- ... red = 1
- ... green = 2
- ... blue = 3
-
-*Nomenclature*
-
- - The class ``Color`` is an *enumeration* (or *enum*)
- - The attributes ``Color.red``, ``Color.green``, etc., are
- *enumeration members* (or *enum members*).
- - The enum members have *names* and *values* (the name of
- ``Color.red`` is ``red``, the value of ``Color.blue`` is
- ``3``, etc.)
-
-.. note::
-
- Even though we use the ``class`` syntax to create Enums, Enums
- are not normal Python classes. See `How are Enums different?`_ for
- more details.
-
-Enumeration members have human readable string representations::
-
- >>> print(Color.red)
- Color.red
-
-...while their ``repr`` has more information::
-
- >>> print(repr(Color.red))
- <Color.red: 1>
-
-The *type* of an enumeration member is the enumeration it belongs to::
-
- >>> type(Color.red)
- <aenum 'Color'>
- >>> isinstance(Color.green, Color)
- True
-
-Enumerations support iteration. In Python 3.x definition order is used; in
-Python 2.x the definition order is not available, but class attribute
-``_order_`` is supported; otherwise, value order is used if posible,
-otherwise alphabetical name order is used::
-
- >>> class Shake(Enum):
- ... _order_ = 'vanilla chocolate cookies mint' # only needed in 2.x
- ... vanilla = 7
- ... chocolate = 4
- ... cookies = 9
- ... mint = 3
- ...
- >>> for shake in Shake:
- ... print(shake)
- ...
- Shake.vanilla
- Shake.chocolate
- Shake.cookies
- Shake.mint
-
-The ``_order_`` attribute is always removed, but in 3.x it is also used to
-verify that definition order is the same (useful for py2&3 code bases);
-however, in the stdlib version it will be ignored and not removed.
-
-.. note::
-
- To maintain compatibility with Python 3.4 and 3.5, use __order__
- instead (double leading and trailing underscores).
-
-Enumeration members are hashable, so they can be used in dictionaries and sets::
-
- >>> apples = {}
- >>> apples[Color.red] = 'red delicious'
- >>> apples[Color.green] = 'granny smith'
- >>> apples == {Color.red: 'red delicious', Color.green: 'granny smith'}
- True
-
-In Python 3 the class syntax has a few extra advancements::
-
- --> class Color(
- ... Enum,
- ... settings=(AddValue, MultiValue, NoAlias, Unique),
- ... init='field_name1 field_name2 ...',
- ... start=7,
- ... )
- ...
-
-``start`` is used to specify the starting value for the first member::
-
- --> class Count(Enum, start=11):
- ... eleven
- ... twelve
- ...
- --> Count.twelve.value == 12
- True
-
-``init`` specifies the attribute names to store creation values to::
-
- --> class Planet(Enum, init='mass radius'):
- ... MERCURY = (3.303e+23, 2.4397e6)
- ... EARTH = (5.976e+24, 6.37814e6)
- ...
- --> Planet.EARTH.value
- (5.976e+24, 6378140.0)
- --> Planet.EARTH.radius
- 2.4397e6
-
-The various settings enable special behavior:
-
-- ``AddValue`` calls a user supplied ``_generate_next_value_`` to provide
- the initial value
-- ``MultiValue`` allows multiple values per member instead of the usual 1
-- ``NoAlias`` allows different members to have the same value
-- ``Unique`` disallows different members to have the same value
-
-.. note::
-
- To use these features in Python 2 use the _sundered_ versions of
- the names in the class body: ``_start_``, ``_init_``, ``_settings_``.
-
-
-Programmatic access to enumeration members and their attributes
----------------------------------------------------------------
-
-Sometimes it's useful to access members in enumerations programmatically (i.e.
-situations where ``Color.red`` won't do because the exact color is not known
-at program-writing time). ``Enum`` allows such access::
-
- >>> Color(1)
- <Color.red: 1>
- >>> Color(3)
- <Color.blue: 3>
-
-If you want to access enum members by *name*, use item access::
-
- >>> Color['red']
- <Color.red: 1>
- >>> Color['green']
- <Color.green: 2>
-
-If have an enum member and need its ``name`` or ``value``::
-
- >>> member = Color.red
- >>> member.name
- 'red'
- >>> member.value
- 1
-
-
-Duplicating enum members and values
------------------------------------
-
-Having two enum members (or any other attribute) with the same name is invalid;
-in Python 3.x this would raise an error, but in Python 2.x the second member
-simply overwrites the first::
-
- # python 2.x
- --> class Shape(Enum):
- ... square = 2
- ... square = 3
- ...
- --> Shape.square
- <Shape.square: 3>
-
- # python 3.x
- --> class Shape(Enum):
- ... square = 2
- ... square = 3
- Traceback (most recent call last):
- ...
- TypeError: Attempted to reuse key: 'square'
-
-However, two enum members are allowed to have the same value. Given two members
-A and B with the same value (and A defined first), B is an alias to A. By-value
-lookup of the value of A and B will return A. By-name lookup of B will also
-return A::
-
- >>> class Shape(Enum):
- ... _order_ = 'square diamond circle' # needed in 2.x
- ... square = 2
- ... diamond = 1
- ... circle = 3
- ... alias_for_square = 2
- ...
- >>> Shape.square
- <Shape.square: 2>
- >>> Shape.alias_for_square
- <Shape.square: 2>
- >>> Shape(2)
- <Shape.square: 2>
-
-
-Allowing aliases is not always desirable. ``unique`` can be used to ensure
-that none exist in a particular enumeration::
-
- >>> from aenum import unique
- >>> @unique
- ... class Mistake(Enum):
- ... _order_ = 'one two three' # only needed in 2.x
- ... one = 1
- ... two = 2
- ... three = 3
- ... four = 3
- Traceback (most recent call last):
- ...
- ValueError: duplicate names found in <aenum 'Mistake'>: four -> three
-
-Iterating over the members of an enum does not provide the aliases::
-
- >>> list(Shape)
- [<Shape.square: 2>, <Shape.diamond: 1>, <Shape.circle: 3>]
-
-The special attribute ``__members__`` is a dictionary mapping names to members.
-It includes all names defined in the enumeration, including the aliases::
-
- >>> for name, member in sorted(Shape.__members__.items()):
- ... name, member
- ...
- ('alias_for_square', <Shape.square: 2>)
- ('circle', <Shape.circle: 3>)
- ('diamond', <Shape.diamond: 1>)
- ('square', <Shape.square: 2>)
-
-The ``__members__`` attribute can be used for detailed programmatic access to
-the enumeration members. For example, finding all the aliases::
-
- >>> [n for n, mbr in Shape.__members__.items() if mbr.name != n]
- ['alias_for_square']
-
-Comparisons
------------
-
-Enumeration members are compared by identity::
-
- >>> Color.red is Color.red
- True
- >>> Color.red is Color.blue
- False
- >>> Color.red is not Color.blue
- True
-
-Ordered comparisons between enumeration values are *not* supported. Enum
-members are not integers (but see `IntEnum`_ below)::
-
- >>> Color.red < Color.blue
- Traceback (most recent call last):
- File "<stdin>", line 1, in <module>
- TypeError: unorderable types: Color() < Color()
-
-.. warning::
-
- In Python 2 *everything* is ordered, even though the ordering may not
- make sense. If you want your enumerations to have a sensible ordering
- consider using an `OrderedEnum`_.
-
-
-Equality comparisons are defined though::
-
- >>> Color.blue == Color.red
- False
- >>> Color.blue != Color.red
- True
- >>> Color.blue == Color.blue
- True
-
-Comparisons against non-enumeration values will always compare not equal
-(again, ``IntEnum`` was explicitly designed to behave differently, see
-below)::
-
- >>> Color.blue == 2
- False
-
-
-Allowed members and attributes of enumerations
-----------------------------------------------
-
-The examples above use integers for enumeration values. Using integers is
-short and handy (and provided by default by the `Enum Functional API`_), but not
-strictly enforced. In the vast majority of use-cases, one doesn't care what
-the actual value of an enumeration is. But if the value *is* important,
-enumerations can have arbitrary values.
-
-Enumerations are Python classes, and can have methods and special methods as
-usual. If we have this enumeration::
-
- >>> class Mood(Enum):
- ... funky = 1
- ... happy = 3
- ...
- ... def describe(self):
- ... # self is the member here
- ... return self.name, self.value
- ...
- ... def __str__(self):
- ... return 'my custom str! {0}'.format(self.value)
- ...
- ... @classmethod
- ... def favorite_mood(cls):
- ... # cls here is the enumeration
- ... return cls.happy
-
-Then::
-
- >>> Mood.favorite_mood()
- <Mood.happy: 3>
- >>> Mood.happy.describe()
- ('happy', 3)
- >>> str(Mood.funky)
- 'my custom str! 1'
-
-The rules for what is allowed are as follows: _sunder_ names (starting and
-ending with a single underscore) are reserved by enum and cannot be used;
-all other attributes defined within an enumeration will become members of this
-enumeration, with the exception of *__dunder__* names and descriptors (methods
-are also descriptors).
-
-.. note::
-
- If your enumeration defines ``__new__`` and/or ``__init__`` then
- whatever value(s) were given to the enum member will be passed into
- those methods. See `Planet`_ for an example.
-
-
-Restricted Enum subclassing
----------------------------
-
-A new `Enum` class must have one base Enum class, up to one concrete
-data type, and as many `object`-based mixin classes as needed. The
-order of these base classes is::
-
- def EnumName([mix-in, ...,] [data-type,] base-enum):
- pass
-
-Also, subclassing an enumeration is allowed only if the enumeration does not define
-
-any members. So this is forbidden::
-
- >>> class MoreColor(Color):
- ... pink = 17
- Traceback (most recent call last):
- ...
- TypeError: <aenum 'MoreColor'> cannot extend <aenum 'Color'>
-
-But this is allowed::
-
- >>> class Foo(Enum):
- ... def some_behavior(self):
- ... pass
- ...
- >>> class Bar(Foo):
- ... happy = 1
- ... sad = 2
- ...
-
-Allowing subclassing of enums that define members would lead to a violation of
-some important invariants of types and instances. On the other hand, it makes
-sense to allow sharing some common behavior between a group of enumerations.
-(See `OrderedEnum`_ for an example.)
-
-
-Pickling
---------
-
-Enumerations can be pickled and unpickled::
-
- >>> from aenum.test import Fruit
- >>> from pickle import dumps, loads
- >>> Fruit.tomato is loads(dumps(Fruit.tomato, 2))
- True
-
-The usual restrictions for pickling apply: picklable enums must be defined in
-the top level of a module, since unpickling requires them to be importable
-from that module.
-
-.. note::
-
- With pickle protocol version 4 (introduced in Python 3.4) it is possible
- to easily pickle enums nested in other classes.
-
-
-
-Enum Functional API
--------------------
-
-The ``Enum`` class is callable, providing the following functional API::
-
- >>> Animal = Enum('Animal', 'ant bee cat dog')
- >>> Animal
- <aenum 'Animal'>
- >>> Animal.ant
- <Animal.ant: 1>
- >>> Animal.ant.value
- 1
- >>> list(Animal)
- [<Animal.ant: 1>, <Animal.bee: 2>, <Animal.cat: 3>, <Animal.dog: 4>]
-
-The semantics of this API resemble ``namedtuple``. The first argument
-of the call to ``Enum`` is the name of the enumeration.
-
-The second argument is the *source* of enumeration member names. It can be a
-whitespace-separated string of names, a sequence of names, a sequence of
-2-tuples with key/value pairs, or a mapping (e.g. dictionary) of names to
-values. The last two options enable assigning arbitrary values to
-enumerations; the others auto-assign increasing integers starting with 1. A
-new class derived from ``Enum`` is returned. In other words, the above
-assignment to ``Animal`` is equivalent to::
-
- >>> class Animals(Enum):
- ... ant = 1
- ... bee = 2
- ... cat = 3
- ... dog = 4
-
-Pickling enums created with the functional API can be tricky as frame stack
-implementation details are used to try and figure out which module the
-enumeration is being created in (e.g. it will fail if you use a utility
-function in separate module, and also may not work on IronPython or Jython).
-The solution is to specify the module name explicitly as follows::
-
- >>> Animals = Enum('Animals', 'ant bee cat dog', module=__name__)
-
-Derived Enumerations
---------------------
-
-IntEnum
-^^^^^^^
-
-A variation of ``Enum`` is provided which is also a subclass of
-``int``. Members of an ``IntEnum`` can be compared to integers;
-by extension, integer enumerations of different types can also be compared
-to each other::
-
- >>> from aenum import IntEnum
- >>> class Shape(IntEnum):
- ... circle = 1
- ... square = 2
- ...
- >>> class Request(IntEnum):
- ... post = 1
- ... get = 2
- ...
- >>> Shape == 1
- False
- >>> Shape.circle == 1
- True
- >>> Shape.circle == Request.post
- True
-
-However, they still can't be compared to standard ``Enum`` enumerations::
-
- >>> class Shape(IntEnum):
- ... circle = 1
- ... square = 2
- ...
- >>> class Color(Enum):
- ... red = 1
- ... green = 2
- ...
- >>> Shape.circle == Color.red
- False
-
-``IntEnum`` values behave like integers in other ways you'd expect::
-
- >>> int(Shape.circle)
- 1
- >>> ['a', 'b', 'c'][Shape.circle]
- 'b'
- >>> [i for i in range(Shape.square)]
- [0, 1]
-
-For the vast majority of code, ``Enum`` is strongly recommended,
-since ``IntEnum`` breaks some semantic promises of an enumeration (by
-being comparable to integers, and thus by transitivity to other
-unrelated enumerations). It should be used only in special cases where
-there's no other choice; for example, when integer constants are
-replaced with enumerations and backwards compatibility is required with code
-that still expects integers.
-
-
-IntFlag
-^^^^^^^
-
-The next variation of ``Enum`` provided, ``IntFlag``, is also based
-on ``int``. The difference being ``IntFlag`` members can be combined
-using the bitwise operators (&, \|, ^, ~) and the result is still an
-``IntFlag`` member. However, as the name implies, ``IntFlag``
-members also subclass ``int`` and can be used wherever an ``int`` is
-used. Any operation on an ``IntFlag`` member besides the bit-wise
-operations will lose the ``IntFlag`` membership.
-
-Sample ``IntFlag`` class::
-
- >>> from aenum import IntFlag
- >>> class Perm(IntFlag):
- ... _order_ = 'R W X'
- ... R = 4
- ... W = 2
- ... X = 1
- ...
- >>> Perm.R | Perm.W
- <Perm.R|W: 6>
- >>> Perm.R + Perm.W
- 6
- >>> RW = Perm.R | Perm.W
- >>> Perm.R in RW
- True
-
-It is also possible to name the combinations::
-
- >>> class Perm(IntFlag):
- ... _order_ = 'R W X'
- ... R = 4
- ... W = 2
- ... X = 1
- ... RWX = 7
- >>> Perm.RWX
- <Perm.RWX: 7>
- >>> ~Perm.RWX
- <Perm: 0>
-
-Another important difference between ``IntFlag`` and ``Enum`` is that
-if no flags are set (the value is 0), its boolean evaluation is ``False``::
-
- >>> Perm.R & Perm.X
- <Perm: 0>
- >>> bool(Perm.R & Perm.X)
- False
-
-Because ``IntFlag`` members are also subclasses of ``int`` they can
-be combined with them::
-
- >>> Perm.X | 4
- <Perm.R|X: 5>
-
-If the result is not a ``Flag`` then, depending on the ``_boundary_`` setting,
-an exception is raised (``STRICT``), the extra bits are lost (``CONFORM``), or
-it reverts to an int (``EJECT``):
-
- >>> from aenum import STRICT, CONFORM, EJECT
- >>> Perm._boundary_ = STRICT
- >>> Perm.X | 8
- Traceback (most recent call last):
- ...
- ValueError: Perm: invalid value: 9
- given 0b0 1001
- allowed 0b0 0111
-
- >>> Perm._boundary_ = EJECT
- >>> Perm.X | 8
- 9
-
- >>> Perm._boundary_ = CONFORM
- >>> Perm.X | 8
- <Perm.X: 1>
-
-
-Flag
-^^^^
-
-The last variation is ``Flag``. Like ``IntFlag``, ``Flag``
-members can be combined using the bitwise operators (&, \|, ^, ~). Unlike
-``IntFlag``, they cannot be combined with, nor compared against, any
-other ``Flag`` enumeration, nor ``int``. While it is possible to
-specify the values directly it is recommended to use ``auto`` as the
-value and let ``Flag`` select an appropriate value.
-
-Like ``IntFlag``, if a combination of ``Flag`` members results in no
-flags being set, the boolean evaluation is ``False``::
-
- >>> from aenum import Flag, auto
- >>> class Color(Flag):
- ... RED = auto()
- ... BLUE = auto()
- ... GREEN = auto()
- ...
- >>> Color.RED & Color.GREEN
- <Color: 0>
- >>> bool(Color.RED & Color.GREEN)
- False
-
-Individual flags should have values that are powers of two (1, 2, 4, 8, ...),
-while combinations of flags won't::
-
- --> class Color(Flag):
- ... RED = auto()
- ... BLUE = auto()
- ... GREEN = auto()
- ... WHITE = RED | BLUE | GREEN
- ...
- --> Color.WHITE
- <Color.WHITE: 7>
-
-Giving a name to the "no flags set" condition does not change its boolean
-value::
-
- >>> class Color(Flag):
- ... BLACK = 0
- ... RED = auto()
- ... BLUE = auto()
- ... GREEN = auto()
- ...
- >>> Color.BLACK
- <Color.BLACK: 0>
- >>> bool(Color.BLACK)
- False
-
-Flags can be iterated over to retrieve the individual truthy flags in the value::
-
- >>> class Color(Flag):
- ... _order_ = 'BLACK RED BLUE GREEN WHITE'
- ... BLACK = 0
- ... RED = auto()
- ... BLUE = auto()
- ... GREEN = auto()
- ... WHITE = RED | BLUE | GREEN
- ...
- >>> list(Color.GREEN)
- [<Color.GREEN: 4>]
- >>> list(Color.WHITE)
- [<Color.RED: 1>, <Color.BLUE: 2>, <Color.GREEN: 4>]
-
-.. note::
-
- For the majority of new code, ``Enum`` and ``Flag`` are strongly
- recommended, since ``IntEnum`` and ``IntFlag`` break some
- semantic promises of an enumeration (by being comparable to integers, and
- thus by transitivity to other unrelated enumerations). ``IntEnum``
- and ``IntFlag`` should be used only in cases where ``Enum`` and
- ``Flag`` will not do; for example, when integer constants are replaced
- with enumerations, or for interoperability with other systems.
-
-
-Others
-^^^^^^
-
-While ``IntEnum`` is part of the ``aenum`` module, it would be very
-simple to implement independently::
-
- class MyIntEnum(int, Enum):
- pass
-
-This demonstrates how similar derived enumerations can be defined; for example
-a ``MyStrEnum`` that mixes in ``str`` instead of ``int``.
-
-Some rules:
-
-1. When subclassing ``Enum``, mix-in types must appear before
- ``Enum`` itself in the sequence of bases, as in the ``MyIntEnum``
- example above.
-2. While ``Enum`` can have members of any type, once you mix in an
- additional type, all the members must have values of that type or be
- convertible into that type. This restriction does not apply to mix-ins
- which only add methods and don't specify another data type.
-3. When another data type is mixed in, the ``value`` attribute is *not the
- same* as the enum member itself, although it is equivalant and will compare
- equal.
-4. %-style formatting: ``%s`` and ``%r`` call ``Enum``'s ``__str__`` and
- ``__repr__`` respectively; other codes (such as ``%i`` or ``%h`` for
- MyIntEnum) treat the enum member as its mixed-in type.
-5. ``str.__format__`` (or ``format``) will use the mixed-in
- type's ``__format__``. If the ``Enum``'s ``str`` or ``repr`` is desired
- use the ``!s`` or ``!r`` ``str`` format codes.
-
-.. note::
-
- If you override the ``__str__`` method, then it will be used to provide the
- string portion of the ``format()`` call.
-
-.. note::
-
- Prior to Python 3.4 there is a bug in ``str``'s %-formatting: ``int``
- subclasses are printed as strings and not numbers when the ``%d``, ``%i``,
- or ``%u`` codes are used.
-
-
-Extra Goodies
--------------
-
-aenum supports a few extra techniques not found in the stdlib version.
-
-enum
-^^^^
-
-If you have several items to initialize your ``Enum`` members with and
-would like to use keyword arguments, the ``enum`` helper is for you::
-
- >>> from aenum import enum
- >>> class Presidents(Enum):
- ... Washington = enum('George Washington', circa=1776, death=1797)
- ... Jackson = enum('Andrew Jackson', circa=1830, death=1837)
- ... Lincoln = enum('Abraham Lincoln', circa=1860, death=1865)
- ...
- >>> Presidents.Lincoln
- <Presidents.Lincoln: enum('Abraham Lincoln', circa=1860, death=1865)>
-
-extend_enum
-^^^^^^^^^^^
-
-For those rare cases when you need to create your ``Enum`` in pieces, you
-can use ``extend_enum`` to add new members after the initial creation
-(the new member is returned)::
-
- >>> from aenum import extend_enum
- >>> class Color(Enum):
- ... red = 1
- ... green = 2
- ... blue = 3
- ...
- >>> list(Color)
- [<Color.red: 1>, <Color.green: 2>, <Color.blue: 3>]
- >>> extend_enum(Color, 'opacity', 4)
- <Color.opacity: 4>
- >>> list(Color)
- [<Color.red: 1>, <Color.green: 2>, <Color.blue: 3>, <Color.opacity: 4>]
- >>> Color.opacity in Color
- True
- >>> Color.opacity.name == 'opacity'
- True
- >>> Color.opacity.value == 4
- True
- >>> Color(4)
- <Color.opacity: 4>
- >>> Color['opacity']
- <Color.opacity: 4>
-
- --> Color.__members__
- OrderedDict([
- ('red', <Color.red: 1>),
- ('green', <Color.green: 2>),
- ('blue', <Color.blue: 3>),
- ('opacity', <Color.opacity: 4>)
- ])
-
-constant
-^^^^^^^^
-
-If you need to have some constant value in your ``Enum`` that isn't a member,
-use ``constant``::
-
- >>> from aenum import constant
- >>> class Planet(Enum):
- ... MERCURY = (3.303e+23, 2.4397e6)
- ... EARTH = (5.976e+24, 6.37814e6)
- ... JUPITER = (1.9e+27, 7.1492e7)
- ... URANUS = (8.686e+25, 2.5559e7)
- ... G = constant(6.67300E-11)
- ... def __init__(self, mass, radius):
- ... self.mass = mass # in kilograms
- ... self.radius = radius # in meters
- ... @property
- ... def surface_gravity(self):
- ... # universal gravitational constant (m3 kg-1 s-2)
- ... return self.G * self.mass / (self.radius * self.radius)
- ...
- >>> Planet.EARTH.value
- (5.976e+24, 6378140.0)
- >>> Planet.EARTH.surface_gravity
- 9.802652743337129
- >>> Planet.G
- 6.673e-11
- >>> Planet.G = 9
- Traceback (most recent call last):
- ...
- AttributeError: Planet: cannot rebind constant 'G'
-
-skip
-^^^^
-
-If you need a standard attribute that is not converted into an ``Enum``
-member, use ``skip``::
-
- >>> from aenum import skip
- >>> class Color(Enum):
- ... red = 1
- ... green = 2
- ... blue = 3
- ... opacity = skip(0.45)
- ...
- >>> Color.opacity
- 0.45
- >>> Color.opacity = 0.77
- >>> Color.opacity
- 0.77
-
-start
-^^^^^
-
-``start`` can be used to turn on auto-numbering (useful for when you don't
-care which numbers are assigned as long as they are consistent and in order)
-The Python 3 version can look like this::
-
- >>> class Color(Enum, start=1): # doctest: +SKIP
- ... red, green, blue
- ...
- >>> Color.blue
- <Color.blue: 3>
-
-This can also be done in Python 2, albeit not as elegantly (this also works in
-Python 3)::
-
- >>> class Color(Enum): # doctest: +SKIP
- ... _start_ = 1
- ... red = auto()
- ... green = auto()
- ... blue = auto()
- ...
- >>> Color.blue
- <Color.blue: 3>
-
-init
-^^^^
-
-If you need an ``__init__`` method that does nothing besides save its
-arguments, ``init`` is for you::
-
- >>> class Planet(Enum, init='mass radius'): # doctest: +SKIP
- ... MERCURY = (3.303e+23, 2.4397e6)
- ... EARTH = (5.976e+24, 6.37814e6)
- ... JUPITER = (1.9e+27, 7.1492e7)
- ... URANUS = (8.686e+25, 2.5559e7)
- ... G = constant(6.67300E-11)
- ... @property
- ... def surface_gravity(self):
- ... # universal gravitational constant (m3 kg-1 s-2)
- ... return self.G * self.mass / (self.radius * self.radius)
- ...
- >>> Planet.JUPITER.value
- (1.9e+27, 71492000.0)
- >>> Planet.JUPITER.mass
- 1.9e+27
-
-.. note::
-
- Just as with ``start`` above, in Python 2 you must put the keyword as a
- _sunder_ in the class body -- ``_init_ = 'mass radius'``.
-
-init and missing values
-^^^^^^^^^^^^^^^^^^^^^^^
-
-If ``_init_`` calls for values that are not supplied, ``_generate_next_value_``
-will be called in an effort to generate them. Here is an example in Python 2::
-
- >>> from aenum import Enum
- >>> class SelectionEnum(Enum):
- ... _init_ = 'db user'
- ... def __new__(cls, *args, **kwds):
- ... count = len(cls.__members__)
- ... obj = object.__new__(cls)
- ... obj._count = count
- ... obj._value_ = args
- ... return obj
- ... @staticmethod
- ... def _generate_next_value_(name, start, count, values, *args, **kwds):
- ... return (name, ) + args
- ...
- >>> class NotificationType(SelectionEnum):
- ... # usually, name is the same as db
- ... # but not for blanks
- ... blank = '', ''
- ... C = 'Catalog'
- ... S = 'Sheet'
- ... B = 'Both'
- ...
- >>> NotificationType.blank
- <NotificationType.blank: ('', '')>
- >>> NotificationType.B
- <NotificationType.B: ('B', 'Both')>
- >>> NotificationType.B.db
- 'B'
- >>> NotificationType.B.user
- 'Both'
-
-combining Flag with other data types
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-Flag does support being combined with other data types. To support this you
-need to provide a ``_create_pseudo_member_values_`` method which will be called
-with the members in a composite flag. You may also need to provide a custom
-``__new__`` method::
-
- >>> class AnsiFlag(str, Flag):
- ... def __new__(cls, value, code):
- ... str_value = '\x1b[%sm' % code
- ... obj = str.__new__(cls, str_value)
- ... obj._value_ = value
- ... obj.code = code
- ... return obj
- ... @classmethod
- ... def _create_pseudo_member_values_(cls, members, *values):
- ... code = ';'.join(m.code for m in members)
- ... return values + (code, )
- ... _order_ = 'FG_Red FG_Green BG_Magenta BG_White'
- ... FG_Red = '31' # ESC [ 31 m # red
- ... FG_Green = '32' # ESC [ 32 m # green
- ... BG_Magenta = '45' # ESC [ 35 m # magenta
- ... BG_White = '47' # ESC [ 37 m # white
- ...
- >>> color = AnsiFlag.BG_White | AnsiFlag.FG_Red
- >>> repr(color)
- '<AnsiFlag.FG_Red|BG_White: 9>'
- >>> str.__repr__(color)
- "'\\x1b[31;47m'"
-
-.. note::
-
- If you do not provide your own ``_create_pseudo_member_values_`` the flags
- may still combine, but may be missing functionality.
-
-
-Decorators
-----------
-
-unique
-^^^^^^
-
-A ``class`` decorator specifically for enumerations. It searches an
-enumeration's ``__members__`` gathering any aliases it finds; if any are
-found ``ValueError`` is raised with the details::
-
- >>> @unique
- ... class NoDupes(Enum):
- ... first = 'one'
- ... second = 'two'
- ... third = 'two'
- Traceback (most recent call last):
- ...
- ValueError: duplicate names found in <aenum 'NoDupes'>: third -> second
-
-
-Interesting examples
---------------------
-
-While ``Enum`` and ``IntEnum`` are expected to cover the majority of
-use-cases, they cannot cover them all. Here are recipes for some different
-types of enumerations that can be used directly (the first three are included
-in the module), or as examples for creating one's own.
-
-
-AutoNumber
-^^^^^^^^^^
-
-Avoids having to specify the value for each enumeration member::
-
- >>> class AutoNumber(Enum):
- ... def __new__(cls):
- ... value = len(cls.__members__) + 1
- ... obj = object.__new__(cls)
- ... obj._value_ = value
- ... return obj
- ...
- >>> class Color(AutoNumber):
- ... _order_ = "red green blue" # only needed in 2.x
- ... red = ()
- ... green = ()
- ... blue = ()
- ...
- >>> Color.green.value == 2
- True
-
-.. note::
-
- The `__new__` method, if defined, is used during creation of the Enum
- members; it is then replaced by Enum's `__new__` which is used after
- class creation for lookup of existing members. Due to the way Enums are
- supposed to behave, there is no way to customize Enum's `__new__` without
- modifying the class after it is created.
-
-
-UniqueEnum
-^^^^^^^^^^
-
-Raises an error if a duplicate member name is found instead of creating an
-alias::
-
- >>> class UniqueEnum(Enum):
- ... def __init__(self, *args):
- ... cls = self.__class__
- ... if any(self.value == e.value for e in cls):
- ... a = self.name
- ... e = cls(self.value).name
- ... raise ValueError(
- ... "aliases not allowed in UniqueEnum: %r --> %r"
- ... % (a, e))
- ...
- >>> class Color(UniqueEnum):
- ... _order_ = 'red green blue'
- ... red = 1
- ... green = 2
- ... blue = 3
- ... grene = 2
- Traceback (most recent call last):
- ...
- ValueError: aliases not allowed in UniqueEnum: 'grene' --> 'green'
-
-
-OrderedEnum
-^^^^^^^^^^^
-
-An ordered enumeration that is not based on ``IntEnum`` and so maintains
-the normal ``Enum`` invariants (such as not being comparable to other
-enumerations)::
-
- >>> class OrderedEnum(Enum):
- ... 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
- ...
- >>> class Grade(OrderedEnum):
- ... __ordered__ = 'A B C D F'
- ... A = 5
- ... B = 4
- ... C = 3
- ... D = 2
- ... F = 1
- ...
- >>> Grade.C < Grade.A
- True
-
-
-Planet
-^^^^^^
-
-If ``__new__`` or ``__init__`` is defined the value of the enum member
-will be passed to those methods::
-
- >>> class Planet(Enum):
- ... MERCURY = (3.303e+23, 2.4397e6)
- ... VENUS = (4.869e+24, 6.0518e6)
- ... EARTH = (5.976e+24, 6.37814e6)
- ... MARS = (6.421e+23, 3.3972e6)
- ... JUPITER = (1.9e+27, 7.1492e7)
- ... SATURN = (5.688e+26, 6.0268e7)
- ... URANUS = (8.686e+25, 2.5559e7)
- ... NEPTUNE = (1.024e+26, 2.4746e7)
- ... def __init__(self, mass, radius):
- ... self.mass = mass # in kilograms
- ... self.radius = radius # in meters
- ... @property
- ... def surface_gravity(self):
- ... # universal gravitational constant (m3 kg-1 s-2)
- ... G = 6.67300E-11
- ... return G * self.mass / (self.radius * self.radius)
- ...
- >>> Planet.EARTH.value
- (5.976e+24, 6378140.0)
- >>> Planet.EARTH.surface_gravity
- 9.802652743337129
-
-
-How are Enums different?
-------------------------
-
-Enums have a custom metaclass that affects many aspects of both derived Enum
-classes and their instances (members).
-
-
-Enum Classes
-^^^^^^^^^^^^
-
-The ``EnumMeta`` metaclass is responsible for providing the
-``__contains__``, ``__dir__``, ``__iter__`` and other methods that
-allow one to do things with an ``Enum`` class that fail on a typical
-class, such as ``list(Color)`` or ``some_var in Color``. ``EnumMeta`` is
-responsible for ensuring that various other methods on the final ``Enum``
-class are correct (such as ``__new__``, ``__getnewargs__``,
-``__str__`` and ``__repr__``).
-
-.. note::
-
- ``__dir__`` is not changed in the Python 2 line as it messes up some
- of the decorators included in the stdlib.
-
-
-Enum Members (aka instances)
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-The most interesting thing about Enum members is that they are singletons.
-``EnumMeta`` creates them all while it is creating the ``Enum``
-class itself, and then puts a custom ``__new__`` in place to ensure
-that no new ones are ever instantiated by returning only the existing
-member instances.
-
-
-Finer Points
-^^^^^^^^^^^^
-
-``Enum`` members are instances of an ``Enum`` class, but are not
-accessible as `EnumClass.member1.member2`.
-(changed in version 1.1.1 to be accessible)
-(changed in version 2.2.4 to be inaccessible)::
-
- >>> class FieldTypes(Enum):
- ... name = 1
- ... value = 2
- ... size = 3
- ...
- >>> FieldTypes.size.value
- 3
- >>> FieldTypes.size
- <FieldTypes.size: 3>
- >>> FieldTypes.value.size
- Traceback (most recent call last):
- ...
- AttributeError: <aenum 'FieldTypes'> member has no attribute 'size'
-
-The ``__members__`` attribute is only available on the class.
-
-
-``__members__`` is always an ``OrderedDict``, with the order being the
-definition order in Python 3.x or the order in ``_order_`` in Python 2.7;
-if no ``_order_`` was specified in Python 2.7 then the order of
-``__members__`` is either increasing value or alphabetically by name.
-
-If you give your ``Enum`` subclass extra methods, like the `Planet`_
-class above, those methods will show up in a `dir` of the member,
-but not of the class (in Python 3.x)::
-
- --> dir(Planet)
- ['EARTH', 'JUPITER', 'MARS', 'MERCURY', 'NEPTUNE', 'SATURN', 'URANUS',
- 'VENUS', '__class__', '__doc__', '__members__', '__module__']
- --> dir(Planet.EARTH)
- ['__class__', '__doc__', '__module__', 'name', 'surface_gravity', 'value']
-
-A ``__new__`` method will only be used for the creation of the
-``Enum`` members -- after that it is replaced. This means if you wish to
-change how ``Enum`` members are looked up you either have to write a
-helper function or a ``classmethod``.
-
-.. note::
-
- If you create your own ``__new__`` you should set the ``_value_`` in it;
- if you do not, aenum will try to, but will raise a ``TypeError`` if it
- cannot.
-
-If the stdlib ``enum`` is available (Python 3.4+ and it hasn't been shadowed
-by, for example, ``enum34``) then aenum will be a subclass of it.
-
-To use the ``AddValue``, ``MultiValue``, ``NoAlias``, and ``Unique`` flags
-in Py2 or Py2/Py3 codebases, use ``_settings_ = ...`` in the class body.
-
-To use ``init`` in Py2 or Py2/Py3 codebases use ``_init_`` in the class body.
-
-To use ``start`` in Py2 or Py2/Py3 codebases use ``_start_`` in the class body.
-
-When creating class bodies dynamically, put any variables you need to use into
-``_ignore_``::
-
- >>> from datetime import timedelta
- >>> from aenum import NoAlias
- >>> class Period(timedelta, Enum):
- ... '''
- ... different lengths of time
- ... '''
- ... _init_ = 'value period'
- ... _settings_ = NoAlias
- ... _ignore_ = 'Period i'
- ... Period = vars()
- ... for i in range(31):
- ... Period['day_%d' % i] = i, 'day'
- ... for i in range(15):
- ... Period['week_%d' % i] = i*7, 'week'
- ...
- >>> hasattr(Period, '_ignore_')
- False
- >>> hasattr(Period, 'Period')
- False
- >>> hasattr(Period, 'i')
- False
-
-The name listed in ``_ignore_``, as well as ``_ignore_`` itself, will not be
-present in the final enumeration as neither attributes nor members.
-
-.. note::
-
- except for __dunder__ attributes/methods, all _sunder_ attributes must
- be before any thing else in the class body
-
-.. note::
-
- all _sunder_ attributes that affect member creation are only looked up in
- the last ``Enum`` class listed in the class header
-
-
-Creating NamedTuples
---------------------
-
-Simple
-^^^^^^
-
-The most common way to create a new NamedTuple will be via the functional API::
-
- >>> from aenum import NamedTuple
- >>> Book = NamedTuple('Book', 'title author genre', module=__name__)
-
-This creates a ``NamedTuple`` called ``Book`` that will always contain three
-items, each of which is also addressable as ``title``, ``author``, or ``genre``.
-
-``Book`` instances can be created using positional or keyword argements or a
-mixture of the two::
-
- >>> b1 = Book('Lord of the Rings', 'J.R.R. Tolkien', 'fantasy')
- >>> b2 = Book(title='Jhereg', author='Steven Brust', genre='fantasy')
- >>> b3 = Book('Empire', 'Orson Scott Card', genre='scifi')
-
-If too few or too many arguments are used a ``TypeError`` will be raised::
-
- >>> b4 = Book('Hidden Empire')
- Traceback (most recent call last):
- ...
- TypeError: values not provided for field(s): author, genre
- >>> b5 = Book(genre='business')
- Traceback (most recent call last):
- ...
- TypeError: values not provided for field(s): title, author
-
-As a ``class`` the above ``Book`` ``NamedTuple`` would look like::
-
- >>> class Book(NamedTuple):
- ... title = 0
- ... author = 1
- ... genre = 2
- ...
-
-For compatibility with the stdlib ``namedtuple``, NamedTuple also has the
-``_asdict``, ``_make``, and ``_replace`` methods, and the ``_fields``
-attribute, which all function similarly::
-
- >>> class Point(NamedTuple):
- ... x = 0, 'horizontal coordinate', 1
- ... y = 1, 'vertical coordinate', -1
- ...
- >>> class Color(NamedTuple):
- ... r = 0, 'red component', 11
- ... g = 1, 'green component', 29
- ... b = 2, 'blue component', 37
- ...
- >>> Pixel = NamedTuple('Pixel', Point+Color, module=__name__)
- >>> pixel = Pixel(99, -101, 255, 128, 0)
-
- >>> pixel._asdict()
- OrderedDict([('x', 99), ('y', -101), ('r', 255), ('g', 128), ('b', 0)])
-
- >>> Point._make((4, 5))
- Point(x=4, y=5)
-
- >>> purple = Color(127, 0, 127)
- >>> mid_gray = purple._replace(g=127)
- >>> mid_gray
- Color(r=127, g=127, b=127)
-
- >>> pixel._fields
- ['x', 'y', 'r', 'g', 'b']
-
- >>> Pixel._fields
- ['x', 'y', 'r', 'g', 'b']
-
-
-Advanced
-^^^^^^^^
-
-The simple method of creating ``NamedTuples`` requires always specifying all
-possible arguments when creating instances; failure to do so will raise
-exceptions::
-
- >>> class Point(NamedTuple):
- ... x = 0
- ... y = 1
- ...
- >>> Point()
- Traceback (most recent call last):
- ...
- TypeError: values not provided for field(s): x, y
- >>> Point(1)
- Traceback (most recent call last):
- ...
- TypeError: values not provided for field(s): y
- >>> Point(y=2)
- Traceback (most recent call last):
- ...
- TypeError: values not provided for field(s): x
-
-However, it is possible to specify both docstrings and default values when
-creating a ``NamedTuple`` using the class method::
-
- >>> class Point(NamedTuple):
- ... x = 0, 'horizontal coordinate', 0
- ... y = 1, 'vertical coordinate', 0
- ...
- >>> Point()
- Point(x=0, y=0)
- >>> Point(1)
- Point(x=1, y=0)
- >>> Point(y=2)
- Point(x=0, y=2)
-
-It is also possible to create ``NamedTuples`` that only have named attributes
-for certain fields; any fields without names can still be accessed by index::
-
- >>> class Person(NamedTuple):
- ... fullname = 2
- ... phone = 5
- ...
- >>> p = Person('Ethan', 'Furman', 'Ethan Furman',
- ... 'ethan at stoneleaf dot us',
- ... 'ethan.furman', '999.555.1212')
- >>> p
- Person('Ethan', 'Furman', 'Ethan Furman', 'ethan at stoneleaf dot us',
- 'ethan.furman', '999.555.1212')
- >>> p.fullname
- 'Ethan Furman'
- >>> p.phone
- '999.555.1212'
- >>> p[0]
- 'Ethan'
-
-In the above example the last named field was also the last field possible; in
-those cases where you don't need to have the last possible field named, you can
-provide a ``_size_`` of ``TupleSize.minimum`` to declare that more fields are
-okay::
-
- >>> from aenum import TupleSize
- >>> class Person(NamedTuple):
- ... _size_ = TupleSize.minimum
- ... first = 0
- ... last = 1
- ...
-
-or, optionally if using Python 3::
-
- >>> class Person(NamedTuple, size=TupleSize.minimum): # doctest: +SKIP
- ... first = 0
- ... last = 1
-
-and in use::
-
- >>> Person('Ethan', 'Furman')
- Person(first='Ethan', last='Furman')
-
- >>> Person('Ethan', 'Furman', 'ethan.furman')
- Person('Ethan', 'Furman', 'ethan.furman')
-
- >>> Person('Ethan', 'Furman', 'ethan.furman', 'yay Python!')
- Person('Ethan', 'Furman', 'ethan.furman', 'yay Python!')
-
- >>> Person('Ethan')
- Traceback (most recent call last):
- ...
- TypeError: values not provided for field(s): last
-
-Also, for those cases where even named fields may not be present, you can
-specify ``TupleSize.variable``::
-
- >>> class Person(NamedTuple):
- ... _size_ = TupleSize.variable
- ... first = 0
- ... last = 1
- ...
-
- >>> Person('Ethan')
- Person('Ethan')
-
- >>> Person(last='Furman')
- Traceback (most recent call last):
- ...
- TypeError: values not provided for field(s): first
-
-Creating new ``NamedTuples`` from existing ``NamedTuples`` is simple::
-
- >>> Point = NamedTuple('Point', 'x y')
- >>> Color = NamedTuple('Color', 'r g b')
- >>> Pixel = NamedTuple('Pixel', Point+Color, module=__name__)
- >>> Pixel
- <NamedTuple 'Pixel'>
-
-The existing fields in the bases classes are renumbered to fit the new class,
-but keep their doc strings and default values. If you use standard
-subclassing::
-
- >>> Point = NamedTuple('Point', 'x y')
- >>> class Pixel(Point):
- ... r = 2, 'red component', 11
- ... g = 3, 'green component', 29
- ... b = 4, 'blue component', 37
- ...
- >>> Pixel.__fields__
- ['x', 'y', 'r', 'g', 'b']
-
-You must manage the numbering yourself.
-
-
-Creating NamedConstants
------------------------
-
-A ``NamedConstant`` class is created much like an ``Enum``::
-
- >>> from aenum import NamedConstant
- >>> class Konstant(NamedConstant):
- ... PI = 3.14159
- ... TAU = 2 * PI
-
- >>> Konstant.PI
- <Konstant.PI: 3.14159>
-
- >> print(Konstant.PI)
- 3.14159
-
- >>> Konstant.PI = 'apple'
- Traceback (most recent call last):
- ...
- AttributeError: cannot rebind constant <Konstant.PI>
-
- >>> del Konstant.PI
- Traceback (most recent call last):
- ...
- AttributeError: cannot delete constant <Konstant.PI>
diff --git a/venv/Lib/site-packages/aenum/test.py b/venv/Lib/site-packages/aenum/test.py
deleted file mode 100644
index 224293cb..00000000
--- a/venv/Lib/site-packages/aenum/test.py
+++ /dev/null
@@ -1,6832 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from __future__ import division, print_function
-import sys
-import aenum
-import doctest
-import os
-import shutil
-import tempfile
-import textwrap
-import unittest
-import uuid
-import warnings
-from aenum import EnumType, EnumMeta, Enum, IntEnum, StrEnum, LowerStrEnum, UpperStrEnum
-from aenum import AutoNumberEnum, MultiValueEnum, OrderedEnum, UniqueEnum, AddValueEnum, Flag, IntFlag
-from aenum import NamedTuple, TupleSize, NamedConstant, constant, NoAlias, AddValue, Unique
-from aenum import STRICT, CONFORM, EJECT, KEEP
-from aenum import _reduce_ex_by_name, unique, skip, extend_enum, auto, enum, MultiValue, member, nonmember, no_arg
-from aenum import basestring, baseinteger, unicode, enum_property
-from aenum import pyver, PY2, PY3, PY2_6, PY3_3, PY3_4, PY3_5, PY3_6, PY3_11
-from collections import OrderedDict
-from datetime import timedelta
-from pickle import dumps, loads, PicklingError, HIGHEST_PROTOCOL
-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 operator import div as _div_
-try:
- import threading
-except ImportError:
- threading = None
-
-try:
- any
-except NameError:
- from aenum import any
-
-MODULE = __name__
-SHORT_MODULE = MODULE.split('.')[-1]
-
-def load_tests(loader, tests, ignore):
- tests.addTests(doctest.DocTestSuite(aenum))
- tests.addTests(doctest.DocFileSuite(
- 'doc/aenum.rst',
- package=aenum,
- optionflags=doctest.ELLIPSIS|doctest.NORMALIZE_WHITESPACE,
- ))
- return tests
-
-class TestCase(unittest.TestCase):
-
- def __init__(self, *args, **kwds):
- regex = getattr(self, 'assertRaisesRegex', None)
- if regex is None:
- self.assertRaisesRegex = getattr(self, 'assertRaisesRegexp')
- super(TestCase, self).__init__(*args, **kwds)
-
-
-# for pickle tests
-try:
- class Stooges(Enum):
- LARRY = 1
- CURLY = 2
- MOE = 3
-except Exception:
- Stooges = sys.exc_info()[1]
-
-try:
- class IntStooges(int, Enum):
- LARRY = 1
- CURLY = 2
- MOE = 3
-except Exception:
- IntStooges = sys.exc_info()[1]
-
-try:
- class FloatStooges(float, Enum):
- LARRY = 1.39
- CURLY = 2.72
- MOE = 3.142596
-except Exception:
- FloatStooges = sys.exc_info()[1]
-
-try:
- class FlagStooges(Flag):
- LARRY = 1
- CURLY = 2
- MOE = 3
-except Exception as exc:
- FlagStooges = exc
-
-try:
- LifeForm = NamedTuple('LifeForm', 'branch genus species', module=__name__)
-except Exception:
- LifeForm = sys.exc_info()[1]
-
-try:
- class DeathForm(NamedTuple):
- color = 0
- rigidity = 1
- odor = 2
-except Exception:
- DeathForm = sys.exc_info()[1]
-
-# for pickle test and subclass tests
-try:
- class Name(StrEnum):
- BDFL = 'Guido van Rossum'
- FLUFL = 'Barry Warsaw'
-except Exception:
- Name = sys.exc_info()[1]
-
-try:
- Question = Enum('Question', 'who what when where why', module=__name__)
-except Exception:
- Question = sys.exc_info()[1]
-
-try:
- Answer = Enum('Answer', 'him this then there because')
-except Exception:
- Answer = sys.exc_info()[1]
-
-try:
- class WhatsIt(NamedTuple):
- def what(self):
- return self[0]
- class ThatsIt(WhatsIt):
- blah = 0
- bleh = 1
-except Exception:
- ThatsIt = sys.exc_info()[1]
-
-# for doctests
-try:
- class Fruit(Enum):
- tomato = 1
- banana = 2
- cherry = 3
-except Exception:
- pass
-
-def test_pickle_dump_load(assertion, source, target=None, protocol=(0, HIGHEST_PROTOCOL)):
- start, stop = protocol
- failures = []
- for protocol in range(start, stop+1):
- try:
- if target is None:
- assertion(loads(dumps(source, protocol=protocol)), source)
- else:
- assertion(loads(dumps(source, protocol=protocol)), target)
- except Exception:
- exc, tb = sys.exc_info()[1:]
- failures.append('%2d: %s' %(protocol, exc))
- if failures:
- raise ValueError('Failed with protocols: %s' % ', '.join(failures))
-
-def test_pickle_exception(assertion, exception, obj,
- protocol=(0, HIGHEST_PROTOCOL)):
- start, stop = protocol
- failures = []
- for protocol in range(start, stop+1):
- try:
- assertion(exception, dumps, obj, protocol=protocol)
- except Exception:
- exc = sys.exc_info()[1]
- failures.append('%d: %s %s' % (protocol, exc.__class__.__name__, exc))
- if failures:
- raise ValueError('Failed with protocols: %s' % ', '.join(failures))
-
-if PY3:
- from aenum.test_v3 import TestEnumV3, TestOrderV3, TestNamedTupleV3, TestStackoverflowAnswersV3, TestIssuesV3, TestExtendEnumV3
- from aenum import test_v3
- test_v3.IntStooges = IntStooges
- test_v3.test_pickle_exception = test_pickle_exception
- test_v3.test_pickle_dump_load = test_pickle_dump_load
-
-# for subclassing tests
-
-class classproperty(object):
-
- def __init__(self, fget=None, fset=None, fdel=None, doc=None):
- self.fget = fget
- self.fset = fset
- self.fdel = fdel
- if doc is None and fget is not None:
- doc = fget.__doc__
- self.__doc__ = doc
-
- def __get__(self, instance, ownerclass):
- return self.fget(ownerclass)
-
-
-# tests
-class TestOrder(TestCase):
- """
- Test _order_ extra/missing members.
- """
-
- def test_same_members(self):
- class Color(Enum):
- _order_ = 'red green blue'
- red = 1
- green = 2
- blue = 3
-
- def test_same_members_with_aliases(self):
- class Color(Enum):
- _order_ = 'red green blue'
- red = 1
- green = 2
- blue = 3
- verde = green
-
- def test_order_has_extra_members(self):
- with self.assertRaisesRegex(TypeError, r'member order does not match _order_'):
- class Color(Enum):
- _order_ = 'red green blue purple'
- red = 1
- green = 2
- blue = 3
-
- def test_order_has_extra_members_with_aliases(self):
- with self.assertRaisesRegex(TypeError, r'member order does not match _order_'):
- class Color(Enum):
- _order_ = 'red green blue purple'
- red = 1
- green = 2
- blue = 3
- verde = green
-
- def test_enum_has_extra_members(self):
- with self.assertRaisesRegex(TypeError, r'member order does not match _order_'):
- class Color(Enum):
- _order_ = 'red green blue'
- red = 1
- green = 2
- blue = 3
- purple = 4
-
- def test_enum_has_extra_members_with_aliases(self):
- with self.assertRaisesRegex(TypeError, r'member order does not match _order_'):
- class Color(Enum):
- _order_ = 'red green blue'
- red = 1
- green = 2
- blue = 3
- purple = 4
- verde = green
-
- def test_same_members_flag(self):
- class Color(Flag):
- _order_ = 'red green blue'
- red = 1
- green = 2
- blue = 4
-
- def test_same_members_with_aliases_flag(self):
- class Color(Flag):
- _order_ = 'red green blue'
- red = 1
- green = 2
- blue = 4
- verde = green
-
- def test_order_has_extra_members_flag(self):
- with self.assertRaisesRegex(TypeError, r'member order does not match _order_'):
- class Color(Flag):
- _order_ = 'red green blue purple'
- red = 1
- green = 2
- blue = 4
-
- def test_order_has_extra_members_with_aliases_flag(self):
- with self.assertRaisesRegex(TypeError, r'member order does not match _order_'):
- class Color(Flag):
- _order_ = 'red green blue purple'
- red = 1
- green = 2
- blue = 4
- verde = green
-
- def test_enum_has_extra_members_flag(self):
- with self.assertRaisesRegex(TypeError, r'member order does not match _order_'):
- class Color(Flag):
- _order_ = 'red green blue'
- red = 1
- green = 2
- blue = 4
- purple = 8
-
- def test_enum_has_extra_members_with_aliases_flag(self):
- with self.assertRaisesRegex(TypeError, r'member order does not match _order_'):
- class Color(Flag):
- _order_ = 'red green blue'
- red = 1
- green = 2
- blue = 4
- purple = 8
- verde = green
-
-
-class TestAutoValue(TestCase):
-
- def test_bare(self):
- #
- class BareEnum(Enum):
- _order_ = 'ONE TWO THREE'
- ONE = auto()
- TWO = auto()
- THREE = auto()
- self.assertEqual(BareEnum.THREE.value, 3)
- #
- class BareIntEnum(IntEnum):
- _order_ = 'ONE TWO THREE'
- ONE = auto()
- TWO = auto()
- THREE = auto()
- self.assertEqual(BareIntEnum.THREE, 3)
- #
- class BareFlag(Flag):
- _order_ = 'ONE TWO THREE'
- ONE = auto()
- TWO = auto()
- THREE = auto()
- self.assertEqual(BareFlag.THREE.value, 4)
- #
- class BareIntFlag(IntFlag):
- _order_ = 'ONE TWO THREE'
- ONE = auto()
- TWO = auto()
- THREE = auto()
- self.assertEqual(BareIntFlag.THREE, 4)
-
- def test_init_only_final(self):
- #
- class InitEnumValue(Enum):
- _init_ = 'value description'
- _order_ = 'ONE TWO THREE'
- ONE = 'the loneliest number'
- TWO = 'the number with you'
- THREE = 'a triangle'
- self.assertEqual(InitEnumValue.THREE.value, 3)
- self.assertEqual(InitEnumValue.THREE.description, 'a triangle')
- #
- class InitEnum(Enum):
- _init_ = 'value description'
- _order_ = 'ONE TWO THREE'
- ONE = 'the loneliest number'
- TWO = 'the number with you'
- THREE = 'a triangle'
- self.assertEqual(InitEnum.THREE.value, 3)
- self.assertEqual(InitEnum.THREE.description, 'a triangle')
- #
- class InitIntEnum(IntEnum):
- _init_ = 'value description'
- _order_ = 'ONE TWO THREE'
- ONE = 'the loneliest number'
- TWO = 'the number with you'
- THREE = 'a triangle'
- self.assertEqual(InitIntEnum.THREE, 3)
- self.assertEqual(InitIntEnum.THREE.description, 'a triangle')
- #
- class InitFlag(Flag):
- _init_ = 'value description'
- _order_ = 'ONE TWO THREE'
- ONE = 'the loneliest number'
- TWO = 'the number with you'
- THREE = 'a triangle'
- self.assertEqual(InitFlag.THREE.value, 4)
- self.assertEqual(InitFlag.THREE.description, 'a triangle')
- #
- class InitIntFlag(IntFlag):
- _init_ = 'value description'
- _order_ = 'ONE TWO THREE'
- ONE = 'the loneliest number'
- TWO = 'the number with you'
- THREE = 'a triangle'
- self.assertEqual(InitIntFlag.THREE, 4)
- self.assertEqual(InitIntFlag.THREE.description, 'a triangle')
-
- def test_init_only_inherit(self):
- #
- class InitInheritEnum(Enum):
- _init_ = 'value description'
- #
- class InitEnum(InitInheritEnum):
- _order_ = 'ONE TWO THREE'
- ONE = 'the loneliest number'
- TWO = 'the number with you'
- THREE = 'a triangle'
- self.assertEqual(InitEnum.THREE.value, 3)
- self.assertEqual(InitEnum.THREE.description, 'a triangle')
- #
- #
- class InitInheritValueEnum(Enum):
- _init_ = 'value description'
- #
- class InitEnum(InitInheritValueEnum):
- _order_ = 'ONE TWO THREE'
- ONE = 'the loneliest number'
- TWO = 'the number with you'
- THREE = 'a triangle'
- self.assertEqual(InitEnum.THREE.value, 3)
- self.assertEqual(InitEnum.THREE.description, 'a triangle')
- #
- class InitIntEnum(int, InitInheritValueEnum):
- _order_ = 'ONE TWO THREE'
- ONE = 'the loneliest number'
- TWO = 'the number with you'
- THREE = 'a triangle'
- self.assertEqual(InitIntEnum.THREE, 3)
- self.assertEqual(InitIntEnum.THREE.description, 'a triangle')
- #
- class InitInheritValueFlag(Flag):
- _init_ = 'value description'
- #
- class InitFlag(InitInheritValueFlag):
- _order_ = 'ONE TWO THREE'
- ONE = 'the loneliest number'
- TWO = 'the number with you'
- THREE = 'a triangle'
- self.assertEqual(InitFlag.THREE.value, 4)
- self.assertEqual(InitFlag.THREE.description, 'a triangle')
- #
- class InitIntFlag(int, InitInheritValueFlag):
- _order_ = 'ONE TWO THREE'
- ONE = 'the loneliest number'
- TWO = 'the number with you'
- THREE = 'a triangle'
- self.assertEqual(InitIntFlag.THREE, 4)
- self.assertEqual(InitIntFlag.THREE.description, 'a triangle')
-
- def test_new_only_final(self):
- #
- class NewFinalEnum(Enum):
- _order_ = 'ONE TWO THREE'
- def __new__(cls, value):
- member = object.__new__(cls)
- member._value_ = value
- member.proof = 'NFE1'
- return member
- ONE = auto()
- TWO = auto()
- THREE = auto()
- self.assertEqual(NewFinalEnum.THREE.value, 3)
- self.assertEqual(NewFinalEnum.TWO.proof, 'NFE1')
- #
- class NewFinalIntEnum(IntEnum):
- _order_ = 'ONE TWO THREE'
- def __new__(cls, value):
- member = int.__new__(cls, value)
- member._value_ = value
- member.proof = 'NFE2'
- return member
- ONE = auto()
- TWO = auto()
- THREE = auto()
- self.assertEqual(NewFinalIntEnum.THREE, 3)
- self.assertEqual(NewFinalIntEnum.TWO.proof, 'NFE2')
- #
- class NewFinalFlag(Flag):
- _order_ = 'ONE TWO THREE'
- def __new__(cls, value):
- member = object.__new__(cls)
- member._value_ = value
- member.proof = 'NFE3'
- return member
- ONE = auto()
- TWO = auto()
- THREE = auto()
- self.assertEqual(NewFinalFlag.THREE.value, 4)
- self.assertEqual(NewFinalFlag.TWO.proof, 'NFE3')
- #
- class NewFinalIntFlag(IntFlag):
- _order_ = 'ONE TWO THREE'
- def __new__(cls, value):
- member = int.__new__(cls, value)
- member._value_ = value
- member.proof = 'NFE4'
- return member
- ONE = auto()
- TWO = auto()
- THREE = auto()
- self.assertEqual(NewFinalIntFlag.THREE, 4)
- self.assertEqual(NewFinalIntFlag.TWO.proof, 'NFE4')
- #
- class NewFinalStrEnum(str, Enum):
- #
- _order_ = "AllReset Bright FG_Cyan BG_Black"
- #
- def __new__(cls, value, code, description):
- str_value = '\x1b[%sm' % code
- obj = str.__new__(cls, str_value)
- obj._value_ = value
- obj.code = code
- obj.description = description
- return obj
- #
- __str__ = str.__str__
- #
- AllReset = '0', 'reset all (colors and brightness)'
- Bright = '1', 'bright lights!'
- FG_Cyan = '36', 'cyan'
- BG_Black = '40', 'black'
- self.assertEqual(NewFinalStrEnum.FG_Cyan.value, 3)
- self.assertEqual(NewFinalStrEnum.BG_Black.value, 4)
- self.assertEqual(NewFinalStrEnum.AllReset.code, '0')
- self.assertEqual(NewFinalStrEnum.Bright.description, 'bright lights!')
- #
- class NewFinalStrFlag(str, Flag):
- #
- _order_ = "AllReset Bright FG_Cyan BG_Black"
- #
- def __new__(cls, value, code, description):
- str_value = '\x1b[%sm' % code
- obj = str.__new__(cls, str_value)
- obj._value_ = value
- obj.code = code
- obj.description = description
- return obj
- #
- __str__ = str.__str__
- #
- AllReset = '0', 'reset all (colors and brightness)'
- Bright = '1', 'bright lights!'
- FG_Cyan = '36', 'cyan'
- BG_Black = '40', 'black'
- self.assertEqual(NewFinalStrFlag.FG_Cyan.value, 4)
- self.assertEqual(NewFinalStrFlag.BG_Black.value, 8)
- self.assertEqual(NewFinalStrFlag.AllReset.code, '0')
- self.assertEqual(NewFinalStrFlag.Bright.description, 'bright lights!')
-
- def test_new_only_inherited(self):
- #
- class NewInheritEnum(Enum):
- def __new__(cls, value):
- if cls._member_type_ is int:
- member = int.__new__(cls, value*2)
- else:
- member = object.__new__(cls)
- member._value_ = value * 2
- member.proof = 'NIE'
- return member
- #
- class NewFinalEnum(NewInheritEnum):
- _order_ = 'ONE TWO THREE'
- ONE = auto()
- TWO = auto()
- THREE = auto()
- self.assertEqual(NewFinalEnum.THREE.value, 6)
- self.assertEqual(NewFinalEnum.TWO.proof, 'NIE')
- #
- class NewFinalIntEnum(int, NewInheritEnum):
- _order_ = 'ONE TWO THREE'
- ONE = auto()
- TWO = auto()
- THREE = auto()
- self.assertEqual(NewFinalIntEnum.THREE, 6)
- self.assertEqual(NewFinalIntEnum.TWO.proof, 'NIE')
- #
- class NewInheritFlag(Flag):
- def __new__(cls, value):
- if cls._member_type_ is int:
- member = int.__new__(cls, value*2)
- else:
- member = object.__new__(cls)
- member._value_ = value * 2
- member.proof = 'NIE'
- return member
- #
- class NewFinalFlag(NewInheritFlag):
- _order_ = 'ONE TWO THREE'
- ONE = auto()
- TWO = auto()
- THREE = auto()
- self.assertEqual(NewFinalFlag.THREE.value, 8)
- self.assertEqual(NewFinalFlag.TWO.proof, 'NIE')
- #
- class NewFinalIntFlag(int, NewInheritFlag):
- _order_ = 'ONE TWO THREE'
- ONE = auto()
- TWO = auto()
- THREE = auto()
- self.assertEqual(NewFinalIntFlag.THREE, 8)
- self.assertEqual(NewFinalIntFlag.TWO.proof, 'NIE')
-
- def test_init_new_only(self):
- #
- class InitNewEnum(Enum):
- _init_ = "value description"
- _order_ = 'ONE TWO THREE'
- def __new__(cls, value, *args):
- member = object.__new__(cls)
- member._value_ = value
- member.proof = 'INE1'
- return member
- ONE = 'the loneliest number'
- TWO = 'the number with you'
- THREE = 'a triangle'
- self.assertEqual(InitNewEnum.THREE.value, 3)
- self.assertEqual(InitNewEnum.THREE.description, 'a triangle')
- self.assertEqual(InitNewEnum.TWO.proof, 'INE1')
- #
- class InitNewIntEnum(IntEnum):
- _init_ = "value description"
- _order_ = 'ONE TWO THREE'
- def __new__(cls, value, *args):
- member = int.__new__(cls, value)
- member._value_ = value
- member.proof = 'INE2'
- return member
- ONE = 'the loneliest number'
- TWO = 'the number with you'
- THREE = 'a triangle'
- self.assertEqual(InitNewIntEnum.THREE, 3)
- self.assertEqual(InitNewIntEnum.THREE.description, 'a triangle')
- self.assertEqual(InitNewIntEnum.TWO.proof, 'INE2')
- #
- class InitNewFlag(Flag):
- _init_ = "value description"
- _order_ = 'ONE TWO THREE'
- def __new__(cls, value, *args):
- member = object.__new__(cls)
- member._value_ = value
- member.proof = 'INE3'
- return member
- ONE = 'the loneliest number'
- TWO = 'the number with you'
- THREE = 'a triangle'
- self.assertEqual(InitNewFlag.THREE.value, 4)
- self.assertEqual(InitNewFlag.THREE.description, 'a triangle')
- self.assertEqual(InitNewFlag.TWO.proof, 'INE3')
- #
- class InitNewIntFlag(IntFlag):
- _init_ = "value description"
- _order_ = 'ONE TWO THREE'
- def __new__(cls, value, *args):
- member = int.__new__(cls, value)
- member._value_ = value
- member.proof = 'INE4'
- return member
- ONE = 'the loneliest number'
- TWO = 'the number with you'
- THREE = 'a triangle'
- self.assertEqual(InitNewIntFlag.THREE, 4)
- self.assertEqual(InitNewIntFlag.THREE.description, 'a triangle')
- self.assertEqual(InitNewIntFlag.TWO.proof, 'INE4')
-
- def test_init_new_inherit(self):
- #
- class InitNew(Enum):
- _init_ = "value description"
- def __new__(cls, value, *args):
- member = object.__new__(cls)
- member._value_ = value
- member.proof = 'IN'
- return member
- #
- class InitNewEnum(InitNew):
- _order_ = 'ONE TWO THREE'
- ONE = 'the loneliest number'
- TWO = 'the number with you'
- THREE = 'a triangle'
- self.assertEqual(InitNewEnum.THREE.value, 3)
- self.assertEqual(InitNewEnum.THREE.description, 'a triangle')
- self.assertEqual(InitNewEnum.TWO.proof, 'IN')
- #
- class InitNewInt(Enum):
- _init_ = "value description"
- def __new__(cls, value, *args):
- member = int.__new__(cls, value)
- member._value_ = value
- member.proof = 'IN'
- return member
- #
- class InitNewIntEnum(int, InitNewInt):
- _order_ = 'ONE TWO THREE'
- ONE = 'the loneliest number'
- TWO = 'the number with you'
- THREE = 'a triangle'
- self.assertEqual(InitNewIntEnum.THREE, 3)
- self.assertEqual(InitNewIntEnum.THREE.description, 'a triangle')
- self.assertEqual(InitNewIntEnum.TWO.proof, 'IN')
- #
- class InitNewFlagBase(Flag):
- _init_ = "value description"
- def __new__(cls, value, *args):
- member = object.__new__(cls)
- member._value_ = value
- member.proof = 'IN'
- return member
- #
- class InitNewFlag(InitNewFlagBase):
- _order_ = 'ONE TWO THREE'
- ONE = 'the loneliest number'
- TWO = 'the number with you'
- THREE = 'a triangle'
- self.assertEqual(InitNewFlag.THREE.value, 4)
- self.assertEqual(InitNewFlag.THREE.description, 'a triangle')
- self.assertEqual(InitNewFlag.TWO.proof, 'IN')
- #
- class InitNewIntFlagBase(int, Flag):
- _init_ = "value description"
- def __new__(cls, value, *args):
- member = int.__new__(cls, value)
- member._value_ = value
- member.proof = 'IN'
- return member
- #
- class InitNewIntFlag(InitNewIntFlagBase):
- _order_ = 'ONE TWO THREE'
- ONE = 'the loneliest number'
- TWO = 'the number with you'
- THREE = 'a triangle'
- self.assertEqual(InitNewIntFlag.THREE, 4)
- self.assertEqual(InitNewIntFlag.THREE.description, 'a triangle')
- self.assertEqual(InitNewIntFlag.TWO.proof, 'IN')
-
-
-class TestHelpers(TestCase):
- # _is_descriptor, _is_sunder, _is_dunder
-
- def test_is_descriptor(self):
- class foo:
- pass
- for attr in ('__get__','__set__','__delete__'):
- obj = foo()
- self.assertFalse(aenum._is_descriptor(obj))
- setattr(obj, attr, 1)
- self.assertTrue(aenum._is_descriptor(obj))
-
- def test_is_sunder(self):
- for s in ('_a_', '_aa_'):
- self.assertTrue(aenum._is_sunder(s))
-
- for s in ('a', 'a_', '_a', '__a', 'a__', '__a__', '_a__', '__a_', '_',
- '__', '___', '____', '_____',):
- self.assertFalse(aenum._is_sunder(s))
-
- def test_is_dunder(self):
- for s in ('__a__', '__aa__'):
- self.assertTrue(aenum._is_dunder(s))
- for s in ('a', 'a_', '_a', '__a', 'a__', '_a_', '_a__', '__a_', '_',
- '__', '___', '____', '_____',):
- self.assertFalse(aenum._is_dunder(s))
-
- def test_auto(self):
- def tester(first, op, final, second=None):
- if second is None:
- left = auto()
- value = op(left)
- left.value = first
- self.assertEqual(value.value, final,
- "%s %r -> %r != %r" % (op.__name__, first, value, final))
- else:
- left = first
- right = auto()
- value = op(left, right)
- right.value = second
- self.assertEqual(value.value, final,
- "forward: %r %s %r -> %r != %r" % (first, op.__name__, second, value.value, final))
- left = auto()
- right = second
- value = op(left, right)
- left.value = first
- self.assertEqual(value.value, final,
- "reversed: %r %s %r -> %r != %r" % (second, op.__name__, first, value.value, final))
- for args in (
- (1, _abs_, abs(1)),
- (-3, _abs_, abs(-3)),
- (1, _add_, 1+2, 2),
- (25, _floordiv_, 25 // 5, 5),
- (49, _truediv_, 49 / 9, 9),
- (6, _mod_, 6 % 9, 9),
- (5, _lshift_, 5 << 2, 2),
- (5, _rshift_, 5 >> 2, 2),
- (3, _mul_, 3 * 6, 6),
- (5, _neg_, -5),
- (-4, _pos_, +(-4)),
- (2, _pow_, 2**5, 5),
- (7, _sub_, 7 - 10, 10),
- (1, _or_, 1 | 2, 2),
- (3, _xor_, 3 ^ 6, 6),
- (3, _and_, 3 & 6, 6),
- (7, _inv_, ~7),
- ('a', _add_, 'a'+'b', 'b'),
- ('a', _mul_, 'a' * 3, 3),
- ):
- tester(*args)
- # operator.div is gone in 3
- if PY2:
- tester(12, _div_, 12 // 5, 5)
- # strings are a pain
- left = auto()
- right = 'eggs'
- value = _mod_(left, right)
- left.value = 'I see 17 %s!'
- self.assertEqual(value.value, 'I see 17 %s!' % 'eggs')
-
- def test_constant(self):
- errors = []
- def tester(first, op, final, second=None):
- if second is None:
- primary = constant(first)
- secondary = constant(op(primary))
- if secondary.value != final:
- errors.append(
- "%s %r -> %r != %r" % (op.__name__, first, secondary.value, final),
- )
- else:
- left = constant(first)
- right = second
- value = op(left, right)
- if value != final:
- errors.append(
- "forward: %r %s %r -> %r != %r" % (first, op.__name__, second, value, final),
- )
- left = first
- right = constant(second)
- value = op(left, right)
- if value != final:
- errors.append(
- "reversed: %r %s %r -> %r != %r" % (second, op.__name__, first, value, final),
- )
- for args in (
- (1, _abs_, abs(1)),
- (-3, _abs_, abs(-3)),
- (1, _add_, 1+2, 2),
- (25, _floordiv_, 25 // 5, 5),
- (49, _truediv_, 49 / 9, 9),
- (6, _mod_, 6 % 9, 9),
- (5, _lshift_, 5 << 2, 2),
- (5, _rshift_, 5 >> 2, 2),
- (3, _mul_, 3 * 6, 6),
- (5, _neg_, -5),
- (-4, _pos_, +(-4)),
- (2, _pow_, 2**5, 5),
- (7, _sub_, 7 - 10, 10),
- (1, _or_, 1 | 2, 2),
- (3, _xor_, 3 ^ 6, 6),
- (3, _and_, 3 & 6, 6),
- (7, _inv_, ~7),
- ('a', _add_, 'a'+'b', 'b'),
- ('a', _mul_, 'a' * 3, 3),
- ):
- tester(*args)
- # operator.div is gone in 3
- if PY2:
- tester(12, _div_, 12 // 5, 5)
- # strings are a pain
- left = constant('I see 17 %s!')
- right = 'eggs'
- value = _mod_(left, right)
- if value != 'I see 17 %s!' % 'eggs':
- errors.append("'I see 17 eggs!' != %r" % value)
- if errors:
- print()
- for error in errors:
- print(error)
- self.assertTrue(False)
-
-
-class TestEnumType(TestCase):
-
- def test_immutability(self):
- class Hah(object):
- @classproperty
- def all_values(cls):
- return [m.value for m in cls]
- class Huh(Hah, Enum):
- one = 1
- two = 2
- self.assertRaisesRegex(AttributeError, 'cannot rebind property', setattr, Huh, 'value', 'boom')
- self.assertRaisesRegex(AttributeError, 'cannot delete property', delattr, Huh, 'value')
- self.assertRaisesRegex(AttributeError, 'cannot set attribute', setattr, Huh.one, 'value', 'boom')
- self.assertRaisesRegex(AttributeError, 'cannot delete attribute', delattr, Huh.two, 'value')
- self.assertEqual(Huh.one.value, 1)
- self.assertEqual(Huh.two.value, 2)
- self.assertEqual(Huh.all_values, [1, 2])
- setattr(Huh, 'all_values', 99)
- self.assertEqual(Huh.all_values, 99)
-
- def test_enum_shadow_base(self):
- class hohum(object):
- def cyan(self):
- "cyanize a color"
- return self.value * 'cyan'
- @property
- def azure(self):
- return 'azure ' + self.name
- class Color(hohum, Enum):
- red = 1
- green = 2
- blue = 3
- cyan = 4
- azure = 5
- self.assertEqual(len(Color), 5)
- self.assertEqual(list(Color), [Color.red, Color.green, Color.blue, Color.cyan, Color.azure])
- self.assertRaisesRegex(AttributeError, 'no attribute .cyan.', lambda: Color.blue.cyan)
- self.assertEqual(Color.red.azure, 'azure red')
-
-
-class TestEnum(TestCase):
-
- def setUp(self):
- class Season(Enum):
- SPRING = 1
- SUMMER = 2
- AUTUMN = 3
- WINTER = 4
- self.Season = Season
-
- class Konstants(float, Enum):
- E = 2.7182818
- PI = 3.1415926
- TAU = 2 * PI
- self.Konstants = Konstants
-
- class Grades(IntEnum):
- A = 5
- B = 4
- C = 3
- D = 2
- F = 0
- self.Grades = Grades
-
- class Directional(str, Enum):
- EAST = 'east'
- WEST = 'west'
- NORTH = 'north'
- SOUTH = 'south'
- self.Directional = Directional
-
- from datetime import date
- class Holiday(date, Enum):
- NEW_YEAR = 2013, 1, 1
- IDES_OF_MARCH = 2013, 3, 15
- self.Holiday = Holiday
-
- def test_set_name(self):
- class Descriptor(object):
- name = None
- def __get__(self, instance, owner_class=None):
- if instance is None:
- return self
- else:
- return instance.__dict__[self.name]
- def __set__(self, instance, value):
- instance.__dict__[self.name] = value
- def __set_name__(self, owner, name):
- self.name = name
- #
- class AnEnum(Enum):
- ONE = 'one'
- two = Descriptor()
- #
- self.assertEqual(list(AnEnum), [AnEnum.ONE])
- self.assertEqual(AnEnum.two.name, 'two')
- AnEnum.ONE.two = 'three'
- self.assertEqual(AnEnum.ONE.two, 'three')
- self.assertEqual(AnEnum.ONE.__dict__['two'], 'three')
-
- def test_private_names(self):
- class Private(Enum):
- __corporal = 'Radar'
- __major_ = 'Hoolihan'
- self.assertEqual(len(Private), 0)
- self.assertEqual(Private._Private__corporal, 'Radar')
- self.assertFalse(isinstance(Private._Private__corporal, Enum))
- self.assertEqual(Private._Private__major_, 'Hoolihan')
- self.assertFalse(isinstance(Private._Private__major_, Enum))
-
- def test_new_with_keywords(self):
- class Huh(IntEnum):
- __order__ = 'PLAIN BOLD_ITALIC HIGHLIGHT'
- def __new__(cls, docstring, open=None, close=None):
- value = len(cls.__members__)
- member = int.__new__(cls, value)
- if open and close is None:
- close = open
- member.open = open
- member.close = close
- member.__doc__ = docstring
- member._value_ = value
- return member
- PLAIN = 'normal'
- BOLD_ITALIC = '***really super important***', '***'
- HIGHLIGHT = 'please ==take notice==', '==', '=='
- p = Huh.PLAIN
- self.assertTrue(type(p) is Huh, type(p))
- self.assertEqual(
- (p.value, p.__doc__, p.open, p.close),
- (0, 'normal', None, None),
- )
- bi = Huh.BOLD_ITALIC
- self.assertEqual(
- (bi.value, bi.__doc__, bi.open, bi.close),
- (1, '***really super important***', '***', '***'),
- )
- h = Huh.HIGHLIGHT
- self.assertEqual(
- (h.value, h.__doc__, h.open, h.close),
- (2, 'please ==take notice==', '==', '=='),
- )
-
- def test_members_is_ordereddict_if_ordered(self):
- class Ordered(Enum):
- __order__ = 'first second third'
- first = 'bippity'
- second = 'boppity'
- third = 'boo'
- self.assertTrue(type(Ordered.__members__) is OrderedDict)
-
- def test_members_is_ordereddict_if_not_ordered(self):
- class Unordered(Enum):
- this = 'that'
- these = 'those'
- self.assertTrue(type(Unordered.__members__) is OrderedDict)
-
- def test_enum_in_enum_out(self):
- Season = self.Season
- self.assertTrue(Season(Season.WINTER) is Season.WINTER)
-
- def test_enum_value(self):
- Season = self.Season
- self.assertEqual(Season.SPRING.value, 1)
-
- def test_intenum_value(self):
- self.assertEqual(IntStooges.CURLY.value, 2)
-
- def test_enum(self):
- Season = self.Season
- lst = list(Season)
- self.assertEqual(len(lst), len(Season))
- self.assertEqual(len(Season), 4, Season)
- self.assertEqual(
- [Season.SPRING, Season.SUMMER, Season.AUTUMN, Season.WINTER], lst)
-
- for i, season in enumerate('SPRING SUMMER AUTUMN WINTER'.split()):
- i += 1
- e = Season(i)
- self.assertEqual(e, getattr(Season, season))
- self.assertEqual(e.value, i)
- self.assertNotEqual(e, i)
- self.assertEqual(e.name, season)
- self.assertTrue(e in Season)
- self.assertTrue(type(e) is Season)
- self.assertTrue(isinstance(e, Season))
- self.assertEqual(str(e), 'Season.' + season)
- self.assertEqual(
- repr(e),
- '<Season.%s: %s>' % (season, i),
- )
- def test_enum_helper(self):
- e1 = enum(1, 2, three=9)
- e2 = enum(1, 2, three=9)
- e3 = enum(1, 2, 9)
- self.assertTrue(e1 is not e2)
- self.assertEqual(e1, e2)
- self.assertNotEqual(e1, e3)
- self.assertNotEqual(e2, e3)
-
- def test_enum_in_enum(self):
- #
- class Level(Enum):
- _order_ = 'DATA_CHECK DESIGN_CHECK ALERT'
- #
- def __new__(cls, *args, **kwds):
- member = object.__new__(cls)
- member._value_ = len(cls) + 1 # members are 1-based
- return member
- #
- def __init__(self, prereq=None, dependent=None):
- # create priority level lists
- self.lower_priority_levels = list(self.__class__._member_map_.values())
- self.greater_priority_levels = []
- # update previous members' greater priority list
- for member in self.lower_priority_levels:
- member.greater_priority_levels.append(self)
- # and save prereq and dependent
- self.prerequisite = prereq and self.__class__[prereq.name] or None
- self.dependent = dependent and self.__class__[dependent.name] or None
- #
- DATA_CHECK = enum()
- DESIGN_CHECK = enum(DATA_CHECK)
- ALERT = enum(None, DATA_CHECK)
- #
- self.assertEqual(Level.DATA_CHECK.value, 1)
- self.assertEqual(Level.DATA_CHECK.prerequisite, None)
- self.assertEqual(Level.DATA_CHECK.dependent, None)
- self.assertEqual(Level.DESIGN_CHECK.prerequisite, Level.DATA_CHECK)
- self.assertEqual(Level.DESIGN_CHECK.dependent, None)
- self.assertEqual(Level.ALERT.prerequisite, None)
- self.assertEqual(Level.ALERT.dependent, Level.DATA_CHECK)
-
- def test_value_name(self):
- Season = self.Season
- self.assertEqual(Season.SPRING.name, 'SPRING')
- self.assertEqual(Season.SPRING.value, 1)
- def set_name(obj, new_value):
- obj.name = new_value
- def set_value(obj, new_value):
- obj.value = new_value
- self.assertRaises(AttributeError, set_name, Season.SPRING, 'invierno', )
- self.assertRaises(AttributeError, set_value, Season.SPRING, 2)
-
- def test_attribute_deletion(self):
- class Season(Enum):
- SPRING = 1
- SUMMER = 2
- AUTUMN = 3
- WINTER = 4
-
- def spam(cls):
- pass
-
- self.assertTrue(hasattr(Season, 'spam'))
- del Season.spam
- self.assertFalse(hasattr(Season, 'spam'))
-
- self.assertRaises(AttributeError, delattr, Season, 'SPRING')
- self.assertRaises(AttributeError, delattr, Season, 'DRY')
- self.assertRaises(AttributeError, delattr, Season.SPRING, 'name')
-
- def test_bool_of_class(self):
- class Empty(Enum):
- pass
- self.assertTrue(bool(Empty))
-
- def test_bool_of_member(self):
- class Count(Enum):
- zero = 0
- one = 1
- two = 2
- for member in Count:
- self.assertTrue(bool(member))
-
- def test_invalid_names(self):
- def create_bad_class_1():
- class Wrong(Enum):
- mro = 9
- def create_bad_class_2():
- class Wrong(Enum):
- _reserved_ = 3
- self.assertRaises(ValueError, create_bad_class_1)
- self.assertRaises(ValueError, create_bad_class_2)
-
- def test_bool(self):
- class Logic(Enum):
- true = True
- false = False
- def __bool__(self):
- return bool(self.value)
- __nonzero__ = __bool__
- self.assertTrue(Logic.true)
- self.assertFalse(Logic.false)
-
- def test_contains(self):
- Season = self.Season
- self.assertRaises(TypeError, lambda: 'AUTUMN' in Season)
- self.assertTrue(Season.AUTUMN in Season)
- self.assertRaises(TypeError, lambda: 3 not in Season)
- val = Season(3)
- self.assertTrue(val in Season)
- #
- class OtherEnum(Enum):
- one = 1; two = 2
- self.assertTrue(OtherEnum.two not in Season)
- #
- class Wierd(Enum):
- this = [1, 2, 3]
- that = (1, 2, 3)
- those = {1: 1, 2: 2, 3: 3}
- self.assertTrue(Wierd.this in Wierd)
- self.assertRaises(TypeError, lambda: [1, 2, 3] in Wierd)
- self.assertRaises(TypeError, lambda: {1: 1, 2: 2, 3: 3} in Wierd)
-
- def test_member_contains(self):
- self.assertRaises(TypeError, lambda: 'test' in self.Season.AUTUMN)
-
- if pyver >= PY2_6: # when `format` came into being
-
- def test_format_enum(self):
- Season = self.Season
- self.assertEqual('{0}'.format(Season.SPRING),
- '{0}'.format(str(Season.SPRING)))
- self.assertEqual( '{0:}'.format(Season.SPRING),
- '{0:}'.format(str(Season.SPRING)))
- self.assertEqual('{0:20}'.format(Season.SPRING),
- '{0:20}'.format(str(Season.SPRING)))
- self.assertEqual('{0:^20}'.format(Season.SPRING),
- '{0:^20}'.format(str(Season.SPRING)))
- self.assertEqual('{0:>20}'.format(Season.SPRING),
- '{0:>20}'.format(str(Season.SPRING)))
- self.assertEqual('{0:<20}'.format(Season.SPRING),
- '{0:<20}'.format(str(Season.SPRING)))
-
- def test_custom_format(self):
- class TestFloat(float, Enum):
- one = 1.0
- two = 2.0
- def __format__(self, spec):
- return 'TestFloat success!'
- self.assertEqual(str(TestFloat.one), 'TestFloat.one')
- self.assertEqual('{0}'.format(TestFloat.one), 'TestFloat success!')
-
- def test_format_with_custom_str(self):
- class TestInt(int, Enum):
- one = 1
- two = 2
- def __str__(self):
- return self.name * 3
- self.assertEqual(str(TestInt.two), 'twotwotwo')
- self.assertEqual('{0}'.format(TestInt.two), 'twotwotwo')
-
- def assertFormatIsValue(self, spec, member):
- self.assertEqual(spec.format(member), spec.format(member.value))
-
- def test_format_enum_date(self):
- Holiday = self.Holiday
- self.assertFormatIsValue('{0}', Holiday.IDES_OF_MARCH)
- self.assertFormatIsValue('{0:}', Holiday.IDES_OF_MARCH)
- self.assertFormatIsValue('{0:20}', Holiday.IDES_OF_MARCH)
- self.assertFormatIsValue('{0:^20}', Holiday.IDES_OF_MARCH)
- self.assertFormatIsValue('{0:>20}', Holiday.IDES_OF_MARCH)
- self.assertFormatIsValue('{0:<20}', Holiday.IDES_OF_MARCH)
- self.assertFormatIsValue('{0:%Y %m}', Holiday.IDES_OF_MARCH)
- self.assertFormatIsValue('{0:%Y %m %M:00}', Holiday.IDES_OF_MARCH)
-
- def test_format_enum_float(self):
- Konstants = self.Konstants
- self.assertFormatIsValue('{0}', Konstants.TAU)
- self.assertFormatIsValue('{0:}', Konstants.TAU)
- self.assertFormatIsValue('{0:20}', Konstants.TAU)
- self.assertFormatIsValue('{0:^20}', Konstants.TAU)
- self.assertFormatIsValue('{0:>20}', Konstants.TAU)
- self.assertFormatIsValue('{0:<20}', Konstants.TAU)
- self.assertFormatIsValue('{0:n}', Konstants.TAU)
- self.assertFormatIsValue('{0:5.2}', Konstants.TAU)
- self.assertFormatIsValue('{0:f}', Konstants.TAU)
-
- def test_format_enum_int(self):
- Grades = self.Grades
- self.assertFormatIsValue('{0}', Grades.C)
- self.assertFormatIsValue('{0:}', Grades.C)
- self.assertFormatIsValue('{0:20}', Grades.C)
- self.assertFormatIsValue('{0:^20}', Grades.C)
- self.assertFormatIsValue('{0:>20}', Grades.C)
- self.assertFormatIsValue('{0:<20}', Grades.C)
- self.assertFormatIsValue('{0:+}', Grades.C)
- self.assertFormatIsValue('{0:08X}', Grades.C)
- self.assertFormatIsValue('{0:b}', Grades.C)
-
- def test_format_enum_str(self):
- Directional = self.Directional
- self.assertFormatIsValue('{0}', Directional.WEST)
- self.assertFormatIsValue('{0:}', Directional.WEST)
- self.assertFormatIsValue('{0:20}', Directional.WEST)
- self.assertFormatIsValue('{0:^20}', Directional.WEST)
- self.assertFormatIsValue('{0:>20}', Directional.WEST)
- self.assertFormatIsValue('{0:<20}', Directional.WEST)
-
- def test_hash(self):
- Season = self.Season
- dates = {}
- dates[Season.WINTER] = '1225'
- dates[Season.SPRING] = '0315'
- dates[Season.SUMMER] = '0704'
- dates[Season.AUTUMN] = '1031'
- self.assertEqual(dates[Season.AUTUMN], '1031')
-
- def test_enum_duplicates(self):
- class Season(Enum):
- __order__ = "SPRING SUMMER AUTUMN WINTER"
- SPRING = 1
- SUMMER = 2
- AUTUMN = FALL = 3
- WINTER = 4
- ANOTHER_SPRING = 1
- lst = list(Season)
- self.assertEqual(
- lst,
- [Season.SPRING, Season.SUMMER,
- Season.AUTUMN, Season.WINTER,
- ])
- self.assertTrue(Season.FALL is Season.AUTUMN)
- self.assertEqual(Season.FALL.value, 3)
- self.assertEqual(Season.AUTUMN.value, 3)
- self.assertTrue(Season(3) is Season.AUTUMN)
- self.assertTrue(Season(1) is Season.SPRING)
- self.assertEqual(Season.FALL.name, 'AUTUMN')
- self.assertEqual(
- set([k for k,v in Season.__members__.items() if v.name != k]),
- set(['FALL', 'ANOTHER_SPRING']),
- )
-
- def test_enum_with_value_name(self):
- class Huh(Enum):
- _order_ = 'name value'
- name = 1
- value = 2
- self.assertEqual(
- list(Huh),
- [Huh.name, Huh.value],
- )
- self.assertTrue(type(Huh.name) is Huh)
- self.assertEqual(Huh.name.name, 'name')
- self.assertEqual(Huh.name.value, 1)
-
- def test_intenum_from_scratch(self):
- class phy(int, Enum):
- pi = 3
- tau = 2 * pi
- self.assertTrue(phy.pi < phy.tau)
-
- def test_intenum_inherited(self):
- class IntEnum(int, Enum):
- pass
- class phy(IntEnum):
- pi = 3
- tau = 2 * pi
- self.assertTrue(phy.pi < phy.tau)
-
- def test_floatenum_from_scratch(self):
- class phy(float, Enum):
- pi = 3.1415926
- tau = 2 * pi
- self.assertTrue(phy.pi < phy.tau)
-
- def test_floatenum_inherited(self):
- class FloatEnum(float, Enum):
- pass
- class phy(FloatEnum):
- pi = 3.1415926
- tau = 2 * pi
- self.assertTrue(phy.pi < phy.tau)
-
- def test_strenum_from_scratch(self):
- class phy(str, Enum):
- pi = 'Pi'
- tau = 'Tau'
- self.assertTrue(phy.pi < phy.tau)
-
- def test_intenum(self):
- class WeekDay(IntEnum):
- SUNDAY = 1
- MONDAY = 2
- TUESDAY = 3
- WEDNESDAY = 4
- THURSDAY = 5
- FRIDAY = 6
- SATURDAY = 7
-
- self.assertEqual(['a', 'b', 'c'][WeekDay.MONDAY], 'c')
- self.assertEqual([i for i in range(WeekDay.TUESDAY)], [0, 1, 2])
-
- lst = list(WeekDay)
- self.assertEqual(len(lst), len(WeekDay))
- self.assertEqual(len(WeekDay), 7)
- target = 'SUNDAY MONDAY TUESDAY WEDNESDAY THURSDAY FRIDAY SATURDAY'
- target = target.split()
- for i, weekday in enumerate(target):
- i += 1
- e = WeekDay(i)
- self.assertEqual(e, i)
- self.assertEqual(int(e), i)
- self.assertEqual(e.name, weekday)
- self.assertTrue(e in WeekDay)
- self.assertEqual(lst.index(e)+1, i)
- self.assertTrue(0 < e < 8)
- self.assertTrue(type(e) is WeekDay)
- self.assertTrue(isinstance(e, int))
- self.assertTrue(isinstance(e, Enum))
-
- def test_intenum_duplicates(self):
- class WeekDay(IntEnum):
- __order__ = 'SUNDAY MONDAY TUESDAY WEDNESDAY THURSDAY FRIDAY SATURDAY'
- SUNDAY = 1
- MONDAY = 2
- TUESDAY = TEUSDAY = 3
- WEDNESDAY = 4
- THURSDAY = 5
- FRIDAY = 6
- SATURDAY = 7
- self.assertTrue(WeekDay.TEUSDAY is WeekDay.TUESDAY)
- self.assertEqual(WeekDay(3).name, 'TUESDAY')
- self.assertEqual([k for k,v in WeekDay.__members__.items()
- if v.name != k], ['TEUSDAY', ])
-
- def test_floatenum_fromhex(self):
- h = float.hex(FloatStooges.MOE.value)
- self.assertIs(FloatStooges.fromhex(h), FloatStooges.MOE)
- h = float.hex(FloatStooges.MOE.value + 0.01)
- with self.assertRaises(ValueError):
- FloatStooges.fromhex(h)
-
- def test_pickle_enum(self):
- if isinstance(Stooges, Exception):
- raise Stooges
- test_pickle_dump_load(self.assertTrue, Stooges.CURLY)
- test_pickle_dump_load(self.assertTrue, Stooges)
-
- def test_pickle_int(self):
- if isinstance(IntStooges, Exception):
- raise IntStooges
- test_pickle_dump_load(self.assertTrue, IntStooges.CURLY)
- test_pickle_dump_load(self.assertTrue, IntStooges)
-
- def test_pickle_float(self):
- if isinstance(FloatStooges, Exception):
- raise FloatStooges
- test_pickle_dump_load(self.assertTrue, FloatStooges.CURLY)
- test_pickle_dump_load(self.assertTrue, FloatStooges)
-
- def test_pickle_enum_function(self):
- if isinstance(Answer, Exception):
- raise Answer
- test_pickle_dump_load(self.assertTrue, Answer.him)
- test_pickle_dump_load(self.assertTrue, Answer)
-
- def test_pickle_enum_function_with_module(self):
- if isinstance(Question, Exception):
- raise Question
- test_pickle_dump_load(self.assertTrue, Question.who)
- test_pickle_dump_load(self.assertTrue, Question)
-
- def test_pickle_by_name(self):
- class ReplaceGlobalInt(IntEnum):
- ONE = 1
- TWO = 2
- ReplaceGlobalInt.__reduce_ex__ = _reduce_ex_by_name
- for proto in range(HIGHEST_PROTOCOL):
- self.assertEqual(ReplaceGlobalInt.TWO.__reduce_ex__(proto), 'TWO')
-
- def test_exploding_pickle(self):
- BadPickle = Enum('BadPickle', 'dill sweet bread-n-butter')
- aenum._make_class_unpicklable(BadPickle)
- globals()['BadPickle'] = BadPickle
- test_pickle_exception(self.assertRaises, TypeError, BadPickle.dill)
- test_pickle_exception(self.assertRaises, PicklingError, BadPickle)
-
- def test_string_enum(self):
- class SkillLevel(str, Enum):
- master = 'what is the sound of one hand clapping?'
- journeyman = 'why did the chicken cross the road?'
- apprentice = 'knock, knock!'
- self.assertEqual(SkillLevel.apprentice, 'knock, knock!')
-
- def test_getattr_getitem(self):
- class Period(Enum):
- morning = 1
- noon = 2
- evening = 3
- night = 4
- self.assertTrue(Period(2) is Period.noon)
- self.assertTrue(getattr(Period, 'night') is Period.night)
- self.assertTrue(Period['morning'] is Period.morning)
-
- def test_getattr_dunder(self):
- Season = self.Season
- self.assertTrue(getattr(Season, '__hash__'))
-
- def test_iteration_order(self):
- class Season(Enum):
- __order__ = 'SUMMER WINTER AUTUMN SPRING'
- SUMMER = 2
- WINTER = 4
- AUTUMN = 3
- SPRING = 1
- self.assertEqual(
- list(Season),
- [Season.SUMMER, Season.WINTER, Season.AUTUMN, Season.SPRING],
- )
-
- def test_iteration_order_reversed(self):
- self.assertEqual(
- list(reversed(self.Season)),
- [self.Season.WINTER, self.Season.AUTUMN, self.Season.SUMMER,
- self.Season.SPRING]
- )
-
- def test_iteration_order_with_unorderable_values(self):
- class Complex(Enum):
- a = complex(7, 9)
- b = complex(3.14, 2)
- c = complex(1, -1)
- d = complex(-77, 32)
- self.assertEqual(
- list(Complex),
- [Complex.a, Complex.b, Complex.c, Complex.d],
- )
-
- def test_programatic_function_string(self):
- SummerMonth = Enum('SummerMonth', 'june july august')
- lst = list(SummerMonth)
- self.assertEqual(len(lst), len(SummerMonth))
- self.assertEqual(len(SummerMonth), 3, SummerMonth)
- self.assertEqual(
- [SummerMonth.june, SummerMonth.july, SummerMonth.august],
- lst,
- )
- for i, month in enumerate('june july august'.split()):
- i += 1
- e = SummerMonth(i)
- self.assertEqual(int(e.value), i)
- self.assertNotEqual(e, i)
- self.assertEqual(e.name, month)
- self.assertTrue(e in SummerMonth)
- self.assertTrue(type(e) is SummerMonth)
-
- def test_programatic_function_string_with_start(self):
- SummerMonth = Enum('SummerMonth', 'june july august', start=10)
- lst = list(SummerMonth)
- self.assertEqual(len(lst), len(SummerMonth))
- self.assertEqual(len(SummerMonth), 3, SummerMonth)
- self.assertEqual(
- [SummerMonth.june, SummerMonth.july, SummerMonth.august],
- lst,
- )
- for i, month in enumerate('june july august'.split(), 10):
- e = SummerMonth(i)
- self.assertEqual(int(e.value), i)
- self.assertNotEqual(e, i)
- self.assertEqual(e.name, month)
- self.assertTrue(e in SummerMonth)
- self.assertTrue(type(e) is SummerMonth)
-
- def test_programatic_function_string_list(self):
- SummerMonth = Enum('SummerMonth', ['june', 'july', 'august'])
- lst = list(SummerMonth)
- self.assertEqual(len(lst), len(SummerMonth))
- self.assertEqual(len(SummerMonth), 3, SummerMonth)
- self.assertEqual(
- [SummerMonth.june, SummerMonth.july, SummerMonth.august],
- lst,
- )
- for i, month in enumerate('june july august'.split()):
- i += 1
- e = SummerMonth(i)
- self.assertEqual(int(e.value), i)
- self.assertNotEqual(e, i)
- self.assertEqual(e.name, month)
- self.assertTrue(e in SummerMonth)
- self.assertTrue(type(e) is SummerMonth)
-
- def test_programatic_function_string_list_with_start(self):
- SummerMonth = Enum('SummerMonth', ['june', 'july', 'august'], start=20)
- lst = list(SummerMonth)
- self.assertEqual(len(lst), len(SummerMonth))
- self.assertEqual(len(SummerMonth), 3, SummerMonth)
- self.assertEqual(
- [SummerMonth.june, SummerMonth.july, SummerMonth.august],
- lst,
- )
- for i, month in enumerate('june july august'.split(), 20):
- e = SummerMonth(i)
- self.assertEqual(int(e.value), i)
- self.assertNotEqual(e, i)
- self.assertEqual(e.name, month)
- self.assertTrue(e in SummerMonth)
- self.assertTrue(type(e) is SummerMonth)
-
- def test_programatic_function_iterable(self):
- SummerMonth = Enum(
- 'SummerMonth',
- (('june', 1), ('july', 2), ('august', 3))
- )
- lst = list(SummerMonth)
- self.assertEqual(len(lst), len(SummerMonth))
- self.assertEqual(len(SummerMonth), 3, SummerMonth)
- self.assertEqual(
- [SummerMonth.june, SummerMonth.july, SummerMonth.august],
- lst,
- )
- for i, month in enumerate('june july august'.split()):
- i += 1
- e = SummerMonth(i)
- self.assertEqual(int(e.value), i)
- self.assertNotEqual(e, i)
- self.assertEqual(e.name, month)
- self.assertTrue(e in SummerMonth)
- self.assertTrue(type(e) is SummerMonth)
-
- def test_programatic_function_from_dict(self):
- SummerMonth = Enum(
- 'SummerMonth',
- dict((('june', 1), ('july', 2), ('august', 3)))
- )
- lst = list(SummerMonth)
- self.assertEqual(len(lst), len(SummerMonth))
- self.assertEqual(len(SummerMonth), 3, SummerMonth)
- if PY2:
- self.assertEqual(
- [SummerMonth.june, SummerMonth.july, SummerMonth.august],
- lst,
- )
- for i, month in enumerate('june july august'.split()):
- i += 1
- e = SummerMonth(i)
- self.assertEqual(int(e.value), i)
- self.assertNotEqual(e, i)
- self.assertEqual(e.name, month)
- self.assertTrue(e in SummerMonth)
- self.assertTrue(type(e) is SummerMonth)
-
- def test_programatic_function_type(self):
- SummerMonth = Enum('SummerMonth', 'june july august', type=int)
- lst = list(SummerMonth)
- self.assertEqual(len(lst), len(SummerMonth))
- self.assertEqual(len(SummerMonth), 3, SummerMonth)
- self.assertEqual(
- [SummerMonth.june, SummerMonth.july, SummerMonth.august],
- lst,
- )
- for i, month in enumerate('june july august'.split()):
- i += 1
- e = SummerMonth(i)
- self.assertEqual(e, i)
- self.assertEqual(e.name, month)
- self.assertTrue(e in SummerMonth)
- self.assertTrue(type(e) is SummerMonth)
-
- def test_programatic_function_type_with_start(self):
- SummerMonth = Enum('SummerMonth', 'june july august', type=int, start=30)
- lst = list(SummerMonth)
- self.assertEqual(len(lst), len(SummerMonth))
- self.assertEqual(len(SummerMonth), 3, SummerMonth)
- self.assertEqual(
- [SummerMonth.june, SummerMonth.july, SummerMonth.august],
- lst,
- )
- for i, month in enumerate('june july august'.split(), 30):
- e = SummerMonth(i)
- self.assertEqual(e, i)
- self.assertEqual(e.name, month)
- self.assertTrue(e in SummerMonth)
- self.assertTrue(type(e) is SummerMonth)
-
- def test_programatic_function_type_from_subclass(self):
- SummerMonth = IntEnum('SummerMonth', 'june july august')
- lst = list(SummerMonth)
- self.assertEqual(len(lst), len(SummerMonth))
- self.assertEqual(len(SummerMonth), 3, SummerMonth)
- self.assertEqual(
- [SummerMonth.june, SummerMonth.july, SummerMonth.august],
- lst,
- )
- for i, month in enumerate('june july august'.split()):
- i += 1
- e = SummerMonth(i)
- self.assertEqual(e, i)
- self.assertEqual(e.name, month)
- self.assertTrue(e in SummerMonth)
- self.assertTrue(type(e) is SummerMonth)
-
- def test_programatic_function_type_from_subclass_with_start(self):
- SummerMonth = IntEnum('SummerMonth', 'june july august', start=40)
- lst = list(SummerMonth)
- self.assertEqual(len(lst), len(SummerMonth))
- self.assertEqual(len(SummerMonth), 3, SummerMonth)
- self.assertEqual(
- [SummerMonth.june, SummerMonth.july, SummerMonth.august],
- lst,
- )
- for i, month in enumerate('june july august'.split(), 40):
- e = SummerMonth(i)
- self.assertEqual(e, i)
- self.assertEqual(e.name, month)
- self.assertTrue(e in SummerMonth)
- self.assertTrue(type(e) is SummerMonth)
-
- def test_programatic_function_unicode(self):
- SummerMonth = Enum('SummerMonth', unicode('june july august'))
- lst = list(SummerMonth)
- self.assertEqual(len(lst), len(SummerMonth))
- self.assertEqual(len(SummerMonth), 3, SummerMonth)
- self.assertEqual(
- [SummerMonth.june, SummerMonth.july, SummerMonth.august],
- lst,
- )
- for i, month in enumerate(unicode('june july august').split()):
- i += 1
- e = SummerMonth(i)
- self.assertEqual(int(e.value), i)
- self.assertNotEqual(e, i)
- self.assertEqual(e.name, month)
- self.assertTrue(e in SummerMonth)
- self.assertTrue(type(e) is SummerMonth)
-
- def test_programatic_function_unicode_list(self):
- SummerMonth = Enum('SummerMonth', [unicode('june'), unicode('july'), unicode('august')])
- lst = list(SummerMonth)
- self.assertEqual(len(lst), len(SummerMonth))
- self.assertEqual(len(SummerMonth), 3, SummerMonth)
- self.assertEqual(
- [SummerMonth.june, SummerMonth.july, SummerMonth.august],
- lst,
- )
- for i, month in enumerate(unicode('june july august').split()):
- i += 1
- e = SummerMonth(i)
- self.assertEqual(int(e.value), i)
- self.assertNotEqual(e, i)
- self.assertEqual(e.name, month)
- self.assertTrue(e in SummerMonth)
- self.assertTrue(type(e) is SummerMonth)
-
- def test_programatic_function_unicode_iterable(self):
- SummerMonth = Enum(
- 'SummerMonth',
- ((unicode('june'), 1), (unicode('july'), 2), (unicode('august'), 3))
- )
- lst = list(SummerMonth)
- self.assertEqual(len(lst), len(SummerMonth))
- self.assertEqual(len(SummerMonth), 3, SummerMonth)
- self.assertEqual(
- [SummerMonth.june, SummerMonth.july, SummerMonth.august],
- lst,
- )
- for i, month in enumerate(unicode('june july august').split()):
- i += 1
- e = SummerMonth(i)
- self.assertEqual(int(e.value), i)
- self.assertNotEqual(e, i)
- self.assertEqual(e.name, month)
- self.assertTrue(e in SummerMonth)
- self.assertTrue(type(e) is SummerMonth)
-
- def test_programatic_function_from_unicode_dict(self):
- SummerMonth = Enum(
- 'SummerMonth',
- dict(((unicode('june'), 1), (unicode('july'), 2), (unicode('august'), 3)))
- )
- lst = list(SummerMonth)
- self.assertEqual(len(lst), len(SummerMonth))
- self.assertEqual(len(SummerMonth), 3, SummerMonth)
- if PY2:
- self.assertEqual(
- [SummerMonth.june, SummerMonth.july, SummerMonth.august],
- lst,
- )
- for i, month in enumerate(unicode('june july august').split()):
- i += 1
- e = SummerMonth(i)
- self.assertEqual(int(e.value), i)
- self.assertNotEqual(e, i)
- self.assertEqual(e.name, month)
- self.assertTrue(e in SummerMonth)
- self.assertTrue(type(e) is SummerMonth)
-
- def test_programatic_function_unicode_type(self):
- SummerMonth = Enum('SummerMonth', unicode('june july august'), type=int)
- lst = list(SummerMonth)
- self.assertEqual(len(lst), len(SummerMonth))
- self.assertEqual(len(SummerMonth), 3, SummerMonth)
- self.assertEqual(
- [SummerMonth.june, SummerMonth.july, SummerMonth.august],
- lst,
- )
- for i, month in enumerate(unicode('june july august').split()):
- i += 1
- e = SummerMonth(i)
- self.assertEqual(e, i)
- self.assertEqual(e.name, month)
- self.assertTrue(e in SummerMonth)
- self.assertTrue(type(e) is SummerMonth)
-
- def test_programatic_function_unicode_type_from_subclass(self):
- SummerMonth = IntEnum('SummerMonth', unicode('june july august'))
- lst = list(SummerMonth)
- self.assertEqual(len(lst), len(SummerMonth))
- self.assertEqual(len(SummerMonth), 3, SummerMonth)
- self.assertEqual(
- [SummerMonth.june, SummerMonth.july, SummerMonth.august],
- lst,
- )
- for i, month in enumerate(unicode('june july august').split()):
- i += 1
- e = SummerMonth(i)
- self.assertEqual(e, i)
- self.assertEqual(e.name, month)
- self.assertTrue(e in SummerMonth)
- self.assertTrue(type(e) is SummerMonth)
-
- def test_programmatic_function_unicode_class(self):
- if PY2:
- class_names = unicode('SummerMonth'), 'S\xfcmm\xe9rM\xf6nth'.decode('latin1')
- else:
- class_names = 'SummerMonth', 'S\xfcmm\xe9rM\xf6nth'
- for i, class_name in enumerate(class_names):
- if PY2 and i == 1:
- self.assertRaises(TypeError, Enum, class_name, unicode('june july august'))
- else:
- SummerMonth = Enum(class_name, unicode('june july august'))
- lst = list(SummerMonth)
- self.assertEqual(len(lst), len(SummerMonth))
- self.assertEqual(len(SummerMonth), 3, SummerMonth)
- self.assertEqual(
- [SummerMonth.june, SummerMonth.july, SummerMonth.august],
- lst,
- )
- for i, month in enumerate(unicode('june july august').split()):
- i += 1
- e = SummerMonth(i)
- self.assertEqual(e.value, i)
- self.assertEqual(e.name, month)
- self.assertTrue(e in SummerMonth)
- self.assertTrue(type(e) is SummerMonth)
-
- def test_subclassing(self):
- if isinstance(Name, Exception):
- raise Name
- self.assertEqual(Name.BDFL, 'Guido van Rossum')
- self.assertTrue(Name.BDFL, Name('Guido van Rossum'))
- self.assertTrue(Name.BDFL is getattr(Name, 'BDFL'))
- test_pickle_dump_load(self.assertTrue, Name.BDFL)
-
- def test_extending(self):
- def bad_extension():
- class Color(Enum):
- red = 1
- green = 2
- blue = 3
- class MoreColor(Color):
- cyan = 4
- magenta = 5
- yellow = 6
- self.assertRaises(TypeError, bad_extension)
-
- def test_exclude_methods(self):
- class whatever(Enum):
- this = 'that'
- these = 'those'
- def really(self):
- return 'no, not %s' % self.value
- self.assertFalse(type(whatever.really) is whatever)
- self.assertEqual(whatever.this.really(), 'no, not that')
-
- def test_wrong_inheritance_order(self):
- def wrong_inherit():
- class Wrong(Enum, str):
- NotHere = 'error before this point'
- self.assertRaises(TypeError, wrong_inherit)
-
- def test_intenum_transitivity(self):
- class number(IntEnum):
- one = 1
- two = 2
- three = 3
- class numero(IntEnum):
- uno = 1
- dos = 2
- tres = 3
- self.assertEqual(number.one, numero.uno)
- self.assertEqual(number.two, numero.dos)
- self.assertEqual(number.three, numero.tres)
-
- def test_introspection(self):
- class Number(IntEnum):
- one = 100
- two = 200
- self.assertTrue(Number.one._member_type_ is int)
- self.assertTrue(Number._member_type_ is int)
- class String(str, Enum):
- yarn = 'soft'
- rope = 'rough'
- wire = 'hard'
- self.assertTrue(String.yarn._member_type_ is str)
- self.assertTrue(String._member_type_ is str)
- class Plain(Enum):
- vanilla = 'white'
- one = 1
- self.assertTrue(Plain.vanilla._member_type_ is object)
- self.assertTrue(Plain._member_type_ is object)
-
- def test_wrong_enum_in_call(self):
- class Monochrome(Enum):
- black = 0
- white = 1
- class Gender(Enum):
- male = 0
- female = 1
- self.assertRaises(ValueError, Monochrome, Gender.male)
-
- def test_wrong_enum_in_mixed_call(self):
- class Monochrome(IntEnum):
- black = 0
- white = 1
- class Gender(Enum):
- male = 0
- female = 1
- self.assertRaises(ValueError, Monochrome, Gender.male)
-
- def test_mixed_enum_in_call_1(self):
- class Monochrome(IntEnum):
- black = 0
- white = 1
- class Gender(IntEnum):
- male = 0
- female = 1
- self.assertTrue(Monochrome(Gender.female) is Monochrome.white)
-
- def test_mixed_enum_in_call_2(self):
- class Monochrome(Enum):
- black = 0
- white = 1
- class Gender(IntEnum):
- male = 0
- female = 1
- self.assertTrue(Monochrome(Gender.male) is Monochrome.black)
-
- def test_flufl_enum(self):
- class Fluflnum(Enum):
- def __int__(self):
- return int(self.value)
- class MailManOptions(Fluflnum):
- option1 = 1
- option2 = 2
- option3 = 3
- self.assertEqual(int(MailManOptions.option1), 1)
-
- def test_no_such_enum_member(self):
- class Color(Enum):
- red = 1
- green = 2
- blue = 3
- self.assertRaises(ValueError, Color, 4)
- self.assertRaises(KeyError, Color.__getitem__, 'chartreuse')
-
- def test_new_repr(self):
- class Color(Enum):
- red = 1
- green = 2
- blue = 3
- def __repr__(self):
- return "don't you just love shades of %s?" % self.name
- self.assertEqual(
- repr(Color.blue),
- "don't you just love shades of blue?",
- )
-
- def test_inherited_repr(self):
- class MyEnum(Enum):
- def __repr__(self):
- return "My name is %s." % self.name
- class MyIntEnum(int, MyEnum):
- this = 1
- that = 2
- theother = 3
- self.assertEqual(repr(MyIntEnum.that), "My name is that.")
-
- def test_multiple_mixin_mro(self):
- class auto_enum(EnumMeta):
- def __new__(metacls, cls, bases, classdict):
- original_dict = classdict
- temp_dict = metacls.__prepare__(cls, bases, {})
- if hasattr(original_dict, '_member_names'):
- for k in original_dict._member_names:
- temp_dict[k] = original_dict[k]
- sunders = [k for k in original_dict.keys() if aenum._is_sunder(k)]
- else:
- sunders = []
- for k, v in original_dict.items():
- if aenum._is_sunder(k):
- sunders.append(k)
- temp_dict[k] = v
- classdict = metacls.__prepare__(cls, bases, {})
- i = 0
- for k in sunders:
- classdict[k] = original_dict[k]
- for k in temp_dict._member_names:
- v = original_dict[k]
- if v == ():
- v = i
- else:
- i = v
- i += 1
- classdict[k] = v
- for k, v in original_dict.items():
- if k not in temp_dict._member_names and k not in sunders:
- classdict[k] = v
- return super(auto_enum, metacls).__new__(
- metacls, cls, bases, classdict)
-
- AutoNumberedEnum = auto_enum('AutoNumberedEnum', (Enum,), {})
-
- AutoIntEnum = auto_enum('AutoIntEnum', (IntEnum,), {})
-
- # class TestAutoNumber(AutoNumberedEnum):
- # a = ()
- # b = 3
- # c = ()
- # self.assertEqual(TestAutoNumber.b.value, 3)
- #
- # if pyver >= 3.0:
- # self.assertEqual(
- # [TestAutoNumber.a.value, TestAutoNumber.b.value, TestAutoNumber.c.value],
- # [0, 3, 4],
- # )
- #
- # class TestAutoInt(AutoIntEnum):
- # a = ()
- # b = 3
- # c = ()
- # self.assertEqual(TestAutoInt.b, 3)
- #
- # if pyver >= 3.0:
- # self.assertEqual(
- # [TestAutoInt.a.value, TestAutoInt.b.value, TestAutoInt.c.value],
- # [0, 3, 4],
- # )
-
- def test_meta_reconfigure(self):
-
- def identity(*args):
- if len(args) == 1:
- return args[0]
- return args
-
- JSONEnum = None
-
- class JSONEnumMeta(EnumMeta):
-
- @classmethod
- def __prepare__(metacls, cls, bases, init=None, start=None, settings=()):
- return {}
-
- def __init__(cls, *args , **kwds):
- super(JSONEnumMeta, cls).__init__(*args)
-
- def __new__(metacls, cls, bases, clsdict, init=None, start=None, settings=()):
- import json
- members = []
- if JSONEnum is not None:
- if '_file' not in clsdict:
- raise TypeError('_file is required')
- if '_name' not in clsdict:
- raise TypeError('_name is required')
- if '_value' not in clsdict:
- raise TypeError('_value is required')
- name_spec = clsdict.pop('_name')
- if not isinstance(name_spec, (tuple, list)):
- name_spec = (name_spec, )
- value_spec = clsdict.pop('_value')
- file = clsdict.pop('_file')
- with open(file) as f:
- json_data = json.load(f)
- for data in json_data:
- values = []
- name = data[name_spec[0]]
- for piece in name_spec[1:]:
- name = name[piece]
- for order, (value_path, func) in sorted(value_spec.items()):
- if not isinstance(value_path, (list, tuple)):
- value_path = (value_path, )
- value = data[value_path[0]]
- for piece in value_path[1:]:
- value = value[piece]
- if func is not None:
- value = func(value)
- values.append(value)
- values = tuple(values)
- members.append(
- (name, identity(*values))
- )
- # get the real EnumDict
- enum_dict = super(JSONEnumMeta, metacls).__prepare__(cls, bases, init, start, settings)
- # transfer the original dict content, _items first
- items = list(clsdict.items())
- items.sort(key=lambda p: (0 if p[0][0] == '_' else 1, p))
- for name, value in items:
- enum_dict[name] = value
- # add the members
- for name, value in members:
- enum_dict[name] = value
- return super(JSONEnumMeta, metacls).__new__(metacls, cls, bases, enum_dict, init, start, settings)
-
- # for use with both Python 2/3
- JSONEnum = JSONEnumMeta('JsonEnum', (Enum, ), {})
-
- test_file = os.path.join(tempdir, 'test_json.json')
- with open(test_file, 'w') as f:
- f.write(
- '[{"name":"Afghanistan","alpha-2":"AF","country-code":"004","notes":{"description":"pretty"}},'
- '{"name":"Åland Islands","alpha-2":"AX","country-code":"248","notes":{"description":"serene"}},'
- '{"name":"Albania","alpha-2":"AL","country-code":"008","notes":{"description":"exciting"}},'
- '{"name":"Algeria","alpha-2":"DZ","country-code":"012","notes":{"description":"scarce"}}]')
-
- class Country(JSONEnum):
- _init_ = 'abbr code country_name description'
- _file = test_file
- _name = 'alpha-2'
- _value = {
- 1: ('alpha-2', None),
- 2: ('country-code', lambda c: int(c)),
- 3: ('name', None),
- 4: (('notes','description'), lambda s: s.title()),
- }
-
- self.assertEqual([Country.AF, Country.AX, Country.AL, Country.DZ], list(Country))
- self.assertEqual(Country.AF.abbr, 'AF')
- self.assertEqual(Country.AX.code, 248)
- self.assertEqual(Country.AL.country_name, 'Albania')
- self.assertEqual(Country.DZ.description, 'Scarce')
-
-
- def test_subclasses_with_getnewargs(self):
- class NamedInt(int):
- __qualname__ = 'NamedInt' # needed for pickle protocol 4
- def __new__(cls, *args):
- _args = args
- if len(args) < 1:
- raise TypeError("name and value must be specified")
- name, args = args[0], args[1:]
- self = int.__new__(cls, *args)
- self._intname = name
- self._args = _args
- return self
- def __getnewargs__(self):
- return self._args
- @property
- def __name__(self):
- return self._intname
- def __repr__(self):
- # repr() is updated to include the name and type info
- return "%s(%r, %s)" % (type(self).__name__,
- self.__name__,
- int.__repr__(self))
- def __str__(self):
- # str() is unchanged, even if it relies on the repr() fallback
- base = int
- base_str = base.__str__
- if base_str.__objclass__ is object:
- return base.__repr__(self)
- return base_str(self)
- # for simplicity, we only define one operator that
- # propagates expressions
- def __add__(self, other):
- temp = int(self) + int( other)
- if isinstance(self, NamedInt) and isinstance(other, NamedInt):
- return NamedInt(
- '(%s + %s)' % (self.__name__, other.__name__),
- temp )
- else:
- return temp
-
- class NEI(NamedInt, Enum):
- __qualname__ = 'NEI' # needed for pickle protocol 4
- x = ('the-x', 1)
- y = ('the-y', 2)
-
- self.assertTrue(NEI.__new__ is Enum.__new__)
- self.assertEqual(repr(NEI.x + NEI.y), "NamedInt('(the-x + the-y)', 3)")
- globals()['NamedInt'] = NamedInt
- globals()['NEI'] = NEI
- NI5 = NamedInt('test', 5)
- self.assertEqual(NI5, 5)
- test_pickle_dump_load(self.assertTrue, NI5, 5)
- self.assertEqual(NEI.y.value, 2)
- test_pickle_dump_load(self.assertTrue, NEI.y)
-
- def test_subclasses_with_reduce(self):
- class NamedInt(int):
- __qualname__ = 'NamedInt' # needed for pickle protocol 4
- def __new__(cls, *args):
- _args = args
- if len(args) < 1:
- raise TypeError("name and value must be specified")
- name, args = args[0], args[1:]
- self = int.__new__(cls, *args)
- self._intname = name
- self._args = _args
- return self
- def __reduce__(self):
- return self.__class__, self._args
- @property
- def __name__(self):
- return self._intname
- def __repr__(self):
- # repr() is updated to include the name and type info
- return "%s(%r, %s)" % (type(self).__name__,
- self.__name__,
- int.__repr__(self))
- def __str__(self):
- # str() is unchanged, even if it relies on the repr() fallback
- base = int
- base_str = base.__str__
- if base_str.__objclass__ is object:
- return base.__repr__(self)
- return base_str(self)
- # for simplicity, we only define one operator that
- # propagates expressions
- def __add__(self, other):
- temp = int(self) + int( other)
- if isinstance(self, NamedInt) and isinstance(other, NamedInt):
- return NamedInt(
- '(%s + %s)' % (self.__name__, other.__name__),
- temp )
- else:
- return temp
-
- class NEI(NamedInt, Enum):
- __qualname__ = 'NEI' # needed for pickle protocol 4
- x = ('the-x', 1)
- y = ('the-y', 2)
-
-
- self.assertTrue(NEI.__new__ is Enum.__new__)
- self.assertEqual(repr(NEI.x + NEI.y), "NamedInt('(the-x + the-y)', 3)")
- globals()['NamedInt'] = NamedInt
- globals()['NEI'] = NEI
- NI5 = NamedInt('test', 5)
- self.assertEqual(NI5, 5)
- test_pickle_dump_load(self.assertEqual, NI5, 5)
- self.assertEqual(NEI.y.value, 2)
- test_pickle_dump_load(self.assertTrue, NEI.y)
-
- def test_subclasses_with_reduce_ex(self):
- class NamedInt(int):
- __qualname__ = 'NamedInt' # needed for pickle protocol 4
- def __new__(cls, *args):
- _args = args
- if len(args) < 1:
- raise TypeError("name and value must be specified")
- name, args = args[0], args[1:]
- self = int.__new__(cls, *args)
- self._intname = name
- self._args = _args
- return self
- def __reduce_ex__(self, proto):
- return self.__class__, self._args
- @property
- def __name__(self):
- return self._intname
- def __repr__(self):
- # repr() is updated to include the name and type info
- return "%s(%r, %s)" % (type(self).__name__,
- self.__name__,
- int.__repr__(self))
- def __str__(self):
- # str() is unchanged, even if it relies on the repr() fallback
- base = int
- base_str = base.__str__
- if base_str.__objclass__ is object:
- return base.__repr__(self)
- return base_str(self)
- # for simplicity, we only define one operator that
- # propagates expressions
- def __add__(self, other):
- temp = int(self) + int( other)
- if isinstance(self, NamedInt) and isinstance(other, NamedInt):
- return NamedInt(
- '(%s + %s)' % (self.__name__, other.__name__),
- temp )
- else:
- return temp
-
- class NEI(NamedInt, Enum):
- __qualname__ = 'NEI' # needed for pickle protocol 4
- x = ('the-x', 1)
- y = ('the-y', 2)
-
-
- self.assertTrue(NEI.__new__ is Enum.__new__)
- self.assertEqual(repr(NEI.x + NEI.y), "NamedInt('(the-x + the-y)', 3)")
- globals()['NamedInt'] = NamedInt
- globals()['NEI'] = NEI
- NI5 = NamedInt('test', 5)
- self.assertEqual(NI5, 5)
- test_pickle_dump_load(self.assertEqual, NI5, 5)
- self.assertEqual(NEI.y.value, 2)
- test_pickle_dump_load(self.assertTrue, NEI.y)
-
- def test_subclasses_without_direct_pickle_support(self):
- class NamedInt(int):
- __qualname__ = 'NamedInt'
- def __new__(cls, *args):
- _args = args
- name, args = args[0], args[1:]
- if len(args) == 0:
- raise TypeError("name and value must be specified")
- self = int.__new__(cls, *args)
- self._intname = name
- self._args = _args
- return self
- @property
- def __name__(self):
- return self._intname
- def __repr__(self):
- # repr() is updated to include the name and type info
- return "%s(%r, %s)" % (type(self).__name__,
- self.__name__,
- int.__repr__(self))
- def __str__(self):
- # str() is unchanged, even if it relies on the repr() fallback
- base = int
- base_str = base.__str__
- if base_str.__objclass__ is object:
- return base.__repr__(self)
- return base_str(self)
- # for simplicity, we only define one operator that
- # propagates expressions
- def __add__(self, other):
- temp = int(self) + int( other)
- if isinstance(self, NamedInt) and isinstance(other, NamedInt):
- return NamedInt(
- '(%s + %s)' % (self.__name__, other.__name__),
- temp )
- else:
- return temp
-
- class NEI(NamedInt, Enum):
- __qualname__ = 'NEI'
- x = ('the-x', 1)
- y = ('the-y', 2)
-
- self.assertTrue(NEI.__new__ is Enum.__new__)
- self.assertEqual(repr(NEI.x + NEI.y), "NamedInt('(the-x + the-y)', 3)")
- globals()['NamedInt'] = NamedInt
- globals()['NEI'] = NEI
- NI5 = NamedInt('test', 5)
- self.assertEqual(NI5, 5)
- self.assertEqual(NEI.y.value, 2)
- test_pickle_exception(self.assertRaises, TypeError, NEI.x)
- test_pickle_exception(self.assertRaises, PicklingError, NEI)
-
- def test_subclasses_without_direct_pickle_support_using_name(self):
- class NamedInt(int):
- __qualname__ = 'NamedInt'
- def __new__(cls, *args):
- _args = args
- name, args = args[0], args[1:]
- if len(args) == 0:
- raise TypeError("name and value must be specified")
- self = int.__new__(cls, *args)
- self._intname = name
- self._args = _args
- return self
- @property
- def __name__(self):
- return self._intname
- def __repr__(self):
- # repr() is updated to include the name and type info
- return "%s(%r, %s)" % (type(self).__name__,
- self.__name__,
- int.__repr__(self))
- def __str__(self):
- # str() is unchanged, even if it relies on the repr() fallback
- base = int
- base_str = base.__str__
- if base_str.__objclass__ is object:
- return base.__repr__(self)
- return base_str(self)
- # for simplicity, we only define one operator that
- # propagates expressions
- def __add__(self, other):
- temp = int(self) + int( other)
- if isinstance(self, NamedInt) and isinstance(other, NamedInt):
- return NamedInt(
- '(%s + %s)' % (self.__name__, other.__name__),
- temp )
- else:
- return temp
-
- class NEI(NamedInt, Enum):
- __qualname__ = 'NEI'
- x = ('the-x', 1)
- y = ('the-y', 2)
- def __reduce_ex__(self, proto):
- return getattr, (self.__class__, self._name_)
-
- self.assertTrue(NEI.__new__ is Enum.__new__)
- self.assertEqual(repr(NEI.x + NEI.y), "NamedInt('(the-x + the-y)', 3)")
- globals()['NamedInt'] = NamedInt
- globals()['NEI'] = NEI
- NI5 = NamedInt('test', 5)
- self.assertEqual(NI5, 5)
- self.assertEqual(NEI.y.value, 2)
- test_pickle_dump_load(self.assertTrue, NEI.y)
- test_pickle_dump_load(self.assertTrue, NEI)
-
- def test_tuple_subclass(self):
- class SomeTuple(tuple, Enum):
- __qualname__ = 'SomeTuple'
- first = (1, 'for the money')
- second = (2, 'for the show')
- third = (3, 'for the music')
- self.assertTrue(type(SomeTuple.first) is SomeTuple)
- self.assertTrue(isinstance(SomeTuple.second, tuple))
- self.assertEqual(SomeTuple.third, (3, 'for the music'))
- globals()['SomeTuple'] = SomeTuple
- test_pickle_dump_load(self.assertTrue, SomeTuple.first)
-
- # def test_duplicate_values_give_unique_enum_items(self):
- # class NumericEnum(AutoNumberEnum):
- # __order__ = 'enum_m enum_d enum_y'
- # enum_m = ()
- # enum_d = ()
- # enum_y = ()
- # def __int__(self):
- # return int(self._value_)
- # self.assertEqual(int(NumericEnum.enum_d), 2)
- # self.assertEqual(NumericEnum.enum_y.value, 3)
- # self.assertTrue(NumericEnum(1) is NumericEnum.enum_m)
- # self.assertEqual(
- # list(NumericEnum),
- # [NumericEnum.enum_m, NumericEnum.enum_d, NumericEnum.enum_y],
- # )
-
- def test_inherited_new_from_enhanced_enum(self):
- class AutoNumber2(Enum):
- def __new__(cls):
- value = len(cls.__members__) + 1
- obj = object.__new__(cls)
- obj._value_ = value
- return obj
- def __int__(self):
- return int(self._value_)
- class Color(AutoNumber2):
- __order__ = 'red green blue'
- red = ()
- green = ()
- blue = ()
- self.assertEqual(len(Color), 3, "wrong number of elements: %d (should be %d)" % (len(Color), 3))
- self.assertEqual(list(Color), [Color.red, Color.green, Color.blue])
- if PY3:
- self.assertEqual(list(map(int, Color)), [1, 2, 3])
-
- def test_inherited_new_from_mixed_enum(self):
- class AutoNumber3(IntEnum):
- def __new__(cls):
- value = len(cls.__members__) + 11
- obj = int.__new__(cls, value)
- obj._value_ = value
- return obj
- class Color(AutoNumber3):
- __order__ = 'red green blue'
- red = ()
- green = ()
- blue = ()
- self.assertEqual(len(Color), 3, "wrong number of elements: %d (should be %d)" % (len(Color), 3))
- Color.red
- Color.green
- Color.blue
- self.assertEqual(Color.blue, 13)
-
- def test_equality(self):
- class AlwaysEqual:
- def __eq__(self, other):
- return True
- class OrdinaryEnum(Enum):
- a = 1
- self.assertEqual(AlwaysEqual(), OrdinaryEnum.a)
- self.assertEqual(OrdinaryEnum.a, AlwaysEqual())
-
- def test_ordered_mixin(self):
- class Grade(OrderedEnum):
- __order__ = 'A B C D F'
- A = 5
- B = 4
- C = 3
- D = 2
- F = 1
- self.assertEqual(list(Grade), [Grade.A, Grade.B, Grade.C, Grade.D, Grade.F])
- self.assertTrue(Grade.A > Grade.B)
- self.assertTrue(Grade.F <= Grade.C)
- self.assertTrue(Grade.D < Grade.A)
- self.assertTrue(Grade.B >= Grade.B)
-
- def test_missing_deprecated(self):
- class Label(Enum):
- AnyApple = 0
- RedApple = 1
- GreenApple = 2
- @classmethod
- def _missing_(cls, name):
- return cls.AnyApple
-
- self.assertEqual(Label.AnyApple, Label(4))
- with self.assertRaises(AttributeError):
- Label.redapple
- with self.assertRaises(KeyError):
- Label['redapple']
-
- def test_missing(self):
- class Label(Enum):
- AnyApple = 0
- RedApple = 1
- GreenApple = 2
- @classmethod
- def _missing_value_(cls, value):
- return cls.AnyApple
-
- self.assertEqual(Label.AnyApple, Label(4))
- with self.assertRaises(AttributeError):
- Label.redapple
- with self.assertRaises(KeyError):
- Label['redapple']
-
- def test_missing_name(self):
- class Label(Enum):
- RedApple = 1
- GreenApple = 2
- @classmethod
- def _missing_name_(cls, name):
- for member in cls:
- if member.name.lower() == name.lower():
- return member
-
- Label['redapple']
- with self.assertRaises(AttributeError):
- Label.redapple
- with self.assertRaises(ValueError):
- Label('redapple')
-
- def test_missing_value_bad_input(self):
- class Label(Enum):
- AnyApple = 0
- RedApple = 1
- GreenApple = 2
- @classmethod
- def _missing_value_(cls, value):
- return cls.AnyApple
-
- self.assertEqual(Label.AnyApple, Label(4))
- with self.assertRaises(KeyError):
- Label[True]
-
- def test_missing_name_bad_return(self):
- class Label(Enum):
- RedApple = 1
- GreenApple = 2
- @classmethod
- def _missing_name_(cls, name):
- return None
-
- with self.assertRaises(AttributeError):
- Label.redapple
- with self.assertRaises(ValueError):
- Label('redapple')
- with self.assertRaises(KeyError):
- Label['redapple']
-
- def test_extending2(self):
- def bad_extension():
- class Shade(Enum):
- def shade(self):
- print(self.name)
- class Color(Shade):
- red = 1
- green = 2
- blue = 3
- class MoreColor(Color):
- cyan = 4
- magenta = 5
- yellow = 6
- self.assertRaises(TypeError, bad_extension)
-
- def test_extending3(self):
- class Shade(Enum):
- def shade(self):
- return self.name
- class Color(Shade):
- def hex(self):
- return '%s hexlified!' % self.value
- class MoreColor(Color):
- cyan = 4
- magenta = 5
- yellow = 6
- self.assertEqual(MoreColor.magenta.hex(), '5 hexlified!')
-
- def test_extending5(self):
- class Color(Enum):
- _order_ = 'red green blue value'
- red = 1
- green = 2
- blue = 3
- value = 4
- self.assertEqual(list(Color), [Color.red, Color.green, Color.blue, Color.value])
- self.assertEqual(Color.value.name, 'value')
- self.assertEqual(Color.value.value, 4)
- self.assertTrue(Color.value in Color)
- self.assertEqual(Color(4), Color.value)
- self.assertEqual(Color['value'], Color.value)
- self.assertEqual(Color.red.value, 1)
-
- CONTINUE = 100, 'Continue', 'Request received, please continue'
- SWITCHING_PROTOCOLS = (101, 'Switching Protocols',
- 'Switching to new protocol; obey Upgrade header')
- PROCESSING = 102, 'Processing'
-
- def test_no_duplicates(self):
- def bad_duplicates():
- class Color1(UniqueEnum):
- red = 1
- green = 2
- blue = 3
- class Color2(UniqueEnum):
- red = 1
- green = 2
- blue = 3
- grene = 2
- self.assertRaises(ValueError, bad_duplicates)
-
- def test_no_duplicates_kinda(self):
- class Silly(UniqueEnum):
- one = 1
- two = 'dos'
- name = 3
- class Sillier(IntEnum, UniqueEnum):
- single = 1
- name = 2
- triple = 3
- value = 4
-
- def test_init(self):
- class Planet(Enum):
- MERCURY = (3.303e+23, 2.4397e6)
- VENUS = (4.869e+24, 6.0518e6)
- EARTH = (5.976e+24, 6.37814e6)
- MARS = (6.421e+23, 3.3972e6)
- JUPITER = (1.9e+27, 7.1492e7)
- SATURN = (5.688e+26, 6.0268e7)
- URANUS = (8.686e+25, 2.5559e7)
- NEPTUNE = (1.024e+26, 2.4746e7)
- def __init__(self, mass, radius):
- self.mass = mass # in kilograms
- self.radius = radius # in meters
- @property
- def surface_gravity(self):
- # universal gravitational constant (m3 kg-1 s-2)
- G = 6.67300E-11
- return G * self.mass / (self.radius * self.radius)
- self.assertEqual(round(Planet.EARTH.surface_gravity, 2), 9.80)
- self.assertEqual(Planet.EARTH.value, (5.976e+24, 6.37814e6))
-
- def test_init_and_shadowing_attribute(self):
- class SelectionEnum(str, Enum):
- _init_ = 'db user'
- def __new__(cls, *args, **kwds):
- count = len(cls.__members__)
- obj = str.__new__(cls, args[0])
- obj._count = count
- obj._value_ = args
- return obj
- @staticmethod
- def _generate_next_value_(name, start, count, values, *args, **kwds):
- return (name, ) + args
- class DeviceTypeSource(SelectionEnum):
- _order_ = 'user system'
- user = "User controlled"
- system = "System controlled"
- self.assertEqual(DeviceTypeSource.system.db, 'system')
- self.assertEqual(DeviceTypeSource.system.user, 'System controlled')
- self.assertEqual(DeviceTypeSource.user.db, 'user')
- self.assertEqual(DeviceTypeSource.user.user, 'User controlled')
-
- def test_nonhash_value(self):
- class AutoNumberInAList(Enum):
- def __new__(cls):
- value = [len(cls.__members__) + 1]
- obj = object.__new__(cls)
- obj._value_ = value
- return obj
- class ColorInAList(AutoNumberInAList):
- __order__ = 'red green blue'
- red = ()
- green = ()
- blue = ()
- self.assertEqual(list(ColorInAList), [ColorInAList.red, ColorInAList.green, ColorInAList.blue])
- self.assertEqual(ColorInAList.red.value, [1])
- self.assertEqual(ColorInAList([1]), ColorInAList.red)
-
- def test_number_reset_and_order_cleanup(self):
- class Confused(Enum):
- _order_ = 'ONE TWO THREE UNO DOS TRES FOUR'
- ONE = auto()
- TWO = auto()
- THREE = auto()
- UNO = 1
- DOS = auto()
- TRES = auto()
- FOUR = auto()
- self.assertEqual(list(Confused), [Confused.ONE, Confused.TWO, Confused.THREE, Confused.FOUR])
- self.assertIs(Confused.TWO, Confused.DOS)
- self.assertEqual(Confused.DOS._value_, 2)
- self.assertEqual(Confused.TRES._value_, 3)
- self.assertEqual(Confused.FOUR._value_, 4)
-
- def test_conflicting_types_resolved_in_new(self):
- class LabelledIntEnum(int, Enum):
- def __new__(cls, *args):
- value, label = args
- obj = int.__new__(cls, value)
- obj.label = label
- obj._value_ = value
- return obj
-
- class LabelledList(LabelledIntEnum):
- unprocessed = (1, "Unprocessed")
- payment_complete = (2, "Payment Complete")
-
- self.assertEqual(LabelledList.unprocessed, 1)
- self.assertEqual(LabelledList(1), LabelledList.unprocessed)
- self.assertEqual(list(LabelledList), [LabelledList.unprocessed, LabelledList.payment_complete])
-
- def test_auto_number(self):
- class Color(Enum):
- _order_ = 'red blue green'
- red = auto()
- blue = auto()
- green = auto()
-
- self.assertEqual(list(Color), [Color.red, Color.blue, Color.green])
- self.assertEqual(Color.red.value, 1)
- self.assertEqual(Color.blue.value, 2)
- self.assertEqual(Color.green.value, 3)
-
- def test_auto_name(self):
- class Color(Enum):
- _order_ = 'red blue green'
- def _generate_next_value_(name, start, count, last):
- return name
- red = auto()
- blue = auto()
- green = auto()
-
- self.assertEqual(list(Color), [Color.red, Color.blue, Color.green])
- self.assertEqual(Color.red.value, 'red')
- self.assertEqual(Color.blue.value, 'blue')
- self.assertEqual(Color.green.value, 'green')
-
- def test_auto_name_inherit(self):
- class AutoNameEnum(Enum):
- def _generate_next_value_(name, start, count, last):
- return name
- class Color(AutoNameEnum):
- _order_ = 'red blue green'
- red = auto()
- blue = auto()
- green = auto()
-
- self.assertEqual(list(Color), [Color.red, Color.blue, Color.green])
- self.assertEqual(Color.red.value, 'red')
- self.assertEqual(Color.blue.value, 'blue')
- self.assertEqual(Color.green.value, 'green')
-
- def test_auto_garbage(self):
- class Color(Enum):
- _order_ = 'red blue'
- red = 'red'
- blue = auto()
- self.assertEqual(Color.blue.value, 1)
-
- def test_auto_garbage_corrected(self):
- class Color(Enum):
- _order_ = 'red blue green'
- red = 'red'
- blue = 2
- green = auto()
-
- self.assertEqual(list(Color), [Color.red, Color.blue, Color.green])
- self.assertEqual(Color.red.value, 'red')
- self.assertEqual(Color.blue.value, 2)
- self.assertEqual(Color.green.value, 3)
-
- def test_duplicate_auto(self):
- #
- class MoreDupes(Enum):
- _order_ = 'A B C'
- A = auto()
- B = A,
- C = auto()
- self.assertEqual(list(MoreDupes), [MoreDupes.A, MoreDupes.B, MoreDupes.C])
- self.assertEqual([m.value for m in MoreDupes], [1, (1, ), 2])
- #
- class Dupes(Enum):
- _order_ = 'first second third'
- first = primero = auto()
- second = auto()
- third = auto()
- self.assertEqual([Dupes.first, Dupes.second, Dupes.third], list(Dupes))
-
- def test_auto_value_with_auto(self):
-
- class SelectionEnum(Enum):
- _init_ = 'db user'
- def __new__(cls, *args, **kwds):
- count = len(cls.__members__)
- obj = object.__new__(cls)
- obj._count = count
- obj._value_ = args
- obj.db, obj.user = args
- return obj
- @staticmethod
- def _generate_next_value_(name, start, count, values, *args, **kwds):
- return (name, ) + args
-
- class Test(SelectionEnum):
- _order_ = 'this that'
- this = auto('these')
- that = auto('those')
-
- self.assertEqual(list(Test), [Test.this, Test.that])
- self.assertEqual(Test.this.name, 'this')
- self.assertEqual(Test.this.value, ('this', 'these'))
- self.assertEqual(Test.this.db, 'this')
- self.assertEqual(Test.this.user, 'these')
- self.assertEqual(Test.that.name, 'that')
- self.assertEqual(Test.that.value, ('that', 'those'))
- self.assertEqual(Test.that.db, 'that')
- self.assertEqual(Test.that.user, 'those')
-
- def test_auto_value_with_autovalue(self):
-
- class SelectionEnum(Enum):
- _init_ = 'db user'
- def __new__(cls, *args, **kwds):
- count = len(cls.__members__)
- obj = object.__new__(cls)
- obj._count = count
- obj._value_ = args
- return obj
- @staticmethod
- def _generate_next_value_(name, start, count, values, *args, **kwds):
- return (name, ) + args
-
- class Test(SelectionEnum):
- _order_ = 'this that'
- this = 'these'
- that = 'those'
-
- self.assertEqual(list(Test), [Test.this, Test.that])
- self.assertEqual(Test.this.name, 'this')
- self.assertEqual(Test.this.value, ('this', 'these'))
- self.assertEqual(Test.this.db, 'this')
- self.assertEqual(Test.this.user, 'these')
- self.assertEqual(Test.that.name, 'that')
- self.assertEqual(Test.that.value, ('that', 'those'))
- self.assertEqual(Test.that.db, 'that')
- self.assertEqual(Test.that.user, 'those')
-
- def test_auto_and_kwds(self):
- class Item(Enum):
- _order_ = 'A B'
- A = auto(size=100, req={'red': True})
- B = auto(size=200, req={'red': False})
- #
- def __new__(cls, value, size, req):
- obj = object.__new__(cls)
- obj._value_ = value
- obj.size = size
- obj.req= req
- return obj
- self.assertEqual((Item.A.value, Item.A.size, Item.A.req), (1, 100, {'red': True}))
- self.assertEqual((Item.B.value, Item.B.size, Item.B.req), (2, 200, {'red': False}))
-
- def test_empty_with_functional_api(self):
- empty = aenum.IntEnum('Foo', {})
- self.assertEqual(len(empty), 0)
-
- def test_auto_init(self):
- class Planet(Enum):
- _init_ = 'mass radius'
- MERCURY = (3.303e+23, 2.4397e6)
- VENUS = (4.869e+24, 6.0518e6)
- EARTH = (5.976e+24, 6.37814e6)
- MARS = (6.421e+23, 3.3972e6)
- JUPITER = (1.9e+27, 7.1492e7)
- SATURN = (5.688e+26, 6.0268e7)
- URANUS = (8.686e+25, 2.5559e7)
- NEPTUNE = (1.024e+26, 2.4746e7)
- @property
- def surface_gravity(self):
- # universal gravitational constant (m3 kg-1 s-2)
- G = 6.67300E-11
- return G * self.mass / (self.radius * self.radius)
- self.assertEqual(round(Planet.EARTH.surface_gravity, 2), 9.80)
- self.assertEqual(Planet.EARTH.value, (5.976e+24, 6.37814e6))
-
- def test_auto_init_with_value(self):
- class Color(Enum):
- _init_='value, rgb'
- RED = 1, (1, 0, 0)
- BLUE = 2, (0, 1, 0)
- GREEN = 3, (0, 0, 1)
- self.assertEqual(Color.RED.value, 1)
- self.assertEqual(Color.BLUE.value, 2)
- self.assertEqual(Color.GREEN.value, 3)
- self.assertEqual(Color.RED.rgb, (1, 0, 0))
- self.assertEqual(Color.BLUE.rgb, (0, 1, 0))
- self.assertEqual(Color.GREEN.rgb, (0, 0, 1))
-
- def test_noalias(self):
- class Settings(Enum):
- _settings_ = NoAlias
- red = 1
- rojo = 1
- self.assertFalse(Settings.red is Settings.rojo)
- self.assertRaises(TypeError, Settings, 1)
-
- def test_auto_and_init(self):
- class Field(int, Enum):
- _order_ = 'TYPE START'
- _init_ = 'value __doc__'
- TYPE = "Char, Date, Logical, etc."
- START = "Field offset in record"
- self.assertEqual(Field.TYPE, 1)
- self.assertEqual(Field.START, 2)
- self.assertEqual(Field.TYPE.__doc__, 'Char, Date, Logical, etc.')
- self.assertEqual(Field.START.__doc__, 'Field offset in record')
-
- def test_auto_and_start(self):
- class Field(IntEnum):
- _order_ = 'TYPE START'
- _start_ = 0
- _init_ = 'value __doc__'
- TYPE = "Char, Date, Logical, etc."
- START = "Field offset in record"
- self.assertEqual(Field.TYPE, 0)
- self.assertEqual(Field.START, 1)
- self.assertEqual(Field.TYPE.__doc__, 'Char, Date, Logical, etc.')
- self.assertEqual(Field.START.__doc__, 'Field offset in record')
-
- def test_auto_and_init_and_some_values(self):
- class Field(int, Enum):
- _order_ = 'TYPE START BLAH BELCH'
- _init_ = 'value __doc__'
- TYPE = "Char, Date, Logical, etc."
- START = "Field offset in record"
- BLAH = 5, "test blah"
- BELCH = 'test belch'
- self.assertEqual(Field.TYPE, 1)
- self.assertEqual(Field.START, 2)
- self.assertEqual(Field.BLAH, 5)
- self.assertEqual(Field.BELCH, 6)
- self.assertEqual(Field.TYPE.__doc__, 'Char, Date, Logical, etc.')
- self.assertEqual(Field.START.__doc__, 'Field offset in record')
- self.assertEqual(Field.BLAH.__doc__, 'test blah')
- self.assertEqual(Field.BELCH.__doc__, 'test belch')
-
- def test_auto_and_init_w_value_and_too_many_values(self):
- with self.assertRaisesRegex(TypeError, r'Field\.BLAH: number of fields provided do not match init'):
- class Field(int, Enum):
- _order_ = 'TYPE START BLAH BELCH'
- _init_ = 'value __doc__'
- TYPE = 1, "Char, Date, Logical, etc."
- START = 2, "Field offset in record"
- BLAH = 5, 6, "test blah"
- BELCH = 7, 'test belch'
-
- def test_auto_and_init_and_some_complex_values(self):
- class Field(int, Enum):
- _order_ = 'TYPE START BLAH BELCH'
- _init_ = 'value __doc__ help'
- TYPE = "Char, Date, Logical, etc.", "fields composed of character data"
- START = "Field offset in record", "where the data starts in the record"
- BLAH = 5, "test blah", "some help"
- BELCH = 'test belch', "some more help"
- self.assertEqual(Field.TYPE, 1)
- self.assertEqual(Field.START, 2)
- self.assertEqual(Field.BLAH, 5)
- self.assertEqual(Field.BELCH, 6)
- self.assertEqual(Field.TYPE.__doc__, 'Char, Date, Logical, etc.')
- self.assertEqual(Field.START.__doc__, 'Field offset in record')
- self.assertEqual(Field.BLAH.__doc__, 'test blah')
- self.assertEqual(Field.BELCH.__doc__, 'test belch')
- self.assertEqual(Field.TYPE.help, "fields composed of character data")
- self.assertEqual(Field.START.help, "where the data starts in the record")
- self.assertEqual(Field.BLAH.help, "some help")
- self.assertEqual(Field.BELCH.help, "some more help")
-
- def test_auto_and_init_inherited(self):
- class AutoEnum(IntEnum):
- _start_ = 0
- _init_ = 'value __doc__'
- class Field(AutoEnum):
- _order_ = 'TYPE START BLAH BELCH'
- TYPE = "Char, Date, Logical, etc."
- START = "Field offset in record"
- BLAH = 5, "test blah"
- BELCH = 'test belch'
- self.assertEqual(Field.TYPE, 0)
- self.assertEqual(Field.START, 1)
- self.assertEqual(Field.BLAH, 5)
- self.assertEqual(Field.BELCH, 6)
- self.assertEqual(Field.TYPE.__doc__, 'Char, Date, Logical, etc.')
- self.assertEqual(Field.START.__doc__, 'Field offset in record')
- self.assertEqual(Field.BLAH.__doc__, 'test blah')
- self.assertEqual(Field.BELCH.__doc__, 'test belch')
-
- def test_missing_value_error(self):
- with self.assertRaisesRegex(TypeError, r"_value_ not set in __new__"):
- class Combined(str, Enum):
- #
- _init_ = 'value sequence'
- _order_ = lambda m: m.sequence
- #
- def __new__(cls, value, *args):
- enum = str.__new__(cls, value)
- if '(' in value:
- fis_name, segment = value.split('(', 1)
- segment = segment.strip(' )')
- else:
- fis_name = value
- segment = None
- enum.fis_name = fis_name
- enum.segment = segment
- return enum
- #
- def __repr__(self):
- return "<%s.%s>" % (self.__class__.__name__, self._name_)
- #
- key_type = 'An$(1,2)', 0
- company_id = 'An$(3,2)', 1
- code = 'An$(5,1)', 2
- description = 'Bn$', 3
-
-
- def test_auto_and_enum(self):
- class Foo(aenum.Flag):
- _order_ = 'a b c'
- a = aenum.auto()
- b = a | aenum.auto()
- c = 2
-
- self.assertEqual([Foo.a, Foo.c], list(Foo))
- self.assertEqual(Foo.a.value, 1)
- self.assertEqual(Foo.b.value, 3)
-
- def test_multiple_arg_auto(self):
- class AutoName(Enum):
- def _generate_next_value_(name, start, count, last, *args, **kwds):
- return (name, ) + args
- #
- class Planet(AutoName):
- _init_ = 'value mass radius'
- MERCURY = auto(3.303e+23, 2.4397e6)
- VENUS = auto(4.869e+24, 6.0518e6)
- self.assertEqual(Planet.MERCURY.value, 'MERCURY')
-
- def test_auto_w_multiple_arg(self):
- class AutoName(Enum):
- def _generate_next_value_(name, start, count, last, *args, **kwds):
- return (name, ) + args
- #
- class Planet(AutoName):
- _init_ = 'value mass radius'
- MERCURY = auto(), 3.303e+23, 2.4397e6 # doesn't work
- VENUS = auto(), 4.869e+24, 6.0518e6 # doesn't work
- self.assertEqual(Planet.MERCURY.value, 'MERCURY')
-
- def test_auto_gnv_and_init(self):
- class AutoName(Enum):
- def _generate_next_value_(name, start, count, last, *args, **kwds):
- return (name, ) + args
- #
- class Planet(AutoName):
- _init_ = 'value mass radius'
- MERCURY = 3.303e+23, 2.4397e6 # doesn't work
- VENUS = 4.869e+24, 6.0518e6 # doesn't work
- self.assertEqual(Planet.MERCURY.value, 'MERCURY')
-
- # def test_AutoNumberEnum_and_property(self):
- # class Color(aenum.AutoNumberEnum):
- # red = ()
- # green = ()
- # blue = ()
- # @property
- # def cap_name(self):
- # return self.name.title()
- # self.assertEqual(Color.blue.cap_name, 'Blue')
-
- # def test_AutoNumberEnum(self):
- # class Color(aenum.AutoNumberEnum):
- # _order_ = 'red green blue'
- # red = ()
- # green = ()
- # blue = ()
- # self.assertEqual(list(Color), [Color.red, Color.green, Color.blue])
- # self.assertEqual(Color.red.value, 1)
- # self.assertEqual(Color.green.value, 2)
- # self.assertEqual(Color.blue.value, 3)
-
- def test_MultiValue_with_init_wo_value(self):
- class Color(Enum):
- _init_ = 'color r g b'
- _order_ = 'red green blue'
- _settings_ = MultiValue
- red = 'red', 1, 2, 3
- green = 'green', 4, 5, 6
- blue = 'blue', 7, 8, 9
- self.assertEqual(Color.red.value, 'red')
- self.assertEqual(Color.red.color, 'red')
- self.assertEqual(Color.red.r, 1)
- self.assertEqual(Color.red.g, 2)
- self.assertEqual(Color.red.b, 3)
- self.assertEqual(Color.green.value, 'green')
- self.assertEqual(Color.green.color, 'green')
- self.assertEqual(Color.green.r, 4)
- self.assertEqual(Color.green.g, 5)
- self.assertEqual(Color.green.b, 6)
- self.assertEqual(Color.blue.value, 'blue')
- self.assertEqual(Color.blue.color, 'blue')
- self.assertEqual(Color.blue.r, 7)
- self.assertEqual(Color.blue.g, 8)
- self.assertEqual(Color.blue.b, 9)
- self.assertIs(Color('red'), Color.red)
- self.assertIs(Color(1), Color.red)
- self.assertIs(Color(2), Color.red)
- self.assertIs(Color(3), Color.red)
- self.assertIs(Color('green'), Color.green)
- self.assertIs(Color(4), Color.green)
- self.assertIs(Color(5), Color.green)
- self.assertIs(Color(6), Color.green)
- self.assertIs(Color('blue'), Color.blue)
- self.assertIs(Color(7), Color.blue)
- self.assertIs(Color(8), Color.blue)
- self.assertIs(Color(9), Color.blue)
-
- def test_MultiValue_with_init_w_value(self):
- class Color(Enum):
- _init_ = 'value r g b'
- _order_ = 'red green blue'
- _settings_ = MultiValue
- red = 'red', 1, 2, 3
- green = 'green', 4, 5, 6
- blue = 'blue', 7, 8, 9
- self.assertEqual(Color.red.value, 'red')
- self.assertEqual(Color.red.r, 1)
- self.assertEqual(Color.red.g, 2)
- self.assertEqual(Color.red.b, 3)
- self.assertEqual(Color.green.value, 'green')
- self.assertEqual(Color.green.r, 4)
- self.assertEqual(Color.green.g, 5)
- self.assertEqual(Color.green.b, 6)
- self.assertEqual(Color.blue.value, 'blue')
- self.assertEqual(Color.blue.r, 7)
- self.assertEqual(Color.blue.g, 8)
- self.assertEqual(Color.blue.b, 9)
- self.assertIs(Color('red'), Color.red)
- self.assertIs(Color(1), Color.red)
- self.assertIs(Color(2), Color.red)
- self.assertIs(Color(3), Color.red)
- self.assertIs(Color('green'), Color.green)
- self.assertIs(Color(4), Color.green)
- self.assertIs(Color(5), Color.green)
- self.assertIs(Color(6), Color.green)
- self.assertIs(Color('blue'), Color.blue)
- self.assertIs(Color(7), Color.blue)
- self.assertIs(Color(8), Color.blue)
- self.assertIs(Color(9), Color.blue)
-
- def test_MultiValue_with_init_wo_value_w_autonumber(self):
- class Color(AutoNumberEnum):
- _init_ = 'color r g b'
- _order_ = 'red green blue'
- _settings_ = MultiValue
- red = 'red', 10, 20, 30
- green = 'green', 40, 50, 60
- blue = 'blue', 70, 80, 90
- self.assertEqual(Color.red.value, 1)
- self.assertEqual(Color.red.color, 'red')
- self.assertEqual(Color.red.r, 10)
- self.assertEqual(Color.red.g, 20)
- self.assertEqual(Color.red.b, 30)
- self.assertEqual(Color.green.value, 2)
- self.assertEqual(Color.green.color, 'green')
- self.assertEqual(Color.green.r, 40)
- self.assertEqual(Color.green.g, 50)
- self.assertEqual(Color.green.b, 60)
- self.assertEqual(Color.blue.value, 3)
- self.assertEqual(Color.blue.color, 'blue')
- self.assertEqual(Color.blue.r, 70)
- self.assertEqual(Color.blue.g, 80)
- self.assertEqual(Color.blue.b, 90)
- self.assertIs(Color(1), Color.red)
- self.assertIs(Color('red'), Color.red)
- self.assertIs(Color(10), Color.red)
- self.assertIs(Color(20), Color.red)
- self.assertIs(Color(30), Color.red)
- self.assertIs(Color(2), Color.green)
- self.assertIs(Color('green'), Color.green)
- self.assertIs(Color(40), Color.green)
- self.assertIs(Color(50), Color.green)
- self.assertIs(Color(60), Color.green)
- self.assertIs(Color(3), Color.blue)
- self.assertIs(Color('blue'), Color.blue)
- self.assertIs(Color(70), Color.blue)
- self.assertIs(Color(80), Color.blue)
- self.assertIs(Color(90), Color.blue)
-
- def test_multivalue_and_autonumber_wo_init_wo_value(self):
- class Day(Enum):
- _settings_ = MultiValue, AddValue
- _order_ = 'one two three'
- _start_ = 7
- one = "21", "one"
- two = "22", "two"
- three = "23", "three"
- self.assertEqual(Day.one.value, 7)
- self.assertEqual(Day.two.value, 8)
- self.assertEqual(Day.three.value, 9)
- self.assertEqual(Day('21'), Day.one)
- self.assertEqual(Day('one'), Day.one)
-
- def test_multivalue_and_autonumber_wo_init_w_some_value(self):
- class Color(Enum):
- _settings_ = MultiValue, Unique
- _order_ = 'BLACK RED BLUE YELLOW GREEN MAGENTA'
- _init_ = "value description"
- BLACK = -1, "Text0"
- RED = -50, "Text1"
- BLUE = auto(), "Text2"
- YELLOW = auto(), "Text3"
- GREEN = -70, "Text4"
- MAGENTA = auto(), "Text5"
- self.assertEqual(Color.BLACK.value, -1)
- self.assertEqual(Color.RED.value, -50)
- self.assertEqual(Color.BLUE.value, -49)
- self.assertEqual(Color.YELLOW.value, -48)
- self.assertEqual(Color.GREEN.value, -70)
- self.assertEqual(Color.MAGENTA.value, -69)
- self.assertEqual(Color(-1), Color.BLACK)
- self.assertEqual(Color('Text2'), Color.BLUE)
-
- def test_combine_new_settings_with_old_settings(self):
- class Auto(Enum):
- _settings_ = Unique
- with self.assertRaises(ValueError):
- class AutoUnique(Auto):
- BLAH = auto()
- BLUH = auto()
- ICK = 1
-
- def test_timedelta(self):
- class Period(timedelta, Enum):
- '''
- different lengths of time
- '''
- _init_ = 'value period'
- _settings_ = NoAlias
- _ignore_ = 'Period i'
- Period = vars()
- for i in range(31):
- Period['day_%d' % i] = i, 'day'
- for i in range(15):
- Period['week_%d' % i] = i*7, 'week'
- for i in range(12):
- Period['month_%d' % i] = i*30, 'month'
- OneDay = day_1
- OneWeek = week_1
- self.assertFalse(hasattr(Period, '_ignore_'))
- self.assertFalse(hasattr(Period, 'Period'))
- self.assertFalse(hasattr(Period, 'i'))
- self.assertTrue(isinstance(Period.day_1, timedelta))
-
- def test_skip(self):
- class enumA(Enum):
- @skip
- class enumB(Enum):
- elementA = 'a'
- elementB = 'b'
- @skip
- class enumC(Enum):
- elementC = 'c'
- elementD = 'd'
- self.assertIs(enumA.enumB, enumA.__dict__['enumB'])
-
- def test_nonmember(self):
- class enumA(Enum):
- @nonmember
- class enumB(Enum):
- elementA = 'a'
- elementB = 'b'
- @nonmember
- class enumC(Enum):
- elementC = 'c'
- elementD = 'd'
- self.assertIs(enumA.enumB, enumA.__dict__['enumB'])
-
- def test_member_with_external_functions(self):
- class Func(Enum):
- _order_ = 'an_int a_str'
- an_int = member(int)
- a_str = member(str)
- @classproperty
- def types(cls):
- return [m.value for m in list(cls)]
- def __repr__(self):
- return "<%s.%s>" % (self.__class__.__name__, self.name, )
- def __call__(self, *args, **kwds):
- return self.value(*args, **kwds)
- #
- self.assertEqual([Func.an_int, Func.a_str], list(Func))
- self.assertEqual([int, str], Func.types)
- self.assertEqual(Func.an_int(7), 7)
- self.assertEqual(Func.a_str('BlahBlah'), 'BlahBlah')
-
- def test_member_with_internal_functions(self):
- class Func(Enum):
- _order_ = 'haha hehe'
- @member
- def haha():
- return 'haha'
- @member
- def hehe(name):
- return 'hehe -- what a name! %s!' % name
- @classproperty
- def types(cls):
- return [m.value for m in list(cls)]
- def __repr__(self):
- return "<%s.%s>" % (self.__class__.__name__, self.name, )
- def __call__(self, *args, **kwds):
- return self.value(*args, **kwds)
- #
- self.assertEqual([Func.haha, Func.hehe], list(Func))
- self.assertEqual([Func.haha.value, Func.hehe.value], Func.types)
- self.assertEqual(Func.haha(), 'haha')
- self.assertEqual(Func.hehe('BlahBlah'), 'hehe -- what a name! BlahBlah!')
-
- def test_constantness_of_constants(self):
- class Universe(Enum):
- PI = constant(3.141596)
- G = constant(6.67300E-11)
- self.assertEqual(Universe.PI, 3.141596)
- self.assertRaisesRegex(AttributeError, r'cannot rebind constant', setattr, Universe, 'PI', 9)
- self.assertRaisesRegex(AttributeError, r'cannot delete constant', delattr, Universe, 'PI')
-
- def test_math_and_stuff_with_constants(self):
- class Universe(Enum):
- PI = constant(3.141596)
- TAU = constant(2 * PI)
- self.assertEqual(Universe.PI, 3.141596)
- self.assertEqual(Universe.TAU, 2 * Universe.PI)
-
- def test_constant_with_auto_is_updated(self):
- class Fruit(Flag):
- _order_ = 'apple banana lemon orange'
- apple = auto()
- banana = auto()
- lemon = auto()
- orange = auto()
- CitrusTypes = constant(lemon | orange)
- self.assertEqual(list(Fruit), [Fruit.apple, Fruit.banana, Fruit.lemon, Fruit.orange])
- self.assertEqual(list(Fruit.CitrusTypes), [Fruit.lemon, Fruit.orange])
- self.assertTrue(Fruit.orange in Fruit.CitrusTypes)
-
-
- def test_order_as_function(self):
- # first with _init_
- class TestSequence(Enum):
- _init_ = 'value, sequence'
- _order_ = lambda member: member.sequence
- item_id = 'An$(1,6)', 0 # Item Code
- company_id = 'An$(7,2)', 1 # Company Code
- warehouse_no = 'An$(9,4)', 2 # Warehouse Number
- company = 'Hn$(13,6)', 3 # 4 SPACES + COMPANY
- key_type = 'Cn$(19,3)', 4 # Key Type = '1**'
- available = 'Zn$(1,1)', 5 # Available?
- contract_item = 'Bn(2,1)', 6 # Contract Item?
- sales_category = 'Fn', 7 # Sales Category
- gl_category = 'Rn$(5,1)', 8 # G/L Category
- warehouse_category = 'Sn$(6,1)', 9 # Warehouse Category
- inv_units = 'Qn$(7,2)', 10 # Inv Units
- for i, member in enumerate(TestSequence):
- self.assertEqual(i, member.sequence)
- ts = TestSequence
- self.assertEqual(ts.item_id.name, 'item_id')
- self.assertEqual(ts.item_id.value, 'An$(1,6)')
- self.assertEqual(ts.item_id.sequence, 0)
- self.assertEqual(ts.company_id.name, 'company_id')
- self.assertEqual(ts.company_id.value, 'An$(7,2)')
- self.assertEqual(ts.company_id.sequence, 1)
- self.assertEqual(ts.warehouse_no.name, 'warehouse_no')
- self.assertEqual(ts.warehouse_no.value, 'An$(9,4)')
- self.assertEqual(ts.warehouse_no.sequence, 2)
- self.assertEqual(ts.company.name, 'company')
- self.assertEqual(ts.company.value, 'Hn$(13,6)')
- self.assertEqual(ts.company.sequence, 3)
- self.assertEqual(ts.key_type.name, 'key_type')
- self.assertEqual(ts.key_type.value, 'Cn$(19,3)')
- self.assertEqual(ts.key_type.sequence, 4)
- self.assertEqual(ts.available.name, 'available')
- self.assertEqual(ts.available.value, 'Zn$(1,1)')
- self.assertEqual(ts.available.sequence, 5)
- self.assertEqual(ts.contract_item.name, 'contract_item')
- self.assertEqual(ts.contract_item.value, 'Bn(2,1)')
- self.assertEqual(ts.contract_item.sequence, 6)
- self.assertEqual(ts.sales_category.name, 'sales_category')
- self.assertEqual(ts.sales_category.value, 'Fn')
- self.assertEqual(ts.sales_category.sequence, 7)
- self.assertEqual(ts.gl_category.name, 'gl_category')
- self.assertEqual(ts.gl_category.value, 'Rn$(5,1)')
- self.assertEqual(ts.gl_category.sequence, 8)
- self.assertEqual(ts.warehouse_category.name, 'warehouse_category')
- self.assertEqual(ts.warehouse_category.value, 'Sn$(6,1)')
- self.assertEqual(ts.warehouse_category.sequence, 9)
- self.assertEqual(ts.inv_units.name, 'inv_units')
- self.assertEqual(ts.inv_units.value, 'Qn$(7,2)')
- self.assertEqual(ts.inv_units.sequence, 10)
- # and then without
- class TestSequence(Enum):
- _order_ = lambda member: member.value[1]
- item_id = 'An$(1,6)', 0 # Item Code
- company_id = 'An$(7,2)', 1 # Company Code
- warehouse_no = 'An$(9,4)', 2 # Warehouse Number
- company = 'Hn$(13,6)', 3 # 4 SPACES + COMPANY
- key_type = 'Cn$(19,3)', 4 # Key Type = '1**'
- available = 'Zn$(1,1)', 5 # Available?
- contract_item = 'Bn(2,1)', 6 # Contract Item?
- sales_category = 'Fn', 7 # Sales Category
- gl_category = 'Rn$(5,1)', 8 # G/L Category
- warehouse_category = 'Sn$(6,1)', 9 # Warehouse Category
- inv_units = 'Qn$(7,2)', 10 # Inv Units
- for i, member in enumerate(TestSequence):
- self.assertEqual(i, member.value[1])
- ts = TestSequence
- self.assertEqual(ts.item_id.name, 'item_id')
- self.assertEqual(ts.item_id.value, ('An$(1,6)', 0))
- self.assertEqual(ts.company_id.name, 'company_id')
- self.assertEqual(ts.company_id.value, ('An$(7,2)', 1))
- self.assertEqual(ts.warehouse_no.name, 'warehouse_no')
- self.assertEqual(ts.warehouse_no.value, ('An$(9,4)', 2))
- self.assertEqual(ts.company.name, 'company')
- self.assertEqual(ts.company.value, ('Hn$(13,6)', 3))
- self.assertEqual(ts.key_type.name, 'key_type')
- self.assertEqual(ts.key_type.value, ('Cn$(19,3)', 4))
- self.assertEqual(ts.available.name, 'available')
- self.assertEqual(ts.available.value, ('Zn$(1,1)', 5))
- self.assertEqual(ts.contract_item.name, 'contract_item')
- self.assertEqual(ts.contract_item.value, ('Bn(2,1)', 6))
- self.assertEqual(ts.sales_category.name, 'sales_category')
- self.assertEqual(ts.sales_category.value, ('Fn', 7))
- self.assertEqual(ts.gl_category.name, 'gl_category')
- self.assertEqual(ts.gl_category.value, ('Rn$(5,1)', 8))
- self.assertEqual(ts.warehouse_category.name, 'warehouse_category')
- self.assertEqual(ts.warehouse_category.value, ('Sn$(6,1)', 9))
- self.assertEqual(ts.inv_units.name, 'inv_units')
- self.assertEqual(ts.inv_units.value, ('Qn$(7,2)', 10))
- # then with _init_ but without value
- with self.assertRaises(TypeError):
- class TestSequence(Enum):
- _init_ = 'sequence'
- _order_ = lambda member: member.sequence
- item_id = 'An$(1,6)', 0 # Item Code
- company_id = 'An$(7,2)', 1 # Company Code
- warehouse_no = 'An$(9,4)', 2 # Warehouse Number
- company = 'Hn$(13,6)', 3 # 4 SPACES + COMPANY
- key_type = 'Cn$(19,3)', 4 # Key Type = '1**'
- available = 'Zn$(1,1)', 5 # Available?
- contract_item = 'Bn(2,1)', 6 # Contract Item?
- sales_category = 'Fn', 7 # Sales Category
- gl_category = 'Rn$(5,1)', 8 # G/L Category
- warehouse_category = 'Sn$(6,1)', 9 # Warehouse Category
- inv_units = 'Qn$(7,2)', 10 # Inv Units
- # finally, out of order so Python 3 barfs
- with self.assertRaises(TypeError):
- class TestSequence(Enum):
- _init_ = 'sequence'
- _order_ = lambda member: member.sequence
- item_id = 'An$(1,6)', 0 # Item Code
- warehouse_no = 'An$(9,4)', 2 # Warehouse Number
- company = 'Hn$(13,6)', 3 # 4 SPACES + COMPANY
- company_id = 'An$(7,2)', 1 # Company Code
- inv_units = 'Qn$(7,2)', 10 # Inv Units
- available = 'Zn$(1,1)', 5 # Available?
- contract_item = 'Bn(2,1)', 6 # Contract Item?
- sales_category = 'Fn', 7 # Sales Category
- key_type = 'Cn$(19,3)', 4 # Key Type = '1**'
- gl_category = 'Rn$(5,1)', 8 # G/L Category
- warehouse_category = 'Sn$(6,1)', 9 # Warehouse Category
-
- def test_order_as_function_in_subclass(self):
- #
- class Parent(Enum):
- _init_ = 'value sequence'
- _order_ = lambda m: m.sequence
- #
- class Child(Parent):
- item_id = 'An$(1,6)', 0 # Item Code
- company_id = 'An$(7,2)', 1 # Company Code
- warehouse_no = 'An$(9,4)', 2 # Warehouse Number
- company = 'Hn$(13,6)', 3 # 4 SPACES + COMPANY
- key_type = 'Cn$(19,3)', 4 # Key Type = '1**'
- available = 'Zn$(1,1)', 5 # Available?
- contract_item = 'Bn(2,1)', 6 # Contract Item?
- sales_category = 'Fn', 7 # Sales Category
- gl_category = 'Rn$(5,1)', 8 # G/L Category
- warehouse_category = 'Sn$(6,1)', 9 # Warehouse Category
- inv_units = 'Qn$(7,2)', 10 # Inv Units
- #
- for i, member in enumerate(Child):
- self.assertEqual(i, member.sequence)
- #
- ts = Child
- self.assertEqual(ts.item_id.name, 'item_id')
- self.assertEqual(ts.item_id.value, 'An$(1,6)')
- self.assertEqual(ts.item_id.sequence, 0)
- self.assertEqual(ts.company_id.name, 'company_id')
- self.assertEqual(ts.company_id.value, 'An$(7,2)')
- self.assertEqual(ts.company_id.sequence, 1)
- self.assertEqual(ts.warehouse_no.name, 'warehouse_no')
- self.assertEqual(ts.warehouse_no.value, 'An$(9,4)')
- self.assertEqual(ts.warehouse_no.sequence, 2)
- self.assertEqual(ts.company.name, 'company')
- self.assertEqual(ts.company.value, 'Hn$(13,6)')
- self.assertEqual(ts.company.sequence, 3)
- self.assertEqual(ts.key_type.name, 'key_type')
- self.assertEqual(ts.key_type.value, 'Cn$(19,3)')
- self.assertEqual(ts.key_type.sequence, 4)
- self.assertEqual(ts.available.name, 'available')
- self.assertEqual(ts.available.value, 'Zn$(1,1)')
- self.assertEqual(ts.available.sequence, 5)
- self.assertEqual(ts.contract_item.name, 'contract_item')
- self.assertEqual(ts.contract_item.value, 'Bn(2,1)')
- self.assertEqual(ts.contract_item.sequence, 6)
- self.assertEqual(ts.sales_category.name, 'sales_category')
- self.assertEqual(ts.sales_category.value, 'Fn')
- self.assertEqual(ts.sales_category.sequence, 7)
- self.assertEqual(ts.gl_category.name, 'gl_category')
- self.assertEqual(ts.gl_category.value, 'Rn$(5,1)')
- self.assertEqual(ts.gl_category.sequence, 8)
- self.assertEqual(ts.warehouse_category.name, 'warehouse_category')
- self.assertEqual(ts.warehouse_category.value, 'Sn$(6,1)')
- self.assertEqual(ts.warehouse_category.sequence, 9)
- self.assertEqual(ts.inv_units.name, 'inv_units')
- self.assertEqual(ts.inv_units.value, 'Qn$(7,2)')
- self.assertEqual(ts.inv_units.sequence, 10)
-
- pass
-
- def test_multiple_mixin(self):
- class MaxMixin(object):
- @classproperty
- def MAX(cls):
- max = len(cls)
- cls.MAX = max
- return max
- class StrMixin(object):
- def __str__(self):
- return self._name_.lower()
- class SomeEnum(Enum):
- def behavior(self):
- return 'booyah'
- class AnotherEnum(Enum):
- def behavior(self):
- return 'nuhuh!'
- def social(self):
- return "what's up?"
- class Color(MaxMixin, Enum):
- _order_ = 'RED GREEN BLUE'
- RED = auto()
- GREEN = auto()
- BLUE = auto()
- self.assertEqual(Color.RED.value, 1)
- self.assertEqual(Color.GREEN.value, 2)
- self.assertEqual(Color.BLUE.value, 3)
- self.assertEqual(Color.MAX, 3)
- self.assertEqual(str(Color.BLUE), 'Color.BLUE')
- class Color(MaxMixin, StrMixin, Enum):
- _order_ = 'RED GREEN BLUE'
- RED = auto()
- GREEN = auto()
- BLUE = auto()
- self.assertEqual(Color.RED.value, 1)
- self.assertEqual(Color.GREEN.value, 2)
- self.assertEqual(Color.BLUE.value, 3)
- self.assertEqual(Color.MAX, 3)
- self.assertEqual(str(Color.BLUE), 'blue', '%r is not %r' % (str(Color.BLUE), 'blue'))
- class Color(StrMixin, MaxMixin, Enum):
- _order_ = 'RED GREEN BLUE'
- RED = auto()
- GREEN = auto()
- BLUE = auto()
- self.assertEqual(Color.RED.value, 1)
- self.assertEqual(Color.GREEN.value, 2)
- self.assertEqual(Color.BLUE.value, 3)
- self.assertEqual(Color.MAX, 3)
- self.assertEqual(str(Color.BLUE), 'blue', '%r is not %r' % (str(Color.BLUE), 'blue'))
- class CoolColor(StrMixin, SomeEnum, Enum):
- _order_ = 'RED GREEN BLUE'
- RED = auto()
- GREEN = auto()
- BLUE = auto()
- self.assertEqual(CoolColor.RED.value, 1)
- self.assertEqual(CoolColor.GREEN.value, 2)
- self.assertEqual(CoolColor.BLUE.value, 3)
- self.assertEqual(str(CoolColor.BLUE), 'blue', '%r is not %r' % (str(Color.BLUE), 'blue'))
- self.assertEqual(CoolColor.RED.behavior(), 'booyah')
- class CoolerColor(StrMixin, AnotherEnum, Enum):
- _order_ = 'RED GREEN BLUE'
- RED = auto()
- GREEN = auto()
- BLUE = auto()
- self.assertEqual(CoolerColor.RED.value, 1)
- self.assertEqual(CoolerColor.GREEN.value, 2)
- self.assertEqual(CoolerColor.BLUE.value, 3)
- self.assertEqual(str(CoolerColor.BLUE), 'blue', '%r is not %r' % (str(Color.BLUE), 'blue'))
- self.assertEqual(CoolerColor.RED.behavior(), 'nuhuh!')
- self.assertEqual(CoolerColor.RED.social(), "what's up?")
- class CoolestColor(StrMixin, SomeEnum, AnotherEnum):
- _order_ = 'RED GREEN BLUE'
- RED = auto()
- GREEN = auto()
- BLUE = auto()
- self.assertEqual(CoolestColor.RED.value, 1)
- self.assertEqual(CoolestColor.GREEN.value, 2)
- self.assertEqual(CoolestColor.BLUE.value, 3)
- self.assertEqual(str(CoolestColor.BLUE), 'blue', '%r is not %r' % (str(Color.BLUE), 'blue'))
- self.assertEqual(CoolestColor.RED.behavior(), 'booyah')
- self.assertEqual(CoolestColor.RED.social(), "what's up?")
- class ConfusedColor(StrMixin, AnotherEnum, SomeEnum):
- _order_ = 'RED GREEN BLUE'
- RED = auto()
- GREEN = auto()
- BLUE = auto()
- self.assertEqual(ConfusedColor.RED.value, 1)
- self.assertEqual(ConfusedColor.GREEN.value, 2)
- self.assertEqual(ConfusedColor.BLUE.value, 3)
- self.assertEqual(str(ConfusedColor.BLUE), 'blue', '%r is not %r' % (str(Color.BLUE), 'blue'))
- self.assertEqual(ConfusedColor.RED.behavior(), 'nuhuh!')
- self.assertEqual(ConfusedColor.RED.social(), "what's up?")
- class ReformedColor(StrMixin, IntEnum, SomeEnum, AnotherEnum):
- _order_ = 'RED GREEN BLUE'
- RED = auto()
- GREEN = auto()
- BLUE = auto()
- self.assertEqual(ReformedColor.RED.value, 1)
- self.assertEqual(ReformedColor.GREEN.value, 2)
- self.assertEqual(ReformedColor.BLUE.value, 3)
- self.assertEqual(str(ReformedColor.BLUE), 'blue', '%r is not %r' % (str(Color.BLUE), 'blue'))
- self.assertEqual(ReformedColor.RED.behavior(), 'booyah')
- self.assertEqual(ConfusedColor.RED.social(), "what's up?")
- self.assertTrue(issubclass(ReformedColor, int))
-
- def test_multiple_inherited_mixin(self):
- @unique
- class Decision1(StrEnum):
- REVERT = "REVERT"
- REVERT_ALL = "REVERT_ALL"
- RETRY = "RETRY"
- class MyEnum(StrEnum):
- pass
- @unique
- class Decision2(MyEnum):
- REVERT = "REVERT"
- REVERT_ALL = "REVERT_ALL"
- RETRY = "RETRY"
-
- def test_value_auto_assign(self):
- class Some(Enum):
- def __new__(cls, val):
- return object.__new__(cls)
- x = 1
- y = 2
- self.assertEqual(Some.x.value, 1)
- self.assertEqual(Some.y.value, 2)
-
- def test_enum_of_types(self):
- """Support using Enum to refer to types deliberately."""
- class MyTypes(Enum):
- i = int
- f = float
- s = str
- self.assertEqual(MyTypes.i.value, int)
- self.assertEqual(MyTypes.f.value, float)
- self.assertEqual(MyTypes.s.value, str)
- class Foo:
- pass
- class Bar:
- pass
- class MyTypes2(Enum):
- a = Foo
- b = Bar
- self.assertEqual(MyTypes2.a.value, Foo)
- self.assertEqual(MyTypes2.b.value, Bar)
- class SpamEnumNotInner:
- pass
- class SpamEnum(Enum):
- spam = SpamEnumNotInner
- self.assertEqual(SpamEnum.spam.value, SpamEnumNotInner)
-
- if PY2:
- def test_nested_classes_in_enum_do_become_members(self):
- # manually set __qualname__ to remove testing framework noise
- class Outer(Enum):
- _order_ = 'a b Inner'
- __qualname__ = "Outer"
- a = 1
- b = 2
- class Inner(Enum):
- __qualname__ = "Outer.Inner"
- foo = 10
- bar = 11
- self.assertTrue(isinstance(Outer.Inner, Outer))
- self.assertEqual(Outer.a.value, 1)
- self.assertEqual(Outer.Inner.value.foo.value, 10)
- self.assertEqual(
- list(Outer.Inner.value),
- [Outer.Inner.value.foo, Outer.Inner.value.bar],
- )
- self.assertEqual(
- list(Outer),
- [Outer.a, Outer.b, Outer.Inner],
- )
-
- def test_really_nested_classes_in_enum_do_become_members(self):
- class Outer(Enum):
- _order_ = 'a b Inner'
- a = 1
- b = 2
- class Inner(Enum):
- foo = 10
- bar = 11
- self.assertTrue(isinstance(Outer.Inner, Outer))
- self.assertEqual(Outer.a.value, 1)
- self.assertEqual(Outer.Inner.value.foo.value, 10)
- self.assertEqual(
- list(Outer.Inner.value),
- [Outer.Inner.value.foo, Outer.Inner.value.bar],
- )
- self.assertEqual(
- list(Outer),
- [Outer.a, Outer.b, Outer.Inner],
- )
-
- def test_nested_classes_in_enum_are_skipped_with_skip(self):
- """Support locally-defined nested classes using @skip"""
- # manually set __qualname__ to remove testing framework noise
- class Outer(Enum):
- __qualname__ = "Outer"
- a = 1
- b = 2
- @skip
- class Inner(Enum):
- __qualname__ = "Outer.Inner"
- foo = 10
- bar = 11
- self.assertTrue(isinstance(Outer.Inner, type))
- self.assertEqual(Outer.a.value, 1)
- self.assertEqual(Outer.Inner.foo.value, 10)
- self.assertEqual(
- list(Outer.Inner),
- [Outer.Inner.foo, Outer.Inner.bar],
- )
- self.assertEqual(
- list(Outer),
- [Outer.a, Outer.b],
- )
-
- def test_really_nested_classes_in_enum_are_skipped_with_skip(self):
- """Support locally-defined nested classes using @skip"""
- class Outer(Enum):
- a = 1
- b = 2
- @skip
- class Inner(Enum):
- foo = 10
- bar = 11
- self.assertTrue(isinstance(Outer.Inner, type))
- self.assertEqual(Outer.a.value, 1)
- self.assertEqual(Outer.Inner.foo.value, 10)
- self.assertEqual(
- list(Outer.Inner),
- [Outer.Inner.foo, Outer.Inner.bar],
- )
- self.assertEqual(
- list(Outer),
- [Outer.a, Outer.b],
- )
-
- def test_enum_call_without_arg(self):
- class Color(Enum):
- black = 0
- red = 1
- green = 2
- blue = 3
- #
- @classmethod
- def _missing_value_(cls, value):
- if value is no_arg:
- return cls.black
- self.assertTrue(Color.red is Color(1))
- self.assertTrue(Color.black is Color())
-
- def test_init_subclass(self):
- class MyEnum(Enum):
- def __init_subclass__(cls, **kwds):
- super(MyEnum, cls).__init_subclass__(**kwds)
- self.assertFalse(cls.__dict__.get('_test', False))
- cls._test1 = 'MyEnum'
- #
- class TheirEnum(MyEnum):
- def __init_subclass__(cls, **kwds):
- super(TheirEnum, cls).__init_subclass__(**kwds)
- cls._test2 = 'TheirEnum'
- class WhoseEnum(TheirEnum):
- def __init_subclass__(cls, **kwds):
- pass
- class NoEnum(WhoseEnum):
- ONE = 1
- self.assertEqual(TheirEnum.__dict__['_test1'], 'MyEnum')
- self.assertEqual(WhoseEnum.__dict__['_test1'], 'MyEnum')
- self.assertEqual(WhoseEnum.__dict__['_test2'], 'TheirEnum')
- self.assertFalse(NoEnum.__dict__.get('_test1', False))
- self.assertFalse(NoEnum.__dict__.get('_test2', False))
- #
- class OurEnum(MyEnum):
- def __init_subclass__(cls, **kwds):
- cls._test2 = 'OurEnum'
- class WhereEnum(OurEnum):
- def __init_subclass__(cls, **kwds):
- pass
- class NeverEnum(WhereEnum):
- ONE = 'one'
- self.assertEqual(OurEnum.__dict__['_test1'], 'MyEnum')
- self.assertFalse(WhereEnum.__dict__.get('_test1', False))
- self.assertEqual(WhereEnum.__dict__['_test2'], 'OurEnum')
- self.assertFalse(NeverEnum.__dict__.get('_test1', False))
- self.assertFalse(NeverEnum.__dict__.get('_test2', False))
-
-
-class TestStrEnum(TestCase):
-
- def test_set_name(self):
- class Descriptor(object):
- name = None
- def __get__(self, instance, owner_class=None):
- if instance is None:
- return self
- else:
- return instance.__dict__[self.name]
- def __set__(self, instance, value):
- instance.__dict__[self.name] = value
- def __set_name__(self, owner, name):
- self.name = name
- #
- class AnEnum(Enum):
- ONE = 'one'
- two = Descriptor()
- #
- self.assertEqual(list(AnEnum), [AnEnum.ONE])
- self.assertEqual(AnEnum.two.name, 'two')
- AnEnum.ONE.two = 'three'
- self.assertEqual(AnEnum.ONE.two, 'three')
- self.assertEqual(AnEnum.ONE.__dict__['two'], 'three')
-
- def test_private_names(self):
- class Private(Enum):
- __corporal = 'Radar'
- __major_ = 'Hoolihan'
- self.assertEqual(len(Private), 0)
- self.assertEqual(Private._Private__corporal, 'Radar')
- self.assertFalse(isinstance(Private._Private__corporal, Enum))
- self.assertEqual(Private._Private__major_, 'Hoolihan')
- self.assertFalse(isinstance(Private._Private__major_, Enum))
-
- def test_strenum_inherited_methods(self):
- class phy(StrEnum):
- pi = 'Pi'
- tau = 'Tau'
- self.assertTrue(phy.pi < phy.tau)
- self.assertEqual(phy.pi.upper(), 'PI')
- self.assertEqual(phy.tau.count('a'), 1)
-
- def test_strict_strenum(self):
- for uhoh in (object, object(), [], Enum, 9):
- with self.assertRaisesRegex(TypeError, r'values must be str'):
- class Huh(StrEnum):
- huh = uhoh
- class Either(StrEnum):
- _order_ = 'this that Those lower upper'
- this = auto()
- that = 'That'
- Those = auto()
- lower = 'lower'
- upper = 'UPPER'
- self.assertEqual([m.value for m in Either], ['this', 'That', 'those', 'lower', 'UPPER'])
- #
- with self.assertRaisesRegex(ValueError, r' is not lower-case'):
- class Huh(LowerStrEnum):
- huh = 'What'
- #
- class Lower(LowerStrEnum):
- _order_ = 'this that Those lower upper'
- this = auto()
- that = 'that'
- Those = auto()
- lower = 'lower'
- upper = 'upper'
- self.assertEqual([m.value for m in Lower], ['this', 'that', 'those', 'lower', 'upper'])
- #
- with self.assertRaisesRegex(ValueError, r' is not upper-case'):
- class Huh(UpperStrEnum):
- huh = 'What'
- #
- class Upper(UpperStrEnum):
- _order_ = 'this that Those lower upper'
- this = auto()
- that = 'THAT'
- Those = auto()
- lower = 'LOWER'
- upper = 'UPPER'
- self.assertEqual([m.value for m in Upper], ['THIS', 'THAT', 'THOSE', 'LOWER', 'UPPER'])
-
- def test_init_subclass(self):
- class MyEnum(StrEnum):
- def __init_subclass__(cls, **kwds):
- super(MyEnum, cls).__init_subclass__(**kwds)
- self.assertFalse(cls.__dict__.get('_test', False))
- cls._test1 = 'MyEnum'
- #
- class TheirEnum(MyEnum):
- def __init_subclass__(cls, **kwds):
- super(TheirEnum, cls).__init_subclass__(**kwds)
- cls._test2 = 'TheirEnum'
- class WhoseEnum(TheirEnum):
- def __init_subclass__(cls, **kwds):
- pass
- class NoEnum(WhoseEnum):
- ONE = 'one'
- self.assertEqual(TheirEnum.__dict__['_test1'], 'MyEnum')
- self.assertEqual(WhoseEnum.__dict__['_test1'], 'MyEnum')
- self.assertEqual(WhoseEnum.__dict__['_test2'], 'TheirEnum')
- self.assertFalse(NoEnum.__dict__.get('_test1', False))
- self.assertFalse(NoEnum.__dict__.get('_test2', False))
- #
- class OurEnum(MyEnum):
- def __init_subclass__(cls, **kwds):
- cls._test2 = 'OurEnum'
- class WhereEnum(OurEnum):
- def __init_subclass__(cls, **kwds):
- pass
- class NeverEnum(WhereEnum):
- ONE = 'one'
- self.assertEqual(OurEnum.__dict__['_test1'], 'MyEnum')
- self.assertFalse(WhereEnum.__dict__.get('_test1', False))
- self.assertEqual(WhereEnum.__dict__['_test2'], 'OurEnum')
- self.assertFalse(NeverEnum.__dict__.get('_test1', False))
- self.assertFalse(NeverEnum.__dict__.get('_test2', False))
-
-
-class TestFlag(TestCase):
- """Tests of the Flags."""
-
- def setUp(self):
- class Perm(Flag):
- _order_ = 'R W X'
- R, W, X = 4, 2, 1
- self.Perm = Perm
- #
- class Color(Flag):
- BLACK = 0
- RED = 1
- ROJO = 1
- GREEN = 2
- BLUE = 4
- PURPLE = RED|BLUE
- WHITE = RED|GREEN|BLUE
- BLANCO = RED|GREEN|BLUE
- self.Color = Color
- #
- class Fun(Flag):
- _order_ = 'ONE TWO FOUR EIGHT'
- ONE = auto()
- TWO = auto()
- THREE = ONE | TWO
- FOUR = auto()
- FIVE = FOUR | ONE
- SIX = FOUR | TWO
- SEVEN = FOUR | TWO | ONE
- EIGHT = auto()
- self.Fun = Fun
- #
- class TermColor(str, Flag):
- def __new__(cls, value, code):
- str_value = '\x1b[%sm' % code
- obj = str.__new__(cls, str_value)
- obj._value_ = value
- obj.code = code
- return obj
- #
- @classmethod
- def _create_pseudo_member_values_(cls, members, *values):
- code = ';'.join(m.code for m in members)
- return values + (code, )
- #
- AllReset = '0' # ESC [ 0 m # reset all (colors and brightness)
- Bright = '1' # ESC [ 1 m # bright
- Dim = '2' # ESC [ 2 m # dim (looks same as normal brightness)
- Underline = '4'
- Normal = '22' # ESC [ 22 m # normal brightness
- #
- # # FOREGROUND - 30s BACKGROUND - 40s:
- FG_Black = '30' # ESC [ 30 m # black
- FG_Red = '31' # ESC [ 31 m # red
- FG_Green = '32' # ESC [ 32 m # green
- FG_Yellow = '33' # ESC [ 33 m # yellow
- FG_Blue = '34' # ESC [ 34 m # blue
- FG_Magenta = '35' # ESC [ 35 m # magenta
- FG_Cyan = '36' # ESC [ 36 m # cyan
- FG_White = '37' # ESC [ 37 m # white
- FG_Reset = '39' # ESC [ 39 m # reset
- #
- BG_Black = '40' # ESC [ 30 m # black
- BG_Red = '41' # ESC [ 31 m # red
- BG_Green = '42' # ESC [ 32 m # green
- BG_Yellow = '43' # ESC [ 33 m # yellow
- BG_Blue = '44' # ESC [ 34 m # blue
- BG_Magenta = '45' # ESC [ 35 m # magenta
- BG_Cyan = '46' # ESC [ 36 m # cyan
- BG_White = '47' # ESC [ 37 m # white
- BG_Reset = '49' # ESC [ 39 m # reset
- #
- __str__ = str.__str__
- #
- def __repr__(self):
- if self._name_ is not None:
- return '<%s.%s>' % (self.__class__.__name__, self._name_)
- else:
- return '<%s: %s>' % (self.__class__.__name__, '|'.join([m.name for m in Flag.__iter__(self)]))
- #
- def __enter__(self):
- print(self.AllReset, end='', verbose=0)
- return self
- #
- def __exit__(self, *args):
- print(self.AllReset, end='', verbose=0)
- self.TermColor = TermColor
- #
- class Open(Flag):
- RO = 0
- WO = 1
- RW = 2
- AC = 3
- CE = 1<<19
- self.Open = Open
-
- def test_set_name(self):
- class Descriptor(object):
- name = None
- def __get__(self, instance, owner_class=None):
- if instance is None:
- return self
- else:
- return instance.__dict__[self.name]
- def __set__(self, instance, value):
- instance.__dict__[self.name] = value
- def __set_name__(self, owner, name):
- self.name = name
- #
- class AnEnum(Enum):
- ONE = 1
- two = Descriptor()
- #
- self.assertEqual(list(AnEnum), [AnEnum.ONE])
- self.assertEqual(AnEnum.two.name, 'two')
- AnEnum.ONE.two = 'three'
- self.assertEqual(AnEnum.ONE.two, 'three')
- self.assertEqual(AnEnum.ONE.__dict__['two'], 'three')
-
- def test_new_with_keywords(self):
- class Huh(IntFlag):
- __order__ = 'PLAIN BOLD_ITALIC HIGHLIGHT'
- def __new__(cls, docstring, open=None, close=None):
- if cls.__members__:
- value = 2 ** (len(cls.__members__)-1)
- else:
- value = 0
- member = int.__new__(cls, value)
- if open and close is None:
- close = open
- member.open = open
- member.close = close
- member.__doc__ = docstring
- member._value_ = value
- return member
- PLAIN = 'normal'
- BOLD_ITALIC = '***really super important***', '***'
- HIGHLIGHT = 'please ==take notice==', '==', '=='
- p = Huh.PLAIN
- self.assertTrue(type(p) is Huh, type(p))
- self.assertEqual(
- (p.value, p.__doc__, p.open, p.close),
- (0, 'normal', None, None),
- )
- bi = Huh.BOLD_ITALIC
- self.assertEqual(
- (bi.value, bi.__doc__, bi.open, bi.close),
- (1, '***really super important***', '***', '***'),
- )
- h = Huh.HIGHLIGHT
- self.assertEqual(
- (h.value, h.__doc__, h.open, h.close),
- (2, 'please ==take notice==', '==', '=='),
- )
-
- def test_private_names(self):
- class Private(Enum):
- __corporal = 'Radar'
- __major_ = 'Hoolihan'
- self.assertEqual(len(Private), 0)
- self.assertEqual(Private._Private__corporal, 'Radar')
- self.assertFalse(isinstance(Private._Private__corporal, Enum))
- self.assertEqual(Private._Private__major_, 'Hoolihan')
- self.assertFalse(isinstance(Private._Private__major_, Enum))
-
- def test_auto_alias(self):
- Fun = self.Fun
- self.assertEqual(
- list(Fun),
- [Fun.ONE, Fun.TWO, Fun.FOUR, Fun.EIGHT],
- )
- self.assertEqual(Fun.THREE._value_, 3)
- self.assertEqual(repr(Fun.SEVEN), '<Fun.SEVEN: 7>')
- self.assertEqual(list(Fun.SEVEN), [Fun.ONE, Fun.TWO, Fun.FOUR])
-
- def test_str_is_str_str(self):
- red, white = self.TermColor.FG_Red, self.TermColor.BG_White
- barber = red | white
- self.assertEqual(barber, '\x1b[31;47m')
- self.assertEqual(barber.value, red.value | white.value)
- self.assertEqual(barber.code, ';'.join([red.code, white.code]))
- self.assertEqual(repr(barber), '<TermColor.FG_Red|BG_White>')
- self.assertEqual(str(barber), '\x1b[31;47m')
-
- def test_membership(self):
- Color = self.Color
- Open = self.Open
- self.assertRaises(TypeError, lambda: 'BLACK' in Color)
- self.assertRaises(TypeError, lambda: 'RO' in Open)
- self.assertTrue(Color.BLACK in Color)
- self.assertTrue(Open.RO in Open)
- self.assertFalse(Color.BLACK in Open)
- self.assertFalse(Open.RO in Color)
- self.assertRaises(TypeError, lambda: 0 in Color)
- self.assertRaises(TypeError, lambda: 0 in Open)
-
- def test_member_contains(self):
- Color = self.Color
- self.assertRaises(TypeError, lambda: 'test' in Color.BLUE)
- self.assertRaises(TypeError, lambda: 2 in Color.BLUE)
- self.assertTrue(Color.BLUE in Color.BLUE)
- self.assertTrue(Color.BLUE in Color['RED|GREEN|BLUE'])
-
- def test_member_length(self):
- self.assertEqual(self.Color.__len__(self.Color.BLACK), 0)
- self.assertEqual(self.Color.__len__(self.Color.GREEN), 1)
- self.assertEqual(self.Color.__len__(self.Color.PURPLE), 2)
- self.assertEqual(self.Color.__len__(self.Color.BLANCO), 3)
-
- def test_number_reset_and_order_cleanup(self):
- class Confused(Flag):
- _order_ = 'ONE TWO FOUR DOS EIGHT SIXTEEN'
- ONE = auto()
- TWO = auto()
- FOUR = auto()
- DOS = 2
- EIGHT = auto()
- SIXTEEN = auto()
- self.assertEqual(
- list(Confused),
- [Confused.ONE, Confused.TWO, Confused.FOUR, Confused.EIGHT, Confused.SIXTEEN])
- self.assertIs(Confused.TWO, Confused.DOS)
- self.assertEqual(Confused.DOS._value_, 2)
- self.assertEqual(Confused.EIGHT._value_, 8)
- self.assertEqual(Confused.SIXTEEN._value_, 16)
-
- def test_str(self):
- Perm = self.Perm
- self.assertEqual(str(Perm.R), 'Perm.R')
- self.assertEqual(str(Perm.W), 'Perm.W')
- self.assertEqual(str(Perm.X), 'Perm.X')
- self.assertEqual(str(Perm.R | Perm.W), 'Perm.R|W')
- self.assertEqual(str(Perm.R | Perm.W | Perm.X), 'Perm.R|W|X')
- self.assertEqual(str(Perm(0)), 'Perm(0)')
- self.assertEqual(str(~Perm.R), 'Perm.W|X')
- self.assertEqual(str(~Perm.W), 'Perm.R|X')
- self.assertEqual(str(~Perm.X), 'Perm.R|W')
- self.assertEqual(str(~(Perm.R | Perm.W)), 'Perm.X')
- self.assertEqual(str(~(Perm.R | Perm.W | Perm.X)), 'Perm(0)')
- self.assertEqual(str(Perm(-1)), 'Perm.R|W|X')
- self.assertEqual(str(Perm(~0)), 'Perm.R|W|X')
-
- Open = self.Open
- self.assertEqual(str(Open.RO), 'Open.RO')
- self.assertEqual(str(Open.WO), 'Open.WO')
- self.assertEqual(str(Open.AC), 'Open.AC')
- self.assertEqual(str(Open.RO | Open.CE), 'Open.CE')
- self.assertEqual(str(Open.WO | Open.CE), 'Open.WO|CE')
- self.assertEqual(str(~Open.RO), 'Open.WO|RW|CE')
- self.assertEqual(str(~Open.WO), 'Open.RW|CE')
- self.assertEqual(str(~Open.AC), 'Open.CE')
- self.assertEqual(str(~(Open.RO | Open.CE)), 'Open.AC')
- self.assertEqual(str(~(Open.WO | Open.CE)), 'Open.RW')
-
- def test_repr(self):
- Perm = self.Perm
- self.assertEqual(repr(Perm.R), '<Perm.R: 4>')
- self.assertEqual(repr(Perm.W), '<Perm.W: 2>')
- self.assertEqual(repr(Perm.X), '<Perm.X: 1>')
- self.assertEqual(repr(Perm.R | Perm.W), '<Perm.R|W: 6>')
- self.assertEqual(repr(Perm.R | Perm.W | Perm.X), '<Perm.R|W|X: 7>')
- self.assertEqual(repr(Perm(0)), '<Perm: 0>')
- self.assertEqual(repr(~Perm.R), '<Perm.W|X: 3>')
- self.assertEqual(repr(~Perm.W), '<Perm.R|X: 5>')
- self.assertEqual(repr(~Perm.X), '<Perm.R|W: 6>')
- self.assertEqual(repr(~(Perm.R | Perm.W)), '<Perm.X: 1>')
- self.assertEqual(repr(~(Perm.R | Perm.W | Perm.X)), '<Perm: 0>')
- self.assertEqual(repr(Perm(~0)), '<Perm.R|W|X: 7>')
-
- Open = self.Open
- self.assertEqual(repr(Open.RO), '<Open.RO: 0>')
- self.assertEqual(repr(Open.WO), '<Open.WO: 1>')
- self.assertEqual(repr(Open.AC), '<Open.AC: 3>')
- self.assertEqual(repr(Open.RO | Open.CE), '<Open.CE: 524288>')
- self.assertEqual(repr(Open.WO | Open.CE), '<Open.WO|CE: 524289>')
- self.assertEqual(repr(~Open.RO), '<Open.WO|RW|CE: 524291>')
- self.assertEqual(repr(~Open.WO), '<Open.RW|CE: 524290>')
- self.assertEqual(repr(~Open.AC), '<Open.CE: 524288>')
- self.assertEqual(repr(~(Open.RO | Open.CE)), '<Open.AC: 3>')
- self.assertEqual(repr(~(Open.WO | Open.CE)), '<Open.RW: 2>')
-
- def test_name_lookup(self):
- Color = self.Color
- self.assertTrue(Color.RED is Color['RED'])
- self.assertTrue(Color.RED|Color.GREEN is Color['RED|GREEN'])
- self.assertTrue(Color.PURPLE is Color['RED|BLUE'])
-
- def test_or(self):
- Perm = self.Perm
- for i in Perm:
- for j in Perm:
- self.assertEqual((i | j), Perm(i.value | j.value))
- self.assertEqual((i | j).value, i.value | j.value)
- self.assertIs(type(i | j), Perm)
- for i in Perm:
- self.assertIs(i | i, i)
- Open = self.Open
- self.assertIs(Open.RO | Open.CE, Open.CE)
-
- def test_and(self):
- Perm = self.Perm
- RW = Perm.R | Perm.W
- RX = Perm.R | Perm.X
- WX = Perm.W | Perm.X
- RWX = Perm.R | Perm.W | Perm.X
- values = list(Perm) + [RW, RX, WX, RWX, Perm(0)]
- for i in values:
- for j in values:
- self.assertEqual((i & j).value, i.value & j.value)
- self.assertIs(type(i & j), Perm)
- for i in Perm:
- self.assertIs(i & i, i)
- self.assertIs(i & RWX, i)
- self.assertIs(RWX & i, i)
- Open = self.Open
- self.assertIs(Open.RO & Open.CE, Open.RO)
-
- def test_xor(self):
- Perm = self.Perm
- for i in Perm:
- for j in Perm:
- self.assertEqual((i ^ j).value, i.value ^ j.value)
- self.assertIs(type(i ^ j), Perm)
- for i in Perm:
- self.assertIs(i ^ Perm(0), i)
- self.assertIs(Perm(0) ^ i, i)
- Open = self.Open
- self.assertIs(Open.RO ^ Open.CE, Open.CE)
- self.assertIs(Open.CE ^ Open.CE, Open.RO)
-
- def test_invert(self):
- Perm = self.Perm
- RW = Perm.R | Perm.W
- RX = Perm.R | Perm.X
- WX = Perm.W | Perm.X
- RWX = Perm.R | Perm.W | Perm.X
- values = list(Perm) + [RW, RX, WX, RWX, Perm(0)]
- for i in values:
- self.assertIs(type(~i), Perm)
- self.assertEqual(~~i, i)
- for i in Perm:
- self.assertIs(~~i, i)
- Open = self.Open
- self.assertIs(Open.WO & ~Open.WO, Open.RO)
- self.assertIs((Open.WO|Open.CE) & ~Open.WO, Open.CE)
-
- def test_bool(self):
- Perm = self.Perm
- for f in Perm:
- self.assertTrue(f)
- Open = self.Open
- for f in Open:
- self.assertEqual(bool(f.value), bool(f))
-
- def test_doc_flag(self):
- class DocFlag(Flag):
- _init_ = 'value __doc__'
- _start_ = 0
- # def __new__(cls, value, doc=None):
- # # if doc is None and isinstance(value, basestring):
- # # value, doc = doc, value
- # # if value is None:
- # # if not len(cls):
- # # value = 0
- # # else:
- # # value = 2 ** (len(cls) -1)
- # # if not isinstance(value, baseinteger):
- # # raise TypeError("%r is not a valid %s value" % (value, cls.__name__))
- # obj = object.__new__(cls)
- # # if doc is None, don't mess with the value
- # if doc:
- # value = value >> 1
- # obj._value_ = value
- # obj.__doc__ = doc
- # return obj
- #
- class AddressSegment(DocFlag):
- _order_ = 'UNKNOWN PO PO_TYPE NUMBER PREORD NAME STREET POSTORD SECONDARY_TYPE SECONDARY_NUMBER AND'
- UNKNOWN = "unable to determine address element type"
- PO = "post office delivery"
- PO_TYPE = "box or drawer"
- NUMBER = "main unit designator"
- PREORD = "N S E W etc"
- NAME = "street name"
- STREET = "st ave blvd etc"
- POSTORD = "N S E W etc"
- SECONDARY_TYPE = "apt bldg floor etc"
- SECONDARY_NUMBER = "secondary unit designator"
- AND = "& indicates a corner address"
- AS = AddressSegment
- self.assertEqual(AS.NAME._value_, 16)
- self.assertEqual(AS.STREET._value_, 32)
- self.assertEqual(AS.SECONDARY_TYPE._value_, 128)
- self.assertEqual((AS.NAME | AS.STREET)._value_, 48, "%r is not 48" % (AS.NAME | AS.STREET))
-
- def test_iteration(self):
- C = self.Color
- self.assertEqual(list(C), [C.RED, C.GREEN, C.BLUE])
- self.assertEqual(list(C.PURPLE), [C.RED, C.BLUE])
-
- def test_member_iteration(self):
- C = self.Color
- self.assertEqual(list(C.BLACK), [])
- self.assertEqual(list(C.RED), [C.RED])
- self.assertEqual(list(C.PURPLE), [C.RED, C.BLUE])
-
- def test_programatic_function_string(self):
- Perm = Flag('Perm', 'R W X')
- lst = list(Perm)
- self.assertEqual(len(lst), len(Perm))
- self.assertEqual(len(Perm), 3, Perm)
- self.assertEqual(lst, [Perm.R, Perm.W, Perm.X])
- for i, n in enumerate('R W X'.split()):
- v = 1<<i
- e = Perm(v)
- self.assertEqual(e.value, v)
- self.assertEqual(type(e.value), int)
- self.assertEqual(e.name, n)
- self.assertIn(e, Perm)
- self.assertIs(type(e), Perm)
-
- def test_programatic_function_string_with_start(self):
- Perm = Flag('Perm', 'R W X', start=8)
- lst = list(Perm)
- self.assertEqual(len(lst), len(Perm))
- self.assertEqual(len(Perm), 3, Perm)
- self.assertEqual(lst, [Perm.R, Perm.W, Perm.X])
- for i, n in enumerate('R W X'.split()):
- v = 8<<i
- e = Perm(v)
- self.assertEqual(e.value, v)
- self.assertEqual(type(e.value), int)
- self.assertEqual(e.name, n)
- self.assertIn(e, Perm)
- self.assertIs(type(e), Perm)
-
- def test_programatic_function_string_list(self):
- Perm = Flag('Perm', ['R', 'W', 'X'])
- lst = list(Perm)
- self.assertEqual(len(lst), len(Perm))
- self.assertEqual(len(Perm), 3, Perm)
- self.assertEqual(lst, [Perm.R, Perm.W, Perm.X])
- for i, n in enumerate('R W X'.split()):
- v = 1<<i
- e = Perm(v)
- self.assertEqual(e.value, v)
- self.assertEqual(type(e.value), int)
- self.assertEqual(e.name, n)
- self.assertIn(e, Perm)
- self.assertIs(type(e), Perm)
-
- def test_programatic_function_iterable(self):
- Perm = Flag('Perm', (('R', 2), ('W', 8), ('X', 32)))
- lst = list(Perm)
- self.assertEqual(len(lst), len(Perm))
- self.assertEqual(len(Perm), 3, Perm)
- self.assertEqual(lst, [Perm.R, Perm.W, Perm.X])
- for i, n in enumerate('R W X'.split()):
- v = 1<<(2*i+1)
- e = Perm(v)
- self.assertEqual(e.value, v)
- self.assertEqual(type(e.value), int)
- self.assertEqual(e.name, n)
- self.assertIn(e, Perm)
- self.assertIs(type(e), Perm)
-
- def test_programatic_function_from_dict(self):
- Perm = Flag('Perm', OrderedDict((('R', 2), ('W', 8), ('X', 32))))
- lst = list(Perm)
- self.assertEqual(len(lst), len(Perm))
- self.assertEqual(len(Perm), 3, Perm)
- self.assertEqual(lst, [Perm.R, Perm.W, Perm.X])
- for i, n in enumerate('R W X'.split()):
- v = 1<<(2*i+1)
- e = Perm(v)
- self.assertEqual(e.value, v)
- self.assertEqual(type(e.value), int)
- self.assertEqual(e.name, n)
- self.assertIn(e, Perm)
- self.assertIs(type(e), Perm)
-
- def test_programatic_function_empty_list(self):
- Perm = IntFlag('Perm', [])
- self.assertEqual(len(list(Perm)), len(Perm))
- self.assertEqual(len(Perm), 0)
- Thing = Enum('Thing', [])
- self.assertEqual(len(list(Thing)), len(Thing))
- self.assertEqual(len(Thing), 0)
-
- def test_programatic_function_empty_tuple(self):
- Perm = IntFlag('Perm', ())
- self.assertEqual(len(list(Perm)), len(Perm))
- self.assertEqual(len(Perm), 0)
- Thing = Enum('Thing', ())
- self.assertEqual(len(list(Thing)), len(Thing))
- self.assertEqual(len(Thing), 0)
-
- def test_pickle(self):
- if isinstance(FlagStooges, Exception):
- raise FlagStooges
- test_pickle_dump_load(self.assertIs, FlagStooges.CURLY|FlagStooges.MOE)
- test_pickle_dump_load(self.assertIs, FlagStooges)
-
- def test_containment(self):
- Perm = self.Perm
- R, W, X = Perm
- RW = R | W
- RX = R | X
- WX = W | X
- RWX = R | W | X
- self.assertTrue(R in RW)
- self.assertTrue(R in RX)
- self.assertTrue(R in RWX)
- self.assertTrue(W in RW)
- self.assertTrue(W in WX)
- self.assertTrue(W in RWX)
- self.assertTrue(X in RX)
- self.assertTrue(X in WX)
- self.assertTrue(X in RWX)
- self.assertFalse(R in WX)
- self.assertFalse(W in RX)
- self.assertFalse(X in RW)
-
- def test_auto_number(self):
- class Color(Flag):
- _order_ = 'red blue green'
- red = auto()
- blue = auto()
- green = auto()
-
- self.assertEqual(list(Color), [Color.red, Color.blue, Color.green])
- self.assertEqual(Color.red.value, 1)
- self.assertEqual(Color.blue.value, 2)
- self.assertEqual(Color.green.value, 4)
-
- def test_auto_number_garbage(self):
- with self.assertRaisesRegex(TypeError, r'invalid Flag value: .not an int.'):
- class Color(Flag):
- _order_ = 'red blue'
- red = 'not an int'
- blue = auto()
-
- def test_auto_w_pending(self):
- class Required(Flag):
- _order_ = 'TO_S FROM_S'
- NONE = 0
- TO_S = auto()
- FROM_S = auto()
- BOTH = TO_S | FROM_S
- self.assertEqual(Required.TO_S.value, 1)
- self.assertEqual(Required.FROM_S.value, 2)
- self.assertEqual(Required.BOTH.value, 3)
-
- def test_duplicate_auto(self):
- class Dupes(Enum):
- _order_ = 'first second third'
- first = primero = auto()
- second = auto()
- third = auto()
- self.assertEqual([Dupes.first, Dupes.second, Dupes.third], list(Dupes))
-
- def test_bizarre(self):
- with self.assertRaisesRegex(TypeError, r"invalid Flag 'Bizarre' -- missing values: 1, 2"):
- class Bizarre(Flag):
- b = 3
- c = 4
- d = 6
-
- def test_multiple_mixin(self):
- class AllMixin(object):
- @classproperty
- def ALL(cls):
- members = list(cls)
- all_value = None
- if members:
- all_value = members[0]
- for member in members[1:]:
- all_value |= member
- cls.ALL = all_value
- return all_value
- class StrMixin(object):
- def __str__(self):
- return self._name_.lower()
- class Color(AllMixin, Flag):
- _order_ = 'RED GREEN BLUE'
- RED = auto()
- GREEN = auto()
- BLUE = auto()
- self.assertEqual(Color.RED.value, 1)
- self.assertEqual(Color.GREEN.value, 2)
- self.assertEqual(Color.BLUE.value, 4)
- self.assertEqual(Color.ALL.value, 7)
- self.assertEqual(str(Color.BLUE), 'Color.BLUE')
- class Color(AllMixin, StrMixin, Flag):
- _order_ = 'RED GREEN BLUE'
- RED = auto()
- GREEN = auto()
- BLUE = auto()
- self.assertEqual(Color.RED.value, 1)
- self.assertEqual(Color.GREEN.value, 2)
- self.assertEqual(Color.BLUE.value, 4)
- self.assertEqual(Color.ALL.value, 7)
- self.assertEqual(str(Color.BLUE), 'blue')
- class Color(StrMixin, AllMixin, Flag):
- _order_ = 'RED GREEN BLUE'
- RED = auto()
- GREEN = auto()
- BLUE = auto()
- self.assertEqual(Color.RED.value, 1)
- self.assertEqual(Color.GREEN.value, 2)
- self.assertEqual(Color.BLUE.value, 4)
- self.assertEqual(Color.ALL.value, 7)
- self.assertEqual(str(Color.BLUE), 'blue')
-
- @unittest.skipUnless(threading, 'Threading required for this test.')
- def test_unique_composite(self):
- # override __eq__ to be identity only
- class TestFlag(Flag):
- _order_ = 'one two three four five six seven eight'
- one = auto()
- two = auto()
- three = auto()
- four = auto()
- five = auto()
- six = auto()
- seven = auto()
- eight = auto()
- def __eq__(self, other):
- return self is other
- def __hash__(self):
- return hash(self._value_)
- # have multiple threads competing to complete the composite members
- seen = set()
- failed = [False]
- def cycle_enum():
- # nonlocal failed
- try:
- for i in range(256):
- seen.add(TestFlag(i))
- except Exception:
- failed[0] = True
- threads = [
- threading.Thread(target=cycle_enum)
- for _ in range(8)
- ]
- for t in threads:
- t.start()
- for t in threads:
- t.join()
- # check that only 248 members were created (8 were created originally)
- self.assertFalse(
- failed[0],
- 'at least one thread failed while creating composite members')
- self.assertEqual(256, len(seen), 'too many composite members created')
-
- def test_init_with_autovalue_and_generate_next_value(self):
- class Color(Flag):
- _init_ = 'value code'
- def _generate_next_value_(name, start, count, last_values, *args, **kwds):
- if not count:
- return ((1, start)[start is not None], ) + args
- error = False
- for last_value in reversed(last_values):
- try:
- high_bit = aenum._high_bit(last_value)
- break
- except Exception:
- error = True
- break
- if error:
- raise TypeError('Invalid Flag value: %r' % (last_value, ))
- return (2 ** (high_bit+1), ) + args
- # TODO: actually test _create_pseudo_member
- @classmethod
- def _create_pseudo_member_(cls, value):
- members = list(cls._iter_member_(value))
- pseudo_member = super(Color, cls)._create_pseudo_member_(value)
- pseudo_member.code = ';'.join(m.code for m in members)
- return pseudo_member
- AllReset = '0' # ESC [ 0 m # reset all (colors and brightness)
- Bright = '1' # ESC [ 1 m # bright
- Dim = '2' # ESC [ 2 m # dim (looks same as normal brightness)
- Underline = '4'
- Normal = '22' # ESC [ 22 m # normal brightness
- # if we got here, we're good
-
- def test_autovalue_and_generate_next_value(self):
- class Color(str, Flag):
- _order_ = 'FG_Black FG_Red FG_Green FG_Blue BG_Yellow BG_Magenta BG_Cyan BG_White'
- def __new__(cls, value, code):
- str_value = '\x1b[%sm' % code
- obj = str.__new__(cls, str_value)
- obj._value_ = value
- obj.code = code
- return obj
- @staticmethod
- def _generate_next_value_(name, start, count, values, *args, **kwds):
- return (2 ** count, ) + args
- # TODO: actually test _create_pseudo_member
- @classmethod
- def _create_pseudo_member_(cls, value):
- # calculate the code
- members = list(cls._iter_member_(value))
- code = ';'.join(m.code for m in members)
- pseudo_member = super(Color, cls)._create_pseudo_member_(value, code)
- return pseudo_member
- #
- # # FOREGROUND - 30s BACKGROUND - 40s:
- FG_Black = '30' # ESC [ 30 m # black
- FG_Red = '31' # ESC [ 31 m # red
- FG_Green = '32' # ESC [ 32 m # green
- FG_Blue = '34' # ESC [ 34 m # blue
- #
- BG_Yellow = '43' # ESC [ 33 m # yellow
- BG_Magenta = '45' # ESC [ 35 m # magenta
- BG_Cyan = '46' # ESC [ 36 m # cyan
- BG_White = '47' # ESC [ 37 m # white
- # if we got here, we're good
-
- def test_subclass(self):
- class Color(str, Flag):
- _order_ = 'FG_Black FG_Red FG_Green FG_Blue BG_Yellow BG_Magenta BG_Cyan BG_White'
- def __new__(cls, value, code):
- str_value = '\x1b[%sm' % code
- obj = str.__new__(cls, str_value)
- obj._value_ = value
- obj.code = code
- return obj
- @staticmethod
- def _generate_next_value_(name, start, count, values, *args, **kwds):
- return (2 ** count, ) + args
- @classmethod
- def _create_pseudo_member_(cls, value):
- # calculate the code
- members = list(cls._iter_member_(value))
- code = ';'.join(m.code for m in members)
- pseudo_member = super(Color, cls)._create_pseudo_member_(value, code)
- return pseudo_member
- #
- # # FOREGROUND - 30s BACKGROUND - 40s:
- FG_Black = '30' # ESC [ 30 m # black
- FG_Red = '31' # ESC [ 31 m # red
- FG_Green = '32' # ESC [ 32 m # green
- FG_Blue = '34' # ESC [ 34 m # blue
- #
- BG_Yellow = '43' # ESC [ 33 m # yellow
- BG_Magenta = '45' # ESC [ 35 m # magenta
- BG_Cyan = '46' # ESC [ 36 m # cyan
- BG_White = '47' # ESC [ 37 m # white
- self.assertTrue(isinstance(Color.FG_Black, Color))
- self.assertTrue(isinstance(Color.FG_Black, str))
- self.assertEqual(Color.FG_Black, '\x1b[30m')
- self.assertEqual(Color.FG_Black.code, '30')
-
- def test_sub_subclass_1(self):
- class StrFlag(str, Flag):
- def __new__(cls, value, code):
- str_value = '\x1b[%sm' % code
- obj = str.__new__(cls, str_value)
- obj._value_ = value
- obj.code = code
- return obj
- @classmethod
- def _create_pseudo_member_(cls, value):
- # calculate the code
- members = list(cls._iter_member_(value))
- code = ';'.join(m.code for m in members)
- pseudo_member = super(Color, cls)._create_pseudo_member_(value, code)
- return pseudo_member
- class Color(StrFlag):
- _order_ = 'FG_Black FG_Red FG_Green FG_Blue BG_Yellow BG_Magenta BG_Cyan BG_White'
- # # FOREGROUND - 30s BACKGROUND - 40s:
- FG_Black = '30' # ESC [ 30 m # black
- FG_Red = '31' # ESC [ 31 m # red
- FG_Green = '32' # ESC [ 32 m # green
- FG_Blue = '34' # ESC [ 34 m # blue
- #
- BG_Yellow = '43' # ESC [ 33 m # yellow
- BG_Magenta = '45' # ESC [ 35 m # magenta
- BG_Cyan = '46' # ESC [ 36 m # cyan
- BG_White = '47' # ESC [ 37 m # white
- self.assertTrue(isinstance(Color.FG_Black, Color))
- self.assertTrue(isinstance(Color.FG_Black, str))
- self.assertEqual(Color.FG_Black, '\x1b[30m')
- self.assertEqual(Color.FG_Black.code, '30')
-
- def test_sub_subclass_2(self):
- class StrFlag(str, Flag):
- @staticmethod
- def _generate_next_value_(name, start, count, values, *args, **kwds):
- return (2 ** count, ) + args
- @classmethod
- def _create_pseudo_member_(cls, value):
- # calculate the code
- members = list(cls._iter_member_(value))
- code = ';'.join(m.code for m in members)
- pseudo_member = super(Color, cls)._create_pseudo_member_(value, code)
- return pseudo_member
- #
- class Color(StrFlag):
- _order_ = 'FG_Black FG_Red FG_Green FG_Blue BG_Yellow BG_Magenta BG_Cyan BG_White'
- def __new__(cls, value, code):
- str_value = '\x1b[%sm' % code
- obj = str.__new__(cls, str_value)
- obj._value_ = value
- obj.code = code
- return obj
- # # FOREGROUND - 30s BACKGROUND - 40s:
- FG_Black = '30' # ESC [ 30 m # black
- FG_Red = '31' # ESC [ 31 m # red
- FG_Green = '32' # ESC [ 32 m # green
- FG_Blue = '34' # ESC [ 34 m # blue
- #
- BG_Yellow = '43' # ESC [ 33 m # yellow
- BG_Magenta = '45' # ESC [ 35 m # magenta
- BG_Cyan = '46' # ESC [ 36 m # cyan
- BG_White = '47' # ESC [ 37 m # white
- self.assertTrue(isinstance(Color.FG_Black, Color))
- self.assertTrue(isinstance(Color.FG_Black, str))
- self.assertEqual(Color.FG_Black, '\x1b[30m')
- self.assertEqual(Color.FG_Black.code, '30')
-
- def test_sub_subclass_3(self):
- class StrFlag(str, Flag):
- def __new__(cls, value, code):
- str_value = '\x1b[%sm' % code
- obj = str.__new__(cls, str_value)
- obj._value_ = value
- obj.code = code
- return obj
- @classmethod
- def _create_pseudo_member_(cls, value):
- # calculate the code
- members = list(cls._iter_member_(value))
- code = ';'.join(m.code for m in members)
- pseudo_member = super(Color, cls)._create_pseudo_member_(value, code)
- return pseudo_member
- #
- class Color(StrFlag):
- _order_ = 'FG_Black FG_Red FG_Green FG_Blue BG_Yellow BG_Magenta BG_Cyan BG_White'
- # # FOREGROUND - 30s BACKGROUND - 40s:
- FG_Black = '30' # ESC [ 30 m # black
- FG_Red = '31' # ESC [ 31 m # red
- FG_Green = '32' # ESC [ 32 m # green
- FG_Blue = '34' # ESC [ 34 m # blue
- #
- BG_Yellow = '43' # ESC [ 33 m # yellow
- BG_Magenta = '45' # ESC [ 35 m # magenta
- BG_Cyan = '46' # ESC [ 36 m # cyan
- BG_White = '47' # ESC [ 37 m # white
- self.assertTrue(isinstance(Color.FG_Black, Color))
- self.assertTrue(isinstance(Color.FG_Black, str))
- self.assertEqual(Color.FG_Black, '\x1b[30m')
- self.assertEqual(Color.FG_Black.code, '30')
-
- def test_sub_subclass_4(self):
- class StrFlag(str, Flag):
- def __new__(cls, value, code):
- str_value = '\x1b[%sm' % code
- obj = str.__new__(cls, str_value)
- obj._value_ = value
- obj.code = code
- return obj
- @classmethod
- def _create_pseudo_member_values_(cls, members, *values):
- code = ';'.join(m.code for m in members)
- return values + (code, )
- #
- class Color(StrFlag):
- _order_ = 'FG_Black FG_Red FG_Green FG_Blue BG_Yellow BG_Magenta BG_Cyan BG_White'
- # # FOREGROUND - 30s BACKGROUND - 40s:
- FG_Black = '30' # ESC [ 30 m # black
- FG_Red = '31' # ESC [ 31 m # red
- FG_Green = '32' # ESC [ 32 m # green
- FG_Blue = '34' # ESC [ 34 m # blue
- #
- BG_Yellow = '43' # ESC [ 33 m # yellow
- BG_Magenta = '45' # ESC [ 35 m # magenta
- BG_Cyan = '46' # ESC [ 36 m # cyan
- BG_White = '47' # ESC [ 37 m # white
- #
- def __repr__(self):
- return '<%s.%s>' % (self.__class__.__name__, self._name_)
- self.assertTrue(isinstance(Color.FG_Black, Color))
- self.assertTrue(isinstance(Color.FG_Black, str))
- self.assertEqual(Color.FG_Black, '\x1b[30m')
- self.assertEqual(Color.FG_Black.code, '30')
- colors = Color.BG_Magenta | Color.FG_Black
- self.assertTrue(isinstance(colors, Color))
- self.assertTrue(isinstance(colors, str))
- self.assertEqual(colors, '\x1b[30;45m')
- self.assertEqual(colors.code, '30;45')
- self.assertEqual(repr(colors), '<Color.FG_Black|BG_Magenta>')
-
- def test_sub_subclass_with_new_new(self):
- class StrFlag(str, Flag):
- def __new__(cls, value, code):
- str_value = '\x1b[%sm' % code
- obj = str.__new__(cls, str_value)
- obj._value_ = value
- obj.code = code
- return obj
- @classmethod
- def _create_pseudo_member_(cls, value):
- # calculate the code
- members = list(cls._iter_member_(value))
- code = ';'.join(m.code for m in members)
- pseudo_member = super(StrFlag, cls)._create_pseudo_member_(value, code)
- return pseudo_member
- #
- class Color(StrFlag):
- _order_ = 'FG_Black FG_Red FG_Green FG_Blue BG_Yellow BG_Magenta BG_Cyan BG_White'
- def __new__(cls, value, string, abbr):
- str_value = (abbr or '').title()
- obj = str.__new__(cls, str_value)
- obj._value_ = value
- obj.code = string
- obj.abbr = abbr
- return obj
- # # FOREGROUND - 30s BACKGROUND - 40s:
- FG_Black = '30', 'blk' # ESC [ 30 m # black
- FG_Red = '31', 'red' # ESC [ 31 m # red
- FG_Green = '32', 'grn' # ESC [ 32 m # green
- FG_Blue = '34', 'blu' # ESC [ 34 m # blue
- #
- BG_Yellow = '43', 'ylw' # ESC [ 33 m # yellow
- BG_Magenta = '45', 'mag' # ESC [ 35 m # magenta
- BG_Cyan = '46', 'cyn' # ESC [ 36 m # cyan
- BG_White = '47', 'wht' # ESC [ 37 m # white
- #
- def __repr__(self):
- if self._name_ is not None:
- return '<%s.%s>' % (self.__class__.__name__, self._name_)
- else:
- return '<%s: %s>' % (self.__class__.__name__, '|'.join([m.name for m in self]))
- self.assertTrue(isinstance(Color.FG_Black, Color))
- self.assertTrue(isinstance(Color.FG_Black, str))
- self.assertEqual(Color.FG_Black, 'Blk', str.__repr__(Color.FG_Black))
- self.assertEqual(Color.FG_Black.abbr, 'blk')
-
- def test_subclass_with_default_new(self):
- class MyFlag(str, Flag):
- _order_ = 'this these theother'
- this = 'that'
- these = 'those'
- theother = 'thingimibobs'
- self.assertEqual(MyFlag.this, 'that')
- self.assertEqual(MyFlag.this.value, 1)
- self.assertEqual(MyFlag.these, 'those')
- self.assertEqual(MyFlag.these.value, 2)
- self.assertEqual(MyFlag.theother, 'thingimibobs')
- self.assertEqual(MyFlag.theother.value, 4)
-
- def test_subclass_a_bunch(self):
- class Color(str, Flag):
- _order_ = 'FG_Black FG_Red FG_Green FG_Blue BG_Yellow BG_Magenta BG_Cyan BG_White'
- def __new__(cls, value, code):
- str_value = '\x1b[%sm' % code
- obj = str.__new__(cls, str_value)
- obj._value_ = value
- obj.code = code
- return obj
- @staticmethod
- def _generate_next_value_(name, start, count, values, *args, **kwds):
- return (2 ** count, ) + args
- @classmethod
- def _create_pseudo_member_(cls, value):
- # calculate the code
- members = list(cls._iter_member_(value))
- code = ';'.join(m.code for m in members)
- pseudo_member = super(Color, cls)._create_pseudo_member_(value, code)
- return pseudo_member
- #
- # # FOREGROUND - 30s BACKGROUND - 40s:
- FG_Black = '30' # ESC [ 30 m # black
- FG_Red = '31' # ESC [ 31 m # red
- FG_Green = '32' # ESC [ 32 m # green
- FG_Blue = '34' # ESC [ 34 m # blue
- #
- BG_Yellow = '43' # ESC [ 33 m # yellow
- BG_Magenta = '45' # ESC [ 35 m # magenta
- BG_Cyan = '46' # ESC [ 36 m # cyan
- BG_White = '47' # ESC [ 37 m # white
- #
- def __repr__(self):
- if self._name_ is not None:
- return '<%s.%s>' % (self.__class__.__name__, self._name_)
- else:
- return '<%s: %s>' % (self.__class__.__name__, '|'.join([m.name for m in self]))
- #
- Purple = Color.BG_Magenta | Color.FG_Blue
- self.assertTrue(isinstance(Purple, Color))
- self.assertTrue(isinstance(Purple, str))
- self.assertIs(Purple, Color.BG_Magenta | Color.FG_Blue)
- self.assertEqual(Purple, '\x1b[34;45m')
- self.assertEqual(Purple.code, '34;45')
- self.assertEqual(Purple.name, 'FG_Blue|BG_Magenta')
-
- def test_init_subclass(self):
- class MyEnum(Flag):
- def __init_subclass__(cls, **kwds):
- super(MyEnum, cls).__init_subclass__(**kwds)
- self.assertFalse(cls.__dict__.get('_test', False))
- cls._test1 = 'MyEnum'
- #
- class TheirEnum(MyEnum):
- def __init_subclass__(cls, **kwds):
- super(TheirEnum, cls).__init_subclass__(**kwds)
- cls._test2 = 'TheirEnum'
- class WhoseEnum(TheirEnum):
- def __init_subclass__(cls, **kwds):
- pass
- class NoEnum(WhoseEnum):
- ONE = 1
- self.assertEqual(TheirEnum.__dict__['_test1'], 'MyEnum')
- self.assertEqual(WhoseEnum.__dict__['_test1'], 'MyEnum')
- self.assertEqual(WhoseEnum.__dict__['_test2'], 'TheirEnum')
- self.assertFalse(NoEnum.__dict__.get('_test1', False))
- self.assertFalse(NoEnum.__dict__.get('_test2', False))
- #
- class OurEnum(MyEnum):
- def __init_subclass__(cls, **kwds):
- cls._test2 = 'OurEnum'
- class WhereEnum(OurEnum):
- def __init_subclass__(cls, **kwds):
- pass
- class NeverEnum(WhereEnum):
- ONE = 1
- self.assertEqual(OurEnum.__dict__['_test1'], 'MyEnum')
- self.assertFalse(WhereEnum.__dict__.get('_test1', False))
- self.assertEqual(WhereEnum.__dict__['_test2'], 'OurEnum')
- self.assertFalse(NeverEnum.__dict__.get('_test1', False))
- self.assertFalse(NeverEnum.__dict__.get('_test2', False))
-
- def test_int_long_conversion(self):
- class Perm(Flag):
- EXEC = 1 << 0
- WRITE = 1 << 1
- READ = 1 << 2
- MSB32 = 1 << 31
- MSB64 = 1 << 63
-
- # 32-bit system test
- self.assertEqual(Perm.MSB32, Perm(0x80000000))
- self.assertEqual(Perm.WRITE|Perm.MSB32, Perm(0x80000002))
-
- # 64-bit system test
- self.assertEqual(Perm.MSB64, Perm(0x8000000000000000))
- self.assertEqual(Perm.MSB64|Perm.WRITE, Perm(0x8000000000000002))
-
-
-class TestIntFlag(TestCase):
- """Tests of the IntFlags."""
-
- def setUp(self):
- #
- class Perm(IntFlag):
- _order_ = 'R W X'
- R = 1 << 2
- W = 1 << 1
- X = 1 << 0
- #
- class Color(IntFlag):
- BLACK = 0
- RED = 1
- GREEN = 2
- BLUE = 4
- PURPLE = RED|BLUE
- #
- class Open(IntFlag):
- "not a good flag candidate"
- RO = 0
- WO = 1
- RW = 2
- AC = 3
- CE = 1<<19
- #
- self.Perm = Perm
- self.Color = Color
- self.Open = Open
-
- def test_set_name(self):
- class Descriptor(object):
- name = None
- def __get__(self, instance, owner_class=None):
- if instance is None:
- return self
- else:
- return instance.__dict__[self.name]
- def __set__(self, instance, value):
- instance.__dict__[self.name] = value
- def __set_name__(self, owner, name):
- self.name = name
- #
- class AnEnum(Enum):
- ONE = 1
- two = Descriptor()
- #
- self.assertEqual(list(AnEnum), [AnEnum.ONE])
- self.assertEqual(AnEnum.two.name, 'two')
- AnEnum.ONE.two = 'three'
- self.assertEqual(AnEnum.ONE.two, 'three')
- self.assertEqual(AnEnum.ONE.__dict__['two'], 'three')
-
- def test_private_names(self):
- class Private(Enum):
- __corporal = 'Radar'
- __major_ = 'Hoolihan'
- self.assertEqual(len(Private), 0)
- self.assertEqual(Private._Private__corporal, 'Radar')
- self.assertFalse(isinstance(Private._Private__corporal, Enum))
- self.assertEqual(Private._Private__major_, 'Hoolihan')
- self.assertFalse(isinstance(Private._Private__major_, Enum))
-
- def test_membership(self):
- Color = self.Color
- Open = self.Open
- self.assertRaises(TypeError, lambda: 'GREEN' in Color)
- self.assertRaises(TypeError, lambda: 'RW' in Open)
- self.assertTrue(Color.GREEN in Color)
- self.assertTrue(Open.RW in Open)
- self.assertFalse(Color.GREEN in Open)
- self.assertFalse(Open.RW in Color)
- self.assertRaises(TypeError, lambda: 2 in Color)
- self.assertRaises(TypeError, lambda: 2 in Open)
-
- def test_member_contains(self):
- Color = self.Color
- self.assertRaises(TypeError, lambda: 'test' in Color.RED)
- self.assertRaises(TypeError, lambda: 1 in Color.RED)
- self.assertTrue(Color.RED in Color.RED)
- self.assertTrue(Color.RED in Color.PURPLE)
-
- def test_name_lookup(self):
- Color = self.Color
- self.assertTrue(Color.RED is Color['RED'])
- self.assertTrue(Color.RED|Color.GREEN is Color['RED|GREEN'])
- self.assertTrue(Color.PURPLE is Color['RED|BLUE'])
-
- def test_type(self):
- Perm = self.Perm
- Open = self.Open
- for f in Perm:
- self.assertTrue(isinstance(f, Perm))
- self.assertEqual(f, f.value)
- self.assertTrue(isinstance(Perm.W | Perm.X, Perm))
- self.assertEqual(Perm.W | Perm.X, 3)
- for f in Open:
- self.assertTrue(isinstance(f, Open))
- self.assertEqual(f, f.value)
- self.assertTrue(isinstance(Open.WO | Open.RW, Open))
- self.assertEqual(Open.WO | Open.RW, 3)
-
-
- def test_str(self):
- Perm = self.Perm
- self.assertEqual(str(Perm.R), '4')
- self.assertEqual(str(Perm.W), '2')
- self.assertEqual(str(Perm.X), '1')
- self.assertEqual(str(Perm.R | Perm.W), '6')
- self.assertEqual(str(Perm.R | Perm.W | Perm.X), '7')
- self.assertEqual(str(Perm(0)), '0')
- self.assertEqual(str(~Perm.R), '3')
- self.assertEqual(str(~Perm.W), '5')
- self.assertEqual(str(~Perm.X), '6')
- self.assertEqual(str(~(Perm.R | Perm.W)), '1')
- self.assertEqual(str(~(Perm.R | Perm.W | Perm.X)), '0')
- self.assertEqual(str(Perm(~0)), '7')
-
- Open = self.Open
- self.assertEqual(str(Open.RO), '0')
- self.assertEqual(str(Open.WO), '1')
- self.assertEqual(str(Open.AC), '3')
- self.assertEqual(str(Open.RO | Open.CE), '524288')
- self.assertEqual(str(Open.WO | Open.CE), '524289')
- self.assertEqual(str(~Open.RO), '524291')
- self.assertEqual(str(~Open.WO), '524290')
- self.assertEqual(str(~Open.AC), '524288')
- self.assertEqual(str(~(Open.RO | Open.CE)), '3')
- self.assertEqual(str(~(Open.WO | Open.CE)), '2')
-
- def test_repr_strict(self):
- class Perm(IntFlag):
- _order_ = 'R W X'
- R = 1 << 2
- W = 1 << 1
- X = 1 << 0
- Perm._boundary_ = aenum.STRICT
- self.assertEqual(repr(Perm.R), '<Perm.R: 4>')
- self.assertEqual(repr(Perm.W), '<Perm.W: 2>')
- self.assertEqual(repr(Perm.X), '<Perm.X: 1>')
- self.assertEqual(repr(Perm.R | Perm.W), '<Perm.R|W: 6>')
- self.assertEqual(repr(Perm.R | Perm.W | Perm.X), '<Perm.R|W|X: 7>')
- self.assertEqual(repr(Perm(0)), '<Perm: 0>')
- self.assertEqual(repr(~Perm.R), '<Perm.W|X: 3>')
- self.assertEqual(repr(~Perm.W), '<Perm.R|X: 5>')
- self.assertEqual(repr(~Perm.X), '<Perm.R|W: 6>')
- self.assertEqual(repr(~(Perm.R | Perm.W)), '<Perm.X: 1>')
- self.assertEqual(repr(~(Perm.R | Perm.W | Perm.X)), '<Perm: 0>')
- #
- with self.assertRaisesRegex(ValueError, r'invalid value: 12'):
- repr(Perm.R | 8)
- with self.assertRaisesRegex(ValueError, r'invalid value: 12'):
- repr(~(Perm.R | 8))
- with self.assertRaisesRegex(ValueError, r'invalid value: -9'):
- repr(Perm(~8))
-
- def test_repr_conform(self):
- class Perm(IntFlag):
- _order_ = 'R W X'
- R = 1 << 2
- W = 1 << 1
- X = 1 << 0
- Perm._boundary_ = aenum.CONFORM
- self.assertEqual(repr(Perm.R), '<Perm.R: 4>')
- self.assertEqual(repr(Perm.W), '<Perm.W: 2>')
- self.assertEqual(repr(Perm.X), '<Perm.X: 1>')
- self.assertEqual(repr(Perm.R | Perm.W), '<Perm.R|W: 6>')
- self.assertEqual(repr(Perm.R | Perm.W | Perm.X), '<Perm.R|W|X: 7>')
- self.assertEqual(repr(Perm(0)), '<Perm: 0>')
- self.assertEqual(repr(~Perm.R), '<Perm.W|X: 3>')
- self.assertEqual(repr(~Perm.W), '<Perm.R|X: 5>')
- self.assertEqual(repr(~Perm.X), '<Perm.R|W: 6>')
- self.assertEqual(repr(~(Perm.R | Perm.W)), '<Perm.X: 1>')
- self.assertEqual(repr(~(Perm.R | Perm.W | Perm.X)), '<Perm: 0>')
- self.assertEqual(repr(Perm.R | 8), '<Perm.R: 4>')
- self.assertEqual(repr(Perm(8)), '<Perm: 0>')
- self.assertEqual(repr(~(Perm.R | 8)), '<Perm.W|X: 3>')
- self.assertEqual(repr(Perm(~8)), '<Perm.R|W|X: 7>')
-
- def test_repr_eject(self):
- class Perm(IntFlag):
- _order_ = 'R W X'
- _boundary_ = EJECT
- R = 1 << 2
- W = 1 << 1
- X = 1 << 0
- self.assertEqual(repr(Perm.R), '<Perm.R: 4>')
- self.assertEqual(repr(Perm.W), '<Perm.W: 2>')
- self.assertEqual(repr(Perm.X), '<Perm.X: 1>')
- self.assertEqual(repr(Perm.R | Perm.W), '<Perm.R|W: 6>')
- self.assertEqual(repr(Perm.R | Perm.W | Perm.X), '<Perm.R|W|X: 7>')
- self.assertEqual(repr(Perm(0)), '<Perm: 0>')
- self.assertEqual(repr(~Perm.R), '<Perm.W|X: 3>')
- self.assertEqual(repr(~Perm.W), '<Perm.R|X: 5>')
- self.assertEqual(repr(~Perm.X), '<Perm.R|W: 6>')
- self.assertEqual(repr(~(Perm.R | Perm.W)), '<Perm.X: 1>')
- self.assertEqual(repr(~(Perm.R | Perm.W | Perm.X)), '<Perm: 0>')
- self.assertEqual(repr(Perm.R | 8), '12')
- self.assertEqual(repr(Perm(8)), '8')
- self.assertEqual(repr(~(Perm.R | 8)), '-13')
- self.assertEqual(repr(Perm(~8)), '-9')
-
- def test_repr_open(self):
- class Open(IntFlag):
- "not a good flag candidate"
- RO = 0
- WO = 1
- RW = 2
- AC = 3
- CE = 1<<19
- Open._boundary_ = aenum.STRICT
- self.assertEqual(repr(Open.RO), '<Open.RO: 0>')
- self.assertEqual(repr(Open.WO), '<Open.WO: 1>')
- self.assertEqual(repr(Open.AC), '<Open.AC: 3>')
- self.assertEqual(repr(Open.RO | Open.CE), '<Open.CE: 524288>')
- self.assertEqual(repr(Open.WO | Open.CE), '<Open.WO|CE: 524289>')
- self.assertEqual(repr(~Open.RO), '<Open.WO|RW|CE: 524291>')
- self.assertEqual(repr(~Open.WO), '<Open.RW|CE: 524290>')
- self.assertEqual(repr(~Open.AC), '<Open.CE: 524288>')
- self.assertEqual(repr(~(Open.RO | Open.CE)), '<Open.AC: 3>')
- self.assertEqual(repr(~(Open.WO | Open.CE)), '<Open.RW: 2>')
- with self.assertRaisesRegex(ValueError, r'invalid value: -5'):
- repr(Open(~4))
- with self.assertRaisesRegex(ValueError, r'invalid value: 4'):
- repr(Open(4))
- #
- class Open(IntFlag):
- "not a good flag candidate"
- RO = 0
- WO = 1
- RW = 2
- AC = 3
- CE = 1<<19
- Open._boundary_ = aenum.CONFORM
- self.assertEqual(repr(Open.RO), '<Open.RO: 0>')
- self.assertEqual(repr(Open.WO), '<Open.WO: 1>')
- self.assertEqual(repr(Open.AC), '<Open.AC: 3>')
- self.assertEqual(repr(Open.RO | Open.CE), '<Open.CE: 524288>')
- self.assertEqual(repr(Open.WO | Open.CE), '<Open.WO|CE: 524289>')
- self.assertEqual(repr(~Open.RO), '<Open.WO|RW|CE: 524291>')
- self.assertEqual(repr(~Open.WO), '<Open.RW|CE: 524290>')
- self.assertEqual(repr(~Open.AC), '<Open.CE: 524288>')
- self.assertEqual(repr(~(Open.RO | Open.CE)), '<Open.AC: 3>')
- self.assertEqual(repr(~(Open.WO | Open.CE)), '<Open.RW: 2>')
- self.assertEqual(repr(Open(~4)), '<Open.WO|RW|CE: 524291>')
- self.assertEqual(repr(Open(4)), '<Open.RO: 0>')
- #
- class Open(IntFlag):
- "not a good flag candidate"
- RO = 0
- WO = 1
- RW = 2
- AC = 3
- CE = 1<<19
- Open._boundary_ = aenum.EJECT
- self.assertEqual(repr(Open.RO), '<Open.RO: 0>')
- self.assertEqual(repr(Open.WO), '<Open.WO: 1>')
- self.assertEqual(repr(Open.AC), '<Open.AC: 3>')
- self.assertEqual(repr(Open.RO | Open.CE), '<Open.CE: 524288>')
- self.assertEqual(repr(Open.WO | Open.CE), '<Open.WO|CE: 524289>')
- self.assertEqual(repr(~Open.RO), '<Open.WO|RW|CE: 524291>')
- self.assertEqual(repr(~Open.WO), '<Open.RW|CE: 524290>')
- self.assertEqual(repr(~Open.AC), '<Open.CE: 524288>')
- self.assertEqual(repr(~(Open.RO | Open.CE)), '<Open.AC: 3>')
- self.assertEqual(repr(~(Open.WO | Open.CE)), '<Open.RW: 2>')
- self.assertEqual(repr(Open(~4)), '-5')
- self.assertEqual(repr(Open(4)), '4')
-
- def test_or(self):
- Perm = self.Perm
- for i in Perm:
- for j in Perm:
- self.assertEqual(i | j, i.value | j.value)
- self.assertEqual((i | j).value, i.value | j.value)
- self.assertIs(type(i | j), Perm)
- for j in range(8):
- self.assertEqual(i | j, i.value | j)
- self.assertEqual((i | j).value, i.value | j)
- self.assertIs(type(i | j), Perm)
- self.assertEqual(j | i, j | i.value)
- self.assertEqual((j | i).value, j | i.value)
- self.assertIs(type(j | i), Perm)
- for i in Perm:
- self.assertIs(i | i, i)
- self.assertIs(i | 0, i)
- self.assertIs(0 | i, i)
- Open = self.Open
- self.assertIs(Open.RO | Open.CE, Open.CE)
-
- def test_and(self):
- Perm = self.Perm
- RW = Perm.R | Perm.W
- RX = Perm.R | Perm.X
- WX = Perm.W | Perm.X
- RWX = Perm.R | Perm.W | Perm.X
- values = list(Perm) + [RW, RX, WX, RWX, Perm(0)]
- for i in values:
- for j in values:
- self.assertEqual(i & j, i.value & j.value, 'i is %r, j is %r' % (i, j))
- self.assertEqual((i & j).value, i.value & j.value, 'i is %r, j is %r' % (i, j))
- self.assertIs(type(i & j), Perm, 'i is %r, j is %r' % (i, j))
- for j in range(8):
- self.assertEqual(i & j, i.value & j)
- self.assertEqual((i & j).value, i.value & j)
- self.assertIs(type(i & j), Perm)
- self.assertEqual(j & i, j & i.value)
- self.assertEqual((j & i).value, j & i.value)
- self.assertIs(type(j & i), Perm)
- for i in Perm:
- self.assertIs(i & i, i)
- self.assertIs(i & 7, i)
- self.assertIs(7 & i, i)
- Open = self.Open
- self.assertIs(Open.RO & Open.CE, Open.RO)
-
- def test_xor(self):
- Perm = self.Perm
- for i in Perm:
- for j in Perm:
- self.assertEqual(i ^ j, i.value ^ j.value)
- self.assertEqual((i ^ j).value, i.value ^ j.value)
- self.assertIs(type(i ^ j), Perm)
- for j in range(8):
- self.assertEqual(i ^ j, i.value ^ j)
- self.assertEqual((i ^ j).value, i.value ^ j)
- self.assertIs(type(i ^ j), Perm)
- self.assertEqual(j ^ i, j ^ i.value)
- self.assertEqual((j ^ i).value, j ^ i.value)
- self.assertIs(type(j ^ i), Perm)
- for i in Perm:
- self.assertIs(i ^ 0, i)
- self.assertIs(0 ^ i, i)
- Open = self.Open
- self.assertIs(Open.RO ^ Open.CE, Open.CE)
- self.assertIs(Open.CE ^ Open.CE, Open.RO)
-
- def test_invert(self):
- Perm = self.Perm
- RW = Perm.R | Perm.W
- RX = Perm.R | Perm.X
- WX = Perm.W | Perm.X
- RWX = Perm.R | Perm.W | Perm.X
- values = list(Perm) + [RW, RX, WX, RWX, Perm(0)]
- for i in values:
- self.assertEqual(~i, (~i).value)
- self.assertIs(type(~i), Perm)
- self.assertEqual(~~i, i)
- for i in Perm:
- self.assertIs(~~i, i)
- Open = self.Open
- self.assertIs(Open.WO & ~Open.WO, Open.RO)
- self.assertIs((Open.WO|Open.CE) & ~Open.WO, Open.CE)
-
- def test_iter(self):
- Perm = self.Perm
- NoPerm = Perm.R ^ Perm.R
- RWX = Perm.R | Perm.W | Perm.X
- self.assertEqual(list(NoPerm), [])
- self.assertEqual(list(Perm.R), [Perm.R])
- self.assertEqual(list(RWX), [Perm.R, Perm.W, Perm.X])
-
- def test_programatic_function_string(self):
- Perm = IntFlag('Perm', 'R W X')
- lst = list(Perm)
- self.assertEqual(len(lst), len(Perm))
- self.assertEqual(len(Perm), 3, Perm)
- self.assertEqual(lst, [Perm.R, Perm.W, Perm.X])
- for i, n in enumerate('R W X'.split()):
- v = 1<<i
- e = Perm(v)
- self.assertEqual(e.value, v)
- self.assertEqual(type(e.value), int)
- self.assertEqual(e, v)
- self.assertEqual(e.name, n)
- self.assertIn(e, Perm)
- self.assertIs(type(e), Perm)
-
- def test_programatic_function_string_with_start(self):
- Perm = IntFlag('Perm', 'R W X', start=8)
- lst = list(Perm)
- self.assertEqual(len(lst), len(Perm))
- self.assertEqual(len(Perm), 3, Perm)
- self.assertEqual(lst, [Perm.R, Perm.W, Perm.X])
- for i, n in enumerate('R W X'.split()):
- v = 8<<i
- e = Perm(v)
- self.assertEqual(e.value, v)
- self.assertEqual(type(e.value), int)
- self.assertEqual(e, v)
- self.assertEqual(e.name, n)
- self.assertIn(e, Perm)
- self.assertIs(type(e), Perm)
-
- def test_programatic_function_string_list(self):
- Perm = IntFlag('Perm', ['R', 'W', 'X'])
- lst = list(Perm)
- self.assertEqual(len(lst), len(Perm))
- self.assertEqual(len(Perm), 3, Perm)
- self.assertEqual(lst, [Perm.R, Perm.W, Perm.X])
- for i, n in enumerate('R W X'.split()):
- v = 1<<i
- e = Perm(v)
- self.assertEqual(e.value, v)
- self.assertEqual(type(e.value), int)
- self.assertEqual(e, v)
- self.assertEqual(e.name, n)
- self.assertIn(e, Perm)
- self.assertIs(type(e), Perm)
-
- def test_programatic_function_iterable(self):
- Perm = IntFlag('Perm', (('R', 2), ('W', 8), ('X', 32)))
- lst = list(Perm)
- self.assertEqual(len(lst), len(Perm))
- self.assertEqual(len(Perm), 3, Perm)
- self.assertEqual(lst, [Perm.R, Perm.W, Perm.X])
- for i, n in enumerate('R W X'.split()):
- v = 1<<(2*i+1)
- e = Perm(v)
- self.assertEqual(e.value, v)
- self.assertEqual(type(e.value), int)
- self.assertEqual(e, v)
- self.assertEqual(e.name, n)
- self.assertIn(e, Perm)
- self.assertIs(type(e), Perm)
-
- def test_programatic_function_from_dict(self):
- Perm = IntFlag('Perm', OrderedDict((('R', 2), ('W', 8), ('X', 32))))
- lst = list(Perm)
- self.assertEqual(len(lst), len(Perm))
- self.assertEqual(len(Perm), 3, Perm)
- self.assertEqual(lst, [Perm.R, Perm.W, Perm.X])
- for i, n in enumerate('R W X'.split()):
- v = 1<<(2*i+1)
- e = Perm(v)
- self.assertEqual(e.value, v)
- self.assertEqual(type(e.value), int)
- self.assertEqual(e, v)
- self.assertEqual(e.name, n)
- self.assertIn(e, Perm)
- self.assertIs(type(e), Perm)
-
- def test_containment(self):
- Perm = self.Perm
- R, W, X = Perm
- RW = R | W
- RX = R | X
- WX = W | X
- RWX = R | W | X
- self.assertTrue(R in RW)
- self.assertTrue(R in RX)
- self.assertTrue(R in RWX)
- self.assertTrue(W in RW)
- self.assertTrue(W in WX)
- self.assertTrue(W in RWX)
- self.assertTrue(X in RX)
- self.assertTrue(X in WX)
- self.assertTrue(X in RWX)
- self.assertFalse(R in WX)
- self.assertFalse(W in RX)
- self.assertFalse(X in RW)
-
- def test_bool(self):
- Perm = self.Perm
- for f in Perm:
- self.assertTrue(f)
- Open = self.Open
- for f in Open:
- self.assertEqual(bool(f.value), bool(f))
-
- def test_multiple_mixin(self):
- class AllMixin(object):
- @classproperty
- def ALL(cls):
- members = list(cls)
- all_value = None
- if members:
- all_value = members[0]
- for member in members[1:]:
- all_value |= member
- cls.ALL = all_value
- return all_value
- class StrMixin(object):
- def __str__(self):
- return self._name_.lower()
- class Color(AllMixin, IntFlag):
- _order_ = 'RED GREEN BLUE'
- RED = auto()
- GREEN = auto()
- BLUE = auto()
- self.assertEqual(Color.RED.value, 1)
- self.assertEqual(Color.GREEN.value, 2)
- self.assertEqual(Color.BLUE.value, 4)
- self.assertEqual(Color.ALL.value, 7)
- self.assertEqual(str(Color.BLUE), '4')
- class Color(AllMixin, StrMixin, IntFlag):
- _order_ = 'RED GREEN BLUE'
- __str__ = StrMixin.__str__
- RED = auto()
- GREEN = auto()
- BLUE = auto()
- self.assertEqual(Color.RED.value, 1)
- self.assertEqual(Color.GREEN.value, 2)
- self.assertEqual(Color.BLUE.value, 4)
- self.assertEqual(Color.ALL.value, 7)
- self.assertEqual(str(Color.BLUE), 'blue')
- class Color(StrMixin, AllMixin, IntFlag):
- _order_ = 'RED GREEN BLUE'
- __str__ = StrMixin.__str__
- RED = auto()
- GREEN = auto()
- BLUE = auto()
- self.assertEqual(Color.RED.value, 1)
- self.assertEqual(Color.GREEN.value, 2)
- self.assertEqual(Color.BLUE.value, 4)
- self.assertEqual(Color.ALL.value, 7)
- self.assertEqual(str(Color.BLUE), 'blue')
-
- @unittest.skipUnless(threading, 'Threading required for this test.')
- def test_unique_composite(self):
- # override __eq__ to be identity only
- class TestFlag(IntFlag):
- _order_ = 'one two three four five six seven eight'
- one = auto()
- two = auto()
- three = auto()
- four = auto()
- five = auto()
- six = auto()
- seven = auto()
- eight = auto()
- def __eq__(self, other):
- return self is other
- def __hash__(self):
- return hash(self._value_)
- # have multiple threads competing to complete the composite members
- seen = set()
- failed = [False]
- def cycle_enum():
- # nonlocal failed
- try:
- for i in range(256):
- seen.add(TestFlag(i))
- except Exception:
- failed[0] = True
- threads = [
- threading.Thread(target=cycle_enum)
- for _ in range(8)
- ]
- for t in threads:
- t.start()
- for t in threads:
- t.join()
- # check that only 248 members were created (8 were created originally)
- self.assertFalse(
- failed[0],
- 'at least one thread failed while creating composite members')
- self.assertEqual(256, len(seen), 'too many composite members created')
-
- def test_init_subclass(self):
- class MyEnum(IntEnum):
- def __init_subclass__(cls, **kwds):
- super(MyEnum, cls).__init_subclass__(**kwds)
- self.assertFalse(cls.__dict__.get('_test', False))
- cls._test1 = 'MyEnum'
- #
- class TheirEnum(MyEnum):
- def __init_subclass__(cls, **kwds):
- super(TheirEnum, cls).__init_subclass__(**kwds)
- cls._test2 = 'TheirEnum'
- class WhoseEnum(TheirEnum):
- def __init_subclass__(cls, **kwds):
- pass
- class NoEnum(WhoseEnum):
- ONE = 1
- self.assertEqual(TheirEnum.__dict__['_test1'], 'MyEnum')
- self.assertEqual(WhoseEnum.__dict__['_test1'], 'MyEnum')
- self.assertEqual(WhoseEnum.__dict__['_test2'], 'TheirEnum')
- self.assertFalse(NoEnum.__dict__.get('_test1', False))
- self.assertFalse(NoEnum.__dict__.get('_test2', False))
- #
- class OurEnum(MyEnum):
- def __init_subclass__(cls, **kwds):
- cls._test2 = 'OurEnum'
- class WhereEnum(OurEnum):
- def __init_subclass__(cls, **kwds):
- pass
- class NeverEnum(WhereEnum):
- ONE = 1
- self.assertEqual(OurEnum.__dict__['_test1'], 'MyEnum')
- self.assertFalse(WhereEnum.__dict__.get('_test1', False))
- self.assertEqual(WhereEnum.__dict__['_test2'], 'OurEnum')
- self.assertFalse(NeverEnum.__dict__.get('_test1', False))
- self.assertFalse(NeverEnum.__dict__.get('_test2', False))
-
-
-
-class TestEmptyAndNonLatinStrings(unittest.TestCase):
-
- def test_empty_string(self):
- with self.assertRaises(ValueError):
- empty_abc = Enum('empty_abc', ('', 'B', 'C'))
-
- def test_non_latin_character_string(self):
- greek_abc = Enum('greek_abc', ('\u03B1', 'B', 'C'))
- item = getattr(greek_abc, '\u03B1')
- self.assertEqual(item.value, 1)
-
- def test_non_latin_number_string(self):
- hebrew_123 = Enum('hebrew_123', ('\u05D0', '2', '3'))
- item = getattr(hebrew_123, '\u05D0')
- self.assertEqual(item.value, 1)
-
-
-class TestUnique(TestCase):
- """2.4 doesn't allow class decorators, use function syntax."""
-
- def test_unique_clean(self):
- class Clean(Enum):
- one = 1
- two = 'dos'
- tres = 4.0
- unique(Clean)
- class Cleaner(IntEnum):
- single = 1
- double = 2
- triple = 3
- unique(Cleaner)
-
- def test_unique_dirty(self):
- try:
- class Dirty(Enum):
- __order__ = 'one two'
- one = 1
- two = 'dos'
- tres = 1
- unique(Dirty)
- except ValueError:
- exc = sys.exc_info()[1]
- message = exc.args[0]
- self.assertTrue('tres -> one' in message)
-
- try:
- class Dirtier(IntEnum):
- __order__ = 'single triple'
- single = 1
- double = 1
- triple = 3
- turkey = 3
- unique(Dirtier)
- except ValueError:
- exc = sys.exc_info()[1]
- message = exc.args[0]
- self.assertTrue('double -> single' in message)
- self.assertTrue('turkey -> triple' in message)
-
- def test_unique_with_name(self):
- @unique
- class Silly(Enum):
- one = 1
- two = 'dos'
- name = 3
- @unique
- class Sillier(IntEnum):
- single = 1
- name = 2
- triple = 3
- value = 4
-
-
-class TestNamedTuple(TestCase):
-
- def test_explicit_indexing(self):
- class Person(NamedTuple):
- age = 0
- first = 1
- last = 2
- p1 = Person(17, 'John', 'Doe')
- p2 = Person(21, 'Jane', 'Doe')
- self.assertEqual(p1[0], 17)
- self.assertEqual(p1[1], 'John')
- self.assertEqual(p1[2], 'Doe')
- self.assertEqual(p2[0], 21)
- self.assertEqual(p2[1], 'Jane')
- self.assertEqual(p2[2], 'Doe')
- self.assertEqual(p1.age, 17)
- self.assertEqual(p1.first, 'John')
- self.assertEqual(p1.last, 'Doe')
- self.assertEqual(p2.age, 21)
- self.assertEqual(p2.first, 'Jane')
- self.assertEqual(p2.last, 'Doe')
-
- def test_implicit_indexing(self):
- class Person(NamedTuple):
- __order__ = "age first last"
- age = "person's age"
- first = "person's first name"
- last = "person's last name"
- p1 = Person(17, 'John', 'Doe')
- p2 = Person(21, 'Jane', 'Doe')
- self.assertEqual(p1[0], 17)
- self.assertEqual(p1[1], 'John')
- self.assertEqual(p1[2], 'Doe')
- self.assertEqual(p2[0], 21)
- self.assertEqual(p2[1], 'Jane')
- self.assertEqual(p2[2], 'Doe')
- self.assertEqual(p1.age, 17)
- self.assertEqual(p1.first, 'John')
- self.assertEqual(p1.last, 'Doe')
- self.assertEqual(p2.age, 21)
- self.assertEqual(p2.first, 'Jane')
- self.assertEqual(p2.last, 'Doe')
-
- def test_mixed_indexing(self):
- class Person(NamedTuple):
- __order__ = "age last cars"
- age = "person's age"
- last = 2, "person's last name"
- cars = "person's cars"
- p1 = Person(17, 'John', 'Doe', 3)
- p2 = Person(21, 'Jane', 'Doe', 9)
- self.assertEqual(p1[0], 17)
- self.assertEqual(p1[1], 'John')
- self.assertEqual(p1[2], 'Doe')
- self.assertEqual(p1[3], 3)
- self.assertEqual(p2[0], 21)
- self.assertEqual(p2[1], 'Jane')
- self.assertEqual(p2[2], 'Doe')
- self.assertEqual(p2[3], 9)
- self.assertEqual(p1.age, 17)
- self.assertEqual(p1.last, 'Doe')
- self.assertEqual(p1.cars, 3)
- self.assertEqual(p2.age, 21)
- self.assertEqual(p2.last, 'Doe')
- self.assertEqual(p2.cars, 9)
-
- def test_issubclass(self):
- class Person(NamedTuple):
- age = 0
- first = 1
- last = 2
- self.assertTrue(issubclass(Person, NamedTuple))
- self.assertTrue(issubclass(Person, tuple))
-
- def test_isinstance(self):
- class Person(NamedTuple):
- age = 0
- first = 1
- last = 2
- p1 = Person(17, 'John', 'Doe')
- self.assertTrue(isinstance(p1, Person))
- self.assertTrue(isinstance(p1, NamedTuple))
- self.assertTrue(isinstance(p1, tuple))
-
- def test_explicit_indexing_after_functional_api(self):
- Person = NamedTuple('Person', (('age', 0), ('first', 1), ('last', 2)))
- p1 = Person(17, 'John', 'Doe')
- p2 = Person(21, 'Jane', 'Doe')
- self.assertEqual(p1[0], 17)
- self.assertEqual(p1[1], 'John')
- self.assertEqual(p1[2], 'Doe')
- self.assertEqual(p2[0], 21)
- self.assertEqual(p2[1], 'Jane')
- self.assertEqual(p2[2], 'Doe')
- self.assertEqual(p1.age, 17)
- self.assertEqual(p1.first, 'John')
- self.assertEqual(p1.last, 'Doe')
- self.assertEqual(p2.age, 21)
- self.assertEqual(p2.first, 'Jane')
- self.assertEqual(p2.last, 'Doe')
-
- def test_implicit_indexing_after_functional_api(self):
- Person = NamedTuple('Person', 'age first last')
- p1 = Person(17, 'John', 'Doe')
- p2 = Person(21, 'Jane', 'Doe')
- self.assertEqual(p1[0], 17)
- self.assertEqual(p1[1], 'John')
- self.assertEqual(p1[2], 'Doe')
- self.assertEqual(p2[0], 21)
- self.assertEqual(p2[1], 'Jane')
- self.assertEqual(p2[2], 'Doe')
- self.assertEqual(p1.age, 17)
- self.assertEqual(p1.first, 'John')
- self.assertEqual(p1.last, 'Doe')
- self.assertEqual(p2.age, 21)
- self.assertEqual(p2.first, 'Jane')
- self.assertEqual(p2.last, 'Doe')
-
- def test_mixed_indexing_after_functional_api(self):
- Person = NamedTuple('Person', (('age', 0), ('last', 2), ('cars', 3)))
- p1 = Person(17, 'John', 'Doe', 3)
- p2 = Person(21, 'Jane', 'Doe', 9)
- self.assertEqual(p1[0], 17)
- self.assertEqual(p1[1], 'John')
- self.assertEqual(p1[2], 'Doe')
- self.assertEqual(p1[3], 3)
- self.assertEqual(p2[0], 21)
- self.assertEqual(p2[1], 'Jane')
- self.assertEqual(p2[2], 'Doe')
- self.assertEqual(p2[3], 9)
- self.assertEqual(p1.age, 17)
- self.assertEqual(p1.last, 'Doe')
- self.assertEqual(p1.cars, 3)
- self.assertEqual(p2.age, 21)
- self.assertEqual(p2.last, 'Doe')
- self.assertEqual(p2.cars, 9)
-
- def test_issubclass_after_functional_api(self):
- Person = NamedTuple('Person', 'age first last')
- self.assertTrue(issubclass(Person, NamedTuple))
- self.assertTrue(issubclass(Person, tuple))
-
- def test_isinstance_after_functional_api(self):
- Person = NamedTuple('Person', 'age first last')
- p1 = Person(17, 'John', 'Doe')
- self.assertTrue(isinstance(p1, Person))
- self.assertTrue(isinstance(p1, NamedTuple))
- self.assertTrue(isinstance(p1, tuple))
-
- def test_creation_with_all_keywords(self):
- Person = NamedTuple('Person', 'age first last')
- p1 = Person(age=17, first='John', last='Doe')
- self.assertEqual(p1[0], 17)
- self.assertEqual(p1[1], 'John')
- self.assertEqual(p1[2], 'Doe')
- self.assertEqual(p1.age, 17)
- self.assertEqual(p1.first, 'John')
- self.assertEqual(p1.last, 'Doe')
-
- def test_creation_with_some_keywords(self):
- Person = NamedTuple('Person', 'age first last')
- p1 = Person(17, first='John', last='Doe')
- self.assertEqual(p1[0], 17)
- self.assertEqual(p1[1], 'John')
- self.assertEqual(p1[2], 'Doe')
- self.assertEqual(p1.age, 17)
- self.assertEqual(p1.first, 'John')
- self.assertEqual(p1.last, 'Doe')
- p1 = Person(17, last='Doe', first='John')
- self.assertEqual(p1[0], 17)
- self.assertEqual(p1[1], 'John')
- self.assertEqual(p1[2], 'Doe')
- self.assertEqual(p1.age, 17)
- self.assertEqual(p1.first, 'John')
- self.assertEqual(p1.last, 'Doe')
-
- def test_custom_new(self):
- class Book(NamedTuple):
- title = 0
- author = 1
- genre = 2
- def __new__(cls, string):
- args = [s.strip() for s in string.split(';')]
- return super(Book, cls).__new__(cls, *tuple(args))
- b1 = Book('The Last Mohican; John Doe; Historical')
- self.assertEqual(b1.title, 'The Last Mohican')
- self.assertEqual(b1.author, 'John Doe')
- self.assertEqual(b1.genre, 'Historical')
-
- def test_defaults_in_class(self):
- class Character(NamedTuple):
- name = 0
- gender = 1, None, 'male'
- klass = 2, None, 'fighter'
- for char in (
- {'name':'John Doe'},
- {'name':'William Pickney', 'klass':'scholar'},
- {'name':'Sarah Doughtery', 'gender':'female'},
- {'name':'Sissy Moonbeam', 'gender':'female', 'klass':'sorceress'},
- ):
- c = Character(**char)
- for name, value in (('name', None), ('gender','male'), ('klass','fighter')):
- if name in char:
- value = char[name]
- self.assertEqual(getattr(c, name), value)
-
- def test_defaults_in_class_that_are_falsey(self):
- class Point(NamedTuple):
- x = 0, 'horizondal coordinate', 0
- y = 1, 'vertical coordinate', 0
- p = Point()
- self.assertEqual(p.x, 0)
- self.assertEqual(p.y, 0)
-
- def test_pickle_namedtuple_with_module(self):
- if isinstance(LifeForm, Exception):
- raise LifeForm
- lf = LifeForm('this', 'that', 'theother')
- test_pickle_dump_load(self.assertEqual, lf)
-
- def test_pickle_namedtuple_without_module(self):
- if isinstance(DeathForm, Exception):
- raise DeathForm
- df = DeathForm('sickly green', '2x4', 'foul')
- test_pickle_dump_load(self.assertEqual, df)
-
- def test_subclassing(self):
- if isinstance(ThatsIt, Exception):
- raise ThatsIt
- ti = ThatsIt('Henry', 'Weinhardt')
- self.assertEqual(ti.blah, 'Henry')
- self.assertTrue(ti.what(), 'Henry')
- test_pickle_dump_load(self.assertEqual, ti)
-
- def test_contains(self):
- Book = NamedTuple('Book', 'title author genre')
- b = Book('Teckla', 'Steven Brust', 'fantasy')
- self.assertTrue('Teckla' in b)
- self.assertTrue('Steven Brust' in b)
- self.assertTrue('fantasy' in b)
-
- def test_fixed_size(self):
- class Book(NamedTuple):
- _size_ = TupleSize.fixed
- title = 0
- author = 1
- genre = 2
- b = Book('Teckla', 'Steven Brust', 'fantasy')
- self.assertTrue('Teckla' in b)
- self.assertTrue('Steven Brust' in b)
- self.assertTrue('fantasy' in b)
- self.assertEqual(b.title, 'Teckla')
- self.assertEqual(b.author, 'Steven Brust')
- self.assertRaises(TypeError, Book, 'Teckla', 'Steven Brust')
- self.assertRaises(TypeError, Book, 'Teckla')
-
- def test_minimum_size(self):
- class Book(NamedTuple):
- _size_ = TupleSize.minimum
- title = 0
- author = 1
- b = Book('Teckla', 'Steven Brust', 'fantasy')
- self.assertTrue('Teckla' in b)
- self.assertTrue('Steven Brust' in b)
- self.assertTrue('fantasy' in b)
- self.assertEqual(b.title, 'Teckla')
- self.assertEqual(b.author, 'Steven Brust')
- b = Book('Teckla', 'Steven Brust')
- self.assertTrue('Teckla' in b)
- self.assertTrue('Steven Brust' in b)
- self.assertEqual(b.title, 'Teckla')
- self.assertEqual(b.author, 'Steven Brust')
- self.assertRaises(TypeError, Book, 'Teckla')
-
- def test_variable_size(self):
- class Book(NamedTuple):
- _size_ = TupleSize.variable
- title = 0
- author = 1
- genre = 2
- b = Book('Teckla', 'Steven Brust', 'fantasy')
- self.assertTrue('Teckla' in b)
- self.assertTrue('Steven Brust' in b)
- self.assertTrue('fantasy' in b)
- self.assertEqual(b.title, 'Teckla')
- self.assertEqual(b.author, 'Steven Brust')
- self.assertEqual(b.genre, 'fantasy')
- b = Book('Teckla', 'Steven Brust')
- self.assertTrue('Teckla' in b)
- self.assertTrue('Steven Brust' in b)
- self.assertEqual(b.title, 'Teckla')
- self.assertEqual(b.author, 'Steven Brust')
- self.assertRaises(AttributeError, getattr, b, 'genre')
- self.assertRaises(TypeError, Book, title='Teckla', genre='fantasy')
- self.assertRaises(TypeError, Book, author='Steven Brust')
-
- def test_combining_namedtuples(self):
- class Point(NamedTuple):
- x = 0, 'horizontal coordinate', 1
- y = 1, 'vertical coordinate', -1
- class Color(NamedTuple):
- r = 0, 'red component', 11
- g = 1, 'green component', 29
- b = 2, 'blue component', 37
- Pixel1 = NamedTuple('Pixel', Point+Color, module=__name__)
- class Pixel2(Point, Color):
- "a colored dot"
- class Pixel3(Point):
- r = 2, 'red component', 11
- g = 3, 'green component', 29
- b = 4, 'blue component', 37
- self.assertEqual(Pixel1._fields_, 'x y r g b'.split())
- self.assertEqual(Pixel1.x.__doc__, 'horizontal coordinate')
- self.assertEqual(Pixel1.x.default, 1)
- self.assertEqual(Pixel1.y.__doc__, 'vertical coordinate')
- self.assertEqual(Pixel1.y.default, -1)
- self.assertEqual(Pixel1.r.__doc__, 'red component')
- self.assertEqual(Pixel1.r.default, 11)
- self.assertEqual(Pixel1.g.__doc__, 'green component')
- self.assertEqual(Pixel1.g.default, 29)
- self.assertEqual(Pixel1.b.__doc__, 'blue component')
- self.assertEqual(Pixel1.b.default, 37)
- self.assertEqual(Pixel2._fields_, 'x y r g b'.split())
- self.assertEqual(Pixel2.x.__doc__, 'horizontal coordinate')
- self.assertEqual(Pixel2.x.default, 1)
- self.assertEqual(Pixel2.y.__doc__, 'vertical coordinate')
- self.assertEqual(Pixel2.y.default, -1)
- self.assertEqual(Pixel2.r.__doc__, 'red component')
- self.assertEqual(Pixel2.r.default, 11)
- self.assertEqual(Pixel2.g.__doc__, 'green component')
- self.assertEqual(Pixel2.g.default, 29)
- self.assertEqual(Pixel2.b.__doc__, 'blue component')
- self.assertEqual(Pixel2.b.default, 37)
- self.assertEqual(Pixel3._fields_, 'x y r g b'.split())
- self.assertEqual(Pixel3.x.__doc__, 'horizontal coordinate')
- self.assertEqual(Pixel3.x.default, 1)
- self.assertEqual(Pixel3.y.__doc__, 'vertical coordinate')
- self.assertEqual(Pixel3.y.default, -1)
- self.assertEqual(Pixel3.r.__doc__, 'red component')
- self.assertEqual(Pixel3.r.default, 11)
- self.assertEqual(Pixel3.g.__doc__, 'green component')
- self.assertEqual(Pixel3.g.default, 29)
- self.assertEqual(Pixel3.b.__doc__, 'blue component')
- self.assertEqual(Pixel3.b.default, 37)
-
- def test_function_api_type(self):
- class Tester(NamedTuple):
- def howdy(self):
- return 'backwards', list(reversed(self))
- Testee = NamedTuple('Testee', 'a c e', type=Tester)
- t = Testee(1, 2, 3)
- self.assertEqual(t.howdy(), ('backwards', [3, 2, 1]))
-
- def test_asdict(self):
- class Point(NamedTuple):
- x = 0, 'horizontal coordinate', 1
- y = 1, 'vertical coordinate', -1
- class Color(NamedTuple):
- r = 0, 'red component', 11
- g = 1, 'green component', 29
- b = 2, 'blue component', 37
- Pixel = NamedTuple('Pixel', Point+Color, module=__name__)
- pixel = Pixel(99, -101, 255, 128, 0)
- self.assertEqual(pixel._asdict(), {'x':99, 'y':-101, 'r':255, 'g':128, 'b':0})
-
- def test_make(self):
- class Point(NamedTuple):
- x = 0, 'horizontal coordinate', 1
- y = 1, 'vertical coordinate', -1
- self.assertEqual(Point(4, 5), (4, 5))
- self.assertEqual(Point._make((4, 5)), (4, 5))
-
- def test_replace(self):
- class Color(NamedTuple):
- r = 0, 'red component', 11
- g = 1, 'green component', 29
- b = 2, 'blue component', 37
- purple = Color(127, 0, 127)
- mid_gray = purple._replace(g=127)
- self.assertEqual(mid_gray, (127, 127, 127))
-
-
-class TestNamedConstant(TestCase):
-
- def test_constantness(self):
- class K(NamedConstant):
- PI = 3.141596
- TAU = 2 * PI
- self.assertEqual(K.PI, 3.141596)
- self.assertEqual(K.TAU, 2 * K.PI)
- with self.assertRaisesRegex(AttributeError, r'cannot rebind constant'):
- K.PI = 9
- with self.assertRaisesRegex(AttributeError, r'cannot delete constant'):
- del K.PI
- with self.assertRaisesRegex(AttributeError, r'cannot rebind constant'):
- K('PI', 3)
- self.assertTrue(K.PI in K)
- self.assertTrue(K.TAU in K)
-
- def test_duplicates(self):
- class CardNumber(NamedConstant):
- ACE = 11
- TWO = 2
- THREE = 3
- FOUR = 4
- FIVE = 5
- SIX = 6
- SEVEN = 7
- EIGHT = 8
- NINE = 9
- TEN = 10
- JACK = 10
- QUEEN = 10
- KING = 10
- self.assertFalse(CardNumber.TEN is CardNumber.JACK)
- self.assertEqual(CardNumber.TEN, CardNumber.JACK)
- self.assertEqual(CardNumber.TEN, 10)
-
- def test_extend_constants(self):
- class CardSuit(NamedConstant):
- HEARTS = 1
- SPADES = 2
- DIAMONTS = 3
- CLUBS = 4
- self.assertEqual(CardSuit.HEARTS, 1)
- stars = CardSuit('STARS', 5)
- self.assertIs(stars, CardSuit.STARS)
- self.assertEqual(CardSuit.STARS, 5)
- self.assertTrue(CardSuit.STARS in CardSuit)
-
- def test_constant_with_docstring(self):
- class Stuff(NamedConstant):
- Artifact = constant(7, "lucky number!")
- Bowling = 11
- HillWomp = constant(29, 'blah blah')
- self.assertEqual(Stuff.Artifact, 7)
- self.assertEqual(Stuff.Artifact.__doc__, 'lucky number!')
- self.assertEqual(Stuff.Bowling, 11)
- self.assertEqual(Stuff.Bowling.__doc__, None)
- self.assertEqual(Stuff.HillWomp, 29)
- self.assertEqual(Stuff.HillWomp.__doc__, 'blah blah')
-
- def test_deep_copy(self):
- import copy
- class APITypes(aenum.Constant):
- STRING = "string"
- INT = "int"
- APITypes('string')
- d = {"first": APITypes.STRING}
- copy.deepcopy(d)
- self.assertTrue(d['first'] is APITypes.STRING)
-
- def test_subclass_w_same_value(self):
- class Foo(aenum.Constant):
- BLA = 'bla1'
- ABA = 'aba1'
- class Bar(aenum.Constant):
- BLA = Foo.BLA
- ABA = 'aba2'
- self.assertEqual(Foo.BLA, Bar.BLA)
- self.assertFalse(Foo.BLA is Bar.BLA)
-
-
-class TestStarImport(TestCase):
-
- def test_all_exports_names(self):
- scope = {}
- exec('from aenum import *', scope, scope)
- self.assertIn('Enum', scope)
-
-class TestStackoverflowAnswers(TestCase):
-
- def test_self_referential_directions(self):
- # https://stackoverflow.com/a/64000706/208880
- class Directions(Enum):
- _order_ = 'NORTH WEST SOUTH EAST'
- #
- NORTH = 1, 0
- WEST = 0, 1
- SOUTH = -1, 0
- EAST = 0, -1
- #
- def __init__(self, x, y):
- self.x = x
- self.y = y
- if len(self.__class__):
- # make links
- all = list(self.__class__)
- left, right = all[0], all[-1]
- self.left = left
- self.right = right
- left.right = self
- right.left = self
- #
- D = Directions
- self.assertEqual(D.NORTH.value, (1, 0))
- self.assertTrue(D.NORTH.left is D.WEST)
- self.assertTrue(D.SOUTH.right is D.WEST)
-
- def test_self_referential_rock_paper_scissors(self):
- # https://stackoverflow.com/a/57085357/208880
- class RPS(Enum):
- _order_ = 'Rock, Paper, Scissors'
- #
- Rock = "rock"
- Paper = "paper"
- Scissors = "scissors"
- #
- def __init__(self, value):
- if len(self.__class__):
- # make links
- all = list(self.__class__)
- first, previous = all[0], all[-1]
- first.beats = self
- self.beats = previous
- #
- self.assertTrue(RPS.Rock.beats is RPS.Scissors)
- self.assertTrue(RPS.Scissors.beats is RPS.Paper)
- self.assertTrue(RPS.Paper.beats is RPS.Rock)
-
- def test_arduino_headers(self):
- # https://stackoverflow.com/q/65048495/208880
- class CHeader(Enum):
- def __init_subclass__(cls, **kwds):
- # write Enums to C header file
- cls_name = cls.__name__
- header_path = getattr(cls, '_%s__header' % cls_name)
- with open(header_path, 'w') as fh:
- fh.write('initial header stuff here\n')
- for enum in cls:
- fh.write('#define %s %r\n' % (enum.name, enum.value))
- class Arduino(CHeader):
- _order_ = 'ONE TWO'
- __header = os.path.join(tempdir, 'arduino.h')
- ONE = 1
- TWO = 2
- with open(os.path.join(tempdir, 'arduino.h')) as fh:
- data = fh.read()
- self.assertEqual(textwrap.dedent("""\
- initial header stuff here
- #define ONE 1
- #define TWO 2
- """),
- data,
- )
-
- def test_lowercase_compare(self):
- # https://stackoverflow.com/q/65139026/208880
- class CompareLowerCase(Enum):
- def __init_subclass__(cls, **kwds):
- super(CompareLowerCase, cls).__init_subclass__(**kwds)
- cls.lowered_names = set([m.name.lower() for m in cls])
- @classmethod
- def has_name(cls, name):
- return name.lower() in cls.lowered_names
- #
- class LabelEnum(CompareLowerCase, StrEnum):
- ENUM_ONE = "Enum One"
- ENUM_TWO = "Enum Two"
- ENUM_THREE = "Enum Three"
- FOUR = "FOUR"
- FIVE = "FIVE"
- SIX = "SIX"
- #
- self.assertTrue(LabelEnum.has_name('Enum_Three'))
-
-
-class TestExtendEnum(TestCase):
-
- def test_extend_enum_plain(self):
- class Color(Enum):
- red = 1
- green = 2
- blue = 3
- self.assertRaisesRegex(TypeError, 'already in use as', extend_enum, Color, 'blue', 5)
- #
- extend_enum(Color, 'brown', 4)
- self.assertEqual(Color.brown.name, 'brown')
- self.assertEqual(Color.brown.value, 4)
- self.assertTrue(Color.brown in Color)
- self.assertEqual(Color(4), Color.brown)
- self.assertEqual(Color['brown'], Color.brown)
- self.assertEqual(len(Color), 4)
- #
- extend_enum(Color, 'mauve')
- self.assertEqual(Color.mauve.name, 'mauve')
- self.assertEqual(Color.mauve.value, 5)
- self.assertTrue(Color.mauve in Color)
- self.assertEqual(Color(5), Color.mauve)
- self.assertEqual(Color['mauve'], Color.mauve)
- self.assertEqual(len(Color), 5)
-
- def test_extend_enum_alias(self):
- class Color(Enum):
- red = 1
- green = 2
- blue = 3
- extend_enum(Color, 'rojo', 1)
- self.assertEqual(Color.rojo.name, 'red')
- self.assertEqual(Color.rojo.value, 1)
- self.assertTrue(Color.rojo in Color)
- self.assertEqual(Color(1), Color.rojo)
- self.assertEqual(Color['rojo'], Color.red)
- self.assertEqual(len(Color), 3)
-
- def test_extend_enum_unique(self):
- class Color(UniqueEnum):
- red = 1
- green = 2
- blue = 3
- self.assertRaisesRegex(ValueError, r'<Color.rojo: 1> is a duplicate of <Color.red: 1>', extend_enum, Color, 'rojo', 1)
- #
- self.assertEqual(Color.red.name, 'red')
- self.assertEqual(Color.red.value, 1)
- self.assertTrue(Color.red in Color)
- self.assertEqual(Color(1), Color.red)
- self.assertEqual(Color['red'], Color.red)
- self.assertEqual(Color.green.name, 'green')
- self.assertEqual(Color.green.value, 2)
- self.assertTrue(Color.green in Color)
- self.assertEqual(Color(2), Color.green)
- self.assertEqual(Color['blue'], Color.blue)
- self.assertEqual(Color.blue.name, 'blue')
- self.assertEqual(Color.blue.value, 3)
- self.assertTrue(Color.blue in Color)
- self.assertEqual(Color(3), Color.blue)
- self.assertEqual(len(Color), 3)
- #
- extend_enum(Color, 'brown', 4)
- self.assertEqual(Color.brown.name, 'brown')
- self.assertEqual(Color.brown.value, 4)
- self.assertTrue(Color.brown in Color)
- self.assertEqual(Color(4), Color.brown)
- self.assertEqual(Color['brown'], Color.brown)
- self.assertEqual(len(Color), 4)
- #
- self.assertRaisesRegex(ValueError, '', extend_enum, Color, 'verde', 2)
- #
- extend_enum(Color, 'mauve')
- self.assertEqual(Color.mauve.name, 'mauve')
- self.assertEqual(Color.mauve.value, 5)
- self.assertTrue(Color.mauve in Color)
- self.assertEqual(Color(5), Color.mauve)
- self.assertEqual(Color['mauve'], Color.mauve)
- self.assertEqual(len(Color), 5)
-
-
- def test_extend_enum_shadow_property(self):
- class Color(Enum):
- red = 1
- green = 2
- blue = 3
- extend_enum(Color, 'value', 4)
- self.assertEqual(Color.value.name, 'value')
- self.assertEqual(Color.value.value, 4)
- self.assertTrue(Color.value in Color)
- self.assertEqual(Color(4), Color.value)
- self.assertEqual(Color['value'], Color.value)
- self.assertEqual(len(Color), 4)
- self.assertEqual(Color.red.value, 1)
-
- def test_extend_enum_shadow_base(self):
- class hohum(object):
- def cyan(self):
- "cyanize a color"
- return self.value
- class Color(hohum, Enum):
- red = 1
- green = 2
- blue = 3
- self.assertRaisesRegex(TypeError, r'already in use in superclass', extend_enum, Color, 'cyan', 4)
- self.assertEqual(len(Color), 3)
- self.assertEqual(list(Color), [Color.red, Color.green, Color.blue])
-
- def test_extend_enum_multivalue(self):
- class Color(MultiValueEnum):
- red = 1, 4, 7
- green = 2, 5, 8
- blue = 3, 6, 9
- extend_enum(Color, 'brown', 10, 20)
- self.assertEqual(Color.brown.name, 'brown')
- self.assertEqual(Color.brown.value, 10)
- self.assertTrue(Color.brown in Color)
- self.assertEqual(Color(10), Color.brown)
- self.assertEqual(Color(20), Color.brown)
- self.assertEqual(Color['brown'], Color.brown)
- self.assertEqual(len(Color), 4)
- #
- self.assertRaisesRegex(ValueError, 'no values specified for MultiValue enum', extend_enum, Color, 'mauve')
-
- def test_extend_enum_multivalue_alias(self):
- class Color(MultiValueEnum):
- red = 1, 4, 7
- green = 2, 5, 8
- blue = 3, 6, 9
- self.assertRaisesRegex(ValueError, r'<Color.rojo: 7> is a duplicate of <Color.red: 1>', extend_enum, Color, 'rojo', 7)
- self.assertEqual(Color.red.name, 'red')
- self.assertEqual(Color.red.value, 1)
- self.assertTrue(Color.red in Color)
- self.assertEqual(Color(1), Color.red)
- self.assertEqual(Color(4), Color.red)
- self.assertEqual(Color(7), Color.red)
- self.assertEqual(Color['red'], Color.red)
- self.assertEqual(Color.green.name, 'green')
- self.assertEqual(Color.green.value, 2)
- self.assertTrue(Color.green in Color)
- self.assertEqual(Color(2), Color.green)
- self.assertEqual(Color(5), Color.green)
- self.assertEqual(Color(8), Color.green)
- self.assertEqual(Color['blue'], Color.blue)
- self.assertEqual(Color.blue.name, 'blue')
- self.assertEqual(Color.blue.value, 3)
- self.assertTrue(Color.blue in Color)
- self.assertEqual(Color(3), Color.blue)
- self.assertEqual(Color(6), Color.blue)
- self.assertEqual(Color(9), Color.blue)
- self.assertEqual(len(Color), 3)
-
- def test_extend_enum_multivalue_str(self):
- class M(str, MultiValueEnum):
- VALUE_1 = 'value_1', 'VALUE_1'
- VALUE_2 = 'value_2', 'VALUE_2'
- VALUE_3 = 'value_3', 'VALUE_3'
- self.assertTrue(M._member_type_ is str)
- extend_enum(M, 'VALUE_4', 'value_4', 'VALUE_4')
- self.assertEqual(list(M), [M.VALUE_1, M.VALUE_2, M.VALUE_3, M.VALUE_4])
- self.assertTrue(M('value_4') is M.VALUE_4)
- self.assertTrue(M('VALUE_4') is M.VALUE_4)
- self.assertTrue(M.VALUE_4.name == 'VALUE_4')
- self.assertTrue(M.VALUE_4.value == 'value_4')
-
- def test_extend_intenum(self):
- class Index(IntEnum):
- DeviceType = 0x1000
- ErrorRegister = 0x1001
-
- for name, value in (
- ('ControlWord', 0x6040),
- ('StatusWord', 0x6041),
- ('OperationMode', 0x6060),
- ):
- extend_enum(Index, name, value)
-
- self.assertEqual(len(Index), 5)
- self.assertEqual(list(Index), [Index.DeviceType, Index.ErrorRegister, Index.ControlWord, Index.StatusWord, Index.OperationMode])
- self.assertEqual(Index.DeviceType.value, 0x1000)
- self.assertEqual(Index.StatusWord.value, 0x6041)
-
- def test_extend_multi_init(self):
- try:
- from http import HTTPStatus
- length = len(HTTPStatus)
- except ImportError:
- class HTTPStatus(IntEnum):
- def __new__(cls, value, phrase, description):
- obj = int.__new__(cls, value)
- obj._value_ = value
-
- obj.phrase = phrase
- obj.description = description
- return obj
- CONTINUE = 100, 'Continue', 'Request received, please continue'
- SWITCHING_PROTOCOLS = 101, 'Switching Protocols', 'Switching to new protocol; obey Upgrade header'
- PROCESSING = 102, 'Processing', ''
- length = 3
- extend_enum(HTTPStatus, 'BAD_SPAM', 513, 'Too greasy', 'for a train')
- extend_enum(HTTPStatus, 'BAD_EGGS', 514, 'Too green', '')
- self.assertEqual(len(HTTPStatus), length+2)
- self.assertEqual(
- list(HTTPStatus)[-2:],
- [HTTPStatus.BAD_SPAM, HTTPStatus.BAD_EGGS],
- )
- self.assertEqual(HTTPStatus.BAD_SPAM.value, 513)
- self.assertEqual(HTTPStatus.BAD_SPAM.name, 'BAD_SPAM')
- self.assertEqual(HTTPStatus.BAD_SPAM.phrase, 'Too greasy')
- self.assertEqual(HTTPStatus.BAD_SPAM.description, 'for a train')
- self.assertEqual(HTTPStatus.BAD_EGGS.value, 514)
- self.assertEqual(HTTPStatus.BAD_EGGS.name, 'BAD_EGGS')
- self.assertEqual(HTTPStatus.BAD_EGGS.phrase, 'Too green')
- self.assertEqual(HTTPStatus.BAD_EGGS.description, '')
-
- def test_extend_flag(self):
- class Color(Flag):
- BLACK = 0
- RED = 1
- GREEN = 2
- BLUE = 4
- extend_enum(Color, 'MAGENTA')
- self.assertTrue(Color(8) is Color.MAGENTA)
- self.assertTrue(isinstance(Color.MAGENTA, Color))
- self.assertEqual(Color.MAGENTA.value, 8)
- extend_enum(Color, 'PURPLE', 11)
- self.assertTrue(Color(11) is Color.PURPLE)
- self.assertTrue(isinstance(Color.PURPLE, Color))
- self.assertEqual(Color.PURPLE.value, 11)
- self.assertTrue(issubclass(Color, Flag))
-
- def test_extend_flag_backwards(self):
- class Color(Flag):
- BLACK = 0
- RED = 1
- GREEN = 2
- BLUE = 4
- extend_enum(Color, 'PURPLE', 11)
- self.assertTrue(Color(11) is Color.PURPLE)
- self.assertTrue(isinstance(Color.PURPLE, Color))
- self.assertEqual(Color.PURPLE.value, 11)
- self.assertTrue(issubclass(Color, Flag))
- #
- extend_enum(Color, 'MAGENTA')
- self.assertTrue(Color(8) is Color.MAGENTA)
- self.assertTrue(isinstance(Color.MAGENTA, Color))
- self.assertEqual(Color.MAGENTA.value, 8)
- #
- extend_enum(Color, 'mauve')
- self.assertEqual(Color.mauve.name, 'mauve')
- self.assertEqual(Color.mauve.value, 16)
- self.assertTrue(Color.mauve in Color)
- self.assertEqual(Color(16), Color.mauve)
- self.assertEqual(Color['mauve'], Color.mauve)
- self.assertEqual(len(Color), 5)
-
- def test_extend_intflag(self):
- class Color(IntFlag):
- BLACK = 0
- RED = 1
- GREEN = 2
- BLUE = 4
- extend_enum(Color, 'MAGENTA')
- self.assertTrue(Color(8) is Color.MAGENTA)
- self.assertTrue(isinstance(Color.MAGENTA, Color))
- self.assertEqual(Color.MAGENTA.value, 8)
- extend_enum(Color, 'PURPLE', 11)
- self.assertTrue(Color(11) is Color.PURPLE)
- self.assertTrue(isinstance(Color.PURPLE, Color))
- self.assertEqual(Color.PURPLE.value, 11)
- self.assertTrue(issubclass(Color, Flag))
- #
- extend_enum(Color, 'mauve')
- self.assertEqual(Color.mauve.name, 'mauve')
- self.assertEqual(Color.mauve.value, 16)
- self.assertTrue(Color.mauve in Color)
- self.assertEqual(Color(16), Color.mauve)
- self.assertEqual(Color['mauve'], Color.mauve)
- self.assertEqual(len(Color), 5)
-
- def test_extend_intflag_backwards(self):
- class Color(IntFlag):
- BLACK = 0
- RED = 1
- GREEN = 2
- BLUE = 4
- extend_enum(Color, 'PURPLE', 11)
- self.assertTrue(Color(11) is Color.PURPLE)
- self.assertTrue(isinstance(Color.PURPLE, Color))
- self.assertEqual(Color.PURPLE.value, 11)
- self.assertTrue(issubclass(Color, Flag))
- #
- extend_enum(Color, 'MAGENTA')
- self.assertTrue(Color(8) is Color.MAGENTA)
- self.assertTrue(isinstance(Color.MAGENTA, Color))
- self.assertEqual(Color.MAGENTA.value, 8)
- #
- extend_enum(Color, 'mauve')
- self.assertEqual(Color.mauve.name, 'mauve')
- self.assertEqual(Color.mauve.value, 16)
- self.assertTrue(Color.mauve in Color)
- self.assertEqual(Color(16), Color.mauve)
- self.assertEqual(Color['mauve'], Color.mauve)
- self.assertEqual(len(Color), 5)
-
- def test_extend_strenum(self):
- class Color(StrEnum):
- RED = auto()
- GREEN = auto()
- BLUE = auto()
- extend_enum(Color, 'BLACK')
- self.assertEqual(Color.BLACK.name, 'BLACK')
- self.assertEqual(Color.BLACK.value, 'black')
- self.assertEqual(len(Color), 4)
-
-
-class TestIssues(TestCase):
-
- def test_auto_multi_int(self):
- class Measurement(int, MultiValueEnum, AddValueEnum):
- _order_ = 'one two three'
- _start_ = 0
- one = "20110721"
- two = "20120911"
- three = "20110518"
- self.assertEqual([m.value for m in Measurement], [0, 1, 2])
- self.assertEqual([m.name for m in Measurement], ['one', 'two', 'three'])
- self.assertIs(Measurement('20110721'), Measurement.one)
- self.assertIs(Measurement(0), Measurement.one)
- self.assertIs(Measurement('20120911'), Measurement.two)
- self.assertIs(Measurement(1), Measurement.two)
- self.assertIs(Measurement('20110518'), Measurement.three)
- self.assertIs(Measurement(2), Measurement.three)
-
- def test_auto_kwds(self):
- class Item(Enum):
- _order_ = 'A B'
- A = auto(size=100, requirements={})
- B = auto(size=200, requirements={A: 1})
- #
- def __new__(cls, value, size, requirements):
- obj = object.__new__(cls)
- obj._value_ = value
- obj.size = size
- # fix requirements
- new_requirements = {}
- for k, v in requirements.items():
- if isinstance(k, auto):
- k = k.enum_member
- new_requirements[k] = v
- obj.requirements = new_requirements
- return obj
- self.assertEqual((Item.A.value, Item.A.size, Item.A.requirements), (1, 100, {}))
- self.assertEqual((Item.B.value, Item.B.size, Item.B.requirements), (2, 200, {Item.A: 1}))
-
- def test_extend_flag(self):
- class FlagTest(Flag): # Or IntFlag
- NONE = 0
- LOW = 1
- MID = 2
- extend_enum(FlagTest, 'HIGH', 4)
- self.assertEqual(FlagTest.LOW | FlagTest.HIGH, FlagTest(5))
- self.assertEqual((FlagTest.LOW | FlagTest.HIGH).value, 5)
-
- def test_extend_unhashable(self):
- class TestEnum(Enum):
- ABC = {
- 'id': 0,
- 'value': 'abc'
- }
- DEF = {
- 'id': 1,
- 'value': 'def'
- }
- rand = uuid.uuid4().hex
- new_value = {
- 'id': 99,
- 'value': 'new',
- }
- extend_enum(TestEnum, rand, new_value)
-
-
-
-# Test conversion of global constants
-# These are unordered here on purpose to ensure that declaration order
-# makes no difference.
-CONVERT_TEST_NAME_D = 5
-CONVERT_TEST_NAME_C = 5
-CONVERT_TEST_NAME_B = 5
-CONVERT_TEST_NAME_A = 5 # This one should sort first.
-CONVERT_TEST_NAME_E = 5
-CONVERT_TEST_NAME_F = 5
-CONVERT_TEST_SIGABRT = 4 # and this one
-CONVERT_TEST_SIGIOT = 4
-CONVERT_TEST_EIO = 7
-CONVERT_TEST_EBUS = 7 # and this one
-
-CONVERT_STRING_TEST_NAME_D = 5
-CONVERT_STRING_TEST_NAME_C = 5
-CONVERT_STRING_TEST_NAME_B = 5
-CONVERT_STRING_TEST_NAME_A = 5 # This one should sort first.
-CONVERT_STRING_TEST_NAME_E = 5
-CONVERT_STRING_TEST_NAME_F = 5
-
-# global names for StrEnum._convert_ test
-CONVERT_STR_TEST_2 = 'goodbye'
-CONVERT_STR_TEST_1 = 'hello'
-
-# We also need values that cannot be compared:
-UNCOMPARABLE_A = 5
-UNCOMPARABLE_C = (9, 1) # naming order is broken on purpose
-UNCOMPARABLE_B = 'value'
-
-COMPLEX_C = 1j
-COMPLEX_A = 2j
-COMPLEX_B = 3j
-
-
-class TestConvert(TestCase):
-
- def tearDown(self):
- # Reset the module-level test variables to their original integer
- # values, otherwise the already created enum values get converted
- # instead.
- g = globals()
- for suffix in ['A', 'B', 'C', 'D', 'E', 'F']:
- g['CONVERT_TEST_NAME_%s' % suffix] = 5
- g['CONVERT_STRING_TEST_NAME_%s' % suffix] = 5
- for suffix, value in (('A', 5), ('B', (9, 1)), ('C', 'value')):
- g['UNCOMPARABLE_%s' % suffix] = value
- for suffix, value in (('A', 2j), ('B', 3j), ('C', 1j)):
- g['COMPLEX_%s' % suffix] = value
- for suffix, value in (('1', 'hello'), ('2', 'goodbye')):
- g['CONVERT_STR_TEST_%s' % suffix] = value
- g['CONVERT_TEST_SIGABRT'] = 4
- g['CONVERT_TEST_SIGIOT'] = 4
- g['CONVERT_TEST_EIO'] = 7
- g['CONVERT_TEST_EBUS'] = 7
-
- def test_convert_value_lookup_priority(self):
- test_type = IntEnum._convert_(
- 'UnittestConvert',
- MODULE,
- filter=lambda x: x.startswith('CONVERT_TEST_'))
- # We don't want the reverse lookup value to vary when there are
- # multiple possible names for a given value. It should always
- # report the first lexigraphical name in that case.
- self.assertEqual(test_type(5).name, 'CONVERT_TEST_NAME_A')
- self.assertEqual(test_type(4).name, 'CONVERT_TEST_SIGABRT')
- self.assertEqual(test_type(7).name, 'CONVERT_TEST_EBUS')
- self.assertEqual(
- list(test_type),
- [
- test_type.CONVERT_TEST_SIGABRT,
- test_type.CONVERT_TEST_NAME_A,
- test_type.CONVERT_TEST_EBUS,
- ],
- )
-
- def test_convert_int(self):
- test_type = IntEnum._convert_(
- 'UnittestConvert',
- MODULE,
- filter=lambda x: x.startswith('CONVERT_TEST_'))
- # Ensure that test_type has all of the desired names and values.
- self.assertEqual(test_type.CONVERT_TEST_NAME_F,
- test_type.CONVERT_TEST_NAME_A)
- self.assertEqual(test_type.CONVERT_TEST_NAME_B, 5)
- self.assertEqual(test_type.CONVERT_TEST_NAME_C, 5)
- self.assertEqual(test_type.CONVERT_TEST_NAME_D, 5)
- self.assertEqual(test_type.CONVERT_TEST_NAME_E, 5)
- # Ensure that test_type only picked up names matching the filter.
- int_dir = dir(int) + [
- 'CONVERT_TEST_NAME_A', 'CONVERT_TEST_NAME_B', 'CONVERT_TEST_NAME_C',
- 'CONVERT_TEST_NAME_D', 'CONVERT_TEST_NAME_E', 'CONVERT_TEST_NAME_F',
- 'CONVERT_TEST_SIGABRT', 'CONVERT_TEST_SIGIOT',
- 'CONVERT_TEST_EIO', 'CONVERT_TEST_EBUS',
- ]
- extra = [name for name in dir(test_type) if name not in enum_dir(test_type)]
- missing = [name for name in enum_dir(test_type) if name not in dir(test_type)]
- self.assertEqual(
- extra + missing,
- [],
- msg='extra names: %r; missing names: %r' % (extra, missing),
- )
-
- @unittest.skipUnless(PY3, 'everything is comparable on Python 2')
- def test_convert_uncomparable(self):
- uncomp = Enum._convert_(
- 'Uncomparable',
- MODULE,
- filter=lambda x: x.startswith('UNCOMPARABLE_'))
- # Should be ordered by `name` only:
- self.assertEqual(
- list(uncomp),
- [uncomp.UNCOMPARABLE_A, uncomp.UNCOMPARABLE_B, uncomp.UNCOMPARABLE_C],
- list(uncomp),
- )
-
- @unittest.skipUnless(PY3, 'everything is comparable on Python 2')
- def test_convert_complex(self):
- uncomp = Enum._convert_(
- 'Uncomparable',
- MODULE,
- filter=lambda x: x.startswith('COMPLEX_'))
- # Should be ordered by `name` only:
- self.assertEqual(
- list(uncomp),
- [uncomp.COMPLEX_A, uncomp.COMPLEX_B, uncomp.COMPLEX_C],
- )
-
- def test_convert_str(self):
- test_type = StrEnum._convert_(
- 'UnittestConvert',
- MODULE,
- filter=lambda x: x.startswith('CONVERT_STR_'),
- as_global=True)
- # Ensure that test_type has all of the desired names and values.
- self.assertEqual(test_type.CONVERT_STR_TEST_1, 'hello')
- self.assertEqual(test_type.CONVERT_STR_TEST_2, 'goodbye')
- # Ensure that test_type only picked up names matching the filter.
- extra = [name for name in dir(test_type) if name not in enum_dir(test_type)]
- missing = [name for name in enum_dir(test_type) if name not in dir(test_type)]
- self.assertEqual(
- extra + missing,
- [],
- msg='extra names: %r; missing names: %r' % (extra, missing),
- )
- self.assertEqual(repr(test_type.CONVERT_STR_TEST_1), '%s.CONVERT_STR_TEST_1' % SHORT_MODULE)
- self.assertEqual(str(test_type.CONVERT_STR_TEST_2), 'goodbye')
- self.assertEqual(format(test_type.CONVERT_STR_TEST_1), 'hello')
-
- def test_convert_repr_and_str(self):
- test_type = IntEnum._convert_(
- 'UnittestConvert',
- MODULE,
- filter=lambda x: x.startswith('CONVERT_STRING_TEST_'),
- as_global=True)
- self.assertEqual(repr(test_type.CONVERT_STRING_TEST_NAME_A), '%s.CONVERT_STRING_TEST_NAME_A' % SHORT_MODULE)
- self.assertEqual(str(test_type.CONVERT_STRING_TEST_NAME_A), '5')
- self.assertEqual(format(test_type.CONVERT_STRING_TEST_NAME_A), '5')
-
-# helpers
-
-def enum_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)
-
-def member_dir(member):
- if member.__class__._member_type_ is object:
- allowed = set(['__class__', '__doc__', '__eq__', '__hash__', '__module__', 'name', 'value'])
- else:
- allowed = set(dir(member))
- for cls in member.__class__.mro():
- for name, obj in cls.__dict__.items():
- if name[0] == '_':
- continue
- if isinstance(obj, enum.property):
- if obj.fget is not None or name not in member._member_map_:
- allowed.add(name)
- else:
- allowed.discard(name)
- else:
- allowed.add(name)
- return sorted(allowed)
-
-
-
-if __name__ == '__main__':
- tempdir = tempfile.mkdtemp()
- test = None
- try:
- if PY3:
- test_v3.tempdir = tempdir
- test = unittest.main(exit=False)
- sys.stdout.flush()
- for name, reason in test.result.skipped:
- print("%s: %s" % (name, reason))
- finally:
- shutil.rmtree(tempdir, True)
- if test:
- sys.exit(len(test.result.errors or test.result.failures) and 1 or 0)
-
diff --git a/venv/Lib/site-packages/aenum/test_v3.py b/venv/Lib/site-packages/aenum/test_v3.py
deleted file mode 100644
index 62453df1..00000000
--- a/venv/Lib/site-packages/aenum/test_v3.py
+++ /dev/null
@@ -1,1982 +0,0 @@
-from . import EnumMeta, Enum, IntEnum, Flag, IntFlag, StrEnum, UniqueEnum, AutoEnum, AddValueEnum
-from . import NamedTuple, TupleSize, MagicValue, AddValue, NoAlias, Unique, MultiValue
-from . import AutoNumberEnum,MultiValueEnum, OrderedEnum, unique, skip, extend_enum, auto
-from . import StdlibEnumMeta, StdlibEnum, StdlibIntEnum, StdlibFlag, StdlibIntFlag, StdlibStrEnum
-from . import pyver, PY3_3, PY3_4, PY3_5, PY3_6, PY3_11
-from . import add_stdlib_integration, remove_stdlib_integration
-
-from collections import OrderedDict
-from datetime import timedelta
-from pickle import dumps, loads, PicklingError, HIGHEST_PROTOCOL
-from unittest import TestCase, main
-
-import os
-import sys
-import tempfile
-import textwrap
-import unittest
-
-try:
- import pyparsing
-except (ImportError, SyntaxError):
- pyparsing = None
-
-try:
- RecursionError
-except NameError:
- # python3.4
- RecursionError = RuntimeError
-
-class TestEnumV3(TestCase):
-
- def setUp(self):
- class Season(Enum):
- SPRING = 1
- SUMMER = 2
- AUTUMN = 3
- WINTER = 4
- self.Season = Season
-
- class Konstants(float, Enum):
- E = 2.7182818
- PI = 3.1415926
- TAU = 2 * PI
- self.Konstants = Konstants
-
- class Grades(IntEnum):
- A = 5
- B = 4
- C = 3
- D = 2
- F = 0
- self.Grades = Grades
-
- class Directional(str, Enum):
- EAST = 'east'
- WEST = 'west'
- NORTH = 'north'
- SOUTH = 'south'
- self.Directional = Directional
-
- from datetime import date
- class Holiday(date, Enum):
- NEW_YEAR = 2013, 1, 1
- IDES_OF_MARCH = 2013, 3, 15
- self.Holiday = Holiday
-
- @unittest.skipUnless(StdlibEnumMeta, 'Stdlib enum not available')
- def test_stdlib_inheritence(self):
- # 3.4
- self.assertTrue(issubclass(self.Season, StdlibEnum))
- self.assertTrue(isinstance(self.Season.SPRING, StdlibEnum))
- #
- if pyver >= PY3_6:
- class AFlag(Flag):
- one = 1
- self.assertTrue(issubclass(AFlag, StdlibEnum))
- self.assertTrue(isinstance(AFlag.one, StdlibEnum))
- self.assertTrue(issubclass(AFlag, StdlibFlag))
- self.assertTrue(isinstance(AFlag.one, StdlibFlag))
- #
- class AnIntFlag(IntFlag):
- one = 1
- self.assertTrue(issubclass(AnIntFlag, StdlibEnum))
- self.assertTrue(isinstance(AnIntFlag.one, StdlibEnum))
- self.assertTrue(issubclass(AnIntFlag, StdlibFlag))
- self.assertTrue(isinstance(AnIntFlag.one, StdlibFlag))
- self.assertTrue(issubclass(AnIntFlag, StdlibIntFlag))
- self.assertTrue(isinstance(AnIntFlag.one, StdlibIntFlag))
- #
- if pyver >= PY3_11:
- class AStrEnum(StrFlag):
- one = '1'
- self.assertTrue(issubclass(AStrEnum, StdlibEnum))
- self.assertTrue(isinstance(AStrEnum.one, StdlibEnum))
- self.assertTrue(issubclass(AStrEnum, StdlibStrEnum))
- self.assertTrue(isinstance(AStrEnum.one, StdlibStrEnum))
-
- @unittest.skipUnless(StdlibEnumMeta, 'Stdlib enum not available')
- def test_stdlib_bad_getattribute(self):
- class BadEnumType(StdlibEnumMeta):
- def __getattribute__(cls, name):
- obj = super().__getattribute__(name)
- if isinstance(obj, cls):
- obj.deprecate()
- return obj
- with self.assertRaisesRegex(RecursionError, 'endless recursion'):
- class BaseEnum(StdlibEnum):
- pass
- class BadEnum(BaseEnum, metaclass=BadEnumType):
- FOO = 'bar'
- try:
- remove_stdlib_integration()
- class OkayEnum(StdlibEnum, metaclass=BadEnumType):
- FOO = 'bar'
- finally:
- add_stdlib_integration()
-
- @unittest.skipUnless(pyver >= PY3_5, '__qualname__ requires python 3.5 or greater')
- def test_pickle_enum_function_with_qualname(self):
- Theory = Enum('Theory', 'rule law supposition', qualname='spanish_inquisition')
- globals()['spanish_inquisition'] = Theory
- test_pickle_dump_load(self.assertTrue, Theory.rule)
- test_pickle_dump_load(self.assertTrue, Theory)
-
- def test_auto_init(self):
- class Planet(Enum, init='mass radius'):
- MERCURY = (3.303e+23, 2.4397e6)
- VENUS = (4.869e+24, 6.0518e6)
- EARTH = (5.976e+24, 6.37814e6)
- MARS = (6.421e+23, 3.3972e6)
- JUPITER = (1.9e+27, 7.1492e7)
- SATURN = (5.688e+26, 6.0268e7)
- URANUS = (8.686e+25, 2.5559e7)
- NEPTUNE = (1.024e+26, 2.4746e7)
- @property
- def surface_gravity(self):
- # universal gravitational constant (m3 kg-1 s-2)
- G = 6.67300E-11
- return G * self.mass / (self.radius * self.radius)
- self.assertEqual(round(Planet.EARTH.surface_gravity, 2), 9.80)
- self.assertEqual(Planet.EARTH.value, (5.976e+24, 6.37814e6))
-
- def test_auto_init_with_value(self):
- class Color(Enum, init='value, rgb'):
- RED = 1, (1, 0, 0)
- BLUE = 2, (0, 1, 0)
- GREEN = 3, (0, 0, 1)
- self.assertEqual(Color.RED.value, 1)
- self.assertEqual(Color.BLUE.value, 2)
- self.assertEqual(Color.GREEN.value, 3)
- self.assertEqual(Color.RED.rgb, (1, 0, 0))
- self.assertEqual(Color.BLUE.rgb, (0, 1, 0))
- self.assertEqual(Color.GREEN.rgb, (0, 0, 1))
-
- def test_auto_turns_off(self):
- with self.assertRaises(NameError):
- class Color(Enum, settings=MagicValue):
- red
- green
- blue
- def hello(self):
- print('Hello! My serial is %s.' % self.value)
- rose
- with self.assertRaises(NameError):
- class Color(Enum, settings=MagicValue):
- red
- green
- blue
- def __init__(self, *args):
- pass
- rose
-
- def test_magic(self):
- class Color(Enum, settings=MagicValue):
- red, green, blue
- self.assertEqual(list(Color), [Color.red, Color.green, Color.blue])
- self.assertEqual(Color.red.value, 1)
-
- def test_ignore_not_overridden(self):
- with self.assertRaisesRegex(TypeError, 'object is not callable'):
- class Color(Flag):
- _ignore_ = 'irrelevent'
- _settings_ = MagicValue
- @property
- def shade(self):
- print('I am light', self.name.lower())
-
- def test_magic_start(self):
- class Color(Enum, settings=MagicValue, start=0):
- red, green, blue
- self.assertEqual(list(Color), [Color.red, Color.green, Color.blue])
- self.assertEqual(Color.red.value, 0)
-
- def test_dir_on_class(self):
- Season = self.Season
- self.assertEqual(
- set(dir(Season)),
- set(['__class__', '__doc__', '__members__', '__module__',
- 'SPRING', 'SUMMER', 'AUTUMN', 'WINTER',
- '__init_subclass__', '__name__', '__getitem__', '__len__',
- '__contains__', '__iter__', '__qualname__',
- ]))
-
- def test_dir_on_item(self):
- Season = self.Season
- self.assertEqual(
- set(dir(Season.WINTER)),
- set(['__class__', '__doc__', '__eq__', '__hash__', '__module__', 'name', 'value', 'values']),
- )
-
- def test_dir_with_added_behavior(self):
- class Test(Enum):
- this = 'that'
- these = 'those'
- def wowser(self):
- return ("Wowser! I'm %s!" % self.name)
- self.assertEqual(
- set(dir(Test)),
- set([
- '__class__', '__doc__', '__members__', '__module__', 'this', 'these',
- '__init_subclass__', '__name__', '__getitem__', '__len__',
- '__contains__', '__iter__', '__qualname__',
- ]))
- self.assertEqual(
- set(dir(Test.this)),
- set(['__class__', '__doc__', '__eq__', '__hash__', '__module__', 'name', 'value', 'values', 'wowser']),
- )
-
- def test_dir_on_sub_with_behavior_on_super(self):
- # see issue22506
- class SuperEnum(Enum):
- def invisible(self):
- return "did you see me?"
- class SubEnum(SuperEnum):
- sample = 5
- self.assertEqual(
- set(dir(SubEnum.sample)),
- set(['__class__', '__doc__', '__eq__', '__hash__', '__module__', 'name', 'value', 'values', 'invisible']),
- )
-
- def test_members_are_always_ordered(self):
- class AlwaysOrdered(Enum):
- first = 1
- second = 2
- third = 3
- self.assertTrue(type(AlwaysOrdered.__members__) is OrderedDict)
-
- def test_comparisons(self):
- def bad_compare():
- Season.SPRING > 4
- Season = self.Season
- self.assertNotEqual(Season.SPRING, 1)
- self.assertRaises(TypeError, bad_compare)
-
- class Part(Enum):
- SPRING = 1
- CLIP = 2
- BARREL = 3
-
- self.assertNotEqual(Season.SPRING, Part.SPRING)
- def bad_compare():
- Season.SPRING < Part.CLIP
- self.assertRaises(TypeError, bad_compare)
-
- def test_duplicate_name(self):
- with self.assertRaises(TypeError):
- class Color1(Enum):
- red = 1
- green = 2
- blue = 3
- red = 4
-
- with self.assertRaises(TypeError):
- class Color2(Enum):
- red = 1
- green = 2
- blue = 3
- def red(self):
- return 'red'
-
- with self.assertRaises(TypeError):
- class Color3(Enum):
- @property
- def red(self):
- return 'redder'
- red = 1
- green = 2
- blue = 3
-
- def test_duplicate_value_with_unique(self):
- with self.assertRaises(ValueError):
- class Color(Enum, settings=Unique):
- red = 1
- green = 2
- blue = 3
- rojo = 1
-
- def test_duplicate_value_with_noalias(self):
- class Color(Enum, settings=NoAlias):
- red = 1
- green = 2
- blue = 3
- rojo = 1
- self.assertFalse(Color.red is Color.rojo)
- self.assertEqual(Color.red.value, 1)
- self.assertEqual(Color.rojo.value, 1)
- self.assertEqual(len(Color), 4)
- self.assertEqual(list(Color), [Color.red, Color.green, Color.blue, Color.rojo])
-
- def test_noalias_value_lookup(self):
- class Color(Enum, settings=NoAlias):
- red = 1
- green = 2
- blue = 3
- rojo = 1
- self.assertRaises(TypeError, Color, 2)
-
- def test_multivalue(self):
- class Color(Enum, settings=MultiValue):
- red = 1, 'red'
- green = 2, 'green'
- blue = 3, 'blue'
- self.assertEqual(Color.red.value, 1)
- self.assertIs(Color('green'), Color.green)
- self.assertEqual(Color.blue.values, (3, 'blue'))
-
- def test_multivalue_with_duplicate_values(self):
- with self.assertRaises(ValueError):
- class Color(Enum, settings=MultiValue):
- red = 1, 'red'
- green = 2, 'green'
- blue = 3, 'blue', 'red'
-
- def test_multivalue_with_duplicate_values_and_noalias(self):
- with self.assertRaises(TypeError):
- class Color(Enum, settings=(MultiValue, NoAlias)):
- red = 1, 'red'
- green = 2, 'green'
- blue = 3, 'blue', 'red'
-
- def test_multivalue_and_auto(self):
- with self.assertRaisesRegex(TypeError, r'MultiValue and MagicValue are mutually exclusive'):
- class Color(Enum, settings=(MultiValue, MagicValue)):
- red
- green = 3, 'green'
- blue
-
- def test_autonumber_and_init(self):
- class Field(IntEnum, settings=AddValue, init='__doc__'):
- TYPE = "Char, Date, Logical, etc."
- START = "Field offset in record"
- self.assertEqual(Field.TYPE, 1)
- self.assertEqual(Field.START, 2)
- self.assertEqual(Field.TYPE.__doc__, 'Char, Date, Logical, etc.')
- self.assertEqual(Field.START.__doc__, 'Field offset in record')
- self.assertFalse(hasattr(Field, '_order_'))
-
- def test_autovalue_and_init(self):
- class Field(IntEnum, init='value __doc__'):
- TYPE = "Char, Date, Logical, etc."
- START = "Field offset in record"
- self.assertEqual(Field.TYPE, 1)
- self.assertEqual(Field.START.__doc__, 'Field offset in record')
-
- def test_autonumber_and_start(self):
- class Field(IntEnum, init='__doc__', settings=AddValue, start=0):
- TYPE = "Char, Date, Logical, etc."
- START = "Field offset in record"
- self.assertEqual(Field.TYPE, 0)
- self.assertEqual(Field.START, 1)
- self.assertEqual(Field.TYPE.__doc__, 'Char, Date, Logical, etc.')
- self.assertEqual(Field.START.__doc__, 'Field offset in record')
-
- def test_autonumber_and_init_and_some_values(self):
- class Field(IntEnum, init='value __doc__'):
- TYPE = "Char, Date, Logical, etc."
- START = "Field offset in record"
- BLAH = 5, "test blah"
- BELCH = 'test belch'
- self.assertEqual(Field.TYPE, 1)
- self.assertEqual(Field.START, 2)
- self.assertEqual(Field.BLAH, 5)
- self.assertEqual(Field.BELCH, 6)
- self.assertEqual(Field.TYPE.__doc__, 'Char, Date, Logical, etc.')
- self.assertEqual(Field.START.__doc__, 'Field offset in record')
- self.assertEqual(Field.BLAH.__doc__, 'test blah')
- self.assertEqual(Field.BELCH.__doc__, 'test belch')
-
- def test_autonumber_with_irregular_values(self):
- class Point(AutoNumberEnum, init='x y'):
- first = 7, 9
- second = 11, 13
- self.assertEqual(Point.first.value, 1)
- self.assertEqual(Point.first.x, 7)
- self.assertEqual(Point.first.y, 9)
- self.assertEqual(Point.second.value, 2)
- self.assertEqual(Point.second.x, 11)
- self.assertEqual(Point.second.y, 13)
- with self.assertRaisesRegex(TypeError, '.*number of fields provided do not match init ...x., .y.. != .3, 11, 13..'):
- class Point(AutoNumberEnum, init='x y'):
- first = 7, 9
- second = 3, 11, 13
- class Color(AutoNumberEnum, init='__doc__'):
- # interactions between AutoNumberEnum and _generate_next_value_ may not be pretty
- red = ()
- green = 'red'
- blue = ()
- self.assertTrue(Color.red.__doc__, 1)
- self.assertEqual(Color.green.__doc__, 'red')
- self.assertTrue(Color.blue.__doc__, 2)
-
- def test_autonumber_and_property(self):
- with self.assertRaises(TypeError):
- class Color(AutoEnum):
- _ignore_ = ()
- red = ()
- green = ()
- blue = ()
- @property
- def cap_name(self) -> str:
- return self.name.title()
-
- def test_autoenum(self):
- class Color(AutoEnum):
- red
- green
- blue
- self.assertEqual(list(Color), [Color.red, Color.green, Color.blue])
- self.assertEqual([m.value for m in Color], [1, 2, 3])
- self.assertEqual([m.name for m in Color], ['red', 'green', 'blue'])
-
- def test_autoenum_with_str(self):
- class Color(AutoEnum):
- def _generate_next_value_(name, start, count, last_values):
- return name
- red
- green
- blue
- self.assertEqual(list(Color), [Color.red, Color.green, Color.blue])
- self.assertEqual([m.value for m in Color], ['red', 'green', 'blue'])
- self.assertEqual([m.name for m in Color], ['red', 'green', 'blue'])
-
- def test_autoenum_and_default_ignore(self):
- class Color(AutoEnum):
- red
- green
- blue
- @property
- def cap_name(self):
- return self.name.title()
- self.assertEqual(Color.blue.cap_name, 'Blue')
-
- def test_autonumber_and_overridden_ignore(self):
- with self.assertRaises(TypeError):
- class Color(AutoEnum):
- _ignore_ = 'staticmethod'
- red
- green
- blue
- @property
- def cap_name(self) -> str:
- return self.name.title()
-
- def test_autonumber_and_multiple_assignment(self):
- class Color(AutoEnum):
- _ignore_ = 'property'
- red
- green
- blue = cyan
- @property
- def cap_name(self) -> str:
- return self.name.title()
- self.assertEqual(Color.blue.cap_name, 'Cyan')
-
- def test_multivalue_and_autonumber_inherited(self):
- class Measurement(int, Enum, settings=(MultiValue, AddValue), start=0):
- one = "20110721"
- two = "20120911"
- three = "20110518"
- M = Measurement
- self.assertEqual(M.one, 0)
- self.assertTrue(M.one is M(0) is M('20110721'))
-
- def test_combine_new_settings_with_old_settings(self):
- class Auto(Enum, settings=Unique):
- pass
- with self.assertRaises(ValueError):
- class AutoUnique(Auto, settings=MagicValue):
- BLAH
- BLUH
- ICK = 1
-
- def test_timedelta(self):
- class Period(timedelta, Enum):
- '''
- different lengths of time
- '''
- _init_ = 'value period'
- _settings_ = NoAlias
- _ignore_ = 'Period i'
- Period = vars()
- for i in range(31):
- Period['day_%d' % i] = i, 'day'
- for i in range(15):
- Period['week_%d' % i] = i*7, 'week'
- for i in range(12):
- Period['month_%d' % i] = i*30, 'month'
- OneDay = day_1
- OneWeek = week_1
- self.assertFalse(hasattr(Period, '_ignore_'))
- self.assertFalse(hasattr(Period, 'Period'))
- self.assertFalse(hasattr(Period, 'i'))
- self.assertTrue(isinstance(Period.day_1, timedelta))
-
- def test_extend_enum_plain(self):
- class Color(UniqueEnum):
- red = 1
- green = 2
- blue = 3
- extend_enum(Color, 'brown', 4)
- self.assertEqual(Color.brown.name, 'brown')
- self.assertEqual(Color.brown.value, 4)
- self.assertTrue(Color.brown in Color)
- self.assertEqual(len(Color), 4)
-
- def test_extend_enum_shadow(self):
- class Color(UniqueEnum):
- red = 1
- green = 2
- blue = 3
- extend_enum(Color, 'value', 4)
- self.assertEqual(Color.value.name, 'value')
- self.assertEqual(Color.value.value, 4)
- self.assertTrue(Color.value in Color)
- self.assertEqual(len(Color), 4)
- self.assertEqual(Color.red.value, 1)
-
- def test_extend_enum_generate(self):
- class Foo(AutoEnum):
- def _generate_next_value_(name, start, count, values, *args, **kwds):
- return name
- a
- b
- #
- extend_enum(Foo, 'c')
- self.assertEqual(Foo.a.value, 'a')
- self.assertEqual(Foo.b.value, 'b')
- self.assertEqual(Foo.c.value, 'c')
-
- def test_extend_enum_unique_with_duplicate(self):
- with self.assertRaises(ValueError):
- class Color(Enum, settings=Unique):
- red = 1
- green = 2
- blue = 3
- extend_enum(Color, 'value', 1)
-
- def test_extend_enum_multivalue_with_duplicate(self):
- with self.assertRaises(ValueError):
- class Color(Enum, settings=MultiValue):
- red = 1, 'rojo'
- green = 2, 'verde'
- blue = 3, 'azul'
- extend_enum(Color, 'value', 2)
-
- def test_extend_enum_noalias_with_duplicate(self):
- class Color(Enum, settings=NoAlias):
- red = 1
- green = 2
- blue = 3
- extend_enum(Color, 'value', 3, )
- self.assertRaises(TypeError, Color, 3)
- self.assertFalse(Color.value is Color.blue)
- self.assertTrue(Color.value.value, 3)
-
- def test_no_duplicates(self):
- def bad_duplicates():
- class Color(UniqueEnum):
- red = 1
- green = 2
- blue = 3
- class Color(UniqueEnum):
- red = 1
- green = 2
- blue = 3
- grene = 2
- self.assertRaises(ValueError, bad_duplicates)
-
- def test_no_duplicates_kinda(self):
- class Silly(UniqueEnum):
- one = 1
- two = 'dos'
- name = 3
- class Sillier(IntEnum, UniqueEnum):
- single = 1
- name = 2
- triple = 3
- value = 4
-
- def test_auto_number(self):
- class Color(Enum, settings=MagicValue):
- red
- blue
- green
-
- self.assertEqual(list(Color), [Color.red, Color.blue, Color.green])
- self.assertEqual(Color.red.value, 1)
- self.assertEqual(Color.blue.value, 2)
- self.assertEqual(Color.green.value, 3)
-
- def test_auto_name(self):
- class Color(Enum, settings=MagicValue):
- def _generate_next_value_(name, start, count, last):
- return name
- red
- blue
- green
-
- self.assertEqual(list(Color), [Color.red, Color.blue, Color.green])
- self.assertEqual(Color.red.value, 'red')
- self.assertEqual(Color.blue.value, 'blue')
- self.assertEqual(Color.green.value, 'green')
-
- def test_auto_name_inherit(self):
- class AutoNameEnum(Enum):
- def _generate_next_value_(name, start, count, last):
- return name
- class Color(AutoNameEnum, settings=MagicValue):
- red
- blue
- green
-
- self.assertEqual(list(Color), [Color.red, Color.blue, Color.green])
- self.assertEqual(Color.red.value, 'red')
- self.assertEqual(Color.blue.value, 'blue')
- self.assertEqual(Color.green.value, 'green')
-
- def test_auto_garbage(self):
- class Color(Enum):
- _settings_ = MagicValue
- red = 'red'
- blue
- self.assertEqual(Color.blue.value, 1)
-
- def test_auto_garbage_corrected(self):
- class Color(Enum, settings=MagicValue):
- red = 'red'
- blue = 2
- green
-
- self.assertEqual(list(Color), [Color.red, Color.blue, Color.green])
- self.assertEqual(Color.red.value, 'red')
- self.assertEqual(Color.blue.value, 2)
- self.assertEqual(Color.green.value, 3)
-
- def test_duplicate_auto(self):
- class Dupes(Enum, settings=MagicValue):
- first = primero
- second
- third
- self.assertEqual([Dupes.first, Dupes.second, Dupes.third], list(Dupes))
-
- def test_order_as_function(self):
- # first with _init_
- class TestSequence(Enum):
- _init_ = 'value, sequence'
- _order_ = lambda member: member.sequence
- item_id = 'An$(1,6)', 0 # Item Code
- company_id = 'An$(7,2)', 1 # Company Code
- warehouse_no = 'An$(9,4)', 2 # Warehouse Number
- company = 'Hn$(13,6)', 3 # 4 SPACES + COMPANY
- key_type = 'Cn$(19,3)', 4 # Key Type = '1**'
- available = 'Zn$(1,1)', 5 # Available?
- contract_item = 'Bn(2,1)', 6 # Contract Item?
- sales_category = 'Fn', 7 # Sales Category
- gl_category = 'Rn$(5,1)', 8 # G/L Category
- warehouse_category = 'Sn$(6,1)', 9 # Warehouse Category
- inv_units = 'Qn$(7,2)', 10 # Inv Units
- for i, member in enumerate(TestSequence):
- self.assertEqual(i, member.sequence)
- ts = TestSequence
- self.assertEqual(ts.item_id.name, 'item_id')
- self.assertEqual(ts.item_id.value, 'An$(1,6)')
- self.assertEqual(ts.item_id.sequence, 0)
- self.assertEqual(ts.company_id.name, 'company_id')
- self.assertEqual(ts.company_id.value, 'An$(7,2)')
- self.assertEqual(ts.company_id.sequence, 1)
- self.assertEqual(ts.warehouse_no.name, 'warehouse_no')
- self.assertEqual(ts.warehouse_no.value, 'An$(9,4)')
- self.assertEqual(ts.warehouse_no.sequence, 2)
- self.assertEqual(ts.company.name, 'company')
- self.assertEqual(ts.company.value, 'Hn$(13,6)')
- self.assertEqual(ts.company.sequence, 3)
- self.assertEqual(ts.key_type.name, 'key_type')
- self.assertEqual(ts.key_type.value, 'Cn$(19,3)')
- self.assertEqual(ts.key_type.sequence, 4)
- self.assertEqual(ts.available.name, 'available')
- self.assertEqual(ts.available.value, 'Zn$(1,1)')
- self.assertEqual(ts.available.sequence, 5)
- self.assertEqual(ts.contract_item.name, 'contract_item')
- self.assertEqual(ts.contract_item.value, 'Bn(2,1)')
- self.assertEqual(ts.contract_item.sequence, 6)
- self.assertEqual(ts.sales_category.name, 'sales_category')
- self.assertEqual(ts.sales_category.value, 'Fn')
- self.assertEqual(ts.sales_category.sequence, 7)
- self.assertEqual(ts.gl_category.name, 'gl_category')
- self.assertEqual(ts.gl_category.value, 'Rn$(5,1)')
- self.assertEqual(ts.gl_category.sequence, 8)
- self.assertEqual(ts.warehouse_category.name, 'warehouse_category')
- self.assertEqual(ts.warehouse_category.value, 'Sn$(6,1)')
- self.assertEqual(ts.warehouse_category.sequence, 9)
- self.assertEqual(ts.inv_units.name, 'inv_units')
- self.assertEqual(ts.inv_units.value, 'Qn$(7,2)')
- self.assertEqual(ts.inv_units.sequence, 10)
- # and then without
- class TestSequence(Enum):
- _order_ = lambda member: member.value[1]
- item_id = 'An$(1,6)', 0 # Item Code
- company_id = 'An$(7,2)', 1 # Company Code
- warehouse_no = 'An$(9,4)', 2 # Warehouse Number
- company = 'Hn$(13,6)', 3 # 4 SPACES + COMPANY
- key_type = 'Cn$(19,3)', 4 # Key Type = '1**'
- available = 'Zn$(1,1)', 5 # Available?
- contract_item = 'Bn(2,1)', 6 # Contract Item?
- sales_category = 'Fn', 7 # Sales Category
- gl_category = 'Rn$(5,1)', 8 # G/L Category
- warehouse_category = 'Sn$(6,1)', 9 # Warehouse Category
- inv_units = 'Qn$(7,2)', 10 # Inv Units
- for i, member in enumerate(TestSequence):
- self.assertEqual(i, member.value[1])
- ts = TestSequence
- self.assertEqual(ts.item_id.name, 'item_id')
- self.assertEqual(ts.item_id.value, ('An$(1,6)', 0))
- self.assertEqual(ts.company_id.name, 'company_id')
- self.assertEqual(ts.company_id.value, ('An$(7,2)', 1))
- self.assertEqual(ts.warehouse_no.name, 'warehouse_no')
- self.assertEqual(ts.warehouse_no.value, ('An$(9,4)', 2))
- self.assertEqual(ts.company.name, 'company')
- self.assertEqual(ts.company.value, ('Hn$(13,6)', 3))
- self.assertEqual(ts.key_type.name, 'key_type')
- self.assertEqual(ts.key_type.value, ('Cn$(19,3)', 4))
- self.assertEqual(ts.available.name, 'available')
- self.assertEqual(ts.available.value, ('Zn$(1,1)', 5))
- self.assertEqual(ts.contract_item.name, 'contract_item')
- self.assertEqual(ts.contract_item.value, ('Bn(2,1)', 6))
- self.assertEqual(ts.sales_category.name, 'sales_category')
- self.assertEqual(ts.sales_category.value, ('Fn', 7))
- self.assertEqual(ts.gl_category.name, 'gl_category')
- self.assertEqual(ts.gl_category.value, ('Rn$(5,1)', 8))
- self.assertEqual(ts.warehouse_category.name, 'warehouse_category')
- self.assertEqual(ts.warehouse_category.value, ('Sn$(6,1)', 9))
- self.assertEqual(ts.inv_units.name, 'inv_units')
- self.assertEqual(ts.inv_units.value, ('Qn$(7,2)', 10))
- # then with _init_ but without value
- with self.assertRaises(TypeError):
- class TestSequence(Enum):
- _init_ = 'sequence'
- _order_ = lambda member: member.sequence
- item_id = 'An$(1,6)', 0 # Item Code
- company_id = 'An$(7,2)', 1 # Company Code
- warehouse_no = 'An$(9,4)', 2 # Warehouse Number
- company = 'Hn$(13,6)', 3 # 4 SPACES + COMPANY
- key_type = 'Cn$(19,3)', 4 # Key Type = '1**'
- available = 'Zn$(1,1)', 5 # Available?
- contract_item = 'Bn(2,1)', 6 # Contract Item?
- sales_category = 'Fn', 7 # Sales Category
- gl_category = 'Rn$(5,1)', 8 # G/L Category
- warehouse_category = 'Sn$(6,1)', 9 # Warehouse Category
- inv_units = 'Qn$(7,2)', 10 # Inv Units
- # finally, out of order so Python 3 barfs
- with self.assertRaises(TypeError):
- class TestSequence(Enum):
- _init_ = 'sequence'
- _order_ = lambda member: member.sequence
- item_id = 'An$(1,6)', 0 # Item Code
- warehouse_no = 'An$(9,4)', 2 # Warehouse Number
- company = 'Hn$(13,6)', 3 # 4 SPACES + COMPANY
- company_id = 'An$(7,2)', 1 # Company Code
- inv_units = 'Qn$(7,2)', 10 # Inv Units
- available = 'Zn$(1,1)', 5 # Available?
- contract_item = 'Bn(2,1)', 6 # Contract Item?
- sales_category = 'Fn', 7 # Sales Category
- key_type = 'Cn$(19,3)', 4 # Key Type = '1**'
- gl_category = 'Rn$(5,1)', 8 # G/L Category
- warehouse_category = 'Sn$(6,1)', 9 # Warehouse Category
-
- if pyver >= PY3_3:
- def test_missing(self):
- class Color(Enum):
- red = 1
- green = 2
- blue = 3
- @classmethod
- def _missing_(cls, item):
- if item == 'three':
- return cls.blue
- elif item == 'bad return':
- # trigger internal error
- return 5
- elif item == 'error out':
- raise ZeroDivisionError
- else:
- # trigger not found
- return None
- self.assertIs(Color('three'), Color.blue)
- self.assertRaises(ValueError, Color, 7)
- try:
- Color('bad return')
- except TypeError as exc:
- self.assertTrue(isinstance(exc.__cause__, ValueError))
- else:
- raise Exception('Exception not raised.')
- try:
- Color('error out')
- except ZeroDivisionError as exc:
- self.assertTrue(isinstance(exc.__cause__, ValueError))
- else:
- raise Exception('Exception not raised.')
-
- def test_enum_of_types(self):
- """Support using Enum to refer to types deliberately."""
- class MyTypes(Enum):
- i = int
- f = float
- s = str
- self.assertEqual(MyTypes.i.value, int)
- self.assertEqual(MyTypes.f.value, float)
- self.assertEqual(MyTypes.s.value, str)
- class Foo:
- pass
- class Bar:
- pass
- class MyTypes2(Enum):
- a = Foo
- b = Bar
- self.assertEqual(MyTypes2.a.value, Foo)
- self.assertEqual(MyTypes2.b.value, Bar)
- class SpamEnumNotInner:
- pass
- class SpamEnum(Enum):
- spam = SpamEnumNotInner
- self.assertEqual(SpamEnum.spam.value, SpamEnumNotInner)
-
- def test_nested_classes_in_enum_do_not_create_members(self):
- """Support locally-defined nested classes."""
- # manually set __qualname__ to remove testing framework noise
- class Outer(Enum):
- __qualname__ = "Outer"
- a = 1
- b = 2
- class Inner(Enum):
- __qualname__ = "Outer.Inner"
- foo = 10
- bar = 11
- self.assertTrue(isinstance(Outer.Inner, type))
- self.assertEqual(Outer.a.value, 1)
- self.assertEqual(Outer.Inner.foo.value, 10)
- self.assertEqual(
- list(Outer.Inner),
- [Outer.Inner.foo, Outer.Inner.bar],
- )
- self.assertEqual(
- list(Outer),
- [Outer.a, Outer.b],
- )
-
- if pyver == PY3_4:
- def test_class_nested_enum_and_pickle_protocol_four(self):
- # would normally just have this directly in the class namespace
- class NestedEnum(Enum):
- twigs = 'common'
- shiny = 'rare'
-
- self.__class__.NestedEnum = NestedEnum
- self.NestedEnum.__qualname__ = '%s.NestedEnum' % self.__class__.__name__
- test_pickle_exception(
- self.assertRaises, PicklingError, self.NestedEnum.twigs,
- protocol=(0, 3))
- test_pickle_dump_load(self.assertTrue, self.NestedEnum.twigs,
- protocol=(4, HIGHEST_PROTOCOL))
-
- elif pyver >= PY3_5:
- def test_class_nested_enum_and_pickle_protocol_four(self):
- # would normally just have this directly in the class namespace
- class NestedEnum(Enum):
- twigs = 'common'
- shiny = 'rare'
-
- self.__class__.NestedEnum = NestedEnum
- self.NestedEnum.__qualname__ = '%s.NestedEnum' % self.__class__.__name__
- test_pickle_dump_load(self.assertTrue, self.NestedEnum.twigs,
- protocol=(0, HIGHEST_PROTOCOL))
-
- if pyver >= PY3_4:
- def test_enum_injection(self):
- class Color(Enum):
- _order_ = 'BLACK WHITE'
- BLACK = Color('black', '#000')
- WHITE = Color('white', '#fff')
-
- def __init__(self, label, hex):
- self.label = label
- self.hex = hex
-
- self.assertEqual([Color.BLACK, Color.WHITE], list(Color))
- self.assertEqual(Color.WHITE.hex, '#fff')
- self.assertEqual(Color.BLACK.label, 'black')
-
- def test_subclasses_with_getnewargs_ex(self):
- class NamedInt(int):
- __qualname__ = 'NamedInt' # needed for pickle protocol 4
- def __new__(cls, *args):
- _args = args
- if len(args) < 2:
- raise TypeError("name and value must be specified")
- name, args = args[0], args[1:]
- self = int.__new__(cls, *args)
- self._intname = name
- self._args = _args
- return self
- def __getnewargs_ex__(self):
- return self._args, {}
- @property
- def __name__(self):
- return self._intname
- def __repr__(self):
- # repr() is updated to include the name and type info
- return "{}({!r}, {})".format(type(self).__name__,
- self.__name__,
- int.__repr__(self))
- def __str__(self):
- # str() is unchanged, even if it relies on the repr() fallback
- base = int
- base_str = base.__str__
- if base_str.__objclass__ is object:
- return base.__repr__(self)
- return base_str(self)
- # for simplicity, we only define one operator that
- # propagates expressions
- def __add__(self, other):
- temp = int(self) + int( other)
- if isinstance(self, NamedInt) and isinstance(other, NamedInt):
- return NamedInt(
- '({0} + {1})'.format(self.__name__, other.__name__),
- temp )
- else:
- return temp
-
- class NEI(NamedInt, Enum):
- __qualname__ = 'NEI' # needed for pickle protocol 4
- x = ('the-x', 1)
- y = ('the-y', 2)
-
-
- self.assertIs(NEI.__new__, Enum.__new__)
- self.assertEqual(repr(NEI.x + NEI.y), "NamedInt('(the-x + the-y)', 3)")
- globals()['NamedInt'] = NamedInt
- globals()['NEI'] = NEI
- NI5 = NamedInt('test', 5)
- self.assertEqual(NI5, 5)
- test_pickle_dump_load(self.assertEqual, NI5, 5, protocol=(4, HIGHEST_PROTOCOL))
- self.assertEqual(NEI.y.value, 2)
- test_pickle_dump_load(self.assertTrue, NEI.y, protocol=(4, HIGHEST_PROTOCOL))
-
-
-class TestOrderV3(TestCase):
- """
- Test definition order versus _order_ order.
- """
-
- def test_same_members(self):
- class Color(Enum):
- _order_ = 'red green blue'
- red = 1
- green = 2
- blue = 3
-
- def test_same_members_with_aliases(self):
- class Color(Enum):
- _order_ = 'red green blue'
- red = 1
- green = 2
- blue = 3
- verde = green
-
- def test_same_members_wrong_order(self):
- with self.assertRaisesRegex(TypeError, 'member order does not match _order_'):
- class Color(Enum):
- _order_ = 'red green blue'
- red = 1
- blue = 3
- green = 2
-
- def test_order_has_extra_members(self):
- with self.assertRaisesRegex(TypeError, 'member order does not match _order_'):
- class Color(Enum):
- _order_ = 'red green blue purple'
- red = 1
- green = 2
- blue = 3
-
- def test_order_has_extra_members_with_aliases(self):
- with self.assertRaisesRegex(TypeError, 'member order does not match _order_'):
- class Color(Enum):
- _order_ = 'red green blue purple'
- red = 1
- green = 2
- blue = 3
- verde = green
-
- def test_enum_has_extra_members(self):
- with self.assertRaisesRegex(TypeError, 'member order does not match _order_'):
- class Color(Enum):
- _order_ = 'red green blue'
- red = 1
- green = 2
- blue = 3
- purple = 4
-
- def test_enum_has_extra_members_with_aliases(self):
- with self.assertRaisesRegex(TypeError, 'member order does not match _order_'):
- class Color(Enum):
- _order_ = 'red green blue'
- red = 1
- green = 2
- blue = 3
- purple = 4
- verde = green
-
- def test_same_members_flag(self):
- class Color(Flag):
- _order_ = 'red green blue'
- red = 1
- green = 2
- blue = 4
-
- def test_same_members_with_aliases_flag(self):
- class Color(Flag):
- _order_ = 'red green blue'
- red = 1
- green = 2
- blue = 4
- verde = green
-
- def test_same_members_wrong_order_falg(self):
- with self.assertRaisesRegex(TypeError, 'member order does not match _order_'):
- class Color(Flag):
- _order_ = 'red green blue'
- red = 1
- blue = 4
- green = 2
-
- def test_order_has_extra_members_flag(self):
- with self.assertRaisesRegex(TypeError, 'member order does not match _order_'):
- class Color(Flag):
- _order_ = 'red green blue purple'
- red = 1
- green = 2
- blue = 4
-
- def test_order_has_extra_members_with_aliases_flag(self):
- with self.assertRaisesRegex(TypeError, 'member order does not match _order_'):
- class Color(Flag):
- _order_ = 'red green blue purple'
- red = 1
- green = 2
- blue = 4
- verde = green
-
- def test_enum_has_extra_members_flag(self):
- with self.assertRaisesRegex(TypeError, 'member order does not match _order_'):
- class Color(Flag):
- _order_ = 'red green blue'
- red = 1
- green = 2
- blue = 4
- purple = 8
-
- def test_enum_has_extra_members_with_aliases_flag(self):
- with self.assertRaisesRegex(TypeError, 'member order does not match _order_'):
- class Color(Flag):
- _order_ = 'red green blue'
- red = 1
- green = 2
- blue = 4
- purple = 8
- verde = green
-
-
-class TestNamedTupleV3(TestCase):
-
- def test_fixed_size(self):
- class Book(NamedTuple, size=TupleSize.fixed):
- title = 0
- author = 1
- genre = 2
- b = Book('Teckla', 'Steven Brust', 'fantasy')
- self.assertTrue('Teckla' in b)
- self.assertTrue('Steven Brust' in b)
- self.assertTrue('fantasy' in b)
- self.assertEqual(b.title, 'Teckla')
- self.assertEqual(b.author, 'Steven Brust')
- self.assertRaises(TypeError, Book, 'Teckla', 'Steven Brust')
- self.assertRaises(TypeError, Book, 'Teckla')
-
- def test_minimum_size(self):
- class Book(NamedTuple, size=TupleSize.minimum):
- title = 0
- author = 1
- b = Book('Teckla', 'Steven Brust', 'fantasy')
- self.assertTrue('Teckla' in b)
- self.assertTrue('Steven Brust' in b)
- self.assertTrue('fantasy' in b)
- self.assertEqual(b.title, 'Teckla')
- self.assertEqual(b.author, 'Steven Brust')
- self.assertEqual(b[2], 'fantasy')
- b = Book('Teckla', 'Steven Brust')
- self.assertTrue('Teckla' in b)
- self.assertTrue('Steven Brust' in b)
- self.assertEqual(b.title, 'Teckla')
- self.assertEqual(b.author, 'Steven Brust')
- self.assertRaises(TypeError, Book, 'Teckla')
-
- def test_variable_size(self):
- class Book(NamedTuple, size=TupleSize.variable):
- title = 0
- author = 1
- genre = 2
- b = Book('Teckla', 'Steven Brust', 'fantasy')
- self.assertTrue('Teckla' in b)
- self.assertTrue('Steven Brust' in b)
- self.assertTrue('fantasy' in b)
- self.assertEqual(b.title, 'Teckla')
- self.assertEqual(b.author, 'Steven Brust')
- self.assertEqual(b.genre, 'fantasy')
- b = Book('Teckla', 'Steven Brust')
- self.assertTrue('Teckla' in b)
- self.assertTrue('Steven Brust' in b)
- self.assertEqual(b.title, 'Teckla')
- self.assertEqual(b.author, 'Steven Brust')
- self.assertRaises(AttributeError, getattr, b, 'genre')
- self.assertRaises(TypeError, Book, title='Teckla', genre='fantasy')
- self.assertRaises(TypeError, Book, author='Steven Brust')
-
-
-
-class TestStackoverflowAnswersV3(TestCase):
-
- def test_self_referential_directions(self):
- # https://stackoverflow.com/a/64000706/208880
- class Directions(Enum):
- #
- NORTH = 1, 0
- WEST = 0, 1
- SOUTH = -1, 0
- EAST = 0, -1
- #
- def __init__(self, x, y):
- self.x = x
- self.y = y
- if len(self.__class__):
- # make links
- all = list(self.__class__)
- left, right = all[0], all[-1]
- self.left = left
- self.right = right
- left.right = self
- right.left = self
- #
- D = Directions
- self.assertEqual(D.NORTH.value, (1, 0))
- self.assertTrue(D.NORTH.left is D.WEST)
- self.assertTrue(D.SOUTH.right is D.WEST)
-
- def test_self_referential_rock_paper_scissors(self):
- # https://stackoverflow.com/a/57085357/208880
- class RPS(Enum):
- #
- Rock = "rock"
- Paper = "paper"
- Scissors = "scissors"
- #
- def __init__(self, value):
- if len(self.__class__):
- # make links
- all = list(self.__class__)
- first, previous = all[0], all[-1]
- first.beats = self
- self.beats = previous
- #
- self.assertTrue(RPS.Rock.beats is RPS.Scissors)
- self.assertTrue(RPS.Scissors.beats is RPS.Paper)
- self.assertTrue(RPS.Paper.beats is RPS.Rock)
-
- def test_arduino_headers(self):
- # https://stackoverflow.com/q/65048495/208880
- class CHeader(Enum):
- def __init_subclass__(cls, **kwds):
- # write Enums to C header file
- cls_name = cls.__name__
- header_path = getattr(cls, '_%s__header' % cls_name)
- with open(header_path, 'w') as fh:
- fh.write('initial header stuff here\n')
- for enum in cls:
- fh.write('#define %s %r\n' % (enum.name, enum.value))
- class Arduino(CHeader):
- __header = os.path.join(tempdir, 'arduino.h')
- ONE = 1
- TWO = 2
- with open(os.path.join(tempdir, 'arduino.h')) as fh:
- data = fh.read()
- self.assertEqual(textwrap.dedent("""\
- initial header stuff here
- #define ONE 1
- #define TWO 2
- """),
- data,
- )
-
- def test_create_C_like_Enum(self):
- # https://stackoverflow.com/a/35965438/208880
- class Id(Enum, settings=MagicValue, start=0):
- #
- NONE # 0x0
- HEARTBEAT # 0x1
- FLUID_TRANSFER_REQUEST
- FLUID_TRANSFER_STATUS_MSG
- FLUID_TRANSFER_ERROR_MSG
- # ...
- #
- # Camera App Messages
- START_SENDING_PICTURES = 0x010000
- STOP_SENDING_PICTURES
- START_RECORDING_VIDEO_REQ
- STOP_RECORDING_VIDEO_REQ
- # ...
- #
- # Sensor Calibration
- VOLUME_REQUEST = 0x020000
- START_CAL
- CLI_COMMAND_REQUEST
- CLI_COMMAND_RESPONSE
- #
- # File Mananger
- NEW_DELIVERY_REQ = 0x30000
- GET_DELIVERY_FILE_REQ
- GET_FILE_REQ
- #
- ACK_NACK
- RESPONSE
- #
- LAST_ID
- #
- self.assertEqual(Id.NONE.value, 0)
- self.assertEqual(Id.FLUID_TRANSFER_ERROR_MSG.value, 4)
- self.assertEqual(Id.START_SENDING_PICTURES.value, 0x010000)
- self.assertEqual(Id.STOP_RECORDING_VIDEO_REQ.value, 0x010003)
- self.assertEqual(Id.START_CAL.value, 0x020001)
- self.assertEqual(Id.LAST_ID.value, 0x30005)
-
-
- @unittest.skipUnless(pyparsing, 'pyparsing not installed')
- def test_c_header_scanner(self):
- # https://stackoverflow.com/questions/58732872/208880
- with open(os.path.join(tempdir, 'c_plus_plus.h'), 'w') as fh:
- fh.write("""
- stuff before
- enum hello {
- Zero,
- One,
- Two,
- Three,
- Five=5,
- Six,
- Ten=10
- };
- in the middle
- enum blah
- {
- alpha,
- beta,
- gamma = 10 ,
- zeta = 50
- };
- at the end
- """)
- from pyparsing import Group, Optional, Suppress, Word, ZeroOrMore
- from pyparsing import alphas, alphanums, nums
- #
- CPPEnum = None
- class CPPEnumType(EnumMeta):
- #
- @classmethod
- def __prepare__(metacls, clsname, bases, **kwds):
- # return a standard dictionary for the initial processing
- return {}
- #
- def __init__(clsname, *args , **kwds):
- super(CPPEnumType, clsname).__init__(*args)
- #
- def __new__(metacls, clsname, bases, clsdict, **kwds):
- if CPPEnum is None:
- # first time through, ignore the rest
- enum_dict = super(CPPEnumType, metacls).__prepare__(clsname, bases, **kwds)
- enum_dict.update(clsdict)
- return super(CPPEnumType, metacls).__new__(metacls, clsname, bases, enum_dict, **kwds)
- members = []
- #
- # remove _file and _name using `pop()` as they will cause problems in EnumMeta
- try:
- file = clsdict.pop('_file')
- except KeyError:
- raise TypeError('_file not specified')
- cpp_enum_name = clsdict.pop('_name', clsname.lower())
- with open(file) as fh:
- file_contents = fh.read()
- #
- # syntax we don't want to see in the final parse tree
- LBRACE, RBRACE, EQ, COMMA = map(Suppress, "{}=,")
- _enum = Suppress("enum")
- identifier = Word(alphas, alphanums + "_")
- integer = Word(nums)
- enumValue = Group(identifier("name") + Optional(EQ + integer("value")))
- enumList = Group(enumValue + ZeroOrMore(COMMA + enumValue))
- enum = _enum + identifier("enum") + LBRACE + enumList("names") + RBRACE
- #
- # find the cpp_enum_name ignoring other syntax and other enums
- for item, start, stop in enum.scanString(file_contents):
- if item.enum != cpp_enum_name:
- continue
- id = 0
- for entry in item.names:
- if entry.value != "":
- id = int(entry.value)
- members.append((entry.name.upper(), id))
- id += 1
- #
- # get the real EnumDict
- enum_dict = super(CPPEnumType, metacls).__prepare__(clsname, bases, **kwds)
- # transfer the original dict content, names starting with '_' first
- items = list(clsdict.items())
- items.sort(key=lambda p: (0 if p[0][0] == '_' else 1, p))
- for name, value in items:
- enum_dict[name] = value
- # add the members
- for name, value in members:
- enum_dict[name] = value
- return super(CPPEnumType, metacls).__new__(metacls, clsname, bases, enum_dict, **kwds)
- #
- class CPPEnum(IntEnum, metaclass=CPPEnumType):
- pass
- #
- class Hello(CPPEnum):
- _file = os.path.join(tempdir, 'c_plus_plus.h')
- #
- class Blah(CPPEnum):
- _file = os.path.join(tempdir, 'c_plus_plus.h')
- _name = 'blah'
- #
- self.assertEqual(
- list(Hello),
- [Hello.ZERO, Hello.ONE, Hello.TWO, Hello.THREE, Hello.FIVE, Hello.SIX, Hello.TEN],
- )
- self.assertEqual(Hello.ZERO.value, 0)
- self.assertEqual(Hello.THREE.value, 3)
- self.assertEqual(Hello.SIX.value, 6)
- self.assertEqual(Hello.TEN.value, 10)
- #
- self.assertEqual(
- list(Blah),
- [Blah.ALPHA, Blah.BETA, Blah.GAMMA, Blah.ZETA],
- )
- self.assertEqual(Blah.ALPHA.value, 0)
- self.assertEqual(Blah.BETA.value, 1)
- self.assertEqual(Blah.GAMMA.value, 10)
- self.assertEqual(Blah.ZETA.value, 50)
-
-class TestIssuesV3(TestCase):
- """
- Problems that were stated in issues.
- """
-
- def test_auto_multi_int_1(self):
- class Measurement(int, AddValueEnum, MultiValueEnum, start=0):
- one = "20110721"
- two = "20120911"
- three = "20110518"
- self.assertEqual([m.value for m in Measurement], [0, 1, 2])
- self.assertEqual([m.name for m in Measurement], ['one', 'two', 'three'])
- self.assertIs(Measurement(0), Measurement.one)
- self.assertIs(Measurement('20110721'), Measurement.one)
- self.assertIs(Measurement(1), Measurement.two)
- self.assertIs(Measurement('20120911'), Measurement.two)
- self.assertIs(Measurement(2), Measurement.three)
- self.assertIs(Measurement('20110518'), Measurement.three)
-
- def test_auto_multi_int_2(self):
- class Measurement(int, Enum, settings=(MultiValue, AddValue), start=0):
- one = "20110721"
- two = "20120911"
- three = "20110518"
- self.assertEqual([m.value for m in Measurement], [0, 1, 2])
- self.assertEqual([m.name for m in Measurement], ['one', 'two', 'three'])
- self.assertIs(Measurement(0), Measurement.one)
- self.assertIs(Measurement('20110721'), Measurement.one)
- self.assertIs(Measurement(1), Measurement.two)
- self.assertIs(Measurement('20120911'), Measurement.two)
- self.assertIs(Measurement(2), Measurement.three)
- self.assertIs(Measurement('20110518'), Measurement.three)
-
- def test_extend_enum_with_init(self):
- class Color(Enum, settings=MultiValue, init='foo bar'):
- red = '1', 'yes'
- green = '2', 'no'
- blue = '3', 'maybe'
- self.assertEqual(Color.red.value, '1')
- self.assertEqual(Color.red.foo, '1')
- self.assertEqual(Color.red.bar, 'yes')
- extend_enum(Color, 'opacity', '4', 'never')
- self.assertEqual(list(Color), [Color.red, Color.green, Color.blue, Color.opacity])
- self.assertEqual(Color.opacity.value, '4')
- self.assertEqual(Color.opacity.name, 'opacity')
- self.assertTrue(Color('4') is Color.opacity)
- self.assertTrue(Color('never') is Color.opacity)
-
-class TestExtendEnumV3(TestCase):
-
- def test_extend_enum_plain(self):
- class Color(Enum):
- red = 1
- green = 2
- blue = 3
- self.assertRaisesRegex(TypeError, '.blue. already in use as property..Color.blue: 3.', extend_enum, Color, 'blue', 5)
- #
- extend_enum(Color, 'brown', 4)
- self.assertEqual(Color.brown.name, 'brown')
- self.assertEqual(Color.brown.value, 4)
- self.assertTrue(Color.brown in Color)
- self.assertEqual(Color(4), Color.brown)
- self.assertEqual(Color['brown'], Color.brown)
- self.assertEqual(len(Color), 4)
- #
- extend_enum(Color, 'mauve')
- self.assertEqual(Color.mauve.name, 'mauve')
- self.assertEqual(Color.mauve.value, 5)
- self.assertTrue(Color.mauve in Color)
- self.assertEqual(Color(5), Color.mauve)
- self.assertEqual(Color['mauve'], Color.mauve)
- self.assertEqual(len(Color), 5)
-
- def test_extend_enum_alias(self):
- class Color(Enum):
- red = 1
- green = 2
- blue = 3
- extend_enum(Color, 'rojo', 1)
- self.assertEqual(Color.rojo.name, 'red')
- self.assertEqual(Color.rojo.value, 1)
- self.assertTrue(Color.rojo in Color)
- self.assertEqual(Color(1), Color.rojo)
- self.assertEqual(Color['rojo'], Color.red)
- self.assertEqual(len(Color), 3)
-
- def test_extend_enum_unique(self):
- class Color(UniqueEnum):
- red = 1
- green = 2
- blue = 3
- self.assertRaisesRegex(ValueError, r'<Color.rojo: 1> is a duplicate of <Color.red: 1>', extend_enum, Color, 'rojo', 1)
- #
- self.assertEqual(Color.red.name, 'red')
- self.assertEqual(Color.red.value, 1)
- self.assertTrue(Color.red in Color)
- self.assertEqual(Color(1), Color.red)
- self.assertEqual(Color['red'], Color.red)
- self.assertEqual(Color.green.name, 'green')
- self.assertEqual(Color.green.value, 2)
- self.assertTrue(Color.green in Color)
- self.assertEqual(Color(2), Color.green)
- self.assertEqual(Color['blue'], Color.blue)
- self.assertEqual(Color.blue.name, 'blue')
- self.assertEqual(Color.blue.value, 3)
- self.assertTrue(Color.blue in Color)
- self.assertEqual(Color(3), Color.blue)
- self.assertEqual(len(Color), 3)
- #
- extend_enum(Color, 'brown', 4)
- self.assertEqual(Color.brown.name, 'brown')
- self.assertEqual(Color.brown.value, 4)
- self.assertTrue(Color.brown in Color)
- self.assertEqual(Color(4), Color.brown)
- self.assertEqual(Color['brown'], Color.brown)
- self.assertEqual(len(Color), 4)
- #
- self.assertRaisesRegex(ValueError, '<Color.verde: 2> is a duplicate of <Color.green: 2>', extend_enum, Color, 'verde', 2)
- #
- extend_enum(Color, 'mauve')
- self.assertEqual(Color.mauve.name, 'mauve')
- self.assertEqual(Color.mauve.value, 5)
- self.assertTrue(Color.mauve in Color)
- self.assertEqual(Color(5), Color.mauve)
- self.assertEqual(Color['mauve'], Color.mauve)
- self.assertEqual(len(Color), 5)
-
-
- def test_extend_enum_shadow_property(self):
- class Color(Enum):
- red = 1
- green = 2
- blue = 3
- extend_enum(Color, 'value', 4)
- self.assertEqual(Color.value.name, 'value')
- self.assertEqual(Color.value.value, 4)
- self.assertTrue(Color.value in Color)
- self.assertEqual(Color(4), Color.value)
- self.assertEqual(Color['value'], Color.value)
- self.assertEqual(len(Color), 4)
- self.assertEqual(Color.red.value, 1)
-
- def test_extend_enum_shadow_base(self):
- class hohum(object):
- def cyan(self):
- "cyanize a color"
- return self.value
- class Color(hohum, Enum):
- red = 1
- green = 2
- blue = 3
- self.assertRaisesRegex(TypeError, r'already in use in superclass', extend_enum, Color, 'cyan', 4)
- self.assertEqual(len(Color), 3)
- self.assertEqual(list(Color), [Color.red, Color.green, Color.blue])
-
- def test_extend_enum_multivalue(self):
- class Color(MultiValueEnum):
- red = 1, 4, 7
- green = 2, 5, 8
- blue = 3, 6, 9
- extend_enum(Color, 'brown', 10, 20)
- self.assertEqual(Color.brown.name, 'brown')
- self.assertEqual(Color.brown.value, 10)
- self.assertTrue(Color.brown in Color)
- self.assertEqual(Color(10), Color.brown)
- self.assertEqual(Color(20), Color.brown)
- self.assertEqual(Color['brown'], Color.brown)
- self.assertEqual(len(Color), 4)
- #
- self.assertRaisesRegex(ValueError, 'no values specified for MultiValue enum', extend_enum, Color, 'mauve')
-
- def test_extend_enum_multivalue_alias(self):
- class Color(MultiValueEnum):
- red = 1, 4, 7
- green = 2, 5, 8
- blue = 3, 6, 9
- self.assertRaisesRegex(ValueError, r'<Color.rojo: 7> is a duplicate of <Color.red: 1>', extend_enum, Color, 'rojo', 7)
- self.assertEqual(Color.red.name, 'red')
- self.assertEqual(Color.red.value, 1)
- self.assertTrue(Color.red in Color)
- self.assertEqual(Color(1), Color.red)
- self.assertEqual(Color(4), Color.red)
- self.assertEqual(Color(7), Color.red)
- self.assertEqual(Color['red'], Color.red)
- self.assertEqual(Color.green.name, 'green')
- self.assertEqual(Color.green.value, 2)
- self.assertTrue(Color.green in Color)
- self.assertEqual(Color(2), Color.green)
- self.assertEqual(Color(5), Color.green)
- self.assertEqual(Color(8), Color.green)
- self.assertEqual(Color['blue'], Color.blue)
- self.assertEqual(Color.blue.name, 'blue')
- self.assertEqual(Color.blue.value, 3)
- self.assertTrue(Color.blue in Color)
- self.assertEqual(Color(3), Color.blue)
- self.assertEqual(Color(6), Color.blue)
- self.assertEqual(Color(9), Color.blue)
- self.assertEqual(len(Color), 3)
-
- def test_extend_enum_multivalue_str(self):
- class M(str, MultiValueEnum):
- VALUE_1 = 'value_1', 'VALUE_1'
- VALUE_2 = 'value_2', 'VALUE_2'
- VALUE_3 = 'value_3', 'VALUE_3'
- self.assertTrue(M._member_type_ is str)
- extend_enum(M, 'VALUE_4', 'value_4', 'VALUE_4')
- self.assertEqual(list(M), [M.VALUE_1, M.VALUE_2, M.VALUE_3, M.VALUE_4])
- self.assertTrue(M('value_4') is M.VALUE_4)
- self.assertTrue(M('VALUE_4') is M.VALUE_4)
- self.assertTrue(M.VALUE_4.name == 'VALUE_4')
- self.assertTrue(M.VALUE_4.value == 'value_4')
-
- def test_extend_intenum(self):
- class Index(IntEnum):
- DeviceType = 0x1000
- ErrorRegister = 0x1001
-
- for name, value in (
- ('ControlWord', 0x6040),
- ('StatusWord', 0x6041),
- ('OperationMode', 0x6060),
- ):
- extend_enum(Index, name, value)
-
- self.assertEqual(len(Index), 5)
- self.assertEqual(list(Index), [Index.DeviceType, Index.ErrorRegister, Index.ControlWord, Index.StatusWord, Index.OperationMode])
- self.assertEqual(Index.DeviceType.value, 0x1000)
- self.assertEqual(Index.StatusWord.value, 0x6041)
-
- def test_extend_multi_init(self):
- class HTTPStatus(IntEnum):
- def __new__(cls, value, phrase, description):
- obj = int.__new__(cls, value)
- obj._value_ = value
-
- obj.phrase = phrase
- obj.description = description
- return obj
- CONTINUE = 100, 'Continue', 'Request received, please continue'
- SWITCHING_PROTOCOLS = 101, 'Switching Protocols', 'Switching to new protocol; obey Upgrade header'
- PROCESSING = 102, 'Processing', ''
- length = 3
- extend_enum(HTTPStatus, 'BAD_SPAM', 513, 'Too greasy', 'for a train')
- extend_enum(HTTPStatus, 'BAD_EGGS', 514, 'Too green', '')
- self.assertEqual(len(HTTPStatus), length+2)
- self.assertEqual(
- list(HTTPStatus)[-2:],
- [HTTPStatus.BAD_SPAM, HTTPStatus.BAD_EGGS],
- )
- self.assertEqual(HTTPStatus.BAD_SPAM.value, 513)
- self.assertEqual(HTTPStatus.BAD_SPAM.name, 'BAD_SPAM')
- self.assertEqual(HTTPStatus.BAD_SPAM.phrase, 'Too greasy')
- self.assertEqual(HTTPStatus.BAD_SPAM.description, 'for a train')
- self.assertEqual(HTTPStatus.BAD_EGGS.value, 514)
- self.assertEqual(HTTPStatus.BAD_EGGS.name, 'BAD_EGGS')
- self.assertEqual(HTTPStatus.BAD_EGGS.phrase, 'Too green')
- self.assertEqual(HTTPStatus.BAD_EGGS.description, '')
-
- def test_extend_flag(self):
- class Color(Flag):
- BLACK = 0
- RED = 1
- GREEN = 2
- BLUE = 4
- extend_enum(Color, 'MAGENTA')
- self.assertTrue(Color(8) is Color.MAGENTA)
- self.assertTrue(isinstance(Color.MAGENTA, Color))
- self.assertEqual(Color.MAGENTA.value, 8)
- extend_enum(Color, 'PURPLE', 11)
- self.assertTrue(Color(11) is Color.PURPLE)
- self.assertTrue(isinstance(Color.PURPLE, Color))
- self.assertEqual(Color.PURPLE.value, 11)
- self.assertTrue(issubclass(Color, Flag))
-
- def test_extend_flag_backwards(self):
- class Color(Flag):
- BLACK = 0
- RED = 1
- GREEN = 2
- BLUE = 4
- extend_enum(Color, 'PURPLE', 11)
- self.assertTrue(Color(11) is Color.PURPLE)
- self.assertTrue(isinstance(Color.PURPLE, Color))
- self.assertEqual(Color.PURPLE.value, 11)
- self.assertTrue(issubclass(Color, Flag))
- #
- extend_enum(Color, 'MAGENTA')
- self.assertTrue(Color(8) is Color.MAGENTA)
- self.assertTrue(isinstance(Color.MAGENTA, Color))
- self.assertEqual(Color.MAGENTA.value, 8)
- #
- extend_enum(Color, 'mauve')
- self.assertEqual(Color.mauve.name, 'mauve')
- self.assertEqual(Color.mauve.value, 16)
- self.assertTrue(Color.mauve in Color)
- self.assertEqual(Color(16), Color.mauve)
- self.assertEqual(Color['mauve'], Color.mauve)
- self.assertEqual(len(Color), 5)
-
- def test_extend_intflag(self):
- class Color(IntFlag):
- BLACK = 0
- RED = 1
- GREEN = 2
- BLUE = 4
- extend_enum(Color, 'MAGENTA')
- self.assertTrue(Color(8) is Color.MAGENTA)
- self.assertTrue(isinstance(Color.MAGENTA, Color))
- self.assertEqual(Color.MAGENTA.value, 8)
- extend_enum(Color, 'PURPLE', 11)
- self.assertTrue(Color(11) is Color.PURPLE)
- self.assertTrue(isinstance(Color.PURPLE, Color))
- self.assertEqual(Color.PURPLE.value, 11)
- self.assertTrue(issubclass(Color, Flag))
- #
- extend_enum(Color, 'mauve')
- self.assertEqual(Color.mauve.name, 'mauve')
- self.assertEqual(Color.mauve.value, 16)
- self.assertTrue(Color.mauve in Color)
- self.assertEqual(Color(16), Color.mauve)
- self.assertEqual(Color['mauve'], Color.mauve)
- self.assertEqual(len(Color), 5)
-
- def test_extend_intflag_backwards(self):
- class Color(IntFlag):
- BLACK = 0
- RED = 1
- GREEN = 2
- BLUE = 4
- extend_enum(Color, 'PURPLE', 11)
- self.assertTrue(Color(11) is Color.PURPLE)
- self.assertTrue(isinstance(Color.PURPLE, Color))
- self.assertEqual(Color.PURPLE.value, 11)
- self.assertTrue(issubclass(Color, Flag))
- #
- extend_enum(Color, 'MAGENTA')
- self.assertTrue(Color(8) is Color.MAGENTA)
- self.assertTrue(isinstance(Color.MAGENTA, Color))
- self.assertEqual(Color.MAGENTA.value, 8)
- #
- extend_enum(Color, 'mauve')
- self.assertEqual(Color.mauve.name, 'mauve')
- self.assertEqual(Color.mauve.value, 16)
- self.assertTrue(Color.mauve in Color)
- self.assertEqual(Color(16), Color.mauve)
- self.assertEqual(Color['mauve'], Color.mauve)
- self.assertEqual(len(Color), 5)
-
- def test_extend_strenum(self):
- class Color(StrEnum):
- RED = auto()
- GREEN = auto()
- BLUE = auto()
- extend_enum(Color, 'BLACK')
- self.assertEqual(Color.BLACK.name, 'BLACK')
- self.assertEqual(Color.BLACK.value, 'black')
- self.assertEqual(len(Color), 4)
-
- @unittest.skipUnless(StdlibEnum, 'Stdlib Enum not available')
- def test_extend_enum_stdlib(self):
- class Color(StdlibEnum):
- red = 1
- green = 2
- blue = 3
- self.assertEqual(getattr(Color.red, '_values_', None), None)
- extend_enum(Color, 'brown', 4)
- self.assertEqual(Color.brown.name, 'brown')
- self.assertEqual(Color.brown.value, 4)
- self.assertTrue(Color.brown in Color)
- self.assertEqual(Color(4), Color.brown)
- self.assertEqual(Color['brown'], Color.brown)
- self.assertEqual(len(Color), 4)
-
- @unittest.skipUnless(StdlibEnum, 'Stdlib Enum not available')
- def test_extend_enum_plain_stdlib(self):
- class Color(StdlibEnum):
- red = 1
- green = 2
- blue = 3
- self.assertRaisesRegex(TypeError, 'already in use as', extend_enum, Color, 'blue', 5)
- #
- extend_enum(Color, 'brown', 4)
- self.assertEqual(Color.brown.name, 'brown')
- self.assertEqual(Color.brown.value, 4)
- self.assertTrue(Color.brown in Color)
- self.assertEqual(Color(4), Color.brown)
- self.assertEqual(Color['brown'], Color.brown)
- self.assertEqual(len(Color), 4)
- self.assertEqual(list(Color), [Color.red, Color.green, Color.blue, Color.brown])
- self.assertEqual([c.value for c in Color], [1, 2, 3, 4])
- #
- extend_enum(Color, 'mauve')
- self.assertEqual(Color.mauve.name, 'mauve')
- self.assertEqual(Color.mauve.value, 5)
- self.assertTrue(Color.mauve in Color)
- self.assertEqual(Color(5), Color.mauve)
- self.assertEqual(Color['mauve'], Color.mauve)
- self.assertEqual(len(Color), 5)
-
- @unittest.skipUnless(StdlibEnum, 'Stdlib Enum not available')
- def test_extend_enum_alias_stdlib(self):
- class Color(StdlibEnum):
- red = 1
- green = 2
- blue = 3
- extend_enum(Color, 'rojo', 1)
- self.assertEqual(Color.rojo.name, 'red')
- self.assertEqual(Color.rojo.value, 1)
- self.assertTrue(Color.rojo in Color)
- self.assertEqual(Color(1), Color.rojo)
- self.assertEqual(Color['rojo'], Color.red)
- self.assertEqual(len(Color), 3)
-
- @unittest.skipUnless(StdlibEnum, 'Stdlib Enum not available')
- def test_extend_enum_shadow_property_stdlib(self):
- class Color(StdlibEnum):
- red = 1
- green = 2
- blue = 3
- extend_enum(Color, 'value', 4)
- self.assertEqual(Color.value.name, 'value')
- self.assertEqual(Color.value.value, 4)
- self.assertTrue(Color.value in Color)
- self.assertEqual(Color(4), Color.value)
- self.assertEqual(Color['value'], Color.value)
- self.assertEqual(len(Color), 4)
- self.assertEqual(Color.red.value, 1)
-
- @unittest.skipUnless(StdlibEnum, 'Stdlib Enum not available')
- def test_extend_enum_shadow_base_stdlib(self):
- class hohum(object):
- def cyan(self):
- "cyanize a color"
- return self.value
- class Color(hohum, StdlibEnum):
- red = 1
- green = 2
- blue = 3
- self.assertRaisesRegex(TypeError, r'already in use in superclass', extend_enum, Color, 'cyan', 4)
- self.assertEqual(len(Color), 3)
- self.assertEqual(list(Color), [Color.red, Color.green, Color.blue])
-
- @unittest.skipUnless(StdlibIntEnum, 'Stdlib IntEnum not available')
- def test_extend_intenum_stdlib(self):
- class Index(StdlibIntEnum):
- DeviceType = 0x1000
- ErrorRegister = 0x1001
-
- for name, value in (
- ('ControlWord', 0x6040),
- ('StatusWord', 0x6041),
- ('OperationMode', 0x6060),
- ):
- extend_enum(Index, name, value)
-
- self.assertEqual(len(Index), 5)
- self.assertEqual(list(Index), [Index.DeviceType, Index.ErrorRegister, Index.ControlWord, Index.StatusWord, Index.OperationMode])
- self.assertEqual(Index.DeviceType.value, 0x1000)
- self.assertEqual(Index.StatusWord.value, 0x6041)
-
- @unittest.skipUnless(StdlibIntEnum, 'Stdlib IntEnum not available')
- def test_extend_multi_init_stdlib(self):
- class HTTPStatus(StdlibIntEnum):
- def __new__(cls, value, phrase, description):
- obj = int.__new__(cls, value)
- obj._value_ = value
-
- obj.phrase = phrase
- obj.description = description
- return obj
- CONTINUE = 100, 'Continue', 'Request received, please continue'
- SWITCHING_PROTOCOLS = 101, 'Switching Protocols', 'Switching to new protocol; obey Upgrade header'
- PROCESSING = 102, 'Processing', ''
- length = 3
- extend_enum(HTTPStatus, 'BAD_SPAM', 513, 'Too greasy', 'for a train')
- extend_enum(HTTPStatus, 'BAD_EGGS', 514, 'Too green', '')
- self.assertEqual(len(HTTPStatus), length+2)
- self.assertEqual(
- list(HTTPStatus)[-2:],
- [HTTPStatus.BAD_SPAM, HTTPStatus.BAD_EGGS],
- )
- self.assertEqual(HTTPStatus.BAD_SPAM.value, 513)
- self.assertEqual(HTTPStatus.BAD_SPAM.name, 'BAD_SPAM')
- self.assertEqual(HTTPStatus.BAD_SPAM.phrase, 'Too greasy')
- self.assertEqual(HTTPStatus.BAD_SPAM.description, 'for a train')
- self.assertEqual(HTTPStatus.BAD_EGGS.value, 514)
- self.assertEqual(HTTPStatus.BAD_EGGS.name, 'BAD_EGGS')
- self.assertEqual(HTTPStatus.BAD_EGGS.phrase, 'Too green')
- self.assertEqual(HTTPStatus.BAD_EGGS.description, '')
-
- @unittest.skipUnless(StdlibFlag, 'Stdlib Flag not available')
- def test_extend_flag_stdlib(self):
- class Color(StdlibFlag):
- BLACK = 0
- RED = 1
- GREEN = 2
- BLUE = 4
- extend_enum(Color, 'MAGENTA')
- self.assertTrue(Color(8) is Color.MAGENTA)
- self.assertTrue(isinstance(Color.MAGENTA, Color))
- self.assertEqual(Color.MAGENTA.value, 8)
- extend_enum(Color, 'PURPLE', 11)
- self.assertTrue(Color(11) is Color.PURPLE)
- self.assertTrue(isinstance(Color.PURPLE, Color))
- self.assertEqual(Color.PURPLE.value, 11)
- self.assertTrue(issubclass(Color, StdlibFlag))
-
- @unittest.skipUnless(StdlibFlag, 'Stdlib Flag not available')
- def test_extend_flag_backwards_stdlib(self):
- class Color(StdlibFlag):
- BLACK = 0
- RED = 1
- GREEN = 2
- BLUE = 4
- extend_enum(Color, 'PURPLE', 11)
- self.assertTrue(Color(11) is Color.PURPLE)
- self.assertTrue(isinstance(Color.PURPLE, Color))
- self.assertEqual(Color.PURPLE.value, 11)
- self.assertTrue(issubclass(Color, StdlibFlag))
- #
- extend_enum(Color, 'MAGENTA')
- self.assertTrue(Color(16) is Color.MAGENTA)
- self.assertTrue(isinstance(Color.MAGENTA, Color))
- self.assertEqual(Color.MAGENTA.value,16)
- #
- extend_enum(Color, 'mauve')
- self.assertEqual(Color.mauve.name, 'mauve')
- self.assertEqual(Color.mauve.value, 32)
- self.assertTrue(Color.mauve in Color)
- self.assertEqual(Color(32), Color.mauve)
- self.assertEqual(Color['mauve'], Color.mauve)
-
- @unittest.skipUnless(StdlibIntFlag, 'Stdlib IntFlag not available')
- def test_extend_intflag_stdlib(self):
- class Color(StdlibIntFlag):
- BLACK = 0
- RED = 1
- GREEN = 2
- BLUE = 4
- extend_enum(Color, 'MAGENTA')
- self.assertTrue(Color(8) is Color.MAGENTA)
- self.assertTrue(isinstance(Color.MAGENTA, Color))
- self.assertEqual(Color.MAGENTA.value, 8)
- extend_enum(Color, 'PURPLE', 11)
- self.assertTrue(Color(11) is Color.PURPLE)
- self.assertTrue(isinstance(Color.PURPLE, Color))
- self.assertEqual(Color.PURPLE.value, 11)
- self.assertTrue(issubclass(Color, StdlibFlag))
- #
- extend_enum(Color, 'mauve')
- self.assertEqual(Color.mauve.name, 'mauve')
- self.assertEqual(Color.mauve.value, 16)
- self.assertTrue(Color.mauve in Color)
- self.assertEqual(Color(16), Color.mauve)
- self.assertEqual(Color['mauve'], Color.mauve)
-
- @unittest.skipUnless(StdlibIntFlag, 'Stdlib IntFlag not available')
- def test_extend_intflag_backwards_stdlib(self):
- class Color(StdlibIntFlag):
- BLACK = 0
- RED = 1
- GREEN = 2
- BLUE = 4
- if pyver >= PY3_11:
- # flags make more sense in 3.11
- length = 5
- MAGENTA = 8
- mauve = 16
- else:
- length = 7
- MAGENTA = 16
- mauve = 32
- extend_enum(Color, 'PURPLE', 11)
- self.assertTrue(Color(11) is Color.PURPLE)
- self.assertTrue(isinstance(Color.PURPLE, Color))
- self.assertEqual(Color.PURPLE.value, 11)
- self.assertTrue(issubclass(Color, StdlibFlag))
- #
- extend_enum(Color, 'MAGENTA')
- self.assertTrue(Color(MAGENTA) is Color.MAGENTA)
- self.assertTrue(isinstance(Color.MAGENTA, Color))
- self.assertEqual(Color.MAGENTA.value, MAGENTA)
- #
- extend_enum(Color, 'mauve')
- self.assertEqual(Color.mauve.name, 'mauve')
- self.assertEqual(Color.mauve.value, mauve)
- self.assertTrue(Color.mauve in Color)
- self.assertEqual(Color(mauve), Color.mauve)
- self.assertEqual(Color['mauve'], Color.mauve)
- self.assertEqual(len(Color), length, list(Color))
-
- @unittest.skipUnless(StdlibStrEnum, 'Stdlib StrEnum not available')
- def test_extend_strenum_stdlib(self):
- class Color(StrEnum):
- RED = auto()
- GREEN = auto()
- BLUE = auto()
- extend_enum(Color, 'BLACK')
- self.assertEqual(Color.BLACK.name, 'BLACK')
- self.assertEqual(Color.BLACK.value, 'black')
- self.assertEqual(len(Color), 4)
-
-
-if __name__ == '__main__':
- raise RuntimeError("'test_v3.py' should not be run by itself; it's included in 'test.py'")
diff --git a/venv/Lib/site-packages/blendmodes/__init__.py b/venv/Lib/site-packages/blendmodes/__init__.py
deleted file mode 100644
index 2b6e91ad..00000000
--- a/venv/Lib/site-packages/blendmodes/__init__.py
+++ /dev/null
@@ -1,2 +0,0 @@
-"""Use this module to apply a number of blending modes to a background and foreground image
-"""
diff --git a/venv/Lib/site-packages/blendmodes/__pycache__/__init__.cpython-39.pyc b/venv/Lib/site-packages/blendmodes/__pycache__/__init__.cpython-39.pyc
deleted file mode 100644
index da1d6a38..00000000
--- a/venv/Lib/site-packages/blendmodes/__pycache__/__init__.cpython-39.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/Lib/site-packages/blendmodes/__pycache__/blend.cpython-39.pyc b/venv/Lib/site-packages/blendmodes/__pycache__/blend.cpython-39.pyc
deleted file mode 100644
index 23184600..00000000
--- a/venv/Lib/site-packages/blendmodes/__pycache__/blend.cpython-39.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/Lib/site-packages/blendmodes/__pycache__/blendtype.cpython-39.pyc b/venv/Lib/site-packages/blendmodes/__pycache__/blendtype.cpython-39.pyc
deleted file mode 100644
index c599cfb8..00000000
--- a/venv/Lib/site-packages/blendmodes/__pycache__/blendtype.cpython-39.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/Lib/site-packages/blendmodes/blend.py b/venv/Lib/site-packages/blendmodes/blend.py
deleted file mode 100644
index 4165bfa7..00000000
--- a/venv/Lib/site-packages/blendmodes/blend.py
+++ /dev/null
@@ -1,511 +0,0 @@
-"""Provide blending functions and types.
-
-Adapted from https://github.com/addisonElliott/pypdn/blob/master/pypdn/reader.py
-and https://gitlab.com/inklabapp/pyora/-/blob/master/pyora/BlendNonSep.py
-MIT License Copyright (c) 2020 FredHappyface
-
-Credits to:
-
-MIT License Copyright (c) 2019 Paul Jewell
-For implementing blending from the Open Raster Image Spec
-
-MIT License Copyright (c) 2018 Addison Elliott
-For implementing blending from Paint.NET
-
-MIT License Copyright (c) 2017 pashango
-For implementing a number of blending functions used by other popular image
-editors
-"""
-
-from __future__ import annotations
-
-import warnings
-
-import numpy as np
-from PIL import Image
-
-from .blendtype import BlendType
-
-
-def normal(background: np.ndarray, foreground: np.ndarray) -> np.ndarray:
- """BlendType.NORMAL."""
- del background # we don't care about this
- return foreground
-
-
-def multiply(background: np.ndarray, foreground: np.ndarray) -> np.ndarray:
- """BlendType.MULTIPLY."""
- return np.clip(foreground * background, 0.0, 1.0)
-
-
-def additive(background: np.ndarray, foreground: np.ndarray) -> np.ndarray:
- """BlendType.ADDITIVE."""
- return np.minimum(background + foreground, 1.0)
-
-
-def colourburn(background: np.ndarray, foreground: np.ndarray) -> np.ndarray:
- """BlendType.COLOURBURN."""
- with np.errstate(divide="ignore"):
- return np.where(
- foreground != 0.0, np.maximum(1.0 - ((1.0 - background) / foreground), 0.0), 0.0
- )
-
-
-def colourdodge(background: np.ndarray, foreground: np.ndarray) -> np.ndarray:
- """BlendType.COLOURDODGE."""
- with np.errstate(divide="ignore"):
- return np.where(foreground != 1.0, np.minimum(background / (1.0 - foreground), 1.0), 1.0)
-
-
-def reflect(background: np.ndarray, foreground: np.ndarray) -> np.ndarray:
- """BlendType.REFLECT."""
- with np.errstate(divide="ignore"):
- return np.where(
- foreground != 1.0, np.minimum((background ** 2) / (1.0 - foreground), 1.0), 1.0
- )
-
-
-def glow(background: np.ndarray, foreground: np.ndarray) -> np.ndarray:
- """BlendType.GLOW."""
- with np.errstate(divide="ignore"):
- return np.where(
- background != 1.0, np.minimum((foreground ** 2) / (1.0 - background), 1.0), 1.0
- )
-
-
-def overlay(background: np.ndarray, foreground: np.ndarray) -> np.ndarray:
- """BlendType.OVERLAY."""
- return np.where(
- background < 0.5,
- 2 * background * foreground,
- 1.0 - (2 * (1.0 - background) * (1.0 - foreground)),
- )
-
-
-def difference(background: np.ndarray, foreground: np.ndarray) -> np.ndarray:
- """BlendType.DIFFERENCE."""
- return np.abs(background - foreground)
-
-
-def negation(background: np.ndarray, foreground: np.ndarray) -> np.ndarray:
- """BlendType.NEGATION."""
- return np.maximum(background - foreground, 0.0)
-
-
-def lighten(background: np.ndarray, foreground: np.ndarray) -> np.ndarray:
- """BlendType.LIGHTEN."""
- return np.maximum(background, foreground)
-
-
-def darken(background: np.ndarray, foreground: np.ndarray) -> np.ndarray:
- """BlendType.DARKEN."""
- return np.minimum(background, foreground)
-
-
-def screen(background: np.ndarray, foreground: np.ndarray) -> np.ndarray:
- """BlendType.SCREEN."""
- return background + foreground - background * foreground
-
-
-def xor(background: np.ndarray, foreground: np.ndarray) -> np.ndarray:
- """BlendType.XOR."""
- # XOR requires int values so convert to uint8
- with warnings.catch_warnings():
- warnings.simplefilter("ignore")
- return imageIntToFloat(imageFloatToInt(background) ^ imageFloatToInt(foreground))
-
-
-def softlight(background: np.ndarray, foreground: np.ndarray) -> np.ndarray:
- """BlendType.SOFTLIGHT."""
- return (1.0 - background) * background * foreground + background * (
- 1.0 - (1.0 - background) * (1.0 - foreground)
- )
-
-
-def hardlight(background: np.ndarray, foreground: np.ndarray) -> np.ndarray:
- """BlendType.HARDLIGHT."""
- return np.where(
- foreground < 0.5,
- np.minimum(background * 2 * foreground, 1.0),
- np.minimum(1.0 - ((1.0 - background) * (1.0 - (foreground - 0.5) * 2.0)), 1.0),
- )
-
-
-def grainextract(background: np.ndarray, foreground: np.ndarray) -> np.ndarray:
- """BlendType.GRAINEXTRACT."""
- return np.clip(background - foreground + 0.5, 0.0, 1.0)
-
-
-def grainmerge(background: np.ndarray, foreground: np.ndarray) -> np.ndarray:
- """BlendType.GRAINMERGE."""
- return np.clip(background + foreground - 0.5, 0.0, 1.0)
-
-
-def divide(background: np.ndarray, foreground: np.ndarray) -> np.ndarray:
- """BlendType.DIVIDE."""
- return np.minimum((256.0 / 255.0 * background) / (1.0 / 255.0 + foreground), 1.0)
-
-
-def pinlight(background: np.ndarray, foreground: np.ndarray) -> np.ndarray:
- """BlendType.PINLIGHT."""
- return np.minimum(background, 2 * foreground) * (foreground < 0.5) + np.maximum(
- background, 2 * (foreground - 0.5)
- ) * (foreground >= 0.5)
-
-
-def vividlight(background: np.ndarray, foreground: np.ndarray) -> np.ndarray:
- """BlendType.VIVIDLIGHT."""
- return colourburn(background, foreground * 2) * (foreground < 0.5) + colourdodge(
- background, 2 * (foreground - 0.5)
- ) * (foreground >= 0.5)
-
-
-def exclusion(background: np.ndarray, foreground: np.ndarray) -> np.ndarray:
- """BlendType.EXCLUSION."""
- return background + foreground - (2.0 * background * foreground)
-
-
-def _lum(colours: np.ndarray) -> np.ndarray:
- """Luminosity.
-
- :param colours: x by x by 3 matrix of rgb color components of pixels
- :return: x by x by 3 matrix of luminosity of pixels
- """
- return (colours[:, :, 0] * 0.299) + (colours[:, :, 1] * 0.587) + (colours[:, :, 2] * 0.114)
-
-
-def _setLum(originalColours: np.ndarray, newLuminosity: np.ndarray) -> np.ndarray:
- """Set a new luminosity value for the matrix of color."""
- _colours = originalColours.copy()
- _luminosity = _lum(_colours)
- deltaLum = newLuminosity - _luminosity
- _colours[:, :, 0] += deltaLum
- _colours[:, :, 1] += deltaLum
- _colours[:, :, 2] += deltaLum
- _luminosity = _lum(_colours)
- _minColours = np.min(_colours, axis=2)
- _MaxColours = np.max(_colours, axis=2)
- for i in range(_colours.shape[0]):
- for j in range(_colours.shape[1]):
- _colour = _colours[i][j]
- newLuminosity = _luminosity[i, j]
- minColour = _minColours[i, j]
- maxColour = _MaxColours[i, j]
- if minColour < 0:
- _colours[i][j] = newLuminosity + (
- ((_colour - newLuminosity) * newLuminosity) / (newLuminosity - minColour)
- )
- if maxColour > 1:
- _colours[i][j] = newLuminosity + (
- ((_colour - newLuminosity) * (1 - newLuminosity)) / (maxColour - newLuminosity)
- )
- return _colours
-
-
-def _sat(colours: np.ndarray) -> np.ndarray:
- """Saturation.
-
- :param colours: x by x by 3 matrix of rgb color components of pixels
- :return: int of saturation of pixels
- """
- return np.max(colours, axis=2) - np.min(colours, axis=2)
-
-
-def _setSat(originalColours: np.ndarray, newSaturation: np.ndarray) -> np.ndarray:
- """Set a new saturation value for the matrix of color.
-
- The current implementation cannot be vectorized in an efficient manner,
- so it is very slow,
- O(m*n) at least. This might be able to be improved with openCL if that is
- the direction that the lib takes.
- :param c: x by x by 3 matrix of rgb color components of pixels
- :param s: int of the new saturation value for the matrix
- :return: x by x by 3 matrix of luminosity of pixels
- """
- _colours = originalColours.copy()
- for i in range(_colours.shape[0]):
- for j in range(_colours.shape[1]):
- _colour = _colours[i][j]
- minI = 0
- midI = 1
- maxI = 2
- if _colour[midI] < _colour[minI]:
- minI, midI = midI, minI
- if _colour[maxI] < _colour[midI]:
- midI, maxI = maxI, midI
- if _colour[midI] < _colour[minI]:
- minI, midI = midI, minI
- if _colour[maxI] - _colour[minI] > 0.0:
- _colours[i][j][midI] = ((_colour[midI] - _colour[minI]) * newSaturation[i, j]) / (
- _colour[maxI] - _colour[minI]
- )
- _colours[i][j][maxI] = newSaturation[i, j]
- else:
- _colours[i][j][midI] = 0
- _colours[i][j][maxI] = 0
- _colours[i][j][minI] = 0
- return _colours
-
-
-def hue(background: np.ndarray, foreground: np.ndarray) -> np.ndarray:
- """BlendType.HUE."""
- return _setLum(_setSat(foreground, _sat(background)), _lum(background))
-
-
-def saturation(background: np.ndarray, foreground: np.ndarray) -> np.ndarray:
- """BlendType.SATURATION."""
- return _setLum(_setSat(background, _sat(foreground)), _lum(background))
-
-
-def colour(background: np.ndarray, foreground: np.ndarray) -> np.ndarray:
- """BlendType.COLOUR."""
- return _setLum(foreground, _lum(background))
-
-
-def luminosity(background: np.ndarray, foreground: np.ndarray) -> np.ndarray:
- """BlendType.LUMINOSITY."""
- return _setLum(background, _lum(foreground))
-
-
-def destin(
- backgroundAlpha: np.ndarray,
- foregroundAlpha: np.ndarray,
- backgroundColour: np.ndarray,
- foregroundColour: np.ndarray,
-):
- """'clip' composite mode.
-
- All parts of 'layer above' which are alpha in 'layer below' will be made
- also alpha in 'layer above'
- (to whatever degree of alpha they were)
-
- Destination which overlaps the source, replaces the source.
-
- Fa = 0; Fb = αs
- co = αb x Cb x αs
- αo = αb x αs
- """
- del foregroundColour # Not used by function
- outAlpha = backgroundAlpha * foregroundAlpha
- with np.errstate(divide="ignore", invalid="ignore"):
- outRGB = np.divide(
- np.multiply((backgroundAlpha * foregroundAlpha)[:, :, None], backgroundColour),
- outAlpha[:, :, None],
- )
- return outRGB, outAlpha
-
-
-def destout(
- backgroundAlpha: np.ndarray,
- foregroundAlpha: np.ndarray,
- backgroundColour: np.ndarray,
- foregroundColour: np.ndarray,
-):
- """Reverse 'Clip' composite mode.
-
- All parts of 'layer below' which are alpha in 'layer above' will be made
- also alpha in 'layer below'
- (to whatever degree of alpha they were)
-
- """
- del foregroundColour # Not used by function
- outAlpha = backgroundAlpha * (1 - foregroundAlpha)
- with np.errstate(divide="ignore", invalid="ignore"):
- outRGB = np.divide(
- np.multiply((backgroundAlpha * (1 - foregroundAlpha))[:, :, None], backgroundColour),
- outAlpha[:, :, None],
- )
- return outRGB, outAlpha
-
-
-def destatop(
- backgroundAlpha: np.ndarray,
- foregroundAlpha: np.ndarray,
- backgroundColour: np.ndarray,
- foregroundColour: np.ndarray,
-):
- """Place the layer below above the 'layer above' in places where the 'layer above' exists...
-
- where 'layer below' does not exist, but 'layer above' does, place 'layer-above'
-
- """
- outAlpha = (foregroundAlpha * (1 - backgroundAlpha)) + (backgroundAlpha * foregroundAlpha)
- with np.errstate(divide="ignore", invalid="ignore"):
- outRGB = np.divide(
- np.multiply((foregroundAlpha * (1 - backgroundAlpha))[:, :, None], foregroundColour)
- + np.multiply((backgroundAlpha * foregroundAlpha)[:, :, None], backgroundColour),
- outAlpha[:, :, None],
- )
- return outRGB, outAlpha
-
-
-def srcatop(
- backgroundAlpha: np.ndarray,
- foregroundAlpha: np.ndarray,
- backgroundColour: np.ndarray,
- foregroundColour: np.ndarray,
-):
- """Place the layer below above the 'layer above' in places where the 'layer above' exists."""
- outAlpha = (foregroundAlpha * backgroundAlpha) + (backgroundAlpha * (1 - foregroundAlpha))
- with np.errstate(divide="ignore", invalid="ignore"):
- outRGB = np.divide(
- np.multiply((foregroundAlpha * backgroundAlpha)[:, :, None], foregroundColour)
- + np.multiply((backgroundAlpha * (1 - foregroundAlpha))[:, :, None], backgroundColour),
- outAlpha[:, :, None],
- )
-
- return outRGB, outAlpha
-
-
-def imageIntToFloat(image: np.ndarray) -> np.ndarray:
- """Convert a numpy array representing an image to an array of floats.
-
- Args:
- image (np.ndarray): numpy array of ints
-
- Returns:
- np.ndarray: numpy array of floats
- """
- return image / 255
-
-
-def imageFloatToInt(image: np.ndarray) -> np.ndarray:
- """Convert a numpy array representing an image to an array of ints.
-
- Args:
- image (np.ndarray): numpy array of floats
-
- Returns:
- np.ndarray: numpy array of ints
- """
- return (image * 255).astype(np.uint8)
-
-
-def blend(background: np.ndarray, foreground: np.ndarray, blendType: BlendType) -> np.ndarray:
- """Blend pixels.
-
- Args:
- background (np.ndarray): background
- foreground (np.ndarray): foreground
- blendType (BlendType): the blend type
-
- Returns:
- np.ndarray: new array representing the image
-
- background: np.ndarray,
- foreground: np.ndarray and the return are in the form
-
- [[[0. 0. 0.]
- [0. 0. 0.]
- [0. 0. 0.]
- ...
- [0. 0. 0.]
- [0. 0. 0.]
- [0. 0. 0.]]
-
- ...
-
- [[0. 0. 0.]
- [0. 0. 0.]
- [0. 0. 0.]
- ...
- [0. 0. 0.]
- [0. 0. 0.]
- [0. 0. 0.]]]
- """
- blendLookup = {
- BlendType.NORMAL: normal,
- BlendType.MULTIPLY: multiply,
- BlendType.COLOURBURN: colourburn,
- BlendType.COLOURDODGE: colourdodge,
- BlendType.REFLECT: reflect,
- BlendType.OVERLAY: overlay,
- BlendType.DIFFERENCE: difference,
- BlendType.LIGHTEN: lighten,
- BlendType.DARKEN: darken,
- BlendType.SCREEN: screen,
- BlendType.SOFTLIGHT: softlight,
- BlendType.HARDLIGHT: hardlight,
- BlendType.GRAINEXTRACT: grainextract,
- BlendType.GRAINMERGE: grainmerge,
- BlendType.DIVIDE: divide,
- BlendType.HUE: hue,
- BlendType.SATURATION: saturation,
- BlendType.COLOUR: colour,
- BlendType.LUMINOSITY: luminosity,
- BlendType.XOR: xor,
- BlendType.NEGATION: negation,
- BlendType.PINLIGHT: pinlight,
- BlendType.VIVIDLIGHT: vividlight,
- BlendType.EXCLUSION: exclusion,
- }
-
- if blendType not in blendLookup:
- return normal(background, foreground)
- return blendLookup[blendType](background, foreground)
-
-
-def blendLayers(
- background: Image.Image,
- foreground: Image.Image,
- blendType: BlendType | tuple[str, ...],
- opacity: float = 1.0,
-) -> Image.Image:
- """Blend layers using numpy array.
-
- Args:
- background (Image.Image): background layer
- foreground (Image.Image): foreground layer (must be same size as background)
- blendType (BlendType): The blendtype
- opacity (float): The opacity of the foreground image
-
- Returns:
- Image.Image: combined image
- """
- # Convert the Image.Image to a numpy array
- npForeground: np.ndarray = imageIntToFloat(np.array(foreground.convert("RGBA")))
- npBackground: np.ndarray = imageIntToFloat(np.array(background.convert("RGBA")))
-
- # Get the alpha from the layers
- backgroundAlpha = npBackground[:, :, 3]
- foregroundAlpha = npForeground[:, :, 3] * opacity
- combinedAlpha = backgroundAlpha * foregroundAlpha
-
- # Get the colour from the layers
- backgroundColor = npBackground[:, :, 0:3]
- foregroundColor = npForeground[:, :, 0:3]
-
- # Some effects require alpha
- alphaFunc = {
- BlendType.DESTIN: destin,
- BlendType.DESTOUT: destout,
- BlendType.SRCATOP: srcatop,
- BlendType.DESTATOP: destatop,
- }
-
- if blendType in alphaFunc:
- return Image.fromarray(
- imageFloatToInt(
- np.clip(
- np.dstack(
- alphaFunc[blendType](
- backgroundAlpha, foregroundAlpha, backgroundColor, foregroundColor
- )
- ),
- a_min=0,
- a_max=1,
- )
- )
- )
-
- # Get the colours and the alpha for the new image
- colorComponents = (
- (backgroundAlpha - combinedAlpha)[:, :, None] * backgroundColor
- + (foregroundAlpha - combinedAlpha)[:, :, None] * foregroundColor
- + combinedAlpha[:, :, None] * blend(backgroundColor, foregroundColor, blendType)
- )
- alphaComponent = backgroundAlpha + foregroundAlpha - combinedAlpha
-
- return Image.fromarray(
- imageFloatToInt(np.clip(np.dstack((colorComponents, alphaComponent)), a_min=0, a_max=1))
- )
diff --git a/venv/Lib/site-packages/blendmodes/blendtype.py b/venv/Lib/site-packages/blendmodes/blendtype.py
deleted file mode 100644
index 1bde12a6..00000000
--- a/venv/Lib/site-packages/blendmodes/blendtype.py
+++ /dev/null
@@ -1,72 +0,0 @@
-"""Specify supported blend types."""
-
-from __future__ import annotations
-
-from aenum import MultiValueEnum
-
-
-class BlendType(str, MultiValueEnum):
- """Specify supported blend types.
-
- NORMAL = "bm:normal", "normal"
- MULTIPLY = "bm:multiply", "multiply"
- ADDITIVE = "bm:additive", "additive"
- COLOURBURN = "bm:colourburn", "colourburn"
- COLOURDODGE = "bm:colourdodge", "colourdodge"
- REFLECT = "bm:reflect", "reflect"
- GLOW = "bm:glow", "glow"
- OVERLAY = "bm:overlay", "overlay"
- DIFFERENCE = "bm:difference", "difference"
- NEGATION = "bm:negation", "negation"
- LIGHTEN = "bm:lighten", "lighten"
- DARKEN = "bm:darken", "darken"
- SCREEN = "bm:screen", "screen"
- XOR = "bm:xor", "xor"
- SOFTLIGHT = "bm:softlight", "softlight"
- HARDLIGHT = "bm:hardlight", "hardlight"
- GRAINEXTRACT = "bm:grainextract", "grainextract"
- GRAINMERGE = "bm:grainmerge", "grainmerge"
- DIVIDE = "bm:divide", "divide"
- HUE = "bm:hue", "hue"
- SATURATION = "bm:saturation", "saturation"
- COLOUR = "bm:colour", "colour"
- LUMINOSITY = "bm:luminosity", "luminosity"
- PINLIGHT = "bm:pinlight", "pinlight"
- VIVIDLIGHT = "bm:vividlight", "vividlight"
- EXCLUSION = "bm:exclusion", "exclusion"
- DESTIN = "bm:destin", "destin"
- DESTOUT = "bm:destout", "destout"
- SRCATOP = "bm:srcatop", "srcatop"
- DESTATOP = "bm:destatop", "destatop"
- """
-
- NORMAL = "bm:normal", "normal"
- MULTIPLY = "bm:multiply", "multiply"
- ADDITIVE = "bm:additive", "additive"
- COLOURBURN = "bm:colourburn", "colourburn"
- COLOURDODGE = "bm:colourdodge", "colourdodge"
- REFLECT = "bm:reflect", "reflect"
- GLOW = "bm:glow", "glow"
- OVERLAY = "bm:overlay", "overlay"
- DIFFERENCE = "bm:difference", "difference"
- NEGATION = "bm:negation", "negation"
- LIGHTEN = "bm:lighten", "lighten"
- DARKEN = "bm:darken", "darken"
- SCREEN = "bm:screen", "screen"
- XOR = "bm:xor", "xor"
- SOFTLIGHT = "bm:softlight", "softlight"
- HARDLIGHT = "bm:hardlight", "hardlight"
- GRAINEXTRACT = "bm:grainextract", "grainextract"
- GRAINMERGE = "bm:grainmerge", "grainmerge"
- DIVIDE = "bm:divide", "divide"
- HUE = "bm:hue", "hue"
- SATURATION = "bm:saturation", "saturation"
- COLOUR = "bm:colour", "colour"
- LUMINOSITY = "bm:luminosity", "luminosity"
- PINLIGHT = "bm:pinlight", "pinlight"
- VIVIDLIGHT = "bm:vividlight", "vividlight"
- EXCLUSION = "bm:exclusion", "exclusion"
- DESTIN = "bm:destin", "destin"
- DESTOUT = "bm:destout", "destout"
- SRCATOP = "bm:srcatop", "srcatop"
- DESTATOP = "bm:destatop", "destatop"
diff --git a/venv/Lib/site-packages/blendmodes/imagetools.py b/venv/Lib/site-packages/blendmodes/imagetools.py
deleted file mode 100644
index 834b7c86..00000000
--- a/venv/Lib/site-packages/blendmodes/imagetools.py
+++ /dev/null
@@ -1,48 +0,0 @@
-"""Do stuff to images to prepare them.
-"""
-from __future__ import annotations
-
-import warnings
-
-from deprecation import deprecated
-from PIL import Image
-
-
-@deprecated(deprecated_in="2021.1", removed_in="", details="use renderWAlphaOffset")
-def rasterImageOA( # pylint:disable=missing-function-docstring
- image: Image.Image, size: tuple[int, int], alpha: float = 1.0, offsets: tuple[int, int] = (0, 0)
-) -> Image.Image:
- warnings.warn(
- "Call to deprecated function rasterImageOA.", category=DeprecationWarning, stacklevel=2
- )
- return renderWAlphaOffset(image, size, alpha, offsets)
-
-
-@deprecated(deprecated_in="2021.1", removed_in="", details="use renderWAlphaOffset")
-def rasterImageOffset( # pylint:disable=missing-function-docstring
- image: Image.Image, size: tuple[int, int], offsets: tuple[int, int] = (0, 0)
-) -> Image.Image:
- warnings.warn(
- "Call to deprecated function rasterImageOffset.", category=DeprecationWarning, stacklevel=2
- )
- return renderWAlphaOffset(image, size, 1, offsets)
-
-
-def renderWAlphaOffset(
- image: Image.Image, size: tuple[int, int], alpha: float = 1.0, offsets: tuple[int, int] = (0, 0)
-) -> Image.Image:
- """Render an image with offset and alpha to a given size.
-
- Args:
- image (Image.Image): pil image to draw
- size (tuple[int, int]): width, height as a tuple
- alpha (float, optional): alpha transparency. Defaults to 1.0.
- offsets (tuple[int, int], optional): x, y offsets as a tuple.
- Defaults to (0, 0).
-
- Returns:
- Image.Image: new image
- """
- imageOffset = Image.new("RGBA", size)
- imageOffset.paste(image.convert("RGBA"), offsets, image.convert("RGBA"))
- return Image.blend(Image.new("RGBA", size), imageOffset, alpha)