blob: fcfa7d923e75604c13bb5818382ee497fd938644 [file] [log] [blame]
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001import enum
Ethan Furman5875d742013-10-21 20:45:55 -07002import inspect
3import pydoc
orlnub1230fb9fad2018-09-12 20:28:53 +03004import sys
Ethan Furman6b3d64a2013-06-14 16:55:46 -07005import unittest
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02006import threading
Ethan Furman6b3d64a2013-06-14 16:55:46 -07007from collections import OrderedDict
Ethan Furmanc16595e2016-09-10 23:36:59 -07008from enum import Enum, IntEnum, EnumMeta, Flag, IntFlag, unique, auto
Ethan Furman5875d742013-10-21 20:45:55 -07009from io import StringIO
Ethan Furman2ddb39a2014-02-06 17:28:50 -080010from pickle import dumps, loads, PicklingError, HIGHEST_PROTOCOL
Martin Panter19e69c52015-11-14 12:46:42 +000011from test import support
Ethan Furmana4b1bb42018-01-22 07:56:37 -080012from datetime import timedelta
Ethan Furman28cf6632017-01-24 12:12:06 -080013
Ethan Furman6b3d64a2013-06-14 16:55:46 -070014
15# for pickle tests
16try:
17 class Stooges(Enum):
18 LARRY = 1
19 CURLY = 2
20 MOE = 3
21except Exception as exc:
22 Stooges = exc
23
24try:
25 class IntStooges(int, Enum):
26 LARRY = 1
27 CURLY = 2
28 MOE = 3
29except Exception as exc:
30 IntStooges = exc
31
32try:
33 class FloatStooges(float, Enum):
34 LARRY = 1.39
35 CURLY = 2.72
36 MOE = 3.142596
37except Exception as exc:
38 FloatStooges = exc
39
Ethan Furman65a5a472016-09-01 23:55:19 -070040try:
41 class FlagStooges(Flag):
42 LARRY = 1
43 CURLY = 2
44 MOE = 3
45except Exception as exc:
46 FlagStooges = exc
47
Ethan Furman6b3d64a2013-06-14 16:55:46 -070048# for pickle test and subclass tests
49try:
50 class StrEnum(str, Enum):
51 'accepts only string values'
52 class Name(StrEnum):
53 BDFL = 'Guido van Rossum'
54 FLUFL = 'Barry Warsaw'
55except Exception as exc:
56 Name = exc
57
58try:
59 Question = Enum('Question', 'who what when where why', module=__name__)
60except Exception as exc:
61 Question = exc
62
63try:
64 Answer = Enum('Answer', 'him this then there because')
65except Exception as exc:
66 Answer = exc
67
Ethan Furmanca1b7942014-02-08 11:36:27 -080068try:
69 Theory = Enum('Theory', 'rule law supposition', qualname='spanish_inquisition')
70except Exception as exc:
71 Theory = exc
72
Ethan Furman6b3d64a2013-06-14 16:55:46 -070073# for doctests
74try:
75 class Fruit(Enum):
Ethan Furman23bb6f42016-11-21 09:22:05 -080076 TOMATO = 1
77 BANANA = 2
78 CHERRY = 3
Ethan Furman6b3d64a2013-06-14 16:55:46 -070079except Exception:
80 pass
81
Serhiy Storchakae50e7802015-03-31 16:56:49 +030082def test_pickle_dump_load(assertion, source, target=None):
Ethan Furman2ddb39a2014-02-06 17:28:50 -080083 if target is None:
84 target = source
Serhiy Storchakae50e7802015-03-31 16:56:49 +030085 for protocol in range(HIGHEST_PROTOCOL + 1):
Ethan Furman2ddb39a2014-02-06 17:28:50 -080086 assertion(loads(dumps(source, protocol=protocol)), target)
87
Serhiy Storchakae50e7802015-03-31 16:56:49 +030088def test_pickle_exception(assertion, exception, obj):
89 for protocol in range(HIGHEST_PROTOCOL + 1):
Ethan Furman2ddb39a2014-02-06 17:28:50 -080090 with assertion(exception):
91 dumps(obj, protocol=protocol)
Ethan Furman648f8602013-10-06 17:19:54 -070092
93class TestHelpers(unittest.TestCase):
94 # _is_descriptor, _is_sunder, _is_dunder
95
96 def test_is_descriptor(self):
97 class foo:
98 pass
99 for attr in ('__get__','__set__','__delete__'):
100 obj = foo()
101 self.assertFalse(enum._is_descriptor(obj))
102 setattr(obj, attr, 1)
103 self.assertTrue(enum._is_descriptor(obj))
104
105 def test_is_sunder(self):
106 for s in ('_a_', '_aa_'):
107 self.assertTrue(enum._is_sunder(s))
108
109 for s in ('a', 'a_', '_a', '__a', 'a__', '__a__', '_a__', '__a_', '_',
110 '__', '___', '____', '_____',):
111 self.assertFalse(enum._is_sunder(s))
112
113 def test_is_dunder(self):
114 for s in ('__a__', '__aa__'):
115 self.assertTrue(enum._is_dunder(s))
116 for s in ('a', 'a_', '_a', '__a', 'a__', '_a_', '_a__', '__a_', '_',
117 '__', '___', '____', '_____',):
118 self.assertFalse(enum._is_dunder(s))
119
Ethan Furman5bdab642018-09-21 19:03:09 -0700120# for subclassing tests
121
122class classproperty:
123
124 def __init__(self, fget=None, fset=None, fdel=None, doc=None):
125 self.fget = fget
126 self.fset = fset
127 self.fdel = fdel
128 if doc is None and fget is not None:
129 doc = fget.__doc__
130 self.__doc__ = doc
131
132 def __get__(self, instance, ownerclass):
133 return self.fget(ownerclass)
134
135
Ethan Furmanc16595e2016-09-10 23:36:59 -0700136# tests
Ethan Furman648f8602013-10-06 17:19:54 -0700137
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700138class TestEnum(unittest.TestCase):
Ethan Furmanca1b7942014-02-08 11:36:27 -0800139
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700140 def setUp(self):
141 class Season(Enum):
142 SPRING = 1
143 SUMMER = 2
144 AUTUMN = 3
145 WINTER = 4
146 self.Season = Season
147
Ethan Furmanec15a822013-08-31 19:17:41 -0700148 class Konstants(float, Enum):
149 E = 2.7182818
150 PI = 3.1415926
151 TAU = 2 * PI
152 self.Konstants = Konstants
153
154 class Grades(IntEnum):
155 A = 5
156 B = 4
157 C = 3
158 D = 2
159 F = 0
160 self.Grades = Grades
161
162 class Directional(str, Enum):
163 EAST = 'east'
164 WEST = 'west'
165 NORTH = 'north'
166 SOUTH = 'south'
167 self.Directional = Directional
168
169 from datetime import date
170 class Holiday(date, Enum):
171 NEW_YEAR = 2013, 1, 1
172 IDES_OF_MARCH = 2013, 3, 15
173 self.Holiday = Holiday
174
Ethan Furman388a3922013-08-12 06:51:41 -0700175 def test_dir_on_class(self):
176 Season = self.Season
177 self.assertEqual(
178 set(dir(Season)),
Ethan Furmanc850f342013-09-15 16:59:35 -0700179 set(['__class__', '__doc__', '__members__', '__module__',
Ethan Furman388a3922013-08-12 06:51:41 -0700180 'SPRING', 'SUMMER', 'AUTUMN', 'WINTER']),
181 )
182
183 def test_dir_on_item(self):
184 Season = self.Season
185 self.assertEqual(
186 set(dir(Season.WINTER)),
Ethan Furmanc850f342013-09-15 16:59:35 -0700187 set(['__class__', '__doc__', '__module__', 'name', 'value']),
Ethan Furman388a3922013-08-12 06:51:41 -0700188 )
189
Ethan Furmanc850f342013-09-15 16:59:35 -0700190 def test_dir_with_added_behavior(self):
191 class Test(Enum):
192 this = 'that'
193 these = 'those'
194 def wowser(self):
195 return ("Wowser! I'm %s!" % self.name)
196 self.assertEqual(
197 set(dir(Test)),
198 set(['__class__', '__doc__', '__members__', '__module__', 'this', 'these']),
199 )
200 self.assertEqual(
201 set(dir(Test.this)),
202 set(['__class__', '__doc__', '__module__', 'name', 'value', 'wowser']),
203 )
204
Ethan Furman0ae550b2014-10-14 08:58:32 -0700205 def test_dir_on_sub_with_behavior_on_super(self):
206 # see issue22506
207 class SuperEnum(Enum):
208 def invisible(self):
209 return "did you see me?"
210 class SubEnum(SuperEnum):
211 sample = 5
212 self.assertEqual(
213 set(dir(SubEnum.sample)),
214 set(['__class__', '__doc__', '__module__', 'name', 'value', 'invisible']),
215 )
216
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700217 def test_enum_in_enum_out(self):
218 Season = self.Season
219 self.assertIs(Season(Season.WINTER), Season.WINTER)
220
221 def test_enum_value(self):
222 Season = self.Season
223 self.assertEqual(Season.SPRING.value, 1)
224
225 def test_intenum_value(self):
226 self.assertEqual(IntStooges.CURLY.value, 2)
227
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700228 def test_enum(self):
229 Season = self.Season
230 lst = list(Season)
231 self.assertEqual(len(lst), len(Season))
232 self.assertEqual(len(Season), 4, Season)
233 self.assertEqual(
234 [Season.SPRING, Season.SUMMER, Season.AUTUMN, Season.WINTER], lst)
235
236 for i, season in enumerate('SPRING SUMMER AUTUMN WINTER'.split(), 1):
237 e = Season(i)
238 self.assertEqual(e, getattr(Season, season))
239 self.assertEqual(e.value, i)
240 self.assertNotEqual(e, i)
241 self.assertEqual(e.name, season)
242 self.assertIn(e, Season)
243 self.assertIs(type(e), Season)
244 self.assertIsInstance(e, Season)
245 self.assertEqual(str(e), 'Season.' + season)
246 self.assertEqual(
247 repr(e),
248 '<Season.{0}: {1}>'.format(season, i),
249 )
250
251 def test_value_name(self):
252 Season = self.Season
253 self.assertEqual(Season.SPRING.name, 'SPRING')
254 self.assertEqual(Season.SPRING.value, 1)
255 with self.assertRaises(AttributeError):
256 Season.SPRING.name = 'invierno'
257 with self.assertRaises(AttributeError):
258 Season.SPRING.value = 2
259
Ethan Furmanf203f2d2013-09-06 07:16:48 -0700260 def test_changing_member(self):
261 Season = self.Season
262 with self.assertRaises(AttributeError):
263 Season.WINTER = 'really cold'
264
Ethan Furman64a99722013-09-22 16:18:19 -0700265 def test_attribute_deletion(self):
266 class Season(Enum):
267 SPRING = 1
268 SUMMER = 2
269 AUTUMN = 3
270 WINTER = 4
271
272 def spam(cls):
273 pass
274
275 self.assertTrue(hasattr(Season, 'spam'))
276 del Season.spam
277 self.assertFalse(hasattr(Season, 'spam'))
278
279 with self.assertRaises(AttributeError):
280 del Season.SPRING
281 with self.assertRaises(AttributeError):
282 del Season.DRY
283 with self.assertRaises(AttributeError):
284 del Season.SPRING.name
285
Ethan Furman5de67b12016-04-13 23:52:09 -0700286 def test_bool_of_class(self):
287 class Empty(Enum):
288 pass
289 self.assertTrue(bool(Empty))
290
291 def test_bool_of_member(self):
292 class Count(Enum):
293 zero = 0
294 one = 1
295 two = 2
296 for member in Count:
297 self.assertTrue(bool(member))
298
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700299 def test_invalid_names(self):
300 with self.assertRaises(ValueError):
301 class Wrong(Enum):
302 mro = 9
303 with self.assertRaises(ValueError):
304 class Wrong(Enum):
305 _create_= 11
306 with self.assertRaises(ValueError):
307 class Wrong(Enum):
308 _get_mixins_ = 9
309 with self.assertRaises(ValueError):
310 class Wrong(Enum):
311 _find_new_ = 1
312 with self.assertRaises(ValueError):
313 class Wrong(Enum):
314 _any_name_ = 9
315
Ethan Furman6db1fd52015-09-17 21:49:12 -0700316 def test_bool(self):
Ethan Furman60255b62016-01-15 15:01:33 -0800317 # plain Enum members are always True
Ethan Furman6db1fd52015-09-17 21:49:12 -0700318 class Logic(Enum):
319 true = True
320 false = False
321 self.assertTrue(Logic.true)
Ethan Furman60255b62016-01-15 15:01:33 -0800322 self.assertTrue(Logic.false)
323 # unless overridden
324 class RealLogic(Enum):
325 true = True
326 false = False
327 def __bool__(self):
328 return bool(self._value_)
329 self.assertTrue(RealLogic.true)
330 self.assertFalse(RealLogic.false)
331 # mixed Enums depend on mixed-in type
332 class IntLogic(int, Enum):
333 true = 1
334 false = 0
335 self.assertTrue(IntLogic.true)
336 self.assertFalse(IntLogic.false)
Ethan Furman6db1fd52015-09-17 21:49:12 -0700337
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700338 def test_contains(self):
339 Season = self.Season
340 self.assertIn(Season.AUTUMN, Season)
Rahul Jha94306522018-09-10 23:51:04 +0530341 with self.assertRaises(TypeError):
342 3 in Season
343 with self.assertRaises(TypeError):
344 'AUTUMN' in Season
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700345
346 val = Season(3)
347 self.assertIn(val, Season)
348
349 class OtherEnum(Enum):
350 one = 1; two = 2
351 self.assertNotIn(OtherEnum.two, Season)
352
353 def test_comparisons(self):
354 Season = self.Season
355 with self.assertRaises(TypeError):
356 Season.SPRING < Season.WINTER
357 with self.assertRaises(TypeError):
358 Season.SPRING > 4
359
360 self.assertNotEqual(Season.SPRING, 1)
361
362 class Part(Enum):
363 SPRING = 1
364 CLIP = 2
365 BARREL = 3
366
367 self.assertNotEqual(Season.SPRING, Part.SPRING)
368 with self.assertRaises(TypeError):
369 Season.SPRING < Part.CLIP
370
371 def test_enum_duplicates(self):
372 class Season(Enum):
373 SPRING = 1
374 SUMMER = 2
375 AUTUMN = FALL = 3
376 WINTER = 4
377 ANOTHER_SPRING = 1
378 lst = list(Season)
379 self.assertEqual(
380 lst,
381 [Season.SPRING, Season.SUMMER,
382 Season.AUTUMN, Season.WINTER,
383 ])
384 self.assertIs(Season.FALL, Season.AUTUMN)
385 self.assertEqual(Season.FALL.value, 3)
386 self.assertEqual(Season.AUTUMN.value, 3)
387 self.assertIs(Season(3), Season.AUTUMN)
388 self.assertIs(Season(1), Season.SPRING)
389 self.assertEqual(Season.FALL.name, 'AUTUMN')
390 self.assertEqual(
391 [k for k,v in Season.__members__.items() if v.name != k],
392 ['FALL', 'ANOTHER_SPRING'],
393 )
394
Ethan Furman101e0742013-09-15 12:34:36 -0700395 def test_duplicate_name(self):
396 with self.assertRaises(TypeError):
397 class Color(Enum):
398 red = 1
399 green = 2
400 blue = 3
401 red = 4
402
403 with self.assertRaises(TypeError):
404 class Color(Enum):
405 red = 1
406 green = 2
407 blue = 3
408 def red(self):
409 return 'red'
410
411 with self.assertRaises(TypeError):
412 class Color(Enum):
413 @property
414 def red(self):
415 return 'redder'
416 red = 1
417 green = 2
418 blue = 3
419
420
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700421 def test_enum_with_value_name(self):
422 class Huh(Enum):
423 name = 1
424 value = 2
425 self.assertEqual(
426 list(Huh),
427 [Huh.name, Huh.value],
428 )
429 self.assertIs(type(Huh.name), Huh)
430 self.assertEqual(Huh.name.name, 'name')
431 self.assertEqual(Huh.name.value, 1)
Ethan Furmanec15a822013-08-31 19:17:41 -0700432
433 def test_format_enum(self):
434 Season = self.Season
435 self.assertEqual('{}'.format(Season.SPRING),
436 '{}'.format(str(Season.SPRING)))
437 self.assertEqual( '{:}'.format(Season.SPRING),
438 '{:}'.format(str(Season.SPRING)))
439 self.assertEqual('{:20}'.format(Season.SPRING),
440 '{:20}'.format(str(Season.SPRING)))
441 self.assertEqual('{:^20}'.format(Season.SPRING),
442 '{:^20}'.format(str(Season.SPRING)))
443 self.assertEqual('{:>20}'.format(Season.SPRING),
444 '{:>20}'.format(str(Season.SPRING)))
445 self.assertEqual('{:<20}'.format(Season.SPRING),
446 '{:<20}'.format(str(Season.SPRING)))
447
thatneat2f19e822019-07-04 11:28:37 -0700448 def test_str_override_enum(self):
449 class EnumWithStrOverrides(Enum):
450 one = auto()
451 two = auto()
452
453 def __str__(self):
454 return 'Str!'
455 self.assertEqual(str(EnumWithStrOverrides.one), 'Str!')
456 self.assertEqual('{}'.format(EnumWithStrOverrides.one), 'Str!')
457
458 def test_format_override_enum(self):
459 class EnumWithFormatOverride(Enum):
460 one = 1.0
461 two = 2.0
462 def __format__(self, spec):
463 return 'Format!!'
464 self.assertEqual(str(EnumWithFormatOverride.one), 'EnumWithFormatOverride.one')
465 self.assertEqual('{}'.format(EnumWithFormatOverride.one), 'Format!!')
466
467 def test_str_and_format_override_enum(self):
468 class EnumWithStrFormatOverrides(Enum):
469 one = auto()
470 two = auto()
471 def __str__(self):
472 return 'Str!'
473 def __format__(self, spec):
474 return 'Format!'
475 self.assertEqual(str(EnumWithStrFormatOverrides.one), 'Str!')
476 self.assertEqual('{}'.format(EnumWithStrFormatOverrides.one), 'Format!')
477
478 def test_str_override_mixin(self):
479 class MixinEnumWithStrOverride(float, Enum):
480 one = 1.0
481 two = 2.0
482 def __str__(self):
483 return 'Overridden!'
484 self.assertEqual(str(MixinEnumWithStrOverride.one), 'Overridden!')
485 self.assertEqual('{}'.format(MixinEnumWithStrOverride.one), 'Overridden!')
486
487 def test_str_and_format_override_mixin(self):
488 class MixinWithStrFormatOverrides(float, Enum):
489 one = 1.0
490 two = 2.0
491 def __str__(self):
492 return 'Str!'
493 def __format__(self, spec):
494 return 'Format!'
495 self.assertEqual(str(MixinWithStrFormatOverrides.one), 'Str!')
496 self.assertEqual('{}'.format(MixinWithStrFormatOverrides.one), 'Format!')
497
498 def test_format_override_mixin(self):
Ethan Furmanec15a822013-08-31 19:17:41 -0700499 class TestFloat(float, Enum):
500 one = 1.0
501 two = 2.0
502 def __format__(self, spec):
503 return 'TestFloat success!'
thatneat2f19e822019-07-04 11:28:37 -0700504 self.assertEqual(str(TestFloat.one), 'TestFloat.one')
Ethan Furmanec15a822013-08-31 19:17:41 -0700505 self.assertEqual('{}'.format(TestFloat.one), 'TestFloat success!')
506
507 def assertFormatIsValue(self, spec, member):
508 self.assertEqual(spec.format(member), spec.format(member.value))
509
510 def test_format_enum_date(self):
511 Holiday = self.Holiday
512 self.assertFormatIsValue('{}', Holiday.IDES_OF_MARCH)
513 self.assertFormatIsValue('{:}', Holiday.IDES_OF_MARCH)
514 self.assertFormatIsValue('{:20}', Holiday.IDES_OF_MARCH)
515 self.assertFormatIsValue('{:^20}', Holiday.IDES_OF_MARCH)
516 self.assertFormatIsValue('{:>20}', Holiday.IDES_OF_MARCH)
517 self.assertFormatIsValue('{:<20}', Holiday.IDES_OF_MARCH)
518 self.assertFormatIsValue('{:%Y %m}', Holiday.IDES_OF_MARCH)
519 self.assertFormatIsValue('{:%Y %m %M:00}', Holiday.IDES_OF_MARCH)
520
521 def test_format_enum_float(self):
522 Konstants = self.Konstants
523 self.assertFormatIsValue('{}', Konstants.TAU)
524 self.assertFormatIsValue('{:}', Konstants.TAU)
525 self.assertFormatIsValue('{:20}', Konstants.TAU)
526 self.assertFormatIsValue('{:^20}', Konstants.TAU)
527 self.assertFormatIsValue('{:>20}', Konstants.TAU)
528 self.assertFormatIsValue('{:<20}', Konstants.TAU)
529 self.assertFormatIsValue('{:n}', Konstants.TAU)
530 self.assertFormatIsValue('{:5.2}', Konstants.TAU)
531 self.assertFormatIsValue('{:f}', Konstants.TAU)
532
533 def test_format_enum_int(self):
534 Grades = self.Grades
535 self.assertFormatIsValue('{}', Grades.C)
536 self.assertFormatIsValue('{:}', Grades.C)
537 self.assertFormatIsValue('{:20}', Grades.C)
538 self.assertFormatIsValue('{:^20}', Grades.C)
539 self.assertFormatIsValue('{:>20}', Grades.C)
540 self.assertFormatIsValue('{:<20}', Grades.C)
541 self.assertFormatIsValue('{:+}', Grades.C)
542 self.assertFormatIsValue('{:08X}', Grades.C)
543 self.assertFormatIsValue('{:b}', Grades.C)
544
545 def test_format_enum_str(self):
546 Directional = self.Directional
547 self.assertFormatIsValue('{}', Directional.WEST)
548 self.assertFormatIsValue('{:}', Directional.WEST)
549 self.assertFormatIsValue('{:20}', Directional.WEST)
550 self.assertFormatIsValue('{:^20}', Directional.WEST)
551 self.assertFormatIsValue('{:>20}', Directional.WEST)
552 self.assertFormatIsValue('{:<20}', Directional.WEST)
553
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700554 def test_hash(self):
555 Season = self.Season
556 dates = {}
557 dates[Season.WINTER] = '1225'
558 dates[Season.SPRING] = '0315'
559 dates[Season.SUMMER] = '0704'
560 dates[Season.AUTUMN] = '1031'
561 self.assertEqual(dates[Season.AUTUMN], '1031')
562
563 def test_intenum_from_scratch(self):
564 class phy(int, Enum):
565 pi = 3
566 tau = 2 * pi
567 self.assertTrue(phy.pi < phy.tau)
568
569 def test_intenum_inherited(self):
570 class IntEnum(int, Enum):
571 pass
572 class phy(IntEnum):
573 pi = 3
574 tau = 2 * pi
575 self.assertTrue(phy.pi < phy.tau)
576
577 def test_floatenum_from_scratch(self):
578 class phy(float, Enum):
Ethan Furmanec15a822013-08-31 19:17:41 -0700579 pi = 3.1415926
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700580 tau = 2 * pi
581 self.assertTrue(phy.pi < phy.tau)
582
583 def test_floatenum_inherited(self):
584 class FloatEnum(float, Enum):
585 pass
586 class phy(FloatEnum):
Ethan Furmanec15a822013-08-31 19:17:41 -0700587 pi = 3.1415926
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700588 tau = 2 * pi
589 self.assertTrue(phy.pi < phy.tau)
590
591 def test_strenum_from_scratch(self):
592 class phy(str, Enum):
593 pi = 'Pi'
594 tau = 'Tau'
595 self.assertTrue(phy.pi < phy.tau)
596
597 def test_strenum_inherited(self):
598 class StrEnum(str, Enum):
599 pass
600 class phy(StrEnum):
601 pi = 'Pi'
602 tau = 'Tau'
603 self.assertTrue(phy.pi < phy.tau)
604
605
606 def test_intenum(self):
607 class WeekDay(IntEnum):
608 SUNDAY = 1
609 MONDAY = 2
610 TUESDAY = 3
611 WEDNESDAY = 4
612 THURSDAY = 5
613 FRIDAY = 6
614 SATURDAY = 7
615
616 self.assertEqual(['a', 'b', 'c'][WeekDay.MONDAY], 'c')
617 self.assertEqual([i for i in range(WeekDay.TUESDAY)], [0, 1, 2])
618
619 lst = list(WeekDay)
620 self.assertEqual(len(lst), len(WeekDay))
621 self.assertEqual(len(WeekDay), 7)
622 target = 'SUNDAY MONDAY TUESDAY WEDNESDAY THURSDAY FRIDAY SATURDAY'
623 target = target.split()
624 for i, weekday in enumerate(target, 1):
625 e = WeekDay(i)
626 self.assertEqual(e, i)
627 self.assertEqual(int(e), i)
628 self.assertEqual(e.name, weekday)
629 self.assertIn(e, WeekDay)
630 self.assertEqual(lst.index(e)+1, i)
631 self.assertTrue(0 < e < 8)
632 self.assertIs(type(e), WeekDay)
633 self.assertIsInstance(e, int)
634 self.assertIsInstance(e, Enum)
635
636 def test_intenum_duplicates(self):
637 class WeekDay(IntEnum):
638 SUNDAY = 1
639 MONDAY = 2
640 TUESDAY = TEUSDAY = 3
641 WEDNESDAY = 4
642 THURSDAY = 5
643 FRIDAY = 6
644 SATURDAY = 7
645 self.assertIs(WeekDay.TEUSDAY, WeekDay.TUESDAY)
646 self.assertEqual(WeekDay(3).name, 'TUESDAY')
647 self.assertEqual([k for k,v in WeekDay.__members__.items()
648 if v.name != k], ['TEUSDAY', ])
649
Serhiy Storchakaea36c942016-05-12 10:37:58 +0300650 def test_intenum_from_bytes(self):
651 self.assertIs(IntStooges.from_bytes(b'\x00\x03', 'big'), IntStooges.MOE)
652 with self.assertRaises(ValueError):
653 IntStooges.from_bytes(b'\x00\x05', 'big')
654
655 def test_floatenum_fromhex(self):
656 h = float.hex(FloatStooges.MOE.value)
657 self.assertIs(FloatStooges.fromhex(h), FloatStooges.MOE)
658 h = float.hex(FloatStooges.MOE.value + 0.01)
659 with self.assertRaises(ValueError):
660 FloatStooges.fromhex(h)
661
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700662 def test_pickle_enum(self):
663 if isinstance(Stooges, Exception):
664 raise Stooges
Ethan Furman2ddb39a2014-02-06 17:28:50 -0800665 test_pickle_dump_load(self.assertIs, Stooges.CURLY)
666 test_pickle_dump_load(self.assertIs, Stooges)
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700667
668 def test_pickle_int(self):
669 if isinstance(IntStooges, Exception):
670 raise IntStooges
Ethan Furman2ddb39a2014-02-06 17:28:50 -0800671 test_pickle_dump_load(self.assertIs, IntStooges.CURLY)
672 test_pickle_dump_load(self.assertIs, IntStooges)
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700673
674 def test_pickle_float(self):
675 if isinstance(FloatStooges, Exception):
676 raise FloatStooges
Ethan Furman2ddb39a2014-02-06 17:28:50 -0800677 test_pickle_dump_load(self.assertIs, FloatStooges.CURLY)
678 test_pickle_dump_load(self.assertIs, FloatStooges)
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700679
680 def test_pickle_enum_function(self):
681 if isinstance(Answer, Exception):
682 raise Answer
Ethan Furman2ddb39a2014-02-06 17:28:50 -0800683 test_pickle_dump_load(self.assertIs, Answer.him)
684 test_pickle_dump_load(self.assertIs, Answer)
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700685
686 def test_pickle_enum_function_with_module(self):
687 if isinstance(Question, Exception):
688 raise Question
Ethan Furman2ddb39a2014-02-06 17:28:50 -0800689 test_pickle_dump_load(self.assertIs, Question.who)
690 test_pickle_dump_load(self.assertIs, Question)
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700691
Ethan Furmanca1b7942014-02-08 11:36:27 -0800692 def test_enum_function_with_qualname(self):
693 if isinstance(Theory, Exception):
694 raise Theory
695 self.assertEqual(Theory.__qualname__, 'spanish_inquisition')
696
697 def test_class_nested_enum_and_pickle_protocol_four(self):
698 # would normally just have this directly in the class namespace
699 class NestedEnum(Enum):
700 twigs = 'common'
701 shiny = 'rare'
702
703 self.__class__.NestedEnum = NestedEnum
704 self.NestedEnum.__qualname__ = '%s.NestedEnum' % self.__class__.__name__
Serhiy Storchakae50e7802015-03-31 16:56:49 +0300705 test_pickle_dump_load(self.assertIs, self.NestedEnum.twigs)
Ethan Furmanca1b7942014-02-08 11:36:27 -0800706
Ethan Furman24e837f2015-03-18 17:27:57 -0700707 def test_pickle_by_name(self):
708 class ReplaceGlobalInt(IntEnum):
709 ONE = 1
710 TWO = 2
711 ReplaceGlobalInt.__reduce_ex__ = enum._reduce_ex_by_name
712 for proto in range(HIGHEST_PROTOCOL):
713 self.assertEqual(ReplaceGlobalInt.TWO.__reduce_ex__(proto), 'TWO')
714
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700715 def test_exploding_pickle(self):
Ethan Furmanca1b7942014-02-08 11:36:27 -0800716 BadPickle = Enum(
717 'BadPickle', 'dill sweet bread-n-butter', module=__name__)
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700718 globals()['BadPickle'] = BadPickle
Ethan Furmanca1b7942014-02-08 11:36:27 -0800719 # now break BadPickle to test exception raising
720 enum._make_class_unpicklable(BadPickle)
Ethan Furman2ddb39a2014-02-06 17:28:50 -0800721 test_pickle_exception(self.assertRaises, TypeError, BadPickle.dill)
722 test_pickle_exception(self.assertRaises, PicklingError, BadPickle)
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700723
724 def test_string_enum(self):
725 class SkillLevel(str, Enum):
726 master = 'what is the sound of one hand clapping?'
727 journeyman = 'why did the chicken cross the road?'
728 apprentice = 'knock, knock!'
729 self.assertEqual(SkillLevel.apprentice, 'knock, knock!')
730
731 def test_getattr_getitem(self):
732 class Period(Enum):
733 morning = 1
734 noon = 2
735 evening = 3
736 night = 4
737 self.assertIs(Period(2), Period.noon)
738 self.assertIs(getattr(Period, 'night'), Period.night)
739 self.assertIs(Period['morning'], Period.morning)
740
741 def test_getattr_dunder(self):
742 Season = self.Season
743 self.assertTrue(getattr(Season, '__eq__'))
744
745 def test_iteration_order(self):
746 class Season(Enum):
747 SUMMER = 2
748 WINTER = 4
749 AUTUMN = 3
750 SPRING = 1
751 self.assertEqual(
752 list(Season),
753 [Season.SUMMER, Season.WINTER, Season.AUTUMN, Season.SPRING],
754 )
755
Ethan Furman2131a4a2013-09-14 18:11:24 -0700756 def test_reversed_iteration_order(self):
757 self.assertEqual(
758 list(reversed(self.Season)),
759 [self.Season.WINTER, self.Season.AUTUMN, self.Season.SUMMER,
760 self.Season.SPRING]
761 )
762
Martin Pantereb995702016-07-28 01:11:04 +0000763 def test_programmatic_function_string(self):
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700764 SummerMonth = Enum('SummerMonth', 'june july august')
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(), 1):
773 e = SummerMonth(i)
774 self.assertEqual(int(e.value), i)
775 self.assertNotEqual(e, i)
776 self.assertEqual(e.name, month)
777 self.assertIn(e, SummerMonth)
778 self.assertIs(type(e), SummerMonth)
779
Martin Pantereb995702016-07-28 01:11:04 +0000780 def test_programmatic_function_string_with_start(self):
Ethan Furmand9925a12014-09-16 20:35:55 -0700781 SummerMonth = Enum('SummerMonth', 'june july august', start=10)
782 lst = list(SummerMonth)
783 self.assertEqual(len(lst), len(SummerMonth))
784 self.assertEqual(len(SummerMonth), 3, SummerMonth)
785 self.assertEqual(
786 [SummerMonth.june, SummerMonth.july, SummerMonth.august],
787 lst,
788 )
789 for i, month in enumerate('june july august'.split(), 10):
790 e = SummerMonth(i)
791 self.assertEqual(int(e.value), i)
792 self.assertNotEqual(e, i)
793 self.assertEqual(e.name, month)
794 self.assertIn(e, SummerMonth)
795 self.assertIs(type(e), SummerMonth)
796
Martin Pantereb995702016-07-28 01:11:04 +0000797 def test_programmatic_function_string_list(self):
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700798 SummerMonth = Enum('SummerMonth', ['june', 'july', 'august'])
799 lst = list(SummerMonth)
800 self.assertEqual(len(lst), len(SummerMonth))
801 self.assertEqual(len(SummerMonth), 3, SummerMonth)
802 self.assertEqual(
803 [SummerMonth.june, SummerMonth.july, SummerMonth.august],
804 lst,
805 )
806 for i, month in enumerate('june july august'.split(), 1):
807 e = SummerMonth(i)
808 self.assertEqual(int(e.value), i)
809 self.assertNotEqual(e, i)
810 self.assertEqual(e.name, month)
811 self.assertIn(e, SummerMonth)
812 self.assertIs(type(e), SummerMonth)
813
Martin Pantereb995702016-07-28 01:11:04 +0000814 def test_programmatic_function_string_list_with_start(self):
Ethan Furmand9925a12014-09-16 20:35:55 -0700815 SummerMonth = Enum('SummerMonth', ['june', 'july', 'august'], start=20)
816 lst = list(SummerMonth)
817 self.assertEqual(len(lst), len(SummerMonth))
818 self.assertEqual(len(SummerMonth), 3, SummerMonth)
819 self.assertEqual(
820 [SummerMonth.june, SummerMonth.july, SummerMonth.august],
821 lst,
822 )
823 for i, month in enumerate('june july august'.split(), 20):
824 e = SummerMonth(i)
825 self.assertEqual(int(e.value), i)
826 self.assertNotEqual(e, i)
827 self.assertEqual(e.name, month)
828 self.assertIn(e, SummerMonth)
829 self.assertIs(type(e), SummerMonth)
830
Martin Pantereb995702016-07-28 01:11:04 +0000831 def test_programmatic_function_iterable(self):
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700832 SummerMonth = Enum(
833 'SummerMonth',
834 (('june', 1), ('july', 2), ('august', 3))
835 )
836 lst = list(SummerMonth)
837 self.assertEqual(len(lst), len(SummerMonth))
838 self.assertEqual(len(SummerMonth), 3, SummerMonth)
839 self.assertEqual(
840 [SummerMonth.june, SummerMonth.july, SummerMonth.august],
841 lst,
842 )
843 for i, month in enumerate('june july august'.split(), 1):
844 e = SummerMonth(i)
845 self.assertEqual(int(e.value), i)
846 self.assertNotEqual(e, i)
847 self.assertEqual(e.name, month)
848 self.assertIn(e, SummerMonth)
849 self.assertIs(type(e), SummerMonth)
850
Martin Pantereb995702016-07-28 01:11:04 +0000851 def test_programmatic_function_from_dict(self):
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700852 SummerMonth = Enum(
853 'SummerMonth',
854 OrderedDict((('june', 1), ('july', 2), ('august', 3)))
855 )
856 lst = list(SummerMonth)
857 self.assertEqual(len(lst), len(SummerMonth))
858 self.assertEqual(len(SummerMonth), 3, SummerMonth)
859 self.assertEqual(
860 [SummerMonth.june, SummerMonth.july, SummerMonth.august],
861 lst,
862 )
863 for i, month in enumerate('june july august'.split(), 1):
864 e = SummerMonth(i)
865 self.assertEqual(int(e.value), i)
866 self.assertNotEqual(e, i)
867 self.assertEqual(e.name, month)
868 self.assertIn(e, SummerMonth)
869 self.assertIs(type(e), SummerMonth)
870
Martin Pantereb995702016-07-28 01:11:04 +0000871 def test_programmatic_function_type(self):
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700872 SummerMonth = Enum('SummerMonth', 'june july august', type=int)
873 lst = list(SummerMonth)
874 self.assertEqual(len(lst), len(SummerMonth))
875 self.assertEqual(len(SummerMonth), 3, SummerMonth)
876 self.assertEqual(
877 [SummerMonth.june, SummerMonth.july, SummerMonth.august],
878 lst,
879 )
880 for i, month in enumerate('june july august'.split(), 1):
881 e = SummerMonth(i)
882 self.assertEqual(e, i)
883 self.assertEqual(e.name, month)
884 self.assertIn(e, SummerMonth)
885 self.assertIs(type(e), SummerMonth)
886
Martin Pantereb995702016-07-28 01:11:04 +0000887 def test_programmatic_function_type_with_start(self):
Ethan Furmand9925a12014-09-16 20:35:55 -0700888 SummerMonth = Enum('SummerMonth', 'june july august', type=int, start=30)
889 lst = list(SummerMonth)
890 self.assertEqual(len(lst), len(SummerMonth))
891 self.assertEqual(len(SummerMonth), 3, SummerMonth)
892 self.assertEqual(
893 [SummerMonth.june, SummerMonth.july, SummerMonth.august],
894 lst,
895 )
896 for i, month in enumerate('june july august'.split(), 30):
897 e = SummerMonth(i)
898 self.assertEqual(e, i)
899 self.assertEqual(e.name, month)
900 self.assertIn(e, SummerMonth)
901 self.assertIs(type(e), SummerMonth)
902
Martin Pantereb995702016-07-28 01:11:04 +0000903 def test_programmatic_function_type_from_subclass(self):
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700904 SummerMonth = IntEnum('SummerMonth', 'june july august')
905 lst = list(SummerMonth)
906 self.assertEqual(len(lst), len(SummerMonth))
907 self.assertEqual(len(SummerMonth), 3, SummerMonth)
908 self.assertEqual(
909 [SummerMonth.june, SummerMonth.july, SummerMonth.august],
910 lst,
911 )
912 for i, month in enumerate('june july august'.split(), 1):
913 e = SummerMonth(i)
914 self.assertEqual(e, i)
915 self.assertEqual(e.name, month)
916 self.assertIn(e, SummerMonth)
917 self.assertIs(type(e), SummerMonth)
918
Martin Pantereb995702016-07-28 01:11:04 +0000919 def test_programmatic_function_type_from_subclass_with_start(self):
Ethan Furmand9925a12014-09-16 20:35:55 -0700920 SummerMonth = IntEnum('SummerMonth', 'june july august', start=40)
921 lst = list(SummerMonth)
922 self.assertEqual(len(lst), len(SummerMonth))
923 self.assertEqual(len(SummerMonth), 3, SummerMonth)
924 self.assertEqual(
925 [SummerMonth.june, SummerMonth.july, SummerMonth.august],
926 lst,
927 )
928 for i, month in enumerate('june july august'.split(), 40):
929 e = SummerMonth(i)
930 self.assertEqual(e, i)
931 self.assertEqual(e.name, month)
932 self.assertIn(e, SummerMonth)
933 self.assertIs(type(e), SummerMonth)
934
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700935 def test_subclassing(self):
936 if isinstance(Name, Exception):
937 raise Name
938 self.assertEqual(Name.BDFL, 'Guido van Rossum')
939 self.assertTrue(Name.BDFL, Name('Guido van Rossum'))
940 self.assertIs(Name.BDFL, getattr(Name, 'BDFL'))
Ethan Furman2ddb39a2014-02-06 17:28:50 -0800941 test_pickle_dump_load(self.assertIs, Name.BDFL)
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700942
943 def test_extending(self):
944 class Color(Enum):
945 red = 1
946 green = 2
947 blue = 3
948 with self.assertRaises(TypeError):
949 class MoreColor(Color):
950 cyan = 4
951 magenta = 5
952 yellow = 6
953
954 def test_exclude_methods(self):
955 class whatever(Enum):
956 this = 'that'
957 these = 'those'
958 def really(self):
959 return 'no, not %s' % self.value
960 self.assertIsNot(type(whatever.really), whatever)
961 self.assertEqual(whatever.this.really(), 'no, not that')
962
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700963 def test_wrong_inheritance_order(self):
964 with self.assertRaises(TypeError):
965 class Wrong(Enum, str):
966 NotHere = 'error before this point'
967
968 def test_intenum_transitivity(self):
969 class number(IntEnum):
970 one = 1
971 two = 2
972 three = 3
973 class numero(IntEnum):
974 uno = 1
975 dos = 2
976 tres = 3
977 self.assertEqual(number.one, numero.uno)
978 self.assertEqual(number.two, numero.dos)
979 self.assertEqual(number.three, numero.tres)
980
981 def test_wrong_enum_in_call(self):
982 class Monochrome(Enum):
983 black = 0
984 white = 1
985 class Gender(Enum):
986 male = 0
987 female = 1
988 self.assertRaises(ValueError, Monochrome, Gender.male)
989
990 def test_wrong_enum_in_mixed_call(self):
991 class Monochrome(IntEnum):
992 black = 0
993 white = 1
994 class Gender(Enum):
995 male = 0
996 female = 1
997 self.assertRaises(ValueError, Monochrome, Gender.male)
998
999 def test_mixed_enum_in_call_1(self):
1000 class Monochrome(IntEnum):
1001 black = 0
1002 white = 1
1003 class Gender(IntEnum):
1004 male = 0
1005 female = 1
1006 self.assertIs(Monochrome(Gender.female), Monochrome.white)
1007
1008 def test_mixed_enum_in_call_2(self):
1009 class Monochrome(Enum):
1010 black = 0
1011 white = 1
1012 class Gender(IntEnum):
1013 male = 0
1014 female = 1
1015 self.assertIs(Monochrome(Gender.male), Monochrome.black)
1016
1017 def test_flufl_enum(self):
1018 class Fluflnum(Enum):
1019 def __int__(self):
1020 return int(self.value)
1021 class MailManOptions(Fluflnum):
1022 option1 = 1
1023 option2 = 2
1024 option3 = 3
1025 self.assertEqual(int(MailManOptions.option1), 1)
1026
Ethan Furman5e5a8232013-08-04 08:42:23 -07001027 def test_introspection(self):
1028 class Number(IntEnum):
1029 one = 100
1030 two = 200
1031 self.assertIs(Number.one._member_type_, int)
1032 self.assertIs(Number._member_type_, int)
1033 class String(str, Enum):
1034 yarn = 'soft'
1035 rope = 'rough'
1036 wire = 'hard'
1037 self.assertIs(String.yarn._member_type_, str)
1038 self.assertIs(String._member_type_, str)
1039 class Plain(Enum):
1040 vanilla = 'white'
1041 one = 1
1042 self.assertIs(Plain.vanilla._member_type_, object)
1043 self.assertIs(Plain._member_type_, object)
1044
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001045 def test_no_such_enum_member(self):
1046 class Color(Enum):
1047 red = 1
1048 green = 2
1049 blue = 3
1050 with self.assertRaises(ValueError):
1051 Color(4)
1052 with self.assertRaises(KeyError):
1053 Color['chartreuse']
1054
1055 def test_new_repr(self):
1056 class Color(Enum):
1057 red = 1
1058 green = 2
1059 blue = 3
1060 def __repr__(self):
1061 return "don't you just love shades of %s?" % self.name
1062 self.assertEqual(
1063 repr(Color.blue),
1064 "don't you just love shades of blue?",
1065 )
1066
1067 def test_inherited_repr(self):
1068 class MyEnum(Enum):
1069 def __repr__(self):
1070 return "My name is %s." % self.name
1071 class MyIntEnum(int, MyEnum):
1072 this = 1
1073 that = 2
1074 theother = 3
1075 self.assertEqual(repr(MyIntEnum.that), "My name is that.")
1076
1077 def test_multiple_mixin_mro(self):
1078 class auto_enum(type(Enum)):
1079 def __new__(metacls, cls, bases, classdict):
1080 temp = type(classdict)()
1081 names = set(classdict._member_names)
1082 i = 0
1083 for k in classdict._member_names:
1084 v = classdict[k]
1085 if v is Ellipsis:
1086 v = i
1087 else:
1088 i = v
1089 i += 1
1090 temp[k] = v
1091 for k, v in classdict.items():
1092 if k not in names:
1093 temp[k] = v
1094 return super(auto_enum, metacls).__new__(
1095 metacls, cls, bases, temp)
1096
1097 class AutoNumberedEnum(Enum, metaclass=auto_enum):
1098 pass
1099
1100 class AutoIntEnum(IntEnum, metaclass=auto_enum):
1101 pass
1102
1103 class TestAutoNumber(AutoNumberedEnum):
1104 a = ...
1105 b = 3
1106 c = ...
1107
1108 class TestAutoInt(AutoIntEnum):
1109 a = ...
1110 b = 3
1111 c = ...
1112
1113 def test_subclasses_with_getnewargs(self):
1114 class NamedInt(int):
Ethan Furman2ddb39a2014-02-06 17:28:50 -08001115 __qualname__ = 'NamedInt' # needed for pickle protocol 4
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001116 def __new__(cls, *args):
1117 _args = args
1118 name, *args = args
1119 if len(args) == 0:
1120 raise TypeError("name and value must be specified")
1121 self = int.__new__(cls, *args)
1122 self._intname = name
1123 self._args = _args
1124 return self
1125 def __getnewargs__(self):
1126 return self._args
1127 @property
1128 def __name__(self):
1129 return self._intname
1130 def __repr__(self):
1131 # repr() is updated to include the name and type info
1132 return "{}({!r}, {})".format(type(self).__name__,
1133 self.__name__,
1134 int.__repr__(self))
1135 def __str__(self):
1136 # str() is unchanged, even if it relies on the repr() fallback
1137 base = int
1138 base_str = base.__str__
1139 if base_str.__objclass__ is object:
1140 return base.__repr__(self)
1141 return base_str(self)
1142 # for simplicity, we only define one operator that
1143 # propagates expressions
1144 def __add__(self, other):
1145 temp = int(self) + int( other)
1146 if isinstance(self, NamedInt) and isinstance(other, NamedInt):
1147 return NamedInt(
1148 '({0} + {1})'.format(self.__name__, other.__name__),
1149 temp )
1150 else:
1151 return temp
1152
1153 class NEI(NamedInt, Enum):
Ethan Furman2ddb39a2014-02-06 17:28:50 -08001154 __qualname__ = 'NEI' # needed for pickle protocol 4
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001155 x = ('the-x', 1)
1156 y = ('the-y', 2)
1157
Ethan Furman2aa27322013-07-19 19:35:56 -07001158
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001159 self.assertIs(NEI.__new__, Enum.__new__)
1160 self.assertEqual(repr(NEI.x + NEI.y), "NamedInt('(the-x + the-y)', 3)")
1161 globals()['NamedInt'] = NamedInt
1162 globals()['NEI'] = NEI
1163 NI5 = NamedInt('test', 5)
1164 self.assertEqual(NI5, 5)
Ethan Furman2ddb39a2014-02-06 17:28:50 -08001165 test_pickle_dump_load(self.assertEqual, NI5, 5)
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001166 self.assertEqual(NEI.y.value, 2)
Ethan Furman2ddb39a2014-02-06 17:28:50 -08001167 test_pickle_dump_load(self.assertIs, NEI.y)
Ethan Furmandc870522014-02-18 12:37:12 -08001168 test_pickle_dump_load(self.assertIs, NEI)
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001169
Ethan Furmanca1b7942014-02-08 11:36:27 -08001170 def test_subclasses_with_getnewargs_ex(self):
1171 class NamedInt(int):
1172 __qualname__ = 'NamedInt' # needed for pickle protocol 4
1173 def __new__(cls, *args):
1174 _args = args
1175 name, *args = args
1176 if len(args) == 0:
1177 raise TypeError("name and value must be specified")
1178 self = int.__new__(cls, *args)
1179 self._intname = name
1180 self._args = _args
1181 return self
1182 def __getnewargs_ex__(self):
1183 return self._args, {}
1184 @property
1185 def __name__(self):
1186 return self._intname
1187 def __repr__(self):
1188 # repr() is updated to include the name and type info
1189 return "{}({!r}, {})".format(type(self).__name__,
1190 self.__name__,
1191 int.__repr__(self))
1192 def __str__(self):
1193 # str() is unchanged, even if it relies on the repr() fallback
1194 base = int
1195 base_str = base.__str__
1196 if base_str.__objclass__ is object:
1197 return base.__repr__(self)
1198 return base_str(self)
1199 # for simplicity, we only define one operator that
1200 # propagates expressions
1201 def __add__(self, other):
1202 temp = int(self) + int( other)
1203 if isinstance(self, NamedInt) and isinstance(other, NamedInt):
1204 return NamedInt(
1205 '({0} + {1})'.format(self.__name__, other.__name__),
1206 temp )
1207 else:
1208 return temp
1209
1210 class NEI(NamedInt, Enum):
1211 __qualname__ = 'NEI' # needed for pickle protocol 4
1212 x = ('the-x', 1)
1213 y = ('the-y', 2)
1214
1215
1216 self.assertIs(NEI.__new__, Enum.__new__)
1217 self.assertEqual(repr(NEI.x + NEI.y), "NamedInt('(the-x + the-y)', 3)")
1218 globals()['NamedInt'] = NamedInt
1219 globals()['NEI'] = NEI
1220 NI5 = NamedInt('test', 5)
1221 self.assertEqual(NI5, 5)
Serhiy Storchakae50e7802015-03-31 16:56:49 +03001222 test_pickle_dump_load(self.assertEqual, NI5, 5)
Ethan Furmanca1b7942014-02-08 11:36:27 -08001223 self.assertEqual(NEI.y.value, 2)
Serhiy Storchakae50e7802015-03-31 16:56:49 +03001224 test_pickle_dump_load(self.assertIs, NEI.y)
Ethan Furmandc870522014-02-18 12:37:12 -08001225 test_pickle_dump_load(self.assertIs, NEI)
Ethan Furmanca1b7942014-02-08 11:36:27 -08001226
1227 def test_subclasses_with_reduce(self):
1228 class NamedInt(int):
1229 __qualname__ = 'NamedInt' # needed for pickle protocol 4
1230 def __new__(cls, *args):
1231 _args = args
1232 name, *args = args
1233 if len(args) == 0:
1234 raise TypeError("name and value must be specified")
1235 self = int.__new__(cls, *args)
1236 self._intname = name
1237 self._args = _args
1238 return self
1239 def __reduce__(self):
1240 return self.__class__, self._args
1241 @property
1242 def __name__(self):
1243 return self._intname
1244 def __repr__(self):
1245 # repr() is updated to include the name and type info
1246 return "{}({!r}, {})".format(type(self).__name__,
1247 self.__name__,
1248 int.__repr__(self))
1249 def __str__(self):
1250 # str() is unchanged, even if it relies on the repr() fallback
1251 base = int
1252 base_str = base.__str__
1253 if base_str.__objclass__ is object:
1254 return base.__repr__(self)
1255 return base_str(self)
1256 # for simplicity, we only define one operator that
1257 # propagates expressions
1258 def __add__(self, other):
1259 temp = int(self) + int( other)
1260 if isinstance(self, NamedInt) and isinstance(other, NamedInt):
1261 return NamedInt(
1262 '({0} + {1})'.format(self.__name__, other.__name__),
1263 temp )
1264 else:
1265 return temp
1266
1267 class NEI(NamedInt, Enum):
1268 __qualname__ = 'NEI' # needed for pickle protocol 4
1269 x = ('the-x', 1)
1270 y = ('the-y', 2)
1271
1272
1273 self.assertIs(NEI.__new__, Enum.__new__)
1274 self.assertEqual(repr(NEI.x + NEI.y), "NamedInt('(the-x + the-y)', 3)")
1275 globals()['NamedInt'] = NamedInt
1276 globals()['NEI'] = NEI
1277 NI5 = NamedInt('test', 5)
1278 self.assertEqual(NI5, 5)
1279 test_pickle_dump_load(self.assertEqual, NI5, 5)
1280 self.assertEqual(NEI.y.value, 2)
1281 test_pickle_dump_load(self.assertIs, NEI.y)
Ethan Furmandc870522014-02-18 12:37:12 -08001282 test_pickle_dump_load(self.assertIs, NEI)
Ethan Furmanca1b7942014-02-08 11:36:27 -08001283
1284 def test_subclasses_with_reduce_ex(self):
1285 class NamedInt(int):
1286 __qualname__ = 'NamedInt' # needed for pickle protocol 4
1287 def __new__(cls, *args):
1288 _args = args
1289 name, *args = args
1290 if len(args) == 0:
1291 raise TypeError("name and value must be specified")
1292 self = int.__new__(cls, *args)
1293 self._intname = name
1294 self._args = _args
1295 return self
1296 def __reduce_ex__(self, proto):
1297 return self.__class__, self._args
1298 @property
1299 def __name__(self):
1300 return self._intname
1301 def __repr__(self):
1302 # repr() is updated to include the name and type info
1303 return "{}({!r}, {})".format(type(self).__name__,
1304 self.__name__,
1305 int.__repr__(self))
1306 def __str__(self):
1307 # str() is unchanged, even if it relies on the repr() fallback
1308 base = int
1309 base_str = base.__str__
1310 if base_str.__objclass__ is object:
1311 return base.__repr__(self)
1312 return base_str(self)
1313 # for simplicity, we only define one operator that
1314 # propagates expressions
1315 def __add__(self, other):
1316 temp = int(self) + int( other)
1317 if isinstance(self, NamedInt) and isinstance(other, NamedInt):
1318 return NamedInt(
1319 '({0} + {1})'.format(self.__name__, other.__name__),
1320 temp )
1321 else:
1322 return temp
1323
1324 class NEI(NamedInt, Enum):
1325 __qualname__ = 'NEI' # needed for pickle protocol 4
1326 x = ('the-x', 1)
1327 y = ('the-y', 2)
1328
1329
1330 self.assertIs(NEI.__new__, Enum.__new__)
1331 self.assertEqual(repr(NEI.x + NEI.y), "NamedInt('(the-x + the-y)', 3)")
1332 globals()['NamedInt'] = NamedInt
1333 globals()['NEI'] = NEI
1334 NI5 = NamedInt('test', 5)
1335 self.assertEqual(NI5, 5)
1336 test_pickle_dump_load(self.assertEqual, NI5, 5)
1337 self.assertEqual(NEI.y.value, 2)
1338 test_pickle_dump_load(self.assertIs, NEI.y)
Ethan Furmandc870522014-02-18 12:37:12 -08001339 test_pickle_dump_load(self.assertIs, NEI)
Ethan Furmanca1b7942014-02-08 11:36:27 -08001340
Ethan Furmandc870522014-02-18 12:37:12 -08001341 def test_subclasses_without_direct_pickle_support(self):
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001342 class NamedInt(int):
Ethan Furman2ddb39a2014-02-06 17:28:50 -08001343 __qualname__ = 'NamedInt'
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001344 def __new__(cls, *args):
1345 _args = args
1346 name, *args = args
1347 if len(args) == 0:
1348 raise TypeError("name and value must be specified")
1349 self = int.__new__(cls, *args)
1350 self._intname = name
1351 self._args = _args
1352 return self
1353 @property
1354 def __name__(self):
1355 return self._intname
1356 def __repr__(self):
1357 # repr() is updated to include the name and type info
1358 return "{}({!r}, {})".format(type(self).__name__,
1359 self.__name__,
1360 int.__repr__(self))
1361 def __str__(self):
1362 # str() is unchanged, even if it relies on the repr() fallback
1363 base = int
1364 base_str = base.__str__
1365 if base_str.__objclass__ is object:
1366 return base.__repr__(self)
1367 return base_str(self)
1368 # for simplicity, we only define one operator that
1369 # propagates expressions
1370 def __add__(self, other):
1371 temp = int(self) + int( other)
1372 if isinstance(self, NamedInt) and isinstance(other, NamedInt):
1373 return NamedInt(
1374 '({0} + {1})'.format(self.__name__, other.__name__),
1375 temp )
1376 else:
1377 return temp
1378
1379 class NEI(NamedInt, Enum):
Ethan Furman2ddb39a2014-02-06 17:28:50 -08001380 __qualname__ = 'NEI'
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001381 x = ('the-x', 1)
1382 y = ('the-y', 2)
1383
1384 self.assertIs(NEI.__new__, Enum.__new__)
1385 self.assertEqual(repr(NEI.x + NEI.y), "NamedInt('(the-x + the-y)', 3)")
1386 globals()['NamedInt'] = NamedInt
1387 globals()['NEI'] = NEI
1388 NI5 = NamedInt('test', 5)
1389 self.assertEqual(NI5, 5)
1390 self.assertEqual(NEI.y.value, 2)
Ethan Furman2ddb39a2014-02-06 17:28:50 -08001391 test_pickle_exception(self.assertRaises, TypeError, NEI.x)
1392 test_pickle_exception(self.assertRaises, PicklingError, NEI)
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001393
Ethan Furmandc870522014-02-18 12:37:12 -08001394 def test_subclasses_without_direct_pickle_support_using_name(self):
1395 class NamedInt(int):
1396 __qualname__ = 'NamedInt'
1397 def __new__(cls, *args):
1398 _args = args
1399 name, *args = args
1400 if len(args) == 0:
1401 raise TypeError("name and value must be specified")
1402 self = int.__new__(cls, *args)
1403 self._intname = name
1404 self._args = _args
1405 return self
1406 @property
1407 def __name__(self):
1408 return self._intname
1409 def __repr__(self):
1410 # repr() is updated to include the name and type info
1411 return "{}({!r}, {})".format(type(self).__name__,
1412 self.__name__,
1413 int.__repr__(self))
1414 def __str__(self):
1415 # str() is unchanged, even if it relies on the repr() fallback
1416 base = int
1417 base_str = base.__str__
1418 if base_str.__objclass__ is object:
1419 return base.__repr__(self)
1420 return base_str(self)
1421 # for simplicity, we only define one operator that
1422 # propagates expressions
1423 def __add__(self, other):
1424 temp = int(self) + int( other)
1425 if isinstance(self, NamedInt) and isinstance(other, NamedInt):
1426 return NamedInt(
1427 '({0} + {1})'.format(self.__name__, other.__name__),
1428 temp )
1429 else:
1430 return temp
1431
1432 class NEI(NamedInt, Enum):
1433 __qualname__ = 'NEI'
1434 x = ('the-x', 1)
1435 y = ('the-y', 2)
1436 def __reduce_ex__(self, proto):
1437 return getattr, (self.__class__, self._name_)
1438
1439 self.assertIs(NEI.__new__, Enum.__new__)
1440 self.assertEqual(repr(NEI.x + NEI.y), "NamedInt('(the-x + the-y)', 3)")
1441 globals()['NamedInt'] = NamedInt
1442 globals()['NEI'] = NEI
1443 NI5 = NamedInt('test', 5)
1444 self.assertEqual(NI5, 5)
1445 self.assertEqual(NEI.y.value, 2)
1446 test_pickle_dump_load(self.assertIs, NEI.y)
1447 test_pickle_dump_load(self.assertIs, NEI)
1448
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001449 def test_tuple_subclass(self):
1450 class SomeTuple(tuple, Enum):
Ethan Furman2ddb39a2014-02-06 17:28:50 -08001451 __qualname__ = 'SomeTuple' # needed for pickle protocol 4
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001452 first = (1, 'for the money')
1453 second = (2, 'for the show')
1454 third = (3, 'for the music')
1455 self.assertIs(type(SomeTuple.first), SomeTuple)
1456 self.assertIsInstance(SomeTuple.second, tuple)
1457 self.assertEqual(SomeTuple.third, (3, 'for the music'))
1458 globals()['SomeTuple'] = SomeTuple
Ethan Furman2ddb39a2014-02-06 17:28:50 -08001459 test_pickle_dump_load(self.assertIs, SomeTuple.first)
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001460
1461 def test_duplicate_values_give_unique_enum_items(self):
1462 class AutoNumber(Enum):
1463 first = ()
1464 second = ()
1465 third = ()
1466 def __new__(cls):
1467 value = len(cls.__members__) + 1
1468 obj = object.__new__(cls)
Ethan Furman520ad572013-07-19 19:47:21 -07001469 obj._value_ = value
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001470 return obj
1471 def __int__(self):
Ethan Furman520ad572013-07-19 19:47:21 -07001472 return int(self._value_)
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001473 self.assertEqual(
1474 list(AutoNumber),
1475 [AutoNumber.first, AutoNumber.second, AutoNumber.third],
1476 )
1477 self.assertEqual(int(AutoNumber.second), 2)
Ethan Furman2aa27322013-07-19 19:35:56 -07001478 self.assertEqual(AutoNumber.third.value, 3)
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001479 self.assertIs(AutoNumber(1), AutoNumber.first)
1480
1481 def test_inherited_new_from_enhanced_enum(self):
1482 class AutoNumber(Enum):
1483 def __new__(cls):
1484 value = len(cls.__members__) + 1
1485 obj = object.__new__(cls)
Ethan Furman520ad572013-07-19 19:47:21 -07001486 obj._value_ = value
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001487 return obj
1488 def __int__(self):
Ethan Furman520ad572013-07-19 19:47:21 -07001489 return int(self._value_)
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001490 class Color(AutoNumber):
1491 red = ()
1492 green = ()
1493 blue = ()
1494 self.assertEqual(list(Color), [Color.red, Color.green, Color.blue])
1495 self.assertEqual(list(map(int, Color)), [1, 2, 3])
1496
1497 def test_inherited_new_from_mixed_enum(self):
1498 class AutoNumber(IntEnum):
1499 def __new__(cls):
1500 value = len(cls.__members__) + 1
1501 obj = int.__new__(cls, value)
Ethan Furman520ad572013-07-19 19:47:21 -07001502 obj._value_ = value
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001503 return obj
1504 class Color(AutoNumber):
1505 red = ()
1506 green = ()
1507 blue = ()
1508 self.assertEqual(list(Color), [Color.red, Color.green, Color.blue])
1509 self.assertEqual(list(map(int, Color)), [1, 2, 3])
1510
Ethan Furmanbe3c2fe2013-11-13 14:25:45 -08001511 def test_equality(self):
1512 class AlwaysEqual:
1513 def __eq__(self, other):
1514 return True
1515 class OrdinaryEnum(Enum):
1516 a = 1
1517 self.assertEqual(AlwaysEqual(), OrdinaryEnum.a)
1518 self.assertEqual(OrdinaryEnum.a, AlwaysEqual())
1519
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001520 def test_ordered_mixin(self):
1521 class OrderedEnum(Enum):
1522 def __ge__(self, other):
1523 if self.__class__ is other.__class__:
Ethan Furman520ad572013-07-19 19:47:21 -07001524 return self._value_ >= other._value_
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001525 return NotImplemented
1526 def __gt__(self, other):
1527 if self.__class__ is other.__class__:
Ethan Furman520ad572013-07-19 19:47:21 -07001528 return self._value_ > other._value_
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001529 return NotImplemented
1530 def __le__(self, other):
1531 if self.__class__ is other.__class__:
Ethan Furman520ad572013-07-19 19:47:21 -07001532 return self._value_ <= other._value_
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001533 return NotImplemented
1534 def __lt__(self, other):
1535 if self.__class__ is other.__class__:
Ethan Furman520ad572013-07-19 19:47:21 -07001536 return self._value_ < other._value_
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001537 return NotImplemented
1538 class Grade(OrderedEnum):
1539 A = 5
1540 B = 4
1541 C = 3
1542 D = 2
1543 F = 1
1544 self.assertGreater(Grade.A, Grade.B)
1545 self.assertLessEqual(Grade.F, Grade.C)
1546 self.assertLess(Grade.D, Grade.A)
1547 self.assertGreaterEqual(Grade.B, Grade.B)
Ethan Furmanbe3c2fe2013-11-13 14:25:45 -08001548 self.assertEqual(Grade.B, Grade.B)
1549 self.assertNotEqual(Grade.C, Grade.D)
Ethan Furman520ad572013-07-19 19:47:21 -07001550
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001551 def test_extending2(self):
1552 class Shade(Enum):
1553 def shade(self):
1554 print(self.name)
1555 class Color(Shade):
1556 red = 1
1557 green = 2
1558 blue = 3
1559 with self.assertRaises(TypeError):
1560 class MoreColor(Color):
1561 cyan = 4
1562 magenta = 5
1563 yellow = 6
1564
1565 def test_extending3(self):
1566 class Shade(Enum):
1567 def shade(self):
1568 return self.name
1569 class Color(Shade):
1570 def hex(self):
1571 return '%s hexlified!' % self.value
1572 class MoreColor(Color):
1573 cyan = 4
1574 magenta = 5
1575 yellow = 6
1576 self.assertEqual(MoreColor.magenta.hex(), '5 hexlified!')
1577
orlnub1230fb9fad2018-09-12 20:28:53 +03001578 def test_subclass_duplicate_name(self):
1579 class Base(Enum):
1580 def test(self):
1581 pass
1582 class Test(Base):
1583 test = 1
1584 self.assertIs(type(Test.test), Test)
1585
1586 def test_subclass_duplicate_name_dynamic(self):
1587 from types import DynamicClassAttribute
1588 class Base(Enum):
1589 @DynamicClassAttribute
1590 def test(self):
1591 return 'dynamic'
1592 class Test(Base):
1593 test = 1
1594 self.assertEqual(Test.test.test, 'dynamic')
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001595
1596 def test_no_duplicates(self):
1597 class UniqueEnum(Enum):
1598 def __init__(self, *args):
1599 cls = self.__class__
1600 if any(self.value == e.value for e in cls):
1601 a = self.name
1602 e = cls(self.value).name
1603 raise ValueError(
1604 "aliases not allowed in UniqueEnum: %r --> %r"
1605 % (a, e)
1606 )
1607 class Color(UniqueEnum):
1608 red = 1
1609 green = 2
1610 blue = 3
1611 with self.assertRaises(ValueError):
1612 class Color(UniqueEnum):
1613 red = 1
1614 green = 2
1615 blue = 3
1616 grene = 2
1617
1618 def test_init(self):
1619 class Planet(Enum):
1620 MERCURY = (3.303e+23, 2.4397e6)
1621 VENUS = (4.869e+24, 6.0518e6)
1622 EARTH = (5.976e+24, 6.37814e6)
1623 MARS = (6.421e+23, 3.3972e6)
1624 JUPITER = (1.9e+27, 7.1492e7)
1625 SATURN = (5.688e+26, 6.0268e7)
1626 URANUS = (8.686e+25, 2.5559e7)
1627 NEPTUNE = (1.024e+26, 2.4746e7)
1628 def __init__(self, mass, radius):
1629 self.mass = mass # in kilograms
1630 self.radius = radius # in meters
1631 @property
1632 def surface_gravity(self):
1633 # universal gravitational constant (m3 kg-1 s-2)
1634 G = 6.67300E-11
1635 return G * self.mass / (self.radius * self.radius)
1636 self.assertEqual(round(Planet.EARTH.surface_gravity, 2), 9.80)
1637 self.assertEqual(Planet.EARTH.value, (5.976e+24, 6.37814e6))
1638
Ethan Furmana4b1bb42018-01-22 07:56:37 -08001639 def test_ignore(self):
1640 class Period(timedelta, Enum):
1641 '''
1642 different lengths of time
1643 '''
1644 def __new__(cls, value, period):
1645 obj = timedelta.__new__(cls, value)
1646 obj._value_ = value
1647 obj.period = period
1648 return obj
1649 _ignore_ = 'Period i'
1650 Period = vars()
1651 for i in range(13):
1652 Period['month_%d' % i] = i*30, 'month'
1653 for i in range(53):
1654 Period['week_%d' % i] = i*7, 'week'
1655 for i in range(32):
1656 Period['day_%d' % i] = i, 'day'
1657 OneDay = day_1
1658 OneWeek = week_1
1659 OneMonth = month_1
1660 self.assertFalse(hasattr(Period, '_ignore_'))
1661 self.assertFalse(hasattr(Period, 'Period'))
1662 self.assertFalse(hasattr(Period, 'i'))
1663 self.assertTrue(isinstance(Period.day_1, timedelta))
1664 self.assertTrue(Period.month_1 is Period.day_30)
1665 self.assertTrue(Period.week_4 is Period.day_28)
1666
Ethan Furman2aa27322013-07-19 19:35:56 -07001667 def test_nonhash_value(self):
1668 class AutoNumberInAList(Enum):
1669 def __new__(cls):
1670 value = [len(cls.__members__) + 1]
1671 obj = object.__new__(cls)
Ethan Furman520ad572013-07-19 19:47:21 -07001672 obj._value_ = value
Ethan Furman2aa27322013-07-19 19:35:56 -07001673 return obj
1674 class ColorInAList(AutoNumberInAList):
1675 red = ()
1676 green = ()
1677 blue = ()
1678 self.assertEqual(list(ColorInAList), [ColorInAList.red, ColorInAList.green, ColorInAList.blue])
Ethan Furman1a162882013-10-16 19:09:31 -07001679 for enum, value in zip(ColorInAList, range(3)):
1680 value += 1
1681 self.assertEqual(enum.value, [value])
1682 self.assertIs(ColorInAList([value]), enum)
Ethan Furman2aa27322013-07-19 19:35:56 -07001683
Ethan Furmanb41803e2013-07-25 13:50:45 -07001684 def test_conflicting_types_resolved_in_new(self):
1685 class LabelledIntEnum(int, Enum):
1686 def __new__(cls, *args):
1687 value, label = args
1688 obj = int.__new__(cls, value)
1689 obj.label = label
1690 obj._value_ = value
1691 return obj
1692
1693 class LabelledList(LabelledIntEnum):
1694 unprocessed = (1, "Unprocessed")
1695 payment_complete = (2, "Payment Complete")
1696
1697 self.assertEqual(list(LabelledList), [LabelledList.unprocessed, LabelledList.payment_complete])
1698 self.assertEqual(LabelledList.unprocessed, 1)
1699 self.assertEqual(LabelledList(1), LabelledList.unprocessed)
Ethan Furman2aa27322013-07-19 19:35:56 -07001700
Ethan Furmanc16595e2016-09-10 23:36:59 -07001701 def test_auto_number(self):
1702 class Color(Enum):
1703 red = auto()
1704 blue = auto()
1705 green = auto()
1706
1707 self.assertEqual(list(Color), [Color.red, Color.blue, Color.green])
1708 self.assertEqual(Color.red.value, 1)
1709 self.assertEqual(Color.blue.value, 2)
1710 self.assertEqual(Color.green.value, 3)
1711
1712 def test_auto_name(self):
1713 class Color(Enum):
1714 def _generate_next_value_(name, start, count, last):
1715 return name
1716 red = auto()
1717 blue = auto()
1718 green = auto()
1719
1720 self.assertEqual(list(Color), [Color.red, Color.blue, Color.green])
1721 self.assertEqual(Color.red.value, 'red')
1722 self.assertEqual(Color.blue.value, 'blue')
1723 self.assertEqual(Color.green.value, 'green')
1724
1725 def test_auto_name_inherit(self):
1726 class AutoNameEnum(Enum):
1727 def _generate_next_value_(name, start, count, last):
1728 return name
1729 class Color(AutoNameEnum):
1730 red = auto()
1731 blue = auto()
1732 green = auto()
1733
1734 self.assertEqual(list(Color), [Color.red, Color.blue, Color.green])
1735 self.assertEqual(Color.red.value, 'red')
1736 self.assertEqual(Color.blue.value, 'blue')
1737 self.assertEqual(Color.green.value, 'green')
1738
1739 def test_auto_garbage(self):
1740 class Color(Enum):
1741 red = 'red'
1742 blue = auto()
1743 self.assertEqual(Color.blue.value, 1)
1744
1745 def test_auto_garbage_corrected(self):
1746 class Color(Enum):
1747 red = 'red'
1748 blue = 2
1749 green = auto()
1750
1751 self.assertEqual(list(Color), [Color.red, Color.blue, Color.green])
1752 self.assertEqual(Color.red.value, 'red')
1753 self.assertEqual(Color.blue.value, 2)
1754 self.assertEqual(Color.green.value, 3)
1755
Ethan Furman3515dcc2016-09-18 13:15:41 -07001756 def test_duplicate_auto(self):
1757 class Dupes(Enum):
1758 first = primero = auto()
1759 second = auto()
1760 third = auto()
1761 self.assertEqual([Dupes.first, Dupes.second, Dupes.third], list(Dupes))
1762
Ethan Furman019f0a02018-09-12 11:43:34 -07001763 def test_missing(self):
1764 class Color(Enum):
1765 red = 1
1766 green = 2
1767 blue = 3
1768 @classmethod
1769 def _missing_(cls, item):
1770 if item == 'three':
1771 return cls.blue
1772 elif item == 'bad return':
1773 # trigger internal error
1774 return 5
1775 elif item == 'error out':
1776 raise ZeroDivisionError
1777 else:
1778 # trigger not found
1779 return None
1780 self.assertIs(Color('three'), Color.blue)
1781 self.assertRaises(ValueError, Color, 7)
1782 try:
1783 Color('bad return')
1784 except TypeError as exc:
1785 self.assertTrue(isinstance(exc.__context__, ValueError))
1786 else:
1787 raise Exception('Exception not raised.')
1788 try:
1789 Color('error out')
1790 except ZeroDivisionError as exc:
1791 self.assertTrue(isinstance(exc.__context__, ValueError))
1792 else:
1793 raise Exception('Exception not raised.')
1794
Ethan Furman5bdab642018-09-21 19:03:09 -07001795 def test_multiple_mixin(self):
1796 class MaxMixin:
1797 @classproperty
1798 def MAX(cls):
1799 max = len(cls)
1800 cls.MAX = max
1801 return max
1802 class StrMixin:
1803 def __str__(self):
1804 return self._name_.lower()
1805 class SomeEnum(Enum):
1806 def behavior(self):
1807 return 'booyah'
1808 class AnotherEnum(Enum):
1809 def behavior(self):
1810 return 'nuhuh!'
1811 def social(self):
1812 return "what's up?"
1813 class Color(MaxMixin, Enum):
1814 RED = auto()
1815 GREEN = auto()
1816 BLUE = auto()
1817 self.assertEqual(Color.RED.value, 1)
1818 self.assertEqual(Color.GREEN.value, 2)
1819 self.assertEqual(Color.BLUE.value, 3)
1820 self.assertEqual(Color.MAX, 3)
1821 self.assertEqual(str(Color.BLUE), 'Color.BLUE')
1822 class Color(MaxMixin, StrMixin, Enum):
1823 RED = auto()
1824 GREEN = auto()
1825 BLUE = auto()
1826 self.assertEqual(Color.RED.value, 1)
1827 self.assertEqual(Color.GREEN.value, 2)
1828 self.assertEqual(Color.BLUE.value, 3)
1829 self.assertEqual(Color.MAX, 3)
1830 self.assertEqual(str(Color.BLUE), 'blue')
1831 class Color(StrMixin, MaxMixin, Enum):
1832 RED = auto()
1833 GREEN = auto()
1834 BLUE = auto()
1835 self.assertEqual(Color.RED.value, 1)
1836 self.assertEqual(Color.GREEN.value, 2)
1837 self.assertEqual(Color.BLUE.value, 3)
1838 self.assertEqual(Color.MAX, 3)
1839 self.assertEqual(str(Color.BLUE), 'blue')
1840 class CoolColor(StrMixin, SomeEnum, Enum):
1841 RED = auto()
1842 GREEN = auto()
1843 BLUE = auto()
1844 self.assertEqual(CoolColor.RED.value, 1)
1845 self.assertEqual(CoolColor.GREEN.value, 2)
1846 self.assertEqual(CoolColor.BLUE.value, 3)
1847 self.assertEqual(str(CoolColor.BLUE), 'blue')
1848 self.assertEqual(CoolColor.RED.behavior(), 'booyah')
1849 class CoolerColor(StrMixin, AnotherEnum, Enum):
1850 RED = auto()
1851 GREEN = auto()
1852 BLUE = auto()
1853 self.assertEqual(CoolerColor.RED.value, 1)
1854 self.assertEqual(CoolerColor.GREEN.value, 2)
1855 self.assertEqual(CoolerColor.BLUE.value, 3)
1856 self.assertEqual(str(CoolerColor.BLUE), 'blue')
1857 self.assertEqual(CoolerColor.RED.behavior(), 'nuhuh!')
1858 self.assertEqual(CoolerColor.RED.social(), "what's up?")
1859 class CoolestColor(StrMixin, SomeEnum, AnotherEnum):
1860 RED = auto()
1861 GREEN = auto()
1862 BLUE = auto()
1863 self.assertEqual(CoolestColor.RED.value, 1)
1864 self.assertEqual(CoolestColor.GREEN.value, 2)
1865 self.assertEqual(CoolestColor.BLUE.value, 3)
1866 self.assertEqual(str(CoolestColor.BLUE), 'blue')
1867 self.assertEqual(CoolestColor.RED.behavior(), 'booyah')
1868 self.assertEqual(CoolestColor.RED.social(), "what's up?")
1869 class ConfusedColor(StrMixin, AnotherEnum, SomeEnum):
1870 RED = auto()
1871 GREEN = auto()
1872 BLUE = auto()
1873 self.assertEqual(ConfusedColor.RED.value, 1)
1874 self.assertEqual(ConfusedColor.GREEN.value, 2)
1875 self.assertEqual(ConfusedColor.BLUE.value, 3)
1876 self.assertEqual(str(ConfusedColor.BLUE), 'blue')
1877 self.assertEqual(ConfusedColor.RED.behavior(), 'nuhuh!')
1878 self.assertEqual(ConfusedColor.RED.social(), "what's up?")
1879 class ReformedColor(StrMixin, IntEnum, SomeEnum, AnotherEnum):
1880 RED = auto()
1881 GREEN = auto()
1882 BLUE = auto()
1883 self.assertEqual(ReformedColor.RED.value, 1)
1884 self.assertEqual(ReformedColor.GREEN.value, 2)
1885 self.assertEqual(ReformedColor.BLUE.value, 3)
1886 self.assertEqual(str(ReformedColor.BLUE), 'blue')
1887 self.assertEqual(ReformedColor.RED.behavior(), 'booyah')
1888 self.assertEqual(ConfusedColor.RED.social(), "what's up?")
1889 self.assertTrue(issubclass(ReformedColor, int))
1890
Ethan Furmancd453852018-10-05 23:29:36 -07001891 def test_multiple_inherited_mixin(self):
1892 class StrEnum(str, Enum):
1893 def __new__(cls, *args, **kwargs):
1894 for a in args:
1895 if not isinstance(a, str):
1896 raise TypeError("Enumeration '%s' (%s) is not"
1897 " a string" % (a, type(a).__name__))
1898 return str.__new__(cls, *args, **kwargs)
1899 @unique
1900 class Decision1(StrEnum):
1901 REVERT = "REVERT"
1902 REVERT_ALL = "REVERT_ALL"
1903 RETRY = "RETRY"
1904 class MyEnum(StrEnum):
1905 pass
1906 @unique
1907 class Decision2(MyEnum):
1908 REVERT = "REVERT"
1909 REVERT_ALL = "REVERT_ALL"
1910 RETRY = "RETRY"
1911
Rémi Lapeyre1fd06f12019-01-24 20:43:13 +01001912 def test_empty_globals(self):
1913 # bpo-35717: sys._getframe(2).f_globals['__name__'] fails with KeyError
1914 # when using compile and exec because f_globals is empty
1915 code = "from enum import Enum; Enum('Animal', 'ANT BEE CAT DOG')"
1916 code = compile(code, "<string>", "exec")
1917 global_ns = {}
1918 local_ls = {}
1919 exec(code, global_ns, local_ls)
1920
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001921
Ethan Furmane8e61272016-08-20 07:19:31 -07001922class TestOrder(unittest.TestCase):
1923
1924 def test_same_members(self):
1925 class Color(Enum):
1926 _order_ = 'red green blue'
1927 red = 1
1928 green = 2
1929 blue = 3
1930
1931 def test_same_members_with_aliases(self):
1932 class Color(Enum):
1933 _order_ = 'red green blue'
1934 red = 1
1935 green = 2
1936 blue = 3
1937 verde = green
1938
1939 def test_same_members_wrong_order(self):
1940 with self.assertRaisesRegex(TypeError, 'member order does not match _order_'):
1941 class Color(Enum):
1942 _order_ = 'red green blue'
1943 red = 1
1944 blue = 3
1945 green = 2
1946
1947 def test_order_has_extra_members(self):
1948 with self.assertRaisesRegex(TypeError, 'member order does not match _order_'):
1949 class Color(Enum):
1950 _order_ = 'red green blue purple'
1951 red = 1
1952 green = 2
1953 blue = 3
1954
1955 def test_order_has_extra_members_with_aliases(self):
1956 with self.assertRaisesRegex(TypeError, 'member order does not match _order_'):
1957 class Color(Enum):
1958 _order_ = 'red green blue purple'
1959 red = 1
1960 green = 2
1961 blue = 3
1962 verde = green
1963
1964 def test_enum_has_extra_members(self):
1965 with self.assertRaisesRegex(TypeError, 'member order does not match _order_'):
1966 class Color(Enum):
1967 _order_ = 'red green blue'
1968 red = 1
1969 green = 2
1970 blue = 3
1971 purple = 4
1972
1973 def test_enum_has_extra_members_with_aliases(self):
1974 with self.assertRaisesRegex(TypeError, 'member order does not match _order_'):
1975 class Color(Enum):
1976 _order_ = 'red green blue'
1977 red = 1
1978 green = 2
1979 blue = 3
1980 purple = 4
1981 verde = green
1982
1983
Ethan Furman65a5a472016-09-01 23:55:19 -07001984class TestFlag(unittest.TestCase):
Ethan Furmanee47e5c2016-08-31 00:12:15 -07001985 """Tests of the Flags."""
1986
Ethan Furman65a5a472016-09-01 23:55:19 -07001987 class Perm(Flag):
Ethan Furmanee47e5c2016-08-31 00:12:15 -07001988 R, W, X = 4, 2, 1
1989
Ethan Furman65a5a472016-09-01 23:55:19 -07001990 class Open(Flag):
Ethan Furmanee47e5c2016-08-31 00:12:15 -07001991 RO = 0
1992 WO = 1
1993 RW = 2
1994 AC = 3
1995 CE = 1<<19
1996
Rahul Jha94306522018-09-10 23:51:04 +05301997 class Color(Flag):
1998 BLACK = 0
1999 RED = 1
2000 GREEN = 2
2001 BLUE = 4
2002 PURPLE = RED|BLUE
2003
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002004 def test_str(self):
2005 Perm = self.Perm
2006 self.assertEqual(str(Perm.R), 'Perm.R')
2007 self.assertEqual(str(Perm.W), 'Perm.W')
2008 self.assertEqual(str(Perm.X), 'Perm.X')
2009 self.assertEqual(str(Perm.R | Perm.W), 'Perm.R|W')
2010 self.assertEqual(str(Perm.R | Perm.W | Perm.X), 'Perm.R|W|X')
2011 self.assertEqual(str(Perm(0)), 'Perm.0')
2012 self.assertEqual(str(~Perm.R), 'Perm.W|X')
2013 self.assertEqual(str(~Perm.W), 'Perm.R|X')
2014 self.assertEqual(str(~Perm.X), 'Perm.R|W')
2015 self.assertEqual(str(~(Perm.R | Perm.W)), 'Perm.X')
2016 self.assertEqual(str(~(Perm.R | Perm.W | Perm.X)), 'Perm.0')
2017 self.assertEqual(str(Perm(~0)), 'Perm.R|W|X')
2018
2019 Open = self.Open
2020 self.assertEqual(str(Open.RO), 'Open.RO')
2021 self.assertEqual(str(Open.WO), 'Open.WO')
2022 self.assertEqual(str(Open.AC), 'Open.AC')
2023 self.assertEqual(str(Open.RO | Open.CE), 'Open.CE')
2024 self.assertEqual(str(Open.WO | Open.CE), 'Open.CE|WO')
Ethan Furman3515dcc2016-09-18 13:15:41 -07002025 self.assertEqual(str(~Open.RO), 'Open.CE|AC|RW|WO')
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002026 self.assertEqual(str(~Open.WO), 'Open.CE|RW')
2027 self.assertEqual(str(~Open.AC), 'Open.CE')
2028 self.assertEqual(str(~(Open.RO | Open.CE)), 'Open.AC')
2029 self.assertEqual(str(~(Open.WO | Open.CE)), 'Open.RW')
2030
2031 def test_repr(self):
2032 Perm = self.Perm
2033 self.assertEqual(repr(Perm.R), '<Perm.R: 4>')
2034 self.assertEqual(repr(Perm.W), '<Perm.W: 2>')
2035 self.assertEqual(repr(Perm.X), '<Perm.X: 1>')
2036 self.assertEqual(repr(Perm.R | Perm.W), '<Perm.R|W: 6>')
2037 self.assertEqual(repr(Perm.R | Perm.W | Perm.X), '<Perm.R|W|X: 7>')
Ethan Furman27682d22016-09-04 11:39:01 -07002038 self.assertEqual(repr(Perm(0)), '<Perm.0: 0>')
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002039 self.assertEqual(repr(~Perm.R), '<Perm.W|X: 3>')
2040 self.assertEqual(repr(~Perm.W), '<Perm.R|X: 5>')
2041 self.assertEqual(repr(~Perm.X), '<Perm.R|W: 6>')
2042 self.assertEqual(repr(~(Perm.R | Perm.W)), '<Perm.X: 1>')
Ethan Furman27682d22016-09-04 11:39:01 -07002043 self.assertEqual(repr(~(Perm.R | Perm.W | Perm.X)), '<Perm.0: 0>')
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002044 self.assertEqual(repr(Perm(~0)), '<Perm.R|W|X: 7>')
2045
2046 Open = self.Open
2047 self.assertEqual(repr(Open.RO), '<Open.RO: 0>')
2048 self.assertEqual(repr(Open.WO), '<Open.WO: 1>')
2049 self.assertEqual(repr(Open.AC), '<Open.AC: 3>')
2050 self.assertEqual(repr(Open.RO | Open.CE), '<Open.CE: 524288>')
2051 self.assertEqual(repr(Open.WO | Open.CE), '<Open.CE|WO: 524289>')
Ethan Furman3515dcc2016-09-18 13:15:41 -07002052 self.assertEqual(repr(~Open.RO), '<Open.CE|AC|RW|WO: 524291>')
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002053 self.assertEqual(repr(~Open.WO), '<Open.CE|RW: 524290>')
2054 self.assertEqual(repr(~Open.AC), '<Open.CE: 524288>')
2055 self.assertEqual(repr(~(Open.RO | Open.CE)), '<Open.AC: 3>')
2056 self.assertEqual(repr(~(Open.WO | Open.CE)), '<Open.RW: 2>')
2057
2058 def test_or(self):
2059 Perm = self.Perm
2060 for i in Perm:
2061 for j in Perm:
2062 self.assertEqual((i | j), Perm(i.value | j.value))
2063 self.assertEqual((i | j).value, i.value | j.value)
2064 self.assertIs(type(i | j), Perm)
2065 for i in Perm:
2066 self.assertIs(i | i, i)
2067 Open = self.Open
2068 self.assertIs(Open.RO | Open.CE, Open.CE)
2069
2070 def test_and(self):
2071 Perm = self.Perm
2072 RW = Perm.R | Perm.W
2073 RX = Perm.R | Perm.X
2074 WX = Perm.W | Perm.X
2075 RWX = Perm.R | Perm.W | Perm.X
2076 values = list(Perm) + [RW, RX, WX, RWX, Perm(0)]
2077 for i in values:
2078 for j in values:
2079 self.assertEqual((i & j).value, i.value & j.value)
2080 self.assertIs(type(i & j), Perm)
2081 for i in Perm:
2082 self.assertIs(i & i, i)
2083 self.assertIs(i & RWX, i)
2084 self.assertIs(RWX & i, i)
2085 Open = self.Open
2086 self.assertIs(Open.RO & Open.CE, Open.RO)
2087
2088 def test_xor(self):
2089 Perm = self.Perm
2090 for i in Perm:
2091 for j in Perm:
2092 self.assertEqual((i ^ j).value, i.value ^ j.value)
2093 self.assertIs(type(i ^ j), Perm)
2094 for i in Perm:
2095 self.assertIs(i ^ Perm(0), i)
2096 self.assertIs(Perm(0) ^ i, i)
2097 Open = self.Open
2098 self.assertIs(Open.RO ^ Open.CE, Open.CE)
2099 self.assertIs(Open.CE ^ Open.CE, Open.RO)
2100
2101 def test_invert(self):
2102 Perm = self.Perm
2103 RW = Perm.R | Perm.W
2104 RX = Perm.R | Perm.X
2105 WX = Perm.W | Perm.X
2106 RWX = Perm.R | Perm.W | Perm.X
2107 values = list(Perm) + [RW, RX, WX, RWX, Perm(0)]
2108 for i in values:
2109 self.assertIs(type(~i), Perm)
2110 self.assertEqual(~~i, i)
2111 for i in Perm:
2112 self.assertIs(~~i, i)
2113 Open = self.Open
2114 self.assertIs(Open.WO & ~Open.WO, Open.RO)
2115 self.assertIs((Open.WO|Open.CE) & ~Open.WO, Open.CE)
2116
Ethan Furman25d94bb2016-09-02 16:32:32 -07002117 def test_bool(self):
2118 Perm = self.Perm
2119 for f in Perm:
2120 self.assertTrue(f)
2121 Open = self.Open
2122 for f in Open:
2123 self.assertEqual(bool(f.value), bool(f))
2124
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002125 def test_programatic_function_string(self):
Ethan Furman65a5a472016-09-01 23:55:19 -07002126 Perm = Flag('Perm', 'R W X')
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002127 lst = list(Perm)
2128 self.assertEqual(len(lst), len(Perm))
2129 self.assertEqual(len(Perm), 3, Perm)
2130 self.assertEqual(lst, [Perm.R, Perm.W, Perm.X])
2131 for i, n in enumerate('R W X'.split()):
2132 v = 1<<i
2133 e = Perm(v)
2134 self.assertEqual(e.value, v)
2135 self.assertEqual(type(e.value), int)
2136 self.assertEqual(e.name, n)
2137 self.assertIn(e, Perm)
2138 self.assertIs(type(e), Perm)
2139
2140 def test_programatic_function_string_with_start(self):
Ethan Furman65a5a472016-09-01 23:55:19 -07002141 Perm = Flag('Perm', 'R W X', start=8)
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002142 lst = list(Perm)
2143 self.assertEqual(len(lst), len(Perm))
2144 self.assertEqual(len(Perm), 3, Perm)
2145 self.assertEqual(lst, [Perm.R, Perm.W, Perm.X])
2146 for i, n in enumerate('R W X'.split()):
2147 v = 8<<i
2148 e = Perm(v)
2149 self.assertEqual(e.value, v)
2150 self.assertEqual(type(e.value), int)
2151 self.assertEqual(e.name, n)
2152 self.assertIn(e, Perm)
2153 self.assertIs(type(e), Perm)
2154
2155 def test_programatic_function_string_list(self):
Ethan Furman65a5a472016-09-01 23:55:19 -07002156 Perm = Flag('Perm', ['R', 'W', 'X'])
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002157 lst = list(Perm)
2158 self.assertEqual(len(lst), len(Perm))
2159 self.assertEqual(len(Perm), 3, Perm)
2160 self.assertEqual(lst, [Perm.R, Perm.W, Perm.X])
2161 for i, n in enumerate('R W X'.split()):
2162 v = 1<<i
2163 e = Perm(v)
2164 self.assertEqual(e.value, v)
2165 self.assertEqual(type(e.value), int)
2166 self.assertEqual(e.name, n)
2167 self.assertIn(e, Perm)
2168 self.assertIs(type(e), Perm)
2169
2170 def test_programatic_function_iterable(self):
Ethan Furman65a5a472016-09-01 23:55:19 -07002171 Perm = Flag('Perm', (('R', 2), ('W', 8), ('X', 32)))
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002172 lst = list(Perm)
2173 self.assertEqual(len(lst), len(Perm))
2174 self.assertEqual(len(Perm), 3, Perm)
2175 self.assertEqual(lst, [Perm.R, Perm.W, Perm.X])
2176 for i, n in enumerate('R W X'.split()):
2177 v = 1<<(2*i+1)
2178 e = Perm(v)
2179 self.assertEqual(e.value, v)
2180 self.assertEqual(type(e.value), int)
2181 self.assertEqual(e.name, n)
2182 self.assertIn(e, Perm)
2183 self.assertIs(type(e), Perm)
2184
2185 def test_programatic_function_from_dict(self):
Ethan Furman65a5a472016-09-01 23:55:19 -07002186 Perm = Flag('Perm', OrderedDict((('R', 2), ('W', 8), ('X', 32))))
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002187 lst = list(Perm)
2188 self.assertEqual(len(lst), len(Perm))
2189 self.assertEqual(len(Perm), 3, Perm)
2190 self.assertEqual(lst, [Perm.R, Perm.W, Perm.X])
2191 for i, n in enumerate('R W X'.split()):
2192 v = 1<<(2*i+1)
2193 e = Perm(v)
2194 self.assertEqual(e.value, v)
2195 self.assertEqual(type(e.value), int)
2196 self.assertEqual(e.name, n)
2197 self.assertIn(e, Perm)
2198 self.assertIs(type(e), Perm)
2199
Ethan Furman65a5a472016-09-01 23:55:19 -07002200 def test_pickle(self):
2201 if isinstance(FlagStooges, Exception):
2202 raise FlagStooges
2203 test_pickle_dump_load(self.assertIs, FlagStooges.CURLY|FlagStooges.MOE)
2204 test_pickle_dump_load(self.assertIs, FlagStooges)
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002205
Rahul Jha94306522018-09-10 23:51:04 +05302206 def test_contains(self):
2207 Open = self.Open
2208 Color = self.Color
2209 self.assertFalse(Color.BLACK in Open)
2210 self.assertFalse(Open.RO in Color)
2211 with self.assertRaises(TypeError):
2212 'BLACK' in Color
2213 with self.assertRaises(TypeError):
2214 'RO' in Open
2215 with self.assertRaises(TypeError):
2216 1 in Color
2217 with self.assertRaises(TypeError):
2218 1 in Open
2219
2220 def test_member_contains(self):
Ethan Furman65a5a472016-09-01 23:55:19 -07002221 Perm = self.Perm
2222 R, W, X = Perm
2223 RW = R | W
2224 RX = R | X
2225 WX = W | X
2226 RWX = R | W | X
2227 self.assertTrue(R in RW)
2228 self.assertTrue(R in RX)
2229 self.assertTrue(R in RWX)
2230 self.assertTrue(W in RW)
2231 self.assertTrue(W in WX)
2232 self.assertTrue(W in RWX)
2233 self.assertTrue(X in RX)
2234 self.assertTrue(X in WX)
2235 self.assertTrue(X in RWX)
2236 self.assertFalse(R in WX)
2237 self.assertFalse(W in RX)
2238 self.assertFalse(X in RW)
2239
Ethan Furmanc16595e2016-09-10 23:36:59 -07002240 def test_auto_number(self):
2241 class Color(Flag):
2242 red = auto()
2243 blue = auto()
2244 green = auto()
2245
2246 self.assertEqual(list(Color), [Color.red, Color.blue, Color.green])
2247 self.assertEqual(Color.red.value, 1)
2248 self.assertEqual(Color.blue.value, 2)
2249 self.assertEqual(Color.green.value, 4)
2250
2251 def test_auto_number_garbage(self):
2252 with self.assertRaisesRegex(TypeError, 'Invalid Flag value: .not an int.'):
2253 class Color(Flag):
2254 red = 'not an int'
2255 blue = auto()
2256
Ethan Furman3515dcc2016-09-18 13:15:41 -07002257 def test_cascading_failure(self):
2258 class Bizarre(Flag):
2259 c = 3
2260 d = 4
2261 f = 6
2262 # Bizarre.c | Bizarre.d
2263 self.assertRaisesRegex(ValueError, "5 is not a valid Bizarre", Bizarre, 5)
2264 self.assertRaisesRegex(ValueError, "5 is not a valid Bizarre", Bizarre, 5)
2265 self.assertRaisesRegex(ValueError, "2 is not a valid Bizarre", Bizarre, 2)
2266 self.assertRaisesRegex(ValueError, "2 is not a valid Bizarre", Bizarre, 2)
2267 self.assertRaisesRegex(ValueError, "1 is not a valid Bizarre", Bizarre, 1)
2268 self.assertRaisesRegex(ValueError, "1 is not a valid Bizarre", Bizarre, 1)
2269
2270 def test_duplicate_auto(self):
2271 class Dupes(Enum):
2272 first = primero = auto()
2273 second = auto()
2274 third = auto()
2275 self.assertEqual([Dupes.first, Dupes.second, Dupes.third], list(Dupes))
2276
2277 def test_bizarre(self):
2278 class Bizarre(Flag):
2279 b = 3
2280 c = 4
2281 d = 6
2282 self.assertEqual(repr(Bizarre(7)), '<Bizarre.d|c|b: 7>')
2283
Ethan Furman5bdab642018-09-21 19:03:09 -07002284 def test_multiple_mixin(self):
2285 class AllMixin:
2286 @classproperty
2287 def ALL(cls):
2288 members = list(cls)
2289 all_value = None
2290 if members:
2291 all_value = members[0]
2292 for member in members[1:]:
2293 all_value |= member
2294 cls.ALL = all_value
2295 return all_value
2296 class StrMixin:
2297 def __str__(self):
2298 return self._name_.lower()
2299 class Color(AllMixin, Flag):
2300 RED = auto()
2301 GREEN = auto()
2302 BLUE = auto()
2303 self.assertEqual(Color.RED.value, 1)
2304 self.assertEqual(Color.GREEN.value, 2)
2305 self.assertEqual(Color.BLUE.value, 4)
2306 self.assertEqual(Color.ALL.value, 7)
2307 self.assertEqual(str(Color.BLUE), 'Color.BLUE')
2308 class Color(AllMixin, StrMixin, Flag):
2309 RED = auto()
2310 GREEN = auto()
2311 BLUE = auto()
2312 self.assertEqual(Color.RED.value, 1)
2313 self.assertEqual(Color.GREEN.value, 2)
2314 self.assertEqual(Color.BLUE.value, 4)
2315 self.assertEqual(Color.ALL.value, 7)
2316 self.assertEqual(str(Color.BLUE), 'blue')
2317 class Color(StrMixin, AllMixin, Flag):
2318 RED = auto()
2319 GREEN = auto()
2320 BLUE = auto()
2321 self.assertEqual(Color.RED.value, 1)
2322 self.assertEqual(Color.GREEN.value, 2)
2323 self.assertEqual(Color.BLUE.value, 4)
2324 self.assertEqual(Color.ALL.value, 7)
2325 self.assertEqual(str(Color.BLUE), 'blue')
2326
Ethan Furman28cf6632017-01-24 12:12:06 -08002327 @support.reap_threads
2328 def test_unique_composite(self):
2329 # override __eq__ to be identity only
2330 class TestFlag(Flag):
2331 one = auto()
2332 two = auto()
2333 three = auto()
2334 four = auto()
2335 five = auto()
2336 six = auto()
2337 seven = auto()
2338 eight = auto()
2339 def __eq__(self, other):
2340 return self is other
2341 def __hash__(self):
2342 return hash(self._value_)
2343 # have multiple threads competing to complete the composite members
2344 seen = set()
2345 failed = False
2346 def cycle_enum():
2347 nonlocal failed
2348 try:
2349 for i in range(256):
2350 seen.add(TestFlag(i))
2351 except Exception:
2352 failed = True
2353 threads = [
2354 threading.Thread(target=cycle_enum)
2355 for _ in range(8)
2356 ]
2357 with support.start_threads(threads):
2358 pass
2359 # check that only 248 members were created
2360 self.assertFalse(
2361 failed,
2362 'at least one thread failed while creating composite members')
2363 self.assertEqual(256, len(seen), 'too many composite members created')
2364
Ethan Furmanc16595e2016-09-10 23:36:59 -07002365
Ethan Furman65a5a472016-09-01 23:55:19 -07002366class TestIntFlag(unittest.TestCase):
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002367 """Tests of the IntFlags."""
2368
Ethan Furman65a5a472016-09-01 23:55:19 -07002369 class Perm(IntFlag):
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002370 X = 1 << 0
2371 W = 1 << 1
2372 R = 1 << 2
2373
Ethan Furman65a5a472016-09-01 23:55:19 -07002374 class Open(IntFlag):
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002375 RO = 0
2376 WO = 1
2377 RW = 2
2378 AC = 3
2379 CE = 1<<19
2380
Rahul Jha94306522018-09-10 23:51:04 +05302381 class Color(IntFlag):
2382 BLACK = 0
2383 RED = 1
2384 GREEN = 2
2385 BLUE = 4
2386 PURPLE = RED|BLUE
2387
Ethan Furman3515dcc2016-09-18 13:15:41 -07002388 def test_type(self):
2389 Perm = self.Perm
2390 Open = self.Open
2391 for f in Perm:
2392 self.assertTrue(isinstance(f, Perm))
2393 self.assertEqual(f, f.value)
2394 self.assertTrue(isinstance(Perm.W | Perm.X, Perm))
2395 self.assertEqual(Perm.W | Perm.X, 3)
2396 for f in Open:
2397 self.assertTrue(isinstance(f, Open))
2398 self.assertEqual(f, f.value)
2399 self.assertTrue(isinstance(Open.WO | Open.RW, Open))
2400 self.assertEqual(Open.WO | Open.RW, 3)
2401
2402
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002403 def test_str(self):
2404 Perm = self.Perm
2405 self.assertEqual(str(Perm.R), 'Perm.R')
2406 self.assertEqual(str(Perm.W), 'Perm.W')
2407 self.assertEqual(str(Perm.X), 'Perm.X')
2408 self.assertEqual(str(Perm.R | Perm.W), 'Perm.R|W')
2409 self.assertEqual(str(Perm.R | Perm.W | Perm.X), 'Perm.R|W|X')
2410 self.assertEqual(str(Perm.R | 8), 'Perm.8|R')
2411 self.assertEqual(str(Perm(0)), 'Perm.0')
2412 self.assertEqual(str(Perm(8)), 'Perm.8')
Ethan Furman3515dcc2016-09-18 13:15:41 -07002413 self.assertEqual(str(~Perm.R), 'Perm.W|X')
2414 self.assertEqual(str(~Perm.W), 'Perm.R|X')
2415 self.assertEqual(str(~Perm.X), 'Perm.R|W')
2416 self.assertEqual(str(~(Perm.R | Perm.W)), 'Perm.X')
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002417 self.assertEqual(str(~(Perm.R | Perm.W | Perm.X)), 'Perm.-8')
Ethan Furman3515dcc2016-09-18 13:15:41 -07002418 self.assertEqual(str(~(Perm.R | 8)), 'Perm.W|X')
2419 self.assertEqual(str(Perm(~0)), 'Perm.R|W|X')
2420 self.assertEqual(str(Perm(~8)), 'Perm.R|W|X')
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002421
2422 Open = self.Open
2423 self.assertEqual(str(Open.RO), 'Open.RO')
2424 self.assertEqual(str(Open.WO), 'Open.WO')
2425 self.assertEqual(str(Open.AC), 'Open.AC')
2426 self.assertEqual(str(Open.RO | Open.CE), 'Open.CE')
2427 self.assertEqual(str(Open.WO | Open.CE), 'Open.CE|WO')
2428 self.assertEqual(str(Open(4)), 'Open.4')
Ethan Furman3515dcc2016-09-18 13:15:41 -07002429 self.assertEqual(str(~Open.RO), 'Open.CE|AC|RW|WO')
2430 self.assertEqual(str(~Open.WO), 'Open.CE|RW')
2431 self.assertEqual(str(~Open.AC), 'Open.CE')
2432 self.assertEqual(str(~(Open.RO | Open.CE)), 'Open.AC|RW|WO')
2433 self.assertEqual(str(~(Open.WO | Open.CE)), 'Open.RW')
2434 self.assertEqual(str(Open(~4)), 'Open.CE|AC|RW|WO')
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002435
2436 def test_repr(self):
2437 Perm = self.Perm
2438 self.assertEqual(repr(Perm.R), '<Perm.R: 4>')
2439 self.assertEqual(repr(Perm.W), '<Perm.W: 2>')
2440 self.assertEqual(repr(Perm.X), '<Perm.X: 1>')
2441 self.assertEqual(repr(Perm.R | Perm.W), '<Perm.R|W: 6>')
2442 self.assertEqual(repr(Perm.R | Perm.W | Perm.X), '<Perm.R|W|X: 7>')
2443 self.assertEqual(repr(Perm.R | 8), '<Perm.8|R: 12>')
Ethan Furman27682d22016-09-04 11:39:01 -07002444 self.assertEqual(repr(Perm(0)), '<Perm.0: 0>')
2445 self.assertEqual(repr(Perm(8)), '<Perm.8: 8>')
Ethan Furman3515dcc2016-09-18 13:15:41 -07002446 self.assertEqual(repr(~Perm.R), '<Perm.W|X: -5>')
2447 self.assertEqual(repr(~Perm.W), '<Perm.R|X: -3>')
2448 self.assertEqual(repr(~Perm.X), '<Perm.R|W: -2>')
2449 self.assertEqual(repr(~(Perm.R | Perm.W)), '<Perm.X: -7>')
Ethan Furman27682d22016-09-04 11:39:01 -07002450 self.assertEqual(repr(~(Perm.R | Perm.W | Perm.X)), '<Perm.-8: -8>')
Ethan Furman3515dcc2016-09-18 13:15:41 -07002451 self.assertEqual(repr(~(Perm.R | 8)), '<Perm.W|X: -13>')
2452 self.assertEqual(repr(Perm(~0)), '<Perm.R|W|X: -1>')
2453 self.assertEqual(repr(Perm(~8)), '<Perm.R|W|X: -9>')
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002454
2455 Open = self.Open
2456 self.assertEqual(repr(Open.RO), '<Open.RO: 0>')
2457 self.assertEqual(repr(Open.WO), '<Open.WO: 1>')
2458 self.assertEqual(repr(Open.AC), '<Open.AC: 3>')
2459 self.assertEqual(repr(Open.RO | Open.CE), '<Open.CE: 524288>')
2460 self.assertEqual(repr(Open.WO | Open.CE), '<Open.CE|WO: 524289>')
Ethan Furman27682d22016-09-04 11:39:01 -07002461 self.assertEqual(repr(Open(4)), '<Open.4: 4>')
Ethan Furman3515dcc2016-09-18 13:15:41 -07002462 self.assertEqual(repr(~Open.RO), '<Open.CE|AC|RW|WO: -1>')
2463 self.assertEqual(repr(~Open.WO), '<Open.CE|RW: -2>')
2464 self.assertEqual(repr(~Open.AC), '<Open.CE: -4>')
2465 self.assertEqual(repr(~(Open.RO | Open.CE)), '<Open.AC|RW|WO: -524289>')
2466 self.assertEqual(repr(~(Open.WO | Open.CE)), '<Open.RW: -524290>')
2467 self.assertEqual(repr(Open(~4)), '<Open.CE|AC|RW|WO: -5>')
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002468
2469 def test_or(self):
2470 Perm = self.Perm
2471 for i in Perm:
2472 for j in Perm:
2473 self.assertEqual(i | j, i.value | j.value)
2474 self.assertEqual((i | j).value, i.value | j.value)
2475 self.assertIs(type(i | j), Perm)
2476 for j in range(8):
2477 self.assertEqual(i | j, i.value | j)
2478 self.assertEqual((i | j).value, i.value | j)
2479 self.assertIs(type(i | j), Perm)
2480 self.assertEqual(j | i, j | i.value)
2481 self.assertEqual((j | i).value, j | i.value)
2482 self.assertIs(type(j | i), Perm)
2483 for i in Perm:
2484 self.assertIs(i | i, i)
2485 self.assertIs(i | 0, i)
2486 self.assertIs(0 | i, i)
2487 Open = self.Open
2488 self.assertIs(Open.RO | Open.CE, Open.CE)
2489
2490 def test_and(self):
2491 Perm = self.Perm
2492 RW = Perm.R | Perm.W
2493 RX = Perm.R | Perm.X
2494 WX = Perm.W | Perm.X
2495 RWX = Perm.R | Perm.W | Perm.X
2496 values = list(Perm) + [RW, RX, WX, RWX, Perm(0)]
2497 for i in values:
2498 for j in values:
2499 self.assertEqual(i & j, i.value & j.value, 'i is %r, j is %r' % (i, j))
2500 self.assertEqual((i & j).value, i.value & j.value, 'i is %r, j is %r' % (i, j))
2501 self.assertIs(type(i & j), Perm, 'i is %r, j is %r' % (i, j))
2502 for j in range(8):
2503 self.assertEqual(i & j, i.value & j)
2504 self.assertEqual((i & j).value, i.value & j)
2505 self.assertIs(type(i & j), Perm)
2506 self.assertEqual(j & i, j & i.value)
2507 self.assertEqual((j & i).value, j & i.value)
2508 self.assertIs(type(j & i), Perm)
2509 for i in Perm:
2510 self.assertIs(i & i, i)
2511 self.assertIs(i & 7, i)
2512 self.assertIs(7 & i, i)
2513 Open = self.Open
2514 self.assertIs(Open.RO & Open.CE, Open.RO)
2515
2516 def test_xor(self):
2517 Perm = self.Perm
2518 for i in Perm:
2519 for j in Perm:
2520 self.assertEqual(i ^ j, i.value ^ j.value)
2521 self.assertEqual((i ^ j).value, i.value ^ j.value)
2522 self.assertIs(type(i ^ j), Perm)
2523 for j in range(8):
2524 self.assertEqual(i ^ j, i.value ^ j)
2525 self.assertEqual((i ^ j).value, i.value ^ j)
2526 self.assertIs(type(i ^ j), Perm)
2527 self.assertEqual(j ^ i, j ^ i.value)
2528 self.assertEqual((j ^ i).value, j ^ i.value)
2529 self.assertIs(type(j ^ i), Perm)
2530 for i in Perm:
2531 self.assertIs(i ^ 0, i)
2532 self.assertIs(0 ^ i, i)
2533 Open = self.Open
2534 self.assertIs(Open.RO ^ Open.CE, Open.CE)
2535 self.assertIs(Open.CE ^ Open.CE, Open.RO)
2536
2537 def test_invert(self):
2538 Perm = self.Perm
2539 RW = Perm.R | Perm.W
2540 RX = Perm.R | Perm.X
2541 WX = Perm.W | Perm.X
2542 RWX = Perm.R | Perm.W | Perm.X
2543 values = list(Perm) + [RW, RX, WX, RWX, Perm(0)]
2544 for i in values:
2545 self.assertEqual(~i, ~i.value)
2546 self.assertEqual((~i).value, ~i.value)
2547 self.assertIs(type(~i), Perm)
2548 self.assertEqual(~~i, i)
2549 for i in Perm:
2550 self.assertIs(~~i, i)
2551 Open = self.Open
2552 self.assertIs(Open.WO & ~Open.WO, Open.RO)
2553 self.assertIs((Open.WO|Open.CE) & ~Open.WO, Open.CE)
2554
2555 def test_programatic_function_string(self):
Ethan Furman65a5a472016-09-01 23:55:19 -07002556 Perm = IntFlag('Perm', 'R W X')
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002557 lst = list(Perm)
2558 self.assertEqual(len(lst), len(Perm))
2559 self.assertEqual(len(Perm), 3, Perm)
2560 self.assertEqual(lst, [Perm.R, Perm.W, Perm.X])
2561 for i, n in enumerate('R W X'.split()):
2562 v = 1<<i
2563 e = Perm(v)
2564 self.assertEqual(e.value, v)
2565 self.assertEqual(type(e.value), int)
2566 self.assertEqual(e, v)
2567 self.assertEqual(e.name, n)
2568 self.assertIn(e, Perm)
2569 self.assertIs(type(e), Perm)
2570
2571 def test_programatic_function_string_with_start(self):
Ethan Furman65a5a472016-09-01 23:55:19 -07002572 Perm = IntFlag('Perm', 'R W X', start=8)
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002573 lst = list(Perm)
2574 self.assertEqual(len(lst), len(Perm))
2575 self.assertEqual(len(Perm), 3, Perm)
2576 self.assertEqual(lst, [Perm.R, Perm.W, Perm.X])
2577 for i, n in enumerate('R W X'.split()):
2578 v = 8<<i
2579 e = Perm(v)
2580 self.assertEqual(e.value, v)
2581 self.assertEqual(type(e.value), int)
2582 self.assertEqual(e, v)
2583 self.assertEqual(e.name, n)
2584 self.assertIn(e, Perm)
2585 self.assertIs(type(e), Perm)
2586
2587 def test_programatic_function_string_list(self):
Ethan Furman65a5a472016-09-01 23:55:19 -07002588 Perm = IntFlag('Perm', ['R', 'W', 'X'])
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002589 lst = list(Perm)
2590 self.assertEqual(len(lst), len(Perm))
2591 self.assertEqual(len(Perm), 3, Perm)
2592 self.assertEqual(lst, [Perm.R, Perm.W, Perm.X])
2593 for i, n in enumerate('R W X'.split()):
2594 v = 1<<i
2595 e = Perm(v)
2596 self.assertEqual(e.value, v)
2597 self.assertEqual(type(e.value), int)
2598 self.assertEqual(e, v)
2599 self.assertEqual(e.name, n)
2600 self.assertIn(e, Perm)
2601 self.assertIs(type(e), Perm)
2602
2603 def test_programatic_function_iterable(self):
Ethan Furman65a5a472016-09-01 23:55:19 -07002604 Perm = IntFlag('Perm', (('R', 2), ('W', 8), ('X', 32)))
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002605 lst = list(Perm)
2606 self.assertEqual(len(lst), len(Perm))
2607 self.assertEqual(len(Perm), 3, Perm)
2608 self.assertEqual(lst, [Perm.R, Perm.W, Perm.X])
2609 for i, n in enumerate('R W X'.split()):
2610 v = 1<<(2*i+1)
2611 e = Perm(v)
2612 self.assertEqual(e.value, v)
2613 self.assertEqual(type(e.value), int)
2614 self.assertEqual(e, v)
2615 self.assertEqual(e.name, n)
2616 self.assertIn(e, Perm)
2617 self.assertIs(type(e), Perm)
2618
2619 def test_programatic_function_from_dict(self):
Ethan Furman65a5a472016-09-01 23:55:19 -07002620 Perm = IntFlag('Perm', OrderedDict((('R', 2), ('W', 8), ('X', 32))))
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002621 lst = list(Perm)
2622 self.assertEqual(len(lst), len(Perm))
2623 self.assertEqual(len(Perm), 3, Perm)
2624 self.assertEqual(lst, [Perm.R, Perm.W, Perm.X])
2625 for i, n in enumerate('R W X'.split()):
2626 v = 1<<(2*i+1)
2627 e = Perm(v)
2628 self.assertEqual(e.value, v)
2629 self.assertEqual(type(e.value), int)
2630 self.assertEqual(e, v)
2631 self.assertEqual(e.name, n)
2632 self.assertIn(e, Perm)
2633 self.assertIs(type(e), Perm)
2634
2635
Dong-hee Nadcc8ce42017-06-22 01:52:32 +09002636 def test_programatic_function_from_empty_list(self):
2637 Perm = enum.IntFlag('Perm', [])
2638 lst = list(Perm)
2639 self.assertEqual(len(lst), len(Perm))
2640 self.assertEqual(len(Perm), 0, Perm)
2641 Thing = enum.Enum('Thing', [])
2642 lst = list(Thing)
2643 self.assertEqual(len(lst), len(Thing))
2644 self.assertEqual(len(Thing), 0, Thing)
2645
2646
2647 def test_programatic_function_from_empty_tuple(self):
2648 Perm = enum.IntFlag('Perm', ())
2649 lst = list(Perm)
2650 self.assertEqual(len(lst), len(Perm))
2651 self.assertEqual(len(Perm), 0, Perm)
2652 Thing = enum.Enum('Thing', ())
2653 self.assertEqual(len(lst), len(Thing))
2654 self.assertEqual(len(Thing), 0, Thing)
2655
Rahul Jha94306522018-09-10 23:51:04 +05302656 def test_contains(self):
2657 Open = self.Open
2658 Color = self.Color
2659 self.assertTrue(Color.GREEN in Color)
2660 self.assertTrue(Open.RW in Open)
2661 self.assertFalse(Color.GREEN in Open)
2662 self.assertFalse(Open.RW in Color)
2663 with self.assertRaises(TypeError):
2664 'GREEN' in Color
2665 with self.assertRaises(TypeError):
2666 'RW' in Open
2667 with self.assertRaises(TypeError):
2668 2 in Color
2669 with self.assertRaises(TypeError):
2670 2 in Open
2671
2672 def test_member_contains(self):
Ethan Furman65a5a472016-09-01 23:55:19 -07002673 Perm = self.Perm
2674 R, W, X = Perm
2675 RW = R | W
2676 RX = R | X
2677 WX = W | X
2678 RWX = R | W | X
2679 self.assertTrue(R in RW)
2680 self.assertTrue(R in RX)
2681 self.assertTrue(R in RWX)
2682 self.assertTrue(W in RW)
2683 self.assertTrue(W in WX)
2684 self.assertTrue(W in RWX)
2685 self.assertTrue(X in RX)
2686 self.assertTrue(X in WX)
2687 self.assertTrue(X in RWX)
2688 self.assertFalse(R in WX)
2689 self.assertFalse(W in RX)
2690 self.assertFalse(X in RW)
Rahul Jha94306522018-09-10 23:51:04 +05302691 with self.assertRaises(TypeError):
2692 self.assertFalse('test' in RW)
Ethan Furman65a5a472016-09-01 23:55:19 -07002693
Ethan Furman25d94bb2016-09-02 16:32:32 -07002694 def test_bool(self):
2695 Perm = self.Perm
2696 for f in Perm:
2697 self.assertTrue(f)
2698 Open = self.Open
2699 for f in Open:
2700 self.assertEqual(bool(f.value), bool(f))
2701
Ethan Furman5bdab642018-09-21 19:03:09 -07002702 def test_multiple_mixin(self):
2703 class AllMixin:
2704 @classproperty
2705 def ALL(cls):
2706 members = list(cls)
2707 all_value = None
2708 if members:
2709 all_value = members[0]
2710 for member in members[1:]:
2711 all_value |= member
2712 cls.ALL = all_value
2713 return all_value
2714 class StrMixin:
2715 def __str__(self):
2716 return self._name_.lower()
2717 class Color(AllMixin, IntFlag):
2718 RED = auto()
2719 GREEN = auto()
2720 BLUE = auto()
2721 self.assertEqual(Color.RED.value, 1)
2722 self.assertEqual(Color.GREEN.value, 2)
2723 self.assertEqual(Color.BLUE.value, 4)
2724 self.assertEqual(Color.ALL.value, 7)
2725 self.assertEqual(str(Color.BLUE), 'Color.BLUE')
2726 class Color(AllMixin, StrMixin, IntFlag):
2727 RED = auto()
2728 GREEN = auto()
2729 BLUE = auto()
2730 self.assertEqual(Color.RED.value, 1)
2731 self.assertEqual(Color.GREEN.value, 2)
2732 self.assertEqual(Color.BLUE.value, 4)
2733 self.assertEqual(Color.ALL.value, 7)
2734 self.assertEqual(str(Color.BLUE), 'blue')
2735 class Color(StrMixin, AllMixin, IntFlag):
2736 RED = auto()
2737 GREEN = auto()
2738 BLUE = auto()
2739 self.assertEqual(Color.RED.value, 1)
2740 self.assertEqual(Color.GREEN.value, 2)
2741 self.assertEqual(Color.BLUE.value, 4)
2742 self.assertEqual(Color.ALL.value, 7)
2743 self.assertEqual(str(Color.BLUE), 'blue')
2744
Ethan Furman28cf6632017-01-24 12:12:06 -08002745 @support.reap_threads
2746 def test_unique_composite(self):
2747 # override __eq__ to be identity only
2748 class TestFlag(IntFlag):
2749 one = auto()
2750 two = auto()
2751 three = auto()
2752 four = auto()
2753 five = auto()
2754 six = auto()
2755 seven = auto()
2756 eight = auto()
2757 def __eq__(self, other):
2758 return self is other
2759 def __hash__(self):
2760 return hash(self._value_)
2761 # have multiple threads competing to complete the composite members
2762 seen = set()
2763 failed = False
2764 def cycle_enum():
2765 nonlocal failed
2766 try:
2767 for i in range(256):
2768 seen.add(TestFlag(i))
2769 except Exception:
2770 failed = True
2771 threads = [
2772 threading.Thread(target=cycle_enum)
2773 for _ in range(8)
2774 ]
2775 with support.start_threads(threads):
2776 pass
2777 # check that only 248 members were created
2778 self.assertFalse(
2779 failed,
2780 'at least one thread failed while creating composite members')
2781 self.assertEqual(256, len(seen), 'too many composite members created')
2782
2783
Brennan D Baraban8b914d22019-03-03 14:09:11 -08002784class TestEmptyAndNonLatinStrings(unittest.TestCase):
2785
2786 def test_empty_string(self):
2787 with self.assertRaises(ValueError):
2788 empty_abc = Enum('empty_abc', ('', 'B', 'C'))
2789
2790 def test_non_latin_character_string(self):
2791 greek_abc = Enum('greek_abc', ('\u03B1', 'B', 'C'))
2792 item = getattr(greek_abc, '\u03B1')
2793 self.assertEqual(item.value, 1)
2794
2795 def test_non_latin_number_string(self):
2796 hebrew_123 = Enum('hebrew_123', ('\u05D0', '2', '3'))
2797 item = getattr(hebrew_123, '\u05D0')
2798 self.assertEqual(item.value, 1)
2799
2800
Ethan Furmanf24bb352013-07-18 17:05:39 -07002801class TestUnique(unittest.TestCase):
2802
2803 def test_unique_clean(self):
2804 @unique
2805 class Clean(Enum):
2806 one = 1
2807 two = 'dos'
2808 tres = 4.0
2809 @unique
2810 class Cleaner(IntEnum):
2811 single = 1
2812 double = 2
2813 triple = 3
2814
2815 def test_unique_dirty(self):
2816 with self.assertRaisesRegex(ValueError, 'tres.*one'):
2817 @unique
2818 class Dirty(Enum):
2819 one = 1
2820 two = 'dos'
2821 tres = 1
2822 with self.assertRaisesRegex(
2823 ValueError,
2824 'double.*single.*turkey.*triple',
2825 ):
2826 @unique
2827 class Dirtier(IntEnum):
2828 single = 1
2829 double = 1
2830 triple = 3
2831 turkey = 3
2832
Ethan Furman3803ad42016-05-01 10:03:53 -07002833 def test_unique_with_name(self):
2834 @unique
2835 class Silly(Enum):
2836 one = 1
2837 two = 'dos'
2838 name = 3
2839 @unique
2840 class Sillier(IntEnum):
2841 single = 1
2842 name = 2
2843 triple = 3
2844 value = 4
2845
Ethan Furmanf24bb352013-07-18 17:05:39 -07002846
Ethan Furman5bdab642018-09-21 19:03:09 -07002847
Ethan Furman3323da92015-04-11 09:39:59 -07002848expected_help_output_with_docs = """\
Ethan Furman5875d742013-10-21 20:45:55 -07002849Help on class Color in module %s:
2850
2851class Color(enum.Enum)
Serhiy Storchaka90f63322017-01-24 09:06:22 +02002852 | Color(value, names=None, *, module=None, qualname=None, type=None, start=1)
2853 |\x20\x20
Ethan Furman48a724f2015-04-11 23:23:06 -07002854 | An enumeration.
Serhiy Storchakab599ca82015-04-04 12:48:04 +03002855 |\x20\x20
Ethan Furman5875d742013-10-21 20:45:55 -07002856 | Method resolution order:
2857 | Color
2858 | enum.Enum
2859 | builtins.object
2860 |\x20\x20
2861 | Data and other attributes defined here:
2862 |\x20\x20
2863 | blue = <Color.blue: 3>
2864 |\x20\x20
2865 | green = <Color.green: 2>
2866 |\x20\x20
2867 | red = <Color.red: 1>
2868 |\x20\x20
2869 | ----------------------------------------------------------------------
2870 | Data descriptors inherited from enum.Enum:
2871 |\x20\x20
2872 | name
2873 | The name of the Enum member.
2874 |\x20\x20
2875 | value
2876 | The value of the Enum member.
2877 |\x20\x20
2878 | ----------------------------------------------------------------------
Raymond Hettinger62be3382019-03-24 17:07:47 -07002879 | Readonly properties inherited from enum.EnumMeta:
Ethan Furman5875d742013-10-21 20:45:55 -07002880 |\x20\x20
2881 | __members__
2882 | Returns a mapping of member name->value.
2883 |\x20\x20\x20\x20\x20\x20
2884 | This mapping lists all enum members, including aliases. Note that this
Ethan Furman3323da92015-04-11 09:39:59 -07002885 | is a read-only view of the internal mapping."""
2886
2887expected_help_output_without_docs = """\
2888Help on class Color in module %s:
2889
2890class Color(enum.Enum)
Serhiy Storchaka90f63322017-01-24 09:06:22 +02002891 | Color(value, names=None, *, module=None, qualname=None, type=None, start=1)
2892 |\x20\x20
Ethan Furman3323da92015-04-11 09:39:59 -07002893 | Method resolution order:
2894 | Color
2895 | enum.Enum
2896 | builtins.object
2897 |\x20\x20
2898 | Data and other attributes defined here:
2899 |\x20\x20
2900 | blue = <Color.blue: 3>
2901 |\x20\x20
2902 | green = <Color.green: 2>
2903 |\x20\x20
2904 | red = <Color.red: 1>
2905 |\x20\x20
2906 | ----------------------------------------------------------------------
2907 | Data descriptors inherited from enum.Enum:
2908 |\x20\x20
2909 | name
2910 |\x20\x20
2911 | value
2912 |\x20\x20
2913 | ----------------------------------------------------------------------
2914 | Data descriptors inherited from enum.EnumMeta:
2915 |\x20\x20
2916 | __members__"""
Ethan Furman5875d742013-10-21 20:45:55 -07002917
2918class TestStdLib(unittest.TestCase):
2919
Ethan Furman48a724f2015-04-11 23:23:06 -07002920 maxDiff = None
2921
Ethan Furman5875d742013-10-21 20:45:55 -07002922 class Color(Enum):
2923 red = 1
2924 green = 2
2925 blue = 3
2926
2927 def test_pydoc(self):
2928 # indirectly test __objclass__
Ethan Furman3323da92015-04-11 09:39:59 -07002929 if StrEnum.__doc__ is None:
2930 expected_text = expected_help_output_without_docs % __name__
2931 else:
2932 expected_text = expected_help_output_with_docs % __name__
Ethan Furman5875d742013-10-21 20:45:55 -07002933 output = StringIO()
2934 helper = pydoc.Helper(output=output)
2935 helper(self.Color)
2936 result = output.getvalue().strip()
Victor Stinner4b0432d2014-06-16 22:48:43 +02002937 self.assertEqual(result, expected_text)
Ethan Furman5875d742013-10-21 20:45:55 -07002938
2939 def test_inspect_getmembers(self):
2940 values = dict((
2941 ('__class__', EnumMeta),
Ethan Furman48a724f2015-04-11 23:23:06 -07002942 ('__doc__', 'An enumeration.'),
Ethan Furman5875d742013-10-21 20:45:55 -07002943 ('__members__', self.Color.__members__),
2944 ('__module__', __name__),
2945 ('blue', self.Color.blue),
2946 ('green', self.Color.green),
2947 ('name', Enum.__dict__['name']),
2948 ('red', self.Color.red),
2949 ('value', Enum.__dict__['value']),
2950 ))
2951 result = dict(inspect.getmembers(self.Color))
2952 self.assertEqual(values.keys(), result.keys())
2953 failed = False
2954 for k in values.keys():
2955 if result[k] != values[k]:
2956 print()
2957 print('\n%s\n key: %s\n result: %s\nexpected: %s\n%s\n' %
2958 ('=' * 75, k, result[k], values[k], '=' * 75), sep='')
2959 failed = True
2960 if failed:
2961 self.fail("result does not equal expected, see print above")
2962
2963 def test_inspect_classify_class_attrs(self):
2964 # indirectly test __objclass__
2965 from inspect import Attribute
2966 values = [
2967 Attribute(name='__class__', kind='data',
2968 defining_class=object, object=EnumMeta),
2969 Attribute(name='__doc__', kind='data',
Ethan Furman48a724f2015-04-11 23:23:06 -07002970 defining_class=self.Color, object='An enumeration.'),
Ethan Furman5875d742013-10-21 20:45:55 -07002971 Attribute(name='__members__', kind='property',
2972 defining_class=EnumMeta, object=EnumMeta.__members__),
2973 Attribute(name='__module__', kind='data',
2974 defining_class=self.Color, object=__name__),
2975 Attribute(name='blue', kind='data',
2976 defining_class=self.Color, object=self.Color.blue),
2977 Attribute(name='green', kind='data',
2978 defining_class=self.Color, object=self.Color.green),
2979 Attribute(name='red', kind='data',
2980 defining_class=self.Color, object=self.Color.red),
2981 Attribute(name='name', kind='data',
2982 defining_class=Enum, object=Enum.__dict__['name']),
2983 Attribute(name='value', kind='data',
2984 defining_class=Enum, object=Enum.__dict__['value']),
2985 ]
2986 values.sort(key=lambda item: item.name)
2987 result = list(inspect.classify_class_attrs(self.Color))
2988 result.sort(key=lambda item: item.name)
2989 failed = False
2990 for v, r in zip(values, result):
2991 if r != v:
2992 print('\n%s\n%s\n%s\n%s\n' % ('=' * 75, r, v, '=' * 75), sep='')
2993 failed = True
2994 if failed:
2995 self.fail("result does not equal expected, see print above")
2996
Martin Panter19e69c52015-11-14 12:46:42 +00002997
2998class MiscTestCase(unittest.TestCase):
2999 def test__all__(self):
3000 support.check__all__(self, enum)
3001
3002
Gregory P. Smith ext:(%20%5BGoogle%20Inc.%5D)6f20bd62016-06-03 19:14:52 +00003003# These are unordered here on purpose to ensure that declaration order
3004# makes no difference.
3005CONVERT_TEST_NAME_D = 5
3006CONVERT_TEST_NAME_C = 5
3007CONVERT_TEST_NAME_B = 5
3008CONVERT_TEST_NAME_A = 5 # This one should sort first.
3009CONVERT_TEST_NAME_E = 5
3010CONVERT_TEST_NAME_F = 5
3011
3012class TestIntEnumConvert(unittest.TestCase):
3013 def test_convert_value_lookup_priority(self):
orlnub1230fb9fad2018-09-12 20:28:53 +03003014 test_type = enum.IntEnum._convert_(
Ethan Furman28cf6632017-01-24 12:12:06 -08003015 'UnittestConvert',
3016 ('test.test_enum', '__main__')[__name__=='__main__'],
Gregory P. Smith ext:(%20%5BGoogle%20Inc.%5D)6f20bd62016-06-03 19:14:52 +00003017 filter=lambda x: x.startswith('CONVERT_TEST_'))
3018 # We don't want the reverse lookup value to vary when there are
3019 # multiple possible names for a given value. It should always
3020 # report the first lexigraphical name in that case.
3021 self.assertEqual(test_type(5).name, 'CONVERT_TEST_NAME_A')
3022
3023 def test_convert(self):
orlnub1230fb9fad2018-09-12 20:28:53 +03003024 test_type = enum.IntEnum._convert_(
Ethan Furman28cf6632017-01-24 12:12:06 -08003025 'UnittestConvert',
3026 ('test.test_enum', '__main__')[__name__=='__main__'],
Gregory P. Smith ext:(%20%5BGoogle%20Inc.%5D)6f20bd62016-06-03 19:14:52 +00003027 filter=lambda x: x.startswith('CONVERT_TEST_'))
3028 # Ensure that test_type has all of the desired names and values.
3029 self.assertEqual(test_type.CONVERT_TEST_NAME_F,
3030 test_type.CONVERT_TEST_NAME_A)
3031 self.assertEqual(test_type.CONVERT_TEST_NAME_B, 5)
3032 self.assertEqual(test_type.CONVERT_TEST_NAME_C, 5)
3033 self.assertEqual(test_type.CONVERT_TEST_NAME_D, 5)
3034 self.assertEqual(test_type.CONVERT_TEST_NAME_E, 5)
3035 # Ensure that test_type only picked up names matching the filter.
3036 self.assertEqual([name for name in dir(test_type)
3037 if name[0:2] not in ('CO', '__')],
3038 [], msg='Names other than CONVERT_TEST_* found.')
3039
orlnub1230fb9fad2018-09-12 20:28:53 +03003040 @unittest.skipUnless(sys.version_info[:2] == (3, 8),
3041 '_convert was deprecated in 3.8')
3042 def test_convert_warn(self):
3043 with self.assertWarns(DeprecationWarning):
3044 enum.IntEnum._convert(
3045 'UnittestConvert',
3046 ('test.test_enum', '__main__')[__name__=='__main__'],
3047 filter=lambda x: x.startswith('CONVERT_TEST_'))
3048
3049 @unittest.skipUnless(sys.version_info >= (3, 9),
3050 '_convert was removed in 3.9')
3051 def test_convert_raise(self):
3052 with self.assertRaises(AttributeError):
3053 enum.IntEnum._convert(
3054 'UnittestConvert',
3055 ('test.test_enum', '__main__')[__name__=='__main__'],
3056 filter=lambda x: x.startswith('CONVERT_TEST_'))
3057
Gregory P. Smith ext:(%20%5BGoogle%20Inc.%5D)6f20bd62016-06-03 19:14:52 +00003058
Ethan Furman6b3d64a2013-06-14 16:55:46 -07003059if __name__ == '__main__':
3060 unittest.main()