blob: 03f0e5d5cda5acac3aee15ab6a59f4ee8b474427 [file] [log] [blame]
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001import enum
Ethan Furman5875d742013-10-21 20:45:55 -07002import inspect
3import pydoc
Ethan Furman6b3d64a2013-06-14 16:55:46 -07004import unittest
5from collections import OrderedDict
Ethan Furman5875d742013-10-21 20:45:55 -07006from enum import Enum, IntEnum, EnumMeta, unique
7from io import StringIO
Ethan Furman6b3d64a2013-06-14 16:55:46 -07008from pickle import dumps, loads, PicklingError
Ethan Furman6b3d64a2013-06-14 16:55:46 -07009
10# for pickle tests
11try:
12 class Stooges(Enum):
13 LARRY = 1
14 CURLY = 2
15 MOE = 3
16except Exception as exc:
17 Stooges = exc
18
19try:
20 class IntStooges(int, Enum):
21 LARRY = 1
22 CURLY = 2
23 MOE = 3
24except Exception as exc:
25 IntStooges = exc
26
27try:
28 class FloatStooges(float, Enum):
29 LARRY = 1.39
30 CURLY = 2.72
31 MOE = 3.142596
32except Exception as exc:
33 FloatStooges = exc
34
35# for pickle test and subclass tests
36try:
37 class StrEnum(str, Enum):
38 'accepts only string values'
39 class Name(StrEnum):
40 BDFL = 'Guido van Rossum'
41 FLUFL = 'Barry Warsaw'
42except Exception as exc:
43 Name = exc
44
45try:
46 Question = Enum('Question', 'who what when where why', module=__name__)
47except Exception as exc:
48 Question = exc
49
50try:
51 Answer = Enum('Answer', 'him this then there because')
52except Exception as exc:
53 Answer = exc
54
55# for doctests
56try:
57 class Fruit(Enum):
58 tomato = 1
59 banana = 2
60 cherry = 3
61except Exception:
62 pass
63
Ethan Furman648f8602013-10-06 17:19:54 -070064
65class TestHelpers(unittest.TestCase):
66 # _is_descriptor, _is_sunder, _is_dunder
67
68 def test_is_descriptor(self):
69 class foo:
70 pass
71 for attr in ('__get__','__set__','__delete__'):
72 obj = foo()
73 self.assertFalse(enum._is_descriptor(obj))
74 setattr(obj, attr, 1)
75 self.assertTrue(enum._is_descriptor(obj))
76
77 def test_is_sunder(self):
78 for s in ('_a_', '_aa_'):
79 self.assertTrue(enum._is_sunder(s))
80
81 for s in ('a', 'a_', '_a', '__a', 'a__', '__a__', '_a__', '__a_', '_',
82 '__', '___', '____', '_____',):
83 self.assertFalse(enum._is_sunder(s))
84
85 def test_is_dunder(self):
86 for s in ('__a__', '__aa__'):
87 self.assertTrue(enum._is_dunder(s))
88 for s in ('a', 'a_', '_a', '__a', 'a__', '_a_', '_a__', '__a_', '_',
89 '__', '___', '____', '_____',):
90 self.assertFalse(enum._is_dunder(s))
91
92
Ethan Furman6b3d64a2013-06-14 16:55:46 -070093class TestEnum(unittest.TestCase):
94 def setUp(self):
95 class Season(Enum):
96 SPRING = 1
97 SUMMER = 2
98 AUTUMN = 3
99 WINTER = 4
100 self.Season = Season
101
Ethan Furmanec15a822013-08-31 19:17:41 -0700102 class Konstants(float, Enum):
103 E = 2.7182818
104 PI = 3.1415926
105 TAU = 2 * PI
106 self.Konstants = Konstants
107
108 class Grades(IntEnum):
109 A = 5
110 B = 4
111 C = 3
112 D = 2
113 F = 0
114 self.Grades = Grades
115
116 class Directional(str, Enum):
117 EAST = 'east'
118 WEST = 'west'
119 NORTH = 'north'
120 SOUTH = 'south'
121 self.Directional = Directional
122
123 from datetime import date
124 class Holiday(date, Enum):
125 NEW_YEAR = 2013, 1, 1
126 IDES_OF_MARCH = 2013, 3, 15
127 self.Holiday = Holiday
128
Ethan Furman388a3922013-08-12 06:51:41 -0700129 def test_dir_on_class(self):
130 Season = self.Season
131 self.assertEqual(
132 set(dir(Season)),
Ethan Furmanc850f342013-09-15 16:59:35 -0700133 set(['__class__', '__doc__', '__members__', '__module__',
Ethan Furman388a3922013-08-12 06:51:41 -0700134 'SPRING', 'SUMMER', 'AUTUMN', 'WINTER']),
135 )
136
137 def test_dir_on_item(self):
138 Season = self.Season
139 self.assertEqual(
140 set(dir(Season.WINTER)),
Ethan Furmanc850f342013-09-15 16:59:35 -0700141 set(['__class__', '__doc__', '__module__', 'name', 'value']),
Ethan Furman388a3922013-08-12 06:51:41 -0700142 )
143
Ethan Furmanc850f342013-09-15 16:59:35 -0700144 def test_dir_with_added_behavior(self):
145 class Test(Enum):
146 this = 'that'
147 these = 'those'
148 def wowser(self):
149 return ("Wowser! I'm %s!" % self.name)
150 self.assertEqual(
151 set(dir(Test)),
152 set(['__class__', '__doc__', '__members__', '__module__', 'this', 'these']),
153 )
154 self.assertEqual(
155 set(dir(Test.this)),
156 set(['__class__', '__doc__', '__module__', 'name', 'value', 'wowser']),
157 )
158
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700159 def test_enum_in_enum_out(self):
160 Season = self.Season
161 self.assertIs(Season(Season.WINTER), Season.WINTER)
162
163 def test_enum_value(self):
164 Season = self.Season
165 self.assertEqual(Season.SPRING.value, 1)
166
167 def test_intenum_value(self):
168 self.assertEqual(IntStooges.CURLY.value, 2)
169
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700170 def test_enum(self):
171 Season = self.Season
172 lst = list(Season)
173 self.assertEqual(len(lst), len(Season))
174 self.assertEqual(len(Season), 4, Season)
175 self.assertEqual(
176 [Season.SPRING, Season.SUMMER, Season.AUTUMN, Season.WINTER], lst)
177
178 for i, season in enumerate('SPRING SUMMER AUTUMN WINTER'.split(), 1):
179 e = Season(i)
180 self.assertEqual(e, getattr(Season, season))
181 self.assertEqual(e.value, i)
182 self.assertNotEqual(e, i)
183 self.assertEqual(e.name, season)
184 self.assertIn(e, Season)
185 self.assertIs(type(e), Season)
186 self.assertIsInstance(e, Season)
187 self.assertEqual(str(e), 'Season.' + season)
188 self.assertEqual(
189 repr(e),
190 '<Season.{0}: {1}>'.format(season, i),
191 )
192
193 def test_value_name(self):
194 Season = self.Season
195 self.assertEqual(Season.SPRING.name, 'SPRING')
196 self.assertEqual(Season.SPRING.value, 1)
197 with self.assertRaises(AttributeError):
198 Season.SPRING.name = 'invierno'
199 with self.assertRaises(AttributeError):
200 Season.SPRING.value = 2
201
Ethan Furmanf203f2d2013-09-06 07:16:48 -0700202 def test_changing_member(self):
203 Season = self.Season
204 with self.assertRaises(AttributeError):
205 Season.WINTER = 'really cold'
206
Ethan Furman64a99722013-09-22 16:18:19 -0700207 def test_attribute_deletion(self):
208 class Season(Enum):
209 SPRING = 1
210 SUMMER = 2
211 AUTUMN = 3
212 WINTER = 4
213
214 def spam(cls):
215 pass
216
217 self.assertTrue(hasattr(Season, 'spam'))
218 del Season.spam
219 self.assertFalse(hasattr(Season, 'spam'))
220
221 with self.assertRaises(AttributeError):
222 del Season.SPRING
223 with self.assertRaises(AttributeError):
224 del Season.DRY
225 with self.assertRaises(AttributeError):
226 del Season.SPRING.name
227
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700228 def test_invalid_names(self):
229 with self.assertRaises(ValueError):
230 class Wrong(Enum):
231 mro = 9
232 with self.assertRaises(ValueError):
233 class Wrong(Enum):
234 _create_= 11
235 with self.assertRaises(ValueError):
236 class Wrong(Enum):
237 _get_mixins_ = 9
238 with self.assertRaises(ValueError):
239 class Wrong(Enum):
240 _find_new_ = 1
241 with self.assertRaises(ValueError):
242 class Wrong(Enum):
243 _any_name_ = 9
244
245 def test_contains(self):
246 Season = self.Season
247 self.assertIn(Season.AUTUMN, Season)
248 self.assertNotIn(3, Season)
249
250 val = Season(3)
251 self.assertIn(val, Season)
252
253 class OtherEnum(Enum):
254 one = 1; two = 2
255 self.assertNotIn(OtherEnum.two, Season)
256
257 def test_comparisons(self):
258 Season = self.Season
259 with self.assertRaises(TypeError):
260 Season.SPRING < Season.WINTER
261 with self.assertRaises(TypeError):
262 Season.SPRING > 4
263
264 self.assertNotEqual(Season.SPRING, 1)
265
266 class Part(Enum):
267 SPRING = 1
268 CLIP = 2
269 BARREL = 3
270
271 self.assertNotEqual(Season.SPRING, Part.SPRING)
272 with self.assertRaises(TypeError):
273 Season.SPRING < Part.CLIP
274
275 def test_enum_duplicates(self):
276 class Season(Enum):
277 SPRING = 1
278 SUMMER = 2
279 AUTUMN = FALL = 3
280 WINTER = 4
281 ANOTHER_SPRING = 1
282 lst = list(Season)
283 self.assertEqual(
284 lst,
285 [Season.SPRING, Season.SUMMER,
286 Season.AUTUMN, Season.WINTER,
287 ])
288 self.assertIs(Season.FALL, Season.AUTUMN)
289 self.assertEqual(Season.FALL.value, 3)
290 self.assertEqual(Season.AUTUMN.value, 3)
291 self.assertIs(Season(3), Season.AUTUMN)
292 self.assertIs(Season(1), Season.SPRING)
293 self.assertEqual(Season.FALL.name, 'AUTUMN')
294 self.assertEqual(
295 [k for k,v in Season.__members__.items() if v.name != k],
296 ['FALL', 'ANOTHER_SPRING'],
297 )
298
Ethan Furman101e0742013-09-15 12:34:36 -0700299 def test_duplicate_name(self):
300 with self.assertRaises(TypeError):
301 class Color(Enum):
302 red = 1
303 green = 2
304 blue = 3
305 red = 4
306
307 with self.assertRaises(TypeError):
308 class Color(Enum):
309 red = 1
310 green = 2
311 blue = 3
312 def red(self):
313 return 'red'
314
315 with self.assertRaises(TypeError):
316 class Color(Enum):
317 @property
318 def red(self):
319 return 'redder'
320 red = 1
321 green = 2
322 blue = 3
323
324
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700325 def test_enum_with_value_name(self):
326 class Huh(Enum):
327 name = 1
328 value = 2
329 self.assertEqual(
330 list(Huh),
331 [Huh.name, Huh.value],
332 )
333 self.assertIs(type(Huh.name), Huh)
334 self.assertEqual(Huh.name.name, 'name')
335 self.assertEqual(Huh.name.value, 1)
Ethan Furmanec15a822013-08-31 19:17:41 -0700336
337 def test_format_enum(self):
338 Season = self.Season
339 self.assertEqual('{}'.format(Season.SPRING),
340 '{}'.format(str(Season.SPRING)))
341 self.assertEqual( '{:}'.format(Season.SPRING),
342 '{:}'.format(str(Season.SPRING)))
343 self.assertEqual('{:20}'.format(Season.SPRING),
344 '{:20}'.format(str(Season.SPRING)))
345 self.assertEqual('{:^20}'.format(Season.SPRING),
346 '{:^20}'.format(str(Season.SPRING)))
347 self.assertEqual('{:>20}'.format(Season.SPRING),
348 '{:>20}'.format(str(Season.SPRING)))
349 self.assertEqual('{:<20}'.format(Season.SPRING),
350 '{:<20}'.format(str(Season.SPRING)))
351
352 def test_format_enum_custom(self):
353 class TestFloat(float, Enum):
354 one = 1.0
355 two = 2.0
356 def __format__(self, spec):
357 return 'TestFloat success!'
358 self.assertEqual('{}'.format(TestFloat.one), 'TestFloat success!')
359
360 def assertFormatIsValue(self, spec, member):
361 self.assertEqual(spec.format(member), spec.format(member.value))
362
363 def test_format_enum_date(self):
364 Holiday = self.Holiday
365 self.assertFormatIsValue('{}', Holiday.IDES_OF_MARCH)
366 self.assertFormatIsValue('{:}', Holiday.IDES_OF_MARCH)
367 self.assertFormatIsValue('{:20}', Holiday.IDES_OF_MARCH)
368 self.assertFormatIsValue('{:^20}', Holiday.IDES_OF_MARCH)
369 self.assertFormatIsValue('{:>20}', Holiday.IDES_OF_MARCH)
370 self.assertFormatIsValue('{:<20}', Holiday.IDES_OF_MARCH)
371 self.assertFormatIsValue('{:%Y %m}', Holiday.IDES_OF_MARCH)
372 self.assertFormatIsValue('{:%Y %m %M:00}', Holiday.IDES_OF_MARCH)
373
374 def test_format_enum_float(self):
375 Konstants = self.Konstants
376 self.assertFormatIsValue('{}', Konstants.TAU)
377 self.assertFormatIsValue('{:}', Konstants.TAU)
378 self.assertFormatIsValue('{:20}', Konstants.TAU)
379 self.assertFormatIsValue('{:^20}', Konstants.TAU)
380 self.assertFormatIsValue('{:>20}', Konstants.TAU)
381 self.assertFormatIsValue('{:<20}', Konstants.TAU)
382 self.assertFormatIsValue('{:n}', Konstants.TAU)
383 self.assertFormatIsValue('{:5.2}', Konstants.TAU)
384 self.assertFormatIsValue('{:f}', Konstants.TAU)
385
386 def test_format_enum_int(self):
387 Grades = self.Grades
388 self.assertFormatIsValue('{}', Grades.C)
389 self.assertFormatIsValue('{:}', Grades.C)
390 self.assertFormatIsValue('{:20}', Grades.C)
391 self.assertFormatIsValue('{:^20}', Grades.C)
392 self.assertFormatIsValue('{:>20}', Grades.C)
393 self.assertFormatIsValue('{:<20}', Grades.C)
394 self.assertFormatIsValue('{:+}', Grades.C)
395 self.assertFormatIsValue('{:08X}', Grades.C)
396 self.assertFormatIsValue('{:b}', Grades.C)
397
398 def test_format_enum_str(self):
399 Directional = self.Directional
400 self.assertFormatIsValue('{}', Directional.WEST)
401 self.assertFormatIsValue('{:}', Directional.WEST)
402 self.assertFormatIsValue('{:20}', Directional.WEST)
403 self.assertFormatIsValue('{:^20}', Directional.WEST)
404 self.assertFormatIsValue('{:>20}', Directional.WEST)
405 self.assertFormatIsValue('{:<20}', Directional.WEST)
406
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700407 def test_hash(self):
408 Season = self.Season
409 dates = {}
410 dates[Season.WINTER] = '1225'
411 dates[Season.SPRING] = '0315'
412 dates[Season.SUMMER] = '0704'
413 dates[Season.AUTUMN] = '1031'
414 self.assertEqual(dates[Season.AUTUMN], '1031')
415
416 def test_intenum_from_scratch(self):
417 class phy(int, Enum):
418 pi = 3
419 tau = 2 * pi
420 self.assertTrue(phy.pi < phy.tau)
421
422 def test_intenum_inherited(self):
423 class IntEnum(int, Enum):
424 pass
425 class phy(IntEnum):
426 pi = 3
427 tau = 2 * pi
428 self.assertTrue(phy.pi < phy.tau)
429
430 def test_floatenum_from_scratch(self):
431 class phy(float, Enum):
Ethan Furmanec15a822013-08-31 19:17:41 -0700432 pi = 3.1415926
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700433 tau = 2 * pi
434 self.assertTrue(phy.pi < phy.tau)
435
436 def test_floatenum_inherited(self):
437 class FloatEnum(float, Enum):
438 pass
439 class phy(FloatEnum):
Ethan Furmanec15a822013-08-31 19:17:41 -0700440 pi = 3.1415926
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700441 tau = 2 * pi
442 self.assertTrue(phy.pi < phy.tau)
443
444 def test_strenum_from_scratch(self):
445 class phy(str, Enum):
446 pi = 'Pi'
447 tau = 'Tau'
448 self.assertTrue(phy.pi < phy.tau)
449
450 def test_strenum_inherited(self):
451 class StrEnum(str, Enum):
452 pass
453 class phy(StrEnum):
454 pi = 'Pi'
455 tau = 'Tau'
456 self.assertTrue(phy.pi < phy.tau)
457
458
459 def test_intenum(self):
460 class WeekDay(IntEnum):
461 SUNDAY = 1
462 MONDAY = 2
463 TUESDAY = 3
464 WEDNESDAY = 4
465 THURSDAY = 5
466 FRIDAY = 6
467 SATURDAY = 7
468
469 self.assertEqual(['a', 'b', 'c'][WeekDay.MONDAY], 'c')
470 self.assertEqual([i for i in range(WeekDay.TUESDAY)], [0, 1, 2])
471
472 lst = list(WeekDay)
473 self.assertEqual(len(lst), len(WeekDay))
474 self.assertEqual(len(WeekDay), 7)
475 target = 'SUNDAY MONDAY TUESDAY WEDNESDAY THURSDAY FRIDAY SATURDAY'
476 target = target.split()
477 for i, weekday in enumerate(target, 1):
478 e = WeekDay(i)
479 self.assertEqual(e, i)
480 self.assertEqual(int(e), i)
481 self.assertEqual(e.name, weekday)
482 self.assertIn(e, WeekDay)
483 self.assertEqual(lst.index(e)+1, i)
484 self.assertTrue(0 < e < 8)
485 self.assertIs(type(e), WeekDay)
486 self.assertIsInstance(e, int)
487 self.assertIsInstance(e, Enum)
488
489 def test_intenum_duplicates(self):
490 class WeekDay(IntEnum):
491 SUNDAY = 1
492 MONDAY = 2
493 TUESDAY = TEUSDAY = 3
494 WEDNESDAY = 4
495 THURSDAY = 5
496 FRIDAY = 6
497 SATURDAY = 7
498 self.assertIs(WeekDay.TEUSDAY, WeekDay.TUESDAY)
499 self.assertEqual(WeekDay(3).name, 'TUESDAY')
500 self.assertEqual([k for k,v in WeekDay.__members__.items()
501 if v.name != k], ['TEUSDAY', ])
502
503 def test_pickle_enum(self):
504 if isinstance(Stooges, Exception):
505 raise Stooges
506 self.assertIs(Stooges.CURLY, loads(dumps(Stooges.CURLY)))
507 self.assertIs(Stooges, loads(dumps(Stooges)))
508
509 def test_pickle_int(self):
510 if isinstance(IntStooges, Exception):
511 raise IntStooges
512 self.assertIs(IntStooges.CURLY, loads(dumps(IntStooges.CURLY)))
513 self.assertIs(IntStooges, loads(dumps(IntStooges)))
514
515 def test_pickle_float(self):
516 if isinstance(FloatStooges, Exception):
517 raise FloatStooges
518 self.assertIs(FloatStooges.CURLY, loads(dumps(FloatStooges.CURLY)))
519 self.assertIs(FloatStooges, loads(dumps(FloatStooges)))
520
521 def test_pickle_enum_function(self):
522 if isinstance(Answer, Exception):
523 raise Answer
524 self.assertIs(Answer.him, loads(dumps(Answer.him)))
525 self.assertIs(Answer, loads(dumps(Answer)))
526
527 def test_pickle_enum_function_with_module(self):
528 if isinstance(Question, Exception):
529 raise Question
530 self.assertIs(Question.who, loads(dumps(Question.who)))
531 self.assertIs(Question, loads(dumps(Question)))
532
533 def test_exploding_pickle(self):
534 BadPickle = Enum('BadPickle', 'dill sweet bread-n-butter')
535 enum._make_class_unpicklable(BadPickle)
536 globals()['BadPickle'] = BadPickle
537 with self.assertRaises(TypeError):
538 dumps(BadPickle.dill)
539 with self.assertRaises(PicklingError):
540 dumps(BadPickle)
541
542 def test_string_enum(self):
543 class SkillLevel(str, Enum):
544 master = 'what is the sound of one hand clapping?'
545 journeyman = 'why did the chicken cross the road?'
546 apprentice = 'knock, knock!'
547 self.assertEqual(SkillLevel.apprentice, 'knock, knock!')
548
549 def test_getattr_getitem(self):
550 class Period(Enum):
551 morning = 1
552 noon = 2
553 evening = 3
554 night = 4
555 self.assertIs(Period(2), Period.noon)
556 self.assertIs(getattr(Period, 'night'), Period.night)
557 self.assertIs(Period['morning'], Period.morning)
558
559 def test_getattr_dunder(self):
560 Season = self.Season
561 self.assertTrue(getattr(Season, '__eq__'))
562
563 def test_iteration_order(self):
564 class Season(Enum):
565 SUMMER = 2
566 WINTER = 4
567 AUTUMN = 3
568 SPRING = 1
569 self.assertEqual(
570 list(Season),
571 [Season.SUMMER, Season.WINTER, Season.AUTUMN, Season.SPRING],
572 )
573
Ethan Furman2131a4a2013-09-14 18:11:24 -0700574 def test_reversed_iteration_order(self):
575 self.assertEqual(
576 list(reversed(self.Season)),
577 [self.Season.WINTER, self.Season.AUTUMN, self.Season.SUMMER,
578 self.Season.SPRING]
579 )
580
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700581 def test_programatic_function_string(self):
582 SummerMonth = Enum('SummerMonth', 'june july august')
583 lst = list(SummerMonth)
584 self.assertEqual(len(lst), len(SummerMonth))
585 self.assertEqual(len(SummerMonth), 3, SummerMonth)
586 self.assertEqual(
587 [SummerMonth.june, SummerMonth.july, SummerMonth.august],
588 lst,
589 )
590 for i, month in enumerate('june july august'.split(), 1):
591 e = SummerMonth(i)
592 self.assertEqual(int(e.value), i)
593 self.assertNotEqual(e, i)
594 self.assertEqual(e.name, month)
595 self.assertIn(e, SummerMonth)
596 self.assertIs(type(e), SummerMonth)
597
598 def test_programatic_function_string_list(self):
599 SummerMonth = Enum('SummerMonth', ['june', 'july', 'august'])
600 lst = list(SummerMonth)
601 self.assertEqual(len(lst), len(SummerMonth))
602 self.assertEqual(len(SummerMonth), 3, SummerMonth)
603 self.assertEqual(
604 [SummerMonth.june, SummerMonth.july, SummerMonth.august],
605 lst,
606 )
607 for i, month in enumerate('june july august'.split(), 1):
608 e = SummerMonth(i)
609 self.assertEqual(int(e.value), i)
610 self.assertNotEqual(e, i)
611 self.assertEqual(e.name, month)
612 self.assertIn(e, SummerMonth)
613 self.assertIs(type(e), SummerMonth)
614
615 def test_programatic_function_iterable(self):
616 SummerMonth = Enum(
617 'SummerMonth',
618 (('june', 1), ('july', 2), ('august', 3))
619 )
620 lst = list(SummerMonth)
621 self.assertEqual(len(lst), len(SummerMonth))
622 self.assertEqual(len(SummerMonth), 3, SummerMonth)
623 self.assertEqual(
624 [SummerMonth.june, SummerMonth.july, SummerMonth.august],
625 lst,
626 )
627 for i, month in enumerate('june july august'.split(), 1):
628 e = SummerMonth(i)
629 self.assertEqual(int(e.value), i)
630 self.assertNotEqual(e, i)
631 self.assertEqual(e.name, month)
632 self.assertIn(e, SummerMonth)
633 self.assertIs(type(e), SummerMonth)
634
635 def test_programatic_function_from_dict(self):
636 SummerMonth = Enum(
637 'SummerMonth',
638 OrderedDict((('june', 1), ('july', 2), ('august', 3)))
639 )
640 lst = list(SummerMonth)
641 self.assertEqual(len(lst), len(SummerMonth))
642 self.assertEqual(len(SummerMonth), 3, SummerMonth)
643 self.assertEqual(
644 [SummerMonth.june, SummerMonth.july, SummerMonth.august],
645 lst,
646 )
647 for i, month in enumerate('june july august'.split(), 1):
648 e = SummerMonth(i)
649 self.assertEqual(int(e.value), i)
650 self.assertNotEqual(e, i)
651 self.assertEqual(e.name, month)
652 self.assertIn(e, SummerMonth)
653 self.assertIs(type(e), SummerMonth)
654
655 def test_programatic_function_type(self):
656 SummerMonth = Enum('SummerMonth', 'june july august', type=int)
657 lst = list(SummerMonth)
658 self.assertEqual(len(lst), len(SummerMonth))
659 self.assertEqual(len(SummerMonth), 3, SummerMonth)
660 self.assertEqual(
661 [SummerMonth.june, SummerMonth.july, SummerMonth.august],
662 lst,
663 )
664 for i, month in enumerate('june july august'.split(), 1):
665 e = SummerMonth(i)
666 self.assertEqual(e, i)
667 self.assertEqual(e.name, month)
668 self.assertIn(e, SummerMonth)
669 self.assertIs(type(e), SummerMonth)
670
671 def test_programatic_function_type_from_subclass(self):
672 SummerMonth = IntEnum('SummerMonth', 'june july august')
673 lst = list(SummerMonth)
674 self.assertEqual(len(lst), len(SummerMonth))
675 self.assertEqual(len(SummerMonth), 3, SummerMonth)
676 self.assertEqual(
677 [SummerMonth.june, SummerMonth.july, SummerMonth.august],
678 lst,
679 )
680 for i, month in enumerate('june july august'.split(), 1):
681 e = SummerMonth(i)
682 self.assertEqual(e, i)
683 self.assertEqual(e.name, month)
684 self.assertIn(e, SummerMonth)
685 self.assertIs(type(e), SummerMonth)
686
687 def test_subclassing(self):
688 if isinstance(Name, Exception):
689 raise Name
690 self.assertEqual(Name.BDFL, 'Guido van Rossum')
691 self.assertTrue(Name.BDFL, Name('Guido van Rossum'))
692 self.assertIs(Name.BDFL, getattr(Name, 'BDFL'))
693 self.assertIs(Name.BDFL, loads(dumps(Name.BDFL)))
694
695 def test_extending(self):
696 class Color(Enum):
697 red = 1
698 green = 2
699 blue = 3
700 with self.assertRaises(TypeError):
701 class MoreColor(Color):
702 cyan = 4
703 magenta = 5
704 yellow = 6
705
706 def test_exclude_methods(self):
707 class whatever(Enum):
708 this = 'that'
709 these = 'those'
710 def really(self):
711 return 'no, not %s' % self.value
712 self.assertIsNot(type(whatever.really), whatever)
713 self.assertEqual(whatever.this.really(), 'no, not that')
714
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700715 def test_wrong_inheritance_order(self):
716 with self.assertRaises(TypeError):
717 class Wrong(Enum, str):
718 NotHere = 'error before this point'
719
720 def test_intenum_transitivity(self):
721 class number(IntEnum):
722 one = 1
723 two = 2
724 three = 3
725 class numero(IntEnum):
726 uno = 1
727 dos = 2
728 tres = 3
729 self.assertEqual(number.one, numero.uno)
730 self.assertEqual(number.two, numero.dos)
731 self.assertEqual(number.three, numero.tres)
732
733 def test_wrong_enum_in_call(self):
734 class Monochrome(Enum):
735 black = 0
736 white = 1
737 class Gender(Enum):
738 male = 0
739 female = 1
740 self.assertRaises(ValueError, Monochrome, Gender.male)
741
742 def test_wrong_enum_in_mixed_call(self):
743 class Monochrome(IntEnum):
744 black = 0
745 white = 1
746 class Gender(Enum):
747 male = 0
748 female = 1
749 self.assertRaises(ValueError, Monochrome, Gender.male)
750
751 def test_mixed_enum_in_call_1(self):
752 class Monochrome(IntEnum):
753 black = 0
754 white = 1
755 class Gender(IntEnum):
756 male = 0
757 female = 1
758 self.assertIs(Monochrome(Gender.female), Monochrome.white)
759
760 def test_mixed_enum_in_call_2(self):
761 class Monochrome(Enum):
762 black = 0
763 white = 1
764 class Gender(IntEnum):
765 male = 0
766 female = 1
767 self.assertIs(Monochrome(Gender.male), Monochrome.black)
768
769 def test_flufl_enum(self):
770 class Fluflnum(Enum):
771 def __int__(self):
772 return int(self.value)
773 class MailManOptions(Fluflnum):
774 option1 = 1
775 option2 = 2
776 option3 = 3
777 self.assertEqual(int(MailManOptions.option1), 1)
778
Ethan Furman5e5a8232013-08-04 08:42:23 -0700779 def test_introspection(self):
780 class Number(IntEnum):
781 one = 100
782 two = 200
783 self.assertIs(Number.one._member_type_, int)
784 self.assertIs(Number._member_type_, int)
785 class String(str, Enum):
786 yarn = 'soft'
787 rope = 'rough'
788 wire = 'hard'
789 self.assertIs(String.yarn._member_type_, str)
790 self.assertIs(String._member_type_, str)
791 class Plain(Enum):
792 vanilla = 'white'
793 one = 1
794 self.assertIs(Plain.vanilla._member_type_, object)
795 self.assertIs(Plain._member_type_, object)
796
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700797 def test_no_such_enum_member(self):
798 class Color(Enum):
799 red = 1
800 green = 2
801 blue = 3
802 with self.assertRaises(ValueError):
803 Color(4)
804 with self.assertRaises(KeyError):
805 Color['chartreuse']
806
807 def test_new_repr(self):
808 class Color(Enum):
809 red = 1
810 green = 2
811 blue = 3
812 def __repr__(self):
813 return "don't you just love shades of %s?" % self.name
814 self.assertEqual(
815 repr(Color.blue),
816 "don't you just love shades of blue?",
817 )
818
819 def test_inherited_repr(self):
820 class MyEnum(Enum):
821 def __repr__(self):
822 return "My name is %s." % self.name
823 class MyIntEnum(int, MyEnum):
824 this = 1
825 that = 2
826 theother = 3
827 self.assertEqual(repr(MyIntEnum.that), "My name is that.")
828
829 def test_multiple_mixin_mro(self):
830 class auto_enum(type(Enum)):
831 def __new__(metacls, cls, bases, classdict):
832 temp = type(classdict)()
833 names = set(classdict._member_names)
834 i = 0
835 for k in classdict._member_names:
836 v = classdict[k]
837 if v is Ellipsis:
838 v = i
839 else:
840 i = v
841 i += 1
842 temp[k] = v
843 for k, v in classdict.items():
844 if k not in names:
845 temp[k] = v
846 return super(auto_enum, metacls).__new__(
847 metacls, cls, bases, temp)
848
849 class AutoNumberedEnum(Enum, metaclass=auto_enum):
850 pass
851
852 class AutoIntEnum(IntEnum, metaclass=auto_enum):
853 pass
854
855 class TestAutoNumber(AutoNumberedEnum):
856 a = ...
857 b = 3
858 c = ...
859
860 class TestAutoInt(AutoIntEnum):
861 a = ...
862 b = 3
863 c = ...
864
865 def test_subclasses_with_getnewargs(self):
866 class NamedInt(int):
867 def __new__(cls, *args):
868 _args = args
869 name, *args = args
870 if len(args) == 0:
871 raise TypeError("name and value must be specified")
872 self = int.__new__(cls, *args)
873 self._intname = name
874 self._args = _args
875 return self
876 def __getnewargs__(self):
877 return self._args
878 @property
879 def __name__(self):
880 return self._intname
881 def __repr__(self):
882 # repr() is updated to include the name and type info
883 return "{}({!r}, {})".format(type(self).__name__,
884 self.__name__,
885 int.__repr__(self))
886 def __str__(self):
887 # str() is unchanged, even if it relies on the repr() fallback
888 base = int
889 base_str = base.__str__
890 if base_str.__objclass__ is object:
891 return base.__repr__(self)
892 return base_str(self)
893 # for simplicity, we only define one operator that
894 # propagates expressions
895 def __add__(self, other):
896 temp = int(self) + int( other)
897 if isinstance(self, NamedInt) and isinstance(other, NamedInt):
898 return NamedInt(
899 '({0} + {1})'.format(self.__name__, other.__name__),
900 temp )
901 else:
902 return temp
903
904 class NEI(NamedInt, Enum):
905 x = ('the-x', 1)
906 y = ('the-y', 2)
907
Ethan Furman2aa27322013-07-19 19:35:56 -0700908
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700909 self.assertIs(NEI.__new__, Enum.__new__)
910 self.assertEqual(repr(NEI.x + NEI.y), "NamedInt('(the-x + the-y)', 3)")
911 globals()['NamedInt'] = NamedInt
912 globals()['NEI'] = NEI
913 NI5 = NamedInt('test', 5)
914 self.assertEqual(NI5, 5)
915 self.assertEqual(loads(dumps(NI5)), 5)
916 self.assertEqual(NEI.y.value, 2)
917 self.assertIs(loads(dumps(NEI.y)), NEI.y)
918
919 def test_subclasses_without_getnewargs(self):
920 class NamedInt(int):
921 def __new__(cls, *args):
922 _args = args
923 name, *args = args
924 if len(args) == 0:
925 raise TypeError("name and value must be specified")
926 self = int.__new__(cls, *args)
927 self._intname = name
928 self._args = _args
929 return self
930 @property
931 def __name__(self):
932 return self._intname
933 def __repr__(self):
934 # repr() is updated to include the name and type info
935 return "{}({!r}, {})".format(type(self).__name__,
936 self.__name__,
937 int.__repr__(self))
938 def __str__(self):
939 # str() is unchanged, even if it relies on the repr() fallback
940 base = int
941 base_str = base.__str__
942 if base_str.__objclass__ is object:
943 return base.__repr__(self)
944 return base_str(self)
945 # for simplicity, we only define one operator that
946 # propagates expressions
947 def __add__(self, other):
948 temp = int(self) + int( other)
949 if isinstance(self, NamedInt) and isinstance(other, NamedInt):
950 return NamedInt(
951 '({0} + {1})'.format(self.__name__, other.__name__),
952 temp )
953 else:
954 return temp
955
956 class NEI(NamedInt, Enum):
957 x = ('the-x', 1)
958 y = ('the-y', 2)
959
960 self.assertIs(NEI.__new__, Enum.__new__)
961 self.assertEqual(repr(NEI.x + NEI.y), "NamedInt('(the-x + the-y)', 3)")
962 globals()['NamedInt'] = NamedInt
963 globals()['NEI'] = NEI
964 NI5 = NamedInt('test', 5)
965 self.assertEqual(NI5, 5)
966 self.assertEqual(NEI.y.value, 2)
967 with self.assertRaises(TypeError):
968 dumps(NEI.x)
969 with self.assertRaises(PicklingError):
970 dumps(NEI)
971
972 def test_tuple_subclass(self):
973 class SomeTuple(tuple, Enum):
974 first = (1, 'for the money')
975 second = (2, 'for the show')
976 third = (3, 'for the music')
977 self.assertIs(type(SomeTuple.first), SomeTuple)
978 self.assertIsInstance(SomeTuple.second, tuple)
979 self.assertEqual(SomeTuple.third, (3, 'for the music'))
980 globals()['SomeTuple'] = SomeTuple
981 self.assertIs(loads(dumps(SomeTuple.first)), SomeTuple.first)
982
983 def test_duplicate_values_give_unique_enum_items(self):
984 class AutoNumber(Enum):
985 first = ()
986 second = ()
987 third = ()
988 def __new__(cls):
989 value = len(cls.__members__) + 1
990 obj = object.__new__(cls)
Ethan Furman520ad572013-07-19 19:47:21 -0700991 obj._value_ = value
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700992 return obj
993 def __int__(self):
Ethan Furman520ad572013-07-19 19:47:21 -0700994 return int(self._value_)
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700995 self.assertEqual(
996 list(AutoNumber),
997 [AutoNumber.first, AutoNumber.second, AutoNumber.third],
998 )
999 self.assertEqual(int(AutoNumber.second), 2)
Ethan Furman2aa27322013-07-19 19:35:56 -07001000 self.assertEqual(AutoNumber.third.value, 3)
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001001 self.assertIs(AutoNumber(1), AutoNumber.first)
1002
1003 def test_inherited_new_from_enhanced_enum(self):
1004 class AutoNumber(Enum):
1005 def __new__(cls):
1006 value = len(cls.__members__) + 1
1007 obj = object.__new__(cls)
Ethan Furman520ad572013-07-19 19:47:21 -07001008 obj._value_ = value
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001009 return obj
1010 def __int__(self):
Ethan Furman520ad572013-07-19 19:47:21 -07001011 return int(self._value_)
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001012 class Color(AutoNumber):
1013 red = ()
1014 green = ()
1015 blue = ()
1016 self.assertEqual(list(Color), [Color.red, Color.green, Color.blue])
1017 self.assertEqual(list(map(int, Color)), [1, 2, 3])
1018
1019 def test_inherited_new_from_mixed_enum(self):
1020 class AutoNumber(IntEnum):
1021 def __new__(cls):
1022 value = len(cls.__members__) + 1
1023 obj = int.__new__(cls, value)
Ethan Furman520ad572013-07-19 19:47:21 -07001024 obj._value_ = value
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001025 return obj
1026 class Color(AutoNumber):
1027 red = ()
1028 green = ()
1029 blue = ()
1030 self.assertEqual(list(Color), [Color.red, Color.green, Color.blue])
1031 self.assertEqual(list(map(int, Color)), [1, 2, 3])
1032
Ethan Furmanbe3c2fe2013-11-13 14:25:45 -08001033 def test_equality(self):
1034 class AlwaysEqual:
1035 def __eq__(self, other):
1036 return True
1037 class OrdinaryEnum(Enum):
1038 a = 1
1039 self.assertEqual(AlwaysEqual(), OrdinaryEnum.a)
1040 self.assertEqual(OrdinaryEnum.a, AlwaysEqual())
1041
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001042 def test_ordered_mixin(self):
1043 class OrderedEnum(Enum):
1044 def __ge__(self, other):
1045 if self.__class__ is other.__class__:
Ethan Furman520ad572013-07-19 19:47:21 -07001046 return self._value_ >= other._value_
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001047 return NotImplemented
1048 def __gt__(self, other):
1049 if self.__class__ is other.__class__:
Ethan Furman520ad572013-07-19 19:47:21 -07001050 return self._value_ > other._value_
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001051 return NotImplemented
1052 def __le__(self, other):
1053 if self.__class__ is other.__class__:
Ethan Furman520ad572013-07-19 19:47:21 -07001054 return self._value_ <= other._value_
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001055 return NotImplemented
1056 def __lt__(self, other):
1057 if self.__class__ is other.__class__:
Ethan Furman520ad572013-07-19 19:47:21 -07001058 return self._value_ < other._value_
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001059 return NotImplemented
1060 class Grade(OrderedEnum):
1061 A = 5
1062 B = 4
1063 C = 3
1064 D = 2
1065 F = 1
1066 self.assertGreater(Grade.A, Grade.B)
1067 self.assertLessEqual(Grade.F, Grade.C)
1068 self.assertLess(Grade.D, Grade.A)
1069 self.assertGreaterEqual(Grade.B, Grade.B)
Ethan Furmanbe3c2fe2013-11-13 14:25:45 -08001070 self.assertEqual(Grade.B, Grade.B)
1071 self.assertNotEqual(Grade.C, Grade.D)
Ethan Furman520ad572013-07-19 19:47:21 -07001072
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001073 def test_extending2(self):
1074 class Shade(Enum):
1075 def shade(self):
1076 print(self.name)
1077 class Color(Shade):
1078 red = 1
1079 green = 2
1080 blue = 3
1081 with self.assertRaises(TypeError):
1082 class MoreColor(Color):
1083 cyan = 4
1084 magenta = 5
1085 yellow = 6
1086
1087 def test_extending3(self):
1088 class Shade(Enum):
1089 def shade(self):
1090 return self.name
1091 class Color(Shade):
1092 def hex(self):
1093 return '%s hexlified!' % self.value
1094 class MoreColor(Color):
1095 cyan = 4
1096 magenta = 5
1097 yellow = 6
1098 self.assertEqual(MoreColor.magenta.hex(), '5 hexlified!')
1099
1100
1101 def test_no_duplicates(self):
1102 class UniqueEnum(Enum):
1103 def __init__(self, *args):
1104 cls = self.__class__
1105 if any(self.value == e.value for e in cls):
1106 a = self.name
1107 e = cls(self.value).name
1108 raise ValueError(
1109 "aliases not allowed in UniqueEnum: %r --> %r"
1110 % (a, e)
1111 )
1112 class Color(UniqueEnum):
1113 red = 1
1114 green = 2
1115 blue = 3
1116 with self.assertRaises(ValueError):
1117 class Color(UniqueEnum):
1118 red = 1
1119 green = 2
1120 blue = 3
1121 grene = 2
1122
1123 def test_init(self):
1124 class Planet(Enum):
1125 MERCURY = (3.303e+23, 2.4397e6)
1126 VENUS = (4.869e+24, 6.0518e6)
1127 EARTH = (5.976e+24, 6.37814e6)
1128 MARS = (6.421e+23, 3.3972e6)
1129 JUPITER = (1.9e+27, 7.1492e7)
1130 SATURN = (5.688e+26, 6.0268e7)
1131 URANUS = (8.686e+25, 2.5559e7)
1132 NEPTUNE = (1.024e+26, 2.4746e7)
1133 def __init__(self, mass, radius):
1134 self.mass = mass # in kilograms
1135 self.radius = radius # in meters
1136 @property
1137 def surface_gravity(self):
1138 # universal gravitational constant (m3 kg-1 s-2)
1139 G = 6.67300E-11
1140 return G * self.mass / (self.radius * self.radius)
1141 self.assertEqual(round(Planet.EARTH.surface_gravity, 2), 9.80)
1142 self.assertEqual(Planet.EARTH.value, (5.976e+24, 6.37814e6))
1143
Ethan Furman2aa27322013-07-19 19:35:56 -07001144 def test_nonhash_value(self):
1145 class AutoNumberInAList(Enum):
1146 def __new__(cls):
1147 value = [len(cls.__members__) + 1]
1148 obj = object.__new__(cls)
Ethan Furman520ad572013-07-19 19:47:21 -07001149 obj._value_ = value
Ethan Furman2aa27322013-07-19 19:35:56 -07001150 return obj
1151 class ColorInAList(AutoNumberInAList):
1152 red = ()
1153 green = ()
1154 blue = ()
1155 self.assertEqual(list(ColorInAList), [ColorInAList.red, ColorInAList.green, ColorInAList.blue])
Ethan Furman1a162882013-10-16 19:09:31 -07001156 for enum, value in zip(ColorInAList, range(3)):
1157 value += 1
1158 self.assertEqual(enum.value, [value])
1159 self.assertIs(ColorInAList([value]), enum)
Ethan Furman2aa27322013-07-19 19:35:56 -07001160
Ethan Furmanb41803e2013-07-25 13:50:45 -07001161 def test_conflicting_types_resolved_in_new(self):
1162 class LabelledIntEnum(int, Enum):
1163 def __new__(cls, *args):
1164 value, label = args
1165 obj = int.__new__(cls, value)
1166 obj.label = label
1167 obj._value_ = value
1168 return obj
1169
1170 class LabelledList(LabelledIntEnum):
1171 unprocessed = (1, "Unprocessed")
1172 payment_complete = (2, "Payment Complete")
1173
1174 self.assertEqual(list(LabelledList), [LabelledList.unprocessed, LabelledList.payment_complete])
1175 self.assertEqual(LabelledList.unprocessed, 1)
1176 self.assertEqual(LabelledList(1), LabelledList.unprocessed)
Ethan Furman2aa27322013-07-19 19:35:56 -07001177
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001178
Ethan Furmanf24bb352013-07-18 17:05:39 -07001179class TestUnique(unittest.TestCase):
1180
1181 def test_unique_clean(self):
1182 @unique
1183 class Clean(Enum):
1184 one = 1
1185 two = 'dos'
1186 tres = 4.0
1187 @unique
1188 class Cleaner(IntEnum):
1189 single = 1
1190 double = 2
1191 triple = 3
1192
1193 def test_unique_dirty(self):
1194 with self.assertRaisesRegex(ValueError, 'tres.*one'):
1195 @unique
1196 class Dirty(Enum):
1197 one = 1
1198 two = 'dos'
1199 tres = 1
1200 with self.assertRaisesRegex(
1201 ValueError,
1202 'double.*single.*turkey.*triple',
1203 ):
1204 @unique
1205 class Dirtier(IntEnum):
1206 single = 1
1207 double = 1
1208 triple = 3
1209 turkey = 3
1210
1211
Ethan Furman5875d742013-10-21 20:45:55 -07001212expected_help_output = """
1213Help on class Color in module %s:
1214
1215class Color(enum.Enum)
1216 | Method resolution order:
1217 | Color
1218 | enum.Enum
1219 | builtins.object
1220 |\x20\x20
1221 | Data and other attributes defined here:
1222 |\x20\x20
1223 | blue = <Color.blue: 3>
1224 |\x20\x20
1225 | green = <Color.green: 2>
1226 |\x20\x20
1227 | red = <Color.red: 1>
1228 |\x20\x20
1229 | ----------------------------------------------------------------------
1230 | Data descriptors inherited from enum.Enum:
1231 |\x20\x20
1232 | name
1233 | The name of the Enum member.
1234 |\x20\x20
1235 | value
1236 | The value of the Enum member.
1237 |\x20\x20
1238 | ----------------------------------------------------------------------
1239 | Data descriptors inherited from enum.EnumMeta:
1240 |\x20\x20
1241 | __members__
1242 | Returns a mapping of member name->value.
1243 |\x20\x20\x20\x20\x20\x20
1244 | This mapping lists all enum members, including aliases. Note that this
1245 | is a read-only view of the internal mapping.
1246""".strip()
1247
1248class TestStdLib(unittest.TestCase):
1249
1250 class Color(Enum):
1251 red = 1
1252 green = 2
1253 blue = 3
1254
1255 def test_pydoc(self):
1256 # indirectly test __objclass__
1257 expected_text = expected_help_output % __name__
1258 output = StringIO()
1259 helper = pydoc.Helper(output=output)
1260 helper(self.Color)
1261 result = output.getvalue().strip()
1262 if result != expected_text:
1263 print_diffs(expected_text, result)
1264 self.fail("outputs are not equal, see diff above")
1265
1266 def test_inspect_getmembers(self):
1267 values = dict((
1268 ('__class__', EnumMeta),
1269 ('__doc__', None),
1270 ('__members__', self.Color.__members__),
1271 ('__module__', __name__),
1272 ('blue', self.Color.blue),
1273 ('green', self.Color.green),
1274 ('name', Enum.__dict__['name']),
1275 ('red', self.Color.red),
1276 ('value', Enum.__dict__['value']),
1277 ))
1278 result = dict(inspect.getmembers(self.Color))
1279 self.assertEqual(values.keys(), result.keys())
1280 failed = False
1281 for k in values.keys():
1282 if result[k] != values[k]:
1283 print()
1284 print('\n%s\n key: %s\n result: %s\nexpected: %s\n%s\n' %
1285 ('=' * 75, k, result[k], values[k], '=' * 75), sep='')
1286 failed = True
1287 if failed:
1288 self.fail("result does not equal expected, see print above")
1289
1290 def test_inspect_classify_class_attrs(self):
1291 # indirectly test __objclass__
1292 from inspect import Attribute
1293 values = [
1294 Attribute(name='__class__', kind='data',
1295 defining_class=object, object=EnumMeta),
1296 Attribute(name='__doc__', kind='data',
1297 defining_class=self.Color, object=None),
1298 Attribute(name='__members__', kind='property',
1299 defining_class=EnumMeta, object=EnumMeta.__members__),
1300 Attribute(name='__module__', kind='data',
1301 defining_class=self.Color, object=__name__),
1302 Attribute(name='blue', kind='data',
1303 defining_class=self.Color, object=self.Color.blue),
1304 Attribute(name='green', kind='data',
1305 defining_class=self.Color, object=self.Color.green),
1306 Attribute(name='red', kind='data',
1307 defining_class=self.Color, object=self.Color.red),
1308 Attribute(name='name', kind='data',
1309 defining_class=Enum, object=Enum.__dict__['name']),
1310 Attribute(name='value', kind='data',
1311 defining_class=Enum, object=Enum.__dict__['value']),
1312 ]
1313 values.sort(key=lambda item: item.name)
1314 result = list(inspect.classify_class_attrs(self.Color))
1315 result.sort(key=lambda item: item.name)
1316 failed = False
1317 for v, r in zip(values, result):
1318 if r != v:
1319 print('\n%s\n%s\n%s\n%s\n' % ('=' * 75, r, v, '=' * 75), sep='')
1320 failed = True
1321 if failed:
1322 self.fail("result does not equal expected, see print above")
1323
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001324if __name__ == '__main__':
1325 unittest.main()