• 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_auto_order(self):
1706        with self.assertRaises(TypeError):
1707            class Color(Enum):
1708                red = auto()
1709                green = auto()
1710                blue = auto()
1711                def _generate_next_value_(name, start, count, last):
1712                    return name
1713
1714
1715    def test_duplicate_auto(self):
1716        class Dupes(Enum):
1717            first = primero = auto()
1718            second = auto()
1719            third = auto()
1720        self.assertEqual([Dupes.first, Dupes.second, Dupes.third], list(Dupes))
1721
1722    def test_missing(self):
1723        class Color(Enum):
1724            red = 1
1725            green = 2
1726            blue = 3
1727            @classmethod
1728            def _missing_(cls, item):
1729                if item == 'three':
1730                    return cls.blue
1731                elif item == 'bad return':
1732                    # trigger internal error
1733                    return 5
1734                elif item == 'error out':
1735                    raise ZeroDivisionError
1736                else:
1737                    # trigger not found
1738                    return None
1739        self.assertIs(Color('three'), Color.blue)
1740        self.assertRaises(ValueError, Color, 7)
1741        try:
1742            Color('bad return')
1743        except TypeError as exc:
1744            self.assertTrue(isinstance(exc.__context__, ValueError))
1745        else:
1746            raise Exception('Exception not raised.')
1747        try:
1748            Color('error out')
1749        except ZeroDivisionError as exc:
1750            self.assertTrue(isinstance(exc.__context__, ValueError))
1751        else:
1752            raise Exception('Exception not raised.')
1753
1754    def test_multiple_mixin(self):
1755        class MaxMixin:
1756            @classproperty
1757            def MAX(cls):
1758                max = len(cls)
1759                cls.MAX = max
1760                return max
1761        class StrMixin:
1762            def __str__(self):
1763                return self._name_.lower()
1764        class SomeEnum(Enum):
1765            def behavior(self):
1766                return 'booyah'
1767        class AnotherEnum(Enum):
1768            def behavior(self):
1769                return 'nuhuh!'
1770            def social(self):
1771                return "what's up?"
1772        class Color(MaxMixin, Enum):
1773            RED = auto()
1774            GREEN = auto()
1775            BLUE = auto()
1776        self.assertEqual(Color.RED.value, 1)
1777        self.assertEqual(Color.GREEN.value, 2)
1778        self.assertEqual(Color.BLUE.value, 3)
1779        self.assertEqual(Color.MAX, 3)
1780        self.assertEqual(str(Color.BLUE), 'Color.BLUE')
1781        class Color(MaxMixin, StrMixin, Enum):
1782            RED = auto()
1783            GREEN = auto()
1784            BLUE = auto()
1785        self.assertEqual(Color.RED.value, 1)
1786        self.assertEqual(Color.GREEN.value, 2)
1787        self.assertEqual(Color.BLUE.value, 3)
1788        self.assertEqual(Color.MAX, 3)
1789        self.assertEqual(str(Color.BLUE), 'blue')
1790        class Color(StrMixin, MaxMixin, Enum):
1791            RED = auto()
1792            GREEN = auto()
1793            BLUE = auto()
1794        self.assertEqual(Color.RED.value, 1)
1795        self.assertEqual(Color.GREEN.value, 2)
1796        self.assertEqual(Color.BLUE.value, 3)
1797        self.assertEqual(Color.MAX, 3)
1798        self.assertEqual(str(Color.BLUE), 'blue')
1799        class CoolColor(StrMixin, SomeEnum, Enum):
1800            RED = auto()
1801            GREEN = auto()
1802            BLUE = auto()
1803        self.assertEqual(CoolColor.RED.value, 1)
1804        self.assertEqual(CoolColor.GREEN.value, 2)
1805        self.assertEqual(CoolColor.BLUE.value, 3)
1806        self.assertEqual(str(CoolColor.BLUE), 'blue')
1807        self.assertEqual(CoolColor.RED.behavior(), 'booyah')
1808        class CoolerColor(StrMixin, AnotherEnum, Enum):
1809            RED = auto()
1810            GREEN = auto()
1811            BLUE = auto()
1812        self.assertEqual(CoolerColor.RED.value, 1)
1813        self.assertEqual(CoolerColor.GREEN.value, 2)
1814        self.assertEqual(CoolerColor.BLUE.value, 3)
1815        self.assertEqual(str(CoolerColor.BLUE), 'blue')
1816        self.assertEqual(CoolerColor.RED.behavior(), 'nuhuh!')
1817        self.assertEqual(CoolerColor.RED.social(), "what's up?")
1818        class CoolestColor(StrMixin, SomeEnum, AnotherEnum):
1819            RED = auto()
1820            GREEN = auto()
1821            BLUE = auto()
1822        self.assertEqual(CoolestColor.RED.value, 1)
1823        self.assertEqual(CoolestColor.GREEN.value, 2)
1824        self.assertEqual(CoolestColor.BLUE.value, 3)
1825        self.assertEqual(str(CoolestColor.BLUE), 'blue')
1826        self.assertEqual(CoolestColor.RED.behavior(), 'booyah')
1827        self.assertEqual(CoolestColor.RED.social(), "what's up?")
1828        class ConfusedColor(StrMixin, AnotherEnum, SomeEnum):
1829            RED = auto()
1830            GREEN = auto()
1831            BLUE = auto()
1832        self.assertEqual(ConfusedColor.RED.value, 1)
1833        self.assertEqual(ConfusedColor.GREEN.value, 2)
1834        self.assertEqual(ConfusedColor.BLUE.value, 3)
1835        self.assertEqual(str(ConfusedColor.BLUE), 'blue')
1836        self.assertEqual(ConfusedColor.RED.behavior(), 'nuhuh!')
1837        self.assertEqual(ConfusedColor.RED.social(), "what's up?")
1838        class ReformedColor(StrMixin, IntEnum, SomeEnum, AnotherEnum):
1839            RED = auto()
1840            GREEN = auto()
1841            BLUE = auto()
1842        self.assertEqual(ReformedColor.RED.value, 1)
1843        self.assertEqual(ReformedColor.GREEN.value, 2)
1844        self.assertEqual(ReformedColor.BLUE.value, 3)
1845        self.assertEqual(str(ReformedColor.BLUE), 'blue')
1846        self.assertEqual(ReformedColor.RED.behavior(), 'booyah')
1847        self.assertEqual(ConfusedColor.RED.social(), "what's up?")
1848        self.assertTrue(issubclass(ReformedColor, int))
1849
1850    def test_multiple_inherited_mixin(self):
1851        class StrEnum(str, Enum):
1852            def __new__(cls, *args, **kwargs):
1853                for a in args:
1854                    if not isinstance(a, str):
1855                        raise TypeError("Enumeration '%s' (%s) is not"
1856                                        " a string" % (a, type(a).__name__))
1857                return str.__new__(cls, *args, **kwargs)
1858        @unique
1859        class Decision1(StrEnum):
1860            REVERT = "REVERT"
1861            REVERT_ALL = "REVERT_ALL"
1862            RETRY = "RETRY"
1863        class MyEnum(StrEnum):
1864            pass
1865        @unique
1866        class Decision2(MyEnum):
1867            REVERT = "REVERT"
1868            REVERT_ALL = "REVERT_ALL"
1869            RETRY = "RETRY"
1870
1871    def test_empty_globals(self):
1872        # bpo-35717: sys._getframe(2).f_globals['__name__'] fails with KeyError
1873        # when using compile and exec because f_globals is empty
1874        code = "from enum import Enum; Enum('Animal', 'ANT BEE CAT DOG')"
1875        code = compile(code, "<string>", "exec")
1876        global_ns = {}
1877        local_ls = {}
1878        exec(code, global_ns, local_ls)
1879
1880
1881class TestOrder(unittest.TestCase):
1882
1883    def test_same_members(self):
1884        class Color(Enum):
1885            _order_ = 'red green blue'
1886            red = 1
1887            green = 2
1888            blue = 3
1889
1890    def test_same_members_with_aliases(self):
1891        class Color(Enum):
1892            _order_ = 'red green blue'
1893            red = 1
1894            green = 2
1895            blue = 3
1896            verde = green
1897
1898    def test_same_members_wrong_order(self):
1899        with self.assertRaisesRegex(TypeError, 'member order does not match _order_'):
1900            class Color(Enum):
1901                _order_ = 'red green blue'
1902                red = 1
1903                blue = 3
1904                green = 2
1905
1906    def test_order_has_extra_members(self):
1907        with self.assertRaisesRegex(TypeError, 'member order does not match _order_'):
1908            class Color(Enum):
1909                _order_ = 'red green blue purple'
1910                red = 1
1911                green = 2
1912                blue = 3
1913
1914    def test_order_has_extra_members_with_aliases(self):
1915        with self.assertRaisesRegex(TypeError, 'member order does not match _order_'):
1916            class Color(Enum):
1917                _order_ = 'red green blue purple'
1918                red = 1
1919                green = 2
1920                blue = 3
1921                verde = green
1922
1923    def test_enum_has_extra_members(self):
1924        with self.assertRaisesRegex(TypeError, 'member order does not match _order_'):
1925            class Color(Enum):
1926                _order_ = 'red green blue'
1927                red = 1
1928                green = 2
1929                blue = 3
1930                purple = 4
1931
1932    def test_enum_has_extra_members_with_aliases(self):
1933        with self.assertRaisesRegex(TypeError, 'member order does not match _order_'):
1934            class Color(Enum):
1935                _order_ = 'red green blue'
1936                red = 1
1937                green = 2
1938                blue = 3
1939                purple = 4
1940                verde = green
1941
1942
1943class TestFlag(unittest.TestCase):
1944    """Tests of the Flags."""
1945
1946    class Perm(Flag):
1947        R, W, X = 4, 2, 1
1948
1949    class Open(Flag):
1950        RO = 0
1951        WO = 1
1952        RW = 2
1953        AC = 3
1954        CE = 1<<19
1955
1956    class Color(Flag):
1957        BLACK = 0
1958        RED = 1
1959        GREEN = 2
1960        BLUE = 4
1961        PURPLE = RED|BLUE
1962
1963    def test_str(self):
1964        Perm = self.Perm
1965        self.assertEqual(str(Perm.R), 'Perm.R')
1966        self.assertEqual(str(Perm.W), 'Perm.W')
1967        self.assertEqual(str(Perm.X), 'Perm.X')
1968        self.assertEqual(str(Perm.R | Perm.W), 'Perm.R|W')
1969        self.assertEqual(str(Perm.R | Perm.W | Perm.X), 'Perm.R|W|X')
1970        self.assertEqual(str(Perm(0)), 'Perm.0')
1971        self.assertEqual(str(~Perm.R), 'Perm.W|X')
1972        self.assertEqual(str(~Perm.W), 'Perm.R|X')
1973        self.assertEqual(str(~Perm.X), 'Perm.R|W')
1974        self.assertEqual(str(~(Perm.R | Perm.W)), 'Perm.X')
1975        self.assertEqual(str(~(Perm.R | Perm.W | Perm.X)), 'Perm.0')
1976        self.assertEqual(str(Perm(~0)), 'Perm.R|W|X')
1977
1978        Open = self.Open
1979        self.assertEqual(str(Open.RO), 'Open.RO')
1980        self.assertEqual(str(Open.WO), 'Open.WO')
1981        self.assertEqual(str(Open.AC), 'Open.AC')
1982        self.assertEqual(str(Open.RO | Open.CE), 'Open.CE')
1983        self.assertEqual(str(Open.WO | Open.CE), 'Open.CE|WO')
1984        self.assertEqual(str(~Open.RO), 'Open.CE|AC|RW|WO')
1985        self.assertEqual(str(~Open.WO), 'Open.CE|RW')
1986        self.assertEqual(str(~Open.AC), 'Open.CE')
1987        self.assertEqual(str(~(Open.RO | Open.CE)), 'Open.AC')
1988        self.assertEqual(str(~(Open.WO | Open.CE)), 'Open.RW')
1989
1990    def test_repr(self):
1991        Perm = self.Perm
1992        self.assertEqual(repr(Perm.R), '<Perm.R: 4>')
1993        self.assertEqual(repr(Perm.W), '<Perm.W: 2>')
1994        self.assertEqual(repr(Perm.X), '<Perm.X: 1>')
1995        self.assertEqual(repr(Perm.R | Perm.W), '<Perm.R|W: 6>')
1996        self.assertEqual(repr(Perm.R | Perm.W | Perm.X), '<Perm.R|W|X: 7>')
1997        self.assertEqual(repr(Perm(0)), '<Perm.0: 0>')
1998        self.assertEqual(repr(~Perm.R), '<Perm.W|X: 3>')
1999        self.assertEqual(repr(~Perm.W), '<Perm.R|X: 5>')
2000        self.assertEqual(repr(~Perm.X), '<Perm.R|W: 6>')
2001        self.assertEqual(repr(~(Perm.R | Perm.W)), '<Perm.X: 1>')
2002        self.assertEqual(repr(~(Perm.R | Perm.W | Perm.X)), '<Perm.0: 0>')
2003        self.assertEqual(repr(Perm(~0)), '<Perm.R|W|X: 7>')
2004
2005        Open = self.Open
2006        self.assertEqual(repr(Open.RO), '<Open.RO: 0>')
2007        self.assertEqual(repr(Open.WO), '<Open.WO: 1>')
2008        self.assertEqual(repr(Open.AC), '<Open.AC: 3>')
2009        self.assertEqual(repr(Open.RO | Open.CE), '<Open.CE: 524288>')
2010        self.assertEqual(repr(Open.WO | Open.CE), '<Open.CE|WO: 524289>')
2011        self.assertEqual(repr(~Open.RO), '<Open.CE|AC|RW|WO: 524291>')
2012        self.assertEqual(repr(~Open.WO), '<Open.CE|RW: 524290>')
2013        self.assertEqual(repr(~Open.AC), '<Open.CE: 524288>')
2014        self.assertEqual(repr(~(Open.RO | Open.CE)), '<Open.AC: 3>')
2015        self.assertEqual(repr(~(Open.WO | Open.CE)), '<Open.RW: 2>')
2016
2017    def test_or(self):
2018        Perm = self.Perm
2019        for i in Perm:
2020            for j in Perm:
2021                self.assertEqual((i | j), Perm(i.value | j.value))
2022                self.assertEqual((i | j).value, i.value | j.value)
2023                self.assertIs(type(i | j), Perm)
2024        for i in Perm:
2025            self.assertIs(i | i, i)
2026        Open = self.Open
2027        self.assertIs(Open.RO | Open.CE, Open.CE)
2028
2029    def test_and(self):
2030        Perm = self.Perm
2031        RW = Perm.R | Perm.W
2032        RX = Perm.R | Perm.X
2033        WX = Perm.W | Perm.X
2034        RWX = Perm.R | Perm.W | Perm.X
2035        values = list(Perm) + [RW, RX, WX, RWX, Perm(0)]
2036        for i in values:
2037            for j in values:
2038                self.assertEqual((i & j).value, i.value & j.value)
2039                self.assertIs(type(i & j), Perm)
2040        for i in Perm:
2041            self.assertIs(i & i, i)
2042            self.assertIs(i & RWX, i)
2043            self.assertIs(RWX & i, i)
2044        Open = self.Open
2045        self.assertIs(Open.RO & Open.CE, Open.RO)
2046
2047    def test_xor(self):
2048        Perm = self.Perm
2049        for i in Perm:
2050            for j in Perm:
2051                self.assertEqual((i ^ j).value, i.value ^ j.value)
2052                self.assertIs(type(i ^ j), Perm)
2053        for i in Perm:
2054            self.assertIs(i ^ Perm(0), i)
2055            self.assertIs(Perm(0) ^ i, i)
2056        Open = self.Open
2057        self.assertIs(Open.RO ^ Open.CE, Open.CE)
2058        self.assertIs(Open.CE ^ Open.CE, Open.RO)
2059
2060    def test_invert(self):
2061        Perm = self.Perm
2062        RW = Perm.R | Perm.W
2063        RX = Perm.R | Perm.X
2064        WX = Perm.W | Perm.X
2065        RWX = Perm.R | Perm.W | Perm.X
2066        values = list(Perm) + [RW, RX, WX, RWX, Perm(0)]
2067        for i in values:
2068            self.assertIs(type(~i), Perm)
2069            self.assertEqual(~~i, i)
2070        for i in Perm:
2071            self.assertIs(~~i, i)
2072        Open = self.Open
2073        self.assertIs(Open.WO & ~Open.WO, Open.RO)
2074        self.assertIs((Open.WO|Open.CE) & ~Open.WO, Open.CE)
2075
2076    def test_bool(self):
2077        Perm = self.Perm
2078        for f in Perm:
2079            self.assertTrue(f)
2080        Open = self.Open
2081        for f in Open:
2082            self.assertEqual(bool(f.value), bool(f))
2083
2084    def test_programatic_function_string(self):
2085        Perm = Flag('Perm', 'R W X')
2086        lst = list(Perm)
2087        self.assertEqual(len(lst), len(Perm))
2088        self.assertEqual(len(Perm), 3, Perm)
2089        self.assertEqual(lst, [Perm.R, Perm.W, Perm.X])
2090        for i, n in enumerate('R W X'.split()):
2091            v = 1<<i
2092            e = Perm(v)
2093            self.assertEqual(e.value, v)
2094            self.assertEqual(type(e.value), int)
2095            self.assertEqual(e.name, n)
2096            self.assertIn(e, Perm)
2097            self.assertIs(type(e), Perm)
2098
2099    def test_programatic_function_string_with_start(self):
2100        Perm = Flag('Perm', 'R W X', start=8)
2101        lst = list(Perm)
2102        self.assertEqual(len(lst), len(Perm))
2103        self.assertEqual(len(Perm), 3, Perm)
2104        self.assertEqual(lst, [Perm.R, Perm.W, Perm.X])
2105        for i, n in enumerate('R W X'.split()):
2106            v = 8<<i
2107            e = Perm(v)
2108            self.assertEqual(e.value, v)
2109            self.assertEqual(type(e.value), int)
2110            self.assertEqual(e.name, n)
2111            self.assertIn(e, Perm)
2112            self.assertIs(type(e), Perm)
2113
2114    def test_programatic_function_string_list(self):
2115        Perm = Flag('Perm', ['R', 'W', 'X'])
2116        lst = list(Perm)
2117        self.assertEqual(len(lst), len(Perm))
2118        self.assertEqual(len(Perm), 3, Perm)
2119        self.assertEqual(lst, [Perm.R, Perm.W, Perm.X])
2120        for i, n in enumerate('R W X'.split()):
2121            v = 1<<i
2122            e = Perm(v)
2123            self.assertEqual(e.value, v)
2124            self.assertEqual(type(e.value), int)
2125            self.assertEqual(e.name, n)
2126            self.assertIn(e, Perm)
2127            self.assertIs(type(e), Perm)
2128
2129    def test_programatic_function_iterable(self):
2130        Perm = Flag('Perm', (('R', 2), ('W', 8), ('X', 32)))
2131        lst = list(Perm)
2132        self.assertEqual(len(lst), len(Perm))
2133        self.assertEqual(len(Perm), 3, Perm)
2134        self.assertEqual(lst, [Perm.R, Perm.W, Perm.X])
2135        for i, n in enumerate('R W X'.split()):
2136            v = 1<<(2*i+1)
2137            e = Perm(v)
2138            self.assertEqual(e.value, v)
2139            self.assertEqual(type(e.value), int)
2140            self.assertEqual(e.name, n)
2141            self.assertIn(e, Perm)
2142            self.assertIs(type(e), Perm)
2143
2144    def test_programatic_function_from_dict(self):
2145        Perm = Flag('Perm', OrderedDict((('R', 2), ('W', 8), ('X', 32))))
2146        lst = list(Perm)
2147        self.assertEqual(len(lst), len(Perm))
2148        self.assertEqual(len(Perm), 3, Perm)
2149        self.assertEqual(lst, [Perm.R, Perm.W, Perm.X])
2150        for i, n in enumerate('R W X'.split()):
2151            v = 1<<(2*i+1)
2152            e = Perm(v)
2153            self.assertEqual(e.value, v)
2154            self.assertEqual(type(e.value), int)
2155            self.assertEqual(e.name, n)
2156            self.assertIn(e, Perm)
2157            self.assertIs(type(e), Perm)
2158
2159    def test_pickle(self):
2160        if isinstance(FlagStooges, Exception):
2161            raise FlagStooges
2162        test_pickle_dump_load(self.assertIs, FlagStooges.CURLY|FlagStooges.MOE)
2163        test_pickle_dump_load(self.assertIs, FlagStooges)
2164
2165    def test_contains(self):
2166        Open = self.Open
2167        Color = self.Color
2168        self.assertFalse(Color.BLACK in Open)
2169        self.assertFalse(Open.RO in Color)
2170        with self.assertRaises(TypeError):
2171            'BLACK' in Color
2172        with self.assertRaises(TypeError):
2173            'RO' in Open
2174        with self.assertRaises(TypeError):
2175            1 in Color
2176        with self.assertRaises(TypeError):
2177            1 in Open
2178
2179    def test_member_contains(self):
2180        Perm = self.Perm
2181        R, W, X = Perm
2182        RW = R | W
2183        RX = R | X
2184        WX = W | X
2185        RWX = R | W | X
2186        self.assertTrue(R in RW)
2187        self.assertTrue(R in RX)
2188        self.assertTrue(R in RWX)
2189        self.assertTrue(W in RW)
2190        self.assertTrue(W in WX)
2191        self.assertTrue(W in RWX)
2192        self.assertTrue(X in RX)
2193        self.assertTrue(X in WX)
2194        self.assertTrue(X in RWX)
2195        self.assertFalse(R in WX)
2196        self.assertFalse(W in RX)
2197        self.assertFalse(X in RW)
2198
2199    def test_auto_number(self):
2200        class Color(Flag):
2201            red = auto()
2202            blue = auto()
2203            green = auto()
2204
2205        self.assertEqual(list(Color), [Color.red, Color.blue, Color.green])
2206        self.assertEqual(Color.red.value, 1)
2207        self.assertEqual(Color.blue.value, 2)
2208        self.assertEqual(Color.green.value, 4)
2209
2210    def test_auto_number_garbage(self):
2211        with self.assertRaisesRegex(TypeError, 'Invalid Flag value: .not an int.'):
2212            class Color(Flag):
2213                red = 'not an int'
2214                blue = auto()
2215
2216    def test_cascading_failure(self):
2217        class Bizarre(Flag):
2218            c = 3
2219            d = 4
2220            f = 6
2221        # Bizarre.c | Bizarre.d
2222        self.assertRaisesRegex(ValueError, "5 is not a valid Bizarre", Bizarre, 5)
2223        self.assertRaisesRegex(ValueError, "5 is not a valid Bizarre", Bizarre, 5)
2224        self.assertRaisesRegex(ValueError, "2 is not a valid Bizarre", Bizarre, 2)
2225        self.assertRaisesRegex(ValueError, "2 is not a valid Bizarre", Bizarre, 2)
2226        self.assertRaisesRegex(ValueError, "1 is not a valid Bizarre", Bizarre, 1)
2227        self.assertRaisesRegex(ValueError, "1 is not a valid Bizarre", Bizarre, 1)
2228
2229    def test_duplicate_auto(self):
2230        class Dupes(Enum):
2231            first = primero = auto()
2232            second = auto()
2233            third = auto()
2234        self.assertEqual([Dupes.first, Dupes.second, Dupes.third], list(Dupes))
2235
2236    def test_bizarre(self):
2237        class Bizarre(Flag):
2238            b = 3
2239            c = 4
2240            d = 6
2241        self.assertEqual(repr(Bizarre(7)), '<Bizarre.d|c|b: 7>')
2242
2243    def test_multiple_mixin(self):
2244        class AllMixin:
2245            @classproperty
2246            def ALL(cls):
2247                members = list(cls)
2248                all_value = None
2249                if members:
2250                    all_value = members[0]
2251                    for member in members[1:]:
2252                        all_value |= member
2253                cls.ALL = all_value
2254                return all_value
2255        class StrMixin:
2256            def __str__(self):
2257                return self._name_.lower()
2258        class Color(AllMixin, Flag):
2259            RED = auto()
2260            GREEN = auto()
2261            BLUE = auto()
2262        self.assertEqual(Color.RED.value, 1)
2263        self.assertEqual(Color.GREEN.value, 2)
2264        self.assertEqual(Color.BLUE.value, 4)
2265        self.assertEqual(Color.ALL.value, 7)
2266        self.assertEqual(str(Color.BLUE), 'Color.BLUE')
2267        class Color(AllMixin, StrMixin, Flag):
2268            RED = auto()
2269            GREEN = auto()
2270            BLUE = auto()
2271        self.assertEqual(Color.RED.value, 1)
2272        self.assertEqual(Color.GREEN.value, 2)
2273        self.assertEqual(Color.BLUE.value, 4)
2274        self.assertEqual(Color.ALL.value, 7)
2275        self.assertEqual(str(Color.BLUE), 'blue')
2276        class Color(StrMixin, AllMixin, Flag):
2277            RED = auto()
2278            GREEN = auto()
2279            BLUE = auto()
2280        self.assertEqual(Color.RED.value, 1)
2281        self.assertEqual(Color.GREEN.value, 2)
2282        self.assertEqual(Color.BLUE.value, 4)
2283        self.assertEqual(Color.ALL.value, 7)
2284        self.assertEqual(str(Color.BLUE), 'blue')
2285
2286    @support.reap_threads
2287    def test_unique_composite(self):
2288        # override __eq__ to be identity only
2289        class TestFlag(Flag):
2290            one = auto()
2291            two = auto()
2292            three = auto()
2293            four = auto()
2294            five = auto()
2295            six = auto()
2296            seven = auto()
2297            eight = auto()
2298            def __eq__(self, other):
2299                return self is other
2300            def __hash__(self):
2301                return hash(self._value_)
2302        # have multiple threads competing to complete the composite members
2303        seen = set()
2304        failed = False
2305        def cycle_enum():
2306            nonlocal failed
2307            try:
2308                for i in range(256):
2309                    seen.add(TestFlag(i))
2310            except Exception:
2311                failed = True
2312        threads = [
2313                threading.Thread(target=cycle_enum)
2314                for _ in range(8)
2315                ]
2316        with support.start_threads(threads):
2317            pass
2318        # check that only 248 members were created
2319        self.assertFalse(
2320                failed,
2321                'at least one thread failed while creating composite members')
2322        self.assertEqual(256, len(seen), 'too many composite members created')
2323
2324
2325class TestIntFlag(unittest.TestCase):
2326    """Tests of the IntFlags."""
2327
2328    class Perm(IntFlag):
2329        X = 1 << 0
2330        W = 1 << 1
2331        R = 1 << 2
2332
2333    class Open(IntFlag):
2334        RO = 0
2335        WO = 1
2336        RW = 2
2337        AC = 3
2338        CE = 1<<19
2339
2340    class Color(IntFlag):
2341        BLACK = 0
2342        RED = 1
2343        GREEN = 2
2344        BLUE = 4
2345        PURPLE = RED|BLUE
2346
2347    def test_type(self):
2348        Perm = self.Perm
2349        Open = self.Open
2350        for f in Perm:
2351            self.assertTrue(isinstance(f, Perm))
2352            self.assertEqual(f, f.value)
2353        self.assertTrue(isinstance(Perm.W | Perm.X, Perm))
2354        self.assertEqual(Perm.W | Perm.X, 3)
2355        for f in Open:
2356            self.assertTrue(isinstance(f, Open))
2357            self.assertEqual(f, f.value)
2358        self.assertTrue(isinstance(Open.WO | Open.RW, Open))
2359        self.assertEqual(Open.WO | Open.RW, 3)
2360
2361
2362    def test_str(self):
2363        Perm = self.Perm
2364        self.assertEqual(str(Perm.R), 'Perm.R')
2365        self.assertEqual(str(Perm.W), 'Perm.W')
2366        self.assertEqual(str(Perm.X), 'Perm.X')
2367        self.assertEqual(str(Perm.R | Perm.W), 'Perm.R|W')
2368        self.assertEqual(str(Perm.R | Perm.W | Perm.X), 'Perm.R|W|X')
2369        self.assertEqual(str(Perm.R | 8), 'Perm.8|R')
2370        self.assertEqual(str(Perm(0)), 'Perm.0')
2371        self.assertEqual(str(Perm(8)), 'Perm.8')
2372        self.assertEqual(str(~Perm.R), 'Perm.W|X')
2373        self.assertEqual(str(~Perm.W), 'Perm.R|X')
2374        self.assertEqual(str(~Perm.X), 'Perm.R|W')
2375        self.assertEqual(str(~(Perm.R | Perm.W)), 'Perm.X')
2376        self.assertEqual(str(~(Perm.R | Perm.W | Perm.X)), 'Perm.-8')
2377        self.assertEqual(str(~(Perm.R | 8)), 'Perm.W|X')
2378        self.assertEqual(str(Perm(~0)), 'Perm.R|W|X')
2379        self.assertEqual(str(Perm(~8)), 'Perm.R|W|X')
2380
2381        Open = self.Open
2382        self.assertEqual(str(Open.RO), 'Open.RO')
2383        self.assertEqual(str(Open.WO), 'Open.WO')
2384        self.assertEqual(str(Open.AC), 'Open.AC')
2385        self.assertEqual(str(Open.RO | Open.CE), 'Open.CE')
2386        self.assertEqual(str(Open.WO | Open.CE), 'Open.CE|WO')
2387        self.assertEqual(str(Open(4)), 'Open.4')
2388        self.assertEqual(str(~Open.RO), 'Open.CE|AC|RW|WO')
2389        self.assertEqual(str(~Open.WO), 'Open.CE|RW')
2390        self.assertEqual(str(~Open.AC), 'Open.CE')
2391        self.assertEqual(str(~(Open.RO | Open.CE)), 'Open.AC|RW|WO')
2392        self.assertEqual(str(~(Open.WO | Open.CE)), 'Open.RW')
2393        self.assertEqual(str(Open(~4)), 'Open.CE|AC|RW|WO')
2394
2395    def test_repr(self):
2396        Perm = self.Perm
2397        self.assertEqual(repr(Perm.R), '<Perm.R: 4>')
2398        self.assertEqual(repr(Perm.W), '<Perm.W: 2>')
2399        self.assertEqual(repr(Perm.X), '<Perm.X: 1>')
2400        self.assertEqual(repr(Perm.R | Perm.W), '<Perm.R|W: 6>')
2401        self.assertEqual(repr(Perm.R | Perm.W | Perm.X), '<Perm.R|W|X: 7>')
2402        self.assertEqual(repr(Perm.R | 8), '<Perm.8|R: 12>')
2403        self.assertEqual(repr(Perm(0)), '<Perm.0: 0>')
2404        self.assertEqual(repr(Perm(8)), '<Perm.8: 8>')
2405        self.assertEqual(repr(~Perm.R), '<Perm.W|X: -5>')
2406        self.assertEqual(repr(~Perm.W), '<Perm.R|X: -3>')
2407        self.assertEqual(repr(~Perm.X), '<Perm.R|W: -2>')
2408        self.assertEqual(repr(~(Perm.R | Perm.W)), '<Perm.X: -7>')
2409        self.assertEqual(repr(~(Perm.R | Perm.W | Perm.X)), '<Perm.-8: -8>')
2410        self.assertEqual(repr(~(Perm.R | 8)), '<Perm.W|X: -13>')
2411        self.assertEqual(repr(Perm(~0)), '<Perm.R|W|X: -1>')
2412        self.assertEqual(repr(Perm(~8)), '<Perm.R|W|X: -9>')
2413
2414        Open = self.Open
2415        self.assertEqual(repr(Open.RO), '<Open.RO: 0>')
2416        self.assertEqual(repr(Open.WO), '<Open.WO: 1>')
2417        self.assertEqual(repr(Open.AC), '<Open.AC: 3>')
2418        self.assertEqual(repr(Open.RO | Open.CE), '<Open.CE: 524288>')
2419        self.assertEqual(repr(Open.WO | Open.CE), '<Open.CE|WO: 524289>')
2420        self.assertEqual(repr(Open(4)), '<Open.4: 4>')
2421        self.assertEqual(repr(~Open.RO), '<Open.CE|AC|RW|WO: -1>')
2422        self.assertEqual(repr(~Open.WO), '<Open.CE|RW: -2>')
2423        self.assertEqual(repr(~Open.AC), '<Open.CE: -4>')
2424        self.assertEqual(repr(~(Open.RO | Open.CE)), '<Open.AC|RW|WO: -524289>')
2425        self.assertEqual(repr(~(Open.WO | Open.CE)), '<Open.RW: -524290>')
2426        self.assertEqual(repr(Open(~4)), '<Open.CE|AC|RW|WO: -5>')
2427
2428    def test_or(self):
2429        Perm = self.Perm
2430        for i in Perm:
2431            for j in Perm:
2432                self.assertEqual(i | j, i.value | j.value)
2433                self.assertEqual((i | j).value, i.value | j.value)
2434                self.assertIs(type(i | j), Perm)
2435            for j in range(8):
2436                self.assertEqual(i | j, i.value | j)
2437                self.assertEqual((i | j).value, i.value | j)
2438                self.assertIs(type(i | j), Perm)
2439                self.assertEqual(j | i, j | i.value)
2440                self.assertEqual((j | i).value, j | i.value)
2441                self.assertIs(type(j | i), Perm)
2442        for i in Perm:
2443            self.assertIs(i | i, i)
2444            self.assertIs(i | 0, i)
2445            self.assertIs(0 | i, i)
2446        Open = self.Open
2447        self.assertIs(Open.RO | Open.CE, Open.CE)
2448
2449    def test_and(self):
2450        Perm = self.Perm
2451        RW = Perm.R | Perm.W
2452        RX = Perm.R | Perm.X
2453        WX = Perm.W | Perm.X
2454        RWX = Perm.R | Perm.W | Perm.X
2455        values = list(Perm) + [RW, RX, WX, RWX, Perm(0)]
2456        for i in values:
2457            for j in values:
2458                self.assertEqual(i & j, i.value & j.value, 'i is %r, j is %r' % (i, j))
2459                self.assertEqual((i & j).value, i.value & j.value, 'i is %r, j is %r' % (i, j))
2460                self.assertIs(type(i & j), Perm, 'i is %r, j is %r' % (i, j))
2461            for j in range(8):
2462                self.assertEqual(i & j, i.value & j)
2463                self.assertEqual((i & j).value, i.value & j)
2464                self.assertIs(type(i & j), Perm)
2465                self.assertEqual(j & i, j & i.value)
2466                self.assertEqual((j & i).value, j & i.value)
2467                self.assertIs(type(j & i), Perm)
2468        for i in Perm:
2469            self.assertIs(i & i, i)
2470            self.assertIs(i & 7, i)
2471            self.assertIs(7 & i, i)
2472        Open = self.Open
2473        self.assertIs(Open.RO & Open.CE, Open.RO)
2474
2475    def test_xor(self):
2476        Perm = self.Perm
2477        for i in Perm:
2478            for j in Perm:
2479                self.assertEqual(i ^ j, i.value ^ j.value)
2480                self.assertEqual((i ^ j).value, i.value ^ j.value)
2481                self.assertIs(type(i ^ j), Perm)
2482            for j in range(8):
2483                self.assertEqual(i ^ j, i.value ^ j)
2484                self.assertEqual((i ^ j).value, i.value ^ j)
2485                self.assertIs(type(i ^ j), Perm)
2486                self.assertEqual(j ^ i, j ^ i.value)
2487                self.assertEqual((j ^ i).value, j ^ i.value)
2488                self.assertIs(type(j ^ i), Perm)
2489        for i in Perm:
2490            self.assertIs(i ^ 0, i)
2491            self.assertIs(0 ^ i, i)
2492        Open = self.Open
2493        self.assertIs(Open.RO ^ Open.CE, Open.CE)
2494        self.assertIs(Open.CE ^ Open.CE, Open.RO)
2495
2496    def test_invert(self):
2497        Perm = self.Perm
2498        RW = Perm.R | Perm.W
2499        RX = Perm.R | Perm.X
2500        WX = Perm.W | Perm.X
2501        RWX = Perm.R | Perm.W | Perm.X
2502        values = list(Perm) + [RW, RX, WX, RWX, Perm(0)]
2503        for i in values:
2504            self.assertEqual(~i, ~i.value)
2505            self.assertEqual((~i).value, ~i.value)
2506            self.assertIs(type(~i), Perm)
2507            self.assertEqual(~~i, i)
2508        for i in Perm:
2509            self.assertIs(~~i, i)
2510        Open = self.Open
2511        self.assertIs(Open.WO & ~Open.WO, Open.RO)
2512        self.assertIs((Open.WO|Open.CE) & ~Open.WO, Open.CE)
2513
2514    def test_programatic_function_string(self):
2515        Perm = IntFlag('Perm', 'R W X')
2516        lst = list(Perm)
2517        self.assertEqual(len(lst), len(Perm))
2518        self.assertEqual(len(Perm), 3, Perm)
2519        self.assertEqual(lst, [Perm.R, Perm.W, Perm.X])
2520        for i, n in enumerate('R W X'.split()):
2521            v = 1<<i
2522            e = Perm(v)
2523            self.assertEqual(e.value, v)
2524            self.assertEqual(type(e.value), int)
2525            self.assertEqual(e, v)
2526            self.assertEqual(e.name, n)
2527            self.assertIn(e, Perm)
2528            self.assertIs(type(e), Perm)
2529
2530    def test_programatic_function_string_with_start(self):
2531        Perm = IntFlag('Perm', 'R W X', start=8)
2532        lst = list(Perm)
2533        self.assertEqual(len(lst), len(Perm))
2534        self.assertEqual(len(Perm), 3, Perm)
2535        self.assertEqual(lst, [Perm.R, Perm.W, Perm.X])
2536        for i, n in enumerate('R W X'.split()):
2537            v = 8<<i
2538            e = Perm(v)
2539            self.assertEqual(e.value, v)
2540            self.assertEqual(type(e.value), int)
2541            self.assertEqual(e, v)
2542            self.assertEqual(e.name, n)
2543            self.assertIn(e, Perm)
2544            self.assertIs(type(e), Perm)
2545
2546    def test_programatic_function_string_list(self):
2547        Perm = IntFlag('Perm', ['R', 'W', 'X'])
2548        lst = list(Perm)
2549        self.assertEqual(len(lst), len(Perm))
2550        self.assertEqual(len(Perm), 3, Perm)
2551        self.assertEqual(lst, [Perm.R, Perm.W, Perm.X])
2552        for i, n in enumerate('R W X'.split()):
2553            v = 1<<i
2554            e = Perm(v)
2555            self.assertEqual(e.value, v)
2556            self.assertEqual(type(e.value), int)
2557            self.assertEqual(e, v)
2558            self.assertEqual(e.name, n)
2559            self.assertIn(e, Perm)
2560            self.assertIs(type(e), Perm)
2561
2562    def test_programatic_function_iterable(self):
2563        Perm = IntFlag('Perm', (('R', 2), ('W', 8), ('X', 32)))
2564        lst = list(Perm)
2565        self.assertEqual(len(lst), len(Perm))
2566        self.assertEqual(len(Perm), 3, Perm)
2567        self.assertEqual(lst, [Perm.R, Perm.W, Perm.X])
2568        for i, n in enumerate('R W X'.split()):
2569            v = 1<<(2*i+1)
2570            e = Perm(v)
2571            self.assertEqual(e.value, v)
2572            self.assertEqual(type(e.value), int)
2573            self.assertEqual(e, v)
2574            self.assertEqual(e.name, n)
2575            self.assertIn(e, Perm)
2576            self.assertIs(type(e), Perm)
2577
2578    def test_programatic_function_from_dict(self):
2579        Perm = IntFlag('Perm', OrderedDict((('R', 2), ('W', 8), ('X', 32))))
2580        lst = list(Perm)
2581        self.assertEqual(len(lst), len(Perm))
2582        self.assertEqual(len(Perm), 3, Perm)
2583        self.assertEqual(lst, [Perm.R, Perm.W, Perm.X])
2584        for i, n in enumerate('R W X'.split()):
2585            v = 1<<(2*i+1)
2586            e = Perm(v)
2587            self.assertEqual(e.value, v)
2588            self.assertEqual(type(e.value), int)
2589            self.assertEqual(e, v)
2590            self.assertEqual(e.name, n)
2591            self.assertIn(e, Perm)
2592            self.assertIs(type(e), Perm)
2593
2594
2595    def test_programatic_function_from_empty_list(self):
2596        Perm = enum.IntFlag('Perm', [])
2597        lst = list(Perm)
2598        self.assertEqual(len(lst), len(Perm))
2599        self.assertEqual(len(Perm), 0, Perm)
2600        Thing = enum.Enum('Thing', [])
2601        lst = list(Thing)
2602        self.assertEqual(len(lst), len(Thing))
2603        self.assertEqual(len(Thing), 0, Thing)
2604
2605
2606    def test_programatic_function_from_empty_tuple(self):
2607        Perm = enum.IntFlag('Perm', ())
2608        lst = list(Perm)
2609        self.assertEqual(len(lst), len(Perm))
2610        self.assertEqual(len(Perm), 0, Perm)
2611        Thing = enum.Enum('Thing', ())
2612        self.assertEqual(len(lst), len(Thing))
2613        self.assertEqual(len(Thing), 0, Thing)
2614
2615    def test_contains(self):
2616        Open = self.Open
2617        Color = self.Color
2618        self.assertTrue(Color.GREEN in Color)
2619        self.assertTrue(Open.RW in Open)
2620        self.assertFalse(Color.GREEN in Open)
2621        self.assertFalse(Open.RW in Color)
2622        with self.assertRaises(TypeError):
2623            'GREEN' in Color
2624        with self.assertRaises(TypeError):
2625            'RW' in Open
2626        with self.assertRaises(TypeError):
2627            2 in Color
2628        with self.assertRaises(TypeError):
2629            2 in Open
2630
2631    def test_member_contains(self):
2632        Perm = self.Perm
2633        R, W, X = Perm
2634        RW = R | W
2635        RX = R | X
2636        WX = W | X
2637        RWX = R | W | X
2638        self.assertTrue(R in RW)
2639        self.assertTrue(R in RX)
2640        self.assertTrue(R in RWX)
2641        self.assertTrue(W in RW)
2642        self.assertTrue(W in WX)
2643        self.assertTrue(W in RWX)
2644        self.assertTrue(X in RX)
2645        self.assertTrue(X in WX)
2646        self.assertTrue(X in RWX)
2647        self.assertFalse(R in WX)
2648        self.assertFalse(W in RX)
2649        self.assertFalse(X in RW)
2650        with self.assertRaises(TypeError):
2651            self.assertFalse('test' in RW)
2652
2653    def test_bool(self):
2654        Perm = self.Perm
2655        for f in Perm:
2656            self.assertTrue(f)
2657        Open = self.Open
2658        for f in Open:
2659            self.assertEqual(bool(f.value), bool(f))
2660
2661    def test_multiple_mixin(self):
2662        class AllMixin:
2663            @classproperty
2664            def ALL(cls):
2665                members = list(cls)
2666                all_value = None
2667                if members:
2668                    all_value = members[0]
2669                    for member in members[1:]:
2670                        all_value |= member
2671                cls.ALL = all_value
2672                return all_value
2673        class StrMixin:
2674            def __str__(self):
2675                return self._name_.lower()
2676        class Color(AllMixin, IntFlag):
2677            RED = auto()
2678            GREEN = auto()
2679            BLUE = auto()
2680        self.assertEqual(Color.RED.value, 1)
2681        self.assertEqual(Color.GREEN.value, 2)
2682        self.assertEqual(Color.BLUE.value, 4)
2683        self.assertEqual(Color.ALL.value, 7)
2684        self.assertEqual(str(Color.BLUE), 'Color.BLUE')
2685        class Color(AllMixin, StrMixin, IntFlag):
2686            RED = auto()
2687            GREEN = auto()
2688            BLUE = auto()
2689        self.assertEqual(Color.RED.value, 1)
2690        self.assertEqual(Color.GREEN.value, 2)
2691        self.assertEqual(Color.BLUE.value, 4)
2692        self.assertEqual(Color.ALL.value, 7)
2693        self.assertEqual(str(Color.BLUE), 'blue')
2694        class Color(StrMixin, AllMixin, IntFlag):
2695            RED = auto()
2696            GREEN = auto()
2697            BLUE = auto()
2698        self.assertEqual(Color.RED.value, 1)
2699        self.assertEqual(Color.GREEN.value, 2)
2700        self.assertEqual(Color.BLUE.value, 4)
2701        self.assertEqual(Color.ALL.value, 7)
2702        self.assertEqual(str(Color.BLUE), 'blue')
2703
2704    @support.reap_threads
2705    def test_unique_composite(self):
2706        # override __eq__ to be identity only
2707        class TestFlag(IntFlag):
2708            one = auto()
2709            two = auto()
2710            three = auto()
2711            four = auto()
2712            five = auto()
2713            six = auto()
2714            seven = auto()
2715            eight = auto()
2716            def __eq__(self, other):
2717                return self is other
2718            def __hash__(self):
2719                return hash(self._value_)
2720        # have multiple threads competing to complete the composite members
2721        seen = set()
2722        failed = False
2723        def cycle_enum():
2724            nonlocal failed
2725            try:
2726                for i in range(256):
2727                    seen.add(TestFlag(i))
2728            except Exception:
2729                failed = True
2730        threads = [
2731                threading.Thread(target=cycle_enum)
2732                for _ in range(8)
2733                ]
2734        with support.start_threads(threads):
2735            pass
2736        # check that only 248 members were created
2737        self.assertFalse(
2738                failed,
2739                'at least one thread failed while creating composite members')
2740        self.assertEqual(256, len(seen), 'too many composite members created')
2741
2742
2743class TestEmptyAndNonLatinStrings(unittest.TestCase):
2744
2745    def test_empty_string(self):
2746        with self.assertRaises(ValueError):
2747            empty_abc = Enum('empty_abc', ('', 'B', 'C'))
2748
2749    def test_non_latin_character_string(self):
2750        greek_abc = Enum('greek_abc', ('\u03B1', 'B', 'C'))
2751        item = getattr(greek_abc, '\u03B1')
2752        self.assertEqual(item.value, 1)
2753
2754    def test_non_latin_number_string(self):
2755        hebrew_123 = Enum('hebrew_123', ('\u05D0', '2', '3'))
2756        item = getattr(hebrew_123, '\u05D0')
2757        self.assertEqual(item.value, 1)
2758
2759
2760class TestUnique(unittest.TestCase):
2761
2762    def test_unique_clean(self):
2763        @unique
2764        class Clean(Enum):
2765            one = 1
2766            two = 'dos'
2767            tres = 4.0
2768        @unique
2769        class Cleaner(IntEnum):
2770            single = 1
2771            double = 2
2772            triple = 3
2773
2774    def test_unique_dirty(self):
2775        with self.assertRaisesRegex(ValueError, 'tres.*one'):
2776            @unique
2777            class Dirty(Enum):
2778                one = 1
2779                two = 'dos'
2780                tres = 1
2781        with self.assertRaisesRegex(
2782                ValueError,
2783                'double.*single.*turkey.*triple',
2784                ):
2785            @unique
2786            class Dirtier(IntEnum):
2787                single = 1
2788                double = 1
2789                triple = 3
2790                turkey = 3
2791
2792    def test_unique_with_name(self):
2793        @unique
2794        class Silly(Enum):
2795            one = 1
2796            two = 'dos'
2797            name = 3
2798        @unique
2799        class Sillier(IntEnum):
2800            single = 1
2801            name = 2
2802            triple = 3
2803            value = 4
2804
2805
2806
2807expected_help_output_with_docs = """\
2808Help on class Color in module %s:
2809
2810class Color(enum.Enum)
2811 |  Color(value, names=None, *, module=None, qualname=None, type=None, start=1)
2812 |\x20\x20
2813 |  An enumeration.
2814 |\x20\x20
2815 |  Method resolution order:
2816 |      Color
2817 |      enum.Enum
2818 |      builtins.object
2819 |\x20\x20
2820 |  Data and other attributes defined here:
2821 |\x20\x20
2822 |  blue = <Color.blue: 3>
2823 |\x20\x20
2824 |  green = <Color.green: 2>
2825 |\x20\x20
2826 |  red = <Color.red: 1>
2827 |\x20\x20
2828 |  ----------------------------------------------------------------------
2829 |  Data descriptors inherited from enum.Enum:
2830 |\x20\x20
2831 |  name
2832 |      The name of the Enum member.
2833 |\x20\x20
2834 |  value
2835 |      The value of the Enum member.
2836 |\x20\x20
2837 |  ----------------------------------------------------------------------
2838 |  Readonly properties inherited from enum.EnumMeta:
2839 |\x20\x20
2840 |  __members__
2841 |      Returns a mapping of member name->value.
2842 |\x20\x20\x20\x20\x20\x20
2843 |      This mapping lists all enum members, including aliases. Note that this
2844 |      is a read-only view of the internal mapping."""
2845
2846expected_help_output_without_docs = """\
2847Help on class Color in module %s:
2848
2849class Color(enum.Enum)
2850 |  Color(value, names=None, *, module=None, qualname=None, type=None, start=1)
2851 |\x20\x20
2852 |  Method resolution order:
2853 |      Color
2854 |      enum.Enum
2855 |      builtins.object
2856 |\x20\x20
2857 |  Data and other attributes defined here:
2858 |\x20\x20
2859 |  blue = <Color.blue: 3>
2860 |\x20\x20
2861 |  green = <Color.green: 2>
2862 |\x20\x20
2863 |  red = <Color.red: 1>
2864 |\x20\x20
2865 |  ----------------------------------------------------------------------
2866 |  Data descriptors inherited from enum.Enum:
2867 |\x20\x20
2868 |  name
2869 |\x20\x20
2870 |  value
2871 |\x20\x20
2872 |  ----------------------------------------------------------------------
2873 |  Data descriptors inherited from enum.EnumMeta:
2874 |\x20\x20
2875 |  __members__"""
2876
2877class TestStdLib(unittest.TestCase):
2878
2879    maxDiff = None
2880
2881    class Color(Enum):
2882        red = 1
2883        green = 2
2884        blue = 3
2885
2886    def test_pydoc(self):
2887        # indirectly test __objclass__
2888        if StrEnum.__doc__ is None:
2889            expected_text = expected_help_output_without_docs % __name__
2890        else:
2891            expected_text = expected_help_output_with_docs % __name__
2892        output = StringIO()
2893        helper = pydoc.Helper(output=output)
2894        helper(self.Color)
2895        result = output.getvalue().strip()
2896        self.assertEqual(result, expected_text)
2897
2898    def test_inspect_getmembers(self):
2899        values = dict((
2900                ('__class__', EnumMeta),
2901                ('__doc__', 'An enumeration.'),
2902                ('__members__', self.Color.__members__),
2903                ('__module__', __name__),
2904                ('blue', self.Color.blue),
2905                ('green', self.Color.green),
2906                ('name', Enum.__dict__['name']),
2907                ('red', self.Color.red),
2908                ('value', Enum.__dict__['value']),
2909                ))
2910        result = dict(inspect.getmembers(self.Color))
2911        self.assertEqual(values.keys(), result.keys())
2912        failed = False
2913        for k in values.keys():
2914            if result[k] != values[k]:
2915                print()
2916                print('\n%s\n     key: %s\n  result: %s\nexpected: %s\n%s\n' %
2917                        ('=' * 75, k, result[k], values[k], '=' * 75), sep='')
2918                failed = True
2919        if failed:
2920            self.fail("result does not equal expected, see print above")
2921
2922    def test_inspect_classify_class_attrs(self):
2923        # indirectly test __objclass__
2924        from inspect import Attribute
2925        values = [
2926                Attribute(name='__class__', kind='data',
2927                    defining_class=object, object=EnumMeta),
2928                Attribute(name='__doc__', kind='data',
2929                    defining_class=self.Color, object='An enumeration.'),
2930                Attribute(name='__members__', kind='property',
2931                    defining_class=EnumMeta, object=EnumMeta.__members__),
2932                Attribute(name='__module__', kind='data',
2933                    defining_class=self.Color, object=__name__),
2934                Attribute(name='blue', kind='data',
2935                    defining_class=self.Color, object=self.Color.blue),
2936                Attribute(name='green', kind='data',
2937                    defining_class=self.Color, object=self.Color.green),
2938                Attribute(name='red', kind='data',
2939                    defining_class=self.Color, object=self.Color.red),
2940                Attribute(name='name', kind='data',
2941                    defining_class=Enum, object=Enum.__dict__['name']),
2942                Attribute(name='value', kind='data',
2943                    defining_class=Enum, object=Enum.__dict__['value']),
2944                ]
2945        values.sort(key=lambda item: item.name)
2946        result = list(inspect.classify_class_attrs(self.Color))
2947        result.sort(key=lambda item: item.name)
2948        failed = False
2949        for v, r in zip(values, result):
2950            if r != v:
2951                print('\n%s\n%s\n%s\n%s\n' % ('=' * 75, r, v, '=' * 75), sep='')
2952                failed = True
2953        if failed:
2954            self.fail("result does not equal expected, see print above")
2955
2956
2957class MiscTestCase(unittest.TestCase):
2958    def test__all__(self):
2959        support.check__all__(self, enum)
2960
2961
2962# These are unordered here on purpose to ensure that declaration order
2963# makes no difference.
2964CONVERT_TEST_NAME_D = 5
2965CONVERT_TEST_NAME_C = 5
2966CONVERT_TEST_NAME_B = 5
2967CONVERT_TEST_NAME_A = 5  # This one should sort first.
2968CONVERT_TEST_NAME_E = 5
2969CONVERT_TEST_NAME_F = 5
2970
2971class TestIntEnumConvert(unittest.TestCase):
2972    def test_convert_value_lookup_priority(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        # We don't want the reverse lookup value to vary when there are
2978        # multiple possible names for a given value.  It should always
2979        # report the first lexigraphical name in that case.
2980        self.assertEqual(test_type(5).name, 'CONVERT_TEST_NAME_A')
2981
2982    def test_convert(self):
2983        test_type = enum.IntEnum._convert_(
2984                'UnittestConvert',
2985                ('test.test_enum', '__main__')[__name__=='__main__'],
2986                filter=lambda x: x.startswith('CONVERT_TEST_'))
2987        # Ensure that test_type has all of the desired names and values.
2988        self.assertEqual(test_type.CONVERT_TEST_NAME_F,
2989                         test_type.CONVERT_TEST_NAME_A)
2990        self.assertEqual(test_type.CONVERT_TEST_NAME_B, 5)
2991        self.assertEqual(test_type.CONVERT_TEST_NAME_C, 5)
2992        self.assertEqual(test_type.CONVERT_TEST_NAME_D, 5)
2993        self.assertEqual(test_type.CONVERT_TEST_NAME_E, 5)
2994        # Ensure that test_type only picked up names matching the filter.
2995        self.assertEqual([name for name in dir(test_type)
2996                          if name[0:2] not in ('CO', '__')],
2997                         [], msg='Names other than CONVERT_TEST_* found.')
2998
2999    @unittest.skipUnless(sys.version_info[:2] == (3, 8),
3000                         '_convert was deprecated in 3.8')
3001    def test_convert_warn(self):
3002        with self.assertWarns(DeprecationWarning):
3003            enum.IntEnum._convert(
3004                'UnittestConvert',
3005                ('test.test_enum', '__main__')[__name__=='__main__'],
3006                filter=lambda x: x.startswith('CONVERT_TEST_'))
3007
3008    @unittest.skipUnless(sys.version_info >= (3, 9),
3009                         '_convert was removed in 3.9')
3010    def test_convert_raise(self):
3011        with self.assertRaises(AttributeError):
3012            enum.IntEnum._convert(
3013                'UnittestConvert',
3014                ('test.test_enum', '__main__')[__name__=='__main__'],
3015                filter=lambda x: x.startswith('CONVERT_TEST_'))
3016
3017
3018if __name__ == '__main__':
3019    unittest.main()
3020