1from pickle import dumps, loads, PicklingError, HIGHEST_PROTOCOL
2import sys
3import unittest
4pyver = float('%s.%s' % sys.version_info[:2])
5if pyver < 2.5:
6    sys.path.insert(0, '.')
7import enum
8from enum import Enum, IntEnum, unique, EnumMeta
9
10if pyver < 2.6:
11    from __builtin__ import enumerate as bltin_enumerate
12    def enumerate(thing, start=0):
13        result = []
14        for i, item in bltin_enumerate(thing):
15            i = i + start
16            result.append((i, item))
17        return result
18
19try:
20    any
21except NameError:
22    def any(iterable):
23        for element in iterable:
24            if element:
25                return True
26        return False
27
28try:
29    unicode
30except NameError:
31    unicode = str
32
33try:
34    from collections import OrderedDict
35except ImportError:
36    OrderedDict = None
37
38# for pickle tests
39try:
40    class Stooges(Enum):
41        LARRY = 1
42        CURLY = 2
43        MOE = 3
44except Exception:
45    Stooges = sys.exc_info()[1]
46
47try:
48    class IntStooges(int, Enum):
49        LARRY = 1
50        CURLY = 2
51        MOE = 3
52except Exception:
53    IntStooges = sys.exc_info()[1]
54
55try:
56    class FloatStooges(float, Enum):
57        LARRY = 1.39
58        CURLY = 2.72
59        MOE = 3.142596
60except Exception:
61    FloatStooges = sys.exc_info()[1]
62
63# for pickle test and subclass tests
64try:
65    class StrEnum(str, Enum):
66        'accepts only string values'
67    class Name(StrEnum):
68        BDFL = 'Guido van Rossum'
69        FLUFL = 'Barry Warsaw'
70except Exception:
71    Name = sys.exc_info()[1]
72
73try:
74    Question = Enum('Question', 'who what when where why', module=__name__)
75except Exception:
76    Question = sys.exc_info()[1]
77
78try:
79    Answer = Enum('Answer', 'him this then there because')
80except Exception:
81    Answer = sys.exc_info()[1]
82
83try:
84    Theory = Enum('Theory', 'rule law supposition', qualname='spanish_inquisition')
85except Exception:
86    Theory = sys.exc_info()[1]
87
88# for doctests
89try:
90    class Fruit(Enum):
91        tomato = 1
92        banana = 2
93        cherry = 3
94except Exception:
95    pass
96
97def test_pickle_dump_load(assertion, source, target=None,
98        protocol=(0, HIGHEST_PROTOCOL)):
99    start, stop = protocol
100    failures = []
101    for protocol in range(start, stop+1):
102        try:
103            if target is None:
104                assertion(loads(dumps(source, protocol=protocol)) is source)
105            else:
106                assertion(loads(dumps(source, protocol=protocol)), target)
107        except Exception:
108            exc, tb = sys.exc_info()[1:]
109            failures.append('%2d: %s' %(protocol, exc))
110    if failures:
111        raise ValueError('Failed with protocols: %s' % ', '.join(failures))
112
113def test_pickle_exception(assertion, exception, obj,
114        protocol=(0, HIGHEST_PROTOCOL)):
115    start, stop = protocol
116    failures = []
117    for protocol in range(start, stop+1):
118        try:
119            assertion(exception, dumps, obj, protocol=protocol)
120        except Exception:
121            exc = sys.exc_info()[1]
122            failures.append('%d: %s %s' % (protocol, exc.__class__.__name__, exc))
123    if failures:
124        raise ValueError('Failed with protocols: %s' % ', '.join(failures))
125
126
127class TestHelpers(unittest.TestCase):
128    # _is_descriptor, _is_sunder, _is_dunder
129
130    def test_is_descriptor(self):
131        class foo:
132            pass
133        for attr in ('__get__','__set__','__delete__'):
134            obj = foo()
135            self.assertFalse(enum._is_descriptor(obj))
136            setattr(obj, attr, 1)
137            self.assertTrue(enum._is_descriptor(obj))
138
139    def test_is_sunder(self):
140        for s in ('_a_', '_aa_'):
141            self.assertTrue(enum._is_sunder(s))
142
143        for s in ('a', 'a_', '_a', '__a', 'a__', '__a__', '_a__', '__a_', '_',
144                '__', '___', '____', '_____',):
145            self.assertFalse(enum._is_sunder(s))
146
147    def test_is_dunder(self):
148        for s in ('__a__', '__aa__'):
149            self.assertTrue(enum._is_dunder(s))
150        for s in ('a', 'a_', '_a', '__a', 'a__', '_a_', '_a__', '__a_', '_',
151                '__', '___', '____', '_____',):
152            self.assertFalse(enum._is_dunder(s))
153
154
155class TestEnum(unittest.TestCase):
156    def setUp(self):
157        class Season(Enum):
158            SPRING = 1
159            SUMMER = 2
160            AUTUMN = 3
161            WINTER = 4
162        self.Season = Season
163
164        class Konstants(float, Enum):
165            E = 2.7182818
166            PI = 3.1415926
167            TAU = 2 * PI
168        self.Konstants = Konstants
169
170        class Grades(IntEnum):
171            A = 5
172            B = 4
173            C = 3
174            D = 2
175            F = 0
176        self.Grades = Grades
177
178        class Directional(str, Enum):
179            EAST = 'east'
180            WEST = 'west'
181            NORTH = 'north'
182            SOUTH = 'south'
183        self.Directional = Directional
184
185        from datetime import date
186        class Holiday(date, Enum):
187            NEW_YEAR = 2013, 1, 1
188            IDES_OF_MARCH = 2013, 3, 15
189        self.Holiday = Holiday
190
191    if pyver >= 3.0:     # do not specify custom `dir` on previous versions
192        def test_dir_on_class(self):
193            Season = self.Season
194            self.assertEqual(
195                set(dir(Season)),
196                set(['__class__', '__doc__', '__members__', '__module__',
197                    'SPRING', 'SUMMER', 'AUTUMN', 'WINTER']),
198                )
199
200        def test_dir_on_item(self):
201            Season = self.Season
202            self.assertEqual(
203                set(dir(Season.WINTER)),
204                set(['__class__', '__doc__', '__module__', 'name', 'value']),
205                )
206
207        def test_dir_with_added_behavior(self):
208            class Test(Enum):
209                this = 'that'
210                these = 'those'
211                def wowser(self):
212                    return ("Wowser! I'm %s!" % self.name)
213            self.assertEqual(
214                    set(dir(Test)),
215                    set(['__class__', '__doc__', '__members__', '__module__', 'this', 'these']),
216                    )
217            self.assertEqual(
218                    set(dir(Test.this)),
219                    set(['__class__', '__doc__', '__module__', 'name', 'value', 'wowser']),
220                    )
221
222        def test_dir_on_sub_with_behavior_on_super(self):
223            # see issue22506
224            class SuperEnum(Enum):
225                def invisible(self):
226                    return "did you see me?"
227            class SubEnum(SuperEnum):
228                sample = 5
229            self.assertEqual(
230                    set(dir(SubEnum.sample)),
231                    set(['__class__', '__doc__', '__module__', 'name', 'value', 'invisible']),
232                    )
233
234    if pyver >= 2.7:    # OrderedDict first available here
235        def test_members_is_ordereddict_if_ordered(self):
236            class Ordered(Enum):
237                __order__ = 'first second third'
238                first = 'bippity'
239                second = 'boppity'
240                third = 'boo'
241            self.assertTrue(type(Ordered.__members__) is OrderedDict)
242
243        def test_members_is_ordereddict_if_not_ordered(self):
244            class Unordered(Enum):
245                this = 'that'
246                these = 'those'
247            self.assertTrue(type(Unordered.__members__) is OrderedDict)
248
249    if pyver >= 3.0:     # all objects are ordered in Python 2.x
250        def test_members_is_always_ordered(self):
251            class AlwaysOrdered(Enum):
252                first = 1
253                second = 2
254                third = 3
255            self.assertTrue(type(AlwaysOrdered.__members__) is OrderedDict)
256
257        def test_comparisons(self):
258            def bad_compare():
259                Season.SPRING > 4
260            Season = self.Season
261            self.assertNotEqual(Season.SPRING, 1)
262            self.assertRaises(TypeError, bad_compare)
263
264            class Part(Enum):
265                SPRING = 1
266                CLIP = 2
267                BARREL = 3
268
269            self.assertNotEqual(Season.SPRING, Part.SPRING)
270            def bad_compare():
271                Season.SPRING < Part.CLIP
272            self.assertRaises(TypeError, bad_compare)
273
274    def test_enum_in_enum_out(self):
275        Season = self.Season
276        self.assertTrue(Season(Season.WINTER) is Season.WINTER)
277
278    def test_enum_value(self):
279        Season = self.Season
280        self.assertEqual(Season.SPRING.value, 1)
281
282    def test_intenum_value(self):
283        self.assertEqual(IntStooges.CURLY.value, 2)
284
285    def test_enum(self):
286        Season = self.Season
287        lst = list(Season)
288        self.assertEqual(len(lst), len(Season))
289        self.assertEqual(len(Season), 4, Season)
290        self.assertEqual(
291            [Season.SPRING, Season.SUMMER, Season.AUTUMN, Season.WINTER], lst)
292
293        for i, season in enumerate('SPRING SUMMER AUTUMN WINTER'.split()):
294            i += 1
295            e = Season(i)
296            self.assertEqual(e, getattr(Season, season))
297            self.assertEqual(e.value, i)
298            self.assertNotEqual(e, i)
299            self.assertEqual(e.name, season)
300            self.assertTrue(e in Season)
301            self.assertTrue(type(e) is Season)
302            self.assertTrue(isinstance(e, Season))
303            self.assertEqual(str(e), 'Season.' + season)
304            self.assertEqual(
305                    repr(e),
306                    '<Season.%s: %s>' % (season, i),
307                    )
308
309    def test_value_name(self):
310        Season = self.Season
311        self.assertEqual(Season.SPRING.name, 'SPRING')
312        self.assertEqual(Season.SPRING.value, 1)
313        def set_name(obj, new_value):
314            obj.name = new_value
315        def set_value(obj, new_value):
316            obj.value = new_value
317        self.assertRaises(AttributeError, set_name, Season.SPRING, 'invierno', )
318        self.assertRaises(AttributeError, set_value, Season.SPRING, 2)
319
320    def test_attribute_deletion(self):
321        class Season(Enum):
322            SPRING = 1
323            SUMMER = 2
324            AUTUMN = 3
325            WINTER = 4
326
327            def spam(cls):
328                pass
329
330        self.assertTrue(hasattr(Season, 'spam'))
331        del Season.spam
332        self.assertFalse(hasattr(Season, 'spam'))
333
334        self.assertRaises(AttributeError, delattr, Season, 'SPRING')
335        self.assertRaises(AttributeError, delattr, Season, 'DRY')
336        self.assertRaises(AttributeError, delattr, Season.SPRING, 'name')
337
338    def test_bool_of_class(self):
339        class Empty(Enum):
340            pass
341        self.assertTrue(bool(Empty))
342
343    def test_bool_of_member(self):
344        class Count(Enum):
345            zero = 0
346            one = 1
347            two = 2
348        for member in Count:
349            self.assertTrue(bool(member))
350
351    def test_invalid_names(self):
352        def create_bad_class_1():
353            class Wrong(Enum):
354                mro = 9
355        def create_bad_class_2():
356            class Wrong(Enum):
357                _reserved_ = 3
358        self.assertRaises(ValueError, create_bad_class_1)
359        self.assertRaises(ValueError, create_bad_class_2)
360
361    def test_contains(self):
362        Season = self.Season
363        self.assertTrue(Season.AUTUMN in Season)
364        self.assertTrue(3 not in Season)
365
366        val = Season(3)
367        self.assertTrue(val in Season)
368
369        class OtherEnum(Enum):
370            one = 1; two = 2
371        self.assertTrue(OtherEnum.two not in Season)
372
373    if pyver >= 2.6:     # when `format` came into being
374
375        def test_format_enum(self):
376            Season = self.Season
377            self.assertEqual('{0}'.format(Season.SPRING),
378                             '{0}'.format(str(Season.SPRING)))
379            self.assertEqual( '{0:}'.format(Season.SPRING),
380                              '{0:}'.format(str(Season.SPRING)))
381            self.assertEqual('{0:20}'.format(Season.SPRING),
382                             '{0:20}'.format(str(Season.SPRING)))
383            self.assertEqual('{0:^20}'.format(Season.SPRING),
384                             '{0:^20}'.format(str(Season.SPRING)))
385            self.assertEqual('{0:>20}'.format(Season.SPRING),
386                             '{0:>20}'.format(str(Season.SPRING)))
387            self.assertEqual('{0:<20}'.format(Season.SPRING),
388                             '{0:<20}'.format(str(Season.SPRING)))
389
390        def test_format_enum_custom(self):
391            class TestFloat(float, Enum):
392                one = 1.0
393                two = 2.0
394                def __format__(self, spec):
395                    return 'TestFloat success!'
396            self.assertEqual('{0}'.format(TestFloat.one), 'TestFloat success!')
397
398        def assertFormatIsValue(self, spec, member):
399            self.assertEqual(spec.format(member), spec.format(member.value))
400
401        def test_format_enum_date(self):
402            Holiday = self.Holiday
403            self.assertFormatIsValue('{0}', Holiday.IDES_OF_MARCH)
404            self.assertFormatIsValue('{0:}', Holiday.IDES_OF_MARCH)
405            self.assertFormatIsValue('{0:20}', Holiday.IDES_OF_MARCH)
406            self.assertFormatIsValue('{0:^20}', Holiday.IDES_OF_MARCH)
407            self.assertFormatIsValue('{0:>20}', Holiday.IDES_OF_MARCH)
408            self.assertFormatIsValue('{0:<20}', Holiday.IDES_OF_MARCH)
409            self.assertFormatIsValue('{0:%Y %m}', Holiday.IDES_OF_MARCH)
410            self.assertFormatIsValue('{0:%Y %m %M:00}', Holiday.IDES_OF_MARCH)
411
412        def test_format_enum_float(self):
413            Konstants = self.Konstants
414            self.assertFormatIsValue('{0}', Konstants.TAU)
415            self.assertFormatIsValue('{0:}', Konstants.TAU)
416            self.assertFormatIsValue('{0:20}', Konstants.TAU)
417            self.assertFormatIsValue('{0:^20}', Konstants.TAU)
418            self.assertFormatIsValue('{0:>20}', Konstants.TAU)
419            self.assertFormatIsValue('{0:<20}', Konstants.TAU)
420            self.assertFormatIsValue('{0:n}', Konstants.TAU)
421            self.assertFormatIsValue('{0:5.2}', Konstants.TAU)
422            self.assertFormatIsValue('{0:f}', Konstants.TAU)
423
424        def test_format_enum_int(self):
425            Grades = self.Grades
426            self.assertFormatIsValue('{0}', Grades.C)
427            self.assertFormatIsValue('{0:}', Grades.C)
428            self.assertFormatIsValue('{0:20}', Grades.C)
429            self.assertFormatIsValue('{0:^20}', Grades.C)
430            self.assertFormatIsValue('{0:>20}', Grades.C)
431            self.assertFormatIsValue('{0:<20}', Grades.C)
432            self.assertFormatIsValue('{0:+}', Grades.C)
433            self.assertFormatIsValue('{0:08X}', Grades.C)
434            self.assertFormatIsValue('{0:b}', Grades.C)
435
436        def test_format_enum_str(self):
437            Directional = self.Directional
438            self.assertFormatIsValue('{0}', Directional.WEST)
439            self.assertFormatIsValue('{0:}', Directional.WEST)
440            self.assertFormatIsValue('{0:20}', Directional.WEST)
441            self.assertFormatIsValue('{0:^20}', Directional.WEST)
442            self.assertFormatIsValue('{0:>20}', Directional.WEST)
443            self.assertFormatIsValue('{0:<20}', Directional.WEST)
444
445    def test_hash(self):
446        Season = self.Season
447        dates = {}
448        dates[Season.WINTER] = '1225'
449        dates[Season.SPRING] = '0315'
450        dates[Season.SUMMER] = '0704'
451        dates[Season.AUTUMN] = '1031'
452        self.assertEqual(dates[Season.AUTUMN], '1031')
453
454    def test_enum_duplicates(self):
455        class Season(Enum):
456            _order_ = "SPRING SUMMER AUTUMN WINTER"
457            SPRING = 1
458            SUMMER = 2
459            AUTUMN = FALL = 3
460            WINTER = 4
461            ANOTHER_SPRING = 1
462        lst = list(Season)
463        self.assertEqual(
464            lst,
465            [Season.SPRING, Season.SUMMER,
466             Season.AUTUMN, Season.WINTER,
467            ])
468        self.assertTrue(Season.FALL is Season.AUTUMN)
469        self.assertEqual(Season.FALL.value, 3)
470        self.assertEqual(Season.AUTUMN.value, 3)
471        self.assertTrue(Season(3) is Season.AUTUMN)
472        self.assertTrue(Season(1) is Season.SPRING)
473        self.assertEqual(Season.FALL.name, 'AUTUMN')
474        self.assertEqual(
475                set([k for k,v in Season.__members__.items() if v.name != k]),
476                set(['FALL', 'ANOTHER_SPRING']),
477                )
478
479    if pyver >= 3.0:
480        cls = vars()
481        result = {'Enum':Enum}
482        exec("""def test_duplicate_name(self):
483            with self.assertRaises(TypeError):
484                class Color(Enum):
485                    red = 1
486                    green = 2
487                    blue = 3
488                    red = 4
489
490            with self.assertRaises(TypeError):
491                class Color(Enum):
492                    red = 1
493                    green = 2
494                    blue = 3
495                    def red(self):
496                        return 'red'
497
498            with self.assertRaises(TypeError):
499                class Color(Enum):
500                    @property
501
502                    def red(self):
503                        return 'redder'
504                    red = 1
505                    green = 2
506                    blue = 3""",
507            result)
508        cls['test_duplicate_name'] = result['test_duplicate_name']
509
510    def test_enum_with_value_name(self):
511        class Huh(Enum):
512            name = 1
513            value = 2
514        self.assertEqual(
515            list(Huh),
516            [Huh.name, Huh.value],
517            )
518        self.assertTrue(type(Huh.name) is Huh)
519        self.assertEqual(Huh.name.name, 'name')
520        self.assertEqual(Huh.name.value, 1)
521
522    def test_intenum_from_scratch(self):
523        class phy(int, Enum):
524            pi = 3
525            tau = 2 * pi
526        self.assertTrue(phy.pi < phy.tau)
527
528    def test_intenum_inherited(self):
529        class IntEnum(int, Enum):
530            pass
531        class phy(IntEnum):
532            pi = 3
533            tau = 2 * pi
534        self.assertTrue(phy.pi < phy.tau)
535
536    def test_floatenum_from_scratch(self):
537        class phy(float, Enum):
538            pi = 3.1415926
539            tau = 2 * pi
540        self.assertTrue(phy.pi < phy.tau)
541
542    def test_floatenum_inherited(self):
543        class FloatEnum(float, Enum):
544            pass
545        class phy(FloatEnum):
546            pi = 3.1415926
547            tau = 2 * pi
548        self.assertTrue(phy.pi < phy.tau)
549
550    def test_strenum_from_scratch(self):
551        class phy(str, Enum):
552            pi = 'Pi'
553            tau = 'Tau'
554        self.assertTrue(phy.pi < phy.tau)
555
556    def test_strenum_inherited(self):
557        class StrEnum(str, Enum):
558            pass
559        class phy(StrEnum):
560            pi = 'Pi'
561            tau = 'Tau'
562        self.assertTrue(phy.pi < phy.tau)
563
564    def test_intenum(self):
565        class WeekDay(IntEnum):
566            SUNDAY = 1
567            MONDAY = 2
568            TUESDAY = 3
569            WEDNESDAY = 4
570            THURSDAY = 5
571            FRIDAY = 6
572            SATURDAY = 7
573
574        self.assertEqual(['a', 'b', 'c'][WeekDay.MONDAY], 'c')
575        self.assertEqual([i for i in range(WeekDay.TUESDAY)], [0, 1, 2])
576
577        lst = list(WeekDay)
578        self.assertEqual(len(lst), len(WeekDay))
579        self.assertEqual(len(WeekDay), 7)
580        target = 'SUNDAY MONDAY TUESDAY WEDNESDAY THURSDAY FRIDAY SATURDAY'
581        target = target.split()
582        for i, weekday in enumerate(target):
583            i += 1
584            e = WeekDay(i)
585            self.assertEqual(e, i)
586            self.assertEqual(int(e), i)
587            self.assertEqual(e.name, weekday)
588            self.assertTrue(e in WeekDay)
589            self.assertEqual(lst.index(e)+1, i)
590            self.assertTrue(0 < e < 8)
591            self.assertTrue(type(e) is WeekDay)
592            self.assertTrue(isinstance(e, int))
593            self.assertTrue(isinstance(e, Enum))
594
595    def test_intenum_duplicates(self):
596        class WeekDay(IntEnum):
597            __order__ = 'SUNDAY MONDAY TUESDAY WEDNESDAY THURSDAY FRIDAY SATURDAY'
598            SUNDAY = 1
599            MONDAY = 2
600            TUESDAY = TEUSDAY = 3
601            WEDNESDAY = 4
602            THURSDAY = 5
603            FRIDAY = 6
604            SATURDAY = 7
605        self.assertTrue(WeekDay.TEUSDAY is WeekDay.TUESDAY)
606        self.assertEqual(WeekDay(3).name, 'TUESDAY')
607        self.assertEqual([k for k,v in WeekDay.__members__.items()
608                if v.name != k], ['TEUSDAY', ])
609
610    def test_pickle_enum(self):
611        if isinstance(Stooges, Exception):
612            raise Stooges
613        test_pickle_dump_load(self.assertTrue, Stooges.CURLY)
614        test_pickle_dump_load(self.assertTrue, Stooges)
615
616    def test_pickle_int(self):
617        if isinstance(IntStooges, Exception):
618            raise IntStooges
619        test_pickle_dump_load(self.assertTrue, IntStooges.CURLY)
620        test_pickle_dump_load(self.assertTrue, IntStooges)
621
622    def test_pickle_float(self):
623        if isinstance(FloatStooges, Exception):
624            raise FloatStooges
625        test_pickle_dump_load(self.assertTrue, FloatStooges.CURLY)
626        test_pickle_dump_load(self.assertTrue, FloatStooges)
627
628    def test_pickle_enum_function(self):
629        if isinstance(Answer, Exception):
630            raise Answer
631        test_pickle_dump_load(self.assertTrue, Answer.him)
632        test_pickle_dump_load(self.assertTrue, Answer)
633
634    def test_pickle_enum_function_with_module(self):
635        if isinstance(Question, Exception):
636            raise Question
637        test_pickle_dump_load(self.assertTrue, Question.who)
638        test_pickle_dump_load(self.assertTrue, Question)
639
640    if pyver == 3.4:
641        def test_class_nested_enum_and_pickle_protocol_four(self):
642            # would normally just have this directly in the class namespace
643            class NestedEnum(Enum):
644                twigs = 'common'
645                shiny = 'rare'
646
647            self.__class__.NestedEnum = NestedEnum
648            self.NestedEnum.__qualname__ = '%s.NestedEnum' % self.__class__.__name__
649            test_pickle_exception(
650                    self.assertRaises, PicklingError, self.NestedEnum.twigs,
651                    protocol=(0, 3))
652            test_pickle_dump_load(self.assertTrue, self.NestedEnum.twigs,
653                    protocol=(4, HIGHEST_PROTOCOL))
654
655    elif pyver == 3.5:
656        def test_class_nested_enum_and_pickle_protocol_four(self):
657            # would normally just have this directly in the class namespace
658            class NestedEnum(Enum):
659                twigs = 'common'
660                shiny = 'rare'
661
662            self.__class__.NestedEnum = NestedEnum
663            self.NestedEnum.__qualname__ = '%s.NestedEnum' % self.__class__.__name__
664            test_pickle_dump_load(self.assertTrue, self.NestedEnum.twigs,
665                    protocol=(0, HIGHEST_PROTOCOL))
666
667    def test_exploding_pickle(self):
668        BadPickle = Enum('BadPickle', 'dill sweet bread_n_butter')
669        enum._make_class_unpicklable(BadPickle)
670        globals()['BadPickle'] = BadPickle
671        test_pickle_exception(self.assertRaises, TypeError, BadPickle.dill)
672        test_pickle_exception(self.assertRaises, PicklingError, BadPickle)
673
674    def test_string_enum(self):
675        class SkillLevel(str, Enum):
676            master = 'what is the sound of one hand clapping?'
677            journeyman = 'why did the chicken cross the road?'
678            apprentice = 'knock, knock!'
679        self.assertEqual(SkillLevel.apprentice, 'knock, knock!')
680
681    def test_getattr_getitem(self):
682        class Period(Enum):
683            morning = 1
684            noon = 2
685            evening = 3
686            night = 4
687        self.assertTrue(Period(2) is Period.noon)
688        self.assertTrue(getattr(Period, 'night') is Period.night)
689        self.assertTrue(Period['morning'] is Period.morning)
690
691    def test_getattr_dunder(self):
692        Season = self.Season
693        self.assertTrue(getattr(Season, '__hash__'))
694
695    def test_iteration_order(self):
696        class Season(Enum):
697            _order_ = 'SUMMER WINTER AUTUMN SPRING'
698            SUMMER = 2
699            WINTER = 4
700            AUTUMN = 3
701            SPRING = 1
702        self.assertEqual(
703                list(Season),
704                [Season.SUMMER, Season.WINTER, Season.AUTUMN, Season.SPRING],
705                )
706
707    def test_iteration_order_reversed(self):
708        self.assertEqual(
709                list(reversed(self.Season)),
710                [self.Season.WINTER, self.Season.AUTUMN, self.Season.SUMMER,
711                 self.Season.SPRING]
712                )
713
714    def test_iteration_order_with_unorderable_values(self):
715        class Complex(Enum):
716            a = complex(7, 9)
717            b = complex(3.14, 2)
718            c = complex(1, -1)
719            d = complex(-77, 32)
720        self.assertEqual(
721                list(Complex),
722                [Complex.a, Complex.b, Complex.c, Complex.d],
723                )
724
725    def test_programatic_function_string(self):
726        SummerMonth = Enum('SummerMonth', 'june july august')
727        lst = list(SummerMonth)
728        self.assertEqual(len(lst), len(SummerMonth))
729        self.assertEqual(len(SummerMonth), 3, SummerMonth)
730        self.assertEqual(
731                [SummerMonth.june, SummerMonth.july, SummerMonth.august],
732                lst,
733                )
734        for i, month in enumerate('june july august'.split()):
735            i += 1
736            e = SummerMonth(i)
737            self.assertEqual(int(e.value), i)
738            self.assertNotEqual(e, i)
739            self.assertEqual(e.name, month)
740            self.assertTrue(e in SummerMonth)
741            self.assertTrue(type(e) is SummerMonth)
742
743    def test_programatic_function_string_with_start(self):
744        SummerMonth = Enum('SummerMonth', 'june july august', start=10)
745        lst = list(SummerMonth)
746        self.assertEqual(len(lst), len(SummerMonth))
747        self.assertEqual(len(SummerMonth), 3, SummerMonth)
748        self.assertEqual(
749                [SummerMonth.june, SummerMonth.july, SummerMonth.august],
750                lst,
751                )
752        for i, month in enumerate('june july august'.split(), 10):
753            e = SummerMonth(i)
754            self.assertEqual(int(e.value), i)
755            self.assertNotEqual(e, i)
756            self.assertEqual(e.name, month)
757            self.assertTrue(e in SummerMonth)
758            self.assertTrue(type(e) is SummerMonth)
759
760    def test_programatic_function_string_list(self):
761        SummerMonth = Enum('SummerMonth', ['june', 'july', 'august'])
762        lst = list(SummerMonth)
763        self.assertEqual(len(lst), len(SummerMonth))
764        self.assertEqual(len(SummerMonth), 3, SummerMonth)
765        self.assertEqual(
766                [SummerMonth.june, SummerMonth.july, SummerMonth.august],
767                lst,
768                )
769        for i, month in enumerate('june july august'.split()):
770            i += 1
771            e = SummerMonth(i)
772            self.assertEqual(int(e.value), i)
773            self.assertNotEqual(e, i)
774            self.assertEqual(e.name, month)
775            self.assertTrue(e in SummerMonth)
776            self.assertTrue(type(e) is SummerMonth)
777
778    def test_programatic_function_string_list_with_start(self):
779        SummerMonth = Enum('SummerMonth', ['june', 'july', 'august'], start=20)
780        lst = list(SummerMonth)
781        self.assertEqual(len(lst), len(SummerMonth))
782        self.assertEqual(len(SummerMonth), 3, SummerMonth)
783        self.assertEqual(
784                [SummerMonth.june, SummerMonth.july, SummerMonth.august],
785                lst,
786                )
787        for i, month in enumerate('june july august'.split(), 20):
788            e = SummerMonth(i)
789            self.assertEqual(int(e.value), i)
790            self.assertNotEqual(e, i)
791            self.assertEqual(e.name, month)
792            self.assertTrue(e in SummerMonth)
793            self.assertTrue(type(e) is SummerMonth)
794
795    def test_programatic_function_iterable(self):
796        SummerMonth = Enum(
797                'SummerMonth',
798                (('june', 1), ('july', 2), ('august', 3))
799                )
800        lst = list(SummerMonth)
801        self.assertEqual(len(lst), len(SummerMonth))
802        self.assertEqual(len(SummerMonth), 3, SummerMonth)
803        self.assertEqual(
804                [SummerMonth.june, SummerMonth.july, SummerMonth.august],
805                lst,
806                )
807        for i, month in enumerate('june july august'.split()):
808            i += 1
809            e = SummerMonth(i)
810            self.assertEqual(int(e.value), i)
811            self.assertNotEqual(e, i)
812            self.assertEqual(e.name, month)
813            self.assertTrue(e in SummerMonth)
814            self.assertTrue(type(e) is SummerMonth)
815
816    def test_programatic_function_iterable_with_weird_names(self):
817        SummerMonth = Enum(
818                'SummerMonth',
819                (('june', 1), ('july', 2), ('august', 3), ('fabulous september', 4))
820                )
821        lst = list(SummerMonth)
822        self.assertEqual(len(lst), len(SummerMonth))
823        self.assertEqual(len(SummerMonth), 4, SummerMonth)
824        self.assertEqual(
825                [SummerMonth.june, SummerMonth.july, SummerMonth.august, SummerMonth['fabulous september']],
826                lst,
827                )
828        for i, month in enumerate('june july august'.split() + ['fabulous september']):
829            i += 1
830            e = SummerMonth(i)
831            self.assertEqual(int(e.value), i)
832            self.assertNotEqual(e, i)
833            self.assertEqual(e.name, month)
834            self.assertTrue(e in SummerMonth)
835            self.assertTrue(type(e) is SummerMonth)
836
837    def test_programatic_function_from_dict(self):
838        SummerMonth = Enum(
839                'SummerMonth',
840                dict((('june', 1), ('july', 2), ('august', 3)))
841                )
842        lst = list(SummerMonth)
843        self.assertEqual(len(lst), len(SummerMonth))
844        self.assertEqual(len(SummerMonth), 3, SummerMonth)
845        if pyver < 3.0:
846            self.assertEqual(
847                    [SummerMonth.june, SummerMonth.july, SummerMonth.august],
848                    lst,
849                    )
850        for i, month in enumerate('june july august'.split()):
851            i += 1
852            e = SummerMonth(i)
853            self.assertEqual(int(e.value), i)
854            self.assertNotEqual(e, i)
855            self.assertEqual(e.name, month)
856            self.assertTrue(e in SummerMonth)
857            self.assertTrue(type(e) is SummerMonth)
858
859    def test_programatic_function_type(self):
860        SummerMonth = Enum('SummerMonth', 'june july august', type=int)
861        lst = list(SummerMonth)
862        self.assertEqual(len(lst), len(SummerMonth))
863        self.assertEqual(len(SummerMonth), 3, SummerMonth)
864        self.assertEqual(
865                [SummerMonth.june, SummerMonth.july, SummerMonth.august],
866                lst,
867                )
868        for i, month in enumerate('june july august'.split()):
869            i += 1
870            e = SummerMonth(i)
871            self.assertEqual(e, i)
872            self.assertEqual(e.name, month)
873            self.assertTrue(e in SummerMonth)
874            self.assertTrue(type(e) is SummerMonth)
875
876    def test_programatic_function_type_with_start(self):
877        SummerMonth = Enum('SummerMonth', 'june july august', type=int, start=30)
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(), 30):
886            e = SummerMonth(i)
887            self.assertEqual(e, i)
888            self.assertEqual(e.name, month)
889            self.assertTrue(e in SummerMonth)
890            self.assertTrue(type(e) is SummerMonth)
891
892    def test_programatic_function_type_from_subclass(self):
893        SummerMonth = IntEnum('SummerMonth', 'june july august')
894        lst = list(SummerMonth)
895        self.assertEqual(len(lst), len(SummerMonth))
896        self.assertEqual(len(SummerMonth), 3, SummerMonth)
897        self.assertEqual(
898                [SummerMonth.june, SummerMonth.july, SummerMonth.august],
899                lst,
900                )
901        for i, month in enumerate('june july august'.split()):
902            i += 1
903            e = SummerMonth(i)
904            self.assertEqual(e, i)
905            self.assertEqual(e.name, month)
906            self.assertTrue(e in SummerMonth)
907            self.assertTrue(type(e) is SummerMonth)
908
909    def test_programatic_function_type_from_subclass_with_start(self):
910        SummerMonth = IntEnum('SummerMonth', 'june july august', start=40)
911        lst = list(SummerMonth)
912        self.assertEqual(len(lst), len(SummerMonth))
913        self.assertEqual(len(SummerMonth), 3, SummerMonth)
914        self.assertEqual(
915                [SummerMonth.june, SummerMonth.july, SummerMonth.august],
916                lst,
917                )
918        for i, month in enumerate('june july august'.split(), 40):
919            e = SummerMonth(i)
920            self.assertEqual(e, i)
921            self.assertEqual(e.name, month)
922            self.assertTrue(e in SummerMonth)
923            self.assertTrue(type(e) is SummerMonth)
924
925    def test_programatic_function_unicode(self):
926        SummerMonth = Enum('SummerMonth', unicode('june july august'))
927        lst = list(SummerMonth)
928        self.assertEqual(len(lst), len(SummerMonth))
929        self.assertEqual(len(SummerMonth), 3, SummerMonth)
930        self.assertEqual(
931                [SummerMonth.june, SummerMonth.july, SummerMonth.august],
932                lst,
933                )
934        for i, month in enumerate(unicode('june july august').split()):
935            i += 1
936            e = SummerMonth(i)
937            self.assertEqual(int(e.value), i)
938            self.assertNotEqual(e, i)
939            self.assertEqual(e.name, month)
940            self.assertTrue(e in SummerMonth)
941            self.assertTrue(type(e) is SummerMonth)
942
943    def test_programatic_function_unicode_list(self):
944        SummerMonth = Enum('SummerMonth', [unicode('june'), unicode('july'), unicode('august')])
945        lst = list(SummerMonth)
946        self.assertEqual(len(lst), len(SummerMonth))
947        self.assertEqual(len(SummerMonth), 3, SummerMonth)
948        self.assertEqual(
949                [SummerMonth.june, SummerMonth.july, SummerMonth.august],
950                lst,
951                )
952        for i, month in enumerate(unicode('june july august').split()):
953            i += 1
954            e = SummerMonth(i)
955            self.assertEqual(int(e.value), i)
956            self.assertNotEqual(e, i)
957            self.assertEqual(e.name, month)
958            self.assertTrue(e in SummerMonth)
959            self.assertTrue(type(e) is SummerMonth)
960
961    def test_programatic_function_unicode_iterable(self):
962        SummerMonth = Enum(
963                'SummerMonth',
964                ((unicode('june'), 1), (unicode('july'), 2), (unicode('august'), 3))
965                )
966        lst = list(SummerMonth)
967        self.assertEqual(len(lst), len(SummerMonth))
968        self.assertEqual(len(SummerMonth), 3, SummerMonth)
969        self.assertEqual(
970                [SummerMonth.june, SummerMonth.july, SummerMonth.august],
971                lst,
972                )
973        for i, month in enumerate(unicode('june july august').split()):
974            i += 1
975            e = SummerMonth(i)
976            self.assertEqual(int(e.value), i)
977            self.assertNotEqual(e, i)
978            self.assertEqual(e.name, month)
979            self.assertTrue(e in SummerMonth)
980            self.assertTrue(type(e) is SummerMonth)
981
982    def test_programatic_function_from_unicode_dict(self):
983        SummerMonth = Enum(
984                'SummerMonth',
985                dict(((unicode('june'), 1), (unicode('july'), 2), (unicode('august'), 3)))
986                )
987        lst = list(SummerMonth)
988        self.assertEqual(len(lst), len(SummerMonth))
989        self.assertEqual(len(SummerMonth), 3, SummerMonth)
990        if pyver < 3.0:
991            self.assertEqual(
992                    [SummerMonth.june, SummerMonth.july, SummerMonth.august],
993                    lst,
994                    )
995        for i, month in enumerate(unicode('june july august').split()):
996            i += 1
997            e = SummerMonth(i)
998            self.assertEqual(int(e.value), i)
999            self.assertNotEqual(e, i)
1000            self.assertEqual(e.name, month)
1001            self.assertTrue(e in SummerMonth)
1002            self.assertTrue(type(e) is SummerMonth)
1003
1004    def test_programatic_function_unicode_type(self):
1005        SummerMonth = Enum('SummerMonth', unicode('june july august'), type=int)
1006        lst = list(SummerMonth)
1007        self.assertEqual(len(lst), len(SummerMonth))
1008        self.assertEqual(len(SummerMonth), 3, SummerMonth)
1009        self.assertEqual(
1010                [SummerMonth.june, SummerMonth.july, SummerMonth.august],
1011                lst,
1012                )
1013        for i, month in enumerate(unicode('june july august').split()):
1014            i += 1
1015            e = SummerMonth(i)
1016            self.assertEqual(e, i)
1017            self.assertEqual(e.name, month)
1018            self.assertTrue(e in SummerMonth)
1019            self.assertTrue(type(e) is SummerMonth)
1020
1021    def test_programatic_function_unicode_type_from_subclass(self):
1022        SummerMonth = IntEnum('SummerMonth', unicode('june july august'))
1023        lst = list(SummerMonth)
1024        self.assertEqual(len(lst), len(SummerMonth))
1025        self.assertEqual(len(SummerMonth), 3, SummerMonth)
1026        self.assertEqual(
1027                [SummerMonth.june, SummerMonth.july, SummerMonth.august],
1028                lst,
1029                )
1030        for i, month in enumerate(unicode('june july august').split()):
1031            i += 1
1032            e = SummerMonth(i)
1033            self.assertEqual(e, i)
1034            self.assertEqual(e.name, month)
1035            self.assertTrue(e in SummerMonth)
1036            self.assertTrue(type(e) is SummerMonth)
1037
1038    def test_programmatic_function_unicode_class(self):
1039        if pyver < 3.0:
1040            class_names = unicode('SummerMonth'), 'S\xfcmm\xe9rM\xf6nth'.decode('latin1')
1041        else:
1042            class_names = 'SummerMonth', 'S\xfcmm\xe9rM\xf6nth'
1043        for i, class_name in enumerate(class_names):
1044            if pyver < 3.0 and i == 1:
1045                self.assertRaises(TypeError, Enum, class_name, unicode('june july august'))
1046            else:
1047                SummerMonth = Enum(class_name, unicode('june july august'))
1048                lst = list(SummerMonth)
1049                self.assertEqual(len(lst), len(SummerMonth))
1050                self.assertEqual(len(SummerMonth), 3, SummerMonth)
1051                self.assertEqual(
1052                        [SummerMonth.june, SummerMonth.july, SummerMonth.august],
1053                        lst,
1054                        )
1055                for i, month in enumerate(unicode('june july august').split()):
1056                    i += 1
1057                    e = SummerMonth(i)
1058                    self.assertEqual(e.value, i)
1059                    self.assertEqual(e.name, month)
1060                    self.assertTrue(e in SummerMonth)
1061                    self.assertTrue(type(e) is SummerMonth)
1062
1063    def test_subclassing(self):
1064        if isinstance(Name, Exception):
1065            raise Name
1066        self.assertEqual(Name.BDFL, 'Guido van Rossum')
1067        self.assertTrue(Name.BDFL, Name('Guido van Rossum'))
1068        self.assertTrue(Name.BDFL is getattr(Name, 'BDFL'))
1069        test_pickle_dump_load(self.assertTrue, Name.BDFL)
1070
1071    def test_extending(self):
1072        def bad_extension():
1073            class Color(Enum):
1074                red = 1
1075                green = 2
1076                blue = 3
1077            class MoreColor(Color):
1078                cyan = 4
1079                magenta = 5
1080                yellow = 6
1081        self.assertRaises(TypeError, bad_extension)
1082
1083    def test_exclude_methods(self):
1084        class whatever(Enum):
1085            this = 'that'
1086            these = 'those'
1087            def really(self):
1088                return 'no, not %s' % self.value
1089        self.assertFalse(type(whatever.really) is whatever)
1090        self.assertEqual(whatever.this.really(), 'no, not that')
1091
1092    def test_wrong_inheritance_order(self):
1093        def wrong_inherit():
1094            class Wrong(Enum, str):
1095                NotHere = 'error before this point'
1096        self.assertRaises(TypeError, wrong_inherit)
1097
1098    def test_intenum_transitivity(self):
1099        class number(IntEnum):
1100            one = 1
1101            two = 2
1102            three = 3
1103        class numero(IntEnum):
1104            uno = 1
1105            dos = 2
1106            tres = 3
1107        self.assertEqual(number.one, numero.uno)
1108        self.assertEqual(number.two, numero.dos)
1109        self.assertEqual(number.three, numero.tres)
1110
1111    def test_introspection(self):
1112        class Number(IntEnum):
1113            one = 100
1114            two = 200
1115        self.assertTrue(Number.one._member_type_ is int)
1116        self.assertTrue(Number._member_type_ is int)
1117        class String(str, Enum):
1118            yarn = 'soft'
1119            rope = 'rough'
1120            wire = 'hard'
1121        self.assertTrue(String.yarn._member_type_ is str)
1122        self.assertTrue(String._member_type_ is str)
1123        class Plain(Enum):
1124            vanilla = 'white'
1125            one = 1
1126        self.assertTrue(Plain.vanilla._member_type_ is object)
1127        self.assertTrue(Plain._member_type_ is object)
1128
1129    def test_wrong_enum_in_call(self):
1130        class Monochrome(Enum):
1131            black = 0
1132            white = 1
1133        class Gender(Enum):
1134            male = 0
1135            female = 1
1136        self.assertRaises(ValueError, Monochrome, Gender.male)
1137
1138    def test_wrong_enum_in_mixed_call(self):
1139        class Monochrome(IntEnum):
1140            black = 0
1141            white = 1
1142        class Gender(Enum):
1143            male = 0
1144            female = 1
1145        self.assertRaises(ValueError, Monochrome, Gender.male)
1146
1147    def test_mixed_enum_in_call_1(self):
1148        class Monochrome(IntEnum):
1149            black = 0
1150            white = 1
1151        class Gender(IntEnum):
1152            male = 0
1153            female = 1
1154        self.assertTrue(Monochrome(Gender.female) is Monochrome.white)
1155
1156    def test_mixed_enum_in_call_2(self):
1157        class Monochrome(Enum):
1158            black = 0
1159            white = 1
1160        class Gender(IntEnum):
1161            male = 0
1162            female = 1
1163        self.assertTrue(Monochrome(Gender.male) is Monochrome.black)
1164
1165    def test_flufl_enum(self):
1166        class Fluflnum(Enum):
1167            def __int__(self):
1168                return int(self.value)
1169        class MailManOptions(Fluflnum):
1170            option1 = 1
1171            option2 = 2
1172            option3 = 3
1173        self.assertEqual(int(MailManOptions.option1), 1)
1174
1175    def test_no_such_enum_member(self):
1176        class Color(Enum):
1177            red = 1
1178            green = 2
1179            blue = 3
1180        self.assertRaises(ValueError, Color, 4)
1181        self.assertRaises(KeyError, Color.__getitem__, 'chartreuse')
1182
1183    def test_new_repr(self):
1184        class Color(Enum):
1185            red = 1
1186            green = 2
1187            blue = 3
1188            def __repr__(self):
1189                return "don't you just love shades of %s?" % self.name
1190        self.assertEqual(
1191                repr(Color.blue),
1192                "don't you just love shades of blue?",
1193                )
1194
1195    def test_inherited_repr(self):
1196        class MyEnum(Enum):
1197            def __repr__(self):
1198                return "My name is %s." % self.name
1199        class MyIntEnum(int, MyEnum):
1200            this = 1
1201            that = 2
1202            theother = 3
1203        self.assertEqual(repr(MyIntEnum.that), "My name is that.")
1204
1205    def test_multiple_mixin_mro(self):
1206        class auto_enum(EnumMeta):
1207            def __new__(metacls, cls, bases, classdict):
1208                original_dict = classdict
1209                classdict = enum._EnumDict()
1210                for k, v in original_dict.items():
1211                    classdict[k] = v
1212                temp = type(classdict)()
1213                names = set(classdict._member_names)
1214                i = 0
1215                for k in classdict._member_names:
1216                    v = classdict[k]
1217                    if v == ():
1218                        v = i
1219                    else:
1220                        i = v
1221                    i += 1
1222                    temp[k] = v
1223                for k, v in classdict.items():
1224                    if k not in names:
1225                        temp[k] = v
1226                return super(auto_enum, metacls).__new__(
1227                        metacls, cls, bases, temp)
1228
1229        AutoNumberedEnum = auto_enum('AutoNumberedEnum', (Enum,), {})
1230
1231        AutoIntEnum = auto_enum('AutoIntEnum', (IntEnum,), {})
1232
1233        class TestAutoNumber(AutoNumberedEnum):
1234            a = ()
1235            b = 3
1236            c = ()
1237
1238        class TestAutoInt(AutoIntEnum):
1239            a = ()
1240            b = 3
1241            c = ()
1242
1243    def test_subclasses_with_getnewargs(self):
1244        class NamedInt(int):
1245            __qualname__ = 'NamedInt'  # needed for pickle protocol 4
1246            def __new__(cls, *args):
1247                _args = args
1248                if len(args) < 1:
1249                    raise TypeError("name and value must be specified")
1250                name, args = args[0], args[1:]
1251                self = int.__new__(cls, *args)
1252                self._intname = name
1253                self._args = _args
1254                return self
1255            def __getnewargs__(self):
1256                return self._args
1257            @property
1258            def __name__(self):
1259                return self._intname
1260            def __repr__(self):
1261                # repr() is updated to include the name and type info
1262                return "%s(%r, %s)" % (type(self).__name__,
1263                                             self.__name__,
1264                                             int.__repr__(self))
1265            def __str__(self):
1266                # str() is unchanged, even if it relies on the repr() fallback
1267                base = int
1268                base_str = base.__str__
1269                if base_str.__objclass__ is object:
1270                    return base.__repr__(self)
1271                return base_str(self)
1272            # for simplicity, we only define one operator that
1273            # propagates expressions
1274            def __add__(self, other):
1275                temp = int(self) + int( other)
1276                if isinstance(self, NamedInt) and isinstance(other, NamedInt):
1277                    return NamedInt(
1278                        '(%s + %s)' % (self.__name__, other.__name__),
1279                        temp )
1280                else:
1281                    return temp
1282
1283        class NEI(NamedInt, Enum):
1284            __qualname__ = 'NEI'  # needed for pickle protocol 4
1285            x = ('the-x', 1)
1286            y = ('the-y', 2)
1287
1288        self.assertTrue(NEI.__new__ is Enum.__new__)
1289        self.assertEqual(repr(NEI.x + NEI.y), "NamedInt('(the-x + the-y)', 3)")
1290        globals()['NamedInt'] = NamedInt
1291        globals()['NEI'] = NEI
1292        NI5 = NamedInt('test', 5)
1293        self.assertEqual(NI5, 5)
1294        test_pickle_dump_load(self.assertTrue, NI5, 5)
1295        self.assertEqual(NEI.y.value, 2)
1296        test_pickle_dump_load(self.assertTrue, NEI.y)
1297
1298    if pyver >= 3.4:
1299        def test_subclasses_with_getnewargs_ex(self):
1300            class NamedInt(int):
1301                __qualname__ = 'NamedInt'       # needed for pickle protocol 4
1302                def __new__(cls, *args):
1303                    _args = args
1304                    if len(args) < 2:
1305                        raise TypeError("name and value must be specified")
1306                    name, args = args[0], args[1:]
1307                    self = int.__new__(cls, *args)
1308                    self._intname = name
1309                    self._args = _args
1310                    return self
1311                def __getnewargs_ex__(self):
1312                    return self._args, {}
1313                @property
1314                def __name__(self):
1315                    return self._intname
1316                def __repr__(self):
1317                    # repr() is updated to include the name and type info
1318                    return "{}({!r}, {})".format(type(self).__name__,
1319                                                 self.__name__,
1320                                                 int.__repr__(self))
1321                def __str__(self):
1322                    # str() is unchanged, even if it relies on the repr() fallback
1323                    base = int
1324                    base_str = base.__str__
1325                    if base_str.__objclass__ is object:
1326                        return base.__repr__(self)
1327                    return base_str(self)
1328                # for simplicity, we only define one operator that
1329                # propagates expressions
1330                def __add__(self, other):
1331                    temp = int(self) + int( other)
1332                    if isinstance(self, NamedInt) and isinstance(other, NamedInt):
1333                        return NamedInt(
1334                            '({0} + {1})'.format(self.__name__, other.__name__),
1335                            temp )
1336                    else:
1337                        return temp
1338
1339            class NEI(NamedInt, Enum):
1340                __qualname__ = 'NEI'      # needed for pickle protocol 4
1341                x = ('the-x', 1)
1342                y = ('the-y', 2)
1343
1344
1345            self.assertIs(NEI.__new__, Enum.__new__)
1346            self.assertEqual(repr(NEI.x + NEI.y), "NamedInt('(the-x + the-y)', 3)")
1347            globals()['NamedInt'] = NamedInt
1348            globals()['NEI'] = NEI
1349            NI5 = NamedInt('test', 5)
1350            self.assertEqual(NI5, 5)
1351            test_pickle_dump_load(self.assertEqual, NI5, 5, protocol=(4, HIGHEST_PROTOCOL))
1352            self.assertEqual(NEI.y.value, 2)
1353            test_pickle_dump_load(self.assertTrue, NEI.y, protocol=(4, HIGHEST_PROTOCOL))
1354
1355    def test_subclasses_with_reduce(self):
1356        class NamedInt(int):
1357            __qualname__ = 'NamedInt'       # needed for pickle protocol 4
1358            def __new__(cls, *args):
1359                _args = args
1360                if len(args) < 1:
1361                    raise TypeError("name and value must be specified")
1362                name, args = args[0], args[1:]
1363                self = int.__new__(cls, *args)
1364                self._intname = name
1365                self._args = _args
1366                return self
1367            def __reduce__(self):
1368                return self.__class__, self._args
1369            @property
1370            def __name__(self):
1371                return self._intname
1372            def __repr__(self):
1373                # repr() is updated to include the name and type info
1374                return "%s(%r, %s)" % (type(self).__name__,
1375                                             self.__name__,
1376                                             int.__repr__(self))
1377            def __str__(self):
1378                # str() is unchanged, even if it relies on the repr() fallback
1379                base = int
1380                base_str = base.__str__
1381                if base_str.__objclass__ is object:
1382                    return base.__repr__(self)
1383                return base_str(self)
1384            # for simplicity, we only define one operator that
1385            # propagates expressions
1386            def __add__(self, other):
1387                temp = int(self) + int( other)
1388                if isinstance(self, NamedInt) and isinstance(other, NamedInt):
1389                    return NamedInt(
1390                        '(%s + %s)' % (self.__name__, other.__name__),
1391                        temp )
1392                else:
1393                    return temp
1394
1395        class NEI(NamedInt, Enum):
1396            __qualname__ = 'NEI'      # needed for pickle protocol 4
1397            x = ('the-x', 1)
1398            y = ('the-y', 2)
1399
1400
1401        self.assertTrue(NEI.__new__ is Enum.__new__)
1402        self.assertEqual(repr(NEI.x + NEI.y), "NamedInt('(the-x + the-y)', 3)")
1403        globals()['NamedInt'] = NamedInt
1404        globals()['NEI'] = NEI
1405        NI5 = NamedInt('test', 5)
1406        self.assertEqual(NI5, 5)
1407        test_pickle_dump_load(self.assertEqual, NI5, 5)
1408        self.assertEqual(NEI.y.value, 2)
1409        test_pickle_dump_load(self.assertTrue, NEI.y)
1410
1411    def test_subclasses_with_reduce_ex(self):
1412        class NamedInt(int):
1413            __qualname__ = 'NamedInt'       # needed for pickle protocol 4
1414            def __new__(cls, *args):
1415                _args = args
1416                if len(args) < 1:
1417                    raise TypeError("name and value must be specified")
1418                name, args = args[0], args[1:]
1419                self = int.__new__(cls, *args)
1420                self._intname = name
1421                self._args = _args
1422                return self
1423            def __reduce_ex__(self, proto):
1424                return self.__class__, self._args
1425            @property
1426            def __name__(self):
1427                return self._intname
1428            def __repr__(self):
1429                # repr() is updated to include the name and type info
1430                return "%s(%r, %s)" % (type(self).__name__,
1431                                             self.__name__,
1432                                             int.__repr__(self))
1433            def __str__(self):
1434                # str() is unchanged, even if it relies on the repr() fallback
1435                base = int
1436                base_str = base.__str__
1437                if base_str.__objclass__ is object:
1438                    return base.__repr__(self)
1439                return base_str(self)
1440            # for simplicity, we only define one operator that
1441            # propagates expressions
1442            def __add__(self, other):
1443                temp = int(self) + int( other)
1444                if isinstance(self, NamedInt) and isinstance(other, NamedInt):
1445                    return NamedInt(
1446                        '(%s + %s)' % (self.__name__, other.__name__),
1447                        temp )
1448                else:
1449                    return temp
1450
1451        class NEI(NamedInt, Enum):
1452            __qualname__ = 'NEI'      # needed for pickle protocol 4
1453            x = ('the-x', 1)
1454            y = ('the-y', 2)
1455
1456
1457        self.assertTrue(NEI.__new__ is Enum.__new__)
1458        self.assertEqual(repr(NEI.x + NEI.y), "NamedInt('(the-x + the-y)', 3)")
1459        globals()['NamedInt'] = NamedInt
1460        globals()['NEI'] = NEI
1461        NI5 = NamedInt('test', 5)
1462        self.assertEqual(NI5, 5)
1463        test_pickle_dump_load(self.assertEqual, NI5, 5)
1464        self.assertEqual(NEI.y.value, 2)
1465        test_pickle_dump_load(self.assertTrue, NEI.y)
1466
1467    def test_subclasses_without_direct_pickle_support(self):
1468        class NamedInt(int):
1469            __qualname__ = 'NamedInt'
1470            def __new__(cls, *args):
1471                _args = args
1472                name, args = args[0], args[1:]
1473                if len(args) == 0:
1474                    raise TypeError("name and value must be specified")
1475                self = int.__new__(cls, *args)
1476                self._intname = name
1477                self._args = _args
1478                return self
1479            @property
1480            def __name__(self):
1481                return self._intname
1482            def __repr__(self):
1483                # repr() is updated to include the name and type info
1484                return "%s(%r, %s)" % (type(self).__name__,
1485                                             self.__name__,
1486                                             int.__repr__(self))
1487            def __str__(self):
1488                # str() is unchanged, even if it relies on the repr() fallback
1489                base = int
1490                base_str = base.__str__
1491                if base_str.__objclass__ is object:
1492                    return base.__repr__(self)
1493                return base_str(self)
1494            # for simplicity, we only define one operator that
1495            # propagates expressions
1496            def __add__(self, other):
1497                temp = int(self) + int( other)
1498                if isinstance(self, NamedInt) and isinstance(other, NamedInt):
1499                    return NamedInt(
1500                        '(%s + %s)' % (self.__name__, other.__name__),
1501                        temp )
1502                else:
1503                    return temp
1504
1505        class NEI(NamedInt, Enum):
1506            __qualname__ = 'NEI'
1507            x = ('the-x', 1)
1508            y = ('the-y', 2)
1509
1510        self.assertTrue(NEI.__new__ is Enum.__new__)
1511        self.assertEqual(repr(NEI.x + NEI.y), "NamedInt('(the-x + the-y)', 3)")
1512        globals()['NamedInt'] = NamedInt
1513        globals()['NEI'] = NEI
1514        NI5 = NamedInt('test', 5)
1515        self.assertEqual(NI5, 5)
1516        self.assertEqual(NEI.y.value, 2)
1517        test_pickle_exception(self.assertRaises, TypeError, NEI.x)
1518        test_pickle_exception(self.assertRaises, PicklingError, NEI)
1519
1520    def test_subclasses_without_direct_pickle_support_using_name(self):
1521        class NamedInt(int):
1522            __qualname__ = 'NamedInt'
1523            def __new__(cls, *args):
1524                _args = args
1525                name, args = args[0], args[1:]
1526                if len(args) == 0:
1527                    raise TypeError("name and value must be specified")
1528                self = int.__new__(cls, *args)
1529                self._intname = name
1530                self._args = _args
1531                return self
1532            @property
1533            def __name__(self):
1534                return self._intname
1535            def __repr__(self):
1536                # repr() is updated to include the name and type info
1537                return "%s(%r, %s)" % (type(self).__name__,
1538                                             self.__name__,
1539                                             int.__repr__(self))
1540            def __str__(self):
1541                # str() is unchanged, even if it relies on the repr() fallback
1542                base = int
1543                base_str = base.__str__
1544                if base_str.__objclass__ is object:
1545                    return base.__repr__(self)
1546                return base_str(self)
1547            # for simplicity, we only define one operator that
1548            # propagates expressions
1549            def __add__(self, other):
1550                temp = int(self) + int( other)
1551                if isinstance(self, NamedInt) and isinstance(other, NamedInt):
1552                    return NamedInt(
1553                        '(%s + %s)' % (self.__name__, other.__name__),
1554                        temp )
1555                else:
1556                    return temp
1557
1558        class NEI(NamedInt, Enum):
1559            __qualname__ = 'NEI'
1560            x = ('the-x', 1)
1561            y = ('the-y', 2)
1562            def __reduce_ex__(self, proto):
1563                return getattr, (self.__class__, self._name_)
1564
1565        self.assertTrue(NEI.__new__ is Enum.__new__)
1566        self.assertEqual(repr(NEI.x + NEI.y), "NamedInt('(the-x + the-y)', 3)")
1567        globals()['NamedInt'] = NamedInt
1568        globals()['NEI'] = NEI
1569        NI5 = NamedInt('test', 5)
1570        self.assertEqual(NI5, 5)
1571        self.assertEqual(NEI.y.value, 2)
1572        test_pickle_dump_load(self.assertTrue, NEI.y)
1573        test_pickle_dump_load(self.assertTrue, NEI)
1574
1575    def test_tuple_subclass(self):
1576        class SomeTuple(tuple, Enum):
1577            __qualname__ = 'SomeTuple'
1578            first = (1, 'for the money')
1579            second = (2, 'for the show')
1580            third = (3, 'for the music')
1581        self.assertTrue(type(SomeTuple.first) is SomeTuple)
1582        self.assertTrue(isinstance(SomeTuple.second, tuple))
1583        self.assertEqual(SomeTuple.third, (3, 'for the music'))
1584        globals()['SomeTuple'] = SomeTuple
1585        test_pickle_dump_load(self.assertTrue, SomeTuple.first)
1586
1587    def test_duplicate_values_give_unique_enum_items(self):
1588        class AutoNumber(Enum):
1589            __order__ = 'enum_m enum_d enum_y'
1590            enum_m = ()
1591            enum_d = ()
1592            enum_y = ()
1593            def __new__(cls):
1594                value = len(cls.__members__) + 1
1595                obj = object.__new__(cls)
1596                obj._value_ = value
1597                return obj
1598            def __int__(self):
1599                return int(self._value_)
1600        self.assertEqual(int(AutoNumber.enum_d), 2)
1601        self.assertEqual(AutoNumber.enum_y.value, 3)
1602        self.assertTrue(AutoNumber(1) is AutoNumber.enum_m)
1603        self.assertEqual(
1604            list(AutoNumber),
1605            [AutoNumber.enum_m, AutoNumber.enum_d, AutoNumber.enum_y],
1606            )
1607
1608    def test_inherited_new_from_enhanced_enum(self):
1609        class AutoNumber2(Enum):
1610            def __new__(cls):
1611                value = len(cls.__members__) + 1
1612                obj = object.__new__(cls)
1613                obj._value_ = value
1614                return obj
1615            def __int__(self):
1616                return int(self._value_)
1617        class Color(AutoNumber2):
1618            _order_ = 'red green blue'
1619            red = ()
1620            green = ()
1621            blue = ()
1622        self.assertEqual(len(Color), 3, "wrong number of elements: %d (should be %d)" % (len(Color), 3))
1623        self.assertEqual(list(Color), [Color.red, Color.green, Color.blue])
1624        if pyver >= 3.0:
1625            self.assertEqual(list(map(int, Color)), [1, 2, 3])
1626
1627    def test_inherited_new_from_mixed_enum(self):
1628        class AutoNumber3(IntEnum):
1629            def __new__(cls):
1630                value = len(cls.__members__) + 1
1631                obj = int.__new__(cls, value)
1632                obj._value_ = value
1633                return obj
1634        class Color(AutoNumber3):
1635            red = ()
1636            green = ()
1637            blue = ()
1638        self.assertEqual(len(Color), 3, "wrong number of elements: %d (should be %d)" % (len(Color), 3))
1639        Color.red
1640        Color.green
1641        Color.blue
1642
1643    def test_equality(self):
1644        class AlwaysEqual:
1645            def __eq__(self, other):
1646                return True
1647        class OrdinaryEnum(Enum):
1648            a = 1
1649        self.assertEqual(AlwaysEqual(), OrdinaryEnum.a)
1650        self.assertEqual(OrdinaryEnum.a, AlwaysEqual())
1651
1652    def test_ordered_mixin(self):
1653        class OrderedEnum(Enum):
1654            def __ge__(self, other):
1655                if self.__class__ is other.__class__:
1656                    return self._value_ >= other._value_
1657                return NotImplemented
1658            def __gt__(self, other):
1659                if self.__class__ is other.__class__:
1660                    return self._value_ > other._value_
1661                return NotImplemented
1662            def __le__(self, other):
1663                if self.__class__ is other.__class__:
1664                    return self._value_ <= other._value_
1665                return NotImplemented
1666            def __lt__(self, other):
1667                if self.__class__ is other.__class__:
1668                    return self._value_ < other._value_
1669                return NotImplemented
1670        class Grade(OrderedEnum):
1671            __order__ = 'A B C D F'
1672            A = 5
1673            B = 4
1674            C = 3
1675            D = 2
1676            F = 1
1677        self.assertEqual(list(Grade), [Grade.A, Grade.B, Grade.C, Grade.D, Grade.F])
1678        self.assertTrue(Grade.A > Grade.B)
1679        self.assertTrue(Grade.F <= Grade.C)
1680        self.assertTrue(Grade.D < Grade.A)
1681        self.assertTrue(Grade.B >= Grade.B)
1682
1683    def test_extending2(self):
1684        def bad_extension():
1685            class Shade(Enum):
1686                def shade(self):
1687                    print(self.name)
1688            class Color(Shade):
1689                red = 1
1690                green = 2
1691                blue = 3
1692            class MoreColor(Color):
1693                cyan = 4
1694                magenta = 5
1695                yellow = 6
1696        self.assertRaises(TypeError, bad_extension)
1697
1698    def test_extending3(self):
1699        class Shade(Enum):
1700            def shade(self):
1701                return self.name
1702        class Color(Shade):
1703            def hex(self):
1704                return '%s hexlified!' % self.value
1705        class MoreColor(Color):
1706            cyan = 4
1707            magenta = 5
1708            yellow = 6
1709        self.assertEqual(MoreColor.magenta.hex(), '5 hexlified!')
1710
1711    def test_no_duplicates(self):
1712        def bad_duplicates():
1713            class UniqueEnum(Enum):
1714                def __init__(self, *args):
1715                    cls = self.__class__
1716                    if any(self.value == e.value for e in cls):
1717                        a = self.name
1718                        e = cls(self.value).name
1719                        raise ValueError(
1720                                "aliases not allowed in UniqueEnum:  %r --> %r"
1721                                % (a, e)
1722                                )
1723            class Color(UniqueEnum):
1724                red = 1
1725                green = 2
1726                blue = 3
1727            class Color(UniqueEnum):
1728                red = 1
1729                green = 2
1730                blue = 3
1731                grene = 2
1732        self.assertRaises(ValueError, bad_duplicates)
1733
1734    def test_init(self):
1735        class Planet(Enum):
1736            MERCURY = (3.303e+23, 2.4397e6)
1737            VENUS   = (4.869e+24, 6.0518e6)
1738            EARTH   = (5.976e+24, 6.37814e6)
1739            MARS    = (6.421e+23, 3.3972e6)
1740            JUPITER = (1.9e+27,   7.1492e7)
1741            SATURN  = (5.688e+26, 6.0268e7)
1742            URANUS  = (8.686e+25, 2.5559e7)
1743            NEPTUNE = (1.024e+26, 2.4746e7)
1744            def __init__(self, mass, radius):
1745                self.mass = mass       # in kilograms
1746                self.radius = radius   # in meters
1747            @property
1748            def surface_gravity(self):
1749                # universal gravitational constant  (m3 kg-1 s-2)
1750                G = 6.67300E-11
1751                return G * self.mass / (self.radius * self.radius)
1752        self.assertEqual(round(Planet.EARTH.surface_gravity, 2), 9.80)
1753        self.assertEqual(Planet.EARTH.value, (5.976e+24, 6.37814e6))
1754
1755    def test_nonhash_value(self):
1756        class AutoNumberInAList(Enum):
1757            def __new__(cls):
1758                value = [len(cls.__members__) + 1]
1759                obj = object.__new__(cls)
1760                obj._value_ = value
1761                return obj
1762        class ColorInAList(AutoNumberInAList):
1763            _order_ = 'red green blue'
1764            red = ()
1765            green = ()
1766            blue = ()
1767        self.assertEqual(list(ColorInAList), [ColorInAList.red, ColorInAList.green, ColorInAList.blue])
1768        self.assertEqual(ColorInAList.red.value, [1])
1769        self.assertEqual(ColorInAList([1]), ColorInAList.red)
1770
1771    def test_conflicting_types_resolved_in_new(self):
1772        class LabelledIntEnum(int, Enum):
1773            def __new__(cls, *args):
1774                value, label = args
1775                obj = int.__new__(cls, value)
1776                obj.label = label
1777                obj._value_ = value
1778                return obj
1779
1780        class LabelledList(LabelledIntEnum):
1781            unprocessed = (1, "Unprocessed")
1782            payment_complete = (2, "Payment Complete")
1783
1784        self.assertEqual(list(LabelledList), [LabelledList.unprocessed, LabelledList.payment_complete])
1785        self.assertEqual(LabelledList.unprocessed, 1)
1786        self.assertEqual(LabelledList(1), LabelledList.unprocessed)
1787
1788    def test_empty_with_functional_api(self):
1789        empty = enum.IntEnum('Foo', {})
1790        self.assertEqual(len(empty), 0)
1791
1792
1793class TestUnique(unittest.TestCase):
1794    """2.4 doesn't allow class decorators, use function syntax."""
1795
1796    def test_unique_clean(self):
1797        class Clean(Enum):
1798            one = 1
1799            two = 'dos'
1800            tres = 4.0
1801        unique(Clean)
1802        class Cleaner(IntEnum):
1803            single = 1
1804            double = 2
1805            triple = 3
1806        unique(Cleaner)
1807
1808    def test_unique_dirty(self):
1809        try:
1810            class Dirty(Enum):
1811                __order__ = 'one two tres'
1812                one = 1
1813                two = 'dos'
1814                tres = 1
1815            unique(Dirty)
1816        except ValueError:
1817            exc = sys.exc_info()[1]
1818            message = exc.args[0]
1819        self.assertTrue('tres -> one' in message)
1820
1821        try:
1822            class Dirtier(IntEnum):
1823                _order_ = 'single double triple turkey'
1824                single = 1
1825                double = 1
1826                triple = 3
1827                turkey = 3
1828            unique(Dirtier)
1829        except ValueError:
1830            exc = sys.exc_info()[1]
1831            message = exc.args[0]
1832        self.assertTrue('double -> single' in message)
1833        self.assertTrue('turkey -> triple' in message)
1834
1835
1836class TestMe(unittest.TestCase):
1837
1838    pass
1839
1840if __name__ == '__main__':
1841    unittest.main()
1842