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