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

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, 7 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
Zach Ware 2013/05/10 17:30:54 3.4
eric.araujo 2013/05/10 18:30:30 I’d just delete the shebang actually, it won’t be
stoneleaf 2013/05/12 14:47:01 Done.
2 from collections import OrderedDict
3 from pickle import dumps, loads
4 import unittest
5 from ref435 import Enum, IntEnum
6 import sys
7
8 print('Using Python', sys.version)
Zach Ware 2013/05/10 17:30:54 Extra output isn't very well appreciated in the te
stoneleaf 2013/05/12 14:47:01 Done.
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_name='__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)
Zach Ware 2013/05/10 17:30:54 Since all of these above are simply creating enums
stoneleaf 2013/05/12 14:47:01 They shouldn't fail, but they have. ;) They have
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))
Zach Ware 2013/05/10 17:30:54 Whitespace between methods
stoneleaf 2013/05/12 14:47:01 Done.
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 def test_pickle_enum_function_from_other_module(self):
234 from test_module import Duh
235 self.assertIs(Duh.umm, loads(dumps(Duh.umm)))
236
237 def test_string_enum(self):
238 class SkillLevel(str, Enum):
239 master = 'what is the sound of one hand clapping?'
240 journeyman = 'why did the chicken cross the road?'
241 apprentice = 'knock, knock!'
242 self.assertEqual(SkillLevel.apprentice, 'knock, knock!')
243
244 def test_getattr_getitem(self):
245 class Period(Enum):
246 morning = 1
247 noon = 2
248 evening = 3
249 night = 4
250 self.assertTrue(Period(2) is Period.noon)
251 self.assertTrue(getattr(Period, 'night') is Period.night)
252 self.assertTrue(Period['morning'] is Period.morning)
253
254 def test_getattr_dunder(self):
255 Season = self.Season
256 self.assertTrue(getattr(Season, '__eq__'))
257
258 def test_iteration_order(self):
259 class Season(Enum):
260 SUMMER = 2
261 WINTER = 4
262 AUTUMN = 3
263 SPRING = 1
264 self.assertEqual(
265 list(Season),
266 [Season.SUMMER, Season.WINTER, Season.AUTUMN, Season.SPRING],
267 )
268
269 def test_programatic_function_string(self):
270 SummerMonth = Enum('SummerMonth', 'june july august')
271 lst = list(SummerMonth)
272 self.assertEqual(len(lst), len(SummerMonth))
273 self.assertEqual(len(SummerMonth), 3, SummerMonth)
274 self.assertEqual([SummerMonth.june, SummerMonth.july, SummerMonth.august ], lst)
275 for i, month in enumerate('june july august'.split(), 1):
276 e = SummerMonth(i)
277 self.assertEqual(int(e.value), i)
278 self.assertNotEqual(e, i)
279 self.assertEqual(e.name, month)
280 self.assertIn(e, SummerMonth)
281 self.assertTrue(type(e) is SummerMonth)
282
283 def test_programatic_function_string_list(self):
284 SummerMonth = Enum('SummerMonth', ['june', 'july', 'august'])
285 lst = list(SummerMonth)
286 self.assertEqual(len(lst), len(SummerMonth))
287 self.assertEqual(len(SummerMonth), 3, SummerMonth)
288 self.assertEqual([SummerMonth.june, SummerMonth.july, SummerMonth.august ], lst)
289 for i, month in enumerate('june july august'.split(), 1):
290 e = SummerMonth(i)
291 self.assertEqual(int(e.value), i)
292 self.assertNotEqual(e, i)
293 self.assertEqual(e.name, month)
294 self.assertIn(e, SummerMonth)
295 self.assertTrue(type(e) is SummerMonth)
296
297 def test_programatic_function_iterable(self):
298 SummerMonth = Enum('SummerMonth', (('june', 1), ('july', 2), ('august', 3)))
299 lst = list(SummerMonth)
300 self.assertEqual(len(lst), len(SummerMonth))
301 self.assertEqual(len(SummerMonth), 3, SummerMonth)
302 self.assertEqual([SummerMonth.june, SummerMonth.july, SummerMonth.august ], lst)
303 for i, month in enumerate('june july august'.split(), 1):
304 e = SummerMonth(i)
305 self.assertEqual(int(e.value), i)
306 self.assertNotEqual(e, i)
307 self.assertEqual(e.name, month)
308 self.assertIn(e, SummerMonth)
309 self.assertTrue(type(e) is SummerMonth)
310
311 def test_programatic_function_from_dict(self):
312 SummerMonth = Enum('SummerMonth', OrderedDict((('june', 1), ('july', 2), ('august', 3))))
313 lst = list(SummerMonth)
314 self.assertEqual(len(lst), len(SummerMonth))
315 self.assertEqual(len(SummerMonth), 3, SummerMonth)
316 self.assertEqual([SummerMonth.june, SummerMonth.july, SummerMonth.august ], lst)
317 for i, month in enumerate('june july august'.split(), 1):
318 e = SummerMonth(i)
319 self.assertEqual(int(e.value), i)
320 self.assertNotEqual(e, i)
321 self.assertEqual(e.name, month)
322 self.assertIn(e, SummerMonth)
323 self.assertTrue(type(e) is SummerMonth)
324
325 def test_programatic_function_type(self):
326 SummerMonth = Enum('SummerMonth', 'june july august', type=int)
327 lst = list(SummerMonth)
328 self.assertEqual(len(lst), len(SummerMonth))
329 self.assertEqual(len(SummerMonth), 3, SummerMonth)
330 self.assertEqual([SummerMonth.june, SummerMonth.july, SummerMonth.august ], lst)
331 for i, month in enumerate('june july august'.split(), 1):
332 e = SummerMonth(i)
333 self.assertEqual(e, i)
334 self.assertEqual(e.name, month)
335 self.assertIn(e, SummerMonth)
336 self.assertTrue(type(e) is SummerMonth)
337
338 def test_programatic_function_type_from_subclass(self):
339 SummerMonth = IntEnum('SummerMonth', 'june july august')
340 lst = list(SummerMonth)
341 self.assertEqual(len(lst), len(SummerMonth))
342 self.assertEqual(len(SummerMonth), 3, SummerMonth)
343 self.assertEqual([SummerMonth.june, SummerMonth.july, SummerMonth.august ], lst)
344 for i, month in enumerate('june july august'.split(), 1):
345 e = SummerMonth(i)
346 self.assertEqual(e, i)
347 self.assertEqual(e.name, month)
348 self.assertIn(e, SummerMonth)
349 self.assertTrue(type(e) is SummerMonth)
350
351 def test_subclassing(self):
352 self.assertEqual(Name.BDFL, 'Guido van Rossum')
353 self.assertTrue(Name.BDFL, Name('Guido van Rossum'))
354 self.assertTrue(Name.BDFL is getattr(Name, 'BDFL'))
355 self.assertTrue(Name.BDFL is loads(dumps(Name.BDFL)))
356
357 def test_extending(self):
358 class Color(Enum):
359 red = 1
360 green = 2
361 blue = 3
362 with self.assertRaises(TypeError):
363 class MoreColor(Color):
364 cyan = 4
365 magenta = 5
366 yellow = 6
367
368 def test_exclude_methods(self):
369 class whatever(Enum):
370 this = 'that'
371 these = 'those'
372 def really(self):
373 return 'no, not %s' % self.value
374 self.assertFalse(type(whatever.really) is whatever)
375 self.assertEqual(whatever.this.really(), 'no, not that')
376
377 def test_overwrite_enums(self):
378 class Why(Enum):
379 question = 1
380 answer = 2
381 propisition = 3
382 def question(self):
383 print(42)
384 self.assertFalse(type(Why.question) is Why)
385 self.assertFalse(Why.question in Why._enum_names)
386 self.assertFalse(Why.question in Why)
387
388 def test_wrong_inheritance_order(self):
389 with self.assertRaises(TypeError):
390 class Wrong(Enum, str):
391 NotHere = 'error before this point'
392
393 def test_wrong_enum_in_call(self):
394 class Monochrome(Enum):
395 black = 0
396 white = 1
397 class Gender(Enum):
398 male = 0
399 female = 1
400 self.assertRaises(ValueError, Monochrome, Gender.male)
401
402 def test_wrong_enum_in_mixed_call(self):
403 class Monochrome(IntEnum):
404 black = 0
405 white = 1
406 class Gender(Enum):
407 male = 0
408 female = 1
409 self.assertRaises(ValueError, Monochrome, Gender.male)
410
411 def test_mixed_enum_in_call_1(self):
412 class Monochrome(IntEnum):
413 black = 0
414 white = 1
415 class Gender(IntEnum):
416 male = 0
417 female = 1
418 self.assertIs(Monochrome(Gender.female), Monochrome.white)
419
420 def test_mixed_enum_in_call_2(self):
421 class Monochrome(Enum):
422 black = 0
423 white = 1
424 class Gender(IntEnum):
425 male = 0
426 female = 1
427 self.assertIs(Monochrome(Gender.male), Monochrome.black)
428
429 def test_flufl_enum(self):
430 class Fluflnum(Enum):
431 def __int__(self):
432 return int(self.value)
433 class MailManOptions(Fluflnum):
434 option1 = 1
435 option2 = 2
436 option3 = 3
437 self.assertEqual(int(MailManOptions.option1), 1)
438
439 def test_no_such_enum_member(self):
440 class Color(Enum):
441 red = 1
442 green = 2
443 blue = 3
444 with self.assertRaises(ValueError):
445 Color(4)
446 with self.assertRaises(KeyError):
447 Color['chartreuse']
448
449 def test_new_repr(self):
450 class Color(Enum):
451 red = 1
452 green = 2
453 blue = 3
454 def __repr__(self):
455 return "don't you just love shades of %s?" % self.name
456 self.assertEqual(repr(Color.blue), "don't you just love shades of blue?" )
457
458 def test_inherited_repr(self):
459 class MyEnum(Enum):
460 def __repr__(self):
461 return "My name is %s." % self.name
462 class MyIntEnum(int, MyEnum):
463 this = 1
464 that = 2
465 theother = 3
466 self.assertEqual(repr(MyIntEnum.that), "My name is that.")
467
468 def test_multiple_mixin_mro(self):
469 class auto_enum(type(Enum)):
470 def __new__(metacls, cls, bases, classdict):
471 temp = type(classdict)()
472 names = set(classdict._enum_names)
473 i = 0
474 for k in classdict._enum_names:
475 v = classdict[k]
476 if v is Ellipsis:
477 v = i
478 else:
479 i = v
480 i += 1
481 temp[k] = v
482 for k, v in classdict.items():
483 if k not in names:
484 temp[k] = v
485 return super(auto_enum, metacls).__new__(metacls, cls, bases, te mp)
486
487 class AutoNumberedEnum(Enum, metaclass=auto_enum):
488 pass
489
490 class AutoIntEnum(IntEnum, metaclass=auto_enum):
491 pass
492
493 class TestAutoNumber(AutoNumberedEnum):
494 a = ...
495 b = 3
496 c = ...
497
498 class TestAutoInt(AutoIntEnum):
499 a = ...
500 b = 3
501 c = ...
502
503 def test_subclasses_with_getnewargs(self):
504 class NamedInt( int ):
505 def __new__( cls, *args, **kwds ):
506 _args = args
507 name, *args = args
508 if len( args ) == 0:
509 raise TypeError("name and value must be specified")
510 self = int.__new__( cls, *args, **kwds )
511 self._intname = name
512 return self
513 @property
514 def __name__( self ):
515 return self._intname
516 def __repr__( self ):
517 # repr() is updated to include the name and type info
518 return "{}({!r}, {})".format(type(self).__name__,
519 self.__name__,
520 int.__repr__(self))
521 def __str__( self ):
522 # str() is unchanged, even if it relies on the repr() fallback
523 base = int
524 base_str = base.__str__
525 if base_str.__objclass__ is object:
526 return base.__repr__(self)
527 return base_str(self)
528 # for simplicity, we only define one operator that propagates expres sions
529 def __add__(self, other):
530 temp = int( self ) + int( other )
531 if isinstance( self, NamedInt ) and isinstance( other, NamedInt ):
532 return NamedInt(
533 '({0} + {1})'.format(self.__name__, other.__name__),
534 temp )
535 else:
536 return temp
537
538 class NEI( NamedInt, Enum ):
539 x = ('the-x', 1 )
540 y = ('the-y', 2 )
541
542 self.assertEqual(repr(NEI.x + NEI.y), "NamedInt('(the-x + the-y)', 3)")
543 globals()['NamedInt'] = NamedInt
544 globals()['NEI'] = NEI
545 self.assertIs(loads(dumps(NEI.y)), NEI.y)
546
547 def test_tuple_subclass(self):
548 class SomeTuple(tuple, Enum):
549 first = (1, 'for the money')
550 second = (2, 'for the show')
551 third = (3, 'for the music')
552 self.assertTrue(type(SomeTuple.first) is SomeTuple)
553 self.assertTrue(isinstance(SomeTuple.second, tuple))
554 self.assertEqual(SomeTuple.third, (3, 'for the music'))
555 globals()['SomeTuple'] = SomeTuple
556 self.assertTrue(loads(dumps(SomeTuple.first)), SomeTuple.first)
557
558 def test_duplicate_values_give_unique_enum_items(self):
559 class AutoNumber(Enum):
560 first = ()
561 second = ()
562 third = ()
563 def __new__(cls):
564 value = len(cls.__members__) + 1
565 obj = object.__new__(cls)
566 obj._value = value
567 return obj
568 def __int__(self):
569 return self.value
570 self.assertEqual(list(AutoNumber), [AutoNumber.first, AutoNumber.second, AutoNumber.third])
571 self.assertEqual(int(AutoNumber.second), 2)
572 self.assertTrue(AutoNumber(1) is AutoNumber.first)
573
574 def test_inherited_new_from_enhanced_enum(self):
575 class AutoNumber(Enum):
576 def __new__(cls):
577 value = len(cls.__members__) + 1
578 obj = object.__new__(cls)
579 obj._value = value
580 return obj
581 def __int__(self):
582 return self._value
583 class Color(AutoNumber):
584 red = ()
585 green = ()
586 blue = ()
587 self.assertEqual(list(Color), [Color.red, Color.green, Color.blue])
588 self.assertEqual(list(map(int, Color)), [1, 2, 3])
589
590 def test_inherited_new_from_mixed_enum(self):
591 class AutoNumber(IntEnum):
592 def __new__(cls):
593 value = len(cls.__members__) + 1
594 obj = int.__new__(cls, value)
595 obj._value = value
596 return obj
597 class Color(AutoNumber):
598 red = ()
599 green = ()
600 blue = ()
601 self.assertEqual(list(Color), [Color.red, Color.green, Color.blue])
602 self.assertEqual(list(map(int, Color)), [1, 2, 3])
603
604 def test_ordered_mixin(self):
605 class OrderedEnum(Enum):
606 def __ge__(self, other):
607 if self.__class__ is other.__class__:
608 return self._value >= other._value
609 return NotImplemented
610 def __gt__(self, other):
611 if self.__class__ is other.__class__:
612 return self._value > other._value
613 return NotImplemented
614 def __le__(self, other):
615 if self.__class__ is other.__class__:
616 return self._value <= other._value
617 return NotImplemented
618 def __lt__(self, other):
619 if self.__class__ is other.__class__:
620 return self._value < other._value
621 return NotImplemented
622 class Grade(OrderedEnum):
623 A = 5
624 B = 4
625 C = 3
626 D = 2
627 F = 1
628 self.assertTrue(Grade.A > Grade.B)
629 self.assertTrue(Grade.F <= Grade.C)
630 self.assertTrue(Grade.D < Grade.A)
631 self.assertTrue(Grade.B >= Grade.B)
632
633 class TestMe(unittest.TestCase):
634 '''stub for testing one at a time'''
Zach Ware 2013/05/10 17:30:54 This should be removed.
stoneleaf 2013/05/12 14:47:01 Done.
635
636 if __name__ == '__main__':
637 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+