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