aboutsummaryrefslogtreecommitdiffstats
path: root/venv/Lib/site-packages/aenum/test.py
diff options
context:
space:
mode:
Diffstat (limited to 'venv/Lib/site-packages/aenum/test.py')
-rw-r--r--venv/Lib/site-packages/aenum/test.py6832
1 files changed, 6832 insertions, 0 deletions
diff --git a/venv/Lib/site-packages/aenum/test.py b/venv/Lib/site-packages/aenum/test.py
new file mode 100644
index 00000000..224293cb
--- /dev/null
+++ b/venv/Lib/site-packages/aenum/test.py
@@ -0,0 +1,6832 @@
+# -*- 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)
+