1# -*- coding: utf-8 -*-
2
3from __future__ import division, print_function
4import sys
5pyver = float('%s.%s' % sys.version_info[:2])
6import aenum
7import doctest
8import os
9import shutil
10import tempfile
11import unittest
12import warnings
13from aenum import EnumMeta, Enum, IntEnum, AutoNumberEnum, MultiValueEnum, OrderedEnum, UniqueEnum, Flag, IntFlag
14from aenum import NamedTuple, TupleSize, NamedConstant, constant, NoAlias, AutoNumber, AutoValue, Unique
15from aenum import _reduce_ex_by_name, unique, skip, extend_enum, auto, enum, MultiValue, member, nonmember, no_arg
16from collections import OrderedDict
17from datetime import timedelta
18from pickle import dumps, loads, PicklingError, HIGHEST_PROTOCOL
19from operator import or_ as _or_, and_ as _and_, xor as _xor_, inv as _inv_
20from operator import abs as _abs_, add as _add_, floordiv as _floordiv_
21from operator import lshift as _lshift_, rshift as _rshift_, mod as _mod_
22from operator import mul as _mul_, neg as _neg_, pos as _pos_, pow as _pow_
23from operator import truediv as _truediv_, sub as _sub_
24if pyver < 3:
25    from operator import div as _div_
26try:
27    import threading
28except ImportError:
29    threading = None
30
31try:
32    basestring
33except NameError:
34    # In Python 2 basestring is the ancestor of both str and unicode
35    # in Python 3 it's just str, but was missing in 3.1
36    basestring = str
37
38try:
39    any
40except NameError:
41    def any(iterable):
42        for element in iterable:
43            if element:
44                return True
45        return False
46
47try:
48    unicode
49except NameError:
50    unicode = str
51
52try:
53    from enum import EnumMeta as StdlibEnumMeta, Enum as StdlibEnum
54    import enum as enum_module
55    if hasattr(enum_module, 'version'):
56        StdlibEnumMeta = StdlibEnum = None
57    del enum_module
58except ImportError:
59    StdlibEnumMeta = StdlibEnum = None
60
61def load_tests(loader, tests, ignore):
62    tests.addTests(doctest.DocTestSuite(aenum))
63    tests.addTests(doctest.DocFileSuite(
64        'doc/aenum.rst',
65        package=aenum,
66        optionflags=doctest.ELLIPSIS|doctest.NORMALIZE_WHITESPACE,
67        ))
68    return tests
69
70class TestCase(unittest.TestCase):
71
72    def __init__(self, *args, **kwds):
73        regex = getattr(self, 'assertRaisesRegex', None)
74        if regex is None:
75            self.assertRaisesRegex = getattr(self, 'assertRaisesRegexp')
76        super(TestCase, self).__init__(*args, **kwds)
77
78    @classmethod
79    def setUpClass(cls, *args, **kwds):
80        super(TestCase, cls).setUpClass(*args, **kwds)
81        # filter warnings
82        warnings.filterwarnings(
83                'ignore',
84                'inspect\.getargspec\(\) is deprecated',
85                DeprecationWarning,
86                'aenum',
87                0,
88                )
89
90# for pickle tests
91try:
92    class Stooges(Enum):
93        LARRY = 1
94        CURLY = 2
95        MOE = 3
96except Exception:
97    Stooges = sys.exc_info()[1]
98
99try:
100    class IntStooges(int, Enum):
101        LARRY = 1
102        CURLY = 2
103        MOE = 3
104except Exception:
105    IntStooges = sys.exc_info()[1]
106
107try:
108    class FloatStooges(float, Enum):
109        LARRY = 1.39
110        CURLY = 2.72
111        MOE = 3.142596
112except Exception:
113    FloatStooges = sys.exc_info()[1]
114
115try:
116    class FlagStooges(Flag):
117        LARRY = 1
118        CURLY = 2
119        MOE = 3
120except Exception as exc:
121    FlagStooges = exc
122
123try:
124    LifeForm = NamedTuple('LifeForm', 'branch genus species', module=__name__)
125except Exception:
126    LifeForm = sys.exc_info()[1]
127
128try:
129    class DeathForm(NamedTuple):
130        color = 0
131        rigidity = 1
132        odor = 2
133except Exception:
134    DeathForm = sys.exc_info()[1]
135
136# for pickle test and subclass tests
137try:
138    class StrEnum(str, Enum):
139        'members become strings'
140    class Name(StrEnum):
141        BDFL = 'Guido van Rossum'
142        FLUFL = 'Barry Warsaw'
143except Exception:
144    Name = sys.exc_info()[1]
145
146try:
147    Question = Enum('Question', 'who what when where why', module=__name__)
148except Exception:
149    Question = sys.exc_info()[1]
150
151try:
152    Answer = Enum('Answer', 'him this then there because')
153except Exception:
154    Answer = sys.exc_info()[1]
155
156try:
157    Theory = Enum('Theory', 'rule law supposition', qualname='spanish_inquisition')
158except Exception:
159    Theory = sys.exc_info()[1]
160
161try:
162    class WhatsIt(NamedTuple):
163        def what(self):
164            return self[0]
165    class ThatsIt(WhatsIt):
166        blah = 0
167        bleh = 1
168except Exception:
169    ThatsIt = sys.exc_info()[1]
170
171# for doctests
172try:
173    class Fruit(Enum):
174        tomato = 1
175        banana = 2
176        cherry = 3
177except Exception:
178    pass
179
180def test_pickle_dump_load(assertion, source, target=None, protocol=(0, HIGHEST_PROTOCOL)):
181    start, stop = protocol
182    failures = []
183    for protocol in range(start, stop+1):
184        try:
185            if target is None:
186                # if isinstance(source, Enum):
187                #     print('tpdl 1')
188                #     assertion(loads(dumps(source, protocol=protocol)) is source)
189                # else:
190                    # print('tpdl 2')
191                    assertion(loads(dumps(source, protocol=protocol)), source)
192            else:
193                # print('tpdl 3')
194                assertion(loads(dumps(source, protocol=protocol)), target)
195        except Exception:
196            exc, tb = sys.exc_info()[1:]
197            failures.append('%2d: %s' %(protocol, exc))
198    if failures:
199        raise ValueError('Failed with protocols: %s' % ', '.join(failures))
200
201def test_pickle_exception(assertion, exception, obj,
202        protocol=(0, HIGHEST_PROTOCOL)):
203    start, stop = protocol
204    failures = []
205    for protocol in range(start, stop+1):
206        try:
207            assertion(exception, dumps, obj, protocol=protocol)
208        except Exception:
209            exc = sys.exc_info()[1]
210            failures.append('%d: %s %s' % (protocol, exc.__class__.__name__, exc))
211    if failures:
212        raise ValueError('Failed with protocols: %s' % ', '.join(failures))
213
214if pyver >= 3.0:
215    from aenum.test_v3 import TestEnumV3, TestOrderV3, TestNamedTupleV3
216    from aenum import test_v3
217    test_v3.pyver = pyver
218    test_v3.IntStooges = IntStooges
219    test_v3.test_pickle_exception = test_pickle_exception
220    test_v3.test_pickle_dump_load = test_pickle_dump_load
221
222# for subclassing tests
223
224class classproperty(object):
225
226    def __init__(self, fget=None, fset=None, fdel=None, doc=None):
227        self.fget = fget
228        self.fset = fset
229        self.fdel = fdel
230        if doc is None and fget is not None:
231            doc = fget.__doc__
232        self.__doc__ = doc
233
234    def __get__(self, instance, ownerclass):
235        return self.fget(ownerclass)
236
237
238# tests
239class TestHelpers(TestCase):
240    # _is_descriptor, _is_sunder, _is_dunder
241
242    def test_is_descriptor(self):
243        class foo:
244            pass
245        for attr in ('__get__','__set__','__delete__'):
246            obj = foo()
247            self.assertFalse(aenum._is_descriptor(obj))
248            setattr(obj, attr, 1)
249            self.assertTrue(aenum._is_descriptor(obj))
250
251    def test_is_sunder(self):
252        for s in ('_a_', '_aa_'):
253            self.assertTrue(aenum._is_sunder(s))
254
255        for s in ('a', 'a_', '_a', '__a', 'a__', '__a__', '_a__', '__a_', '_',
256                '__', '___', '____', '_____',):
257            self.assertFalse(aenum._is_sunder(s))
258
259    def test_is_dunder(self):
260        for s in ('__a__', '__aa__'):
261            self.assertTrue(aenum._is_dunder(s))
262        for s in ('a', 'a_', '_a', '__a', 'a__', '_a_', '_a__', '__a_', '_',
263                '__', '___', '____', '_____',):
264            self.assertFalse(aenum._is_dunder(s))
265
266    def test_auto(self):
267        def tester(first, op, final, second=None):
268            if second is None:
269                left = auto()
270                value = op(left)
271                left.value = first
272                self.assertEqual(value.value, final,
273                        "%s %r -> %r != %r" % (op.__name__, first, value, final))
274            else:
275                left = first
276                right = auto()
277                value = op(left, right)
278                right.value = second
279                self.assertEqual(value.value, final,
280                        "forward: %r %s %r -> %r != %r" % (first, op.__name__, second, value.value, final))
281                left = auto()
282                right = second
283                value = op(left, right)
284                left.value = first
285                self.assertEqual(value.value, final,
286                        "reversed: %r %s %r -> %r != %r" % (second, op.__name__, first, value.value, final))
287        for args in (
288                (1, _abs_, abs(1)),
289                (-3, _abs_, abs(-3)),
290                (1, _add_, 1+2, 2),
291                (25, _floordiv_, 25 // 5, 5),
292                (49, _truediv_, 49 / 9, 9),
293                (6, _mod_, 6 % 9, 9),
294                (5, _lshift_, 5 << 2, 2),
295                (5, _rshift_, 5 >> 2, 2),
296                (3, _mul_, 3 * 6, 6),
297                (5, _neg_, -5),
298                (-4, _pos_, +(-4)),
299                (2, _pow_, 2**5, 5),
300                (7, _sub_, 7 - 10, 10),
301                (1, _or_, 1 | 2, 2),
302                (3, _xor_, 3 ^ 6, 6),
303                (3, _and_, 3 & 6, 6),
304                (7, _inv_, ~7),
305                ('a', _add_, 'a'+'b', 'b'),
306                ('a', _mul_, 'a' * 3, 3),
307                ):
308            tester(*args)
309        # operator.div is gone in 3
310        if pyver < 3:
311            tester(12, _div_, 12 // 5, 5)
312        # strings are a pain
313        left = auto()
314        right = 'eggs'
315        value = _mod_(left, right)
316        left.value = 'I see 17 %s!'
317        self.assertEqual(value.value, 'I see 17 %s!' % 'eggs')
318
319    def test_constant(self):
320        errors = []
321        def tester(first, op, final, second=None):
322            if second is None:
323                primary = constant(first)
324                secondary = constant(op(primary))
325                if secondary.value != final:
326                    errors.append(
327                        "%s %r -> %r != %r" % (op.__name__, first, secondary.value, final),
328                        )
329            else:
330                left = constant(first)
331                right = second
332                value = op(left, right)
333                if value != final:
334                    errors.append(
335                        "forward: %r %s %r -> %r != %r" % (first, op.__name__, second, value, final),
336                        )
337                left = first
338                right = constant(second)
339                value = op(left, right)
340                if value != final:
341                    errors.append(
342                        "reversed: %r %s %r -> %r != %r" % (second, op.__name__, first, value, final),
343                        )
344        for args in (
345                (1, _abs_, abs(1)),
346                (-3, _abs_, abs(-3)),
347                (1, _add_, 1+2, 2),
348                (25, _floordiv_, 25 // 5, 5),
349                (49, _truediv_, 49 / 9, 9),
350                (6, _mod_, 6 % 9, 9),
351                (5, _lshift_, 5 << 2, 2),
352                (5, _rshift_, 5 >> 2, 2),
353                (3, _mul_, 3 * 6, 6),
354                (5, _neg_, -5),
355                (-4, _pos_, +(-4)),
356                (2, _pow_, 2**5, 5),
357                (7, _sub_, 7 - 10, 10),
358                (1, _or_, 1 | 2, 2),
359                (3, _xor_, 3 ^ 6, 6),
360                (3, _and_, 3 & 6, 6),
361                (7, _inv_, ~7),
362                ('a', _add_, 'a'+'b', 'b'),
363                ('a', _mul_, 'a' * 3, 3),
364                ):
365            tester(*args)
366        # operator.div is gone in 3
367        if pyver < 3:
368            tester(12, _div_, 12 // 5, 5)
369        # strings are a pain
370        left = constant('I see 17 %s!')
371        right = 'eggs'
372        value = _mod_(left, right)
373        if value != 'I see 17 %s!' % 'eggs':
374            errors.append("'I see 17 eggs!' != %r" % value)
375        if errors:
376            print()
377            for error in errors:
378                print(error)
379            self.assertTrue(False)
380
381
382class TestEnum(TestCase):
383
384    def setUp(self):
385        class Season(Enum):
386            SPRING = 1
387            SUMMER = 2
388            AUTUMN = 3
389            WINTER = 4
390        self.Season = Season
391
392        class Konstants(float, Enum):
393            E = 2.7182818
394            PI = 3.1415926
395            TAU = 2 * PI
396        self.Konstants = Konstants
397
398        class Grades(IntEnum):
399            A = 5
400            B = 4
401            C = 3
402            D = 2
403            F = 0
404        self.Grades = Grades
405
406        class Directional(str, Enum):
407            EAST = 'east'
408            WEST = 'west'
409            NORTH = 'north'
410            SOUTH = 'south'
411        self.Directional = Directional
412
413        from datetime import date
414        class Holiday(date, Enum):
415            NEW_YEAR = 2013, 1, 1
416            IDES_OF_MARCH = 2013, 3, 15
417        self.Holiday = Holiday
418
419    def test_members_is_ordereddict_if_ordered(self):
420        class Ordered(Enum):
421            __order__ = 'first second third'
422            first = 'bippity'
423            second = 'boppity'
424            third = 'boo'
425        self.assertTrue(type(Ordered.__members__) is OrderedDict)
426
427    def test_members_is_ordereddict_if_not_ordered(self):
428        class Unordered(Enum):
429            this = 'that'
430            these = 'those'
431        self.assertTrue(type(Unordered.__members__) is OrderedDict)
432
433    def test_enum_in_enum_out(self):
434        Season = self.Season
435        self.assertTrue(Season(Season.WINTER) is Season.WINTER)
436
437    def test_enum_value(self):
438        Season = self.Season
439        self.assertEqual(Season.SPRING.value, 1)
440
441    def test_intenum_value(self):
442        self.assertEqual(IntStooges.CURLY.value, 2)
443
444    def test_enum(self):
445        Season = self.Season
446        lst = list(Season)
447        self.assertEqual(len(lst), len(Season))
448        self.assertEqual(len(Season), 4, Season)
449        self.assertEqual(
450            [Season.SPRING, Season.SUMMER, Season.AUTUMN, Season.WINTER], lst)
451
452        for i, season in enumerate('SPRING SUMMER AUTUMN WINTER'.split()):
453            i += 1
454            e = Season(i)
455            self.assertEqual(e, getattr(Season, season))
456            self.assertEqual(e.value, i)
457            self.assertNotEqual(e, i)
458            self.assertEqual(e.name, season)
459            self.assertTrue(e in Season)
460            self.assertTrue(type(e) is Season)
461            self.assertTrue(isinstance(e, Season))
462            self.assertEqual(str(e), 'Season.' + season)
463            self.assertEqual(
464                    repr(e),
465                    '<Season.%s: %s>' % (season, i),
466                    )
467    def test_enum_helper(self):
468        e1 = enum(1, 2, three=9)
469        e2 = enum(1, 2, three=9)
470        e3 = enum(1, 2, 9)
471        self.assertTrue(e1 is not e2)
472        self.assertEqual(e1, e2)
473        self.assertNotEqual(e1, e3)
474        self.assertNotEqual(e2, e3)
475
476    def test_enum_in_enum(self):
477        #
478        class Level(Enum):
479            _order_ = 'DATA_CHECK DESIGN_CHECK ALERT'
480            #
481            def __new__(cls, *args, **kwds):
482                member = object.__new__(cls)
483                member._value_ = len(cls) + 1  # members are 1-based
484                return member
485            #
486            def __init__(self, prereq=None, dependent=None):
487                # create priority level lists
488                self.lower_priority_levels = list(self.__class__._member_map_.values())
489                self.greater_priority_levels = []
490                # update previous members' greater priority list
491                for member in self.lower_priority_levels:
492                    member.greater_priority_levels.append(self)
493                # and save prereq and dependent
494                self.prerequisite = prereq and self.__class__[prereq.name] or None
495                self.dependent = dependent and self.__class__[dependent.name] or None
496            #
497            DATA_CHECK = enum()
498            DESIGN_CHECK = enum(DATA_CHECK)
499            ALERT = enum(None, DATA_CHECK)
500        #
501        self.assertEqual(Level.DATA_CHECK.value, 1)
502        self.assertEqual(Level.DATA_CHECK.prerequisite, None)
503        self.assertEqual(Level.DATA_CHECK.dependent, None)
504        self.assertEqual(Level.DESIGN_CHECK.prerequisite, Level.DATA_CHECK)
505        self.assertEqual(Level.DESIGN_CHECK.dependent, None)
506        self.assertEqual(Level.ALERT.prerequisite, None)
507        self.assertEqual(Level.ALERT.dependent, Level.DATA_CHECK)
508
509    def test_value_name(self):
510        Season = self.Season
511        self.assertEqual(Season.SPRING.name, 'SPRING')
512        self.assertEqual(Season.SPRING.value, 1)
513        def set_name(obj, new_value):
514            obj.name = new_value
515        def set_value(obj, new_value):
516            obj.value = new_value
517        self.assertRaises(AttributeError, set_name, Season.SPRING, 'invierno', )
518        self.assertRaises(AttributeError, set_value, Season.SPRING, 2)
519
520    def test_attribute_deletion(self):
521        class Season(Enum):
522            SPRING = 1
523            SUMMER = 2
524            AUTUMN = 3
525            WINTER = 4
526
527            def spam(cls):
528                pass
529
530        self.assertTrue(hasattr(Season, 'spam'))
531        del Season.spam
532        self.assertFalse(hasattr(Season, 'spam'))
533
534        self.assertRaises(AttributeError, delattr, Season, 'SPRING')
535        self.assertRaises(AttributeError, delattr, Season, 'DRY')
536        self.assertRaises(AttributeError, delattr, Season.SPRING, 'name')
537
538    def test_bool_of_class(self):
539        class Empty(Enum):
540            pass
541        self.assertTrue(bool(Empty))
542
543    def test_bool_of_member(self):
544        class Count(Enum):
545            zero = 0
546            one = 1
547            two = 2
548        for member in Count:
549            self.assertTrue(bool(member))
550
551    def test_invalid_names(self):
552        def create_bad_class_1():
553            class Wrong(Enum):
554                mro = 9
555        def create_bad_class_2():
556            class Wrong(Enum):
557                _reserved_ = 3
558        self.assertRaises(ValueError, create_bad_class_1)
559        self.assertRaises(ValueError, create_bad_class_2)
560
561    def test_bool(self):
562        class Logic(Enum):
563            true = True
564            false = False
565            def __bool__(self):
566                return bool(self.value)
567            __nonzero__ = __bool__
568        self.assertTrue(Logic.true)
569        self.assertFalse(Logic.false)
570
571    def test_contains(self):
572        Season = self.Season
573        self.assertRaises(TypeError, lambda: 'AUTUMN' in Season)
574        self.assertTrue(Season.AUTUMN in Season)
575        self.assertRaises(TypeError, lambda: 3 not in Season)
576        val = Season(3)
577        self.assertTrue(val in Season)
578        #
579        class OtherEnum(Enum):
580            one = 1; two = 2
581        self.assertTrue(OtherEnum.two not in Season)
582        #
583        class Wierd(Enum):
584            this = [1, 2, 3]
585            that = (1, 2, 3)
586            those = {1: 1, 2: 2, 3: 3}
587        self.assertTrue(Wierd.this in Wierd)
588        self.assertRaises(TypeError, lambda: [1, 2, 3] in Wierd)
589        self.assertRaises(TypeError, lambda: {1: 1, 2: 2, 3: 3} in Wierd)
590
591    def test_member_contains(self):
592        self.assertRaises(TypeError, lambda: 'test' in self.Season.AUTUMN)
593
594    if pyver >= 2.6:     # when `format` came into being
595
596        def test_format_enum(self):
597            Season = self.Season
598            self.assertEqual('{0}'.format(Season.SPRING),
599                             '{0}'.format(str(Season.SPRING)))
600            self.assertEqual( '{0:}'.format(Season.SPRING),
601                              '{0:}'.format(str(Season.SPRING)))
602            self.assertEqual('{0:20}'.format(Season.SPRING),
603                             '{0:20}'.format(str(Season.SPRING)))
604            self.assertEqual('{0:^20}'.format(Season.SPRING),
605                             '{0:^20}'.format(str(Season.SPRING)))
606            self.assertEqual('{0:>20}'.format(Season.SPRING),
607                             '{0:>20}'.format(str(Season.SPRING)))
608            self.assertEqual('{0:<20}'.format(Season.SPRING),
609                             '{0:<20}'.format(str(Season.SPRING)))
610
611        def test_custom_format(self):
612            class TestFloat(float, Enum):
613                one = 1.0
614                two = 2.0
615                def __format__(self, spec):
616                    return 'TestFloat success!'
617            self.assertEqual(str(TestFloat.one), 'TestFloat.one')
618            self.assertEqual('{0}'.format(TestFloat.one), 'TestFloat success!')
619
620        def test_format_with_custom_str(self):
621            class TestInt(int, Enum):
622                one = 1
623                two = 2
624                def __str__(self):
625                    return self.name * 3
626            self.assertEqual(str(TestInt.two), 'twotwotwo')
627            self.assertEqual('{0}'.format(TestInt.two), 'twotwotwo')
628
629        def assertFormatIsValue(self, spec, member):
630            self.assertEqual(spec.format(member), spec.format(member.value))
631
632        def test_format_enum_date(self):
633            Holiday = self.Holiday
634            self.assertFormatIsValue('{0}', Holiday.IDES_OF_MARCH)
635            self.assertFormatIsValue('{0:}', Holiday.IDES_OF_MARCH)
636            self.assertFormatIsValue('{0:20}', Holiday.IDES_OF_MARCH)
637            self.assertFormatIsValue('{0:^20}', Holiday.IDES_OF_MARCH)
638            self.assertFormatIsValue('{0:>20}', Holiday.IDES_OF_MARCH)
639            self.assertFormatIsValue('{0:<20}', Holiday.IDES_OF_MARCH)
640            self.assertFormatIsValue('{0:%Y %m}', Holiday.IDES_OF_MARCH)
641            self.assertFormatIsValue('{0:%Y %m %M:00}', Holiday.IDES_OF_MARCH)
642
643        def test_format_enum_float(self):
644            Konstants = self.Konstants
645            self.assertFormatIsValue('{0}', Konstants.TAU)
646            self.assertFormatIsValue('{0:}', Konstants.TAU)
647            self.assertFormatIsValue('{0:20}', Konstants.TAU)
648            self.assertFormatIsValue('{0:^20}', Konstants.TAU)
649            self.assertFormatIsValue('{0:>20}', Konstants.TAU)
650            self.assertFormatIsValue('{0:<20}', Konstants.TAU)
651            self.assertFormatIsValue('{0:n}', Konstants.TAU)
652            self.assertFormatIsValue('{0:5.2}', Konstants.TAU)
653            self.assertFormatIsValue('{0:f}', Konstants.TAU)
654
655        def test_format_enum_int(self):
656            Grades = self.Grades
657            self.assertFormatIsValue('{0}', Grades.C)
658            self.assertFormatIsValue('{0:}', Grades.C)
659            self.assertFormatIsValue('{0:20}', Grades.C)
660            self.assertFormatIsValue('{0:^20}', Grades.C)
661            self.assertFormatIsValue('{0:>20}', Grades.C)
662            self.assertFormatIsValue('{0:<20}', Grades.C)
663            self.assertFormatIsValue('{0:+}', Grades.C)
664            self.assertFormatIsValue('{0:08X}', Grades.C)
665            self.assertFormatIsValue('{0:b}', Grades.C)
666
667        def test_format_enum_str(self):
668            Directional = self.Directional
669            self.assertFormatIsValue('{0}', Directional.WEST)
670            self.assertFormatIsValue('{0:}', Directional.WEST)
671            self.assertFormatIsValue('{0:20}', Directional.WEST)
672            self.assertFormatIsValue('{0:^20}', Directional.WEST)
673            self.assertFormatIsValue('{0:>20}', Directional.WEST)
674            self.assertFormatIsValue('{0:<20}', Directional.WEST)
675
676    def test_hash(self):
677        Season = self.Season
678        dates = {}
679        dates[Season.WINTER] = '1225'
680        dates[Season.SPRING] = '0315'
681        dates[Season.SUMMER] = '0704'
682        dates[Season.AUTUMN] = '1031'
683        self.assertEqual(dates[Season.AUTUMN], '1031')
684
685    def test_enum_duplicates(self):
686        class Season(Enum):
687            __order__ = "SPRING SUMMER AUTUMN WINTER"
688            SPRING = 1
689            SUMMER = 2
690            AUTUMN = FALL = 3
691            WINTER = 4
692            ANOTHER_SPRING = 1
693        lst = list(Season)
694        self.assertEqual(
695            lst,
696            [Season.SPRING, Season.SUMMER,
697             Season.AUTUMN, Season.WINTER,
698            ])
699        self.assertTrue(Season.FALL is Season.AUTUMN)
700        self.assertEqual(Season.FALL.value, 3)
701        self.assertEqual(Season.AUTUMN.value, 3)
702        self.assertTrue(Season(3) is Season.AUTUMN)
703        self.assertTrue(Season(1) is Season.SPRING)
704        self.assertEqual(Season.FALL.name, 'AUTUMN')
705        self.assertEqual(
706                set([k for k,v in Season.__members__.items() if v.name != k]),
707                set(['FALL', 'ANOTHER_SPRING']),
708                )
709
710    def test_enum_with_value_name(self):
711        class Huh(Enum):
712            _order_ = 'name value'
713            name = 1
714            value = 2
715        self.assertEqual(
716            list(Huh),
717            [Huh.name, Huh.value],
718            )
719        self.assertTrue(type(Huh.name) is Huh)
720        self.assertEqual(Huh.name.name, 'name')
721        self.assertEqual(Huh.name.value, 1)
722
723    def test_intenum_from_scratch(self):
724        class phy(int, Enum):
725            pi = 3
726            tau = 2 * pi
727        self.assertTrue(phy.pi < phy.tau)
728
729    def test_intenum_inherited(self):
730        class IntEnum(int, Enum):
731            pass
732        class phy(IntEnum):
733            pi = 3
734            tau = 2 * pi
735        self.assertTrue(phy.pi < phy.tau)
736
737    def test_floatenum_from_scratch(self):
738        class phy(float, Enum):
739            pi = 3.1415926
740            tau = 2 * pi
741        self.assertTrue(phy.pi < phy.tau)
742
743    def test_floatenum_inherited(self):
744        class FloatEnum(float, Enum):
745            pass
746        class phy(FloatEnum):
747            pi = 3.1415926
748            tau = 2 * pi
749        self.assertTrue(phy.pi < phy.tau)
750
751    def test_strenum_from_scratch(self):
752        class phy(str, Enum):
753            pi = 'Pi'
754            tau = 'Tau'
755        self.assertTrue(phy.pi < phy.tau)
756
757    def test_strenum_inherited(self):
758        class StrEnum(str, Enum):
759            pass
760        class phy(StrEnum):
761            pi = 'Pi'
762            tau = 'Tau'
763        self.assertTrue(phy.pi < phy.tau)
764
765    def test_intenum(self):
766        class WeekDay(IntEnum):
767            SUNDAY = 1
768            MONDAY = 2
769            TUESDAY = 3
770            WEDNESDAY = 4
771            THURSDAY = 5
772            FRIDAY = 6
773            SATURDAY = 7
774
775        self.assertEqual(['a', 'b', 'c'][WeekDay.MONDAY], 'c')
776        self.assertEqual([i for i in range(WeekDay.TUESDAY)], [0, 1, 2])
777
778        lst = list(WeekDay)
779        self.assertEqual(len(lst), len(WeekDay))
780        self.assertEqual(len(WeekDay), 7)
781        target = 'SUNDAY MONDAY TUESDAY WEDNESDAY THURSDAY FRIDAY SATURDAY'
782        target = target.split()
783        for i, weekday in enumerate(target):
784            i += 1
785            e = WeekDay(i)
786            self.assertEqual(e, i)
787            self.assertEqual(int(e), i)
788            self.assertEqual(e.name, weekday)
789            self.assertTrue(e in WeekDay)
790            self.assertEqual(lst.index(e)+1, i)
791            self.assertTrue(0 < e < 8)
792            self.assertTrue(type(e) is WeekDay)
793            self.assertTrue(isinstance(e, int))
794            self.assertTrue(isinstance(e, Enum))
795
796    def test_intenum_duplicates(self):
797        class WeekDay(IntEnum):
798            __order__ = 'SUNDAY MONDAY TUESDAY WEDNESDAY THURSDAY FRIDAY SATURDAY'
799            SUNDAY = 1
800            MONDAY = 2
801            TUESDAY = TEUSDAY = 3
802            WEDNESDAY = 4
803            THURSDAY = 5
804            FRIDAY = 6
805            SATURDAY = 7
806        self.assertTrue(WeekDay.TEUSDAY is WeekDay.TUESDAY)
807        self.assertEqual(WeekDay(3).name, 'TUESDAY')
808        self.assertEqual([k for k,v in WeekDay.__members__.items()
809                if v.name != k], ['TEUSDAY', ])
810
811    def test_floatenum_fromhex(self):
812        h = float.hex(FloatStooges.MOE.value)
813        self.assertIs(FloatStooges.fromhex(h), FloatStooges.MOE)
814        h = float.hex(FloatStooges.MOE.value + 0.01)
815        with self.assertRaises(ValueError):
816            FloatStooges.fromhex(h)
817
818    def test_pickle_enum(self):
819        if isinstance(Stooges, Exception):
820            raise Stooges
821        test_pickle_dump_load(self.assertTrue, Stooges.CURLY)
822        test_pickle_dump_load(self.assertTrue, Stooges)
823
824    def test_pickle_int(self):
825        if isinstance(IntStooges, Exception):
826            raise IntStooges
827        test_pickle_dump_load(self.assertTrue, IntStooges.CURLY)
828        test_pickle_dump_load(self.assertTrue, IntStooges)
829
830    def test_pickle_float(self):
831        if isinstance(FloatStooges, Exception):
832            raise FloatStooges
833        test_pickle_dump_load(self.assertTrue, FloatStooges.CURLY)
834        test_pickle_dump_load(self.assertTrue, FloatStooges)
835
836    def test_pickle_enum_function(self):
837        if isinstance(Answer, Exception):
838            raise Answer
839        test_pickle_dump_load(self.assertTrue, Answer.him)
840        test_pickle_dump_load(self.assertTrue, Answer)
841
842    def test_pickle_enum_function_with_module(self):
843        if isinstance(Question, Exception):
844            raise Question
845        test_pickle_dump_load(self.assertTrue, Question.who)
846        test_pickle_dump_load(self.assertTrue, Question)
847
848    def test_pickle_by_name(self):
849        class ReplaceGlobalInt(IntEnum):
850            ONE = 1
851            TWO = 2
852        ReplaceGlobalInt.__reduce_ex__ = _reduce_ex_by_name
853        for proto in range(HIGHEST_PROTOCOL):
854            self.assertEqual(ReplaceGlobalInt.TWO.__reduce_ex__(proto), 'TWO')
855
856    def test_exploding_pickle(self):
857        BadPickle = Enum('BadPickle', 'dill sweet bread-n-butter')
858        aenum._make_class_unpicklable(BadPickle)
859        globals()['BadPickle'] = BadPickle
860        test_pickle_exception(self.assertRaises, TypeError, BadPickle.dill)
861        test_pickle_exception(self.assertRaises, PicklingError, BadPickle)
862
863    def test_string_enum(self):
864        class SkillLevel(str, Enum):
865            master = 'what is the sound of one hand clapping?'
866            journeyman = 'why did the chicken cross the road?'
867            apprentice = 'knock, knock!'
868        self.assertEqual(SkillLevel.apprentice, 'knock, knock!')
869
870    def test_getattr_getitem(self):
871        class Period(Enum):
872            morning = 1
873            noon = 2
874            evening = 3
875            night = 4
876        self.assertTrue(Period(2) is Period.noon)
877        self.assertTrue(getattr(Period, 'night') is Period.night)
878        self.assertTrue(Period['morning'] is Period.morning)
879
880    def test_getattr_dunder(self):
881        Season = self.Season
882        self.assertTrue(getattr(Season, '__hash__'))
883
884    def test_iteration_order(self):
885        class Season(Enum):
886            __order__ = 'SUMMER WINTER AUTUMN SPRING'
887            SUMMER = 2
888            WINTER = 4
889            AUTUMN = 3
890            SPRING = 1
891        self.assertEqual(
892                list(Season),
893                [Season.SUMMER, Season.WINTER, Season.AUTUMN, Season.SPRING],
894                )
895
896    def test_iteration_order_reversed(self):
897        self.assertEqual(
898                list(reversed(self.Season)),
899                [self.Season.WINTER, self.Season.AUTUMN, self.Season.SUMMER,
900                 self.Season.SPRING]
901                )
902
903    def test_iteration_order_with_unorderable_values(self):
904        class Complex(Enum):
905            a = complex(7, 9)
906            b = complex(3.14, 2)
907            c = complex(1, -1)
908            d = complex(-77, 32)
909        self.assertEqual(
910                list(Complex),
911                [Complex.a, Complex.b, Complex.c, Complex.d],
912                )
913
914    def test_programatic_function_string(self):
915        SummerMonth = Enum('SummerMonth', 'june july august')
916        lst = list(SummerMonth)
917        self.assertEqual(len(lst), len(SummerMonth))
918        self.assertEqual(len(SummerMonth), 3, SummerMonth)
919        self.assertEqual(
920                [SummerMonth.june, SummerMonth.july, SummerMonth.august],
921                lst,
922                )
923        for i, month in enumerate('june july august'.split()):
924            i += 1
925            e = SummerMonth(i)
926            self.assertEqual(int(e.value), i)
927            self.assertNotEqual(e, i)
928            self.assertEqual(e.name, month)
929            self.assertTrue(e in SummerMonth)
930            self.assertTrue(type(e) is SummerMonth)
931
932    def test_programatic_function_string_with_start(self):
933        SummerMonth = Enum('SummerMonth', 'june july august', start=10)
934        lst = list(SummerMonth)
935        self.assertEqual(len(lst), len(SummerMonth))
936        self.assertEqual(len(SummerMonth), 3, SummerMonth)
937        self.assertEqual(
938                [SummerMonth.june, SummerMonth.july, SummerMonth.august],
939                lst,
940                )
941        for i, month in enumerate('june july august'.split(), 10):
942            e = SummerMonth(i)
943            self.assertEqual(int(e.value), i)
944            self.assertNotEqual(e, i)
945            self.assertEqual(e.name, month)
946            self.assertTrue(e in SummerMonth)
947            self.assertTrue(type(e) is SummerMonth)
948
949    def test_programatic_function_string_list(self):
950        SummerMonth = Enum('SummerMonth', ['june', 'july', 'august'])
951        lst = list(SummerMonth)
952        self.assertEqual(len(lst), len(SummerMonth))
953        self.assertEqual(len(SummerMonth), 3, SummerMonth)
954        self.assertEqual(
955                [SummerMonth.june, SummerMonth.july, SummerMonth.august],
956                lst,
957                )
958        for i, month in enumerate('june july august'.split()):
959            i += 1
960            e = SummerMonth(i)
961            self.assertEqual(int(e.value), i)
962            self.assertNotEqual(e, i)
963            self.assertEqual(e.name, month)
964            self.assertTrue(e in SummerMonth)
965            self.assertTrue(type(e) is SummerMonth)
966
967    def test_programatic_function_string_list_with_start(self):
968        SummerMonth = Enum('SummerMonth', ['june', 'july', 'august'], start=20)
969        lst = list(SummerMonth)
970        self.assertEqual(len(lst), len(SummerMonth))
971        self.assertEqual(len(SummerMonth), 3, SummerMonth)
972        self.assertEqual(
973                [SummerMonth.june, SummerMonth.july, SummerMonth.august],
974                lst,
975                )
976        for i, month in enumerate('june july august'.split(), 20):
977            e = SummerMonth(i)
978            self.assertEqual(int(e.value), i)
979            self.assertNotEqual(e, i)
980            self.assertEqual(e.name, month)
981            self.assertTrue(e in SummerMonth)
982            self.assertTrue(type(e) is SummerMonth)
983
984    def test_programatic_function_iterable(self):
985        SummerMonth = Enum(
986                'SummerMonth',
987                (('june', 1), ('july', 2), ('august', 3))
988                )
989        lst = list(SummerMonth)
990        self.assertEqual(len(lst), len(SummerMonth))
991        self.assertEqual(len(SummerMonth), 3, SummerMonth)
992        self.assertEqual(
993                [SummerMonth.june, SummerMonth.july, SummerMonth.august],
994                lst,
995                )
996        for i, month in enumerate('june july august'.split()):
997            i += 1
998            e = SummerMonth(i)
999            self.assertEqual(int(e.value), i)
1000            self.assertNotEqual(e, i)
1001            self.assertEqual(e.name, month)
1002            self.assertTrue(e in SummerMonth)
1003            self.assertTrue(type(e) is SummerMonth)
1004
1005    def test_programatic_function_from_dict(self):
1006        SummerMonth = Enum(
1007                'SummerMonth',
1008                dict((('june', 1), ('july', 2), ('august', 3)))
1009                )
1010        lst = list(SummerMonth)
1011        self.assertEqual(len(lst), len(SummerMonth))
1012        self.assertEqual(len(SummerMonth), 3, SummerMonth)
1013        if pyver < 3.0:
1014            self.assertEqual(
1015                    [SummerMonth.june, SummerMonth.july, SummerMonth.august],
1016                    lst,
1017                    )
1018        for i, month in enumerate('june july august'.split()):
1019            i += 1
1020            e = SummerMonth(i)
1021            self.assertEqual(int(e.value), i)
1022            self.assertNotEqual(e, i)
1023            self.assertEqual(e.name, month)
1024            self.assertTrue(e in SummerMonth)
1025            self.assertTrue(type(e) is SummerMonth)
1026
1027    def test_programatic_function_type(self):
1028        SummerMonth = Enum('SummerMonth', 'june july august', type=int)
1029        lst = list(SummerMonth)
1030        self.assertEqual(len(lst), len(SummerMonth))
1031        self.assertEqual(len(SummerMonth), 3, SummerMonth)
1032        self.assertEqual(
1033                [SummerMonth.june, SummerMonth.july, SummerMonth.august],
1034                lst,
1035                )
1036        for i, month in enumerate('june july august'.split()):
1037            i += 1
1038            e = SummerMonth(i)
1039            self.assertEqual(e, i)
1040            self.assertEqual(e.name, month)
1041            self.assertTrue(e in SummerMonth)
1042            self.assertTrue(type(e) is SummerMonth)
1043
1044    def test_programatic_function_type_with_start(self):
1045        SummerMonth = Enum('SummerMonth', 'june july august', type=int, start=30)
1046        lst = list(SummerMonth)
1047        self.assertEqual(len(lst), len(SummerMonth))
1048        self.assertEqual(len(SummerMonth), 3, SummerMonth)
1049        self.assertEqual(
1050                [SummerMonth.june, SummerMonth.july, SummerMonth.august],
1051                lst,
1052                )
1053        for i, month in enumerate('june july august'.split(), 30):
1054            e = SummerMonth(i)
1055            self.assertEqual(e, i)
1056            self.assertEqual(e.name, month)
1057            self.assertTrue(e in SummerMonth)
1058            self.assertTrue(type(e) is SummerMonth)
1059
1060    def test_programatic_function_type_from_subclass(self):
1061        SummerMonth = IntEnum('SummerMonth', 'june july august')
1062        lst = list(SummerMonth)
1063        self.assertEqual(len(lst), len(SummerMonth))
1064        self.assertEqual(len(SummerMonth), 3, SummerMonth)
1065        self.assertEqual(
1066                [SummerMonth.june, SummerMonth.july, SummerMonth.august],
1067                lst,
1068                )
1069        for i, month in enumerate('june july august'.split()):
1070            i += 1
1071            e = SummerMonth(i)
1072            self.assertEqual(e, i)
1073            self.assertEqual(e.name, month)
1074            self.assertTrue(e in SummerMonth)
1075            self.assertTrue(type(e) is SummerMonth)
1076
1077    def test_programatic_function_type_from_subclass_with_start(self):
1078        SummerMonth = IntEnum('SummerMonth', 'june july august', start=40)
1079        lst = list(SummerMonth)
1080        self.assertEqual(len(lst), len(SummerMonth))
1081        self.assertEqual(len(SummerMonth), 3, SummerMonth)
1082        self.assertEqual(
1083                [SummerMonth.june, SummerMonth.july, SummerMonth.august],
1084                lst,
1085                )
1086        for i, month in enumerate('june july august'.split(), 40):
1087            e = SummerMonth(i)
1088            self.assertEqual(e, i)
1089            self.assertEqual(e.name, month)
1090            self.assertTrue(e in SummerMonth)
1091            self.assertTrue(type(e) is SummerMonth)
1092
1093    def test_programatic_function_unicode(self):
1094        SummerMonth = Enum('SummerMonth', unicode('june july august'))
1095        lst = list(SummerMonth)
1096        self.assertEqual(len(lst), len(SummerMonth))
1097        self.assertEqual(len(SummerMonth), 3, SummerMonth)
1098        self.assertEqual(
1099                [SummerMonth.june, SummerMonth.july, SummerMonth.august],
1100                lst,
1101                )
1102        for i, month in enumerate(unicode('june july august').split()):
1103            i += 1
1104            e = SummerMonth(i)
1105            self.assertEqual(int(e.value), i)
1106            self.assertNotEqual(e, i)
1107            self.assertEqual(e.name, month)
1108            self.assertTrue(e in SummerMonth)
1109            self.assertTrue(type(e) is SummerMonth)
1110
1111    def test_programatic_function_unicode_list(self):
1112        SummerMonth = Enum('SummerMonth', [unicode('june'), unicode('july'), unicode('august')])
1113        lst = list(SummerMonth)
1114        self.assertEqual(len(lst), len(SummerMonth))
1115        self.assertEqual(len(SummerMonth), 3, SummerMonth)
1116        self.assertEqual(
1117                [SummerMonth.june, SummerMonth.july, SummerMonth.august],
1118                lst,
1119                )
1120        for i, month in enumerate(unicode('june july august').split()):
1121            i += 1
1122            e = SummerMonth(i)
1123            self.assertEqual(int(e.value), i)
1124            self.assertNotEqual(e, i)
1125            self.assertEqual(e.name, month)
1126            self.assertTrue(e in SummerMonth)
1127            self.assertTrue(type(e) is SummerMonth)
1128
1129    def test_programatic_function_unicode_iterable(self):
1130        SummerMonth = Enum(
1131                'SummerMonth',
1132                ((unicode('june'), 1), (unicode('july'), 2), (unicode('august'), 3))
1133                )
1134        lst = list(SummerMonth)
1135        self.assertEqual(len(lst), len(SummerMonth))
1136        self.assertEqual(len(SummerMonth), 3, SummerMonth)
1137        self.assertEqual(
1138                [SummerMonth.june, SummerMonth.july, SummerMonth.august],
1139                lst,
1140                )
1141        for i, month in enumerate(unicode('june july august').split()):
1142            i += 1
1143            e = SummerMonth(i)
1144            self.assertEqual(int(e.value), i)
1145            self.assertNotEqual(e, i)
1146            self.assertEqual(e.name, month)
1147            self.assertTrue(e in SummerMonth)
1148            self.assertTrue(type(e) is SummerMonth)
1149
1150    def test_programatic_function_from_unicode_dict(self):
1151        SummerMonth = Enum(
1152                'SummerMonth',
1153                dict(((unicode('june'), 1), (unicode('july'), 2), (unicode('august'), 3)))
1154                )
1155        lst = list(SummerMonth)
1156        self.assertEqual(len(lst), len(SummerMonth))
1157        self.assertEqual(len(SummerMonth), 3, SummerMonth)
1158        if pyver < 3.0:
1159            self.assertEqual(
1160                    [SummerMonth.june, SummerMonth.july, SummerMonth.august],
1161                    lst,
1162                    )
1163        for i, month in enumerate(unicode('june july august').split()):
1164            i += 1
1165            e = SummerMonth(i)
1166            self.assertEqual(int(e.value), i)
1167            self.assertNotEqual(e, i)
1168            self.assertEqual(e.name, month)
1169            self.assertTrue(e in SummerMonth)
1170            self.assertTrue(type(e) is SummerMonth)
1171
1172    def test_programatic_function_unicode_type(self):
1173        SummerMonth = Enum('SummerMonth', unicode('june july august'), type=int)
1174        lst = list(SummerMonth)
1175        self.assertEqual(len(lst), len(SummerMonth))
1176        self.assertEqual(len(SummerMonth), 3, SummerMonth)
1177        self.assertEqual(
1178                [SummerMonth.june, SummerMonth.july, SummerMonth.august],
1179                lst,
1180                )
1181        for i, month in enumerate(unicode('june july august').split()):
1182            i += 1
1183            e = SummerMonth(i)
1184            self.assertEqual(e, i)
1185            self.assertEqual(e.name, month)
1186            self.assertTrue(e in SummerMonth)
1187            self.assertTrue(type(e) is SummerMonth)
1188
1189    def test_programatic_function_unicode_type_from_subclass(self):
1190        SummerMonth = IntEnum('SummerMonth', unicode('june july august'))
1191        lst = list(SummerMonth)
1192        self.assertEqual(len(lst), len(SummerMonth))
1193        self.assertEqual(len(SummerMonth), 3, SummerMonth)
1194        self.assertEqual(
1195                [SummerMonth.june, SummerMonth.july, SummerMonth.august],
1196                lst,
1197                )
1198        for i, month in enumerate(unicode('june july august').split()):
1199            i += 1
1200            e = SummerMonth(i)
1201            self.assertEqual(e, i)
1202            self.assertEqual(e.name, month)
1203            self.assertTrue(e in SummerMonth)
1204            self.assertTrue(type(e) is SummerMonth)
1205
1206    def test_programmatic_function_unicode_class(self):
1207        if pyver < 3.0:
1208            class_names = unicode('SummerMonth'), 'S\xfcmm\xe9rM\xf6nth'.decode('latin1')
1209        else:
1210            class_names = 'SummerMonth', 'S\xfcmm\xe9rM\xf6nth'
1211        for i, class_name in enumerate(class_names):
1212            if pyver < 3.0 and i == 1:
1213                self.assertRaises(TypeError, Enum, class_name, unicode('june july august'))
1214            else:
1215                SummerMonth = Enum(class_name, unicode('june july august'))
1216                lst = list(SummerMonth)
1217                self.assertEqual(len(lst), len(SummerMonth))
1218                self.assertEqual(len(SummerMonth), 3, SummerMonth)
1219                self.assertEqual(
1220                        [SummerMonth.june, SummerMonth.july, SummerMonth.august],
1221                        lst,
1222                        )
1223                for i, month in enumerate(unicode('june july august').split()):
1224                    i += 1
1225                    e = SummerMonth(i)
1226                    self.assertEqual(e.value, i)
1227                    self.assertEqual(e.name, month)
1228                    self.assertTrue(e in SummerMonth)
1229                    self.assertTrue(type(e) is SummerMonth)
1230
1231    def test_subclassing(self):
1232        if isinstance(Name, Exception):
1233            raise Name
1234        self.assertEqual(Name.BDFL, 'Guido van Rossum')
1235        self.assertTrue(Name.BDFL, Name('Guido van Rossum'))
1236        self.assertTrue(Name.BDFL is getattr(Name, 'BDFL'))
1237        test_pickle_dump_load(self.assertTrue, Name.BDFL)
1238
1239    def test_extending(self):
1240        def bad_extension():
1241            class Color(Enum):
1242                red = 1
1243                green = 2
1244                blue = 3
1245            class MoreColor(Color):
1246                cyan = 4
1247                magenta = 5
1248                yellow = 6
1249        self.assertRaises(TypeError, bad_extension)
1250
1251    def test_exclude_methods(self):
1252        class whatever(Enum):
1253            this = 'that'
1254            these = 'those'
1255            def really(self):
1256                return 'no, not %s' % self.value
1257        self.assertFalse(type(whatever.really) is whatever)
1258        self.assertEqual(whatever.this.really(), 'no, not that')
1259
1260    def test_wrong_inheritance_order(self):
1261        def wrong_inherit():
1262            class Wrong(Enum, str):
1263                NotHere = 'error before this point'
1264        self.assertRaises(TypeError, wrong_inherit)
1265
1266    def test_intenum_transitivity(self):
1267        class number(IntEnum):
1268            one = 1
1269            two = 2
1270            three = 3
1271        class numero(IntEnum):
1272            uno = 1
1273            dos = 2
1274            tres = 3
1275        self.assertEqual(number.one, numero.uno)
1276        self.assertEqual(number.two, numero.dos)
1277        self.assertEqual(number.three, numero.tres)
1278
1279    def test_introspection(self):
1280        class Number(IntEnum):
1281            one = 100
1282            two = 200
1283        self.assertTrue(Number.one._member_type_ is int)
1284        self.assertTrue(Number._member_type_ is int)
1285        class String(str, Enum):
1286            yarn = 'soft'
1287            rope = 'rough'
1288            wire = 'hard'
1289        self.assertTrue(String.yarn._member_type_ is str)
1290        self.assertTrue(String._member_type_ is str)
1291        class Plain(Enum):
1292            vanilla = 'white'
1293            one = 1
1294        self.assertTrue(Plain.vanilla._member_type_ is object)
1295        self.assertTrue(Plain._member_type_ is object)
1296
1297    def test_wrong_enum_in_call(self):
1298        class Monochrome(Enum):
1299            black = 0
1300            white = 1
1301        class Gender(Enum):
1302            male = 0
1303            female = 1
1304        self.assertRaises(ValueError, Monochrome, Gender.male)
1305
1306    def test_wrong_enum_in_mixed_call(self):
1307        class Monochrome(IntEnum):
1308            black = 0
1309            white = 1
1310        class Gender(Enum):
1311            male = 0
1312            female = 1
1313        self.assertRaises(ValueError, Monochrome, Gender.male)
1314
1315    def test_mixed_enum_in_call_1(self):
1316        class Monochrome(IntEnum):
1317            black = 0
1318            white = 1
1319        class Gender(IntEnum):
1320            male = 0
1321            female = 1
1322        self.assertTrue(Monochrome(Gender.female) is Monochrome.white)
1323
1324    def test_mixed_enum_in_call_2(self):
1325        class Monochrome(Enum):
1326            black = 0
1327            white = 1
1328        class Gender(IntEnum):
1329            male = 0
1330            female = 1
1331        self.assertTrue(Monochrome(Gender.male) is Monochrome.black)
1332
1333    def test_flufl_enum(self):
1334        class Fluflnum(Enum):
1335            def __int__(self):
1336                return int(self.value)
1337        class MailManOptions(Fluflnum):
1338            option1 = 1
1339            option2 = 2
1340            option3 = 3
1341        self.assertEqual(int(MailManOptions.option1), 1)
1342
1343    def test_no_such_enum_member(self):
1344        class Color(Enum):
1345            red = 1
1346            green = 2
1347            blue = 3
1348        self.assertRaises(ValueError, Color, 4)
1349        self.assertRaises(KeyError, Color.__getitem__, 'chartreuse')
1350
1351    def test_new_repr(self):
1352        class Color(Enum):
1353            red = 1
1354            green = 2
1355            blue = 3
1356            def __repr__(self):
1357                return "don't you just love shades of %s?" % self.name
1358        self.assertEqual(
1359                repr(Color.blue),
1360                "don't you just love shades of blue?",
1361                )
1362
1363    def test_inherited_repr(self):
1364        class MyEnum(Enum):
1365            def __repr__(self):
1366                return "My name is %s." % self.name
1367        class MyIntEnum(int, MyEnum):
1368            this = 1
1369            that = 2
1370            theother = 3
1371        self.assertEqual(repr(MyIntEnum.that), "My name is that.")
1372
1373    def test_multiple_mixin_mro(self):
1374        class auto_enum(EnumMeta):
1375            def __new__(metacls, cls, bases, classdict):
1376                original_dict = classdict
1377                temp_dict = metacls.__prepare__(cls, bases, {})
1378                if hasattr(original_dict, '_member_names'):
1379                    for k in original_dict._member_names:
1380                        temp_dict[k] = original_dict[k]
1381                    sunders = [k for k in original_dict.keys() if aenum._is_sunder(k)]
1382                else:
1383                    sunders = []
1384                    for k, v in original_dict.items():
1385                        if aenum._is_sunder(k):
1386                            sunders.append(k)
1387                        temp_dict[k] = v
1388                classdict = metacls.__prepare__(cls, bases, {})
1389                i = 0
1390                for k in sunders:
1391                    classdict[k] = original_dict[k]
1392                for k in temp_dict._member_names:
1393                    v = original_dict[k]
1394                    if v == ():
1395                        v = i
1396                    else:
1397                        i = v
1398                    i += 1
1399                    classdict[k] = v
1400                for k, v in original_dict.items():
1401                    if k not in temp_dict._member_names and k not in sunders:
1402                        classdict[k] = v
1403                return super(auto_enum, metacls).__new__(
1404                        metacls, cls, bases, classdict)
1405
1406        AutoNumberedEnum = auto_enum('AutoNumberedEnum', (Enum,), {})
1407
1408        AutoIntEnum = auto_enum('AutoIntEnum', (IntEnum,), {})
1409
1410        class TestAutoNumber(AutoNumberedEnum):
1411            a = ()
1412            b = 3
1413            c = ()
1414        self.assertEqual(TestAutoNumber.b.value, 3)
1415
1416        if pyver >= 3.0:
1417            self.assertEqual(
1418                [TestAutoNumber.a.value, TestAutoNumber.b.value, TestAutoNumber.c.value],
1419                [0, 3, 4],
1420                )
1421
1422        class TestAutoInt(AutoIntEnum):
1423            a = ()
1424            b = 3
1425            c = ()
1426        self.assertEqual(TestAutoInt.b, 3)
1427
1428        if pyver >= 3.0:
1429            self.assertEqual(
1430                [TestAutoInt.a.value, TestAutoInt.b.value, TestAutoInt.c.value],
1431                [0, 3, 4],
1432                )
1433
1434    def test_meta_reconfigure(self):
1435
1436        def identity(*args):
1437            if len(args) == 1:
1438                return args[0]
1439            return args
1440
1441        JSONEnum = None
1442
1443        class JSONEnumMeta(EnumMeta):
1444
1445            @classmethod
1446            def __prepare__(metacls, cls, bases, init=None, start=None, settings=()):
1447                return {}
1448
1449            def __init__(cls, *args , **kwds):
1450                super(JSONEnumMeta, cls).__init__(*args)
1451
1452            def __new__(metacls, cls, bases, clsdict, init=None, start=None, settings=()):
1453                import json
1454                members = []
1455                if JSONEnum is not None:
1456                    if '_file' not in clsdict:
1457                        raise TypeError('_file is required')
1458                    if '_name' not in clsdict:
1459                        raise TypeError('_name is required')
1460                    if '_value' not in clsdict:
1461                        raise TypeError('_value is required')
1462                    name_spec = clsdict.pop('_name')
1463                    if not isinstance(name_spec, (tuple, list)):
1464                        name_spec = (name_spec, )
1465                    value_spec = clsdict.pop('_value')
1466                    file = clsdict.pop('_file')
1467                    with open(file) as f:
1468                        json_data = json.load(f)
1469                    for data in json_data:
1470                        values = []
1471                        name = data[name_spec[0]]
1472                        for piece in name_spec[1:]:
1473                            name = name[piece]
1474                        for order, (value_path, func) in sorted(value_spec.items()):
1475                            if not isinstance(value_path, (list, tuple)):
1476                                value_path = (value_path, )
1477                            value = data[value_path[0]]
1478                            for piece in value_path[1:]:
1479                                value = value[piece]
1480                            if func is not None:
1481                                value = func(value)
1482                            values.append(value)
1483                        values = tuple(values)
1484                        members.append(
1485                            (name, identity(*values))
1486                            )
1487                # get the real EnumDict
1488                enum_dict = super(JSONEnumMeta, metacls).__prepare__(cls, bases, init, start, settings)
1489                # transfer the original dict content, _items first
1490                items = list(clsdict.items())
1491                items.sort(key=lambda p: (0 if p[0][0] == '_' else 1, p))
1492                for name, value in items:
1493                    enum_dict[name] = value
1494                # add the members
1495                for name, value in members:
1496                    enum_dict[name] = value
1497                return super(JSONEnumMeta, metacls).__new__(metacls, cls, bases, enum_dict, init, start, settings)
1498
1499        # for use with both Python 2/3
1500        JSONEnum = JSONEnumMeta('JsonEnum', (Enum, ), {})
1501
1502        test_file = os.path.join(tempdir, 'test_json.json')
1503        with open(test_file, 'w') as f:
1504            f.write(
1505                '[{"name":"Afghanistan","alpha-2":"AF","country-code":"004","notes":{"description":"pretty"}},'
1506                '{"name":"Åland Islands","alpha-2":"AX","country-code":"248","notes":{"description":"serene"}},'
1507                '{"name":"Albania","alpha-2":"AL","country-code":"008","notes":{"description":"exciting"}},'
1508                '{"name":"Algeria","alpha-2":"DZ","country-code":"012","notes":{"description":"scarce"}}]')
1509
1510        class Country(JSONEnum):
1511            _init_ = 'abbr code country_name description'
1512            _file = test_file
1513            _name = 'alpha-2'
1514            _value = {
1515                    1: ('alpha-2', None),
1516                    2: ('country-code', lambda c: int(c)),
1517                    3: ('name', None),
1518                    4: (('notes','description'), lambda s: s.title()),
1519                    }
1520
1521        self.assertEqual([Country.AF, Country.AX, Country.AL, Country.DZ], list(Country))
1522        self.assertEqual(Country.AF.abbr, 'AF')
1523        self.assertEqual(Country.AX.code, 248)
1524        self.assertEqual(Country.AL.country_name, 'Albania')
1525        self.assertEqual(Country.DZ.description, 'Scarce')
1526
1527
1528    def test_subclasses_with_getnewargs(self):
1529        class NamedInt(int):
1530            __qualname__ = 'NamedInt'  # needed for pickle protocol 4
1531            def __new__(cls, *args):
1532                _args = args
1533                if len(args) < 1:
1534                    raise TypeError("name and value must be specified")
1535                name, args = args[0], args[1:]
1536                self = int.__new__(cls, *args)
1537                self._intname = name
1538                self._args = _args
1539                return self
1540            def __getnewargs__(self):
1541                return self._args
1542            @property
1543            def __name__(self):
1544                return self._intname
1545            def __repr__(self):
1546                # repr() is updated to include the name and type info
1547                return "%s(%r, %s)" % (type(self).__name__,
1548                                             self.__name__,
1549                                             int.__repr__(self))
1550            def __str__(self):
1551                # str() is unchanged, even if it relies on the repr() fallback
1552                base = int
1553                base_str = base.__str__
1554                if base_str.__objclass__ is object:
1555                    return base.__repr__(self)
1556                return base_str(self)
1557            # for simplicity, we only define one operator that
1558            # propagates expressions
1559            def __add__(self, other):
1560                temp = int(self) + int( other)
1561                if isinstance(self, NamedInt) and isinstance(other, NamedInt):
1562                    return NamedInt(
1563                        '(%s + %s)' % (self.__name__, other.__name__),
1564                        temp )
1565                else:
1566                    return temp
1567
1568        class NEI(NamedInt, Enum):
1569            __qualname__ = 'NEI'  # needed for pickle protocol 4
1570            x = ('the-x', 1)
1571            y = ('the-y', 2)
1572
1573        self.assertTrue(NEI.__new__ is Enum.__new__)
1574        self.assertEqual(repr(NEI.x + NEI.y), "NamedInt('(the-x + the-y)', 3)")
1575        globals()['NamedInt'] = NamedInt
1576        globals()['NEI'] = NEI
1577        NI5 = NamedInt('test', 5)
1578        self.assertEqual(NI5, 5)
1579        test_pickle_dump_load(self.assertTrue, NI5, 5)
1580        self.assertEqual(NEI.y.value, 2)
1581        test_pickle_dump_load(self.assertTrue, NEI.y)
1582
1583    def test_subclasses_with_reduce(self):
1584        class NamedInt(int):
1585            __qualname__ = 'NamedInt'       # needed for pickle protocol 4
1586            def __new__(cls, *args):
1587                _args = args
1588                if len(args) < 1:
1589                    raise TypeError("name and value must be specified")
1590                name, args = args[0], args[1:]
1591                self = int.__new__(cls, *args)
1592                self._intname = name
1593                self._args = _args
1594                return self
1595            def __reduce__(self):
1596                return self.__class__, self._args
1597            @property
1598            def __name__(self):
1599                return self._intname
1600            def __repr__(self):
1601                # repr() is updated to include the name and type info
1602                return "%s(%r, %s)" % (type(self).__name__,
1603                                             self.__name__,
1604                                             int.__repr__(self))
1605            def __str__(self):
1606                # str() is unchanged, even if it relies on the repr() fallback
1607                base = int
1608                base_str = base.__str__
1609                if base_str.__objclass__ is object:
1610                    return base.__repr__(self)
1611                return base_str(self)
1612            # for simplicity, we only define one operator that
1613            # propagates expressions
1614            def __add__(self, other):
1615                temp = int(self) + int( other)
1616                if isinstance(self, NamedInt) and isinstance(other, NamedInt):
1617                    return NamedInt(
1618                        '(%s + %s)' % (self.__name__, other.__name__),
1619                        temp )
1620                else:
1621                    return temp
1622
1623        class NEI(NamedInt, Enum):
1624            __qualname__ = 'NEI'      # needed for pickle protocol 4
1625            x = ('the-x', 1)
1626            y = ('the-y', 2)
1627
1628
1629        self.assertTrue(NEI.__new__ is Enum.__new__)
1630        self.assertEqual(repr(NEI.x + NEI.y), "NamedInt('(the-x + the-y)', 3)")
1631        globals()['NamedInt'] = NamedInt
1632        globals()['NEI'] = NEI
1633        NI5 = NamedInt('test', 5)
1634        self.assertEqual(NI5, 5)
1635        test_pickle_dump_load(self.assertEqual, NI5, 5)
1636        self.assertEqual(NEI.y.value, 2)
1637        test_pickle_dump_load(self.assertTrue, NEI.y)
1638
1639    def test_subclasses_with_reduce_ex(self):
1640        class NamedInt(int):
1641            __qualname__ = 'NamedInt'       # needed for pickle protocol 4
1642            def __new__(cls, *args):
1643                _args = args
1644                if len(args) < 1:
1645                    raise TypeError("name and value must be specified")
1646                name, args = args[0], args[1:]
1647                self = int.__new__(cls, *args)
1648                self._intname = name
1649                self._args = _args
1650                return self
1651            def __reduce_ex__(self, proto):
1652                return self.__class__, self._args
1653            @property
1654            def __name__(self):
1655                return self._intname
1656            def __repr__(self):
1657                # repr() is updated to include the name and type info
1658                return "%s(%r, %s)" % (type(self).__name__,
1659                                             self.__name__,
1660                                             int.__repr__(self))
1661            def __str__(self):
1662                # str() is unchanged, even if it relies on the repr() fallback
1663                base = int
1664                base_str = base.__str__
1665                if base_str.__objclass__ is object:
1666                    return base.__repr__(self)
1667                return base_str(self)
1668            # for simplicity, we only define one operator that
1669            # propagates expressions
1670            def __add__(self, other):
1671                temp = int(self) + int( other)
1672                if isinstance(self, NamedInt) and isinstance(other, NamedInt):
1673                    return NamedInt(
1674                        '(%s + %s)' % (self.__name__, other.__name__),
1675                        temp )
1676                else:
1677                    return temp
1678
1679        class NEI(NamedInt, Enum):
1680            __qualname__ = 'NEI'      # needed for pickle protocol 4
1681            x = ('the-x', 1)
1682            y = ('the-y', 2)
1683
1684
1685        self.assertTrue(NEI.__new__ is Enum.__new__)
1686        self.assertEqual(repr(NEI.x + NEI.y), "NamedInt('(the-x + the-y)', 3)")
1687        globals()['NamedInt'] = NamedInt
1688        globals()['NEI'] = NEI
1689        NI5 = NamedInt('test', 5)
1690        self.assertEqual(NI5, 5)
1691        test_pickle_dump_load(self.assertEqual, NI5, 5)
1692        self.assertEqual(NEI.y.value, 2)
1693        test_pickle_dump_load(self.assertTrue, NEI.y)
1694
1695    def test_subclasses_without_direct_pickle_support(self):
1696        class NamedInt(int):
1697            __qualname__ = 'NamedInt'
1698            def __new__(cls, *args):
1699                _args = args
1700                name, args = args[0], args[1:]
1701                if len(args) == 0:
1702                    raise TypeError("name and value must be specified")
1703                self = int.__new__(cls, *args)
1704                self._intname = name
1705                self._args = _args
1706                return self
1707            @property
1708            def __name__(self):
1709                return self._intname
1710            def __repr__(self):
1711                # repr() is updated to include the name and type info
1712                return "%s(%r, %s)" % (type(self).__name__,
1713                                             self.__name__,
1714                                             int.__repr__(self))
1715            def __str__(self):
1716                # str() is unchanged, even if it relies on the repr() fallback
1717                base = int
1718                base_str = base.__str__
1719                if base_str.__objclass__ is object:
1720                    return base.__repr__(self)
1721                return base_str(self)
1722            # for simplicity, we only define one operator that
1723            # propagates expressions
1724            def __add__(self, other):
1725                temp = int(self) + int( other)
1726                if isinstance(self, NamedInt) and isinstance(other, NamedInt):
1727                    return NamedInt(
1728                        '(%s + %s)' % (self.__name__, other.__name__),
1729                        temp )
1730                else:
1731                    return temp
1732
1733        class NEI(NamedInt, Enum):
1734            __qualname__ = 'NEI'
1735            x = ('the-x', 1)
1736            y = ('the-y', 2)
1737
1738        self.assertTrue(NEI.__new__ is Enum.__new__)
1739        self.assertEqual(repr(NEI.x + NEI.y), "NamedInt('(the-x + the-y)', 3)")
1740        globals()['NamedInt'] = NamedInt
1741        globals()['NEI'] = NEI
1742        NI5 = NamedInt('test', 5)
1743        self.assertEqual(NI5, 5)
1744        self.assertEqual(NEI.y.value, 2)
1745        test_pickle_exception(self.assertRaises, TypeError, NEI.x)
1746        test_pickle_exception(self.assertRaises, PicklingError, NEI)
1747
1748    def test_subclasses_without_direct_pickle_support_using_name(self):
1749        class NamedInt(int):
1750            __qualname__ = 'NamedInt'
1751            def __new__(cls, *args):
1752                _args = args
1753                name, args = args[0], args[1:]
1754                if len(args) == 0:
1755                    raise TypeError("name and value must be specified")
1756                self = int.__new__(cls, *args)
1757                self._intname = name
1758                self._args = _args
1759                return self
1760            @property
1761            def __name__(self):
1762                return self._intname
1763            def __repr__(self):
1764                # repr() is updated to include the name and type info
1765                return "%s(%r, %s)" % (type(self).__name__,
1766                                             self.__name__,
1767                                             int.__repr__(self))
1768            def __str__(self):
1769                # str() is unchanged, even if it relies on the repr() fallback
1770                base = int
1771                base_str = base.__str__
1772                if base_str.__objclass__ is object:
1773                    return base.__repr__(self)
1774                return base_str(self)
1775            # for simplicity, we only define one operator that
1776            # propagates expressions
1777            def __add__(self, other):
1778                temp = int(self) + int( other)
1779                if isinstance(self, NamedInt) and isinstance(other, NamedInt):
1780                    return NamedInt(
1781                        '(%s + %s)' % (self.__name__, other.__name__),
1782                        temp )
1783                else:
1784                    return temp
1785
1786        class NEI(NamedInt, Enum):
1787            __qualname__ = 'NEI'
1788            x = ('the-x', 1)
1789            y = ('the-y', 2)
1790            def __reduce_ex__(self, proto):
1791                return getattr, (self.__class__, self._name_)
1792
1793        self.assertTrue(NEI.__new__ is Enum.__new__)
1794        self.assertEqual(repr(NEI.x + NEI.y), "NamedInt('(the-x + the-y)', 3)")
1795        globals()['NamedInt'] = NamedInt
1796        globals()['NEI'] = NEI
1797        NI5 = NamedInt('test', 5)
1798        self.assertEqual(NI5, 5)
1799        self.assertEqual(NEI.y.value, 2)
1800        test_pickle_dump_load(self.assertTrue, NEI.y)
1801        test_pickle_dump_load(self.assertTrue, NEI)
1802
1803    def test_tuple_subclass(self):
1804        class SomeTuple(tuple, Enum):
1805            __qualname__ = 'SomeTuple'
1806            first = (1, 'for the money')
1807            second = (2, 'for the show')
1808            third = (3, 'for the music')
1809        self.assertTrue(type(SomeTuple.first) is SomeTuple)
1810        self.assertTrue(isinstance(SomeTuple.second, tuple))
1811        self.assertEqual(SomeTuple.third, (3, 'for the music'))
1812        globals()['SomeTuple'] = SomeTuple
1813        test_pickle_dump_load(self.assertTrue, SomeTuple.first)
1814
1815    def test_duplicate_values_give_unique_enum_items(self):
1816        class NumericEnum(AutoNumberEnum):
1817            __order__ = 'enum_m enum_d enum_y'
1818            enum_m = ()
1819            enum_d = ()
1820            enum_y = ()
1821            def __int__(self):
1822                return int(self._value_)
1823        self.assertEqual(int(NumericEnum.enum_d), 2)
1824        self.assertEqual(NumericEnum.enum_y.value, 3)
1825        self.assertTrue(NumericEnum(1) is NumericEnum.enum_m)
1826        self.assertEqual(
1827            list(NumericEnum),
1828            [NumericEnum.enum_m, NumericEnum.enum_d, NumericEnum.enum_y],
1829            )
1830
1831    def test_inherited_new_from_enhanced_enum(self):
1832        class AutoNumber2(Enum):
1833            def __new__(cls):
1834                value = len(cls.__members__) + 1
1835                obj = object.__new__(cls)
1836                obj._value_ = value
1837                return obj
1838            def __int__(self):
1839                return int(self._value_)
1840        class Color(AutoNumber2):
1841            __order__ = 'red green blue'
1842            red = ()
1843            green = ()
1844            blue = ()
1845        self.assertEqual(len(Color), 3, "wrong number of elements: %d (should be %d)" % (len(Color), 3))
1846        self.assertEqual(list(Color), [Color.red, Color.green, Color.blue])
1847        if pyver >= 3.0:
1848            self.assertEqual(list(map(int, Color)), [1, 2, 3])
1849
1850    def test_inherited_new_from_mixed_enum(self):
1851        class AutoNumber3(IntEnum):
1852            def __new__(cls):
1853                value = len(cls.__members__) + 11
1854                obj = int.__new__(cls, value)
1855                obj._value_ = value
1856                return obj
1857        class Color(AutoNumber3):
1858            __order__ = 'red green blue'
1859            red = ()
1860            green = ()
1861            blue = ()
1862        self.assertEqual(len(Color), 3, "wrong number of elements: %d (should be %d)" % (len(Color), 3))
1863        Color.red
1864        Color.green
1865        Color.blue
1866        self.assertEqual(Color.blue, 13)
1867
1868    def test_equality(self):
1869        class AlwaysEqual:
1870            def __eq__(self, other):
1871                return True
1872        class OrdinaryEnum(Enum):
1873            a = 1
1874        self.assertEqual(AlwaysEqual(), OrdinaryEnum.a)
1875        self.assertEqual(OrdinaryEnum.a, AlwaysEqual())
1876
1877    def test_ordered_mixin(self):
1878        class Grade(OrderedEnum):
1879            __order__ = 'A B C D F'
1880            A = 5
1881            B = 4
1882            C = 3
1883            D = 2
1884            F = 1
1885        self.assertEqual(list(Grade), [Grade.A, Grade.B, Grade.C, Grade.D, Grade.F])
1886        self.assertTrue(Grade.A > Grade.B)
1887        self.assertTrue(Grade.F <= Grade.C)
1888        self.assertTrue(Grade.D < Grade.A)
1889        self.assertTrue(Grade.B >= Grade.B)
1890
1891    def test_missing_deprecated(self):
1892        class Label(Enum):
1893            AnyApple = 0
1894            RedApple = 1
1895            GreenApple = 2
1896            @classmethod
1897            def _missing_(cls, name):
1898                return cls.AnyApple
1899
1900        self.assertEqual(Label.AnyApple, Label(4))
1901        with self.assertRaises(AttributeError):
1902            Label.redapple
1903        with self.assertRaises(KeyError):
1904            Label['redapple']
1905
1906    def test_missing(self):
1907        class Label(Enum):
1908            AnyApple = 0
1909            RedApple = 1
1910            GreenApple = 2
1911            @classmethod
1912            def _missing_value_(cls, value):
1913                return cls.AnyApple
1914
1915        self.assertEqual(Label.AnyApple, Label(4))
1916        with self.assertRaises(AttributeError):
1917            Label.redapple
1918        with self.assertRaises(KeyError):
1919            Label['redapple']
1920
1921    def test_missing_name(self):
1922        class Label(Enum):
1923            RedApple = 1
1924            GreenApple = 2
1925            @classmethod
1926            def _missing_name_(cls, name):
1927                for member in cls:
1928                    if member.name.lower() == name.lower():
1929                        return member
1930
1931        Label['redapple']
1932        with self.assertRaises(AttributeError):
1933            Label.redapple
1934        with self.assertRaises(ValueError):
1935            Label('redapple')
1936
1937    def test_missing_value_bad_input(self):
1938        class Label(Enum):
1939            AnyApple = 0
1940            RedApple = 1
1941            GreenApple = 2
1942            @classmethod
1943            def _missing_value_(cls, value):
1944                return cls.AnyApple
1945
1946        self.assertEqual(Label.AnyApple, Label(4))
1947        with self.assertRaises(KeyError):
1948            Label[True]
1949
1950    def test_missing_name_bad_return(self):
1951        class Label(Enum):
1952            RedApple = 1
1953            GreenApple = 2
1954            @classmethod
1955            def _missing_name_(cls, name):
1956                return None
1957
1958        with self.assertRaises(AttributeError):
1959            Label.redapple
1960        with self.assertRaises(ValueError):
1961            Label('redapple')
1962        with self.assertRaises(KeyError):
1963            Label['redapple']
1964
1965    def test_extending2(self):
1966        def bad_extension():
1967            class Shade(Enum):
1968                def shade(self):
1969                    print(self.name)
1970            class Color(Shade):
1971                red = 1
1972                green = 2
1973                blue = 3
1974            class MoreColor(Color):
1975                cyan = 4
1976                magenta = 5
1977                yellow = 6
1978        self.assertRaises(TypeError, bad_extension)
1979
1980    def test_extending3(self):
1981        class Shade(Enum):
1982            def shade(self):
1983                return self.name
1984        class Color(Shade):
1985            def hex(self):
1986                return '%s hexlified!' % self.value
1987        class MoreColor(Color):
1988            cyan = 4
1989            magenta = 5
1990            yellow = 6
1991        self.assertEqual(MoreColor.magenta.hex(), '5 hexlified!')
1992
1993    def test_extending4(self):
1994        class hohum(object):
1995            def cyan(self):
1996                "cyanize a color"
1997                return self.value * 7
1998        class Color(hohum, Enum):
1999            red = 1
2000            green = 2
2001            blue = 3
2002            cyan = 4
2003        self.assertEqual(list(Color), [Color.red, Color.green, Color.blue, Color.cyan])
2004        self.assertEqual(Color.red.cyan(), 7)
2005        self.assertEqual(Color.green.cyan(), 14)
2006        self.assertEqual(Color.blue.cyan(), 21)
2007        self.assertEqual(Color.cyan.cyan(), 28)
2008
2009
2010    def test_extending5(self):
2011        class Color(Enum):
2012            _order_ = 'red green blue value'
2013            red = 1
2014            green = 2
2015            blue = 3
2016            value = 4
2017        self.assertEqual(list(Color), [Color.red, Color.green, Color.blue, Color.value])
2018        self.assertEqual(Color.value.name, 'value')
2019        self.assertEqual(Color.value.value, 4)
2020        self.assertTrue(Color.value in Color)
2021        self.assertEqual(Color(4), Color.value)
2022        self.assertEqual(Color['value'], Color.value)
2023        self.assertEqual(Color.red.value, 1)
2024
2025    if StdlibEnum is not None:
2026
2027        def test_extend_enum_stdlib(self):
2028            class Color(StdlibEnum):
2029                red = 1
2030                green = 2
2031                blue = 3
2032            self.assertEqual(getattr(Color.red, '_values_', None), None)
2033            extend_enum(Color, 'brown', 4)
2034            self.assertEqual(Color.brown.name, 'brown')
2035            self.assertEqual(Color.brown.value, 4)
2036            self.assertTrue(Color.brown in Color)
2037            self.assertEqual(Color(4), Color.brown)
2038            self.assertEqual(Color['brown'], Color.brown)
2039            self.assertEqual(len(Color), 4)
2040
2041    def test_extend_enum_plain(self):
2042        class Color(UniqueEnum):
2043            red = 1
2044            green = 2
2045            blue = 3
2046        extend_enum(Color, 'brown', 4)
2047        self.assertEqual(Color.brown.name, 'brown')
2048        self.assertEqual(Color.brown.value, 4)
2049        self.assertTrue(Color.brown in Color)
2050        self.assertEqual(Color(4), Color.brown)
2051        self.assertEqual(Color['brown'], Color.brown)
2052        self.assertEqual(len(Color), 4)
2053
2054    def test_extend_enum_alias(self):
2055        class Color(Enum):
2056            red = 1
2057            green = 2
2058            blue = 3
2059        extend_enum(Color, 'rojo', 1)
2060        self.assertEqual(Color.rojo.name, 'red')
2061        self.assertEqual(Color.rojo.value, 1)
2062        self.assertTrue(Color.rojo in Color)
2063        self.assertEqual(Color(1), Color.rojo)
2064        self.assertEqual(Color['rojo'], Color.red)
2065        self.assertEqual(len(Color), 3)
2066
2067    def test_extend_enum_no_alias(self):
2068        class Color(UniqueEnum):
2069            red = 1
2070            green = 2
2071            blue = 3
2072        self.assertRaisesRegex(ValueError, 'rojo is a duplicate of red', extend_enum, Color, 'rojo', 1)
2073        self.assertEqual(Color.red.name, 'red')
2074        self.assertEqual(Color.red.value, 1)
2075        self.assertTrue(Color.red in Color)
2076        self.assertEqual(Color(1), Color.red)
2077        self.assertEqual(Color['red'], Color.red)
2078        self.assertEqual(Color.green.name, 'green')
2079        self.assertEqual(Color.green.value, 2)
2080        self.assertTrue(Color.green in Color)
2081        self.assertEqual(Color(2), Color.green)
2082        self.assertEqual(Color['blue'], Color.blue)
2083        self.assertEqual(Color.blue.name, 'blue')
2084        self.assertEqual(Color.blue.value, 3)
2085        self.assertTrue(Color.blue in Color)
2086        self.assertEqual(Color(3), Color.blue)
2087        self.assertEqual(len(Color), 3)
2088
2089    def test_extend_enum_shadow(self):
2090        class Color(UniqueEnum):
2091            red = 1
2092            green = 2
2093            blue = 3
2094        extend_enum(Color, 'value', 4)
2095        self.assertEqual(Color.value.name, 'value')
2096        self.assertEqual(Color.value.value, 4)
2097        self.assertTrue(Color.value in Color)
2098        self.assertEqual(Color(4), Color.value)
2099        self.assertEqual(Color['value'], Color.value)
2100        self.assertEqual(len(Color), 4)
2101        self.assertEqual(Color.red.value, 1)
2102
2103    def test_extend_enum_shadow_base(self):
2104        class hohum(object):
2105            def cyan(self):
2106                "cyanize a color"
2107                return self.value
2108        class Color(hohum, UniqueEnum):
2109            red = 1
2110            green = 2
2111            blue = 3
2112        with self.assertRaises(TypeError):
2113            extend_enum(Color, 'cyan', 4)
2114        self.assertEqual(len(Color), 3)
2115        self.assertEqual(list(Color), [Color.red, Color.green, Color.blue])
2116
2117    def test_extend_enum_multivalue(self):
2118        class Color(MultiValueEnum):
2119            red = 1, 4, 7
2120            green = 2, 5, 8
2121            blue = 3, 6, 9
2122        extend_enum(Color, 'brown', 10, 20)
2123        self.assertEqual(Color.brown.name, 'brown')
2124        self.assertEqual(Color.brown.value, 10)
2125        self.assertTrue(Color.brown in Color)
2126        self.assertEqual(Color(10), Color.brown)
2127        self.assertEqual(Color(20), Color.brown)
2128        self.assertEqual(Color['brown'], Color.brown)
2129        self.assertEqual(len(Color), 4)
2130
2131    def test_extend_enum_multivalue_alias(self):
2132        class Color(MultiValueEnum):
2133            red = 1, 4, 7
2134            green = 2, 5, 8
2135            blue = 3, 6, 9
2136        self.assertRaisesRegex(ValueError, 'rojo is a duplicate of red', extend_enum, Color, 'rojo', 7)
2137        self.assertEqual(Color.red.name, 'red')
2138        self.assertEqual(Color.red.value, 1)
2139        self.assertTrue(Color.red in Color)
2140        self.assertEqual(Color(1), Color.red)
2141        self.assertEqual(Color(4), Color.red)
2142        self.assertEqual(Color(7), Color.red)
2143        self.assertEqual(Color['red'], Color.red)
2144        self.assertEqual(Color.green.name, 'green')
2145        self.assertEqual(Color.green.value, 2)
2146        self.assertTrue(Color.green in Color)
2147        self.assertEqual(Color(2), Color.green)
2148        self.assertEqual(Color(5), Color.green)
2149        self.assertEqual(Color(8), Color.green)
2150        self.assertEqual(Color['blue'], Color.blue)
2151        self.assertEqual(Color.blue.name, 'blue')
2152        self.assertEqual(Color.blue.value, 3)
2153        self.assertTrue(Color.blue in Color)
2154        self.assertEqual(Color(3), Color.blue)
2155        self.assertEqual(Color(6), Color.blue)
2156        self.assertEqual(Color(9), Color.blue)
2157        self.assertEqual(len(Color), 3)
2158
2159    def test_extend_intenum(self):
2160        class Index(IntEnum):
2161            DeviceType    = 0x1000
2162            ErrorRegister = 0x1001
2163
2164        for name, value in (
2165                ('ControlWord', 0x6040),
2166                ('StatusWord', 0x6041),
2167                ('OperationMode', 0x6060),
2168                ):
2169            extend_enum(Index, name, value)
2170
2171        self.assertEqual(len(Index), 5)
2172        self.assertEqual(list(Index), [Index.DeviceType, Index.ErrorRegister, Index.ControlWord, Index.StatusWord, Index.OperationMode])
2173        self.assertEqual(Index.DeviceType.value, 0x1000)
2174        self.assertEqual(Index.StatusWord.value, 0x6041)
2175
2176    def test_extend_multi_init(self):
2177        try:
2178            from http import HTTPStatus
2179            length = len(HTTPStatus)
2180        except ImportError:
2181            class HTTPStatus(IntEnum):
2182                def __new__(cls, value, phrase, description):
2183                    obj = int.__new__(cls, value)
2184                    obj._value_ = value
2185
2186                    obj.phrase = phrase
2187                    obj.description = description
2188                    return obj
2189                CONTINUE = 100, 'Continue', 'Request received, please continue'
2190                SWITCHING_PROTOCOLS = 101, 'Switching Protocols', 'Switching to new protocol; obey Upgrade header'
2191                PROCESSING = 102, 'Processing', ''
2192            length = 3
2193        extend_enum(HTTPStatus, 'BAD_SPAM', 513, 'Too greasy', 'for a train')
2194        extend_enum(HTTPStatus, 'BAD_EGGS', 514, 'Too green', '')
2195        self.assertEqual(len(HTTPStatus), length+2)
2196        self.assertEqual(
2197                list(HTTPStatus)[-2:],
2198                [HTTPStatus.BAD_SPAM, HTTPStatus.BAD_EGGS],
2199                )
2200        self.assertEqual(HTTPStatus.BAD_SPAM.value, 513)
2201        self.assertEqual(HTTPStatus.BAD_SPAM.name, 'BAD_SPAM')
2202        self.assertEqual(HTTPStatus.BAD_SPAM.phrase, 'Too greasy')
2203        self.assertEqual(HTTPStatus.BAD_SPAM.description, 'for a train')
2204        self.assertEqual(HTTPStatus.BAD_EGGS.value, 514)
2205        self.assertEqual(HTTPStatus.BAD_EGGS.name, 'BAD_EGGS')
2206        self.assertEqual(HTTPStatus.BAD_EGGS.phrase, 'Too green')
2207        self.assertEqual(HTTPStatus.BAD_EGGS.description, '')
2208
2209    # informational
2210    CONTINUE = 100, 'Continue', 'Request received, please continue'
2211    SWITCHING_PROTOCOLS = (101, 'Switching Protocols',
2212            'Switching to new protocol; obey Upgrade header')
2213    PROCESSING = 102, 'Processing'
2214
2215    def test_no_duplicates(self):
2216        def bad_duplicates():
2217            class Color1(UniqueEnum):
2218                red = 1
2219                green = 2
2220                blue = 3
2221            class Color2(UniqueEnum):
2222                red = 1
2223                green = 2
2224                blue = 3
2225                grene = 2
2226        self.assertRaises(ValueError, bad_duplicates)
2227
2228    def test_no_duplicates_kinda(self):
2229        class Silly(UniqueEnum):
2230            one = 1
2231            two = 'dos'
2232            name = 3
2233        class Sillier(IntEnum, UniqueEnum):
2234            single = 1
2235            name = 2
2236            triple = 3
2237            value = 4
2238
2239    def test_init(self):
2240        class Planet(Enum):
2241            MERCURY = (3.303e+23, 2.4397e6)
2242            VENUS   = (4.869e+24, 6.0518e6)
2243            EARTH   = (5.976e+24, 6.37814e6)
2244            MARS    = (6.421e+23, 3.3972e6)
2245            JUPITER = (1.9e+27,   7.1492e7)
2246            SATURN  = (5.688e+26, 6.0268e7)
2247            URANUS  = (8.686e+25, 2.5559e7)
2248            NEPTUNE = (1.024e+26, 2.4746e7)
2249            def __init__(self, mass, radius):
2250                self.mass = mass       # in kilograms
2251                self.radius = radius   # in meters
2252            @property
2253            def surface_gravity(self):
2254                # universal gravitational constant  (m3 kg-1 s-2)
2255                G = 6.67300E-11
2256                return G * self.mass / (self.radius * self.radius)
2257        self.assertEqual(round(Planet.EARTH.surface_gravity, 2), 9.80)
2258        self.assertEqual(Planet.EARTH.value, (5.976e+24, 6.37814e6))
2259
2260        @unittest.skip
2261        def test_init_and_autonumber(self):
2262            pass
2263
2264        @unittest.skip
2265        def test_init_and_autonumber_and_value(self):
2266            pass
2267
2268    def test_no_init_and_autonumber(self):
2269        class DocEnum(str, Enum):
2270            """
2271            compares equal to all cased versions of its name
2272            accepts a docstring for each member
2273            """
2274            _settings_ = AutoNumber
2275            def __init__(self, value, doc=None):
2276                # first, fix _value_
2277                self._value_ = self._name_.lower()
2278                self.__doc__ = doc
2279            def __eq__(self, other):
2280                if isinstance(other, basestring):
2281                    return self._value_ == other.lower()
2282                elif isinstance(other, self.__class__):
2283                    return self is other
2284                else:
2285                    return False
2286            def __ne__(self, other):
2287                return not self == other
2288            REQUIRED = "required value"
2289            OPTION = "single value per name"
2290            MULTI = "multiple values per name (list form, no whitespace)"
2291            FLAG = "boolean/trivalent value per name"
2292            KEYWORD = 'unknown options'
2293        self.assertEqual(DocEnum.REQUIRED, 'required')
2294        self.assertEqual(DocEnum.REQUIRED, 'Required')
2295        self.assertEqual(DocEnum.REQUIRED, 'REQUIRED')
2296
2297    def test_nonhash_value(self):
2298        class AutoNumberInAList(Enum):
2299            def __new__(cls):
2300                value = [len(cls.__members__) + 1]
2301                obj = object.__new__(cls)
2302                obj._value_ = value
2303                return obj
2304        class ColorInAList(AutoNumberInAList):
2305            __order__ = 'red green blue'
2306            red = ()
2307            green = ()
2308            blue = ()
2309        self.assertEqual(list(ColorInAList), [ColorInAList.red, ColorInAList.green, ColorInAList.blue])
2310        self.assertEqual(ColorInAList.red.value, [1])
2311        self.assertEqual(ColorInAList([1]), ColorInAList.red)
2312
2313    def test_conflicting_types_resolved_in_new(self):
2314        class LabelledIntEnum(int, Enum):
2315            def __new__(cls, *args):
2316                value, label = args
2317                obj = int.__new__(cls, value)
2318                obj.label = label
2319                obj._value_ = value
2320                return obj
2321
2322        class LabelledList(LabelledIntEnum):
2323            unprocessed = (1, "Unprocessed")
2324            payment_complete = (2, "Payment Complete")
2325
2326        self.assertEqual(LabelledList.unprocessed, 1)
2327        self.assertEqual(LabelledList(1), LabelledList.unprocessed)
2328        self.assertEqual(list(LabelledList), [LabelledList.unprocessed, LabelledList.payment_complete])
2329
2330    def test_auto_number(self):
2331        class Color(Enum):
2332            _order_ = 'red blue green'
2333            red = auto()
2334            blue = auto()
2335            green = auto()
2336
2337        self.assertEqual(list(Color), [Color.red, Color.blue, Color.green])
2338        self.assertEqual(Color.red.value, 1)
2339        self.assertEqual(Color.blue.value, 2)
2340        self.assertEqual(Color.green.value, 3)
2341
2342    def test_auto_name(self):
2343        class Color(Enum):
2344            _order_ = 'red blue green'
2345            def _generate_next_value_(name, start, count, last):
2346                return name
2347            red = auto()
2348            blue = auto()
2349            green = auto()
2350
2351        self.assertEqual(list(Color), [Color.red, Color.blue, Color.green])
2352        self.assertEqual(Color.red.value, 'red')
2353        self.assertEqual(Color.blue.value, 'blue')
2354        self.assertEqual(Color.green.value, 'green')
2355
2356    def test_auto_name_inherit(self):
2357        class AutoNameEnum(Enum):
2358            def _generate_next_value_(name, start, count, last):
2359                return name
2360        class Color(AutoNameEnum):
2361            _order_ = 'red blue green'
2362            red = auto()
2363            blue = auto()
2364            green = auto()
2365
2366        self.assertEqual(list(Color), [Color.red, Color.blue, Color.green])
2367        self.assertEqual(Color.red.value, 'red')
2368        self.assertEqual(Color.blue.value, 'blue')
2369        self.assertEqual(Color.green.value, 'green')
2370
2371    def test_auto_garbage(self):
2372        class Color(Enum):
2373            _order_ = 'red blue'
2374            red = 'red'
2375            blue = auto()
2376        self.assertEqual(Color.blue.value, 1)
2377
2378    def test_auto_garbage_corrected(self):
2379        class Color(Enum):
2380            _order_ = 'red blue green'
2381            red = 'red'
2382            blue = 2
2383            green = auto()
2384
2385        self.assertEqual(list(Color), [Color.red, Color.blue, Color.green])
2386        self.assertEqual(Color.red.value, 'red')
2387        self.assertEqual(Color.blue.value, 2)
2388        self.assertEqual(Color.green.value, 3)
2389
2390    def test_duplicate_auto(self):
2391        class Dupes(Enum):
2392            _order_ = 'first second third'
2393            first = primero = auto()
2394            second = auto()
2395            third = auto()
2396        self.assertEqual([Dupes.first, Dupes.second, Dupes.third], list(Dupes))
2397
2398    def test_auto_value_with_auto(self):
2399
2400        class SelectionEnum(Enum):
2401            _init_ = 'db user'
2402            def __new__(cls, *args, **kwds):
2403                count = len(cls.__members__)
2404                obj = object.__new__(cls)
2405                obj._count = count
2406                obj._value_ = args
2407                obj.db, obj.user = args
2408                return obj
2409            @staticmethod
2410            def _generate_next_value_(name, start, count, values, *args, **kwds):
2411                return (name, ) + args
2412
2413        class Test(SelectionEnum):
2414            _order_ = 'this that'
2415            this = auto('these')
2416            that = auto('those')
2417
2418        self.assertEqual(list(Test), [Test.this, Test.that])
2419        self.assertEqual(Test.this.name, 'this')
2420        self.assertEqual(Test.this.value, ('this', 'these'))
2421        self.assertEqual(Test.this.db, 'this')
2422        self.assertEqual(Test.this.user, 'these')
2423        self.assertEqual(Test.that.name, 'that')
2424        self.assertEqual(Test.that.value, ('that', 'those'))
2425        self.assertEqual(Test.that.db, 'that')
2426        self.assertEqual(Test.that.user, 'those')
2427
2428    def test_auto_value_with_autovalue(self):
2429
2430        class SelectionEnum(Enum):
2431            _init_ = 'db user'
2432            _settings_ = AutoValue
2433            def __new__(cls, *args, **kwds):
2434                count = len(cls.__members__)
2435                obj = object.__new__(cls)
2436                obj._count = count
2437                obj._value_ = args
2438                return obj
2439            @staticmethod
2440            def _generate_next_value_(name, start, count, values, *args, **kwds):
2441                return (name, ) + args
2442
2443        class Test(SelectionEnum):
2444            _order_ = 'this that'
2445            this = 'these'
2446            that = 'those'
2447
2448        self.assertEqual(list(Test), [Test.this, Test.that])
2449        self.assertEqual(Test.this.name, 'this')
2450        self.assertEqual(Test.this.value, ('this', 'these'))
2451        self.assertEqual(Test.this.db, 'this')
2452        self.assertEqual(Test.this.user, 'these')
2453        self.assertEqual(Test.that.name, 'that')
2454        self.assertEqual(Test.that.value, ('that', 'those'))
2455        self.assertEqual(Test.that.db, 'that')
2456        self.assertEqual(Test.that.user, 'those')
2457
2458    def test_empty_with_functional_api(self):
2459        empty = aenum.IntEnum('Foo', {})
2460        self.assertEqual(len(empty), 0)
2461
2462    def test_auto_init(self):
2463        class Planet(Enum):
2464            _init_ = 'mass radius'
2465            MERCURY = (3.303e+23, 2.4397e6)
2466            VENUS   = (4.869e+24, 6.0518e6)
2467            EARTH   = (5.976e+24, 6.37814e6)
2468            MARS    = (6.421e+23, 3.3972e6)
2469            JUPITER = (1.9e+27,   7.1492e7)
2470            SATURN  = (5.688e+26, 6.0268e7)
2471            URANUS  = (8.686e+25, 2.5559e7)
2472            NEPTUNE = (1.024e+26, 2.4746e7)
2473            @property
2474            def surface_gravity(self):
2475                # universal gravitational constant  (m3 kg-1 s-2)
2476                G = 6.67300E-11
2477                return G * self.mass / (self.radius * self.radius)
2478        self.assertEqual(round(Planet.EARTH.surface_gravity, 2), 9.80)
2479        self.assertEqual(Planet.EARTH.value, (5.976e+24, 6.37814e6))
2480
2481    def test_auto_init_with_value(self):
2482        class Color(Enum):
2483            _init_='value, rgb'
2484            RED = 1, (1, 0, 0)
2485            BLUE = 2, (0, 1, 0)
2486            GREEN = 3, (0, 0, 1)
2487        self.assertEqual(Color.RED.value, 1)
2488        self.assertEqual(Color.BLUE.value, 2)
2489        self.assertEqual(Color.GREEN.value, 3)
2490        self.assertEqual(Color.RED.rgb, (1, 0, 0))
2491        self.assertEqual(Color.BLUE.rgb, (0, 1, 0))
2492        self.assertEqual(Color.GREEN.rgb, (0, 0, 1))
2493
2494    def test_noalias(self):
2495        class Settings(Enum):
2496            _settings_ = NoAlias
2497            red = 1
2498            rojo = 1
2499        self.assertFalse(Settings.red is Settings.rojo)
2500        self.assertRaises(TypeError, Settings, 1)
2501
2502    def test_auto_and_init(self):
2503        class Field(IntEnum):
2504            _order_ = 'TYPE START'
2505            _init_ = '__doc__'
2506            _settings_ = AutoNumber
2507            TYPE = "Char, Date, Logical, etc."
2508            START = "Field offset in record"
2509        self.assertEqual(Field.TYPE, 1)
2510        self.assertEqual(Field.START, 2)
2511        self.assertEqual(Field.TYPE.__doc__, 'Char, Date, Logical, etc.')
2512        self.assertEqual(Field.START.__doc__, 'Field offset in record')
2513
2514    def test_auto_and_start(self):
2515        class Field(IntEnum):
2516            _order_ = 'TYPE START'
2517            _start_ = 0
2518            _init_ = '__doc__'
2519            TYPE = "Char, Date, Logical, etc."
2520            START = "Field offset in record"
2521        self.assertEqual(Field.TYPE, 0)
2522        self.assertEqual(Field.START, 1)
2523        self.assertEqual(Field.TYPE.__doc__, 'Char, Date, Logical, etc.')
2524        self.assertEqual(Field.START.__doc__, 'Field offset in record')
2525
2526    def test_auto_and_init_and_some_values(self):
2527        class Field(IntEnum):
2528            _order_ = 'TYPE START BLAH BELCH'
2529            _init_ = '__doc__'
2530            _settings_ = AutoNumber
2531            TYPE = "Char, Date, Logical, etc."
2532            START = "Field offset in record"
2533            BLAH = 5, "test blah"
2534            BELCH = 'test belch'
2535        self.assertEqual(Field.TYPE, 1)
2536        self.assertEqual(Field.START, 2)
2537        self.assertEqual(Field.BLAH, 5)
2538        self.assertEqual(Field.BELCH, 6)
2539        self.assertEqual(Field.TYPE.__doc__, 'Char, Date, Logical, etc.')
2540        self.assertEqual(Field.START.__doc__, 'Field offset in record')
2541        self.assertEqual(Field.BLAH.__doc__, 'test blah')
2542        self.assertEqual(Field.BELCH.__doc__, 'test belch')
2543
2544    def test_auto_and_init_w_value_and_some_values(self):
2545        class Field(IntEnum):
2546            _order_ = 'TYPE START BLAH BELCH'
2547            _init_ = 'value __doc__'
2548            _settings_ = AutoNumber
2549            TYPE = 1, "Char, Date, Logical, etc."
2550            START = 2, "Field offset in record"
2551            BLAH = 5, "test blah"
2552            BELCH = 7, 'test belch'
2553        self.assertEqual(Field.TYPE, 1)
2554        self.assertEqual(Field.START, 2)
2555        self.assertEqual(Field.BLAH, 5)
2556        self.assertEqual(Field.BELCH, 7)
2557        self.assertEqual(Field.TYPE.__doc__, 'Char, Date, Logical, etc.')
2558        self.assertEqual(Field.START.__doc__, 'Field offset in record')
2559        self.assertEqual(Field.BLAH.__doc__, 'test blah')
2560        self.assertEqual(Field.BELCH.__doc__, 'test belch')
2561
2562    def test_auto_and_init_w_value_and_too_many_values(self):
2563        with self.assertRaisesRegex(TypeError, 'BLAH: number of fields provided do not match init'):
2564            class Field(IntEnum):
2565                _order_ = 'TYPE START BLAH BELCH'
2566                _init_ = 'value __doc__'
2567                _settings_ = AutoNumber
2568                TYPE = 1, "Char, Date, Logical, etc."
2569                START = 2, "Field offset in record"
2570                BLAH = 5, 6, "test blah"
2571                BELCH = 7, 'test belch'
2572
2573    def test_auto_and_init_and_some_complex_values(self):
2574        class Field(IntEnum):
2575            _order_ = 'TYPE START BLAH BELCH'
2576            _init_ = '__doc__ help'
2577            _settings_ = AutoNumber
2578            TYPE = "Char, Date, Logical, etc.", "fields composed of character data"
2579            START = "Field offset in record", "where the data starts in the record"
2580            BLAH = 5, "test blah", "some help"
2581            BELCH = 'test belch', "some more help"
2582        self.assertEqual(Field.TYPE, 1)
2583        self.assertEqual(Field.START, 2)
2584        self.assertEqual(Field.BLAH, 5)
2585        self.assertEqual(Field.BELCH, 6)
2586        self.assertEqual(Field.TYPE.__doc__, 'Char, Date, Logical, etc.')
2587        self.assertEqual(Field.START.__doc__, 'Field offset in record')
2588        self.assertEqual(Field.BLAH.__doc__, 'test blah')
2589        self.assertEqual(Field.BELCH.__doc__, 'test belch')
2590        self.assertEqual(Field.TYPE.help, "fields composed of character data")
2591        self.assertEqual(Field.START.help, "where the data starts in the record")
2592        self.assertEqual(Field.BLAH.help, "some help")
2593        self.assertEqual(Field.BELCH.help, "some more help")
2594
2595    def test_auto_and_init_inherited(self):
2596        class AutoEnum(IntEnum):
2597            _start_ = 0
2598            _init_ = '__doc__'
2599        class Field(AutoEnum):
2600            _order_ = 'TYPE START BLAH BELCH'
2601            TYPE = "Char, Date, Logical, etc."
2602            START = "Field offset in record"
2603            BLAH = 5, "test blah"
2604            BELCH = 'test belch'
2605        self.assertEqual(Field.TYPE, 0)
2606        self.assertEqual(Field.START, 1)
2607        self.assertEqual(Field.BLAH, 5)
2608        self.assertEqual(Field.BELCH, 6)
2609        self.assertEqual(Field.TYPE.__doc__, 'Char, Date, Logical, etc.')
2610        self.assertEqual(Field.START.__doc__, 'Field offset in record')
2611        self.assertEqual(Field.BLAH.__doc__, 'test blah')
2612        self.assertEqual(Field.BELCH.__doc__, 'test belch')
2613
2614    def test_auto_and_enum(self):
2615        class Foo(aenum.Flag):
2616            _order_ = 'a b'
2617            a = aenum.auto()
2618            b = a | aenum.auto()
2619
2620        self.assertEqual([Foo.a, Foo.b], list(Foo))
2621        self.assertEqual(Foo.a.value, 1)
2622        self.assertEqual(Foo.b.value, 3)
2623
2624    def test_AutoNumberEnum_and_property(self):
2625        class Color(aenum.AutoNumberEnum):
2626            red = ()
2627            green = ()
2628            blue = ()
2629            @property
2630            def cap_name(self):
2631                return self.name.title()
2632        self.assertEqual(Color.blue.cap_name, 'Blue')
2633
2634    def test_AutoNumberEnum(self):
2635        class Color(aenum.AutoNumberEnum):
2636            _order_ = 'red green blue'
2637            red = ()
2638            green = ()
2639            blue = ()
2640        self.assertEqual(list(Color), [Color.red, Color.green, Color.blue])
2641        self.assertEqual(Color.red.value, 1)
2642        self.assertEqual(Color.green.value, 2)
2643        self.assertEqual(Color.blue.value, 3)
2644
2645    def test_MultiValue_with_init_wo_value(self):
2646        class Color(Enum):
2647            _init_ = 'color r g b'
2648            _order_ = 'red green blue'
2649            _settings_ = MultiValue
2650            red = 'red', 1, 2, 3
2651            green = 'green', 4, 5, 6
2652            blue = 'blue', 7, 8, 9
2653        self.assertEqual(Color.red.value, 'red')
2654        self.assertEqual(Color.red.color, 'red')
2655        self.assertEqual(Color.red.r, 1)
2656        self.assertEqual(Color.red.g, 2)
2657        self.assertEqual(Color.red.b, 3)
2658        self.assertEqual(Color.green.value, 'green')
2659        self.assertEqual(Color.green.color, 'green')
2660        self.assertEqual(Color.green.r, 4)
2661        self.assertEqual(Color.green.g, 5)
2662        self.assertEqual(Color.green.b, 6)
2663        self.assertEqual(Color.blue.value, 'blue')
2664        self.assertEqual(Color.blue.color, 'blue')
2665        self.assertEqual(Color.blue.r, 7)
2666        self.assertEqual(Color.blue.g, 8)
2667        self.assertEqual(Color.blue.b, 9)
2668        self.assertIs(Color('red'), Color.red)
2669        self.assertIs(Color(1), Color.red)
2670        self.assertIs(Color(2), Color.red)
2671        self.assertIs(Color(3), Color.red)
2672        self.assertIs(Color('green'), Color.green)
2673        self.assertIs(Color(4), Color.green)
2674        self.assertIs(Color(5), Color.green)
2675        self.assertIs(Color(6), Color.green)
2676        self.assertIs(Color('blue'), Color.blue)
2677        self.assertIs(Color(7), Color.blue)
2678        self.assertIs(Color(8), Color.blue)
2679        self.assertIs(Color(9), Color.blue)
2680
2681    def test_MultiValue_with_init_w_value(self):
2682        class Color(Enum):
2683            _init_ = 'value r g b'
2684            _order_ = 'red green blue'
2685            _settings_ = MultiValue
2686            red = 'red', 1, 2, 3
2687            green = 'green', 4, 5, 6
2688            blue = 'blue', 7, 8, 9
2689        self.assertEqual(Color.red.value, 'red')
2690        self.assertEqual(Color.red.r, 1)
2691        self.assertEqual(Color.red.g, 2)
2692        self.assertEqual(Color.red.b, 3)
2693        self.assertEqual(Color.green.value, 'green')
2694        self.assertEqual(Color.green.r, 4)
2695        self.assertEqual(Color.green.g, 5)
2696        self.assertEqual(Color.green.b, 6)
2697        self.assertEqual(Color.blue.value, 'blue')
2698        self.assertEqual(Color.blue.r, 7)
2699        self.assertEqual(Color.blue.g, 8)
2700        self.assertEqual(Color.blue.b, 9)
2701        self.assertIs(Color('red'), Color.red)
2702        self.assertIs(Color(1), Color.red)
2703        self.assertIs(Color(2), Color.red)
2704        self.assertIs(Color(3), Color.red)
2705        self.assertIs(Color('green'), Color.green)
2706        self.assertIs(Color(4), Color.green)
2707        self.assertIs(Color(5), Color.green)
2708        self.assertIs(Color(6), Color.green)
2709        self.assertIs(Color('blue'), Color.blue)
2710        self.assertIs(Color(7), Color.blue)
2711        self.assertIs(Color(8), Color.blue)
2712        self.assertIs(Color(9), Color.blue)
2713
2714    def test_MultiValue_with_init_wo_value_w_autonumber(self):
2715        class Color(Enum):
2716            _init_ = 'color r g b'
2717            _order_ = 'red green blue'
2718            _settings_ = MultiValue, AutoNumber
2719            red = 'red', 10, 20, 30
2720            green = 'green', 40, 50, 60
2721            blue = 'blue', 70, 80, 90
2722        self.assertEqual(Color.red.value, 1)
2723        self.assertEqual(Color.red.color, 'red')
2724        self.assertEqual(Color.red.r, 10)
2725        self.assertEqual(Color.red.g, 20)
2726        self.assertEqual(Color.red.b, 30)
2727        self.assertEqual(Color.green.value, 2)
2728        self.assertEqual(Color.green.color, 'green')
2729        self.assertEqual(Color.green.r, 40)
2730        self.assertEqual(Color.green.g, 50)
2731        self.assertEqual(Color.green.b, 60)
2732        self.assertEqual(Color.blue.value, 3)
2733        self.assertEqual(Color.blue.color, 'blue')
2734        self.assertEqual(Color.blue.r, 70)
2735        self.assertEqual(Color.blue.g, 80)
2736        self.assertEqual(Color.blue.b, 90)
2737        self.assertIs(Color(1), Color.red)
2738        self.assertIs(Color('red'), Color.red)
2739        self.assertIs(Color(10), Color.red)
2740        self.assertIs(Color(20), Color.red)
2741        self.assertIs(Color(30), Color.red)
2742        self.assertIs(Color(2), Color.green)
2743        self.assertIs(Color('green'), Color.green)
2744        self.assertIs(Color(40), Color.green)
2745        self.assertIs(Color(50), Color.green)
2746        self.assertIs(Color(60), Color.green)
2747        self.assertIs(Color(3), Color.blue)
2748        self.assertIs(Color('blue'), Color.blue)
2749        self.assertIs(Color(70), Color.blue)
2750        self.assertIs(Color(80), Color.blue)
2751        self.assertIs(Color(90), Color.blue)
2752
2753    def test_MultiValue_with_init_wo_value_w_autonumber_and_value(self):
2754        class Color(Enum):
2755            _init_ = 'color r g b'
2756            _order_ = 'red green blue chartruese'
2757            _settings_ = MultiValue, AutoNumber
2758            red = 'red', 10, 20, 30
2759            green = 'green', 40, 50, 60
2760            blue = 5, 'blue', 70, 80, 90
2761            chartruese = 'chartruese', 100, 110, 120
2762        self.assertEqual(Color.red.value, 1)
2763        self.assertEqual(Color.red.color, 'red')
2764        self.assertEqual(Color.red.r, 10)
2765        self.assertEqual(Color.red.g, 20)
2766        self.assertEqual(Color.red.b, 30)
2767        self.assertEqual(Color.green.value, 2)
2768        self.assertEqual(Color.green.color, 'green')
2769        self.assertEqual(Color.green.r, 40)
2770        self.assertEqual(Color.green.g, 50)
2771        self.assertEqual(Color.green.b, 60)
2772        self.assertEqual(Color.blue.value, 5)
2773        self.assertEqual(Color.blue.color, 'blue')
2774        self.assertEqual(Color.blue.r, 70)
2775        self.assertEqual(Color.blue.g, 80)
2776        self.assertEqual(Color.blue.b, 90)
2777        self.assertEqual(Color.chartruese.value, 6)
2778        self.assertEqual(Color.chartruese.color, 'chartruese')
2779        self.assertEqual(Color.chartruese.r, 100)
2780        self.assertEqual(Color.chartruese.g, 110)
2781        self.assertEqual(Color.chartruese.b, 120)
2782        self.assertIs(Color(1), Color.red)
2783        self.assertIs(Color('red'), Color.red)
2784        self.assertIs(Color(10), Color.red)
2785        self.assertIs(Color(20), Color.red)
2786        self.assertIs(Color(30), Color.red)
2787        self.assertIs(Color(2), Color.green)
2788        self.assertIs(Color('green'), Color.green)
2789        self.assertIs(Color(40), Color.green)
2790        self.assertIs(Color(50), Color.green)
2791        self.assertIs(Color(60), Color.green)
2792        self.assertIs(Color(5), Color.blue)
2793        self.assertIs(Color('blue'), Color.blue)
2794        self.assertIs(Color(70), Color.blue)
2795        self.assertIs(Color(80), Color.blue)
2796        self.assertIs(Color(90), Color.blue)
2797        self.assertIs(Color(6), Color.chartruese)
2798        self.assertIs(Color('chartruese'), Color.chartruese)
2799        self.assertIs(Color(100), Color.chartruese)
2800        self.assertIs(Color(110), Color.chartruese)
2801        self.assertIs(Color(120), Color.chartruese)
2802
2803    def test_multivalue_and_autonumber_wo_init_wo_value(self):
2804        class Day(Enum):
2805            _settings_ = MultiValue, AutoNumber
2806            _order_ = 'one two three'
2807            _start_ = 1
2808            one = "21", "one"
2809            two = "22", "two"
2810            three = "23", "three"
2811        self.assertEqual(Day.one.value, 1)
2812        self.assertEqual(Day.two.value, 2)
2813        self.assertEqual(Day.three.value, 3)
2814        self.assertEqual(Day('one'), Day.one)
2815
2816    def test_multivalue_and_autonumber_wo_init_w_some_value(self):
2817        class Color(Enum):
2818            _settings_ = AutoNumber, MultiValue, Unique
2819            _order_ = 'BLACK RED BLUE YELLOW GREEN MAGENTA'
2820            _init_ = "value description"
2821            BLACK = -1, "Text0"
2822            RED = -50, "Text1"
2823            BLUE = auto(), "Text2"
2824            YELLOW = auto(), "Text3"
2825            GREEN = -70, "Text4"
2826            MAGENTA = auto(), "Text5"
2827        self.assertEqual(Color.BLACK.value, -1)
2828        self.assertEqual(Color.RED.value, -50)
2829        self.assertEqual(Color.BLUE.value, -49)
2830        self.assertEqual(Color.YELLOW.value, -48)
2831        self.assertEqual(Color.GREEN.value, -70)
2832        self.assertEqual(Color.MAGENTA.value, -69)
2833        self.assertEqual(Color(-1), Color.BLACK)
2834        self.assertEqual(Color('Text2'), Color.BLUE)
2835
2836    def test_combine_new_settings_with_old_settings(self):
2837        class Auto(Enum):
2838            _settings_ = Unique
2839        with self.assertRaises(ValueError):
2840            class AutoUnique(Auto):
2841                _settings_ = AutoNumber
2842                BLAH = ()
2843                BLUH = ()
2844                ICK = 1
2845
2846    def test_timedelta(self):
2847        class Period(timedelta, Enum):
2848            '''
2849            different lengths of time
2850            '''
2851            _init_ = 'value period'
2852            _settings_ = NoAlias
2853            _ignore_ = 'Period i'
2854            Period = vars()
2855            for i in range(31):
2856                Period['day_%d' % i] = i, 'day'
2857            for i in range(15):
2858                Period['week_%d' % i] = i*7, 'week'
2859            for i in range(12):
2860                Period['month_%d' % i] = i*30, 'month'
2861            OneDay = day_1
2862            OneWeek = week_1
2863        self.assertFalse(hasattr(Period, '_ignore_'))
2864        self.assertFalse(hasattr(Period, 'Period'))
2865        self.assertFalse(hasattr(Period, 'i'))
2866        self.assertTrue(isinstance(Period.day_1, timedelta))
2867
2868    def test_skip(self):
2869        class enumA(Enum):
2870            @skip
2871            class enumB(Enum):
2872                elementA = 'a'
2873                elementB = 'b'
2874            @skip
2875            class enumC(Enum):
2876                elementC = 'c'
2877                elementD = 'd'
2878        self.assertIs(enumA.enumB, enumA.__dict__['enumB'])
2879
2880    def test_nonmember(self):
2881        class enumA(Enum):
2882            @nonmember
2883            class enumB(Enum):
2884                elementA = 'a'
2885                elementB = 'b'
2886            @nonmember
2887            class enumC(Enum):
2888                elementC = 'c'
2889                elementD = 'd'
2890        self.assertIs(enumA.enumB, enumA.__dict__['enumB'])
2891
2892    def test_member_with_external_functions(self):
2893        class Func(Enum):
2894            _order_ = 'an_int a_str'
2895            an_int = member(int)
2896            a_str = member(str)
2897            @classproperty
2898            def types(cls):
2899                return [m.value for m in list(cls)]
2900            def __repr__(self):
2901                return "<%s.%s>" % (self.__class__.__name__, self.name, )
2902            def __call__(self, *args, **kwds):
2903                return self.value(*args, **kwds)
2904        #
2905        self.assertEqual([Func.an_int, Func.a_str], list(Func))
2906        self.assertEqual([int, str], Func.types)
2907        self.assertEqual(Func.an_int(7), 7)
2908        self.assertEqual(Func.a_str('BlahBlah'), 'BlahBlah')
2909
2910    def test_member_with_internal_functions(self):
2911        class Func(Enum):
2912            _order_ = 'haha hehe'
2913            @member
2914            def haha():
2915                return 'haha'
2916            @member
2917            def hehe(name):
2918                return 'hehe -- what a name!  %s!' % name
2919            @classproperty
2920            def types(cls):
2921                return [m.value for m in list(cls)]
2922            def __repr__(self):
2923                return "<%s.%s>" % (self.__class__.__name__, self.name, )
2924            def __call__(self, *args, **kwds):
2925                return self.value(*args, **kwds)
2926        #
2927        self.assertEqual([Func.haha, Func.hehe], list(Func))
2928        self.assertEqual([Func.haha.value, Func.hehe.value], Func.types)
2929        self.assertEqual(Func.haha(), 'haha')
2930        self.assertEqual(Func.hehe('BlahBlah'), 'hehe -- what a name!  BlahBlah!')
2931
2932    def test_constantness_of_constants(self):
2933        class Universe(Enum):
2934            PI = constant(3.141596)
2935            G = constant(6.67300E-11)
2936        self.assertEqual(Universe.PI, 3.141596)
2937        self.assertRaisesRegex(AttributeError, 'cannot rebind constant', setattr, Universe, 'PI', 9)
2938        self.assertRaisesRegex(AttributeError, 'cannot delete constant', delattr, Universe, 'PI')
2939
2940    def test_math_and_stuff_with_constants(self):
2941        class Universe(Enum):
2942            PI = constant(3.141596)
2943            TAU = constant(2 * PI)
2944        self.assertEqual(Universe.PI, 3.141596)
2945        self.assertEqual(Universe.TAU, 2 * Universe.PI)
2946
2947    def test_constant_with_auto_is_updated(self):
2948        class Fruit(Flag):
2949            _order_ = 'apple banana lemon orange'
2950            apple = auto()
2951            banana = auto()
2952            lemon = auto()
2953            orange = auto()
2954            CitrusTypes = constant(lemon | orange)
2955        self.assertEqual(list(Fruit), [Fruit.apple, Fruit.banana, Fruit.lemon, Fruit.orange])
2956        self.assertEqual(list(Fruit.CitrusTypes), [Fruit.orange, Fruit.lemon])
2957        self.assertTrue(Fruit.orange in Fruit.CitrusTypes)
2958
2959    def test_constant_with_enum_is_updated(self):
2960        class Fruit(Flag):
2961            _order_ = 'apple banana lemon orange'
2962            apple = auto()
2963            banana = auto()
2964            lemon = auto()
2965            orange = auto()
2966            CitrusTypes = constant(lemon | orange)
2967        self.assertEqual(list(Fruit), [Fruit.apple, Fruit.banana, Fruit.lemon, Fruit.orange])
2968        self.assertEqual(list(Fruit.CitrusTypes), [Fruit.orange, Fruit.lemon])
2969        self.assertTrue(Fruit.orange in Fruit.CitrusTypes)
2970
2971    def test_order_as_function(self):
2972        # first with _init_
2973        class TestSequence(Enum):
2974            _init_ = 'value, sequence'
2975            _order_ = lambda member: member.sequence
2976            item_id                  = 'An$(1,6)',      0     # Item Code
2977            company_id               = 'An$(7,2)',      1     # Company Code
2978            warehouse_no             = 'An$(9,4)',      2     # Warehouse Number
2979            company                  = 'Hn$(13,6)',     3     # 4 SPACES + COMPANY
2980            key_type                 = 'Cn$(19,3)',     4     # Key Type = '1**'
2981            available                = 'Zn$(1,1)',      5     # Available?
2982            contract_item            = 'Bn(2,1)',       6     # Contract Item?
2983            sales_category           = 'Fn',            7     # Sales Category
2984            gl_category              = 'Rn$(5,1)',      8     # G/L Category
2985            warehouse_category       = 'Sn$(6,1)',      9     # Warehouse Category
2986            inv_units                = 'Qn$(7,2)',     10     # Inv Units
2987        for i, member in enumerate(TestSequence):
2988            self.assertEqual(i, member.sequence)
2989        ts = TestSequence
2990        self.assertEqual(ts.item_id.name, 'item_id')
2991        self.assertEqual(ts.item_id.value, 'An$(1,6)')
2992        self.assertEqual(ts.item_id.sequence, 0)
2993        self.assertEqual(ts.company_id.name, 'company_id')
2994        self.assertEqual(ts.company_id.value, 'An$(7,2)')
2995        self.assertEqual(ts.company_id.sequence, 1)
2996        self.assertEqual(ts.warehouse_no.name, 'warehouse_no')
2997        self.assertEqual(ts.warehouse_no.value, 'An$(9,4)')
2998        self.assertEqual(ts.warehouse_no.sequence, 2)
2999        self.assertEqual(ts.company.name, 'company')
3000        self.assertEqual(ts.company.value, 'Hn$(13,6)')
3001        self.assertEqual(ts.company.sequence, 3)
3002        self.assertEqual(ts.key_type.name, 'key_type')
3003        self.assertEqual(ts.key_type.value, 'Cn$(19,3)')
3004        self.assertEqual(ts.key_type.sequence, 4)
3005        self.assertEqual(ts.available.name, 'available')
3006        self.assertEqual(ts.available.value, 'Zn$(1,1)')
3007        self.assertEqual(ts.available.sequence, 5)
3008        self.assertEqual(ts.contract_item.name, 'contract_item')
3009        self.assertEqual(ts.contract_item.value, 'Bn(2,1)')
3010        self.assertEqual(ts.contract_item.sequence, 6)
3011        self.assertEqual(ts.sales_category.name, 'sales_category')
3012        self.assertEqual(ts.sales_category.value, 'Fn')
3013        self.assertEqual(ts.sales_category.sequence, 7)
3014        self.assertEqual(ts.gl_category.name, 'gl_category')
3015        self.assertEqual(ts.gl_category.value, 'Rn$(5,1)')
3016        self.assertEqual(ts.gl_category.sequence, 8)
3017        self.assertEqual(ts.warehouse_category.name, 'warehouse_category')
3018        self.assertEqual(ts.warehouse_category.value, 'Sn$(6,1)')
3019        self.assertEqual(ts.warehouse_category.sequence, 9)
3020        self.assertEqual(ts.inv_units.name, 'inv_units')
3021        self.assertEqual(ts.inv_units.value, 'Qn$(7,2)')
3022        self.assertEqual(ts.inv_units.sequence, 10)
3023        # and then without
3024        class TestSequence(Enum):
3025            _order_ = lambda member: member.value[1]
3026            item_id                  = 'An$(1,6)',      0     # Item Code
3027            company_id               = 'An$(7,2)',      1     # Company Code
3028            warehouse_no             = 'An$(9,4)',      2     # Warehouse Number
3029            company                  = 'Hn$(13,6)',     3     # 4 SPACES + COMPANY
3030            key_type                 = 'Cn$(19,3)',     4     # Key Type = '1**'
3031            available                = 'Zn$(1,1)',      5     # Available?
3032            contract_item            = 'Bn(2,1)',       6     # Contract Item?
3033            sales_category           = 'Fn',            7     # Sales Category
3034            gl_category              = 'Rn$(5,1)',      8     # G/L Category
3035            warehouse_category       = 'Sn$(6,1)',      9     # Warehouse Category
3036            inv_units                = 'Qn$(7,2)',     10     # Inv Units
3037        for i, member in enumerate(TestSequence):
3038            self.assertEqual(i, member.value[1])
3039        ts = TestSequence
3040        self.assertEqual(ts.item_id.name, 'item_id')
3041        self.assertEqual(ts.item_id.value, ('An$(1,6)', 0))
3042        self.assertEqual(ts.company_id.name, 'company_id')
3043        self.assertEqual(ts.company_id.value, ('An$(7,2)', 1))
3044        self.assertEqual(ts.warehouse_no.name, 'warehouse_no')
3045        self.assertEqual(ts.warehouse_no.value, ('An$(9,4)', 2))
3046        self.assertEqual(ts.company.name, 'company')
3047        self.assertEqual(ts.company.value, ('Hn$(13,6)', 3))
3048        self.assertEqual(ts.key_type.name, 'key_type')
3049        self.assertEqual(ts.key_type.value, ('Cn$(19,3)', 4))
3050        self.assertEqual(ts.available.name, 'available')
3051        self.assertEqual(ts.available.value, ('Zn$(1,1)', 5))
3052        self.assertEqual(ts.contract_item.name, 'contract_item')
3053        self.assertEqual(ts.contract_item.value, ('Bn(2,1)', 6))
3054        self.assertEqual(ts.sales_category.name, 'sales_category')
3055        self.assertEqual(ts.sales_category.value, ('Fn', 7))
3056        self.assertEqual(ts.gl_category.name, 'gl_category')
3057        self.assertEqual(ts.gl_category.value, ('Rn$(5,1)', 8))
3058        self.assertEqual(ts.warehouse_category.name, 'warehouse_category')
3059        self.assertEqual(ts.warehouse_category.value, ('Sn$(6,1)', 9))
3060        self.assertEqual(ts.inv_units.name, 'inv_units')
3061        self.assertEqual(ts.inv_units.value, ('Qn$(7,2)', 10))
3062        # then with _init_ but without value
3063        with self.assertRaises(TypeError):
3064            class TestSequence(Enum):
3065                _init_ = 'sequence'
3066                _order_ = lambda member: member.sequence
3067                item_id                  = 'An$(1,6)',      0     # Item Code
3068                company_id               = 'An$(7,2)',      1     # Company Code
3069                warehouse_no             = 'An$(9,4)',      2     # Warehouse Number
3070                company                  = 'Hn$(13,6)',     3     # 4 SPACES + COMPANY
3071                key_type                 = 'Cn$(19,3)',     4     # Key Type = '1**'
3072                available                = 'Zn$(1,1)',      5     # Available?
3073                contract_item            = 'Bn(2,1)',       6     # Contract Item?
3074                sales_category           = 'Fn',            7     # Sales Category
3075                gl_category              = 'Rn$(5,1)',      8     # G/L Category
3076                warehouse_category       = 'Sn$(6,1)',      9     # Warehouse Category
3077                inv_units                = 'Qn$(7,2)',     10     # Inv Units
3078        # finally, out of order so Python 3 barfs
3079        with self.assertRaises(TypeError):
3080            class TestSequence(Enum):
3081                _init_ = 'sequence'
3082                _order_ = lambda member: member.sequence
3083                item_id                  = 'An$(1,6)',      0     # Item Code
3084                warehouse_no             = 'An$(9,4)',      2     # Warehouse Number
3085                company                  = 'Hn$(13,6)',     3     # 4 SPACES + COMPANY
3086                company_id               = 'An$(7,2)',      1     # Company Code
3087                inv_units                = 'Qn$(7,2)',     10     # Inv Units
3088                available                = 'Zn$(1,1)',      5     # Available?
3089                contract_item            = 'Bn(2,1)',       6     # Contract Item?
3090                sales_category           = 'Fn',            7     # Sales Category
3091                key_type                 = 'Cn$(19,3)',     4     # Key Type = '1**'
3092                gl_category              = 'Rn$(5,1)',      8     # G/L Category
3093                warehouse_category       = 'Sn$(6,1)',      9     # Warehouse Category
3094
3095    def test_order_as_function_in_subclass(self):
3096        #
3097        class Parent(Enum):
3098            _init_ = 'value sequence'
3099            _order_ = lambda m: m.sequence
3100        #
3101        class Child(Parent):
3102            item_id                  = 'An$(1,6)',      0     # Item Code
3103            company_id               = 'An$(7,2)',      1     # Company Code
3104            warehouse_no             = 'An$(9,4)',      2     # Warehouse Number
3105            company                  = 'Hn$(13,6)',     3     # 4 SPACES + COMPANY
3106            key_type                 = 'Cn$(19,3)',     4     # Key Type = '1**'
3107            available                = 'Zn$(1,1)',      5     # Available?
3108            contract_item            = 'Bn(2,1)',       6     # Contract Item?
3109            sales_category           = 'Fn',            7     # Sales Category
3110            gl_category              = 'Rn$(5,1)',      8     # G/L Category
3111            warehouse_category       = 'Sn$(6,1)',      9     # Warehouse Category
3112            inv_units                = 'Qn$(7,2)',     10     # Inv Units
3113        #
3114        for i, member in enumerate(Child):
3115            self.assertEqual(i, member.sequence)
3116        #
3117        ts = Child
3118        self.assertEqual(ts.item_id.name, 'item_id')
3119        self.assertEqual(ts.item_id.value, 'An$(1,6)')
3120        self.assertEqual(ts.item_id.sequence, 0)
3121        self.assertEqual(ts.company_id.name, 'company_id')
3122        self.assertEqual(ts.company_id.value, 'An$(7,2)')
3123        self.assertEqual(ts.company_id.sequence, 1)
3124        self.assertEqual(ts.warehouse_no.name, 'warehouse_no')
3125        self.assertEqual(ts.warehouse_no.value, 'An$(9,4)')
3126        self.assertEqual(ts.warehouse_no.sequence, 2)
3127        self.assertEqual(ts.company.name, 'company')
3128        self.assertEqual(ts.company.value, 'Hn$(13,6)')
3129        self.assertEqual(ts.company.sequence, 3)
3130        self.assertEqual(ts.key_type.name, 'key_type')
3131        self.assertEqual(ts.key_type.value, 'Cn$(19,3)')
3132        self.assertEqual(ts.key_type.sequence, 4)
3133        self.assertEqual(ts.available.name, 'available')
3134        self.assertEqual(ts.available.value, 'Zn$(1,1)')
3135        self.assertEqual(ts.available.sequence, 5)
3136        self.assertEqual(ts.contract_item.name, 'contract_item')
3137        self.assertEqual(ts.contract_item.value, 'Bn(2,1)')
3138        self.assertEqual(ts.contract_item.sequence, 6)
3139        self.assertEqual(ts.sales_category.name, 'sales_category')
3140        self.assertEqual(ts.sales_category.value, 'Fn')
3141        self.assertEqual(ts.sales_category.sequence, 7)
3142        self.assertEqual(ts.gl_category.name, 'gl_category')
3143        self.assertEqual(ts.gl_category.value, 'Rn$(5,1)')
3144        self.assertEqual(ts.gl_category.sequence, 8)
3145        self.assertEqual(ts.warehouse_category.name, 'warehouse_category')
3146        self.assertEqual(ts.warehouse_category.value, 'Sn$(6,1)')
3147        self.assertEqual(ts.warehouse_category.sequence, 9)
3148        self.assertEqual(ts.inv_units.name, 'inv_units')
3149        self.assertEqual(ts.inv_units.value, 'Qn$(7,2)')
3150        self.assertEqual(ts.inv_units.sequence, 10)
3151
3152        pass
3153
3154    if StdlibEnumMeta is not None:
3155        def test_stdlib_inheritence(self):
3156            self.assertTrue(isinstance(self.Season, StdlibEnumMeta))
3157            self.assertTrue(issubclass(self.Season, StdlibEnum))
3158
3159    def test_multiple_mixin(self):
3160        class MaxMixin(object):
3161            @classproperty
3162            def MAX(cls):
3163                max = len(cls)
3164                cls.MAX = max
3165                return max
3166        class StrMixin(object):
3167            def __str__(self):
3168                return self._name_.lower()
3169        class SomeEnum(Enum):
3170            def behavior(self):
3171                return 'booyah'
3172        class AnotherEnum(Enum):
3173            def behavior(self):
3174                return 'nuhuh!'
3175            def social(self):
3176                return "what's up?"
3177        class Color(MaxMixin, Enum):
3178            _order_ = 'RED GREEN BLUE'
3179            RED = auto()
3180            GREEN = auto()
3181            BLUE = auto()
3182        self.assertEqual(Color.RED.value, 1)
3183        self.assertEqual(Color.GREEN.value, 2)
3184        self.assertEqual(Color.BLUE.value, 3)
3185        self.assertEqual(Color.MAX, 3)
3186        self.assertEqual(str(Color.BLUE), 'Color.BLUE')
3187        class Color(MaxMixin, StrMixin, Enum):
3188            _order_ = 'RED GREEN BLUE'
3189            RED = auto()
3190            GREEN = auto()
3191            BLUE = auto()
3192        # print('-' * 15)
3193        # print(list(Color))
3194        # print(Color.__mro__)
3195        # print('-' * 15)
3196        self.assertEqual(Color.RED.value, 1)
3197        self.assertEqual(Color.GREEN.value, 2)
3198        self.assertEqual(Color.BLUE.value, 3)
3199        self.assertEqual(Color.MAX, 3)
3200        self.assertEqual(str(Color.BLUE), 'blue', '%r is not %r' % (str(Color.BLUE), 'blue'))
3201        class Color(StrMixin, MaxMixin, Enum):
3202            _order_ = 'RED GREEN BLUE'
3203            RED = auto()
3204            GREEN = auto()
3205            BLUE = auto()
3206        self.assertEqual(Color.RED.value, 1)
3207        self.assertEqual(Color.GREEN.value, 2)
3208        self.assertEqual(Color.BLUE.value, 3)
3209        self.assertEqual(Color.MAX, 3)
3210        self.assertEqual(str(Color.BLUE), 'blue', '%r is not %r' % (str(Color.BLUE), 'blue'))
3211        class CoolColor(StrMixin, SomeEnum, Enum):
3212            _order_ = 'RED GREEN BLUE'
3213            RED = auto()
3214            GREEN = auto()
3215            BLUE = auto()
3216        self.assertEqual(CoolColor.RED.value, 1)
3217        self.assertEqual(CoolColor.GREEN.value, 2)
3218        self.assertEqual(CoolColor.BLUE.value, 3)
3219        self.assertEqual(str(CoolColor.BLUE), 'blue', '%r is not %r' % (str(Color.BLUE), 'blue'))
3220        self.assertEqual(CoolColor.RED.behavior(), 'booyah')
3221        class CoolerColor(StrMixin, AnotherEnum, Enum):
3222            _order_ = 'RED GREEN BLUE'
3223            RED = auto()
3224            GREEN = auto()
3225            BLUE = auto()
3226        self.assertEqual(CoolerColor.RED.value, 1)
3227        self.assertEqual(CoolerColor.GREEN.value, 2)
3228        self.assertEqual(CoolerColor.BLUE.value, 3)
3229        self.assertEqual(str(CoolerColor.BLUE), 'blue', '%r is not %r' % (str(Color.BLUE), 'blue'))
3230        self.assertEqual(CoolerColor.RED.behavior(), 'nuhuh!')
3231        self.assertEqual(CoolerColor.RED.social(), "what's up?")
3232        class CoolestColor(StrMixin, SomeEnum, AnotherEnum):
3233            _order_ = 'RED GREEN BLUE'
3234            RED = auto()
3235            GREEN = auto()
3236            BLUE = auto()
3237        self.assertEqual(CoolestColor.RED.value, 1)
3238        self.assertEqual(CoolestColor.GREEN.value, 2)
3239        self.assertEqual(CoolestColor.BLUE.value, 3)
3240        self.assertEqual(str(CoolestColor.BLUE), 'blue', '%r is not %r' % (str(Color.BLUE), 'blue'))
3241        self.assertEqual(CoolestColor.RED.behavior(), 'booyah')
3242        self.assertEqual(CoolestColor.RED.social(), "what's up?")
3243        class ConfusedColor(StrMixin, AnotherEnum, SomeEnum):
3244            _order_ = 'RED GREEN BLUE'
3245            RED = auto()
3246            GREEN = auto()
3247            BLUE = auto()
3248        self.assertEqual(ConfusedColor.RED.value, 1)
3249        self.assertEqual(ConfusedColor.GREEN.value, 2)
3250        self.assertEqual(ConfusedColor.BLUE.value, 3)
3251        self.assertEqual(str(ConfusedColor.BLUE), 'blue', '%r is not %r' % (str(Color.BLUE), 'blue'))
3252        self.assertEqual(ConfusedColor.RED.behavior(), 'nuhuh!')
3253        self.assertEqual(ConfusedColor.RED.social(), "what's up?")
3254        class ReformedColor(StrMixin, IntEnum, SomeEnum, AnotherEnum):
3255            _order_ = 'RED GREEN BLUE'
3256            RED = auto()
3257            GREEN = auto()
3258            BLUE = auto()
3259        self.assertEqual(ReformedColor.RED.value, 1)
3260        self.assertEqual(ReformedColor.GREEN.value, 2)
3261        self.assertEqual(ReformedColor.BLUE.value, 3)
3262        self.assertEqual(str(ReformedColor.BLUE), 'blue', '%r is not %r' % (str(Color.BLUE), 'blue'))
3263        self.assertEqual(ReformedColor.RED.behavior(), 'booyah')
3264        self.assertEqual(ConfusedColor.RED.social(), "what's up?")
3265        self.assertTrue(issubclass(ReformedColor, int))
3266
3267    def test_multiple_inherited_mixin(self):
3268        class StrEnum(str, Enum):
3269            def __new__(cls, *args, **kwargs):
3270                for a in args:
3271                    if not isinstance(a, str):
3272                        raise TypeError("Enumeration '%s' (%s) is not"
3273                                        " a string" % (a, type(a).__name__))
3274                return str.__new__(cls, *args, **kwargs)
3275        @unique
3276        class Decision1(StrEnum):
3277            REVERT = "REVERT"
3278            REVERT_ALL = "REVERT_ALL"
3279            RETRY = "RETRY"
3280        class MyEnum(StrEnum):
3281            pass
3282        @unique
3283        class Decision2(MyEnum):
3284            REVERT = "REVERT"
3285            REVERT_ALL = "REVERT_ALL"
3286            RETRY = "RETRY"
3287
3288
3289    def test_enum_of_types(self):
3290        """Support using Enum to refer to types deliberately."""
3291        class MyTypes(Enum):
3292            i = int
3293            f = float
3294            s = str
3295        self.assertEqual(MyTypes.i.value, int)
3296        self.assertEqual(MyTypes.f.value, float)
3297        self.assertEqual(MyTypes.s.value, str)
3298        class Foo:
3299            pass
3300        class Bar:
3301            pass
3302        class MyTypes2(Enum):
3303            a = Foo
3304            b = Bar
3305        self.assertEqual(MyTypes2.a.value, Foo)
3306        self.assertEqual(MyTypes2.b.value, Bar)
3307        class SpamEnumNotInner:
3308            pass
3309        class SpamEnum(Enum):
3310            spam = SpamEnumNotInner
3311        self.assertEqual(SpamEnum.spam.value, SpamEnumNotInner)
3312
3313    if pyver < 3.0:
3314        def test_nested_classes_in_enum_do_become_members(self):
3315            # manually set __qualname__ to remove testing framework noise
3316            class Outer(Enum):
3317                _order_ = 'a b Inner'
3318                __qualname__ = "Outer"
3319                a = 1
3320                b = 2
3321                class Inner(Enum):
3322                    __qualname__ = "Outer.Inner"
3323                    foo = 10
3324                    bar = 11
3325            self.assertTrue(isinstance(Outer.Inner, Outer))
3326            self.assertEqual(Outer.a.value, 1)
3327            self.assertEqual(Outer.Inner.value.foo.value, 10)
3328            self.assertEqual(
3329                list(Outer.Inner.value),
3330                [Outer.Inner.value.foo, Outer.Inner.value.bar],
3331                )
3332            self.assertEqual(
3333                list(Outer),
3334                [Outer.a, Outer.b, Outer.Inner],
3335                )
3336
3337        def test_really_nested_classes_in_enum_do_become_members(self):
3338            class Outer(Enum):
3339                _order_ = 'a b Inner'
3340                a = 1
3341                b = 2
3342                class Inner(Enum):
3343                    foo = 10
3344                    bar = 11
3345            self.assertTrue(isinstance(Outer.Inner, Outer))
3346            self.assertEqual(Outer.a.value, 1)
3347            self.assertEqual(Outer.Inner.value.foo.value, 10)
3348            self.assertEqual(
3349                list(Outer.Inner.value),
3350                [Outer.Inner.value.foo, Outer.Inner.value.bar],
3351                )
3352            self.assertEqual(
3353                list(Outer),
3354                [Outer.a, Outer.b, Outer.Inner],
3355                )
3356
3357    def test_nested_classes_in_enum_are_skipped_with_skip(self):
3358        """Support locally-defined nested classes using @skip"""
3359        # manually set __qualname__ to remove testing framework noise
3360        class Outer(Enum):
3361            __qualname__ = "Outer"
3362            a = 1
3363            b = 2
3364            @skip
3365            class Inner(Enum):
3366                __qualname__ = "Outer.Inner"
3367                foo = 10
3368                bar = 11
3369        self.assertTrue(isinstance(Outer.Inner, type))
3370        self.assertEqual(Outer.a.value, 1)
3371        self.assertEqual(Outer.Inner.foo.value, 10)
3372        self.assertEqual(
3373            list(Outer.Inner),
3374            [Outer.Inner.foo, Outer.Inner.bar],
3375            )
3376        self.assertEqual(
3377            list(Outer),
3378            [Outer.a, Outer.b],
3379            )
3380
3381    def test_really_nested_classes_in_enum_are_skipped_with_skip(self):
3382        """Support locally-defined nested classes using @skip"""
3383        class Outer(Enum):
3384            a = 1
3385            b = 2
3386            @skip
3387            class Inner(Enum):
3388                foo = 10
3389                bar = 11
3390        self.assertTrue(isinstance(Outer.Inner, type))
3391        self.assertEqual(Outer.a.value, 1)
3392        self.assertEqual(Outer.Inner.foo.value, 10)
3393        self.assertEqual(
3394            list(Outer.Inner),
3395            [Outer.Inner.foo, Outer.Inner.bar],
3396            )
3397        self.assertEqual(
3398            list(Outer),
3399            [Outer.a, Outer.b],
3400            )
3401
3402    def test_enum_call_without_arg(self):
3403        class Color(Enum):
3404            black = 0
3405            red = 1
3406            green = 2
3407            blue = 3
3408            #
3409            @classmethod
3410            def _missing_value_(cls, value):
3411                if value is no_arg:
3412                    return cls.black
3413        self.assertTrue(Color.red is Color(1))
3414        self.assertTrue(Color.black is Color())
3415
3416    def test_strict_strenum(self):
3417        from aenum import StrEnum, LowerStrEnum, UpperStrEnum
3418        with self.assertRaisesRegex(TypeError, 'only a single string value may be specified'):
3419            class Huh(StrEnum):
3420                huh = 'this', 'is', 'too', 'many'
3421
3422        for uhoh in (object, object(), [], Enum, 9):
3423            with self.assertRaisesRegex(TypeError, 'values for StrEnum must be strings, not '):
3424                class Huh(StrEnum):
3425                    huh = uhoh
3426
3427        class Either(StrEnum):
3428            _order_ = 'this that Those lower upper'
3429            this = auto()
3430            that = 'That'
3431            Those = auto()
3432            lower = 'lower'
3433            upper = 'UPPER'
3434
3435        self.assertEqual([m.value for m in Either], ['this', 'That', 'Those', 'lower', 'UPPER'])
3436
3437        with self.assertRaisesRegex(ValueError, ' is not lower-case'):
3438            class Huh(LowerStrEnum):
3439                huh = 'What'
3440
3441        class Lower(LowerStrEnum):
3442            _order_ = 'this that Those lower upper'
3443            this = auto()
3444            that = 'that'
3445            Those = auto()
3446            lower = 'lower'
3447            upper = 'upper'
3448
3449        self.assertEqual([m.value for m in Lower], ['this', 'that', 'those', 'lower', 'upper'])
3450
3451        with self.assertRaisesRegex(ValueError, ' is not upper-case'):
3452            class Huh(UpperStrEnum):
3453                huh = 'What'
3454
3455        class Upper(UpperStrEnum):
3456            _order_ = 'this that Those lower upper'
3457            this = auto()
3458            that = 'THAT'
3459            Those = auto()
3460            lower = 'LOWER'
3461            upper = 'UPPER'
3462
3463        self.assertEqual([m.value for m in Upper], ['THIS', 'THAT', 'THOSE', 'LOWER', 'UPPER'])
3464
3465    def test_enum_property(self):
3466        class SomeClass(object):
3467            #
3468            an_attr = 97
3469            _attr_x = None
3470            #
3471            def a_method(self, some_number):
3472                return self.an_attr - some_number
3473            #
3474            @property
3475            def attr(self):
3476                return self._attr_x
3477            @attr.setter
3478            def attr(self, value):
3479                self._attr_x = value
3480            #
3481            @classmethod
3482            def a_class_method(cls, another_number, a_string=None):
3483                return a_string * (9 - another_number)
3484            #
3485            @staticmethod
3486            def a_static_method(a, b):
3487                return a * b
3488        #
3489        class SomeEnum(SomeClass, Enum):
3490            _order_ = 'an_attr a_method attr a_class_method a_static_method'
3491            an_attr = 1
3492            a_method = 2
3493            attr = 3
3494            a_class_method = 4
3495            a_static_method = 5
3496        #
3497        SE = SomeEnum
3498        self.assertEqual(
3499                list(SomeEnum),
3500                [SE.an_attr, SE.a_method, SE.attr, SE.a_class_method, SE.a_static_method],
3501                )
3502        self.assertEqual(SE.an_attr.a_static_method(2, 3), 6)
3503        self.assertEqual(SE.a_method.an_attr, 97)
3504        self.assertEqual(SE.attr.a_class_method(6, 'x'), 'xxx')
3505        self.assertEqual(SE.a_class_method.attr, None)
3506        SE.a_class_method.attr = 99
3507        self.assertEqual(SE.a_class_method.attr, 99)
3508        self.assertEqual(SE.a_method.attr, None)
3509        self.assertEqual(SE.a_static_method.a_method(90), 7)
3510
3511
3512class TestFlag(TestCase):
3513    """Tests of the Flags."""
3514
3515    class Perm(Flag):
3516        R, W, X = 4, 2, 1
3517
3518    class Color(Flag):
3519        BLACK = 0
3520        RED = 1
3521        GREEN = 2
3522        BLUE = 4
3523        PURPLE = RED|BLUE
3524
3525    class TermColor(str, Flag):
3526        _settings_ = AutoValue
3527
3528        def __new__(cls, value, code):
3529            str_value = '\x1b[%sm' % code
3530            obj = str.__new__(cls, str_value)
3531            obj._value_ = value
3532            obj.code = code
3533            return obj
3534
3535        @classmethod
3536        def _create_pseudo_member_values_(cls, members, *values):
3537            code = ';'.join(m.code for m in members)
3538            return values + (code, )
3539
3540        AllReset = '0'           # ESC [ 0 m       # reset all (colors and brightness)
3541        Bright = '1'          # ESC [ 1 m       # bright
3542        Dim = '2'             # ESC [ 2 m       # dim (looks same as normal brightness)
3543        Underline = '4'
3544        Normal = '22'         # ESC [ 22 m      # normal brightness
3545                            #
3546                            # # FOREGROUND - 30s  BACKGROUND - 40s:
3547        FG_Black = '30'           # ESC [ 30 m      # black
3548        FG_Red = '31'             # ESC [ 31 m      # red
3549        FG_Green = '32'           # ESC [ 32 m      # green
3550        FG_Yellow = '33'          # ESC [ 33 m      # yellow
3551        FG_Blue = '34'            # ESC [ 34 m      # blue
3552        FG_Magenta = '35'         # ESC [ 35 m      # magenta
3553        FG_Cyan = '36'            # ESC [ 36 m      # cyan
3554        FG_White = '37'           # ESC [ 37 m      # white
3555        FG_Reset = '39'           # ESC [ 39 m      # reset
3556                                #
3557        BG_Black = '40'           # ESC [ 30 m      # black
3558        BG_Red = '41'             # ESC [ 31 m      # red
3559        BG_Green = '42'           # ESC [ 32 m      # green
3560        BG_Yellow = '43'          # ESC [ 33 m      # yellow
3561        BG_Blue = '44'            # ESC [ 34 m      # blue
3562        BG_Magenta = '45'         # ESC [ 35 m      # magenta
3563        BG_Cyan = '46'            # ESC [ 36 m      # cyan
3564        BG_White = '47'           # ESC [ 37 m      # white
3565        BG_Reset = '49'           # ESC [ 39 m      # reset
3566
3567        __str__ = str.__str__
3568
3569        def __repr__(self):
3570            if self._name_ is not None:
3571                return '<%s.%s>' % (self.__class__.__name__, self._name_)
3572            else:
3573                return '<%s: %s>' % (self.__class__.__name__, '|'.join([m.name for m in Flag.__iter__(self)]))
3574
3575        def __enter__(self):
3576            print(self.AllReset, end='', verbose=0)
3577            return self
3578
3579        def __exit__(self, *args):
3580            print(self.AllReset, end='', verbose=0)
3581
3582
3583    class Open(Flag):
3584        RO = 0
3585        WO = 1
3586        RW = 2
3587        AC = 3
3588        CE = 1<<19
3589
3590    def test_str_is_str_str(self):
3591        red, white = self.TermColor.FG_Red, self.TermColor.BG_White
3592        barber = red | white
3593        self.assertEqual(barber, '\x1b[47;31m')
3594        self.assertEqual(barber.value, red.value | white.value)
3595        self.assertEqual(barber.code, ';'.join([white.code, red.code]))
3596        self.assertEqual(repr(barber), '<TermColor: BG_White|FG_Red>')
3597        self.assertEqual(str(barber), '\x1b[47;31m')
3598
3599    def test_membership(self):
3600        Color = self.Color
3601        Open = self.Open
3602        self.assertRaises(TypeError, lambda: 'BLACK' in Color)
3603        self.assertRaises(TypeError, lambda: 'RO' in Open)
3604        self.assertTrue(Color.BLACK in Color)
3605        self.assertTrue(Open.RO in Open)
3606        self.assertFalse(Color.BLACK in Open)
3607        self.assertFalse(Open.RO in Color)
3608        self.assertRaises(TypeError, lambda: 0 in Color)
3609        self.assertRaises(TypeError, lambda: 0 in Open)
3610
3611    def test_member_contains(self):
3612        Color = self.Color
3613        self.assertRaises(TypeError, lambda: 'test' in Color.BLUE)
3614        self.assertRaises(TypeError, lambda: 2 in Color.BLUE)
3615        self.assertTrue(Color.BLUE in Color.BLUE)
3616        self.assertTrue(Color.BLUE in Color['RED|GREEN|BLUE'])
3617
3618    def test_str(self):
3619        Perm = self.Perm
3620        self.assertEqual(str(Perm.R), 'Perm.R')
3621        self.assertEqual(str(Perm.W), 'Perm.W')
3622        self.assertEqual(str(Perm.X), 'Perm.X')
3623        self.assertEqual(str(Perm.R | Perm.W), 'Perm.R|W')
3624        self.assertEqual(str(Perm.R | Perm.W | Perm.X), 'Perm.R|W|X')
3625        self.assertEqual(str(Perm(0)), 'Perm.0')
3626        self.assertEqual(str(~Perm.R), 'Perm.W|X')
3627        self.assertEqual(str(~Perm.W), 'Perm.R|X')
3628        self.assertEqual(str(~Perm.X), 'Perm.R|W')
3629        self.assertEqual(str(~(Perm.R | Perm.W)), 'Perm.X')
3630        self.assertEqual(str(~(Perm.R | Perm.W | Perm.X)), 'Perm.0')
3631        self.assertEqual(str(Perm(~0)), 'Perm.R|W|X')
3632
3633        Open = self.Open
3634        self.assertEqual(str(Open.RO), 'Open.RO')
3635        self.assertEqual(str(Open.WO), 'Open.WO')
3636        self.assertEqual(str(Open.AC), 'Open.AC')
3637        self.assertEqual(str(Open.RO | Open.CE), 'Open.CE')
3638        self.assertEqual(str(Open.WO | Open.CE), 'Open.CE|WO')
3639        self.assertEqual(str(~Open.RO), 'Open.CE|AC|RW|WO')
3640        self.assertEqual(str(~Open.WO), 'Open.CE|RW')
3641        self.assertEqual(str(~Open.AC), 'Open.CE')
3642        self.assertEqual(str(~(Open.RO | Open.CE)), 'Open.AC')
3643        self.assertEqual(str(~(Open.WO | Open.CE)), 'Open.RW')
3644
3645    def test_repr(self):
3646        Perm = self.Perm
3647        self.assertEqual(repr(Perm.R), '<Perm.R: 4>')
3648        self.assertEqual(repr(Perm.W), '<Perm.W: 2>')
3649        self.assertEqual(repr(Perm.X), '<Perm.X: 1>')
3650        self.assertEqual(repr(Perm.R | Perm.W), '<Perm.R|W: 6>')
3651        self.assertEqual(repr(Perm.R | Perm.W | Perm.X), '<Perm.R|W|X: 7>')
3652        self.assertEqual(repr(Perm(0)), '<Perm.0: 0>')
3653        self.assertEqual(repr(~Perm.R), '<Perm.W|X: 3>')
3654        self.assertEqual(repr(~Perm.W), '<Perm.R|X: 5>')
3655        self.assertEqual(repr(~Perm.X), '<Perm.R|W: 6>')
3656        self.assertEqual(repr(~(Perm.R | Perm.W)), '<Perm.X: 1>')
3657        self.assertEqual(repr(~(Perm.R | Perm.W | Perm.X)), '<Perm.0: 0>')
3658        self.assertEqual(repr(Perm(~0)), '<Perm.R|W|X: 7>')
3659
3660        Open = self.Open
3661        self.assertEqual(repr(Open.RO), '<Open.RO: 0>')
3662        self.assertEqual(repr(Open.WO), '<Open.WO: 1>')
3663        self.assertEqual(repr(Open.AC), '<Open.AC: 3>')
3664        self.assertEqual(repr(Open.RO | Open.CE), '<Open.CE: 524288>')
3665        self.assertEqual(repr(Open.WO | Open.CE), '<Open.CE|WO: 524289>')
3666        self.assertEqual(repr(~Open.RO), '<Open.CE|AC|RW|WO: 524291>')
3667        self.assertEqual(repr(~Open.WO), '<Open.CE|RW: 524290>')
3668        self.assertEqual(repr(~Open.AC), '<Open.CE: 524288>')
3669        self.assertEqual(repr(~(Open.RO | Open.CE)), '<Open.AC: 3>')
3670        self.assertEqual(repr(~(Open.WO | Open.CE)), '<Open.RW: 2>')
3671
3672    def test_name_lookup(self):
3673        Color = self.Color
3674        self.assertTrue(Color.RED is Color['RED'])
3675        self.assertTrue(Color.RED|Color.GREEN is Color['RED|GREEN'])
3676        self.assertTrue(Color.PURPLE is Color['RED|BLUE'])
3677
3678    def test_or(self):
3679        Perm = self.Perm
3680        for i in Perm:
3681            for j in Perm:
3682                self.assertEqual((i | j), Perm(i.value | j.value))
3683                self.assertEqual((i | j).value, i.value | j.value)
3684                self.assertIs(type(i | j), Perm)
3685        for i in Perm:
3686            self.assertIs(i | i, i)
3687        Open = self.Open
3688        self.assertIs(Open.RO | Open.CE, Open.CE)
3689
3690    def test_and(self):
3691        Perm = self.Perm
3692        RW = Perm.R | Perm.W
3693        RX = Perm.R | Perm.X
3694        WX = Perm.W | Perm.X
3695        RWX = Perm.R | Perm.W | Perm.X
3696        values = list(Perm) + [RW, RX, WX, RWX, Perm(0)]
3697        for i in values:
3698            for j in values:
3699                self.assertEqual((i & j).value, i.value & j.value)
3700                self.assertIs(type(i & j), Perm)
3701        for i in Perm:
3702            self.assertIs(i & i, i)
3703            self.assertIs(i & RWX, i)
3704            self.assertIs(RWX & i, i)
3705        Open = self.Open
3706        self.assertIs(Open.RO & Open.CE, Open.RO)
3707
3708    def test_xor(self):
3709        Perm = self.Perm
3710        for i in Perm:
3711            for j in Perm:
3712                self.assertEqual((i ^ j).value, i.value ^ j.value)
3713                self.assertIs(type(i ^ j), Perm)
3714        for i in Perm:
3715            self.assertIs(i ^ Perm(0), i)
3716            self.assertIs(Perm(0) ^ i, i)
3717        Open = self.Open
3718        self.assertIs(Open.RO ^ Open.CE, Open.CE)
3719        self.assertIs(Open.CE ^ Open.CE, Open.RO)
3720
3721    def test_invert(self):
3722        Perm = self.Perm
3723        RW = Perm.R | Perm.W
3724        RX = Perm.R | Perm.X
3725        WX = Perm.W | Perm.X
3726        RWX = Perm.R | Perm.W | Perm.X
3727        values = list(Perm) + [RW, RX, WX, RWX, Perm(0)]
3728        for i in values:
3729            self.assertIs(type(~i), Perm)
3730            self.assertEqual(~~i, i)
3731        for i in Perm:
3732            self.assertIs(~~i, i)
3733        Open = self.Open
3734        self.assertIs(Open.WO & ~Open.WO, Open.RO)
3735        self.assertIs((Open.WO|Open.CE) & ~Open.WO, Open.CE)
3736
3737    def test_bool(self):
3738        Perm = self.Perm
3739        for f in Perm:
3740            self.assertTrue(f)
3741        Open = self.Open
3742        for f in Open:
3743            self.assertEqual(bool(f.value), bool(f))
3744
3745    def test_iteration(self):
3746        C = self.Color
3747        self.assertEqual(list(C), [C.BLACK, C.RED, C.GREEN, C.BLUE, C.PURPLE])
3748
3749    def test_member_iteration(self):
3750        C = self.Color
3751        self.assertEqual(list(C.BLACK), [])
3752        self.assertEqual(list(C.RED), [C.RED])
3753        self.assertEqual(list(C.PURPLE), [C.BLUE, C.RED])
3754
3755    def test_programatic_function_string(self):
3756        Perm = Flag('Perm', 'R W X')
3757        lst = list(Perm)
3758        self.assertEqual(len(lst), len(Perm))
3759        self.assertEqual(len(Perm), 3, Perm)
3760        self.assertEqual(lst, [Perm.R, Perm.W, Perm.X])
3761        for i, n in enumerate('R W X'.split()):
3762            v = 1<<i
3763            e = Perm(v)
3764            self.assertEqual(e.value, v)
3765            self.assertEqual(type(e.value), int)
3766            self.assertEqual(e.name, n)
3767            self.assertIn(e, Perm)
3768            self.assertIs(type(e), Perm)
3769
3770    def test_programatic_function_string_with_start(self):
3771        Perm = Flag('Perm', 'R W X', start=8)
3772        lst = list(Perm)
3773        self.assertEqual(len(lst), len(Perm))
3774        self.assertEqual(len(Perm), 3, Perm)
3775        self.assertEqual(lst, [Perm.R, Perm.W, Perm.X])
3776        for i, n in enumerate('R W X'.split()):
3777            v = 8<<i
3778            e = Perm(v)
3779            self.assertEqual(e.value, v)
3780            self.assertEqual(type(e.value), int)
3781            self.assertEqual(e.name, n)
3782            self.assertIn(e, Perm)
3783            self.assertIs(type(e), Perm)
3784
3785    def test_programatic_function_string_list(self):
3786        Perm = Flag('Perm', ['R', 'W', 'X'])
3787        lst = list(Perm)
3788        self.assertEqual(len(lst), len(Perm))
3789        self.assertEqual(len(Perm), 3, Perm)
3790        self.assertEqual(lst, [Perm.R, Perm.W, Perm.X])
3791        for i, n in enumerate('R W X'.split()):
3792            v = 1<<i
3793            e = Perm(v)
3794            self.assertEqual(e.value, v)
3795            self.assertEqual(type(e.value), int)
3796            self.assertEqual(e.name, n)
3797            self.assertIn(e, Perm)
3798            self.assertIs(type(e), Perm)
3799
3800    def test_programatic_function_iterable(self):
3801        Perm = Flag('Perm', (('R', 2), ('W', 8), ('X', 32)))
3802        lst = list(Perm)
3803        self.assertEqual(len(lst), len(Perm))
3804        self.assertEqual(len(Perm), 3, Perm)
3805        self.assertEqual(lst, [Perm.R, Perm.W, Perm.X])
3806        for i, n in enumerate('R W X'.split()):
3807            v = 1<<(2*i+1)
3808            e = Perm(v)
3809            self.assertEqual(e.value, v)
3810            self.assertEqual(type(e.value), int)
3811            self.assertEqual(e.name, n)
3812            self.assertIn(e, Perm)
3813            self.assertIs(type(e), Perm)
3814
3815    def test_programatic_function_from_dict(self):
3816        Perm = Flag('Perm', OrderedDict((('R', 2), ('W', 8), ('X', 32))))
3817        lst = list(Perm)
3818        self.assertEqual(len(lst), len(Perm))
3819        self.assertEqual(len(Perm), 3, Perm)
3820        self.assertEqual(lst, [Perm.R, Perm.W, Perm.X])
3821        for i, n in enumerate('R W X'.split()):
3822            v = 1<<(2*i+1)
3823            e = Perm(v)
3824            self.assertEqual(e.value, v)
3825            self.assertEqual(type(e.value), int)
3826            self.assertEqual(e.name, n)
3827            self.assertIn(e, Perm)
3828            self.assertIs(type(e), Perm)
3829
3830    def test_programatic_function_empty_list(self):
3831        Perm = IntFlag('Perm', [])
3832        self.assertEqual(len(list(Perm)), len(Perm))
3833        self.assertEqual(len(Perm), 0)
3834        Thing = Enum('Thing', [])
3835        self.assertEqual(len(list(Thing)), len(Thing))
3836        self.assertEqual(len(Thing), 0)
3837
3838    def test_programatic_function_empty_tuple(self):
3839        Perm = IntFlag('Perm', ())
3840        self.assertEqual(len(list(Perm)), len(Perm))
3841        self.assertEqual(len(Perm), 0)
3842        Thing = Enum('Thing', ())
3843        self.assertEqual(len(list(Thing)), len(Thing))
3844        self.assertEqual(len(Thing), 0)
3845
3846    def test_pickle(self):
3847        if isinstance(FlagStooges, Exception):
3848            raise FlagStooges
3849        test_pickle_dump_load(self.assertIs, FlagStooges.CURLY|FlagStooges.MOE)
3850        test_pickle_dump_load(self.assertIs, FlagStooges)
3851
3852    def test_containment(self):
3853        Perm = self.Perm
3854        R, W, X = Perm
3855        RW = R | W
3856        RX = R | X
3857        WX = W | X
3858        RWX = R | W | X
3859        self.assertTrue(R in RW)
3860        self.assertTrue(R in RX)
3861        self.assertTrue(R in RWX)
3862        self.assertTrue(W in RW)
3863        self.assertTrue(W in WX)
3864        self.assertTrue(W in RWX)
3865        self.assertTrue(X in RX)
3866        self.assertTrue(X in WX)
3867        self.assertTrue(X in RWX)
3868        self.assertFalse(R in WX)
3869        self.assertFalse(W in RX)
3870        self.assertFalse(X in RW)
3871
3872    def test_auto_number(self):
3873        class Color(Flag):
3874            _order_ = 'red blue green'
3875            red = auto()
3876            blue = auto()
3877            green = auto()
3878
3879        self.assertEqual(list(Color), [Color.red, Color.blue, Color.green])
3880        self.assertEqual(Color.red.value, 1)
3881        self.assertEqual(Color.blue.value, 2)
3882        self.assertEqual(Color.green.value, 4)
3883
3884    def test_auto_number_garbage(self):
3885        with self.assertRaisesRegex(TypeError, 'invalid Flag value: .not an int.'):
3886            class Color(Flag):
3887                _order_ = 'red blue'
3888                red = 'not an int'
3889                blue = auto()
3890
3891    def test_auto_w_pending(self):
3892        class Required(Flag):
3893            _order_ = 'NONE TO_S FROM_S BOTH'
3894            NONE = 0
3895            TO_S = auto()
3896            FROM_S = auto()
3897            BOTH = TO_S | FROM_S
3898        self.assertEqual(Required.TO_S.value, 1)
3899        self.assertEqual(Required.FROM_S.value, 2)
3900        self.assertEqual(Required.BOTH.value, 3)
3901
3902    def test_cascading_failure(self):
3903        class Bizarre(Flag):
3904            c = 3
3905            d = 4
3906            f = 6
3907        # Bizarre.c | Bizarre.d
3908        self.assertRaisesRegex(ValueError, "5 is not a valid Bizarre", Bizarre, 5)
3909        self.assertRaisesRegex(ValueError, "5 is not a valid Bizarre", Bizarre, 5)
3910        self.assertRaisesRegex(ValueError, "2 is not a valid Bizarre", Bizarre, 2)
3911        self.assertRaisesRegex(ValueError, "2 is not a valid Bizarre", Bizarre, 2)
3912        self.assertRaisesRegex(ValueError, "1 is not a valid Bizarre", Bizarre, 1)
3913        self.assertRaisesRegex(ValueError, "1 is not a valid Bizarre", Bizarre, 1)
3914
3915    def test_duplicate_auto(self):
3916        class Dupes(Enum):
3917            _order_ = 'first second third'
3918            first = primero = auto()
3919            second = auto()
3920            third = auto()
3921        self.assertEqual([Dupes.first, Dupes.second, Dupes.third], list(Dupes))
3922
3923    def test_bizarre(self):
3924        class Bizarre(Flag):
3925            b = 3
3926            c = 4
3927            d = 6
3928        self.assertEqual(repr(Bizarre(7)), '<Bizarre.d|c|b: 7>')
3929
3930    def test_multiple_mixin(self):
3931        class AllMixin(object):
3932            @classproperty
3933            def ALL(cls):
3934                members = list(cls)
3935                all_value = None
3936                if members:
3937                    all_value = members[0]
3938                    for member in members[1:]:
3939                        all_value |= member
3940                cls.ALL = all_value
3941                return all_value
3942        class StrMixin(object):
3943            def __str__(self):
3944                return self._name_.lower()
3945        class Color(AllMixin, Flag):
3946            _order_ = 'RED GREEN BLUE'
3947            RED = auto()
3948            GREEN = auto()
3949            BLUE = auto()
3950        self.assertEqual(Color.RED.value, 1)
3951        self.assertEqual(Color.GREEN.value, 2)
3952        self.assertEqual(Color.BLUE.value, 4)
3953        self.assertEqual(Color.ALL.value, 7)
3954        self.assertEqual(str(Color.BLUE), 'Color.BLUE')
3955        class Color(AllMixin, StrMixin, Flag):
3956            _order_ = 'RED GREEN BLUE'
3957            RED = auto()
3958            GREEN = auto()
3959            BLUE = auto()
3960        self.assertEqual(Color.RED.value, 1)
3961        self.assertEqual(Color.GREEN.value, 2)
3962        self.assertEqual(Color.BLUE.value, 4)
3963        self.assertEqual(Color.ALL.value, 7)
3964        self.assertEqual(str(Color.BLUE), 'blue')
3965        class Color(StrMixin, AllMixin, Flag):
3966            _order_ = 'RED GREEN BLUE'
3967            RED = auto()
3968            GREEN = auto()
3969            BLUE = auto()
3970        self.assertEqual(Color.RED.value, 1)
3971        self.assertEqual(Color.GREEN.value, 2)
3972        self.assertEqual(Color.BLUE.value, 4)
3973        self.assertEqual(Color.ALL.value, 7)
3974        self.assertEqual(str(Color.BLUE), 'blue')
3975
3976    @unittest.skipUnless(threading, 'Threading required for this test.')
3977    def test_unique_composite(self):
3978        # override __eq__ to be identity only
3979        class TestFlag(Flag):
3980            _order_ = 'one two three four five six seven eight'
3981            one = auto()
3982            two = auto()
3983            three = auto()
3984            four = auto()
3985            five = auto()
3986            six = auto()
3987            seven = auto()
3988            eight = auto()
3989            def __eq__(self, other):
3990                return self is other
3991            def __hash__(self):
3992                return hash(self._value_)
3993        # have multiple threads competing to complete the composite members
3994        seen = set()
3995        failed = [False]
3996        def cycle_enum():
3997            # nonlocal failed
3998            try:
3999                for i in range(256):
4000                    seen.add(TestFlag(i))
4001            except Exception:
4002                failed[0] = True
4003        threads = [
4004                threading.Thread(target=cycle_enum)
4005                for _ in range(8)
4006                ]
4007        for t in threads:
4008            t.start()
4009        for t in threads:
4010            t.join()
4011        # check that only 248 members were created (8 were created originally)
4012        self.assertFalse(
4013                failed[0],
4014                'at least one thread failed while creating composite members')
4015        self.assertEqual(256, len(seen), 'too many composite members created')
4016
4017    def test_init_with_autovalue_and_generate_next_value(self):
4018        class Color(Flag):
4019            _settings_ = AutoValue
4020            _init_ = 'value code'
4021            def _generate_next_value_(name, start, count, last_values, *args, **kwds):
4022                if not count:
4023                    return ((1, start)[start is not None], ) + args
4024                error = False
4025                for last_value_pair in reversed(last_values):
4026                    last_value, last_code = last_value_pair
4027                    try:
4028                        high_bit = aenum._high_bit(last_value)
4029                        break
4030                    except Exception:
4031                        error = True
4032                        break
4033                if error:
4034                    raise TypeError('Invalid Flag value: %r' % (last_value, ))
4035                return (2 ** (high_bit+1), ) + args
4036            # TODO: actually test _create_pseudo_member
4037            @classmethod
4038            def _create_pseudo_member_(cls, value):
4039                pseudo_member = cls._value2member_map_.get(value, None)
4040                if pseudo_member is None:
4041                    members, _ = aenum._decompose(cls, value)
4042                    pseudo_member = super(Color, cls)._create_pseudo_member_(value)
4043                    pseudo_member.code = ';'.join(m.code for m in members)
4044                return pseudo_member
4045            AllReset = '0'           # ESC [ 0 m       # reset all (colors and brightness)
4046            Bright = '1'          # ESC [ 1 m       # bright
4047            Dim = '2'             # ESC [ 2 m       # dim (looks same as normal brightness)
4048            Underline = '4'
4049            Normal = '22'         # ESC [ 22 m      # normal brightness
4050        # if we got here, we're good
4051
4052    def test_autovalue_and_generate_next_value(self):
4053        class Color(str, Flag):
4054            _order_ = 'FG_Black FG_Red FG_Green FG_Blue BG_Yellow BG_Magenta BG_Cyan BG_White'
4055            _settings_ = AutoValue
4056            def __new__(cls, value, code):
4057                str_value = '\x1b[%sm' % code
4058                obj = str.__new__(cls, str_value)
4059                obj._value_ = value
4060                obj.code = code
4061                return obj
4062            @staticmethod
4063            def _generate_next_value_(name, start, count, values, *args, **kwds):
4064                return (2 ** count, ) + args
4065            # TODO: actually test _create_pseudo_member
4066            @classmethod
4067            def _create_pseudo_member_(cls, value):
4068                pseudo_member = cls._value2member_map_.get(value, None)
4069                if pseudo_member is None:
4070                    # calculate the code
4071                    members, _ = aenum._decompose(cls, value)
4072                    code = ';'.join(m.code for m in members)
4073                    pseudo_member = super(Color, cls)._create_pseudo_member_(value, code)
4074                return pseudo_member
4075            #
4076                                      # # FOREGROUND - 30s  BACKGROUND - 40s:
4077            FG_Black = '30'           # ESC [ 30 m      # black
4078            FG_Red = '31'             # ESC [ 31 m      # red
4079            FG_Green = '32'           # ESC [ 32 m      # green
4080            FG_Blue = '34'            # ESC [ 34 m      # blue
4081                                      #
4082            BG_Yellow = '43'          # ESC [ 33 m      # yellow
4083            BG_Magenta = '45'         # ESC [ 35 m      # magenta
4084            BG_Cyan = '46'            # ESC [ 36 m      # cyan
4085            BG_White = '47'           # ESC [ 37 m      # white
4086        # if we got here, we're good
4087
4088    def test_subclass(self):
4089        class Color(str, Flag):
4090            _order_ = 'FG_Black FG_Red FG_Green FG_Blue BG_Yellow BG_Magenta BG_Cyan BG_White'
4091            _settings_ = AutoValue
4092            def __new__(cls, value, code):
4093                str_value = '\x1b[%sm' % code
4094                obj = str.__new__(cls, str_value)
4095                obj._value_ = value
4096                obj.code = code
4097                return obj
4098            @staticmethod
4099            def _generate_next_value_(name, start, count, values, *args, **kwds):
4100                return (2 ** count, ) + args
4101            @classmethod
4102            def _create_pseudo_member_(cls, value):
4103                pseudo_member = cls._value2member_map_.get(value, None)
4104                if pseudo_member is None:
4105                    # calculate the code
4106                    members, _ = aenum._decompose(cls, value)
4107                    code = ';'.join(m.code for m in members)
4108                    pseudo_member = super(Color, cls)._create_pseudo_member_(value, code)
4109                return pseudo_member
4110            #
4111                                      # # FOREGROUND - 30s  BACKGROUND - 40s:
4112            FG_Black = '30'           # ESC [ 30 m      # black
4113            FG_Red = '31'             # ESC [ 31 m      # red
4114            FG_Green = '32'           # ESC [ 32 m      # green
4115            FG_Blue = '34'            # ESC [ 34 m      # blue
4116                                      #
4117            BG_Yellow = '43'          # ESC [ 33 m      # yellow
4118            BG_Magenta = '45'         # ESC [ 35 m      # magenta
4119            BG_Cyan = '46'            # ESC [ 36 m      # cyan
4120            BG_White = '47'           # ESC [ 37 m      # white
4121        self.assertTrue(isinstance(Color.FG_Black, Color))
4122        self.assertTrue(isinstance(Color.FG_Black, str))
4123        self.assertEqual(Color.FG_Black, '\x1b[30m')
4124        self.assertEqual(Color.FG_Black.code, '30')
4125
4126    def test_sub_subclass_1(self):
4127        class StrFlag(str, Flag):
4128            _settings_ = AutoValue
4129            def __new__(cls, value, code):
4130                str_value = '\x1b[%sm' % code
4131                obj = str.__new__(cls, str_value)
4132                obj._value_ = value
4133                obj.code = code
4134                return obj
4135            @classmethod
4136            def _create_pseudo_member_(cls, value):
4137                pseudo_member = cls._value2member_map_.get(value, None)
4138                if pseudo_member is None:
4139                    # calculate the code
4140                    members, _ = aenum._decompose(cls, value)
4141                    code = ';'.join(m.code for m in members)
4142                    pseudo_member = super(Color, cls)._create_pseudo_member_(value, code)
4143                return pseudo_member
4144            #
4145        class Color(StrFlag):
4146            _order_ = 'FG_Black FG_Red FG_Green FG_Blue BG_Yellow BG_Magenta BG_Cyan BG_White'
4147                                      # # FOREGROUND - 30s  BACKGROUND - 40s:
4148            FG_Black = '30'           # ESC [ 30 m      # black
4149            FG_Red = '31'             # ESC [ 31 m      # red
4150            FG_Green = '32'           # ESC [ 32 m      # green
4151            FG_Blue = '34'            # ESC [ 34 m      # blue
4152                                      #
4153            BG_Yellow = '43'          # ESC [ 33 m      # yellow
4154            BG_Magenta = '45'         # ESC [ 35 m      # magenta
4155            BG_Cyan = '46'            # ESC [ 36 m      # cyan
4156            BG_White = '47'           # ESC [ 37 m      # white
4157        self.assertTrue(isinstance(Color.FG_Black, Color))
4158        self.assertTrue(isinstance(Color.FG_Black, str))
4159        self.assertEqual(Color.FG_Black, '\x1b[30m')
4160        self.assertEqual(Color.FG_Black.code, '30')
4161
4162    def test_sub_subclass_2(self):
4163        class StrFlag(str, Flag):
4164            _settings_ = AutoValue
4165            @staticmethod
4166            def _generate_next_value_(name, start, count, values, *args, **kwds):
4167                return (2 ** count, ) + args
4168            @classmethod
4169            def _create_pseudo_member_(cls, value):
4170                pseudo_member = cls._value2member_map_.get(value, None)
4171                if pseudo_member is None:
4172                    # calculate the code
4173                    members, _ = aenum._decompose(cls, value)
4174                    code = ';'.join(m.code for m in members)
4175                    pseudo_member = super(Color, cls)._create_pseudo_member_(value, code)
4176                return pseudo_member
4177            #
4178        class Color(StrFlag):
4179            _order_ = 'FG_Black FG_Red FG_Green FG_Blue BG_Yellow BG_Magenta BG_Cyan BG_White'
4180            def __new__(cls, value, code):
4181                str_value = '\x1b[%sm' % code
4182                obj = str.__new__(cls, str_value)
4183                obj._value_ = value
4184                obj.code = code
4185                return obj
4186                                      # # FOREGROUND - 30s  BACKGROUND - 40s:
4187            FG_Black = '30'           # ESC [ 30 m      # black
4188            FG_Red = '31'             # ESC [ 31 m      # red
4189            FG_Green = '32'           # ESC [ 32 m      # green
4190            FG_Blue = '34'            # ESC [ 34 m      # blue
4191                                      #
4192            BG_Yellow = '43'          # ESC [ 33 m      # yellow
4193            BG_Magenta = '45'         # ESC [ 35 m      # magenta
4194            BG_Cyan = '46'            # ESC [ 36 m      # cyan
4195            BG_White = '47'           # ESC [ 37 m      # white
4196        self.assertTrue(isinstance(Color.FG_Black, Color))
4197        self.assertTrue(isinstance(Color.FG_Black, str))
4198        self.assertEqual(Color.FG_Black, '\x1b[30m')
4199        self.assertEqual(Color.FG_Black.code, '30')
4200
4201    def test_sub_subclass_3(self):
4202        class StrFlag(str, Flag):
4203            def __new__(cls, value, code):
4204                str_value = '\x1b[%sm' % code
4205                obj = str.__new__(cls, str_value)
4206                obj._value_ = value
4207                obj.code = code
4208                return obj
4209            @classmethod
4210            def _create_pseudo_member_(cls, value):
4211                pseudo_member = cls._value2member_map_.get(value, None)
4212                if pseudo_member is None:
4213                    # calculate the code
4214                    members, _ = aenum._decompose(cls, value)
4215                    code = ';'.join(m.code for m in members)
4216                    pseudo_member = super(Color, cls)._create_pseudo_member_(value, code)
4217                return pseudo_member
4218            #
4219        class Color(StrFlag):
4220            _settings_ = AutoValue
4221            _order_ = 'FG_Black FG_Red FG_Green FG_Blue BG_Yellow BG_Magenta BG_Cyan BG_White'
4222                                      # # FOREGROUND - 30s  BACKGROUND - 40s:
4223            FG_Black = '30'           # ESC [ 30 m      # black
4224            FG_Red = '31'             # ESC [ 31 m      # red
4225            FG_Green = '32'           # ESC [ 32 m      # green
4226            FG_Blue = '34'            # ESC [ 34 m      # blue
4227                                      #
4228            BG_Yellow = '43'          # ESC [ 33 m      # yellow
4229            BG_Magenta = '45'         # ESC [ 35 m      # magenta
4230            BG_Cyan = '46'            # ESC [ 36 m      # cyan
4231            BG_White = '47'           # ESC [ 37 m      # white
4232        self.assertTrue(isinstance(Color.FG_Black, Color))
4233        self.assertTrue(isinstance(Color.FG_Black, str))
4234        self.assertEqual(Color.FG_Black, '\x1b[30m')
4235        self.assertEqual(Color.FG_Black.code, '30')
4236
4237    def test_sub_subclass_4(self):
4238        class StrFlag(str, Flag):
4239            def __new__(cls, value, code):
4240                str_value = '\x1b[%sm' % code
4241                obj = str.__new__(cls, str_value)
4242                obj._value_ = value
4243                obj.code = code
4244                return obj
4245            @classmethod
4246            def _create_pseudo_member_values_(cls, members, *values):
4247                code = ';'.join(m.code for m in members)
4248                return values + (code, )
4249            #
4250        class Color(StrFlag):
4251            _settings_ = AutoValue
4252            _order_ = 'FG_Black FG_Red FG_Green FG_Blue BG_Yellow BG_Magenta BG_Cyan BG_White'
4253                                      # # FOREGROUND - 30s  BACKGROUND - 40s:
4254            FG_Black = '30'           # ESC [ 30 m      # black
4255            FG_Red = '31'             # ESC [ 31 m      # red
4256            FG_Green = '32'           # ESC [ 32 m      # green
4257            FG_Blue = '34'            # ESC [ 34 m      # blue
4258                                      #
4259            BG_Yellow = '43'          # ESC [ 33 m      # yellow
4260            BG_Magenta = '45'         # ESC [ 35 m      # magenta
4261            BG_Cyan = '46'            # ESC [ 36 m      # cyan
4262            BG_White = '47'           # ESC [ 37 m      # white
4263            #
4264            def __repr__(self):
4265                if self._name_ is not None:
4266                    return '<%s.%s>' % (self.__class__.__name__, self._name_)
4267                else:
4268                    return '<%s: %s>' % (self.__class__.__name__, '|'.join([m.name for m in Flag.__iter__(self)]))
4269        self.assertTrue(isinstance(Color.FG_Black, Color))
4270        self.assertTrue(isinstance(Color.FG_Black, str))
4271        self.assertEqual(Color.FG_Black, '\x1b[30m')
4272        self.assertEqual(Color.FG_Black.code, '30')
4273        colors = Color.BG_Magenta | Color.FG_Black
4274        self.assertTrue(isinstance(colors, Color))
4275        self.assertTrue(isinstance(colors, str))
4276        self.assertEqual(colors, '\x1b[45;30m')
4277        self.assertEqual(colors.code, '45;30')
4278        self.assertEqual(repr(colors), '<Color: BG_Magenta|FG_Black>')
4279
4280    def test_sub_subclass_with_new_new(self):
4281        class StrFlag(str, Flag):
4282            def __new__(cls, value, code):
4283                str_value = '\x1b[%sm' % code
4284                obj = str.__new__(cls, str_value)
4285                obj._value_ = value
4286                obj.code = code
4287                return obj
4288            @classmethod
4289            def _create_pseudo_member_(cls, value):
4290                pseudo_member = cls._value2member_map_.get(value, None)
4291                if pseudo_member is None:
4292                    # calculate the code
4293                    members, _ = aenum._decompose(cls, value)
4294                    code = ';'.join(m.code for m in members)
4295                    pseudo_member = super(Color, cls)._create_pseudo_member_(value, code)
4296                return pseudo_member
4297            #
4298        class Color(StrFlag):
4299            _settings_ = AutoValue
4300            _order_ = 'FG_Black FG_Red FG_Green FG_Blue BG_Yellow BG_Magenta BG_Cyan BG_White'
4301            def __new__(cls, value, string, abbr):
4302                str_value = abbr.title()
4303                obj = str.__new__(cls, str_value)
4304                obj._value_ = value
4305                obj.code = string
4306                obj.abbr = abbr
4307                return obj
4308                                      # # FOREGROUND - 30s  BACKGROUND - 40s:
4309            FG_Black = '30', 'blk'           # ESC [ 30 m      # black
4310            FG_Red = '31', 'red'             # ESC [ 31 m      # red
4311            FG_Green = '32', 'grn'           # ESC [ 32 m      # green
4312            FG_Blue = '34', 'blu'            # ESC [ 34 m      # blue
4313                                      #
4314            BG_Yellow = '43', 'ylw'          # ESC [ 33 m      # yellow
4315            BG_Magenta = '45', 'mag'         # ESC [ 35 m      # magenta
4316            BG_Cyan = '46', 'cyn'            # ESC [ 36 m      # cyan
4317            BG_White = '47', 'wht'           # ESC [ 37 m      # white
4318            #
4319            def __repr__(self):
4320                if self._name_ is not None:
4321                    return '<%s.%s>' % (self.__class__.__name__, self._name_)
4322                else:
4323                    return '<%s: %s>' % (self.__class__.__name__, '|'.join([m.name for m in self]))
4324        self.assertTrue(isinstance(Color.FG_Black, Color))
4325        self.assertTrue(isinstance(Color.FG_Black, str))
4326        self.assertEqual(Color.FG_Black, 'Blk', str.__repr__(Color.FG_Black))
4327        self.assertEqual(Color.FG_Black.abbr, 'blk')
4328
4329    def test_subclass_with_default_new(self):
4330        class MyFlag(str, Flag):
4331            _settings_ = AutoValue
4332            _order_ = 'this these theother'
4333            this = 'that'
4334            these = 'those'
4335            theother = 'thingimibobs'
4336        self.assertEqual(MyFlag.this, 'that')
4337        self.assertEqual(MyFlag.this.value, 1)
4338        self.assertEqual(MyFlag.these, 'those')
4339        self.assertEqual(MyFlag.these.value, 2)
4340        self.assertEqual(MyFlag.theother, 'thingimibobs')
4341        self.assertEqual(MyFlag.theother.value, 4)
4342
4343    def test_extend_flag(self):
4344        class Color(Flag):
4345            BLACK = 0
4346            RED = 1
4347            GREEN = 2
4348            BLUE = 4
4349        extend_enum(Color, 'MAGENTA')
4350        self.assertTrue(Color(8) is Color.MAGENTA)
4351        self.assertTrue(isinstance(Color.MAGENTA, Color))
4352        self.assertEqual(Color.MAGENTA.value, 8)
4353        extend_enum(Color, 'PURPLE', 11)
4354        self.assertTrue(Color(11) is Color.PURPLE)
4355        self.assertTrue(isinstance(Color.PURPLE, Color))
4356        self.assertEqual(Color.PURPLE.value, 11)
4357        self.assertTrue(issubclass(Color, Flag))
4358
4359    def test_extend_flag_subclass(self):
4360        class Color(str, Flag):
4361            _order_ = 'FG_Black FG_Red FG_Green FG_Blue BG_Yellow BG_Magenta BG_Cyan BG_White'
4362            _settings_ = AutoValue
4363            def __new__(cls, value, code=None):
4364                str_value = '\x1b[%sm' % code
4365                obj = str.__new__(cls, str_value)
4366                obj._value_ = value
4367                obj.code = code
4368                return obj
4369            @staticmethod
4370            def _generate_next_value_(name, start, count, values, *args, **kwds):
4371                return (2 ** count, ) + args
4372            @classmethod
4373            def _create_pseudo_member_(cls, value):
4374                pseudo_member = cls._value2member_map_.get(value, None)
4375                if pseudo_member is None:
4376                    # calculate the code
4377                    members, _ = aenum._decompose(cls, value)
4378                    code = ';'.join(m.code for m in members)
4379                    pseudo_member = super(Color, cls)._create_pseudo_member_(value, code)
4380                return pseudo_member
4381            #
4382                                      # # FOREGROUND - 30s  BACKGROUND - 40s:
4383            FG_Black = '30'           # ESC [ 30 m      # black
4384            FG_Red = '31'             # ESC [ 31 m      # red
4385            FG_Green = '32'           # ESC [ 32 m      # green
4386            FG_Blue = '34'            # ESC [ 34 m      # blue
4387                                      #
4388            BG_Yellow = '43'          # ESC [ 33 m      # yellow
4389            BG_Magenta = '45'         # ESC [ 35 m      # magenta
4390            BG_Cyan = '46'            # ESC [ 36 m      # cyan
4391            BG_White = '47'           # ESC [ 37 m      # white
4392            #
4393            def __repr__(self):
4394                if self._name_ is not None:
4395                    return '<%s.%s>' % (self.__class__.__name__, self._name_)
4396                else:
4397                    return '<%s: %s>' % (self.__class__.__name__, '|'.join([m.name for m in self]))
4398        #
4399        Purple = Color.BG_Magenta | Color.FG_Blue
4400        self.assertTrue(isinstance(Purple, Color))
4401        self.assertTrue(isinstance(Purple, str))
4402        self.assertIs(Purple, Color.BG_Magenta | Color.FG_Blue)
4403        self.assertEqual(Purple, '\x1b[45;34m')
4404        self.assertEqual(Purple.code, '45;34')
4405        self.assertIs(Purple.name, None)
4406
4407
4408class TestIntFlag(TestCase):
4409    """Tests of the IntFlags."""
4410
4411    class Perm(IntFlag):
4412        X = 1 << 0
4413        W = 1 << 1
4414        R = 1 << 2
4415
4416    class Color(IntFlag):
4417        BLACK = 0
4418        RED = 1
4419        GREEN = 2
4420        BLUE = 4
4421        PURPLE = RED|BLUE
4422
4423    class Open(IntFlag):
4424        "not a good flag candidate"
4425        RO = 0
4426        WO = 1
4427        RW = 2
4428        AC = 3
4429        CE = 1<<19
4430
4431    def test_membership(self):
4432        Color = self.Color
4433        Open = self.Open
4434        self.assertRaises(TypeError, lambda: 'GREEN' in Color)
4435        self.assertRaises(TypeError, lambda: 'RW' in Open)
4436        self.assertTrue(Color.GREEN in Color)
4437        self.assertTrue(Open.RW in Open)
4438        self.assertFalse(Color.GREEN in Open)
4439        self.assertFalse(Open.RW in Color)
4440        self.assertRaises(TypeError, lambda: 2 in Color)
4441        self.assertRaises(TypeError, lambda: 2 in Open)
4442
4443    def test_member_contains(self):
4444        Color = self.Color
4445        self.assertRaises(TypeError, lambda: 'test' in Color.RED)
4446        self.assertRaises(TypeError, lambda: 1 in Color.RED)
4447        self.assertTrue(Color.RED in Color.RED)
4448        self.assertTrue(Color.RED in Color.PURPLE)
4449
4450    def test_name_lookup(self):
4451        Color = self.Color
4452        self.assertTrue(Color.RED is Color['RED'])
4453        self.assertTrue(Color.RED|Color.GREEN is Color['RED|GREEN'])
4454        self.assertTrue(Color.PURPLE is Color['RED|BLUE'])
4455
4456    def test_type(self):
4457        Perm = self.Perm
4458        Open = self.Open
4459        for f in Perm:
4460            self.assertTrue(isinstance(f, Perm))
4461            self.assertEqual(f, f.value)
4462        self.assertTrue(isinstance(Perm.W | Perm.X, Perm))
4463        self.assertEqual(Perm.W | Perm.X, 3)
4464        for f in Open:
4465            self.assertTrue(isinstance(f, Open))
4466            self.assertEqual(f, f.value)
4467        self.assertTrue(isinstance(Open.WO | Open.RW, Open))
4468        self.assertEqual(Open.WO | Open.RW, 3)
4469
4470
4471    def test_str(self):
4472        Perm = self.Perm
4473        self.assertEqual(str(Perm.R), 'Perm.R')
4474        self.assertEqual(str(Perm.W), 'Perm.W')
4475        self.assertEqual(str(Perm.X), 'Perm.X')
4476        self.assertEqual(str(Perm.R | Perm.W), 'Perm.R|W')
4477        self.assertEqual(str(Perm.R | Perm.W | Perm.X), 'Perm.R|W|X')
4478        self.assertEqual(str(Perm.R | 8), 'Perm.8|R')
4479        self.assertEqual(str(Perm(0)), 'Perm.0')
4480        self.assertEqual(str(Perm(8)), 'Perm.8')
4481        self.assertEqual(str(~Perm.R), 'Perm.W|X')
4482        self.assertEqual(str(~Perm.W), 'Perm.R|X')
4483        self.assertEqual(str(~Perm.X), 'Perm.R|W')
4484        self.assertEqual(str(~(Perm.R | Perm.W)), 'Perm.X')
4485        self.assertEqual(str(~(Perm.R | Perm.W | Perm.X)), 'Perm.-8')
4486        self.assertEqual(str(~(Perm.R | 8)), 'Perm.W|X')
4487        self.assertEqual(str(Perm(~0)), 'Perm.R|W|X')
4488        self.assertEqual(str(Perm(~8)), 'Perm.R|W|X')
4489
4490        Open = self.Open
4491        self.assertEqual(str(Open.RO), 'Open.RO')
4492        self.assertEqual(str(Open.WO), 'Open.WO')
4493        self.assertEqual(str(Open.AC), 'Open.AC')
4494        self.assertEqual(str(Open.RO | Open.CE), 'Open.CE')
4495        self.assertEqual(str(Open.WO | Open.CE), 'Open.CE|WO')
4496        self.assertEqual(str(Open(4)), 'Open.4')
4497        self.assertEqual(str(~Open.RO), 'Open.CE|AC|RW|WO')
4498        self.assertEqual(str(~Open.WO), 'Open.CE|RW')
4499        self.assertEqual(str(~Open.AC), 'Open.CE')
4500        self.assertEqual(str(~(Open.RO | Open.CE)), 'Open.AC|RW|WO')
4501        self.assertEqual(str(~(Open.WO | Open.CE)), 'Open.RW')
4502        self.assertEqual(str(Open(~4)), 'Open.CE|AC|RW|WO')
4503
4504    def test_repr(self):
4505        Perm = self.Perm
4506        self.assertEqual(repr(Perm.R), '<Perm.R: 4>')
4507        self.assertEqual(repr(Perm.W), '<Perm.W: 2>')
4508        self.assertEqual(repr(Perm.X), '<Perm.X: 1>')
4509        self.assertEqual(repr(Perm.R | Perm.W), '<Perm.R|W: 6>')
4510        self.assertEqual(repr(Perm.R | Perm.W | Perm.X), '<Perm.R|W|X: 7>')
4511        self.assertEqual(repr(Perm.R | 8), '<Perm.8|R: 12>')
4512        self.assertEqual(repr(Perm(0)), '<Perm.0: 0>')
4513        self.assertEqual(repr(Perm(8)), '<Perm.8: 8>')
4514        self.assertEqual(repr(~Perm.R), '<Perm.W|X: -5>')
4515        self.assertEqual(repr(~Perm.W), '<Perm.R|X: -3>')
4516        self.assertEqual(repr(~Perm.X), '<Perm.R|W: -2>')
4517        self.assertEqual(repr(~(Perm.R | Perm.W)), '<Perm.X: -7>')
4518        self.assertEqual(repr(~(Perm.R | Perm.W | Perm.X)), '<Perm.-8: -8>')
4519        self.assertEqual(repr(~(Perm.R | 8)), '<Perm.W|X: -13>')
4520        self.assertEqual(repr(Perm(~0)), '<Perm.R|W|X: -1>')
4521        self.assertEqual(repr(Perm(~8)), '<Perm.R|W|X: -9>')
4522
4523        Open = self.Open
4524        self.assertEqual(repr(Open.RO), '<Open.RO: 0>')
4525        self.assertEqual(repr(Open.WO), '<Open.WO: 1>')
4526        self.assertEqual(repr(Open.AC), '<Open.AC: 3>')
4527        self.assertEqual(repr(Open.RO | Open.CE), '<Open.CE: 524288>')
4528        self.assertEqual(repr(Open.WO | Open.CE), '<Open.CE|WO: 524289>')
4529        self.assertEqual(repr(Open(4)), '<Open.4: 4>')
4530        self.assertEqual(repr(~Open.RO), '<Open.CE|AC|RW|WO: -1>')
4531        self.assertEqual(repr(~Open.WO), '<Open.CE|RW: -2>')
4532        self.assertEqual(repr(~Open.AC), '<Open.CE: -4>')
4533        self.assertEqual(repr(~(Open.RO | Open.CE)), '<Open.AC|RW|WO: -524289>')
4534        self.assertEqual(repr(~(Open.WO | Open.CE)), '<Open.RW: -524290>')
4535        self.assertEqual(repr(Open(~4)), '<Open.CE|AC|RW|WO: -5>')
4536
4537    def test_or(self):
4538        Perm = self.Perm
4539        for i in Perm:
4540            for j in Perm:
4541                self.assertEqual(i | j, i.value | j.value)
4542                self.assertEqual((i | j).value, i.value | j.value)
4543                self.assertIs(type(i | j), Perm)
4544            for j in range(8):
4545                self.assertEqual(i | j, i.value | j)
4546                self.assertEqual((i | j).value, i.value | j)
4547                self.assertIs(type(i | j), Perm)
4548                self.assertEqual(j | i, j | i.value)
4549                self.assertEqual((j | i).value, j | i.value)
4550                self.assertIs(type(j | i), Perm)
4551        for i in Perm:
4552            self.assertIs(i | i, i)
4553            self.assertIs(i | 0, i)
4554            self.assertIs(0 | i, i)
4555        Open = self.Open
4556        self.assertIs(Open.RO | Open.CE, Open.CE)
4557
4558    def test_and(self):
4559        Perm = self.Perm
4560        RW = Perm.R | Perm.W
4561        RX = Perm.R | Perm.X
4562        WX = Perm.W | Perm.X
4563        RWX = Perm.R | Perm.W | Perm.X
4564        values = list(Perm) + [RW, RX, WX, RWX, Perm(0)]
4565        for i in values:
4566            for j in values:
4567                self.assertEqual(i & j, i.value & j.value, 'i is %r, j is %r' % (i, j))
4568                self.assertEqual((i & j).value, i.value & j.value, 'i is %r, j is %r' % (i, j))
4569                self.assertIs(type(i & j), Perm, 'i is %r, j is %r' % (i, j))
4570            for j in range(8):
4571                self.assertEqual(i & j, i.value & j)
4572                self.assertEqual((i & j).value, i.value & j)
4573                self.assertIs(type(i & j), Perm)
4574                self.assertEqual(j & i, j & i.value)
4575                self.assertEqual((j & i).value, j & i.value)
4576                self.assertIs(type(j & i), Perm)
4577        for i in Perm:
4578            self.assertIs(i & i, i)
4579            self.assertIs(i & 7, i)
4580            self.assertIs(7 & i, i)
4581        Open = self.Open
4582        self.assertIs(Open.RO & Open.CE, Open.RO)
4583
4584    def test_xor(self):
4585        Perm = self.Perm
4586        for i in Perm:
4587            for j in Perm:
4588                self.assertEqual(i ^ j, i.value ^ j.value)
4589                self.assertEqual((i ^ j).value, i.value ^ j.value)
4590                self.assertIs(type(i ^ j), Perm)
4591            for j in range(8):
4592                self.assertEqual(i ^ j, i.value ^ j)
4593                self.assertEqual((i ^ j).value, i.value ^ j)
4594                self.assertIs(type(i ^ j), Perm)
4595                self.assertEqual(j ^ i, j ^ i.value)
4596                self.assertEqual((j ^ i).value, j ^ i.value)
4597                self.assertIs(type(j ^ i), Perm)
4598        for i in Perm:
4599            self.assertIs(i ^ 0, i)
4600            self.assertIs(0 ^ i, i)
4601        Open = self.Open
4602        self.assertIs(Open.RO ^ Open.CE, Open.CE)
4603        self.assertIs(Open.CE ^ Open.CE, Open.RO)
4604
4605    def test_invert(self):
4606        Perm = self.Perm
4607        RW = Perm.R | Perm.W
4608        RX = Perm.R | Perm.X
4609        WX = Perm.W | Perm.X
4610        RWX = Perm.R | Perm.W | Perm.X
4611        values = list(Perm) + [RW, RX, WX, RWX, Perm(0)]
4612        for i in values:
4613            self.assertEqual(~i, ~i.value)
4614            self.assertEqual((~i).value, ~i.value)
4615            self.assertIs(type(~i), Perm)
4616            self.assertEqual(~~i, i)
4617        for i in Perm:
4618            self.assertIs(~~i, i)
4619        Open = self.Open
4620        self.assertIs(Open.WO & ~Open.WO, Open.RO)
4621        self.assertIs((Open.WO|Open.CE) & ~Open.WO, Open.CE)
4622
4623    def test_iter(self):
4624        Perm = self.Perm
4625        NoPerm = Perm.R ^ Perm.R
4626        RWX = Perm.R | Perm.W | Perm.X
4627        self.assertEqual(list(NoPerm), [])
4628        self.assertEqual(list(Perm.R), [Perm.R])
4629        self.assertEqual(list(RWX), [Perm.R, Perm.W, Perm.X])
4630
4631    def test_programatic_function_string(self):
4632        Perm = IntFlag('Perm', 'R W X')
4633        lst = list(Perm)
4634        self.assertEqual(len(lst), len(Perm))
4635        self.assertEqual(len(Perm), 3, Perm)
4636        self.assertEqual(lst, [Perm.R, Perm.W, Perm.X])
4637        for i, n in enumerate('R W X'.split()):
4638            v = 1<<i
4639            e = Perm(v)
4640            self.assertEqual(e.value, v)
4641            self.assertEqual(type(e.value), int)
4642            self.assertEqual(e, v)
4643            self.assertEqual(e.name, n)
4644            self.assertIn(e, Perm)
4645            self.assertIs(type(e), Perm)
4646
4647    def test_programatic_function_string_with_start(self):
4648        Perm = IntFlag('Perm', 'R W X', start=8)
4649        lst = list(Perm)
4650        self.assertEqual(len(lst), len(Perm))
4651        self.assertEqual(len(Perm), 3, Perm)
4652        self.assertEqual(lst, [Perm.R, Perm.W, Perm.X])
4653        for i, n in enumerate('R W X'.split()):
4654            v = 8<<i
4655            e = Perm(v)
4656            self.assertEqual(e.value, v)
4657            self.assertEqual(type(e.value), int)
4658            self.assertEqual(e, v)
4659            self.assertEqual(e.name, n)
4660            self.assertIn(e, Perm)
4661            self.assertIs(type(e), Perm)
4662
4663    def test_programatic_function_string_list(self):
4664        Perm = IntFlag('Perm', ['R', 'W', 'X'])
4665        lst = list(Perm)
4666        self.assertEqual(len(lst), len(Perm))
4667        self.assertEqual(len(Perm), 3, Perm)
4668        self.assertEqual(lst, [Perm.R, Perm.W, Perm.X])
4669        for i, n in enumerate('R W X'.split()):
4670            v = 1<<i
4671            e = Perm(v)
4672            self.assertEqual(e.value, v)
4673            self.assertEqual(type(e.value), int)
4674            self.assertEqual(e, v)
4675            self.assertEqual(e.name, n)
4676            self.assertIn(e, Perm)
4677            self.assertIs(type(e), Perm)
4678
4679    def test_programatic_function_iterable(self):
4680        Perm = IntFlag('Perm', (('R', 2), ('W', 8), ('X', 32)))
4681        lst = list(Perm)
4682        self.assertEqual(len(lst), len(Perm))
4683        self.assertEqual(len(Perm), 3, Perm)
4684        self.assertEqual(lst, [Perm.R, Perm.W, Perm.X])
4685        for i, n in enumerate('R W X'.split()):
4686            v = 1<<(2*i+1)
4687            e = Perm(v)
4688            self.assertEqual(e.value, v)
4689            self.assertEqual(type(e.value), int)
4690            self.assertEqual(e, v)
4691            self.assertEqual(e.name, n)
4692            self.assertIn(e, Perm)
4693            self.assertIs(type(e), Perm)
4694
4695    def test_programatic_function_from_dict(self):
4696        Perm = IntFlag('Perm', OrderedDict((('R', 2), ('W', 8), ('X', 32))))
4697        lst = list(Perm)
4698        self.assertEqual(len(lst), len(Perm))
4699        self.assertEqual(len(Perm), 3, Perm)
4700        self.assertEqual(lst, [Perm.R, Perm.W, Perm.X])
4701        for i, n in enumerate('R W X'.split()):
4702            v = 1<<(2*i+1)
4703            e = Perm(v)
4704            self.assertEqual(e.value, v)
4705            self.assertEqual(type(e.value), int)
4706            self.assertEqual(e, v)
4707            self.assertEqual(e.name, n)
4708            self.assertIn(e, Perm)
4709            self.assertIs(type(e), Perm)
4710
4711    def test_containment(self):
4712        Perm = self.Perm
4713        R, W, X = Perm
4714        RW = R | W
4715        RX = R | X
4716        WX = W | X
4717        RWX = R | W | X
4718        self.assertTrue(R in RW)
4719        self.assertTrue(R in RX)
4720        self.assertTrue(R in RWX)
4721        self.assertTrue(W in RW)
4722        self.assertTrue(W in WX)
4723        self.assertTrue(W in RWX)
4724        self.assertTrue(X in RX)
4725        self.assertTrue(X in WX)
4726        self.assertTrue(X in RWX)
4727        self.assertFalse(R in WX)
4728        self.assertFalse(W in RX)
4729        self.assertFalse(X in RW)
4730
4731    def test_bool(self):
4732        Perm = self.Perm
4733        for f in Perm:
4734            self.assertTrue(f)
4735        Open = self.Open
4736        for f in Open:
4737            self.assertEqual(bool(f.value), bool(f))
4738
4739    def test_multiple_mixin(self):
4740        class AllMixin(object):
4741            @classproperty
4742            def ALL(cls):
4743                members = list(cls)
4744                all_value = None
4745                if members:
4746                    all_value = members[0]
4747                    for member in members[1:]:
4748                        all_value |= member
4749                cls.ALL = all_value
4750                return all_value
4751        class StrMixin(object):
4752            def __str__(self):
4753                return self._name_.lower()
4754        class Color(AllMixin, IntFlag):
4755            _order_ = 'RED GREEN BLUE'
4756            RED = auto()
4757            GREEN = auto()
4758            BLUE = auto()
4759        self.assertEqual(Color.RED.value, 1)
4760        self.assertEqual(Color.GREEN.value, 2)
4761        self.assertEqual(Color.BLUE.value, 4)
4762        self.assertEqual(Color.ALL.value, 7)
4763        self.assertEqual(str(Color.BLUE), 'Color.BLUE')
4764        class Color(AllMixin, StrMixin, IntFlag):
4765            _order_ = 'RED GREEN BLUE'
4766            RED = auto()
4767            GREEN = auto()
4768            BLUE = auto()
4769        self.assertEqual(Color.RED.value, 1)
4770        self.assertEqual(Color.GREEN.value, 2)
4771        self.assertEqual(Color.BLUE.value, 4)
4772        self.assertEqual(Color.ALL.value, 7)
4773        self.assertEqual(str(Color.BLUE), 'blue')
4774        class Color(StrMixin, AllMixin, IntFlag):
4775            _order_ = 'RED GREEN BLUE'
4776            RED = auto()
4777            GREEN = auto()
4778            BLUE = auto()
4779        self.assertEqual(Color.RED.value, 1)
4780        self.assertEqual(Color.GREEN.value, 2)
4781        self.assertEqual(Color.BLUE.value, 4)
4782        self.assertEqual(Color.ALL.value, 7)
4783        self.assertEqual(str(Color.BLUE), 'blue')
4784
4785    @unittest.skipUnless(threading, 'Threading required for this test.')
4786    def test_unique_composite(self):
4787        # override __eq__ to be identity only
4788        class TestFlag(IntFlag):
4789            _order_ = 'one two three four five six seven eight'
4790            one = auto()
4791            two = auto()
4792            three = auto()
4793            four = auto()
4794            five = auto()
4795            six = auto()
4796            seven = auto()
4797            eight = auto()
4798            def __eq__(self, other):
4799                return self is other
4800            def __hash__(self):
4801                return hash(self._value_)
4802        # have multiple threads competing to complete the composite members
4803        seen = set()
4804        failed = [False]
4805        def cycle_enum():
4806            # nonlocal failed
4807            try:
4808                for i in range(256):
4809                    seen.add(TestFlag(i))
4810            except Exception:
4811                failed[0] = True
4812        threads = [
4813                threading.Thread(target=cycle_enum)
4814                for _ in range(8)
4815                ]
4816        for t in threads:
4817            t.start()
4818        for t in threads:
4819            t.join()
4820        # check that only 248 members were created (8 were created originally)
4821        self.assertFalse(
4822                failed[0],
4823                'at least one thread failed while creating composite members')
4824        self.assertEqual(256, len(seen), 'too many composite members created')
4825
4826
4827class TestEmptyAndNonLatinStrings(unittest.TestCase):
4828
4829    def test_empty_string(self):
4830        with self.assertRaises(ValueError):
4831            empty_abc = Enum('empty_abc', ('', 'B', 'C'))
4832
4833    def test_non_latin_character_string(self):
4834        greek_abc = Enum('greek_abc', ('\u03B1', 'B', 'C'))
4835        item = getattr(greek_abc, '\u03B1')
4836        self.assertEqual(item.value, 1)
4837
4838    def test_non_latin_number_string(self):
4839        hebrew_123 = Enum('hebrew_123', ('\u05D0', '2', '3'))
4840        item = getattr(hebrew_123, '\u05D0')
4841        self.assertEqual(item.value, 1)
4842
4843
4844class TestUnique(TestCase):
4845    """2.4 doesn't allow class decorators, use function syntax."""
4846
4847    def test_unique_clean(self):
4848        class Clean(Enum):
4849            one = 1
4850            two = 'dos'
4851            tres = 4.0
4852        unique(Clean)
4853        class Cleaner(IntEnum):
4854            single = 1
4855            double = 2
4856            triple = 3
4857        unique(Cleaner)
4858
4859    def test_unique_dirty(self):
4860        try:
4861            class Dirty(Enum):
4862                __order__ = 'one two'
4863                one = 1
4864                two = 'dos'
4865                tres = 1
4866            unique(Dirty)
4867        except ValueError:
4868            exc = sys.exc_info()[1]
4869            message = exc.args[0]
4870        self.assertTrue('tres -> one' in message)
4871
4872        try:
4873            class Dirtier(IntEnum):
4874                __order__ = 'single triple'
4875                single = 1
4876                double = 1
4877                triple = 3
4878                turkey = 3
4879            unique(Dirtier)
4880        except ValueError:
4881            exc = sys.exc_info()[1]
4882            message = exc.args[0]
4883        self.assertTrue('double -> single' in message)
4884        self.assertTrue('turkey -> triple' in message)
4885
4886    def test_unique_with_name(self):
4887        @unique
4888        class Silly(Enum):
4889            one = 1
4890            two = 'dos'
4891            name = 3
4892        @unique
4893        class Sillier(IntEnum):
4894            single = 1
4895            name = 2
4896            triple = 3
4897            value = 4
4898
4899
4900class TestNamedTuple(TestCase):
4901
4902    def test_explicit_indexing(self):
4903        class Person(NamedTuple):
4904            age = 0
4905            first = 1
4906            last = 2
4907        p1 = Person(17, 'John', 'Doe')
4908        p2 = Person(21, 'Jane', 'Doe')
4909        self.assertEqual(p1[0], 17)
4910        self.assertEqual(p1[1], 'John')
4911        self.assertEqual(p1[2], 'Doe')
4912        self.assertEqual(p2[0], 21)
4913        self.assertEqual(p2[1], 'Jane')
4914        self.assertEqual(p2[2], 'Doe')
4915        self.assertEqual(p1.age, 17)
4916        self.assertEqual(p1.first, 'John')
4917        self.assertEqual(p1.last, 'Doe')
4918        self.assertEqual(p2.age, 21)
4919        self.assertEqual(p2.first, 'Jane')
4920        self.assertEqual(p2.last, 'Doe')
4921
4922    def test_implicit_indexing(self):
4923        class Person(NamedTuple):
4924            __order__ = "age first last"
4925            age = "person's age"
4926            first = "person's first name"
4927            last = "person's last name"
4928        p1 = Person(17, 'John', 'Doe')
4929        p2 = Person(21, 'Jane', 'Doe')
4930        self.assertEqual(p1[0], 17)
4931        self.assertEqual(p1[1], 'John')
4932        self.assertEqual(p1[2], 'Doe')
4933        self.assertEqual(p2[0], 21)
4934        self.assertEqual(p2[1], 'Jane')
4935        self.assertEqual(p2[2], 'Doe')
4936        self.assertEqual(p1.age, 17)
4937        self.assertEqual(p1.first, 'John')
4938        self.assertEqual(p1.last, 'Doe')
4939        self.assertEqual(p2.age, 21)
4940        self.assertEqual(p2.first, 'Jane')
4941        self.assertEqual(p2.last, 'Doe')
4942
4943    def test_mixed_indexing(self):
4944        class Person(NamedTuple):
4945            __order__ = "age last cars"
4946            age = "person's age"
4947            last = 2, "person's last name"
4948            cars = "person's cars"
4949        p1 = Person(17, 'John', 'Doe', 3)
4950        p2 = Person(21, 'Jane', 'Doe', 9)
4951        self.assertEqual(p1[0], 17)
4952        self.assertEqual(p1[1], 'John')
4953        self.assertEqual(p1[2], 'Doe')
4954        self.assertEqual(p1[3], 3)
4955        self.assertEqual(p2[0], 21)
4956        self.assertEqual(p2[1], 'Jane')
4957        self.assertEqual(p2[2], 'Doe')
4958        self.assertEqual(p2[3], 9)
4959        self.assertEqual(p1.age, 17)
4960        self.assertEqual(p1.last, 'Doe')
4961        self.assertEqual(p1.cars, 3)
4962        self.assertEqual(p2.age, 21)
4963        self.assertEqual(p2.last, 'Doe')
4964        self.assertEqual(p2.cars, 9)
4965
4966    def test_issubclass(self):
4967        class Person(NamedTuple):
4968            age = 0
4969            first = 1
4970            last = 2
4971        self.assertTrue(issubclass(Person, NamedTuple))
4972        self.assertTrue(issubclass(Person, tuple))
4973
4974    def test_isinstance(self):
4975        class Person(NamedTuple):
4976            age = 0
4977            first = 1
4978            last = 2
4979        p1 = Person(17, 'John', 'Doe')
4980        self.assertTrue(isinstance(p1, Person))
4981        self.assertTrue(isinstance(p1, NamedTuple))
4982        self.assertTrue(isinstance(p1, tuple))
4983
4984    def test_explicit_indexing_after_functional_api(self):
4985        Person = NamedTuple('Person', (('age', 0), ('first', 1), ('last', 2)))
4986        p1 = Person(17, 'John', 'Doe')
4987        p2 = Person(21, 'Jane', 'Doe')
4988        self.assertEqual(p1[0], 17)
4989        self.assertEqual(p1[1], 'John')
4990        self.assertEqual(p1[2], 'Doe')
4991        self.assertEqual(p2[0], 21)
4992        self.assertEqual(p2[1], 'Jane')
4993        self.assertEqual(p2[2], 'Doe')
4994        self.assertEqual(p1.age, 17)
4995        self.assertEqual(p1.first, 'John')
4996        self.assertEqual(p1.last, 'Doe')
4997        self.assertEqual(p2.age, 21)
4998        self.assertEqual(p2.first, 'Jane')
4999        self.assertEqual(p2.last, 'Doe')
5000
5001    def test_implicit_indexing_after_functional_api(self):
5002        Person = NamedTuple('Person', 'age first last')
5003        p1 = Person(17, 'John', 'Doe')
5004        p2 = Person(21, 'Jane', 'Doe')
5005        self.assertEqual(p1[0], 17)
5006        self.assertEqual(p1[1], 'John')
5007        self.assertEqual(p1[2], 'Doe')
5008        self.assertEqual(p2[0], 21)
5009        self.assertEqual(p2[1], 'Jane')
5010        self.assertEqual(p2[2], 'Doe')
5011        self.assertEqual(p1.age, 17)
5012        self.assertEqual(p1.first, 'John')
5013        self.assertEqual(p1.last, 'Doe')
5014        self.assertEqual(p2.age, 21)
5015        self.assertEqual(p2.first, 'Jane')
5016        self.assertEqual(p2.last, 'Doe')
5017
5018    def test_mixed_indexing_after_functional_api(self):
5019        Person = NamedTuple('Person', (('age', 0), ('last', 2), ('cars', 3)))
5020        p1 = Person(17, 'John', 'Doe', 3)
5021        p2 = Person(21, 'Jane', 'Doe', 9)
5022        self.assertEqual(p1[0], 17)
5023        self.assertEqual(p1[1], 'John')
5024        self.assertEqual(p1[2], 'Doe')
5025        self.assertEqual(p1[3], 3)
5026        self.assertEqual(p2[0], 21)
5027        self.assertEqual(p2[1], 'Jane')
5028        self.assertEqual(p2[2], 'Doe')
5029        self.assertEqual(p2[3], 9)
5030        self.assertEqual(p1.age, 17)
5031        self.assertEqual(p1.last, 'Doe')
5032        self.assertEqual(p1.cars, 3)
5033        self.assertEqual(p2.age, 21)
5034        self.assertEqual(p2.last, 'Doe')
5035        self.assertEqual(p2.cars, 9)
5036
5037    def test_issubclass_after_functional_api(self):
5038        Person = NamedTuple('Person', 'age first last')
5039        self.assertTrue(issubclass(Person, NamedTuple))
5040        self.assertTrue(issubclass(Person, tuple))
5041
5042    def test_isinstance_after_functional_api(self):
5043        Person = NamedTuple('Person', 'age first last')
5044        p1 = Person(17, 'John', 'Doe')
5045        self.assertTrue(isinstance(p1, Person))
5046        self.assertTrue(isinstance(p1, NamedTuple))
5047        self.assertTrue(isinstance(p1, tuple))
5048
5049    def test_creation_with_all_keywords(self):
5050        Person = NamedTuple('Person', 'age first last')
5051        p1 = Person(age=17, first='John', last='Doe')
5052        self.assertEqual(p1[0], 17)
5053        self.assertEqual(p1[1], 'John')
5054        self.assertEqual(p1[2], 'Doe')
5055        self.assertEqual(p1.age, 17)
5056        self.assertEqual(p1.first, 'John')
5057        self.assertEqual(p1.last, 'Doe')
5058
5059    def test_creation_with_some_keywords(self):
5060        Person = NamedTuple('Person', 'age first last')
5061        p1 = Person(17, first='John', last='Doe')
5062        self.assertEqual(p1[0], 17)
5063        self.assertEqual(p1[1], 'John')
5064        self.assertEqual(p1[2], 'Doe')
5065        self.assertEqual(p1.age, 17)
5066        self.assertEqual(p1.first, 'John')
5067        self.assertEqual(p1.last, 'Doe')
5068        p1 = Person(17, last='Doe', first='John')
5069        self.assertEqual(p1[0], 17)
5070        self.assertEqual(p1[1], 'John')
5071        self.assertEqual(p1[2], 'Doe')
5072        self.assertEqual(p1.age, 17)
5073        self.assertEqual(p1.first, 'John')
5074        self.assertEqual(p1.last, 'Doe')
5075
5076    def test_custom_new(self):
5077        class Book(NamedTuple):
5078            title = 0
5079            author = 1
5080            genre = 2
5081            def __new__(cls, string):
5082                args = [s.strip() for s in string.split(';')]
5083                return super(Book, cls).__new__(cls, *tuple(args))
5084        b1 = Book('The Last Mohican; John Doe; Historical')
5085        self.assertEqual(b1.title, 'The Last Mohican')
5086        self.assertEqual(b1.author, 'John Doe')
5087        self.assertEqual(b1.genre, 'Historical')
5088
5089    def test_defaults_in_class(self):
5090        class Character(NamedTuple):
5091            name = 0
5092            gender = 1, None, 'male'
5093            klass = 2, None, 'fighter'
5094        for char in (
5095                {'name':'John Doe'},
5096                {'name':'William Pickney', 'klass':'scholar'},
5097                {'name':'Sarah Doughtery', 'gender':'female'},
5098                {'name':'Sissy Moonbeam', 'gender':'female', 'klass':'sorceress'},
5099                ):
5100            c = Character(**char)
5101            for name, value in (('name', None), ('gender','male'), ('klass','fighter')):
5102                if name in char:
5103                    value = char[name]
5104                self.assertEqual(getattr(c, name), value)
5105
5106    def test_defaults_in_class_that_are_falsey(self):
5107        class Point(NamedTuple):
5108            x = 0, 'horizondal coordinate', 0
5109            y = 1, 'vertical coordinate', 0
5110        p = Point()
5111        self.assertEqual(p.x, 0)
5112        self.assertEqual(p.y, 0)
5113
5114    def test_pickle_namedtuple_with_module(self):
5115        if isinstance(LifeForm, Exception):
5116            raise LifeForm
5117        lf = LifeForm('this', 'that', 'theother')
5118        test_pickle_dump_load(self.assertEqual, lf)
5119
5120    def test_pickle_namedtuple_without_module(self):
5121        if isinstance(DeathForm, Exception):
5122            raise DeathForm
5123        df = DeathForm('sickly green', '2x4', 'foul')
5124        test_pickle_dump_load(self.assertEqual, df)
5125
5126    def test_subclassing(self):
5127        if isinstance(ThatsIt, Exception):
5128            raise ThatsIt
5129        ti = ThatsIt('Henry', 'Weinhardt')
5130        self.assertEqual(ti.blah, 'Henry')
5131        self.assertTrue(ti.what(), 'Henry')
5132        test_pickle_dump_load(self.assertEqual, ti)
5133
5134    def test_contains(self):
5135        Book = NamedTuple('Book', 'title author genre')
5136        b = Book('Teckla', 'Steven Brust', 'fantasy')
5137        self.assertTrue('Teckla' in b)
5138        self.assertTrue('Steven Brust' in b)
5139        self.assertTrue('fantasy' in b)
5140
5141    def test_fixed_size(self):
5142        class Book(NamedTuple):
5143            _size_ = TupleSize.fixed
5144            title = 0
5145            author = 1
5146            genre = 2
5147        b = Book('Teckla', 'Steven Brust', 'fantasy')
5148        self.assertTrue('Teckla' in b)
5149        self.assertTrue('Steven Brust' in b)
5150        self.assertTrue('fantasy' in b)
5151        self.assertEqual(b.title, 'Teckla')
5152        self.assertEqual(b.author, 'Steven Brust')
5153        self.assertRaises(TypeError, Book, 'Teckla', 'Steven Brust')
5154        self.assertRaises(TypeError, Book, 'Teckla')
5155
5156    def test_minimum_size(self):
5157        class Book(NamedTuple):
5158            _size_ = TupleSize.minimum
5159            title = 0
5160            author = 1
5161        b = Book('Teckla', 'Steven Brust', 'fantasy')
5162        self.assertTrue('Teckla' in b)
5163        self.assertTrue('Steven Brust' in b)
5164        self.assertTrue('fantasy' in b)
5165        self.assertEqual(b.title, 'Teckla')
5166        self.assertEqual(b.author, 'Steven Brust')
5167        b = Book('Teckla', 'Steven Brust')
5168        self.assertTrue('Teckla' in b)
5169        self.assertTrue('Steven Brust' in b)
5170        self.assertEqual(b.title, 'Teckla')
5171        self.assertEqual(b.author, 'Steven Brust')
5172        self.assertRaises(TypeError, Book, 'Teckla')
5173
5174    def test_variable_size(self):
5175        class Book(NamedTuple):
5176            _size_ = TupleSize.variable
5177            title = 0
5178            author = 1
5179            genre = 2
5180        b = Book('Teckla', 'Steven Brust', 'fantasy')
5181        self.assertTrue('Teckla' in b)
5182        self.assertTrue('Steven Brust' in b)
5183        self.assertTrue('fantasy' in b)
5184        self.assertEqual(b.title, 'Teckla')
5185        self.assertEqual(b.author, 'Steven Brust')
5186        self.assertEqual(b.genre, 'fantasy')
5187        b = Book('Teckla', 'Steven Brust')
5188        self.assertTrue('Teckla' in b)
5189        self.assertTrue('Steven Brust' in b)
5190        self.assertEqual(b.title, 'Teckla')
5191        self.assertEqual(b.author, 'Steven Brust')
5192        self.assertRaises(AttributeError, getattr, b, 'genre')
5193        self.assertRaises(TypeError, Book, title='Teckla', genre='fantasy')
5194        self.assertRaises(TypeError, Book, author='Steven Brust')
5195
5196    def test_combining_namedtuples(self):
5197        class Point(NamedTuple):
5198            x = 0, 'horizontal coordinate', 1
5199            y = 1, 'vertical coordinate', -1
5200        class Color(NamedTuple):
5201            r = 0, 'red component', 11
5202            g = 1, 'green component', 29
5203            b = 2, 'blue component', 37
5204        Pixel1 = NamedTuple('Pixel', Point+Color, module=__name__)
5205        class Pixel2(Point, Color):
5206            "a colored dot"
5207        class Pixel3(Point):
5208            r = 2, 'red component', 11
5209            g = 3, 'green component', 29
5210            b = 4, 'blue component', 37
5211        self.assertEqual(Pixel1._fields_, 'x y r g b'.split())
5212        self.assertEqual(Pixel1.x.__doc__, 'horizontal coordinate')
5213        self.assertEqual(Pixel1.x.default, 1)
5214        self.assertEqual(Pixel1.y.__doc__, 'vertical coordinate')
5215        self.assertEqual(Pixel1.y.default, -1)
5216        self.assertEqual(Pixel1.r.__doc__, 'red component')
5217        self.assertEqual(Pixel1.r.default, 11)
5218        self.assertEqual(Pixel1.g.__doc__, 'green component')
5219        self.assertEqual(Pixel1.g.default, 29)
5220        self.assertEqual(Pixel1.b.__doc__, 'blue component')
5221        self.assertEqual(Pixel1.b.default, 37)
5222        self.assertEqual(Pixel2._fields_, 'x y r g b'.split())
5223        self.assertEqual(Pixel2.x.__doc__, 'horizontal coordinate')
5224        self.assertEqual(Pixel2.x.default, 1)
5225        self.assertEqual(Pixel2.y.__doc__, 'vertical coordinate')
5226        self.assertEqual(Pixel2.y.default, -1)
5227        self.assertEqual(Pixel2.r.__doc__, 'red component')
5228        self.assertEqual(Pixel2.r.default, 11)
5229        self.assertEqual(Pixel2.g.__doc__, 'green component')
5230        self.assertEqual(Pixel2.g.default, 29)
5231        self.assertEqual(Pixel2.b.__doc__, 'blue component')
5232        self.assertEqual(Pixel2.b.default, 37)
5233        self.assertEqual(Pixel3._fields_, 'x y r g b'.split())
5234        self.assertEqual(Pixel3.x.__doc__, 'horizontal coordinate')
5235        self.assertEqual(Pixel3.x.default, 1)
5236        self.assertEqual(Pixel3.y.__doc__, 'vertical coordinate')
5237        self.assertEqual(Pixel3.y.default, -1)
5238        self.assertEqual(Pixel3.r.__doc__, 'red component')
5239        self.assertEqual(Pixel3.r.default, 11)
5240        self.assertEqual(Pixel3.g.__doc__, 'green component')
5241        self.assertEqual(Pixel3.g.default, 29)
5242        self.assertEqual(Pixel3.b.__doc__, 'blue component')
5243        self.assertEqual(Pixel3.b.default, 37)
5244
5245    def test_function_api_type(self):
5246        class Tester(NamedTuple):
5247            def howdy(self):
5248                return 'backwards', list(reversed(self))
5249        Testee = NamedTuple('Testee', 'a c e', type=Tester)
5250        t = Testee(1, 2, 3)
5251        self.assertEqual(t.howdy(), ('backwards', [3, 2, 1]))
5252
5253    def test_asdict(self):
5254        class Point(NamedTuple):
5255            x = 0, 'horizontal coordinate', 1
5256            y = 1, 'vertical coordinate', -1
5257        class Color(NamedTuple):
5258            r = 0, 'red component', 11
5259            g = 1, 'green component', 29
5260            b = 2, 'blue component', 37
5261        Pixel = NamedTuple('Pixel', Point+Color, module=__name__)
5262        pixel = Pixel(99, -101, 255, 128, 0)
5263        self.assertEqual(pixel._asdict(), {'x':99, 'y':-101, 'r':255, 'g':128, 'b':0})
5264
5265    def test_make(self):
5266        class Point(NamedTuple):
5267            x = 0, 'horizontal coordinate', 1
5268            y = 1, 'vertical coordinate', -1
5269        self.assertEqual(Point(4, 5), (4, 5))
5270        self.assertEqual(Point._make((4, 5)), (4, 5))
5271
5272    def test_replace(self):
5273        class Color(NamedTuple):
5274            r = 0, 'red component', 11
5275            g = 1, 'green component', 29
5276            b = 2, 'blue component', 37
5277        purple = Color(127, 0, 127)
5278        mid_gray = purple._replace(g=127)
5279        self.assertEqual(mid_gray, (127, 127, 127))
5280
5281
5282class TestNamedConstant(TestCase):
5283
5284    def test_constantness(self):
5285        class K(NamedConstant):
5286            PI = 3.141596
5287            TAU = 2 * PI
5288        self.assertEqual(K.PI, 3.141596)
5289        self.assertEqual(K.TAU, 2 * K.PI)
5290        with self.assertRaisesRegex(AttributeError, 'cannot rebind constant'):
5291            K.PI = 9
5292        with self.assertRaisesRegex(AttributeError, 'cannot delete constant'):
5293            del K.PI
5294        with self.assertRaisesRegex(AttributeError, 'cannot rebind constant'):
5295            K('PI', 3)
5296
5297    def test_duplicates(self):
5298        class CardNumber(NamedConstant):
5299            ACE      = 11
5300            TWO      = 2
5301            THREE    = 3
5302            FOUR     = 4
5303            FIVE     = 5
5304            SIX      = 6
5305            SEVEN    = 7
5306            EIGHT    = 8
5307            NINE     = 9
5308            TEN      = 10
5309            JACK     = 10
5310            QUEEN    = 10
5311            KING     = 10
5312        self.assertFalse(CardNumber.TEN is CardNumber.JACK)
5313        self.assertEqual(CardNumber.TEN, CardNumber.JACK)
5314        self.assertEqual(CardNumber.TEN, 10)
5315
5316    def test_extend_constants(self):
5317        class CardSuit(NamedConstant):
5318            HEARTS = 1
5319            SPADES = 2
5320            DIAMONTS = 3
5321            CLUBS = 4
5322        self.assertEqual(CardSuit.HEARTS, 1)
5323        stars = CardSuit('STARS', 5)
5324        self.assertIs(stars, CardSuit.STARS)
5325        self.assertEqual(CardSuit.STARS, 5)
5326
5327    def test_constant_with_docstring(self):
5328        class Stuff(NamedConstant):
5329            Artifact = constant(7, "lucky number!")
5330            Bowling = 11
5331            HillWomp = constant(29, 'blah blah')
5332        self.assertEqual(Stuff.Artifact, 7)
5333        self.assertEqual(Stuff.Artifact.__doc__, 'lucky number!')
5334        self.assertEqual(Stuff.Bowling, 11)
5335        self.assertEqual(Stuff.Bowling.__doc__, None)
5336        self.assertEqual(Stuff.HillWomp, 29)
5337        self.assertEqual(Stuff.HillWomp.__doc__, 'blah blah')
5338
5339    def test_deep_copy(self):
5340        import copy
5341        class APITypes(aenum.Constant):
5342            STRING = "string"
5343            INT = "int"
5344        APITypes('string')
5345        d = {"first": APITypes.STRING}
5346        copy.deepcopy(d)
5347        self.assertTrue(d['first'] is APITypes.STRING)
5348
5349    def test_subclass_w_same_value(self):
5350        class Foo(aenum.Constant):
5351            BLA = 'bla1'
5352            ABA = 'aba1'
5353        class Bar(aenum.Constant):
5354            BLA = Foo.BLA
5355            ABA = 'aba2'
5356        self.assertEqual(Foo.BLA, Bar.BLA)
5357        self.assertFalse(Foo.BLA is Bar.BLA)
5358
5359# These are unordered here on purpose to ensure that declaration order
5360# makes no difference.
5361CONVERT_TEST_NAME_D = 5
5362CONVERT_TEST_NAME_C = 5
5363CONVERT_TEST_NAME_B = 5
5364CONVERT_TEST_NAME_A = 5  # This one should sort first.
5365CONVERT_TEST_NAME_E = 5
5366CONVERT_TEST_NAME_F = 5
5367CONVERT_TEST_SIGABRT = 4 # and this one
5368CONVERT_TEST_SIGIOT = 4
5369CONVERT_TEST_EIO = 7
5370CONVERT_TEST_EBUS = 7    # and this one
5371
5372class TestIntEnumConvert(TestCase):
5373    def test_convert_value_lookup_priority(self):
5374        test_type = IntEnum._convert(
5375                'UnittestConvert',
5376                '__main__',
5377                filter=lambda x: x.startswith('CONVERT_TEST_'))
5378        # We don't want the reverse lookup value to vary when there are
5379        # multiple possible names for a given value.  It should always
5380        # report the first lexigraphical name in that case.
5381        self.assertEqual(test_type(5).name, 'CONVERT_TEST_NAME_A')
5382        self.assertEqual(test_type(4).name, 'CONVERT_TEST_SIGABRT')
5383        self.assertEqual(test_type(7).name, 'CONVERT_TEST_EBUS')
5384        self.assertEqual(
5385                list(test_type),
5386                [
5387                    test_type.CONVERT_TEST_SIGABRT,
5388                    test_type.CONVERT_TEST_NAME_A,
5389                    test_type.CONVERT_TEST_EBUS,
5390                    ],
5391                )
5392
5393    def test_convert(self):
5394        test_type = IntEnum._convert(
5395                'UnittestConvert',
5396                '__main__',
5397                filter=lambda x: x.startswith('CONVERT_TEST_'))
5398        # Ensure that test_type has all of the desired names and values.
5399        self.assertEqual(test_type.CONVERT_TEST_NAME_F,
5400                         test_type.CONVERT_TEST_NAME_A)
5401        self.assertEqual(test_type.CONVERT_TEST_NAME_B, 5)
5402        self.assertEqual(test_type.CONVERT_TEST_NAME_C, 5)
5403        self.assertEqual(test_type.CONVERT_TEST_NAME_D, 5)
5404        self.assertEqual(test_type.CONVERT_TEST_NAME_E, 5)
5405        # Ensure that test_type only picked up names matching the filter.
5406        self.assertEqual([name for name in dir(test_type)
5407                          if name[0:2] not in ('CO', '__')],
5408                         [], msg='Names other than CONVERT_TEST_* found.')
5409
5410
5411class TestStarImport(TestCase):
5412
5413    def test_all_exports_names(self):
5414        scope = {}
5415        exec('from aenum import *', scope, scope)
5416        self.assertIn('Enum', scope)
5417
5418
5419if __name__ == '__main__':
5420    tempdir = tempfile.mkdtemp()
5421    try:
5422        unittest.main()
5423    finally:
5424        shutil.rmtree(tempdir, True)
5425
5426