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