1import enum
2import inspect
3import pydoc
4import sys
5import unittest
6import threading
7from collections import OrderedDict
8from enum import Enum, IntEnum, EnumMeta, Flag, IntFlag, unique, auto
9from io import StringIO
10from pickle import dumps, loads, PicklingError, HIGHEST_PROTOCOL
11from test import support
12from datetime import timedelta
13
14
15# for pickle tests
16try:
17    class Stooges(Enum):
18        LARRY = 1
19        CURLY = 2
20        MOE = 3
21except Exception as exc:
22    Stooges = exc
23
24try:
25    class IntStooges(int, Enum):
26        LARRY = 1
27        CURLY = 2
28        MOE = 3
29except Exception as exc:
30    IntStooges = exc
31
32try:
33    class FloatStooges(float, Enum):
34        LARRY = 1.39
35        CURLY = 2.72
36        MOE = 3.142596
37except Exception as exc:
38    FloatStooges = exc
39
40try:
41    class FlagStooges(Flag):
42        LARRY = 1
43        CURLY = 2
44        MOE = 3
45except Exception as exc:
46    FlagStooges = exc
47
48# for pickle test and subclass tests
49try:
50    class StrEnum(str, Enum):
51        'accepts only string values'
52    class Name(StrEnum):
53        BDFL = 'Guido van Rossum'
54        FLUFL = 'Barry Warsaw'
55except Exception as exc:
56    Name = exc
57
58try:
59    Question = Enum('Question', 'who what when where why', module=__name__)
60except Exception as exc:
61    Question = exc
62
63try:
64    Answer = Enum('Answer', 'him this then there because')
65except Exception as exc:
66    Answer = exc
67
68try:
69    Theory = Enum('Theory', 'rule law supposition', qualname='spanish_inquisition')
70except Exception as exc:
71    Theory = exc
72
73# for doctests
74try:
75    class Fruit(Enum):
76        TOMATO = 1
77        BANANA = 2
78        CHERRY = 3
79except Exception:
80    pass
81
82def test_pickle_dump_load(assertion, source, target=None):
83    if target is None:
84        target = source
85    for protocol in range(HIGHEST_PROTOCOL + 1):
86        assertion(loads(dumps(source, protocol=protocol)), target)
87
88def test_pickle_exception(assertion, exception, obj):
89    for protocol in range(HIGHEST_PROTOCOL + 1):
90        with assertion(exception):
91            dumps(obj, protocol=protocol)
92
93class TestHelpers(unittest.TestCase):
94    # _is_descriptor, _is_sunder, _is_dunder
95
96    def test_is_descriptor(self):
97        class foo:
98            pass
99        for attr in ('__get__','__set__','__delete__'):
100            obj = foo()
101            self.assertFalse(enum._is_descriptor(obj))
102            setattr(obj, attr, 1)
103            self.assertTrue(enum._is_descriptor(obj))
104
105    def test_is_sunder(self):
106        for s in ('_a_', '_aa_'):
107            self.assertTrue(enum._is_sunder(s))
108
109        for s in ('a', 'a_', '_a', '__a', 'a__', '__a__', '_a__', '__a_', '_',
110                '__', '___', '____', '_____',):
111            self.assertFalse(enum._is_sunder(s))
112
113    def test_is_dunder(self):
114        for s in ('__a__', '__aa__'):
115            self.assertTrue(enum._is_dunder(s))
116        for s in ('a', 'a_', '_a', '__a', 'a__', '_a_', '_a__', '__a_', '_',
117                '__', '___', '____', '_____',):
118            self.assertFalse(enum._is_dunder(s))
119
120# for subclassing tests
121
122class classproperty:
123
124    def __init__(self, fget=None, fset=None, fdel=None, doc=None):
125        self.fget = fget
126        self.fset = fset
127        self.fdel = fdel
128        if doc is None and fget is not None:
129            doc = fget.__doc__
130        self.__doc__ = doc
131
132    def __get__(self, instance, ownerclass):
133        return self.fget(ownerclass)
134
135
136# tests
137
138class TestEnum(unittest.TestCase):
139
140    def setUp(self):
141        class Season(Enum):
142            SPRING = 1
143            SUMMER = 2
144            AUTUMN = 3
145            WINTER = 4
146        self.Season = Season
147
148        class Konstants(float, Enum):
149            E = 2.7182818
150            PI = 3.1415926
151            TAU = 2 * PI
152        self.Konstants = Konstants
153
154        class Grades(IntEnum):
155            A = 5
156            B = 4
157            C = 3
158            D = 2
159            F = 0
160        self.Grades = Grades
161
162        class Directional(str, Enum):
163            EAST = 'east'
164            WEST = 'west'
165            NORTH = 'north'
166            SOUTH = 'south'
167        self.Directional = Directional
168
169        from datetime import date
170        class Holiday(date, Enum):
171            NEW_YEAR = 2013, 1, 1
172            IDES_OF_MARCH = 2013, 3, 15
173        self.Holiday = Holiday
174
175    def test_dir_on_class(self):
176        Season = self.Season
177        self.assertEqual(
178            set(dir(Season)),
179            set(['__class__', '__doc__', '__members__', '__module__',
180                'SPRING', 'SUMMER', 'AUTUMN', 'WINTER']),
181            )
182
183    def test_dir_on_item(self):
184        Season = self.Season
185        self.assertEqual(
186            set(dir(Season.WINTER)),
187            set(['__class__', '__doc__', '__module__', 'name', 'value']),
188            )
189
190    def test_dir_with_added_behavior(self):
191        class Test(Enum):
192            this = 'that'
193            these = 'those'
194            def wowser(self):
195                return ("Wowser! I'm %s!" % self.name)
196        self.assertEqual(
197                set(dir(Test)),
198                set(['__class__', '__doc__', '__members__', '__module__', 'this', 'these']),
199                )
200        self.assertEqual(
201                set(dir(Test.this)),
202                set(['__class__', '__doc__', '__module__', 'name', 'value', 'wowser']),
203                )
204
205    def test_dir_on_sub_with_behavior_on_super(self):
206        # see issue22506
207        class SuperEnum(Enum):
208            def invisible(self):
209                return "did you see me?"
210        class SubEnum(SuperEnum):
211            sample = 5
212        self.assertEqual(
213                set(dir(SubEnum.sample)),
214                set(['__class__', '__doc__', '__module__', 'name', 'value', 'invisible']),
215                )
216
217    def test_dir_on_sub_with_behavior_including_instance_dict_on_super(self):
218        # see issue40084
219        class SuperEnum(IntEnum):
220            def __new__(cls, value, description=""):
221                obj = int.__new__(cls, value)
222                obj._value_ = value
223                obj.description = description
224                return obj
225        class SubEnum(SuperEnum):
226            sample = 5
227        self.assertTrue({'description'} <= set(dir(SubEnum.sample)))
228
229    def test_enum_in_enum_out(self):
230        Season = self.Season
231        self.assertIs(Season(Season.WINTER), Season.WINTER)
232
233    def test_enum_value(self):
234        Season = self.Season
235        self.assertEqual(Season.SPRING.value, 1)
236
237    def test_intenum_value(self):
238        self.assertEqual(IntStooges.CURLY.value, 2)
239
240    def test_enum(self):
241        Season = self.Season
242        lst = list(Season)
243        self.assertEqual(len(lst), len(Season))
244        self.assertEqual(len(Season), 4, Season)
245        self.assertEqual(
246            [Season.SPRING, Season.SUMMER, Season.AUTUMN, Season.WINTER], lst)
247
248        for i, season in enumerate('SPRING SUMMER AUTUMN WINTER'.split(), 1):
249            e = Season(i)
250            self.assertEqual(e, getattr(Season, season))
251            self.assertEqual(e.value, i)
252            self.assertNotEqual(e, i)
253            self.assertEqual(e.name, season)
254            self.assertIn(e, Season)
255            self.assertIs(type(e), Season)
256            self.assertIsInstance(e, Season)
257            self.assertEqual(str(e), 'Season.' + season)
258            self.assertEqual(
259                    repr(e),
260                    '<Season.{0}: {1}>'.format(season, i),
261                    )
262
263    def test_value_name(self):
264        Season = self.Season
265        self.assertEqual(Season.SPRING.name, 'SPRING')
266        self.assertEqual(Season.SPRING.value, 1)
267        with self.assertRaises(AttributeError):
268            Season.SPRING.name = 'invierno'
269        with self.assertRaises(AttributeError):
270            Season.SPRING.value = 2
271
272    def test_changing_member(self):
273        Season = self.Season
274        with self.assertRaises(AttributeError):
275            Season.WINTER = 'really cold'
276
277    def test_attribute_deletion(self):
278        class Season(Enum):
279            SPRING = 1
280            SUMMER = 2
281            AUTUMN = 3
282            WINTER = 4
283
284            def spam(cls):
285                pass
286
287        self.assertTrue(hasattr(Season, 'spam'))
288        del Season.spam
289        self.assertFalse(hasattr(Season, 'spam'))
290
291        with self.assertRaises(AttributeError):
292            del Season.SPRING
293        with self.assertRaises(AttributeError):
294            del Season.DRY
295        with self.assertRaises(AttributeError):
296            del Season.SPRING.name
297
298    def test_bool_of_class(self):
299        class Empty(Enum):
300            pass
301        self.assertTrue(bool(Empty))
302
303    def test_bool_of_member(self):
304        class Count(Enum):
305            zero = 0
306            one = 1
307            two = 2
308        for member in Count:
309            self.assertTrue(bool(member))
310
311    def test_invalid_names(self):
312        with self.assertRaises(ValueError):
313            class Wrong(Enum):
314                mro = 9
315        with self.assertRaises(ValueError):
316            class Wrong(Enum):
317                _create_= 11
318        with self.assertRaises(ValueError):
319            class Wrong(Enum):
320                _get_mixins_ = 9
321        with self.assertRaises(ValueError):
322            class Wrong(Enum):
323                _find_new_ = 1
324        with self.assertRaises(ValueError):
325            class Wrong(Enum):
326                _any_name_ = 9
327
328    def test_bool(self):
329        # plain Enum members are always True
330        class Logic(Enum):
331            true = True
332            false = False
333        self.assertTrue(Logic.true)
334        self.assertTrue(Logic.false)
335        # unless overridden
336        class RealLogic(Enum):
337            true = True
338            false = False
339            def __bool__(self):
340                return bool(self._value_)
341        self.assertTrue(RealLogic.true)
342        self.assertFalse(RealLogic.false)
343        # mixed Enums depend on mixed-in type
344        class IntLogic(int, Enum):
345            true = 1
346            false = 0
347        self.assertTrue(IntLogic.true)
348        self.assertFalse(IntLogic.false)
349
350    def test_contains(self):
351        Season = self.Season
352        self.assertIn(Season.AUTUMN, Season)
353        with self.assertRaises(TypeError):
354            3 in Season
355        with self.assertRaises(TypeError):
356            'AUTUMN' in Season
357
358        val = Season(3)
359        self.assertIn(val, Season)
360
361        class OtherEnum(Enum):
362            one = 1; two = 2
363        self.assertNotIn(OtherEnum.two, Season)
364
365    def test_comparisons(self):
366        Season = self.Season
367        with self.assertRaises(TypeError):
368            Season.SPRING < Season.WINTER
369        with self.assertRaises(TypeError):
370            Season.SPRING > 4
371
372        self.assertNotEqual(Season.SPRING, 1)
373
374        class Part(Enum):
375            SPRING = 1
376            CLIP = 2
377            BARREL = 3
378
379        self.assertNotEqual(Season.SPRING, Part.SPRING)
380        with self.assertRaises(TypeError):
381            Season.SPRING < Part.CLIP
382
383    def test_enum_duplicates(self):
384        class Season(Enum):
385            SPRING = 1
386            SUMMER = 2
387            AUTUMN = FALL = 3
388            WINTER = 4
389            ANOTHER_SPRING = 1
390        lst = list(Season)
391        self.assertEqual(
392            lst,
393            [Season.SPRING, Season.SUMMER,
394             Season.AUTUMN, Season.WINTER,
395            ])
396        self.assertIs(Season.FALL, Season.AUTUMN)
397        self.assertEqual(Season.FALL.value, 3)
398        self.assertEqual(Season.AUTUMN.value, 3)
399        self.assertIs(Season(3), Season.AUTUMN)
400        self.assertIs(Season(1), Season.SPRING)
401        self.assertEqual(Season.FALL.name, 'AUTUMN')
402        self.assertEqual(
403                [k for k,v in Season.__members__.items() if v.name != k],
404                ['FALL', 'ANOTHER_SPRING'],
405                )
406
407    def test_duplicate_name(self):
408        with self.assertRaises(TypeError):
409            class Color(Enum):
410                red = 1
411                green = 2
412                blue = 3
413                red = 4
414
415        with self.assertRaises(TypeError):
416            class Color(Enum):
417                red = 1
418                green = 2
419                blue = 3
420                def red(self):
421                    return 'red'
422
423        with self.assertRaises(TypeError):
424            class Color(Enum):
425                @property
426                def red(self):
427                    return 'redder'
428                red = 1
429                green = 2
430                blue = 3
431
432    def test_enum_with_value_name(self):
433        class Huh(Enum):
434            name = 1
435            value = 2
436        self.assertEqual(
437            list(Huh),
438            [Huh.name, Huh.value],
439            )
440        self.assertIs(type(Huh.name), Huh)
441        self.assertEqual(Huh.name.name, 'name')
442        self.assertEqual(Huh.name.value, 1)
443
444    def test_format_enum(self):
445        Season = self.Season
446        self.assertEqual('{}'.format(Season.SPRING),
447                         '{}'.format(str(Season.SPRING)))
448        self.assertEqual( '{:}'.format(Season.SPRING),
449                          '{:}'.format(str(Season.SPRING)))
450        self.assertEqual('{:20}'.format(Season.SPRING),
451                         '{:20}'.format(str(Season.SPRING)))
452        self.assertEqual('{:^20}'.format(Season.SPRING),
453                         '{:^20}'.format(str(Season.SPRING)))
454        self.assertEqual('{:>20}'.format(Season.SPRING),
455                         '{:>20}'.format(str(Season.SPRING)))
456        self.assertEqual('{:<20}'.format(Season.SPRING),
457                         '{:<20}'.format(str(Season.SPRING)))
458
459    def test_str_override_enum(self):
460        class EnumWithStrOverrides(Enum):
461            one = auto()
462            two = auto()
463
464            def __str__(self):
465                return 'Str!'
466        self.assertEqual(str(EnumWithStrOverrides.one), 'Str!')
467        self.assertEqual('{}'.format(EnumWithStrOverrides.one), 'Str!')
468
469    def test_format_override_enum(self):
470        class EnumWithFormatOverride(Enum):
471            one = 1.0
472            two = 2.0
473            def __format__(self, spec):
474                return 'Format!!'
475        self.assertEqual(str(EnumWithFormatOverride.one), 'EnumWithFormatOverride.one')
476        self.assertEqual('{}'.format(EnumWithFormatOverride.one), 'Format!!')
477
478    def test_str_and_format_override_enum(self):
479        class EnumWithStrFormatOverrides(Enum):
480            one = auto()
481            two = auto()
482            def __str__(self):
483                return 'Str!'
484            def __format__(self, spec):
485                return 'Format!'
486        self.assertEqual(str(EnumWithStrFormatOverrides.one), 'Str!')
487        self.assertEqual('{}'.format(EnumWithStrFormatOverrides.one), 'Format!')
488
489    def test_str_override_mixin(self):
490        class MixinEnumWithStrOverride(float, Enum):
491            one = 1.0
492            two = 2.0
493            def __str__(self):
494                return 'Overridden!'
495        self.assertEqual(str(MixinEnumWithStrOverride.one), 'Overridden!')
496        self.assertEqual('{}'.format(MixinEnumWithStrOverride.one), 'Overridden!')
497
498    def test_str_and_format_override_mixin(self):
499        class MixinWithStrFormatOverrides(float, Enum):
500            one = 1.0
501            two = 2.0
502            def __str__(self):
503                return 'Str!'
504            def __format__(self, spec):
505                return 'Format!'
506        self.assertEqual(str(MixinWithStrFormatOverrides.one), 'Str!')
507        self.assertEqual('{}'.format(MixinWithStrFormatOverrides.one), 'Format!')
508
509    def test_format_override_mixin(self):
510        class TestFloat(float, Enum):
511            one = 1.0
512            two = 2.0
513            def __format__(self, spec):
514                return 'TestFloat success!'
515        self.assertEqual(str(TestFloat.one), 'TestFloat.one')
516        self.assertEqual('{}'.format(TestFloat.one), 'TestFloat success!')
517
518    def assertFormatIsValue(self, spec, member):
519        self.assertEqual(spec.format(member), spec.format(member.value))
520
521    def test_format_enum_date(self):
522        Holiday = self.Holiday
523        self.assertFormatIsValue('{}', Holiday.IDES_OF_MARCH)
524        self.assertFormatIsValue('{:}', Holiday.IDES_OF_MARCH)
525        self.assertFormatIsValue('{:20}', Holiday.IDES_OF_MARCH)
526        self.assertFormatIsValue('{:^20}', Holiday.IDES_OF_MARCH)
527        self.assertFormatIsValue('{:>20}', Holiday.IDES_OF_MARCH)
528        self.assertFormatIsValue('{:<20}', Holiday.IDES_OF_MARCH)
529        self.assertFormatIsValue('{:%Y %m}', Holiday.IDES_OF_MARCH)
530        self.assertFormatIsValue('{:%Y %m %M:00}', Holiday.IDES_OF_MARCH)
531
532    def test_format_enum_float(self):
533        Konstants = self.Konstants
534        self.assertFormatIsValue('{}', Konstants.TAU)
535        self.assertFormatIsValue('{:}', Konstants.TAU)
536        self.assertFormatIsValue('{:20}', Konstants.TAU)
537        self.assertFormatIsValue('{:^20}', Konstants.TAU)
538        self.assertFormatIsValue('{:>20}', Konstants.TAU)
539        self.assertFormatIsValue('{:<20}', Konstants.TAU)
540        self.assertFormatIsValue('{:n}', Konstants.TAU)
541        self.assertFormatIsValue('{:5.2}', Konstants.TAU)
542        self.assertFormatIsValue('{:f}', Konstants.TAU)
543
544    def test_format_enum_int(self):
545        Grades = self.Grades
546        self.assertFormatIsValue('{}', Grades.C)
547        self.assertFormatIsValue('{:}', Grades.C)
548        self.assertFormatIsValue('{:20}', Grades.C)
549        self.assertFormatIsValue('{:^20}', Grades.C)
550        self.assertFormatIsValue('{:>20}', Grades.C)
551        self.assertFormatIsValue('{:<20}', Grades.C)
552        self.assertFormatIsValue('{:+}', Grades.C)
553        self.assertFormatIsValue('{:08X}', Grades.C)
554        self.assertFormatIsValue('{:b}', Grades.C)
555
556    def test_format_enum_str(self):
557        Directional = self.Directional
558        self.assertFormatIsValue('{}', Directional.WEST)
559        self.assertFormatIsValue('{:}', Directional.WEST)
560        self.assertFormatIsValue('{:20}', Directional.WEST)
561        self.assertFormatIsValue('{:^20}', Directional.WEST)
562        self.assertFormatIsValue('{:>20}', Directional.WEST)
563        self.assertFormatIsValue('{:<20}', Directional.WEST)
564
565    def test_object_str_override(self):
566        class Colors(Enum):
567            RED, GREEN, BLUE = 1, 2, 3
568            def __repr__(self):
569                return "test.%s" % (self._name_, )
570            __str__ = object.__str__
571        self.assertEqual(str(Colors.RED), 'test.RED')
572
573    def test_enum_str_override(self):
574        class MyStrEnum(Enum):
575            def __str__(self):
576                return 'MyStr'
577        class MyMethodEnum(Enum):
578            def hello(self):
579                return 'Hello!  My name is %s' % self.name
580        class Test1Enum(MyMethodEnum, int, MyStrEnum):
581            One = 1
582            Two = 2
583        self.assertTrue(Test1Enum._member_type_ is int)
584        self.assertEqual(str(Test1Enum.One), 'MyStr')
585        self.assertEqual(format(Test1Enum.One, ''), 'MyStr')
586        #
587        class Test2Enum(MyStrEnum, MyMethodEnum):
588            One = 1
589            Two = 2
590        self.assertEqual(str(Test2Enum.One), 'MyStr')
591        self.assertEqual(format(Test1Enum.One, ''), 'MyStr')
592
593    def test_inherited_data_type(self):
594        class HexInt(int):
595            def __repr__(self):
596                return hex(self)
597        class MyEnum(HexInt, enum.Enum):
598            A = 1
599            B = 2
600            C = 3
601        self.assertEqual(repr(MyEnum.A), '<MyEnum.A: 0x1>')
602
603    def test_too_many_data_types(self):
604        with self.assertRaisesRegex(TypeError, 'too many data types'):
605            class Huh(str, int, Enum):
606                One = 1
607
608        class MyStr(str):
609            def hello(self):
610                return 'hello, %s' % self
611        class MyInt(int):
612            def repr(self):
613                return hex(self)
614        with self.assertRaisesRegex(TypeError, 'too many data types'):
615            class Huh(MyStr, MyInt, Enum):
616                One = 1
617
618    def test_hash(self):
619        Season = self.Season
620        dates = {}
621        dates[Season.WINTER] = '1225'
622        dates[Season.SPRING] = '0315'
623        dates[Season.SUMMER] = '0704'
624        dates[Season.AUTUMN] = '1031'
625        self.assertEqual(dates[Season.AUTUMN], '1031')
626
627    def test_intenum_from_scratch(self):
628        class phy(int, Enum):
629            pi = 3
630            tau = 2 * pi
631        self.assertTrue(phy.pi < phy.tau)
632
633    def test_intenum_inherited(self):
634        class IntEnum(int, Enum):
635            pass
636        class phy(IntEnum):
637            pi = 3
638            tau = 2 * pi
639        self.assertTrue(phy.pi < phy.tau)
640
641    def test_floatenum_from_scratch(self):
642        class phy(float, Enum):
643            pi = 3.1415926
644            tau = 2 * pi
645        self.assertTrue(phy.pi < phy.tau)
646
647    def test_floatenum_inherited(self):
648        class FloatEnum(float, Enum):
649            pass
650        class phy(FloatEnum):
651            pi = 3.1415926
652            tau = 2 * pi
653        self.assertTrue(phy.pi < phy.tau)
654
655    def test_strenum_from_scratch(self):
656        class phy(str, Enum):
657            pi = 'Pi'
658            tau = 'Tau'
659        self.assertTrue(phy.pi < phy.tau)
660
661    def test_strenum_inherited(self):
662        class StrEnum(str, Enum):
663            pass
664        class phy(StrEnum):
665            pi = 'Pi'
666            tau = 'Tau'
667        self.assertTrue(phy.pi < phy.tau)
668
669
670    def test_intenum(self):
671        class WeekDay(IntEnum):
672            SUNDAY = 1
673            MONDAY = 2
674            TUESDAY = 3
675            WEDNESDAY = 4
676            THURSDAY = 5
677            FRIDAY = 6
678            SATURDAY = 7
679
680        self.assertEqual(['a', 'b', 'c'][WeekDay.MONDAY], 'c')
681        self.assertEqual([i for i in range(WeekDay.TUESDAY)], [0, 1, 2])
682
683        lst = list(WeekDay)
684        self.assertEqual(len(lst), len(WeekDay))
685        self.assertEqual(len(WeekDay), 7)
686        target = 'SUNDAY MONDAY TUESDAY WEDNESDAY THURSDAY FRIDAY SATURDAY'
687        target = target.split()
688        for i, weekday in enumerate(target, 1):
689            e = WeekDay(i)
690            self.assertEqual(e, i)
691            self.assertEqual(int(e), i)
692            self.assertEqual(e.name, weekday)
693            self.assertIn(e, WeekDay)
694            self.assertEqual(lst.index(e)+1, i)
695            self.assertTrue(0 < e < 8)
696            self.assertIs(type(e), WeekDay)
697            self.assertIsInstance(e, int)
698            self.assertIsInstance(e, Enum)
699
700    def test_intenum_duplicates(self):
701        class WeekDay(IntEnum):
702            SUNDAY = 1
703            MONDAY = 2
704            TUESDAY = TEUSDAY = 3
705            WEDNESDAY = 4
706            THURSDAY = 5
707            FRIDAY = 6
708            SATURDAY = 7
709        self.assertIs(WeekDay.TEUSDAY, WeekDay.TUESDAY)
710        self.assertEqual(WeekDay(3).name, 'TUESDAY')
711        self.assertEqual([k for k,v in WeekDay.__members__.items()
712                if v.name != k], ['TEUSDAY', ])
713
714    def test_intenum_from_bytes(self):
715        self.assertIs(IntStooges.from_bytes(b'\x00\x03', 'big'), IntStooges.MOE)
716        with self.assertRaises(ValueError):
717            IntStooges.from_bytes(b'\x00\x05', 'big')
718
719    def test_floatenum_fromhex(self):
720        h = float.hex(FloatStooges.MOE.value)
721        self.assertIs(FloatStooges.fromhex(h), FloatStooges.MOE)
722        h = float.hex(FloatStooges.MOE.value + 0.01)
723        with self.assertRaises(ValueError):
724            FloatStooges.fromhex(h)
725
726    def test_pickle_enum(self):
727        if isinstance(Stooges, Exception):
728            raise Stooges
729        test_pickle_dump_load(self.assertIs, Stooges.CURLY)
730        test_pickle_dump_load(self.assertIs, Stooges)
731
732    def test_pickle_int(self):
733        if isinstance(IntStooges, Exception):
734            raise IntStooges
735        test_pickle_dump_load(self.assertIs, IntStooges.CURLY)
736        test_pickle_dump_load(self.assertIs, IntStooges)
737
738    def test_pickle_float(self):
739        if isinstance(FloatStooges, Exception):
740            raise FloatStooges
741        test_pickle_dump_load(self.assertIs, FloatStooges.CURLY)
742        test_pickle_dump_load(self.assertIs, FloatStooges)
743
744    def test_pickle_enum_function(self):
745        if isinstance(Answer, Exception):
746            raise Answer
747        test_pickle_dump_load(self.assertIs, Answer.him)
748        test_pickle_dump_load(self.assertIs, Answer)
749
750    def test_pickle_enum_function_with_module(self):
751        if isinstance(Question, Exception):
752            raise Question
753        test_pickle_dump_load(self.assertIs, Question.who)
754        test_pickle_dump_load(self.assertIs, Question)
755
756    def test_enum_function_with_qualname(self):
757        if isinstance(Theory, Exception):
758            raise Theory
759        self.assertEqual(Theory.__qualname__, 'spanish_inquisition')
760
761    def test_class_nested_enum_and_pickle_protocol_four(self):
762        # would normally just have this directly in the class namespace
763        class NestedEnum(Enum):
764            twigs = 'common'
765            shiny = 'rare'
766
767        self.__class__.NestedEnum = NestedEnum
768        self.NestedEnum.__qualname__ = '%s.NestedEnum' % self.__class__.__name__
769        test_pickle_dump_load(self.assertIs, self.NestedEnum.twigs)
770
771    def test_pickle_by_name(self):
772        class ReplaceGlobalInt(IntEnum):
773            ONE = 1
774            TWO = 2
775        ReplaceGlobalInt.__reduce_ex__ = enum._reduce_ex_by_name
776        for proto in range(HIGHEST_PROTOCOL):
777            self.assertEqual(ReplaceGlobalInt.TWO.__reduce_ex__(proto), 'TWO')
778
779    def test_exploding_pickle(self):
780        BadPickle = Enum(
781                'BadPickle', 'dill sweet bread-n-butter', module=__name__)
782        globals()['BadPickle'] = BadPickle
783        # now break BadPickle to test exception raising
784        enum._make_class_unpicklable(BadPickle)
785        test_pickle_exception(self.assertRaises, TypeError, BadPickle.dill)
786        test_pickle_exception(self.assertRaises, PicklingError, BadPickle)
787
788    def test_string_enum(self):
789        class SkillLevel(str, Enum):
790            master = 'what is the sound of one hand clapping?'
791            journeyman = 'why did the chicken cross the road?'
792            apprentice = 'knock, knock!'
793        self.assertEqual(SkillLevel.apprentice, 'knock, knock!')
794
795    def test_getattr_getitem(self):
796        class Period(Enum):
797            morning = 1
798            noon = 2
799            evening = 3
800            night = 4
801        self.assertIs(Period(2), Period.noon)
802        self.assertIs(getattr(Period, 'night'), Period.night)
803        self.assertIs(Period['morning'], Period.morning)
804
805    def test_getattr_dunder(self):
806        Season = self.Season
807        self.assertTrue(getattr(Season, '__eq__'))
808
809    def test_iteration_order(self):
810        class Season(Enum):
811            SUMMER = 2
812            WINTER = 4
813            AUTUMN = 3
814            SPRING = 1
815        self.assertEqual(
816                list(Season),
817                [Season.SUMMER, Season.WINTER, Season.AUTUMN, Season.SPRING],
818                )
819
820    def test_reversed_iteration_order(self):
821        self.assertEqual(
822                list(reversed(self.Season)),
823                [self.Season.WINTER, self.Season.AUTUMN, self.Season.SUMMER,
824                 self.Season.SPRING]
825                )
826
827    def test_programmatic_function_string(self):
828        SummerMonth = Enum('SummerMonth', 'june july august')
829        lst = list(SummerMonth)
830        self.assertEqual(len(lst), len(SummerMonth))
831        self.assertEqual(len(SummerMonth), 3, SummerMonth)
832        self.assertEqual(
833                [SummerMonth.june, SummerMonth.july, SummerMonth.august],
834                lst,
835                )
836        for i, month in enumerate('june july august'.split(), 1):
837            e = SummerMonth(i)
838            self.assertEqual(int(e.value), i)
839            self.assertNotEqual(e, i)
840            self.assertEqual(e.name, month)
841            self.assertIn(e, SummerMonth)
842            self.assertIs(type(e), SummerMonth)
843
844    def test_programmatic_function_string_with_start(self):
845        SummerMonth = Enum('SummerMonth', 'june july august', start=10)
846        lst = list(SummerMonth)
847        self.assertEqual(len(lst), len(SummerMonth))
848        self.assertEqual(len(SummerMonth), 3, SummerMonth)
849        self.assertEqual(
850                [SummerMonth.june, SummerMonth.july, SummerMonth.august],
851                lst,
852                )
853        for i, month in enumerate('june july august'.split(), 10):
854            e = SummerMonth(i)
855            self.assertEqual(int(e.value), i)
856            self.assertNotEqual(e, i)
857            self.assertEqual(e.name, month)
858            self.assertIn(e, SummerMonth)
859            self.assertIs(type(e), SummerMonth)
860
861    def test_programmatic_function_string_list(self):
862        SummerMonth = Enum('SummerMonth', ['june', 'july', 'august'])
863        lst = list(SummerMonth)
864        self.assertEqual(len(lst), len(SummerMonth))
865        self.assertEqual(len(SummerMonth), 3, SummerMonth)
866        self.assertEqual(
867                [SummerMonth.june, SummerMonth.july, SummerMonth.august],
868                lst,
869                )
870        for i, month in enumerate('june july august'.split(), 1):
871            e = SummerMonth(i)
872            self.assertEqual(int(e.value), i)
873            self.assertNotEqual(e, i)
874            self.assertEqual(e.name, month)
875            self.assertIn(e, SummerMonth)
876            self.assertIs(type(e), SummerMonth)
877
878    def test_programmatic_function_string_list_with_start(self):
879        SummerMonth = Enum('SummerMonth', ['june', 'july', 'august'], start=20)
880        lst = list(SummerMonth)
881        self.assertEqual(len(lst), len(SummerMonth))
882        self.assertEqual(len(SummerMonth), 3, SummerMonth)
883        self.assertEqual(
884                [SummerMonth.june, SummerMonth.july, SummerMonth.august],
885                lst,
886                )
887        for i, month in enumerate('june july august'.split(), 20):
888            e = SummerMonth(i)
889            self.assertEqual(int(e.value), i)
890            self.assertNotEqual(e, i)
891            self.assertEqual(e.name, month)
892            self.assertIn(e, SummerMonth)
893            self.assertIs(type(e), SummerMonth)
894
895    def test_programmatic_function_iterable(self):
896        SummerMonth = Enum(
897                'SummerMonth',
898                (('june', 1), ('july', 2), ('august', 3))
899                )
900        lst = list(SummerMonth)
901        self.assertEqual(len(lst), len(SummerMonth))
902        self.assertEqual(len(SummerMonth), 3, SummerMonth)
903        self.assertEqual(
904                [SummerMonth.june, SummerMonth.july, SummerMonth.august],
905                lst,
906                )
907        for i, month in enumerate('june july august'.split(), 1):
908            e = SummerMonth(i)
909            self.assertEqual(int(e.value), i)
910            self.assertNotEqual(e, i)
911            self.assertEqual(e.name, month)
912            self.assertIn(e, SummerMonth)
913            self.assertIs(type(e), SummerMonth)
914
915    def test_programmatic_function_from_dict(self):
916        SummerMonth = Enum(
917                'SummerMonth',
918                OrderedDict((('june', 1), ('july', 2), ('august', 3)))
919                )
920        lst = list(SummerMonth)
921        self.assertEqual(len(lst), len(SummerMonth))
922        self.assertEqual(len(SummerMonth), 3, SummerMonth)
923        self.assertEqual(
924                [SummerMonth.june, SummerMonth.july, SummerMonth.august],
925                lst,
926                )
927        for i, month in enumerate('june july august'.split(), 1):
928            e = SummerMonth(i)
929            self.assertEqual(int(e.value), i)
930            self.assertNotEqual(e, i)
931            self.assertEqual(e.name, month)
932            self.assertIn(e, SummerMonth)
933            self.assertIs(type(e), SummerMonth)
934
935    def test_programmatic_function_type(self):
936        SummerMonth = Enum('SummerMonth', 'june july august', type=int)
937        lst = list(SummerMonth)
938        self.assertEqual(len(lst), len(SummerMonth))
939        self.assertEqual(len(SummerMonth), 3, SummerMonth)
940        self.assertEqual(
941                [SummerMonth.june, SummerMonth.july, SummerMonth.august],
942                lst,
943                )
944        for i, month in enumerate('june july august'.split(), 1):
945            e = SummerMonth(i)
946            self.assertEqual(e, i)
947            self.assertEqual(e.name, month)
948            self.assertIn(e, SummerMonth)
949            self.assertIs(type(e), SummerMonth)
950
951    def test_programmatic_function_type_with_start(self):
952        SummerMonth = Enum('SummerMonth', 'june july august', type=int, start=30)
953        lst = list(SummerMonth)
954        self.assertEqual(len(lst), len(SummerMonth))
955        self.assertEqual(len(SummerMonth), 3, SummerMonth)
956        self.assertEqual(
957                [SummerMonth.june, SummerMonth.july, SummerMonth.august],
958                lst,
959                )
960        for i, month in enumerate('june july august'.split(), 30):
961            e = SummerMonth(i)
962            self.assertEqual(e, i)
963            self.assertEqual(e.name, month)
964            self.assertIn(e, SummerMonth)
965            self.assertIs(type(e), SummerMonth)
966
967    def test_programmatic_function_type_from_subclass(self):
968        SummerMonth = IntEnum('SummerMonth', 'june july august')
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(), 1):
977            e = SummerMonth(i)
978            self.assertEqual(e, i)
979            self.assertEqual(e.name, month)
980            self.assertIn(e, SummerMonth)
981            self.assertIs(type(e), SummerMonth)
982
983    def test_programmatic_function_type_from_subclass_with_start(self):
984        SummerMonth = IntEnum('SummerMonth', 'june july august', start=40)
985        lst = list(SummerMonth)
986        self.assertEqual(len(lst), len(SummerMonth))
987        self.assertEqual(len(SummerMonth), 3, SummerMonth)
988        self.assertEqual(
989                [SummerMonth.june, SummerMonth.july, SummerMonth.august],
990                lst,
991                )
992        for i, month in enumerate('june july august'.split(), 40):
993            e = SummerMonth(i)
994            self.assertEqual(e, i)
995            self.assertEqual(e.name, month)
996            self.assertIn(e, SummerMonth)
997            self.assertIs(type(e), SummerMonth)
998
999    def test_subclassing(self):
1000        if isinstance(Name, Exception):
1001            raise Name
1002        self.assertEqual(Name.BDFL, 'Guido van Rossum')
1003        self.assertTrue(Name.BDFL, Name('Guido van Rossum'))
1004        self.assertIs(Name.BDFL, getattr(Name, 'BDFL'))
1005        test_pickle_dump_load(self.assertIs, Name.BDFL)
1006
1007    def test_extending(self):
1008        class Color(Enum):
1009            red = 1
1010            green = 2
1011            blue = 3
1012        with self.assertRaises(TypeError):
1013            class MoreColor(Color):
1014                cyan = 4
1015                magenta = 5
1016                yellow = 6
1017        with self.assertRaisesRegex(TypeError, "EvenMoreColor: cannot extend enumeration 'Color'"):
1018            class EvenMoreColor(Color, IntEnum):
1019                chartruese = 7
1020
1021    def test_exclude_methods(self):
1022        class whatever(Enum):
1023            this = 'that'
1024            these = 'those'
1025            def really(self):
1026                return 'no, not %s' % self.value
1027        self.assertIsNot(type(whatever.really), whatever)
1028        self.assertEqual(whatever.this.really(), 'no, not that')
1029
1030    def test_wrong_inheritance_order(self):
1031        with self.assertRaises(TypeError):
1032            class Wrong(Enum, str):
1033                NotHere = 'error before this point'
1034
1035    def test_intenum_transitivity(self):
1036        class number(IntEnum):
1037            one = 1
1038            two = 2
1039            three = 3
1040        class numero(IntEnum):
1041            uno = 1
1042            dos = 2
1043            tres = 3
1044        self.assertEqual(number.one, numero.uno)
1045        self.assertEqual(number.two, numero.dos)
1046        self.assertEqual(number.three, numero.tres)
1047
1048    def test_wrong_enum_in_call(self):
1049        class Monochrome(Enum):
1050            black = 0
1051            white = 1
1052        class Gender(Enum):
1053            male = 0
1054            female = 1
1055        self.assertRaises(ValueError, Monochrome, Gender.male)
1056
1057    def test_wrong_enum_in_mixed_call(self):
1058        class Monochrome(IntEnum):
1059            black = 0
1060            white = 1
1061        class Gender(Enum):
1062            male = 0
1063            female = 1
1064        self.assertRaises(ValueError, Monochrome, Gender.male)
1065
1066    def test_mixed_enum_in_call_1(self):
1067        class Monochrome(IntEnum):
1068            black = 0
1069            white = 1
1070        class Gender(IntEnum):
1071            male = 0
1072            female = 1
1073        self.assertIs(Monochrome(Gender.female), Monochrome.white)
1074
1075    def test_mixed_enum_in_call_2(self):
1076        class Monochrome(Enum):
1077            black = 0
1078            white = 1
1079        class Gender(IntEnum):
1080            male = 0
1081            female = 1
1082        self.assertIs(Monochrome(Gender.male), Monochrome.black)
1083
1084    def test_flufl_enum(self):
1085        class Fluflnum(Enum):
1086            def __int__(self):
1087                return int(self.value)
1088        class MailManOptions(Fluflnum):
1089            option1 = 1
1090            option2 = 2
1091            option3 = 3
1092        self.assertEqual(int(MailManOptions.option1), 1)
1093
1094    def test_introspection(self):
1095        class Number(IntEnum):
1096            one = 100
1097            two = 200
1098        self.assertIs(Number.one._member_type_, int)
1099        self.assertIs(Number._member_type_, int)
1100        class String(str, Enum):
1101            yarn = 'soft'
1102            rope = 'rough'
1103            wire = 'hard'
1104        self.assertIs(String.yarn._member_type_, str)
1105        self.assertIs(String._member_type_, str)
1106        class Plain(Enum):
1107            vanilla = 'white'
1108            one = 1
1109        self.assertIs(Plain.vanilla._member_type_, object)
1110        self.assertIs(Plain._member_type_, object)
1111
1112    def test_no_such_enum_member(self):
1113        class Color(Enum):
1114            red = 1
1115            green = 2
1116            blue = 3
1117        with self.assertRaises(ValueError):
1118            Color(4)
1119        with self.assertRaises(KeyError):
1120            Color['chartreuse']
1121
1122    def test_new_repr(self):
1123        class Color(Enum):
1124            red = 1
1125            green = 2
1126            blue = 3
1127            def __repr__(self):
1128                return "don't you just love shades of %s?" % self.name
1129        self.assertEqual(
1130                repr(Color.blue),
1131                "don't you just love shades of blue?",
1132                )
1133
1134    def test_inherited_repr(self):
1135        class MyEnum(Enum):
1136            def __repr__(self):
1137                return "My name is %s." % self.name
1138        class MyIntEnum(int, MyEnum):
1139            this = 1
1140            that = 2
1141            theother = 3
1142        self.assertEqual(repr(MyIntEnum.that), "My name is that.")
1143
1144    def test_multiple_mixin_mro(self):
1145        class auto_enum(type(Enum)):
1146            def __new__(metacls, cls, bases, classdict):
1147                temp = type(classdict)()
1148                names = set(classdict._member_names)
1149                i = 0
1150                for k in classdict._member_names:
1151                    v = classdict[k]
1152                    if v is Ellipsis:
1153                        v = i
1154                    else:
1155                        i = v
1156                    i += 1
1157                    temp[k] = v
1158                for k, v in classdict.items():
1159                    if k not in names:
1160                        temp[k] = v
1161                return super(auto_enum, metacls).__new__(
1162                        metacls, cls, bases, temp)
1163
1164        class AutoNumberedEnum(Enum, metaclass=auto_enum):
1165            pass
1166
1167        class AutoIntEnum(IntEnum, metaclass=auto_enum):
1168            pass
1169
1170        class TestAutoNumber(AutoNumberedEnum):
1171            a = ...
1172            b = 3
1173            c = ...
1174
1175        class TestAutoInt(AutoIntEnum):
1176            a = ...
1177            b = 3
1178            c = ...
1179
1180    def test_subclasses_with_getnewargs(self):
1181        class NamedInt(int):
1182            __qualname__ = 'NamedInt'       # needed for pickle protocol 4
1183            def __new__(cls, *args):
1184                _args = args
1185                name, *args = args
1186                if len(args) == 0:
1187                    raise TypeError("name and value must be specified")
1188                self = int.__new__(cls, *args)
1189                self._intname = name
1190                self._args = _args
1191                return self
1192            def __getnewargs__(self):
1193                return self._args
1194            @property
1195            def __name__(self):
1196                return self._intname
1197            def __repr__(self):
1198                # repr() is updated to include the name and type info
1199                return "{}({!r}, {})".format(type(self).__name__,
1200                                             self.__name__,
1201                                             int.__repr__(self))
1202            def __str__(self):
1203                # str() is unchanged, even if it relies on the repr() fallback
1204                base = int
1205                base_str = base.__str__
1206                if base_str.__objclass__ is object:
1207                    return base.__repr__(self)
1208                return base_str(self)
1209            # for simplicity, we only define one operator that
1210            # propagates expressions
1211            def __add__(self, other):
1212                temp = int(self) + int( other)
1213                if isinstance(self, NamedInt) and isinstance(other, NamedInt):
1214                    return NamedInt(
1215                        '({0} + {1})'.format(self.__name__, other.__name__),
1216                        temp )
1217                else:
1218                    return temp
1219
1220        class NEI(NamedInt, Enum):
1221            __qualname__ = 'NEI'      # needed for pickle protocol 4
1222            x = ('the-x', 1)
1223            y = ('the-y', 2)
1224
1225
1226        self.assertIs(NEI.__new__, Enum.__new__)
1227        self.assertEqual(repr(NEI.x + NEI.y), "NamedInt('(the-x + the-y)', 3)")
1228        globals()['NamedInt'] = NamedInt
1229        globals()['NEI'] = NEI
1230        NI5 = NamedInt('test', 5)
1231        self.assertEqual(NI5, 5)
1232        test_pickle_dump_load(self.assertEqual, NI5, 5)
1233        self.assertEqual(NEI.y.value, 2)
1234        test_pickle_dump_load(self.assertIs, NEI.y)
1235        test_pickle_dump_load(self.assertIs, NEI)
1236
1237    def test_subclasses_with_getnewargs_ex(self):
1238        class NamedInt(int):
1239            __qualname__ = 'NamedInt'       # needed for pickle protocol 4
1240            def __new__(cls, *args):
1241                _args = args
1242                name, *args = args
1243                if len(args) == 0:
1244                    raise TypeError("name and value must be specified")
1245                self = int.__new__(cls, *args)
1246                self._intname = name
1247                self._args = _args
1248                return self
1249            def __getnewargs_ex__(self):
1250                return self._args, {}
1251            @property
1252            def __name__(self):
1253                return self._intname
1254            def __repr__(self):
1255                # repr() is updated to include the name and type info
1256                return "{}({!r}, {})".format(type(self).__name__,
1257                                             self.__name__,
1258                                             int.__repr__(self))
1259            def __str__(self):
1260                # str() is unchanged, even if it relies on the repr() fallback
1261                base = int
1262                base_str = base.__str__
1263                if base_str.__objclass__ is object:
1264                    return base.__repr__(self)
1265                return base_str(self)
1266            # for simplicity, we only define one operator that
1267            # propagates expressions
1268            def __add__(self, other):
1269                temp = int(self) + int( other)
1270                if isinstance(self, NamedInt) and isinstance(other, NamedInt):
1271                    return NamedInt(
1272                        '({0} + {1})'.format(self.__name__, other.__name__),
1273                        temp )
1274                else:
1275                    return temp
1276
1277        class NEI(NamedInt, Enum):
1278            __qualname__ = 'NEI'      # needed for pickle protocol 4
1279            x = ('the-x', 1)
1280            y = ('the-y', 2)
1281
1282
1283        self.assertIs(NEI.__new__, Enum.__new__)
1284        self.assertEqual(repr(NEI.x + NEI.y), "NamedInt('(the-x + the-y)', 3)")
1285        globals()['NamedInt'] = NamedInt
1286        globals()['NEI'] = NEI
1287        NI5 = NamedInt('test', 5)
1288        self.assertEqual(NI5, 5)
1289        test_pickle_dump_load(self.assertEqual, NI5, 5)
1290        self.assertEqual(NEI.y.value, 2)
1291        test_pickle_dump_load(self.assertIs, NEI.y)
1292        test_pickle_dump_load(self.assertIs, NEI)
1293
1294    def test_subclasses_with_reduce(self):
1295        class NamedInt(int):
1296            __qualname__ = 'NamedInt'       # needed for pickle protocol 4
1297            def __new__(cls, *args):
1298                _args = args
1299                name, *args = args
1300                if len(args) == 0:
1301                    raise TypeError("name and value must be specified")
1302                self = int.__new__(cls, *args)
1303                self._intname = name
1304                self._args = _args
1305                return self
1306            def __reduce__(self):
1307                return self.__class__, self._args
1308            @property
1309            def __name__(self):
1310                return self._intname
1311            def __repr__(self):
1312                # repr() is updated to include the name and type info
1313                return "{}({!r}, {})".format(type(self).__name__,
1314                                             self.__name__,
1315                                             int.__repr__(self))
1316            def __str__(self):
1317                # str() is unchanged, even if it relies on the repr() fallback
1318                base = int
1319                base_str = base.__str__
1320                if base_str.__objclass__ is object:
1321                    return base.__repr__(self)
1322                return base_str(self)
1323            # for simplicity, we only define one operator that
1324            # propagates expressions
1325            def __add__(self, other):
1326                temp = int(self) + int( other)
1327                if isinstance(self, NamedInt) and isinstance(other, NamedInt):
1328                    return NamedInt(
1329                        '({0} + {1})'.format(self.__name__, other.__name__),
1330                        temp )
1331                else:
1332                    return temp
1333
1334        class NEI(NamedInt, Enum):
1335            __qualname__ = 'NEI'      # needed for pickle protocol 4
1336            x = ('the-x', 1)
1337            y = ('the-y', 2)
1338
1339
1340        self.assertIs(NEI.__new__, Enum.__new__)
1341        self.assertEqual(repr(NEI.x + NEI.y), "NamedInt('(the-x + the-y)', 3)")
1342        globals()['NamedInt'] = NamedInt
1343        globals()['NEI'] = NEI
1344        NI5 = NamedInt('test', 5)
1345        self.assertEqual(NI5, 5)
1346        test_pickle_dump_load(self.assertEqual, NI5, 5)
1347        self.assertEqual(NEI.y.value, 2)
1348        test_pickle_dump_load(self.assertIs, NEI.y)
1349        test_pickle_dump_load(self.assertIs, NEI)
1350
1351    def test_subclasses_with_reduce_ex(self):
1352        class NamedInt(int):
1353            __qualname__ = 'NamedInt'       # needed for pickle protocol 4
1354            def __new__(cls, *args):
1355                _args = args
1356                name, *args = args
1357                if len(args) == 0:
1358                    raise TypeError("name and value must be specified")
1359                self = int.__new__(cls, *args)
1360                self._intname = name
1361                self._args = _args
1362                return self
1363            def __reduce_ex__(self, proto):
1364                return self.__class__, self._args
1365            @property
1366            def __name__(self):
1367                return self._intname
1368            def __repr__(self):
1369                # repr() is updated to include the name and type info
1370                return "{}({!r}, {})".format(type(self).__name__,
1371                                             self.__name__,
1372                                             int.__repr__(self))
1373            def __str__(self):
1374                # str() is unchanged, even if it relies on the repr() fallback
1375                base = int
1376                base_str = base.__str__
1377                if base_str.__objclass__ is object:
1378                    return base.__repr__(self)
1379                return base_str(self)
1380            # for simplicity, we only define one operator that
1381            # propagates expressions
1382            def __add__(self, other):
1383                temp = int(self) + int( other)
1384                if isinstance(self, NamedInt) and isinstance(other, NamedInt):
1385                    return NamedInt(
1386                        '({0} + {1})'.format(self.__name__, other.__name__),
1387                        temp )
1388                else:
1389                    return temp
1390
1391        class NEI(NamedInt, Enum):
1392            __qualname__ = 'NEI'      # needed for pickle protocol 4
1393            x = ('the-x', 1)
1394            y = ('the-y', 2)
1395
1396
1397        self.assertIs(NEI.__new__, Enum.__new__)
1398        self.assertEqual(repr(NEI.x + NEI.y), "NamedInt('(the-x + the-y)', 3)")
1399        globals()['NamedInt'] = NamedInt
1400        globals()['NEI'] = NEI
1401        NI5 = NamedInt('test', 5)
1402        self.assertEqual(NI5, 5)
1403        test_pickle_dump_load(self.assertEqual, NI5, 5)
1404        self.assertEqual(NEI.y.value, 2)
1405        test_pickle_dump_load(self.assertIs, NEI.y)
1406        test_pickle_dump_load(self.assertIs, NEI)
1407
1408    def test_subclasses_without_direct_pickle_support(self):
1409        class NamedInt(int):
1410            __qualname__ = 'NamedInt'
1411            def __new__(cls, *args):
1412                _args = args
1413                name, *args = args
1414                if len(args) == 0:
1415                    raise TypeError("name and value must be specified")
1416                self = int.__new__(cls, *args)
1417                self._intname = name
1418                self._args = _args
1419                return self
1420            @property
1421            def __name__(self):
1422                return self._intname
1423            def __repr__(self):
1424                # repr() is updated to include the name and type info
1425                return "{}({!r}, {})".format(type(self).__name__,
1426                                             self.__name__,
1427                                             int.__repr__(self))
1428            def __str__(self):
1429                # str() is unchanged, even if it relies on the repr() fallback
1430                base = int
1431                base_str = base.__str__
1432                if base_str.__objclass__ is object:
1433                    return base.__repr__(self)
1434                return base_str(self)
1435            # for simplicity, we only define one operator that
1436            # propagates expressions
1437            def __add__(self, other):
1438                temp = int(self) + int( other)
1439                if isinstance(self, NamedInt) and isinstance(other, NamedInt):
1440                    return NamedInt(
1441                        '({0} + {1})'.format(self.__name__, other.__name__),
1442                        temp )
1443                else:
1444                    return temp
1445
1446        class NEI(NamedInt, Enum):
1447            __qualname__ = 'NEI'
1448            x = ('the-x', 1)
1449            y = ('the-y', 2)
1450
1451        self.assertIs(NEI.__new__, Enum.__new__)
1452        self.assertEqual(repr(NEI.x + NEI.y), "NamedInt('(the-x + the-y)', 3)")
1453        globals()['NamedInt'] = NamedInt
1454        globals()['NEI'] = NEI
1455        NI5 = NamedInt('test', 5)
1456        self.assertEqual(NI5, 5)
1457        self.assertEqual(NEI.y.value, 2)
1458        test_pickle_exception(self.assertRaises, TypeError, NEI.x)
1459        test_pickle_exception(self.assertRaises, PicklingError, NEI)
1460
1461    def test_subclasses_without_direct_pickle_support_using_name(self):
1462        class NamedInt(int):
1463            __qualname__ = 'NamedInt'
1464            def __new__(cls, *args):
1465                _args = args
1466                name, *args = args
1467                if len(args) == 0:
1468                    raise TypeError("name and value must be specified")
1469                self = int.__new__(cls, *args)
1470                self._intname = name
1471                self._args = _args
1472                return self
1473            @property
1474            def __name__(self):
1475                return self._intname
1476            def __repr__(self):
1477                # repr() is updated to include the name and type info
1478                return "{}({!r}, {})".format(type(self).__name__,
1479                                             self.__name__,
1480                                             int.__repr__(self))
1481            def __str__(self):
1482                # str() is unchanged, even if it relies on the repr() fallback
1483                base = int
1484                base_str = base.__str__
1485                if base_str.__objclass__ is object:
1486                    return base.__repr__(self)
1487                return base_str(self)
1488            # for simplicity, we only define one operator that
1489            # propagates expressions
1490            def __add__(self, other):
1491                temp = int(self) + int( other)
1492                if isinstance(self, NamedInt) and isinstance(other, NamedInt):
1493                    return NamedInt(
1494                        '({0} + {1})'.format(self.__name__, other.__name__),
1495                        temp )
1496                else:
1497                    return temp
1498
1499        class NEI(NamedInt, Enum):
1500            __qualname__ = 'NEI'
1501            x = ('the-x', 1)
1502            y = ('the-y', 2)
1503            def __reduce_ex__(self, proto):
1504                return getattr, (self.__class__, self._name_)
1505
1506        self.assertIs(NEI.__new__, Enum.__new__)
1507        self.assertEqual(repr(NEI.x + NEI.y), "NamedInt('(the-x + the-y)', 3)")
1508        globals()['NamedInt'] = NamedInt
1509        globals()['NEI'] = NEI
1510        NI5 = NamedInt('test', 5)
1511        self.assertEqual(NI5, 5)
1512        self.assertEqual(NEI.y.value, 2)
1513        test_pickle_dump_load(self.assertIs, NEI.y)
1514        test_pickle_dump_load(self.assertIs, NEI)
1515
1516    def test_tuple_subclass(self):
1517        class SomeTuple(tuple, Enum):
1518            __qualname__ = 'SomeTuple'      # needed for pickle protocol 4
1519            first = (1, 'for the money')
1520            second = (2, 'for the show')
1521            third = (3, 'for the music')
1522        self.assertIs(type(SomeTuple.first), SomeTuple)
1523        self.assertIsInstance(SomeTuple.second, tuple)
1524        self.assertEqual(SomeTuple.third, (3, 'for the music'))
1525        globals()['SomeTuple'] = SomeTuple
1526        test_pickle_dump_load(self.assertIs, SomeTuple.first)
1527
1528    def test_duplicate_values_give_unique_enum_items(self):
1529        class AutoNumber(Enum):
1530            first = ()
1531            second = ()
1532            third = ()
1533            def __new__(cls):
1534                value = len(cls.__members__) + 1
1535                obj = object.__new__(cls)
1536                obj._value_ = value
1537                return obj
1538            def __int__(self):
1539                return int(self._value_)
1540        self.assertEqual(
1541                list(AutoNumber),
1542                [AutoNumber.first, AutoNumber.second, AutoNumber.third],
1543                )
1544        self.assertEqual(int(AutoNumber.second), 2)
1545        self.assertEqual(AutoNumber.third.value, 3)
1546        self.assertIs(AutoNumber(1), AutoNumber.first)
1547
1548    def test_inherited_new_from_enhanced_enum(self):
1549        class AutoNumber(Enum):
1550            def __new__(cls):
1551                value = len(cls.__members__) + 1
1552                obj = object.__new__(cls)
1553                obj._value_ = value
1554                return obj
1555            def __int__(self):
1556                return int(self._value_)
1557        class Color(AutoNumber):
1558            red = ()
1559            green = ()
1560            blue = ()
1561        self.assertEqual(list(Color), [Color.red, Color.green, Color.blue])
1562        self.assertEqual(list(map(int, Color)), [1, 2, 3])
1563
1564    def test_inherited_new_from_mixed_enum(self):
1565        class AutoNumber(IntEnum):
1566            def __new__(cls):
1567                value = len(cls.__members__) + 1
1568                obj = int.__new__(cls, value)
1569                obj._value_ = value
1570                return obj
1571        class Color(AutoNumber):
1572            red = ()
1573            green = ()
1574            blue = ()
1575        self.assertEqual(list(Color), [Color.red, Color.green, Color.blue])
1576        self.assertEqual(list(map(int, Color)), [1, 2, 3])
1577
1578    def test_equality(self):
1579        class AlwaysEqual:
1580            def __eq__(self, other):
1581                return True
1582        class OrdinaryEnum(Enum):
1583            a = 1
1584        self.assertEqual(AlwaysEqual(), OrdinaryEnum.a)
1585        self.assertEqual(OrdinaryEnum.a, AlwaysEqual())
1586
1587    def test_ordered_mixin(self):
1588        class OrderedEnum(Enum):
1589            def __ge__(self, other):
1590                if self.__class__ is other.__class__:
1591                    return self._value_ >= other._value_
1592                return NotImplemented
1593            def __gt__(self, other):
1594                if self.__class__ is other.__class__:
1595                    return self._value_ > other._value_
1596                return NotImplemented
1597            def __le__(self, other):
1598                if self.__class__ is other.__class__:
1599                    return self._value_ <= other._value_
1600                return NotImplemented
1601            def __lt__(self, other):
1602                if self.__class__ is other.__class__:
1603                    return self._value_ < other._value_
1604                return NotImplemented
1605        class Grade(OrderedEnum):
1606            A = 5
1607            B = 4
1608            C = 3
1609            D = 2
1610            F = 1
1611        self.assertGreater(Grade.A, Grade.B)
1612        self.assertLessEqual(Grade.F, Grade.C)
1613        self.assertLess(Grade.D, Grade.A)
1614        self.assertGreaterEqual(Grade.B, Grade.B)
1615        self.assertEqual(Grade.B, Grade.B)
1616        self.assertNotEqual(Grade.C, Grade.D)
1617
1618    def test_extending2(self):
1619        class Shade(Enum):
1620            def shade(self):
1621                print(self.name)
1622        class Color(Shade):
1623            red = 1
1624            green = 2
1625            blue = 3
1626        with self.assertRaises(TypeError):
1627            class MoreColor(Color):
1628                cyan = 4
1629                magenta = 5
1630                yellow = 6
1631
1632    def test_extending3(self):
1633        class Shade(Enum):
1634            def shade(self):
1635                return self.name
1636        class Color(Shade):
1637            def hex(self):
1638                return '%s hexlified!' % self.value
1639        class MoreColor(Color):
1640            cyan = 4
1641            magenta = 5
1642            yellow = 6
1643        self.assertEqual(MoreColor.magenta.hex(), '5 hexlified!')
1644
1645    def test_subclass_duplicate_name(self):
1646        class Base(Enum):
1647            def test(self):
1648                pass
1649        class Test(Base):
1650            test = 1
1651        self.assertIs(type(Test.test), Test)
1652
1653    def test_subclass_duplicate_name_dynamic(self):
1654        from types import DynamicClassAttribute
1655        class Base(Enum):
1656            @DynamicClassAttribute
1657            def test(self):
1658                return 'dynamic'
1659        class Test(Base):
1660            test = 1
1661        self.assertEqual(Test.test.test, 'dynamic')
1662
1663    def test_no_duplicates(self):
1664        class UniqueEnum(Enum):
1665            def __init__(self, *args):
1666                cls = self.__class__
1667                if any(self.value == e.value for e in cls):
1668                    a = self.name
1669                    e = cls(self.value).name
1670                    raise ValueError(
1671                            "aliases not allowed in UniqueEnum:  %r --> %r"
1672                            % (a, e)
1673                            )
1674        class Color(UniqueEnum):
1675            red = 1
1676            green = 2
1677            blue = 3
1678        with self.assertRaises(ValueError):
1679            class Color(UniqueEnum):
1680                red = 1
1681                green = 2
1682                blue = 3
1683                grene = 2
1684
1685    def test_init(self):
1686        class Planet(Enum):
1687            MERCURY = (3.303e+23, 2.4397e6)
1688            VENUS   = (4.869e+24, 6.0518e6)
1689            EARTH   = (5.976e+24, 6.37814e6)
1690            MARS    = (6.421e+23, 3.3972e6)
1691            JUPITER = (1.9e+27,   7.1492e7)
1692            SATURN  = (5.688e+26, 6.0268e7)
1693            URANUS  = (8.686e+25, 2.5559e7)
1694            NEPTUNE = (1.024e+26, 2.4746e7)
1695            def __init__(self, mass, radius):
1696                self.mass = mass       # in kilograms
1697                self.radius = radius   # in meters
1698            @property
1699            def surface_gravity(self):
1700                # universal gravitational constant  (m3 kg-1 s-2)
1701                G = 6.67300E-11
1702                return G * self.mass / (self.radius * self.radius)
1703        self.assertEqual(round(Planet.EARTH.surface_gravity, 2), 9.80)
1704        self.assertEqual(Planet.EARTH.value, (5.976e+24, 6.37814e6))
1705
1706    def test_ignore(self):
1707        class Period(timedelta, Enum):
1708            '''
1709            different lengths of time
1710            '''
1711            def __new__(cls, value, period):
1712                obj = timedelta.__new__(cls, value)
1713                obj._value_ = value
1714                obj.period = period
1715                return obj
1716            _ignore_ = 'Period i'
1717            Period = vars()
1718            for i in range(13):
1719                Period['month_%d' % i] = i*30, 'month'
1720            for i in range(53):
1721                Period['week_%d' % i] = i*7, 'week'
1722            for i in range(32):
1723                Period['day_%d' % i] = i, 'day'
1724            OneDay = day_1
1725            OneWeek = week_1
1726            OneMonth = month_1
1727        self.assertFalse(hasattr(Period, '_ignore_'))
1728        self.assertFalse(hasattr(Period, 'Period'))
1729        self.assertFalse(hasattr(Period, 'i'))
1730        self.assertTrue(isinstance(Period.day_1, timedelta))
1731        self.assertTrue(Period.month_1 is Period.day_30)
1732        self.assertTrue(Period.week_4 is Period.day_28)
1733
1734    def test_nonhash_value(self):
1735        class AutoNumberInAList(Enum):
1736            def __new__(cls):
1737                value = [len(cls.__members__) + 1]
1738                obj = object.__new__(cls)
1739                obj._value_ = value
1740                return obj
1741        class ColorInAList(AutoNumberInAList):
1742            red = ()
1743            green = ()
1744            blue = ()
1745        self.assertEqual(list(ColorInAList), [ColorInAList.red, ColorInAList.green, ColorInAList.blue])
1746        for enum, value in zip(ColorInAList, range(3)):
1747            value += 1
1748            self.assertEqual(enum.value, [value])
1749            self.assertIs(ColorInAList([value]), enum)
1750
1751    def test_conflicting_types_resolved_in_new(self):
1752        class LabelledIntEnum(int, Enum):
1753            def __new__(cls, *args):
1754                value, label = args
1755                obj = int.__new__(cls, value)
1756                obj.label = label
1757                obj._value_ = value
1758                return obj
1759
1760        class LabelledList(LabelledIntEnum):
1761            unprocessed = (1, "Unprocessed")
1762            payment_complete = (2, "Payment Complete")
1763
1764        self.assertEqual(list(LabelledList), [LabelledList.unprocessed, LabelledList.payment_complete])
1765        self.assertEqual(LabelledList.unprocessed, 1)
1766        self.assertEqual(LabelledList(1), LabelledList.unprocessed)
1767
1768    def test_auto_number(self):
1769        class Color(Enum):
1770            red = auto()
1771            blue = auto()
1772            green = auto()
1773
1774        self.assertEqual(list(Color), [Color.red, Color.blue, Color.green])
1775        self.assertEqual(Color.red.value, 1)
1776        self.assertEqual(Color.blue.value, 2)
1777        self.assertEqual(Color.green.value, 3)
1778
1779    def test_auto_name(self):
1780        class Color(Enum):
1781            def _generate_next_value_(name, start, count, last):
1782                return name
1783            red = auto()
1784            blue = auto()
1785            green = auto()
1786
1787        self.assertEqual(list(Color), [Color.red, Color.blue, Color.green])
1788        self.assertEqual(Color.red.value, 'red')
1789        self.assertEqual(Color.blue.value, 'blue')
1790        self.assertEqual(Color.green.value, 'green')
1791
1792    def test_auto_name_inherit(self):
1793        class AutoNameEnum(Enum):
1794            def _generate_next_value_(name, start, count, last):
1795                return name
1796        class Color(AutoNameEnum):
1797            red = auto()
1798            blue = auto()
1799            green = auto()
1800
1801        self.assertEqual(list(Color), [Color.red, Color.blue, Color.green])
1802        self.assertEqual(Color.red.value, 'red')
1803        self.assertEqual(Color.blue.value, 'blue')
1804        self.assertEqual(Color.green.value, 'green')
1805
1806    def test_auto_garbage(self):
1807        class Color(Enum):
1808            red = 'red'
1809            blue = auto()
1810        self.assertEqual(Color.blue.value, 1)
1811
1812    def test_auto_garbage_corrected(self):
1813        class Color(Enum):
1814            red = 'red'
1815            blue = 2
1816            green = auto()
1817
1818        self.assertEqual(list(Color), [Color.red, Color.blue, Color.green])
1819        self.assertEqual(Color.red.value, 'red')
1820        self.assertEqual(Color.blue.value, 2)
1821        self.assertEqual(Color.green.value, 3)
1822
1823    def test_auto_order(self):
1824        with self.assertRaises(TypeError):
1825            class Color(Enum):
1826                red = auto()
1827                green = auto()
1828                blue = auto()
1829                def _generate_next_value_(name, start, count, last):
1830                    return name
1831
1832    def test_auto_order_wierd(self):
1833        weird_auto = auto()
1834        weird_auto.value = 'pathological case'
1835        class Color(Enum):
1836            red = weird_auto
1837            def _generate_next_value_(name, start, count, last):
1838                return name
1839            blue = auto()
1840        self.assertEqual(list(Color), [Color.red, Color.blue])
1841        self.assertEqual(Color.red.value, 'pathological case')
1842        self.assertEqual(Color.blue.value, 'blue')
1843
1844    def test_duplicate_auto(self):
1845        class Dupes(Enum):
1846            first = primero = auto()
1847            second = auto()
1848            third = auto()
1849        self.assertEqual([Dupes.first, Dupes.second, Dupes.third], list(Dupes))
1850
1851    def test_default_missing(self):
1852        class Color(Enum):
1853            RED = 1
1854            GREEN = 2
1855            BLUE = 3
1856        try:
1857            Color(7)
1858        except ValueError as exc:
1859            self.assertTrue(exc.__context__ is None)
1860        else:
1861            raise Exception('Exception not raised.')
1862
1863    def test_missing(self):
1864        class Color(Enum):
1865            red = 1
1866            green = 2
1867            blue = 3
1868            @classmethod
1869            def _missing_(cls, item):
1870                if item == 'three':
1871                    return cls.blue
1872                elif item == 'bad return':
1873                    # trigger internal error
1874                    return 5
1875                elif item == 'error out':
1876                    raise ZeroDivisionError
1877                else:
1878                    # trigger not found
1879                    return None
1880        self.assertIs(Color('three'), Color.blue)
1881        try:
1882            Color(7)
1883        except ValueError as exc:
1884            self.assertTrue(exc.__context__ is None)
1885        else:
1886            raise Exception('Exception not raised.')
1887        try:
1888            Color('bad return')
1889        except TypeError as exc:
1890            self.assertTrue(isinstance(exc.__context__, ValueError))
1891        else:
1892            raise Exception('Exception not raised.')
1893        try:
1894            Color('error out')
1895        except ZeroDivisionError as exc:
1896            self.assertTrue(isinstance(exc.__context__, ValueError))
1897        else:
1898            raise Exception('Exception not raised.')
1899
1900    def test_missing_exceptions_reset(self):
1901        import weakref
1902        #
1903        class TestEnum(enum.Enum):
1904            VAL1 = 'val1'
1905            VAL2 = 'val2'
1906        #
1907        class Class1:
1908            def __init__(self):
1909                # Gracefully handle an exception of our own making
1910                try:
1911                    raise ValueError()
1912                except ValueError:
1913                    pass
1914        #
1915        class Class2:
1916            def __init__(self):
1917                # Gracefully handle an exception of Enum's making
1918                try:
1919                    TestEnum('invalid_value')
1920                except ValueError:
1921                    pass
1922        # No strong refs here so these are free to die.
1923        class_1_ref = weakref.ref(Class1())
1924        class_2_ref = weakref.ref(Class2())
1925        #
1926        # The exception raised by Enum creates a reference loop and thus
1927        # Class2 instances will stick around until the next gargage collection
1928        # cycle, unlike Class1.
1929        self.assertIs(class_1_ref(), None)
1930        self.assertIs(class_2_ref(), None)
1931
1932    def test_multiple_mixin(self):
1933        class MaxMixin:
1934            @classproperty
1935            def MAX(cls):
1936                max = len(cls)
1937                cls.MAX = max
1938                return max
1939        class StrMixin:
1940            def __str__(self):
1941                return self._name_.lower()
1942        class SomeEnum(Enum):
1943            def behavior(self):
1944                return 'booyah'
1945        class AnotherEnum(Enum):
1946            def behavior(self):
1947                return 'nuhuh!'
1948            def social(self):
1949                return "what's up?"
1950        class Color(MaxMixin, Enum):
1951            RED = auto()
1952            GREEN = auto()
1953            BLUE = auto()
1954        self.assertEqual(Color.RED.value, 1)
1955        self.assertEqual(Color.GREEN.value, 2)
1956        self.assertEqual(Color.BLUE.value, 3)
1957        self.assertEqual(Color.MAX, 3)
1958        self.assertEqual(str(Color.BLUE), 'Color.BLUE')
1959        class Color(MaxMixin, StrMixin, Enum):
1960            RED = auto()
1961            GREEN = auto()
1962            BLUE = auto()
1963        self.assertEqual(Color.RED.value, 1)
1964        self.assertEqual(Color.GREEN.value, 2)
1965        self.assertEqual(Color.BLUE.value, 3)
1966        self.assertEqual(Color.MAX, 3)
1967        self.assertEqual(str(Color.BLUE), 'blue')
1968        class Color(StrMixin, MaxMixin, Enum):
1969            RED = auto()
1970            GREEN = auto()
1971            BLUE = auto()
1972        self.assertEqual(Color.RED.value, 1)
1973        self.assertEqual(Color.GREEN.value, 2)
1974        self.assertEqual(Color.BLUE.value, 3)
1975        self.assertEqual(Color.MAX, 3)
1976        self.assertEqual(str(Color.BLUE), 'blue')
1977        class CoolColor(StrMixin, SomeEnum, Enum):
1978            RED = auto()
1979            GREEN = auto()
1980            BLUE = auto()
1981        self.assertEqual(CoolColor.RED.value, 1)
1982        self.assertEqual(CoolColor.GREEN.value, 2)
1983        self.assertEqual(CoolColor.BLUE.value, 3)
1984        self.assertEqual(str(CoolColor.BLUE), 'blue')
1985        self.assertEqual(CoolColor.RED.behavior(), 'booyah')
1986        class CoolerColor(StrMixin, AnotherEnum, Enum):
1987            RED = auto()
1988            GREEN = auto()
1989            BLUE = auto()
1990        self.assertEqual(CoolerColor.RED.value, 1)
1991        self.assertEqual(CoolerColor.GREEN.value, 2)
1992        self.assertEqual(CoolerColor.BLUE.value, 3)
1993        self.assertEqual(str(CoolerColor.BLUE), 'blue')
1994        self.assertEqual(CoolerColor.RED.behavior(), 'nuhuh!')
1995        self.assertEqual(CoolerColor.RED.social(), "what's up?")
1996        class CoolestColor(StrMixin, SomeEnum, AnotherEnum):
1997            RED = auto()
1998            GREEN = auto()
1999            BLUE = auto()
2000        self.assertEqual(CoolestColor.RED.value, 1)
2001        self.assertEqual(CoolestColor.GREEN.value, 2)
2002        self.assertEqual(CoolestColor.BLUE.value, 3)
2003        self.assertEqual(str(CoolestColor.BLUE), 'blue')
2004        self.assertEqual(CoolestColor.RED.behavior(), 'booyah')
2005        self.assertEqual(CoolestColor.RED.social(), "what's up?")
2006        class ConfusedColor(StrMixin, AnotherEnum, SomeEnum):
2007            RED = auto()
2008            GREEN = auto()
2009            BLUE = auto()
2010        self.assertEqual(ConfusedColor.RED.value, 1)
2011        self.assertEqual(ConfusedColor.GREEN.value, 2)
2012        self.assertEqual(ConfusedColor.BLUE.value, 3)
2013        self.assertEqual(str(ConfusedColor.BLUE), 'blue')
2014        self.assertEqual(ConfusedColor.RED.behavior(), 'nuhuh!')
2015        self.assertEqual(ConfusedColor.RED.social(), "what's up?")
2016        class ReformedColor(StrMixin, IntEnum, SomeEnum, AnotherEnum):
2017            RED = auto()
2018            GREEN = auto()
2019            BLUE = auto()
2020        self.assertEqual(ReformedColor.RED.value, 1)
2021        self.assertEqual(ReformedColor.GREEN.value, 2)
2022        self.assertEqual(ReformedColor.BLUE.value, 3)
2023        self.assertEqual(str(ReformedColor.BLUE), 'blue')
2024        self.assertEqual(ReformedColor.RED.behavior(), 'booyah')
2025        self.assertEqual(ConfusedColor.RED.social(), "what's up?")
2026        self.assertTrue(issubclass(ReformedColor, int))
2027
2028    def test_multiple_inherited_mixin(self):
2029        class StrEnum(str, Enum):
2030            def __new__(cls, *args, **kwargs):
2031                for a in args:
2032                    if not isinstance(a, str):
2033                        raise TypeError("Enumeration '%s' (%s) is not"
2034                                        " a string" % (a, type(a).__name__))
2035                return str.__new__(cls, *args, **kwargs)
2036        @unique
2037        class Decision1(StrEnum):
2038            REVERT = "REVERT"
2039            REVERT_ALL = "REVERT_ALL"
2040            RETRY = "RETRY"
2041        class MyEnum(StrEnum):
2042            pass
2043        @unique
2044        class Decision2(MyEnum):
2045            REVERT = "REVERT"
2046            REVERT_ALL = "REVERT_ALL"
2047            RETRY = "RETRY"
2048
2049    def test_multiple_mixin_inherited(self):
2050        class MyInt(int):
2051            def __new__(cls, value):
2052                return super().__new__(cls, value)
2053
2054        class HexMixin:
2055            def __repr__(self):
2056                return hex(self)
2057
2058        class MyIntEnum(HexMixin, MyInt, enum.Enum):
2059            pass
2060
2061        class Foo(MyIntEnum):
2062            TEST = 1
2063        self.assertTrue(isinstance(Foo.TEST, MyInt))
2064        self.assertEqual(repr(Foo.TEST), "0x1")
2065
2066        class Fee(MyIntEnum):
2067            TEST = 1
2068            def __new__(cls, value):
2069                value += 1
2070                member = int.__new__(cls, value)
2071                member._value_ = value
2072                return member
2073        self.assertEqual(Fee.TEST, 2)
2074
2075    def test_empty_globals(self):
2076        # bpo-35717: sys._getframe(2).f_globals['__name__'] fails with KeyError
2077        # when using compile and exec because f_globals is empty
2078        code = "from enum import Enum; Enum('Animal', 'ANT BEE CAT DOG')"
2079        code = compile(code, "<string>", "exec")
2080        global_ns = {}
2081        local_ls = {}
2082        exec(code, global_ns, local_ls)
2083
2084
2085class TestOrder(unittest.TestCase):
2086
2087    def test_same_members(self):
2088        class Color(Enum):
2089            _order_ = 'red green blue'
2090            red = 1
2091            green = 2
2092            blue = 3
2093
2094    def test_same_members_with_aliases(self):
2095        class Color(Enum):
2096            _order_ = 'red green blue'
2097            red = 1
2098            green = 2
2099            blue = 3
2100            verde = green
2101
2102    def test_same_members_wrong_order(self):
2103        with self.assertRaisesRegex(TypeError, 'member order does not match _order_'):
2104            class Color(Enum):
2105                _order_ = 'red green blue'
2106                red = 1
2107                blue = 3
2108                green = 2
2109
2110    def test_order_has_extra_members(self):
2111        with self.assertRaisesRegex(TypeError, 'member order does not match _order_'):
2112            class Color(Enum):
2113                _order_ = 'red green blue purple'
2114                red = 1
2115                green = 2
2116                blue = 3
2117
2118    def test_order_has_extra_members_with_aliases(self):
2119        with self.assertRaisesRegex(TypeError, 'member order does not match _order_'):
2120            class Color(Enum):
2121                _order_ = 'red green blue purple'
2122                red = 1
2123                green = 2
2124                blue = 3
2125                verde = green
2126
2127    def test_enum_has_extra_members(self):
2128        with self.assertRaisesRegex(TypeError, 'member order does not match _order_'):
2129            class Color(Enum):
2130                _order_ = 'red green blue'
2131                red = 1
2132                green = 2
2133                blue = 3
2134                purple = 4
2135
2136    def test_enum_has_extra_members_with_aliases(self):
2137        with self.assertRaisesRegex(TypeError, 'member order does not match _order_'):
2138            class Color(Enum):
2139                _order_ = 'red green blue'
2140                red = 1
2141                green = 2
2142                blue = 3
2143                purple = 4
2144                verde = green
2145
2146
2147class TestFlag(unittest.TestCase):
2148    """Tests of the Flags."""
2149
2150    class Perm(Flag):
2151        R, W, X = 4, 2, 1
2152
2153    class Open(Flag):
2154        RO = 0
2155        WO = 1
2156        RW = 2
2157        AC = 3
2158        CE = 1<<19
2159
2160    class Color(Flag):
2161        BLACK = 0
2162        RED = 1
2163        GREEN = 2
2164        BLUE = 4
2165        PURPLE = RED|BLUE
2166
2167    def test_str(self):
2168        Perm = self.Perm
2169        self.assertEqual(str(Perm.R), 'Perm.R')
2170        self.assertEqual(str(Perm.W), 'Perm.W')
2171        self.assertEqual(str(Perm.X), 'Perm.X')
2172        self.assertEqual(str(Perm.R | Perm.W), 'Perm.R|W')
2173        self.assertEqual(str(Perm.R | Perm.W | Perm.X), 'Perm.R|W|X')
2174        self.assertEqual(str(Perm(0)), 'Perm.0')
2175        self.assertEqual(str(~Perm.R), 'Perm.W|X')
2176        self.assertEqual(str(~Perm.W), 'Perm.R|X')
2177        self.assertEqual(str(~Perm.X), 'Perm.R|W')
2178        self.assertEqual(str(~(Perm.R | Perm.W)), 'Perm.X')
2179        self.assertEqual(str(~(Perm.R | Perm.W | Perm.X)), 'Perm.0')
2180        self.assertEqual(str(Perm(~0)), 'Perm.R|W|X')
2181
2182        Open = self.Open
2183        self.assertEqual(str(Open.RO), 'Open.RO')
2184        self.assertEqual(str(Open.WO), 'Open.WO')
2185        self.assertEqual(str(Open.AC), 'Open.AC')
2186        self.assertEqual(str(Open.RO | Open.CE), 'Open.CE')
2187        self.assertEqual(str(Open.WO | Open.CE), 'Open.CE|WO')
2188        self.assertEqual(str(~Open.RO), 'Open.CE|AC|RW|WO')
2189        self.assertEqual(str(~Open.WO), 'Open.CE|RW')
2190        self.assertEqual(str(~Open.AC), 'Open.CE')
2191        self.assertEqual(str(~(Open.RO | Open.CE)), 'Open.AC')
2192        self.assertEqual(str(~(Open.WO | Open.CE)), 'Open.RW')
2193
2194    def test_repr(self):
2195        Perm = self.Perm
2196        self.assertEqual(repr(Perm.R), '<Perm.R: 4>')
2197        self.assertEqual(repr(Perm.W), '<Perm.W: 2>')
2198        self.assertEqual(repr(Perm.X), '<Perm.X: 1>')
2199        self.assertEqual(repr(Perm.R | Perm.W), '<Perm.R|W: 6>')
2200        self.assertEqual(repr(Perm.R | Perm.W | Perm.X), '<Perm.R|W|X: 7>')
2201        self.assertEqual(repr(Perm(0)), '<Perm.0: 0>')
2202        self.assertEqual(repr(~Perm.R), '<Perm.W|X: 3>')
2203        self.assertEqual(repr(~Perm.W), '<Perm.R|X: 5>')
2204        self.assertEqual(repr(~Perm.X), '<Perm.R|W: 6>')
2205        self.assertEqual(repr(~(Perm.R | Perm.W)), '<Perm.X: 1>')
2206        self.assertEqual(repr(~(Perm.R | Perm.W | Perm.X)), '<Perm.0: 0>')
2207        self.assertEqual(repr(Perm(~0)), '<Perm.R|W|X: 7>')
2208
2209        Open = self.Open
2210        self.assertEqual(repr(Open.RO), '<Open.RO: 0>')
2211        self.assertEqual(repr(Open.WO), '<Open.WO: 1>')
2212        self.assertEqual(repr(Open.AC), '<Open.AC: 3>')
2213        self.assertEqual(repr(Open.RO | Open.CE), '<Open.CE: 524288>')
2214        self.assertEqual(repr(Open.WO | Open.CE), '<Open.CE|WO: 524289>')
2215        self.assertEqual(repr(~Open.RO), '<Open.CE|AC|RW|WO: 524291>')
2216        self.assertEqual(repr(~Open.WO), '<Open.CE|RW: 524290>')
2217        self.assertEqual(repr(~Open.AC), '<Open.CE: 524288>')
2218        self.assertEqual(repr(~(Open.RO | Open.CE)), '<Open.AC: 3>')
2219        self.assertEqual(repr(~(Open.WO | Open.CE)), '<Open.RW: 2>')
2220
2221    def test_format(self):
2222        Perm = self.Perm
2223        self.assertEqual(format(Perm.R, ''), 'Perm.R')
2224        self.assertEqual(format(Perm.R | Perm.X, ''), 'Perm.R|X')
2225
2226    def test_or(self):
2227        Perm = self.Perm
2228        for i in Perm:
2229            for j in Perm:
2230                self.assertEqual((i | j), Perm(i.value | j.value))
2231                self.assertEqual((i | j).value, i.value | j.value)
2232                self.assertIs(type(i | j), Perm)
2233        for i in Perm:
2234            self.assertIs(i | i, i)
2235        Open = self.Open
2236        self.assertIs(Open.RO | Open.CE, Open.CE)
2237
2238    def test_and(self):
2239        Perm = self.Perm
2240        RW = Perm.R | Perm.W
2241        RX = Perm.R | Perm.X
2242        WX = Perm.W | Perm.X
2243        RWX = Perm.R | Perm.W | Perm.X
2244        values = list(Perm) + [RW, RX, WX, RWX, Perm(0)]
2245        for i in values:
2246            for j in values:
2247                self.assertEqual((i & j).value, i.value & j.value)
2248                self.assertIs(type(i & j), Perm)
2249        for i in Perm:
2250            self.assertIs(i & i, i)
2251            self.assertIs(i & RWX, i)
2252            self.assertIs(RWX & i, i)
2253        Open = self.Open
2254        self.assertIs(Open.RO & Open.CE, Open.RO)
2255
2256    def test_xor(self):
2257        Perm = self.Perm
2258        for i in Perm:
2259            for j in Perm:
2260                self.assertEqual((i ^ j).value, i.value ^ j.value)
2261                self.assertIs(type(i ^ j), Perm)
2262        for i in Perm:
2263            self.assertIs(i ^ Perm(0), i)
2264            self.assertIs(Perm(0) ^ i, i)
2265        Open = self.Open
2266        self.assertIs(Open.RO ^ Open.CE, Open.CE)
2267        self.assertIs(Open.CE ^ Open.CE, Open.RO)
2268
2269    def test_invert(self):
2270        Perm = self.Perm
2271        RW = Perm.R | Perm.W
2272        RX = Perm.R | Perm.X
2273        WX = Perm.W | Perm.X
2274        RWX = Perm.R | Perm.W | Perm.X
2275        values = list(Perm) + [RW, RX, WX, RWX, Perm(0)]
2276        for i in values:
2277            self.assertIs(type(~i), Perm)
2278            self.assertEqual(~~i, i)
2279        for i in Perm:
2280            self.assertIs(~~i, i)
2281        Open = self.Open
2282        self.assertIs(Open.WO & ~Open.WO, Open.RO)
2283        self.assertIs((Open.WO|Open.CE) & ~Open.WO, Open.CE)
2284
2285    def test_bool(self):
2286        Perm = self.Perm
2287        for f in Perm:
2288            self.assertTrue(f)
2289        Open = self.Open
2290        for f in Open:
2291            self.assertEqual(bool(f.value), bool(f))
2292
2293    def test_programatic_function_string(self):
2294        Perm = Flag('Perm', 'R W X')
2295        lst = list(Perm)
2296        self.assertEqual(len(lst), len(Perm))
2297        self.assertEqual(len(Perm), 3, Perm)
2298        self.assertEqual(lst, [Perm.R, Perm.W, Perm.X])
2299        for i, n in enumerate('R W X'.split()):
2300            v = 1<<i
2301            e = Perm(v)
2302            self.assertEqual(e.value, v)
2303            self.assertEqual(type(e.value), int)
2304            self.assertEqual(e.name, n)
2305            self.assertIn(e, Perm)
2306            self.assertIs(type(e), Perm)
2307
2308    def test_programatic_function_string_with_start(self):
2309        Perm = Flag('Perm', 'R W X', start=8)
2310        lst = list(Perm)
2311        self.assertEqual(len(lst), len(Perm))
2312        self.assertEqual(len(Perm), 3, Perm)
2313        self.assertEqual(lst, [Perm.R, Perm.W, Perm.X])
2314        for i, n in enumerate('R W X'.split()):
2315            v = 8<<i
2316            e = Perm(v)
2317            self.assertEqual(e.value, v)
2318            self.assertEqual(type(e.value), int)
2319            self.assertEqual(e.name, n)
2320            self.assertIn(e, Perm)
2321            self.assertIs(type(e), Perm)
2322
2323    def test_programatic_function_string_list(self):
2324        Perm = Flag('Perm', ['R', 'W', 'X'])
2325        lst = list(Perm)
2326        self.assertEqual(len(lst), len(Perm))
2327        self.assertEqual(len(Perm), 3, Perm)
2328        self.assertEqual(lst, [Perm.R, Perm.W, Perm.X])
2329        for i, n in enumerate('R W X'.split()):
2330            v = 1<<i
2331            e = Perm(v)
2332            self.assertEqual(e.value, v)
2333            self.assertEqual(type(e.value), int)
2334            self.assertEqual(e.name, n)
2335            self.assertIn(e, Perm)
2336            self.assertIs(type(e), Perm)
2337
2338    def test_programatic_function_iterable(self):
2339        Perm = Flag('Perm', (('R', 2), ('W', 8), ('X', 32)))
2340        lst = list(Perm)
2341        self.assertEqual(len(lst), len(Perm))
2342        self.assertEqual(len(Perm), 3, Perm)
2343        self.assertEqual(lst, [Perm.R, Perm.W, Perm.X])
2344        for i, n in enumerate('R W X'.split()):
2345            v = 1<<(2*i+1)
2346            e = Perm(v)
2347            self.assertEqual(e.value, v)
2348            self.assertEqual(type(e.value), int)
2349            self.assertEqual(e.name, n)
2350            self.assertIn(e, Perm)
2351            self.assertIs(type(e), Perm)
2352
2353    def test_programatic_function_from_dict(self):
2354        Perm = Flag('Perm', OrderedDict((('R', 2), ('W', 8), ('X', 32))))
2355        lst = list(Perm)
2356        self.assertEqual(len(lst), len(Perm))
2357        self.assertEqual(len(Perm), 3, Perm)
2358        self.assertEqual(lst, [Perm.R, Perm.W, Perm.X])
2359        for i, n in enumerate('R W X'.split()):
2360            v = 1<<(2*i+1)
2361            e = Perm(v)
2362            self.assertEqual(e.value, v)
2363            self.assertEqual(type(e.value), int)
2364            self.assertEqual(e.name, n)
2365            self.assertIn(e, Perm)
2366            self.assertIs(type(e), Perm)
2367
2368    def test_pickle(self):
2369        if isinstance(FlagStooges, Exception):
2370            raise FlagStooges
2371        test_pickle_dump_load(self.assertIs, FlagStooges.CURLY|FlagStooges.MOE)
2372        test_pickle_dump_load(self.assertIs, FlagStooges)
2373
2374    def test_contains(self):
2375        Open = self.Open
2376        Color = self.Color
2377        self.assertFalse(Color.BLACK in Open)
2378        self.assertFalse(Open.RO in Color)
2379        with self.assertRaises(TypeError):
2380            'BLACK' in Color
2381        with self.assertRaises(TypeError):
2382            'RO' in Open
2383        with self.assertRaises(TypeError):
2384            1 in Color
2385        with self.assertRaises(TypeError):
2386            1 in Open
2387
2388    def test_member_contains(self):
2389        Perm = self.Perm
2390        R, W, X = Perm
2391        RW = R | W
2392        RX = R | X
2393        WX = W | X
2394        RWX = R | W | X
2395        self.assertTrue(R in RW)
2396        self.assertTrue(R in RX)
2397        self.assertTrue(R in RWX)
2398        self.assertTrue(W in RW)
2399        self.assertTrue(W in WX)
2400        self.assertTrue(W in RWX)
2401        self.assertTrue(X in RX)
2402        self.assertTrue(X in WX)
2403        self.assertTrue(X in RWX)
2404        self.assertFalse(R in WX)
2405        self.assertFalse(W in RX)
2406        self.assertFalse(X in RW)
2407
2408    def test_auto_number(self):
2409        class Color(Flag):
2410            red = auto()
2411            blue = auto()
2412            green = auto()
2413
2414        self.assertEqual(list(Color), [Color.red, Color.blue, Color.green])
2415        self.assertEqual(Color.red.value, 1)
2416        self.assertEqual(Color.blue.value, 2)
2417        self.assertEqual(Color.green.value, 4)
2418
2419    def test_auto_number_garbage(self):
2420        with self.assertRaisesRegex(TypeError, 'Invalid Flag value: .not an int.'):
2421            class Color(Flag):
2422                red = 'not an int'
2423                blue = auto()
2424
2425    def test_cascading_failure(self):
2426        class Bizarre(Flag):
2427            c = 3
2428            d = 4
2429            f = 6
2430        # Bizarre.c | Bizarre.d
2431        self.assertRaisesRegex(ValueError, "5 is not a valid Bizarre", Bizarre, 5)
2432        self.assertRaisesRegex(ValueError, "5 is not a valid Bizarre", Bizarre, 5)
2433        self.assertRaisesRegex(ValueError, "2 is not a valid Bizarre", Bizarre, 2)
2434        self.assertRaisesRegex(ValueError, "2 is not a valid Bizarre", Bizarre, 2)
2435        self.assertRaisesRegex(ValueError, "1 is not a valid Bizarre", Bizarre, 1)
2436        self.assertRaisesRegex(ValueError, "1 is not a valid Bizarre", Bizarre, 1)
2437
2438    def test_duplicate_auto(self):
2439        class Dupes(Enum):
2440            first = primero = auto()
2441            second = auto()
2442            third = auto()
2443        self.assertEqual([Dupes.first, Dupes.second, Dupes.third], list(Dupes))
2444
2445    def test_bizarre(self):
2446        class Bizarre(Flag):
2447            b = 3
2448            c = 4
2449            d = 6
2450        self.assertEqual(repr(Bizarre(7)), '<Bizarre.d|c|b: 7>')
2451
2452    def test_multiple_mixin(self):
2453        class AllMixin:
2454            @classproperty
2455            def ALL(cls):
2456                members = list(cls)
2457                all_value = None
2458                if members:
2459                    all_value = members[0]
2460                    for member in members[1:]:
2461                        all_value |= member
2462                cls.ALL = all_value
2463                return all_value
2464        class StrMixin:
2465            def __str__(self):
2466                return self._name_.lower()
2467        class Color(AllMixin, Flag):
2468            RED = auto()
2469            GREEN = auto()
2470            BLUE = auto()
2471        self.assertEqual(Color.RED.value, 1)
2472        self.assertEqual(Color.GREEN.value, 2)
2473        self.assertEqual(Color.BLUE.value, 4)
2474        self.assertEqual(Color.ALL.value, 7)
2475        self.assertEqual(str(Color.BLUE), 'Color.BLUE')
2476        class Color(AllMixin, StrMixin, Flag):
2477            RED = auto()
2478            GREEN = auto()
2479            BLUE = auto()
2480        self.assertEqual(Color.RED.value, 1)
2481        self.assertEqual(Color.GREEN.value, 2)
2482        self.assertEqual(Color.BLUE.value, 4)
2483        self.assertEqual(Color.ALL.value, 7)
2484        self.assertEqual(str(Color.BLUE), 'blue')
2485        class Color(StrMixin, AllMixin, Flag):
2486            RED = auto()
2487            GREEN = auto()
2488            BLUE = auto()
2489        self.assertEqual(Color.RED.value, 1)
2490        self.assertEqual(Color.GREEN.value, 2)
2491        self.assertEqual(Color.BLUE.value, 4)
2492        self.assertEqual(Color.ALL.value, 7)
2493        self.assertEqual(str(Color.BLUE), 'blue')
2494
2495    @support.reap_threads
2496    def test_unique_composite(self):
2497        # override __eq__ to be identity only
2498        class TestFlag(Flag):
2499            one = auto()
2500            two = auto()
2501            three = auto()
2502            four = auto()
2503            five = auto()
2504            six = auto()
2505            seven = auto()
2506            eight = auto()
2507            def __eq__(self, other):
2508                return self is other
2509            def __hash__(self):
2510                return hash(self._value_)
2511        # have multiple threads competing to complete the composite members
2512        seen = set()
2513        failed = False
2514        def cycle_enum():
2515            nonlocal failed
2516            try:
2517                for i in range(256):
2518                    seen.add(TestFlag(i))
2519            except Exception:
2520                failed = True
2521        threads = [
2522                threading.Thread(target=cycle_enum)
2523                for _ in range(8)
2524                ]
2525        with support.start_threads(threads):
2526            pass
2527        # check that only 248 members were created
2528        self.assertFalse(
2529                failed,
2530                'at least one thread failed while creating composite members')
2531        self.assertEqual(256, len(seen), 'too many composite members created')
2532
2533
2534class TestIntFlag(unittest.TestCase):
2535    """Tests of the IntFlags."""
2536
2537    class Perm(IntFlag):
2538        X = 1 << 0
2539        W = 1 << 1
2540        R = 1 << 2
2541
2542    class Open(IntFlag):
2543        RO = 0
2544        WO = 1
2545        RW = 2
2546        AC = 3
2547        CE = 1<<19
2548
2549    class Color(IntFlag):
2550        BLACK = 0
2551        RED = 1
2552        GREEN = 2
2553        BLUE = 4
2554        PURPLE = RED|BLUE
2555
2556    def test_type(self):
2557        Perm = self.Perm
2558        self.assertTrue(Perm._member_type_ is int)
2559        Open = self.Open
2560        for f in Perm:
2561            self.assertTrue(isinstance(f, Perm))
2562            self.assertEqual(f, f.value)
2563        self.assertTrue(isinstance(Perm.W | Perm.X, Perm))
2564        self.assertEqual(Perm.W | Perm.X, 3)
2565        for f in Open:
2566            self.assertTrue(isinstance(f, Open))
2567            self.assertEqual(f, f.value)
2568        self.assertTrue(isinstance(Open.WO | Open.RW, Open))
2569        self.assertEqual(Open.WO | Open.RW, 3)
2570
2571
2572    def test_str(self):
2573        Perm = self.Perm
2574        self.assertEqual(str(Perm.R), 'Perm.R')
2575        self.assertEqual(str(Perm.W), 'Perm.W')
2576        self.assertEqual(str(Perm.X), 'Perm.X')
2577        self.assertEqual(str(Perm.R | Perm.W), 'Perm.R|W')
2578        self.assertEqual(str(Perm.R | Perm.W | Perm.X), 'Perm.R|W|X')
2579        self.assertEqual(str(Perm.R | 8), 'Perm.8|R')
2580        self.assertEqual(str(Perm(0)), 'Perm.0')
2581        self.assertEqual(str(Perm(8)), 'Perm.8')
2582        self.assertEqual(str(~Perm.R), 'Perm.W|X')
2583        self.assertEqual(str(~Perm.W), 'Perm.R|X')
2584        self.assertEqual(str(~Perm.X), 'Perm.R|W')
2585        self.assertEqual(str(~(Perm.R | Perm.W)), 'Perm.X')
2586        self.assertEqual(str(~(Perm.R | Perm.W | Perm.X)), 'Perm.-8')
2587        self.assertEqual(str(~(Perm.R | 8)), 'Perm.W|X')
2588        self.assertEqual(str(Perm(~0)), 'Perm.R|W|X')
2589        self.assertEqual(str(Perm(~8)), 'Perm.R|W|X')
2590
2591        Open = self.Open
2592        self.assertEqual(str(Open.RO), 'Open.RO')
2593        self.assertEqual(str(Open.WO), 'Open.WO')
2594        self.assertEqual(str(Open.AC), 'Open.AC')
2595        self.assertEqual(str(Open.RO | Open.CE), 'Open.CE')
2596        self.assertEqual(str(Open.WO | Open.CE), 'Open.CE|WO')
2597        self.assertEqual(str(Open(4)), 'Open.4')
2598        self.assertEqual(str(~Open.RO), 'Open.CE|AC|RW|WO')
2599        self.assertEqual(str(~Open.WO), 'Open.CE|RW')
2600        self.assertEqual(str(~Open.AC), 'Open.CE')
2601        self.assertEqual(str(~(Open.RO | Open.CE)), 'Open.AC|RW|WO')
2602        self.assertEqual(str(~(Open.WO | Open.CE)), 'Open.RW')
2603        self.assertEqual(str(Open(~4)), 'Open.CE|AC|RW|WO')
2604
2605    def test_repr(self):
2606        Perm = self.Perm
2607        self.assertEqual(repr(Perm.R), '<Perm.R: 4>')
2608        self.assertEqual(repr(Perm.W), '<Perm.W: 2>')
2609        self.assertEqual(repr(Perm.X), '<Perm.X: 1>')
2610        self.assertEqual(repr(Perm.R | Perm.W), '<Perm.R|W: 6>')
2611        self.assertEqual(repr(Perm.R | Perm.W | Perm.X), '<Perm.R|W|X: 7>')
2612        self.assertEqual(repr(Perm.R | 8), '<Perm.8|R: 12>')
2613        self.assertEqual(repr(Perm(0)), '<Perm.0: 0>')
2614        self.assertEqual(repr(Perm(8)), '<Perm.8: 8>')
2615        self.assertEqual(repr(~Perm.R), '<Perm.W|X: -5>')
2616        self.assertEqual(repr(~Perm.W), '<Perm.R|X: -3>')
2617        self.assertEqual(repr(~Perm.X), '<Perm.R|W: -2>')
2618        self.assertEqual(repr(~(Perm.R | Perm.W)), '<Perm.X: -7>')
2619        self.assertEqual(repr(~(Perm.R | Perm.W | Perm.X)), '<Perm.-8: -8>')
2620        self.assertEqual(repr(~(Perm.R | 8)), '<Perm.W|X: -13>')
2621        self.assertEqual(repr(Perm(~0)), '<Perm.R|W|X: -1>')
2622        self.assertEqual(repr(Perm(~8)), '<Perm.R|W|X: -9>')
2623
2624        Open = self.Open
2625        self.assertEqual(repr(Open.RO), '<Open.RO: 0>')
2626        self.assertEqual(repr(Open.WO), '<Open.WO: 1>')
2627        self.assertEqual(repr(Open.AC), '<Open.AC: 3>')
2628        self.assertEqual(repr(Open.RO | Open.CE), '<Open.CE: 524288>')
2629        self.assertEqual(repr(Open.WO | Open.CE), '<Open.CE|WO: 524289>')
2630        self.assertEqual(repr(Open(4)), '<Open.4: 4>')
2631        self.assertEqual(repr(~Open.RO), '<Open.CE|AC|RW|WO: -1>')
2632        self.assertEqual(repr(~Open.WO), '<Open.CE|RW: -2>')
2633        self.assertEqual(repr(~Open.AC), '<Open.CE: -4>')
2634        self.assertEqual(repr(~(Open.RO | Open.CE)), '<Open.AC|RW|WO: -524289>')
2635        self.assertEqual(repr(~(Open.WO | Open.CE)), '<Open.RW: -524290>')
2636        self.assertEqual(repr(Open(~4)), '<Open.CE|AC|RW|WO: -5>')
2637
2638    def test_format(self):
2639        Perm = self.Perm
2640        self.assertEqual(format(Perm.R, ''), '4')
2641        self.assertEqual(format(Perm.R | Perm.X, ''), '5')
2642
2643    def test_or(self):
2644        Perm = self.Perm
2645        for i in Perm:
2646            for j in Perm:
2647                self.assertEqual(i | j, i.value | j.value)
2648                self.assertEqual((i | j).value, i.value | j.value)
2649                self.assertIs(type(i | j), Perm)
2650            for j in range(8):
2651                self.assertEqual(i | j, i.value | j)
2652                self.assertEqual((i | j).value, i.value | j)
2653                self.assertIs(type(i | j), Perm)
2654                self.assertEqual(j | i, j | i.value)
2655                self.assertEqual((j | i).value, j | i.value)
2656                self.assertIs(type(j | i), Perm)
2657        for i in Perm:
2658            self.assertIs(i | i, i)
2659            self.assertIs(i | 0, i)
2660            self.assertIs(0 | i, i)
2661        Open = self.Open
2662        self.assertIs(Open.RO | Open.CE, Open.CE)
2663
2664    def test_and(self):
2665        Perm = self.Perm
2666        RW = Perm.R | Perm.W
2667        RX = Perm.R | Perm.X
2668        WX = Perm.W | Perm.X
2669        RWX = Perm.R | Perm.W | Perm.X
2670        values = list(Perm) + [RW, RX, WX, RWX, Perm(0)]
2671        for i in values:
2672            for j in values:
2673                self.assertEqual(i & j, i.value & j.value, 'i is %r, j is %r' % (i, j))
2674                self.assertEqual((i & j).value, i.value & j.value, 'i is %r, j is %r' % (i, j))
2675                self.assertIs(type(i & j), Perm, 'i is %r, j is %r' % (i, j))
2676            for j in range(8):
2677                self.assertEqual(i & j, i.value & j)
2678                self.assertEqual((i & j).value, i.value & j)
2679                self.assertIs(type(i & j), Perm)
2680                self.assertEqual(j & i, j & i.value)
2681                self.assertEqual((j & i).value, j & i.value)
2682                self.assertIs(type(j & i), Perm)
2683        for i in Perm:
2684            self.assertIs(i & i, i)
2685            self.assertIs(i & 7, i)
2686            self.assertIs(7 & i, i)
2687        Open = self.Open
2688        self.assertIs(Open.RO & Open.CE, Open.RO)
2689
2690    def test_xor(self):
2691        Perm = self.Perm
2692        for i in Perm:
2693            for j in Perm:
2694                self.assertEqual(i ^ j, i.value ^ j.value)
2695                self.assertEqual((i ^ j).value, i.value ^ j.value)
2696                self.assertIs(type(i ^ j), Perm)
2697            for j in range(8):
2698                self.assertEqual(i ^ j, i.value ^ j)
2699                self.assertEqual((i ^ j).value, i.value ^ j)
2700                self.assertIs(type(i ^ j), Perm)
2701                self.assertEqual(j ^ i, j ^ i.value)
2702                self.assertEqual((j ^ i).value, j ^ i.value)
2703                self.assertIs(type(j ^ i), Perm)
2704        for i in Perm:
2705            self.assertIs(i ^ 0, i)
2706            self.assertIs(0 ^ i, i)
2707        Open = self.Open
2708        self.assertIs(Open.RO ^ Open.CE, Open.CE)
2709        self.assertIs(Open.CE ^ Open.CE, Open.RO)
2710
2711    def test_invert(self):
2712        Perm = self.Perm
2713        RW = Perm.R | Perm.W
2714        RX = Perm.R | Perm.X
2715        WX = Perm.W | Perm.X
2716        RWX = Perm.R | Perm.W | Perm.X
2717        values = list(Perm) + [RW, RX, WX, RWX, Perm(0)]
2718        for i in values:
2719            self.assertEqual(~i, ~i.value)
2720            self.assertEqual((~i).value, ~i.value)
2721            self.assertIs(type(~i), Perm)
2722            self.assertEqual(~~i, i)
2723        for i in Perm:
2724            self.assertIs(~~i, i)
2725        Open = self.Open
2726        self.assertIs(Open.WO & ~Open.WO, Open.RO)
2727        self.assertIs((Open.WO|Open.CE) & ~Open.WO, Open.CE)
2728
2729    def test_programatic_function_string(self):
2730        Perm = IntFlag('Perm', 'R W X')
2731        lst = list(Perm)
2732        self.assertEqual(len(lst), len(Perm))
2733        self.assertEqual(len(Perm), 3, Perm)
2734        self.assertEqual(lst, [Perm.R, Perm.W, Perm.X])
2735        for i, n in enumerate('R W X'.split()):
2736            v = 1<<i
2737            e = Perm(v)
2738            self.assertEqual(e.value, v)
2739            self.assertEqual(type(e.value), int)
2740            self.assertEqual(e, v)
2741            self.assertEqual(e.name, n)
2742            self.assertIn(e, Perm)
2743            self.assertIs(type(e), Perm)
2744
2745    def test_programatic_function_string_with_start(self):
2746        Perm = IntFlag('Perm', 'R W X', start=8)
2747        lst = list(Perm)
2748        self.assertEqual(len(lst), len(Perm))
2749        self.assertEqual(len(Perm), 3, Perm)
2750        self.assertEqual(lst, [Perm.R, Perm.W, Perm.X])
2751        for i, n in enumerate('R W X'.split()):
2752            v = 8<<i
2753            e = Perm(v)
2754            self.assertEqual(e.value, v)
2755            self.assertEqual(type(e.value), int)
2756            self.assertEqual(e, v)
2757            self.assertEqual(e.name, n)
2758            self.assertIn(e, Perm)
2759            self.assertIs(type(e), Perm)
2760
2761    def test_programatic_function_string_list(self):
2762        Perm = IntFlag('Perm', ['R', 'W', 'X'])
2763        lst = list(Perm)
2764        self.assertEqual(len(lst), len(Perm))
2765        self.assertEqual(len(Perm), 3, Perm)
2766        self.assertEqual(lst, [Perm.R, Perm.W, Perm.X])
2767        for i, n in enumerate('R W X'.split()):
2768            v = 1<<i
2769            e = Perm(v)
2770            self.assertEqual(e.value, v)
2771            self.assertEqual(type(e.value), int)
2772            self.assertEqual(e, v)
2773            self.assertEqual(e.name, n)
2774            self.assertIn(e, Perm)
2775            self.assertIs(type(e), Perm)
2776
2777    def test_programatic_function_iterable(self):
2778        Perm = IntFlag('Perm', (('R', 2), ('W', 8), ('X', 32)))
2779        lst = list(Perm)
2780        self.assertEqual(len(lst), len(Perm))
2781        self.assertEqual(len(Perm), 3, Perm)
2782        self.assertEqual(lst, [Perm.R, Perm.W, Perm.X])
2783        for i, n in enumerate('R W X'.split()):
2784            v = 1<<(2*i+1)
2785            e = Perm(v)
2786            self.assertEqual(e.value, v)
2787            self.assertEqual(type(e.value), int)
2788            self.assertEqual(e, v)
2789            self.assertEqual(e.name, n)
2790            self.assertIn(e, Perm)
2791            self.assertIs(type(e), Perm)
2792
2793    def test_programatic_function_from_dict(self):
2794        Perm = IntFlag('Perm', OrderedDict((('R', 2), ('W', 8), ('X', 32))))
2795        lst = list(Perm)
2796        self.assertEqual(len(lst), len(Perm))
2797        self.assertEqual(len(Perm), 3, Perm)
2798        self.assertEqual(lst, [Perm.R, Perm.W, Perm.X])
2799        for i, n in enumerate('R W X'.split()):
2800            v = 1<<(2*i+1)
2801            e = Perm(v)
2802            self.assertEqual(e.value, v)
2803            self.assertEqual(type(e.value), int)
2804            self.assertEqual(e, v)
2805            self.assertEqual(e.name, n)
2806            self.assertIn(e, Perm)
2807            self.assertIs(type(e), Perm)
2808
2809
2810    def test_programatic_function_from_empty_list(self):
2811        Perm = enum.IntFlag('Perm', [])
2812        lst = list(Perm)
2813        self.assertEqual(len(lst), len(Perm))
2814        self.assertEqual(len(Perm), 0, Perm)
2815        Thing = enum.Enum('Thing', [])
2816        lst = list(Thing)
2817        self.assertEqual(len(lst), len(Thing))
2818        self.assertEqual(len(Thing), 0, Thing)
2819
2820
2821    def test_programatic_function_from_empty_tuple(self):
2822        Perm = enum.IntFlag('Perm', ())
2823        lst = list(Perm)
2824        self.assertEqual(len(lst), len(Perm))
2825        self.assertEqual(len(Perm), 0, Perm)
2826        Thing = enum.Enum('Thing', ())
2827        self.assertEqual(len(lst), len(Thing))
2828        self.assertEqual(len(Thing), 0, Thing)
2829
2830    def test_contains(self):
2831        Open = self.Open
2832        Color = self.Color
2833        self.assertTrue(Color.GREEN in Color)
2834        self.assertTrue(Open.RW in Open)
2835        self.assertFalse(Color.GREEN in Open)
2836        self.assertFalse(Open.RW in Color)
2837        with self.assertRaises(TypeError):
2838            'GREEN' in Color
2839        with self.assertRaises(TypeError):
2840            'RW' in Open
2841        with self.assertRaises(TypeError):
2842            2 in Color
2843        with self.assertRaises(TypeError):
2844            2 in Open
2845
2846    def test_member_contains(self):
2847        Perm = self.Perm
2848        R, W, X = Perm
2849        RW = R | W
2850        RX = R | X
2851        WX = W | X
2852        RWX = R | W | X
2853        self.assertTrue(R in RW)
2854        self.assertTrue(R in RX)
2855        self.assertTrue(R in RWX)
2856        self.assertTrue(W in RW)
2857        self.assertTrue(W in WX)
2858        self.assertTrue(W in RWX)
2859        self.assertTrue(X in RX)
2860        self.assertTrue(X in WX)
2861        self.assertTrue(X in RWX)
2862        self.assertFalse(R in WX)
2863        self.assertFalse(W in RX)
2864        self.assertFalse(X in RW)
2865        with self.assertRaises(TypeError):
2866            self.assertFalse('test' in RW)
2867
2868    def test_bool(self):
2869        Perm = self.Perm
2870        for f in Perm:
2871            self.assertTrue(f)
2872        Open = self.Open
2873        for f in Open:
2874            self.assertEqual(bool(f.value), bool(f))
2875
2876    def test_multiple_mixin(self):
2877        class AllMixin:
2878            @classproperty
2879            def ALL(cls):
2880                members = list(cls)
2881                all_value = None
2882                if members:
2883                    all_value = members[0]
2884                    for member in members[1:]:
2885                        all_value |= member
2886                cls.ALL = all_value
2887                return all_value
2888        class StrMixin:
2889            def __str__(self):
2890                return self._name_.lower()
2891        class Color(AllMixin, IntFlag):
2892            RED = auto()
2893            GREEN = auto()
2894            BLUE = auto()
2895        self.assertEqual(Color.RED.value, 1)
2896        self.assertEqual(Color.GREEN.value, 2)
2897        self.assertEqual(Color.BLUE.value, 4)
2898        self.assertEqual(Color.ALL.value, 7)
2899        self.assertEqual(str(Color.BLUE), 'Color.BLUE')
2900        class Color(AllMixin, StrMixin, IntFlag):
2901            RED = auto()
2902            GREEN = auto()
2903            BLUE = auto()
2904        self.assertEqual(Color.RED.value, 1)
2905        self.assertEqual(Color.GREEN.value, 2)
2906        self.assertEqual(Color.BLUE.value, 4)
2907        self.assertEqual(Color.ALL.value, 7)
2908        self.assertEqual(str(Color.BLUE), 'blue')
2909        class Color(StrMixin, AllMixin, IntFlag):
2910            RED = auto()
2911            GREEN = auto()
2912            BLUE = auto()
2913        self.assertEqual(Color.RED.value, 1)
2914        self.assertEqual(Color.GREEN.value, 2)
2915        self.assertEqual(Color.BLUE.value, 4)
2916        self.assertEqual(Color.ALL.value, 7)
2917        self.assertEqual(str(Color.BLUE), 'blue')
2918
2919    @support.reap_threads
2920    def test_unique_composite(self):
2921        # override __eq__ to be identity only
2922        class TestFlag(IntFlag):
2923            one = auto()
2924            two = auto()
2925            three = auto()
2926            four = auto()
2927            five = auto()
2928            six = auto()
2929            seven = auto()
2930            eight = auto()
2931            def __eq__(self, other):
2932                return self is other
2933            def __hash__(self):
2934                return hash(self._value_)
2935        # have multiple threads competing to complete the composite members
2936        seen = set()
2937        failed = False
2938        def cycle_enum():
2939            nonlocal failed
2940            try:
2941                for i in range(256):
2942                    seen.add(TestFlag(i))
2943            except Exception:
2944                failed = True
2945        threads = [
2946                threading.Thread(target=cycle_enum)
2947                for _ in range(8)
2948                ]
2949        with support.start_threads(threads):
2950            pass
2951        # check that only 248 members were created
2952        self.assertFalse(
2953                failed,
2954                'at least one thread failed while creating composite members')
2955        self.assertEqual(256, len(seen), 'too many composite members created')
2956
2957
2958class TestEmptyAndNonLatinStrings(unittest.TestCase):
2959
2960    def test_empty_string(self):
2961        with self.assertRaises(ValueError):
2962            empty_abc = Enum('empty_abc', ('', 'B', 'C'))
2963
2964    def test_non_latin_character_string(self):
2965        greek_abc = Enum('greek_abc', ('\u03B1', 'B', 'C'))
2966        item = getattr(greek_abc, '\u03B1')
2967        self.assertEqual(item.value, 1)
2968
2969    def test_non_latin_number_string(self):
2970        hebrew_123 = Enum('hebrew_123', ('\u05D0', '2', '3'))
2971        item = getattr(hebrew_123, '\u05D0')
2972        self.assertEqual(item.value, 1)
2973
2974
2975class TestUnique(unittest.TestCase):
2976
2977    def test_unique_clean(self):
2978        @unique
2979        class Clean(Enum):
2980            one = 1
2981            two = 'dos'
2982            tres = 4.0
2983        @unique
2984        class Cleaner(IntEnum):
2985            single = 1
2986            double = 2
2987            triple = 3
2988
2989    def test_unique_dirty(self):
2990        with self.assertRaisesRegex(ValueError, 'tres.*one'):
2991            @unique
2992            class Dirty(Enum):
2993                one = 1
2994                two = 'dos'
2995                tres = 1
2996        with self.assertRaisesRegex(
2997                ValueError,
2998                'double.*single.*turkey.*triple',
2999                ):
3000            @unique
3001            class Dirtier(IntEnum):
3002                single = 1
3003                double = 1
3004                triple = 3
3005                turkey = 3
3006
3007    def test_unique_with_name(self):
3008        @unique
3009        class Silly(Enum):
3010            one = 1
3011            two = 'dos'
3012            name = 3
3013        @unique
3014        class Sillier(IntEnum):
3015            single = 1
3016            name = 2
3017            triple = 3
3018            value = 4
3019
3020
3021
3022expected_help_output_with_docs = """\
3023Help on class Color in module %s:
3024
3025class Color(enum.Enum)
3026 |  Color(value, names=None, *, module=None, qualname=None, type=None, start=1)
3027 |\x20\x20
3028 |  An enumeration.
3029 |\x20\x20
3030 |  Method resolution order:
3031 |      Color
3032 |      enum.Enum
3033 |      builtins.object
3034 |\x20\x20
3035 |  Data and other attributes defined here:
3036 |\x20\x20
3037 |  blue = <Color.blue: 3>
3038 |\x20\x20
3039 |  green = <Color.green: 2>
3040 |\x20\x20
3041 |  red = <Color.red: 1>
3042 |\x20\x20
3043 |  ----------------------------------------------------------------------
3044 |  Data descriptors inherited from enum.Enum:
3045 |\x20\x20
3046 |  name
3047 |      The name of the Enum member.
3048 |\x20\x20
3049 |  value
3050 |      The value of the Enum member.
3051 |\x20\x20
3052 |  ----------------------------------------------------------------------
3053 |  Readonly properties inherited from enum.EnumMeta:
3054 |\x20\x20
3055 |  __members__
3056 |      Returns a mapping of member name->value.
3057 |\x20\x20\x20\x20\x20\x20
3058 |      This mapping lists all enum members, including aliases. Note that this
3059 |      is a read-only view of the internal mapping."""
3060
3061expected_help_output_without_docs = """\
3062Help on class Color in module %s:
3063
3064class Color(enum.Enum)
3065 |  Color(value, names=None, *, module=None, qualname=None, type=None, start=1)
3066 |\x20\x20
3067 |  Method resolution order:
3068 |      Color
3069 |      enum.Enum
3070 |      builtins.object
3071 |\x20\x20
3072 |  Data and other attributes defined here:
3073 |\x20\x20
3074 |  blue = <Color.blue: 3>
3075 |\x20\x20
3076 |  green = <Color.green: 2>
3077 |\x20\x20
3078 |  red = <Color.red: 1>
3079 |\x20\x20
3080 |  ----------------------------------------------------------------------
3081 |  Data descriptors inherited from enum.Enum:
3082 |\x20\x20
3083 |  name
3084 |\x20\x20
3085 |  value
3086 |\x20\x20
3087 |  ----------------------------------------------------------------------
3088 |  Data descriptors inherited from enum.EnumMeta:
3089 |\x20\x20
3090 |  __members__"""
3091
3092class TestStdLib(unittest.TestCase):
3093
3094    maxDiff = None
3095
3096    class Color(Enum):
3097        red = 1
3098        green = 2
3099        blue = 3
3100
3101    def test_pydoc(self):
3102        # indirectly test __objclass__
3103        if StrEnum.__doc__ is None:
3104            expected_text = expected_help_output_without_docs % __name__
3105        else:
3106            expected_text = expected_help_output_with_docs % __name__
3107        output = StringIO()
3108        helper = pydoc.Helper(output=output)
3109        helper(self.Color)
3110        result = output.getvalue().strip()
3111        self.assertEqual(result, expected_text)
3112
3113    def test_inspect_getmembers(self):
3114        values = dict((
3115                ('__class__', EnumMeta),
3116                ('__doc__', 'An enumeration.'),
3117                ('__members__', self.Color.__members__),
3118                ('__module__', __name__),
3119                ('blue', self.Color.blue),
3120                ('green', self.Color.green),
3121                ('name', Enum.__dict__['name']),
3122                ('red', self.Color.red),
3123                ('value', Enum.__dict__['value']),
3124                ))
3125        result = dict(inspect.getmembers(self.Color))
3126        self.assertEqual(values.keys(), result.keys())
3127        failed = False
3128        for k in values.keys():
3129            if result[k] != values[k]:
3130                print()
3131                print('\n%s\n     key: %s\n  result: %s\nexpected: %s\n%s\n' %
3132                        ('=' * 75, k, result[k], values[k], '=' * 75), sep='')
3133                failed = True
3134        if failed:
3135            self.fail("result does not equal expected, see print above")
3136
3137    def test_inspect_classify_class_attrs(self):
3138        # indirectly test __objclass__
3139        from inspect import Attribute
3140        values = [
3141                Attribute(name='__class__', kind='data',
3142                    defining_class=object, object=EnumMeta),
3143                Attribute(name='__doc__', kind='data',
3144                    defining_class=self.Color, object='An enumeration.'),
3145                Attribute(name='__members__', kind='property',
3146                    defining_class=EnumMeta, object=EnumMeta.__members__),
3147                Attribute(name='__module__', kind='data',
3148                    defining_class=self.Color, object=__name__),
3149                Attribute(name='blue', kind='data',
3150                    defining_class=self.Color, object=self.Color.blue),
3151                Attribute(name='green', kind='data',
3152                    defining_class=self.Color, object=self.Color.green),
3153                Attribute(name='red', kind='data',
3154                    defining_class=self.Color, object=self.Color.red),
3155                Attribute(name='name', kind='data',
3156                    defining_class=Enum, object=Enum.__dict__['name']),
3157                Attribute(name='value', kind='data',
3158                    defining_class=Enum, object=Enum.__dict__['value']),
3159                ]
3160        values.sort(key=lambda item: item.name)
3161        result = list(inspect.classify_class_attrs(self.Color))
3162        result.sort(key=lambda item: item.name)
3163        failed = False
3164        for v, r in zip(values, result):
3165            if r != v:
3166                print('\n%s\n%s\n%s\n%s\n' % ('=' * 75, r, v, '=' * 75), sep='')
3167                failed = True
3168        if failed:
3169            self.fail("result does not equal expected, see print above")
3170
3171
3172class MiscTestCase(unittest.TestCase):
3173    def test__all__(self):
3174        support.check__all__(self, enum)
3175
3176
3177# These are unordered here on purpose to ensure that declaration order
3178# makes no difference.
3179CONVERT_TEST_NAME_D = 5
3180CONVERT_TEST_NAME_C = 5
3181CONVERT_TEST_NAME_B = 5
3182CONVERT_TEST_NAME_A = 5  # This one should sort first.
3183CONVERT_TEST_NAME_E = 5
3184CONVERT_TEST_NAME_F = 5
3185
3186class TestIntEnumConvert(unittest.TestCase):
3187    def test_convert_value_lookup_priority(self):
3188        test_type = enum.IntEnum._convert_(
3189                'UnittestConvert',
3190                ('test.test_enum', '__main__')[__name__=='__main__'],
3191                filter=lambda x: x.startswith('CONVERT_TEST_'))
3192        # We don't want the reverse lookup value to vary when there are
3193        # multiple possible names for a given value.  It should always
3194        # report the first lexigraphical name in that case.
3195        self.assertEqual(test_type(5).name, 'CONVERT_TEST_NAME_A')
3196
3197    def test_convert(self):
3198        test_type = enum.IntEnum._convert_(
3199                'UnittestConvert',
3200                ('test.test_enum', '__main__')[__name__=='__main__'],
3201                filter=lambda x: x.startswith('CONVERT_TEST_'))
3202        # Ensure that test_type has all of the desired names and values.
3203        self.assertEqual(test_type.CONVERT_TEST_NAME_F,
3204                         test_type.CONVERT_TEST_NAME_A)
3205        self.assertEqual(test_type.CONVERT_TEST_NAME_B, 5)
3206        self.assertEqual(test_type.CONVERT_TEST_NAME_C, 5)
3207        self.assertEqual(test_type.CONVERT_TEST_NAME_D, 5)
3208        self.assertEqual(test_type.CONVERT_TEST_NAME_E, 5)
3209        # Ensure that test_type only picked up names matching the filter.
3210        self.assertEqual([name for name in dir(test_type)
3211                          if name[0:2] not in ('CO', '__')],
3212                         [], msg='Names other than CONVERT_TEST_* found.')
3213
3214    @unittest.skipUnless(sys.version_info[:2] == (3, 8),
3215                         '_convert was deprecated in 3.8')
3216    def test_convert_warn(self):
3217        with self.assertWarns(DeprecationWarning):
3218            enum.IntEnum._convert(
3219                'UnittestConvert',
3220                ('test.test_enum', '__main__')[__name__=='__main__'],
3221                filter=lambda x: x.startswith('CONVERT_TEST_'))
3222
3223    @unittest.skipUnless(sys.version_info >= (3, 9),
3224                         '_convert was removed in 3.9')
3225    def test_convert_raise(self):
3226        with self.assertRaises(AttributeError):
3227            enum.IntEnum._convert(
3228                'UnittestConvert',
3229                ('test.test_enum', '__main__')[__name__=='__main__'],
3230                filter=lambda x: x.startswith('CONVERT_TEST_'))
3231
3232
3233if __name__ == '__main__':
3234    unittest.main()
3235