Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(685)

Side by Side Diff: Lib/test/test_enum.py

Issue 17947: Code, test, and doc review for PEP-0435 Enum
Patch Set: Created 6 years, 8 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
View unified diff | Download patch
« Lib/enum.py ('K') | « Lib/enum.py ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 #!/usr/bin/python3.3
2 from collections import OrderedDict
3 from pickle import dumps, loads
4 import unittest
5 from enum import Enum, IntEnum
6 import sys
7
8 print('Using Python', sys.version)
9
10
11 # for pickle tests
12 try:
13 class Stooges(Enum):
14 LARRY = 1
15 CURLY = 2
16 MOE = 3
17 except Exception as exc:
18 print(exc)
19
20 try:
21 class IntStooges(int, Enum):
22 LARRY = 1
23 CURLY = 2
24 MOE = 3
25 except Exception as exc:
26 print(exc)
27
28 try:
29 class FloatStooges(float, Enum):
30 LARRY = 1.39
31 CURLY = 2.72
32 MOE = 3.142596
33 except Exception as exc:
34 print(exc)
35
36 # for pickle test and subclass tests
37 try:
38 class StrEnum(str, Enum):
39 'accepts only string values'
40 class Name(StrEnum):
41 BDFL = 'Guido van Rossum'
42 FLUFL = 'Barry Warsaw'
43 except Exception as exc:
44 print(exc)
45
46 try:
47 Question = Enum('Question', 'who what when where why', module='__main__')
48 except Exception as exc:
49 print(exc)
50
51 try:
52 Answer = Enum('Answer', 'him this then there because')
53 except Exception as exc:
54 print(exc)
55
56 class Test_Enum(unittest.TestCase):
57 def setUp(self):
58 class Season(Enum):
59 SPRING = 1
60 SUMMER = 2
61 AUTUMN = 3
62 WINTER = 4
63 self.Season = Season
64
65 def test_enum_in_enum_out(self):
66 Season = self.Season
67 self.assertIs(Season(Season.WINTER), Season.WINTER)
68
69 def test_dir_on_class(self):
70 Season = self.Season
71 self.assertEqual(
72 set(dir(Season)),
73 set(['__class__', '__doc__', '__members__',
74 'SPRING', 'SUMMER', 'AUTUMN', 'WINTER']),
75 )
76
77 def test_dir_on_item(self):
78 Season = self.Season
79 self.assertEqual(
80 set(dir(Season.WINTER)),
81 set(['__class__', '__doc__', 'name', 'value']),
82 )
83
84 def test_enum(self):
85 Season = self.Season
86 lst = list(Season)
87 self.assertEqual(len(lst), len(Season))
88 self.assertEqual(len(Season), 4, Season)
89 self.assertEqual(
90 [Season.SPRING, Season.SUMMER, Season.AUTUMN, Season.WINTER], lst)
91
92 for i, season in enumerate('SPRING SUMMER AUTUMN WINTER'.split(), 1):
93 e = Season(i)
94 self.assertEqual(e, getattr(Season, season))
95 self.assertEqual(e.value, i)
96 self.assertNotEqual(e, i)
97 self.assertEqual(e.name, season)
98 self.assertIn(e, Season)
99 self.assertTrue(type(e) is Season)
100 self.assertIsInstance(e, Season)
101 self.assertEqual(str(e), 'Season.' + season)
102 self.assertEqual(repr(e),
103 '<Season.{0}: {1}>'.format(season, i))
104 def test_value_name(self):
105 Season = self.Season
106 self.assertEqual(Season.SPRING.name, 'SPRING')
107 self.assertEqual(Season.SPRING.value, 1)
108 with self.assertRaises(AttributeError):
109 Season.SPRING.name = 'invierno'
110 with self.assertRaises(AttributeError):
111 Season.SPRING.value = 2
112
113 def test_contains(self):
114 Season = self.Season
115 self.assertIn(Season.AUTUMN, Season)
116 self.assertNotIn(3, Season)
117
118 val = Season(3)
119 self.assertIn(val, Season)
120
121 class OtherEnum(Enum):
122 one = 1; two = 2
123 self.assertNotIn(OtherEnum.two, Season)
124
125 def test_comparisons(self):
126 Season = self.Season
127 with self.assertRaises(TypeError):
128 Season.SPRING < Season.WINTER
129 with self.assertRaises(TypeError):
130 Season.SPRING > 4
131
132 self.assertNotEqual(Season.SPRING, 1)
133
134 class Part(Enum):
135 SPRING = 1
136 CLIP = 2
137 BARREL = 3
138
139 self.assertNotEqual(Season.SPRING, Part.SPRING)
140 with self.assertRaises(TypeError):
141 Season.SPRING < Part.CLIP
142
143 def test_enum_duplicates(self):
144 class Season(Enum):
145 SPRING = 1
146 SUMMER = 2
147 AUTUMN = FALL = 3
148 WINTER = 4
149 ANOTHER_SPRING = 1
150 lst = list(Season)
151 self.assertEqual(
152 lst,
153 [Season.SPRING, Season.SUMMER,
154 Season.AUTUMN, Season.WINTER,
155 ])
156 self.assertIs(Season.FALL, Season.AUTUMN)
157 self.assertEqual(Season.FALL.value, 3)
158 self.assertEqual(Season.AUTUMN.value, 3)
159 self.assertIs(Season(3), Season.AUTUMN)
160 self.assertIs(Season(1), Season.SPRING)
161 self.assertEqual(Season.FALL.name, 'AUTUMN')
162 self.assertEqual([k for k,v in Season.__members__.items() if v.name != k ], ['FALL', 'ANOTHER_SPRING'])
163
164 def test_enum_with_value_name(self):
165 class Huh(Enum):
166 name = 1
167 value = 2
168 self.assertEqual(
169 list(Huh),
170 [Huh.name, Huh.value],
171 )
172 self.assertTrue(type(Huh.name) is Huh)
173 self.assertEqual(Huh.name.name, 'name')
174 self.assertEqual(Huh.name.value, 1)
175
176 def test_intenum(self):
177 class WeekDay(IntEnum):
178 SUNDAY = 1
179 MONDAY = 2
180 TUESDAY = 3
181 WEDNESDAY = 4
182 THURSDAY = 5
183 FRIDAY = 6
184 SATURDAY = 7
185
186 self.assertEqual(['a', 'b', 'c'][WeekDay.MONDAY], 'c')
187 self.assertEqual([i for i in range(WeekDay.TUESDAY)], [0, 1, 2])
188
189 lst = list(WeekDay)
190 self.assertEqual(len(lst), len(WeekDay))
191 self.assertEqual(len(WeekDay), 7)
192 for i, weekday in enumerate(r'''SUNDAY MONDAY TUESDAY WEDNESDAY
193 THURSDAY FRIDAY SATURDAY'''.split(), 1):
194 e = WeekDay(i)
195 self.assertEqual(e, i)
196 self.assertEqual(int(e), i)
197 self.assertEqual(e.name, weekday)
198 self.assertIn(e, WeekDay)
199 self.assertEqual(lst.index(e)+1, i)
200 self.assertTrue(0 < e < 8)
201 self.assertIs(type(e), WeekDay)
202 self.assertIsInstance(e, int)
203 self.assertIsInstance(e, Enum)
204
205 def test_intenum_duplicates(self):
206 class WeekDay(IntEnum):
207 SUNDAY = 1
208 MONDAY = 2
209 TUESDAY = TEUSDAY = 3
210 WEDNESDAY = 4
211 THURSDAY = 5
212 FRIDAY = 6
213 SATURDAY = 7
214 self.assertTrue(WeekDay.TEUSDAY is WeekDay.TUESDAY)
215 self.assertEqual(WeekDay(3).name, 'TUESDAY')
216 self.assertEqual([k for k,v in WeekDay.__members__.items() if v.name != k], ['TEUSDAY', ])
217
218 def test_pickle_enum(self):
219 self.assertTrue(Stooges.CURLY is loads(dumps(Stooges.CURLY)))
220
221 def test_pickle_int(self):
222 self.assertTrue(IntStooges.CURLY is loads(dumps(IntStooges.CURLY)))
223
224 def test_pickle_float(self):
225 self.assertTrue(FloatStooges.CURLY is loads(dumps(FloatStooges.CURLY)))
226
227 def test_pickle_enum_function(self):
228 self.assertIs(Answer.him, loads(dumps(Answer.him)))
229
230 def test_pickle_enum_function_with_module(self):
231 self.assertIs(Question.who, loads(dumps(Question.who)))
232
233 # not sure how to make this work; create the .py file somewhere importable?
234 # def test_pickle_enum_function_from_other_module(self):
235 # from test_module import Duh
236 # self.assertIs(Duh.umm, loads(dumps(Duh.umm)))
237
238 def test_string_enum(self):
239 class SkillLevel(str, Enum):
240 master = 'what is the sound of one hand clapping?'
241 journeyman = 'why did the chicken cross the road?'
242 apprentice = 'knock, knock!'
243 self.assertEqual(SkillLevel.apprentice, 'knock, knock!')
244
245 def test_getattr_getitem(self):
246 class Period(Enum):
247 morning = 1
248 noon = 2
249 evening = 3
250 night = 4
251 self.assertTrue(Period(2) is Period.noon)
252 self.assertTrue(getattr(Period, 'night') is Period.night)
253 self.assertTrue(Period['morning'] is Period.morning)
254
255 def test_getattr_dunder(self):
256 Season = self.Season
257 self.assertTrue(getattr(Season, '__eq__'))
258
259 def test_iteration_order(self):
260 class Season(Enum):
261 SUMMER = 2
262 WINTER = 4
263 AUTUMN = 3
264 SPRING = 1
265 self.assertEqual(
266 list(Season),
267 [Season.SUMMER, Season.WINTER, Season.AUTUMN, Season.SPRING],
268 )
269
270 def test_programatic_function_string(self):
271 SummerMonth = Enum('SummerMonth', 'june july august')
272 lst = list(SummerMonth)
273 self.assertEqual(len(lst), len(SummerMonth))
274 self.assertEqual(len(SummerMonth), 3, SummerMonth)
275 self.assertEqual([SummerMonth.june, SummerMonth.july, SummerMonth.august ], lst)
276 for i, month in enumerate('june july august'.split(), 1):
277 e = SummerMonth(i)
278 self.assertEqual(int(e.value), i)
279 self.assertNotEqual(e, i)
280 self.assertEqual(e.name, month)
281 self.assertIn(e, SummerMonth)
282 self.assertTrue(type(e) is SummerMonth)
283
284 def test_programatic_function_string_list(self):
285 SummerMonth = Enum('SummerMonth', ['june', 'july', 'august'])
286 lst = list(SummerMonth)
287 self.assertEqual(len(lst), len(SummerMonth))
288 self.assertEqual(len(SummerMonth), 3, SummerMonth)
289 self.assertEqual([SummerMonth.june, SummerMonth.july, SummerMonth.august ], lst)
290 for i, month in enumerate('june july august'.split(), 1):
291 e = SummerMonth(i)
292 self.assertEqual(int(e.value), i)
293 self.assertNotEqual(e, i)
294 self.assertEqual(e.name, month)
295 self.assertIn(e, SummerMonth)
296 self.assertTrue(type(e) is SummerMonth)
297
298 def test_programatic_function_iterable(self):
299 SummerMonth = Enum('SummerMonth', (('june', 1), ('july', 2), ('august', 3)))
300 lst = list(SummerMonth)
301 self.assertEqual(len(lst), len(SummerMonth))
302 self.assertEqual(len(SummerMonth), 3, SummerMonth)
303 self.assertEqual([SummerMonth.june, SummerMonth.july, SummerMonth.august ], lst)
304 for i, month in enumerate('june july august'.split(), 1):
305 e = SummerMonth(i)
306 self.assertEqual(int(e.value), i)
307 self.assertNotEqual(e, i)
308 self.assertEqual(e.name, month)
309 self.assertIn(e, SummerMonth)
310 self.assertTrue(type(e) is SummerMonth)
311
312 def test_programatic_function_from_dict(self):
313 SummerMonth = Enum('SummerMonth', OrderedDict((('june', 1), ('july', 2), ('august', 3))))
314 lst = list(SummerMonth)
315 self.assertEqual(len(lst), len(SummerMonth))
316 self.assertEqual(len(SummerMonth), 3, SummerMonth)
317 self.assertEqual([SummerMonth.june, SummerMonth.july, SummerMonth.august ], lst)
318 for i, month in enumerate('june july august'.split(), 1):
319 e = SummerMonth(i)
320 self.assertEqual(int(e.value), i)
321 self.assertNotEqual(e, i)
322 self.assertEqual(e.name, month)
323 self.assertIn(e, SummerMonth)
324 self.assertTrue(type(e) is SummerMonth)
325
326 def test_programatic_function_type(self):
327 SummerMonth = Enum('SummerMonth', 'june july august', type=int)
328 lst = list(SummerMonth)
329 self.assertEqual(len(lst), len(SummerMonth))
330 self.assertEqual(len(SummerMonth), 3, SummerMonth)
331 self.assertEqual([SummerMonth.june, SummerMonth.july, SummerMonth.august ], lst)
332 for i, month in enumerate('june july august'.split(), 1):
333 e = SummerMonth(i)
334 self.assertEqual(e, i)
335 self.assertEqual(e.name, month)
336 self.assertIn(e, SummerMonth)
337 self.assertTrue(type(e) is SummerMonth)
338
339 def test_programatic_function_type_from_subclass(self):
340 SummerMonth = IntEnum('SummerMonth', 'june july august')
341 lst = list(SummerMonth)
342 self.assertEqual(len(lst), len(SummerMonth))
343 self.assertEqual(len(SummerMonth), 3, SummerMonth)
344 self.assertEqual([SummerMonth.june, SummerMonth.july, SummerMonth.august ], lst)
345 for i, month in enumerate('june july august'.split(), 1):
346 e = SummerMonth(i)
347 self.assertEqual(e, i)
348 self.assertEqual(e.name, month)
349 self.assertIn(e, SummerMonth)
350 self.assertTrue(type(e) is SummerMonth)
351
352 def test_subclassing(self):
353 self.assertEqual(Name.BDFL, 'Guido van Rossum')
354 self.assertTrue(Name.BDFL, Name('Guido van Rossum'))
355 self.assertTrue(Name.BDFL is getattr(Name, 'BDFL'))
356 self.assertTrue(Name.BDFL is loads(dumps(Name.BDFL)))
357
358 def test_extending(self):
359 class Color(Enum):
360 red = 1
361 green = 2
362 blue = 3
363 with self.assertRaises(TypeError):
364 class MoreColor(Color):
365 cyan = 4
366 magenta = 5
367 yellow = 6
368
369 def test_exclude_methods(self):
370 class whatever(Enum):
371 this = 'that'
372 these = 'those'
373 def really(self):
374 return 'no, not %s' % self.value
375 self.assertFalse(type(whatever.really) is whatever)
376 self.assertEqual(whatever.this.really(), 'no, not that')
377
378 def test_overwrite_enums(self):
379 class Why(Enum):
380 question = 1
381 answer = 2
382 propisition = 3
383 def question(self):
384 print(42)
385 self.assertFalse(type(Why.question) is Why)
386 self.assertFalse(Why.question in Why._enum_names)
387 self.assertFalse(Why.question in Why)
388
389 def test_wrong_inheritance_order(self):
390 with self.assertRaises(TypeError):
391 class Wrong(Enum, str):
392 NotHere = 'error before this point'
393
394 def test_wrong_enum_in_call(self):
395 class Monochrome(Enum):
396 black = 0
397 white = 1
398 class Gender(Enum):
399 male = 0
400 female = 1
401 self.assertRaises(ValueError, Monochrome, Gender.male)
402
403 def test_wrong_enum_in_mixed_call(self):
404 class Monochrome(IntEnum):
405 black = 0
406 white = 1
407 class Gender(Enum):
408 male = 0
409 female = 1
410 self.assertRaises(ValueError, Monochrome, Gender.male)
411
412 def test_mixed_enum_in_call_1(self):
413 class Monochrome(IntEnum):
414 black = 0
415 white = 1
416 class Gender(IntEnum):
417 male = 0
418 female = 1
419 self.assertIs(Monochrome(Gender.female), Monochrome.white)
420
421 def test_mixed_enum_in_call_2(self):
422 class Monochrome(Enum):
423 black = 0
424 white = 1
425 class Gender(IntEnum):
426 male = 0
427 female = 1
428 self.assertIs(Monochrome(Gender.male), Monochrome.black)
429
430 def test_flufl_enum(self):
431 class Fluflnum(Enum):
432 def __int__(self):
433 return int(self.value)
434 class MailManOptions(Fluflnum):
435 option1 = 1
436 option2 = 2
437 option3 = 3
438 self.assertEqual(int(MailManOptions.option1), 1)
439
440 def test_no_such_enum_member(self):
441 class Color(Enum):
442 red = 1
443 green = 2
444 blue = 3
445 with self.assertRaises(ValueError):
446 Color(4)
447 with self.assertRaises(KeyError):
448 Color['chartreuse']
449
450 def test_new_repr(self):
451 class Color(Enum):
452 red = 1
453 green = 2
454 blue = 3
455 def __repr__(self):
456 return "don't you just love shades of %s?" % self.name
457 self.assertEqual(repr(Color.blue), "don't you just love shades of blue?" )
458
459 def test_inherited_repr(self):
460 class MyEnum(Enum):
461 def __repr__(self):
462 return "My name is %s." % self.name
463 class MyIntEnum(int, MyEnum):
464 this = 1
465 that = 2
466 theother = 3
467 self.assertEqual(repr(MyIntEnum.that), "My name is that.")
468
469 def test_multiple_mixin_mro(self):
470 class auto_enum(type(Enum)):
471 def __new__(metacls, cls, bases, classdict):
472 temp = type(classdict)()
473 names = set(classdict._enum_names)
474 i = 0
475 for k in classdict._enum_names:
476 v = classdict[k]
477 if v is Ellipsis:
478 v = i
479 else:
480 i = v
481 i += 1
482 temp[k] = v
483 for k, v in classdict.items():
484 if k not in names:
485 temp[k] = v
486 return super(auto_enum, metacls).__new__(metacls, cls, bases, te mp)
487
488 class AutoNumberedEnum(Enum, metaclass=auto_enum):
489 pass
490
491 class AutoIntEnum(IntEnum, metaclass=auto_enum):
492 pass
493
494 class TestAutoNumber(AutoNumberedEnum):
495 a = ...
496 b = 3
497 c = ...
498
499 class TestAutoInt(AutoIntEnum):
500 a = ...
501 b = 3
502 c = ...
503
504 def test_subclasses_with_getnewargs(self):
505 class NamedInt( int ):
506 def __new__( cls, *args, **kwds ):
507 _args = args
508 name, *args = args
509 if len( args ) == 0:
510 raise TypeError("name and value must be specified")
511 self = int.__new__( cls, *args, **kwds )
512 self._intname = name
513 return self
514 @property
515 def __name__( self ):
516 return self._intname
517 def __repr__( self ):
518 # repr() is updated to include the name and type info
519 return "{}({!r}, {})".format(type(self).__name__,
520 self.__name__,
521 int.__repr__(self))
522 def __str__( self ):
523 # str() is unchanged, even if it relies on the repr() fallback
524 base = int
525 base_str = base.__str__
526 if base_str.__objclass__ is object:
527 return base.__repr__(self)
528 return base_str(self)
529 # for simplicity, we only define one operator that propagates expres sions
530 def __add__(self, other):
531 temp = int( self ) + int( other )
532 if isinstance( self, NamedInt ) and isinstance( other, NamedInt ):
533 return NamedInt(
534 '({0} + {1})'.format(self.__name__, other.__name__),
535 temp )
536 else:
537 return temp
538
539 class NEI( NamedInt, Enum ):
540 x = ('the-x', 1 )
541 y = ('the-y', 2 )
542
543 self.assertEqual(repr(NEI.x + NEI.y), "NamedInt('(the-x + the-y)', 3)")
544 globals()['NamedInt'] = NamedInt
545 globals()['NEI'] = NEI
546 self.assertIs(loads(dumps(NEI.y)), NEI.y)
547
548 def test_tuple_subclass(self):
549 class SomeTuple(tuple, Enum):
550 first = (1, 'for the money')
551 second = (2, 'for the show')
552 third = (3, 'for the music')
553 self.assertTrue(type(SomeTuple.first) is SomeTuple)
554 self.assertTrue(isinstance(SomeTuple.second, tuple))
555 self.assertEqual(SomeTuple.third, (3, 'for the music'))
556 globals()['SomeTuple'] = SomeTuple
557 self.assertTrue(loads(dumps(SomeTuple.first)), SomeTuple.first)
558
559 def test_duplicate_values_give_unique_enum_items(self):
560 class AutoNumber(Enum):
561 first = ()
562 second = ()
563 third = ()
564 def __new__(cls):
565 value = len(cls.__members__) + 1
566 obj = object.__new__(cls)
567 obj._value = value
568 return obj
569 def __int__(self):
570 return self.value
571 self.assertEqual(list(AutoNumber), [AutoNumber.first, AutoNumber.second, AutoNumber.third])
572 self.assertEqual(int(AutoNumber.second), 2)
573 self.assertTrue(AutoNumber(1) is AutoNumber.first)
574
575 def test_inherited_new_from_enhanced_enum(self):
576 class AutoNumber(Enum):
577 def __new__(cls):
578 value = len(cls.__members__) + 1
579 obj = object.__new__(cls)
580 obj._value = value
581 return obj
582 def __int__(self):
583 return self._value
584 class Color(AutoNumber):
585 red = ()
586 green = ()
587 blue = ()
588 self.assertEqual(list(Color), [Color.red, Color.green, Color.blue])
589 self.assertEqual(list(map(int, Color)), [1, 2, 3])
590
591 def test_inherited_new_from_mixed_enum(self):
592 class AutoNumber(IntEnum):
593 def __new__(cls):
594 value = len(cls.__members__) + 1
595 obj = int.__new__(cls, value)
596 obj._value = value
597 return obj
598 class Color(AutoNumber):
599 red = ()
600 green = ()
601 blue = ()
602 self.assertEqual(list(Color), [Color.red, Color.green, Color.blue])
603 self.assertEqual(list(map(int, Color)), [1, 2, 3])
604
605 def test_ordered_mixin(self):
606 class OrderedEnum(Enum):
607 def __ge__(self, other):
608 if self.__class__ is other.__class__:
609 return self._value >= other._value
610 return NotImplemented
611 def __gt__(self, other):
612 if self.__class__ is other.__class__:
613 return self._value > other._value
614 return NotImplemented
615 def __le__(self, other):
616 if self.__class__ is other.__class__:
617 return self._value <= other._value
618 return NotImplemented
619 def __lt__(self, other):
620 if self.__class__ is other.__class__:
621 return self._value < other._value
622 return NotImplemented
623 class Grade(OrderedEnum):
624 A = 5
625 B = 4
626 C = 3
627 D = 2
628 F = 1
629 self.assertTrue(Grade.A > Grade.B)
630 self.assertTrue(Grade.F <= Grade.C)
631 self.assertTrue(Grade.D < Grade.A)
632 self.assertTrue(Grade.B >= Grade.B)
633
634 class TestMe(unittest.TestCase):
635 '''stub for testing one at a time'''
636
637 if __name__ == '__main__':
638 unittest.main()
OLDNEW
« Lib/enum.py ('K') | « Lib/enum.py ('k') | no next file » | no next file with comments »

RSS Feeds Recent Issues | This issue
This is Rietveld 894c83f36cb7+