blob: 7bccd6660b52a254180cec3bd4969ecf00045656 [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
Walter Dörwald323842c2019-07-18 20:37:13 +02002263 name = "TestFlag.test_cascading_failure.<locals>.Bizarre"
2264 self.assertRaisesRegex(ValueError, "5 is not a valid " + name, Bizarre, 5)
2265 self.assertRaisesRegex(ValueError, "5 is not a valid " + name, Bizarre, 5)
2266 self.assertRaisesRegex(ValueError, "2 is not a valid " + name, Bizarre, 2)
2267 self.assertRaisesRegex(ValueError, "2 is not a valid " + name, Bizarre, 2)
2268 self.assertRaisesRegex(ValueError, "1 is not a valid " + name, Bizarre, 1)
2269 self.assertRaisesRegex(ValueError, "1 is not a valid " + name, Bizarre, 1)
Ethan Furman3515dcc2016-09-18 13:15:41 -07002270
2271 def test_duplicate_auto(self):
2272 class Dupes(Enum):
2273 first = primero = auto()
2274 second = auto()
2275 third = auto()
2276 self.assertEqual([Dupes.first, Dupes.second, Dupes.third], list(Dupes))
2277
2278 def test_bizarre(self):
2279 class Bizarre(Flag):
2280 b = 3
2281 c = 4
2282 d = 6
2283 self.assertEqual(repr(Bizarre(7)), '<Bizarre.d|c|b: 7>')
2284
Ethan Furman5bdab642018-09-21 19:03:09 -07002285 def test_multiple_mixin(self):
2286 class AllMixin:
2287 @classproperty
2288 def ALL(cls):
2289 members = list(cls)
2290 all_value = None
2291 if members:
2292 all_value = members[0]
2293 for member in members[1:]:
2294 all_value |= member
2295 cls.ALL = all_value
2296 return all_value
2297 class StrMixin:
2298 def __str__(self):
2299 return self._name_.lower()
2300 class Color(AllMixin, Flag):
2301 RED = auto()
2302 GREEN = auto()
2303 BLUE = auto()
2304 self.assertEqual(Color.RED.value, 1)
2305 self.assertEqual(Color.GREEN.value, 2)
2306 self.assertEqual(Color.BLUE.value, 4)
2307 self.assertEqual(Color.ALL.value, 7)
2308 self.assertEqual(str(Color.BLUE), 'Color.BLUE')
2309 class Color(AllMixin, StrMixin, Flag):
2310 RED = auto()
2311 GREEN = auto()
2312 BLUE = auto()
2313 self.assertEqual(Color.RED.value, 1)
2314 self.assertEqual(Color.GREEN.value, 2)
2315 self.assertEqual(Color.BLUE.value, 4)
2316 self.assertEqual(Color.ALL.value, 7)
2317 self.assertEqual(str(Color.BLUE), 'blue')
2318 class Color(StrMixin, AllMixin, Flag):
2319 RED = auto()
2320 GREEN = auto()
2321 BLUE = auto()
2322 self.assertEqual(Color.RED.value, 1)
2323 self.assertEqual(Color.GREEN.value, 2)
2324 self.assertEqual(Color.BLUE.value, 4)
2325 self.assertEqual(Color.ALL.value, 7)
2326 self.assertEqual(str(Color.BLUE), 'blue')
2327
Ethan Furman28cf6632017-01-24 12:12:06 -08002328 @support.reap_threads
2329 def test_unique_composite(self):
2330 # override __eq__ to be identity only
2331 class TestFlag(Flag):
2332 one = auto()
2333 two = auto()
2334 three = auto()
2335 four = auto()
2336 five = auto()
2337 six = auto()
2338 seven = auto()
2339 eight = auto()
2340 def __eq__(self, other):
2341 return self is other
2342 def __hash__(self):
2343 return hash(self._value_)
2344 # have multiple threads competing to complete the composite members
2345 seen = set()
2346 failed = False
2347 def cycle_enum():
2348 nonlocal failed
2349 try:
2350 for i in range(256):
2351 seen.add(TestFlag(i))
2352 except Exception:
2353 failed = True
2354 threads = [
2355 threading.Thread(target=cycle_enum)
2356 for _ in range(8)
2357 ]
2358 with support.start_threads(threads):
2359 pass
2360 # check that only 248 members were created
2361 self.assertFalse(
2362 failed,
2363 'at least one thread failed while creating composite members')
2364 self.assertEqual(256, len(seen), 'too many composite members created')
2365
Ethan Furmanc16595e2016-09-10 23:36:59 -07002366
Ethan Furman65a5a472016-09-01 23:55:19 -07002367class TestIntFlag(unittest.TestCase):
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002368 """Tests of the IntFlags."""
2369
Ethan Furman65a5a472016-09-01 23:55:19 -07002370 class Perm(IntFlag):
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002371 X = 1 << 0
2372 W = 1 << 1
2373 R = 1 << 2
2374
Ethan Furman65a5a472016-09-01 23:55:19 -07002375 class Open(IntFlag):
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002376 RO = 0
2377 WO = 1
2378 RW = 2
2379 AC = 3
2380 CE = 1<<19
2381
Rahul Jha94306522018-09-10 23:51:04 +05302382 class Color(IntFlag):
2383 BLACK = 0
2384 RED = 1
2385 GREEN = 2
2386 BLUE = 4
2387 PURPLE = RED|BLUE
2388
Ethan Furman3515dcc2016-09-18 13:15:41 -07002389 def test_type(self):
2390 Perm = self.Perm
2391 Open = self.Open
2392 for f in Perm:
2393 self.assertTrue(isinstance(f, Perm))
2394 self.assertEqual(f, f.value)
2395 self.assertTrue(isinstance(Perm.W | Perm.X, Perm))
2396 self.assertEqual(Perm.W | Perm.X, 3)
2397 for f in Open:
2398 self.assertTrue(isinstance(f, Open))
2399 self.assertEqual(f, f.value)
2400 self.assertTrue(isinstance(Open.WO | Open.RW, Open))
2401 self.assertEqual(Open.WO | Open.RW, 3)
2402
2403
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002404 def test_str(self):
2405 Perm = self.Perm
2406 self.assertEqual(str(Perm.R), 'Perm.R')
2407 self.assertEqual(str(Perm.W), 'Perm.W')
2408 self.assertEqual(str(Perm.X), 'Perm.X')
2409 self.assertEqual(str(Perm.R | Perm.W), 'Perm.R|W')
2410 self.assertEqual(str(Perm.R | Perm.W | Perm.X), 'Perm.R|W|X')
2411 self.assertEqual(str(Perm.R | 8), 'Perm.8|R')
2412 self.assertEqual(str(Perm(0)), 'Perm.0')
2413 self.assertEqual(str(Perm(8)), 'Perm.8')
Ethan Furman3515dcc2016-09-18 13:15:41 -07002414 self.assertEqual(str(~Perm.R), 'Perm.W|X')
2415 self.assertEqual(str(~Perm.W), 'Perm.R|X')
2416 self.assertEqual(str(~Perm.X), 'Perm.R|W')
2417 self.assertEqual(str(~(Perm.R | Perm.W)), 'Perm.X')
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002418 self.assertEqual(str(~(Perm.R | Perm.W | Perm.X)), 'Perm.-8')
Ethan Furman3515dcc2016-09-18 13:15:41 -07002419 self.assertEqual(str(~(Perm.R | 8)), 'Perm.W|X')
2420 self.assertEqual(str(Perm(~0)), 'Perm.R|W|X')
2421 self.assertEqual(str(Perm(~8)), 'Perm.R|W|X')
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002422
2423 Open = self.Open
2424 self.assertEqual(str(Open.RO), 'Open.RO')
2425 self.assertEqual(str(Open.WO), 'Open.WO')
2426 self.assertEqual(str(Open.AC), 'Open.AC')
2427 self.assertEqual(str(Open.RO | Open.CE), 'Open.CE')
2428 self.assertEqual(str(Open.WO | Open.CE), 'Open.CE|WO')
2429 self.assertEqual(str(Open(4)), 'Open.4')
Ethan Furman3515dcc2016-09-18 13:15:41 -07002430 self.assertEqual(str(~Open.RO), 'Open.CE|AC|RW|WO')
2431 self.assertEqual(str(~Open.WO), 'Open.CE|RW')
2432 self.assertEqual(str(~Open.AC), 'Open.CE')
2433 self.assertEqual(str(~(Open.RO | Open.CE)), 'Open.AC|RW|WO')
2434 self.assertEqual(str(~(Open.WO | Open.CE)), 'Open.RW')
2435 self.assertEqual(str(Open(~4)), 'Open.CE|AC|RW|WO')
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002436
2437 def test_repr(self):
2438 Perm = self.Perm
2439 self.assertEqual(repr(Perm.R), '<Perm.R: 4>')
2440 self.assertEqual(repr(Perm.W), '<Perm.W: 2>')
2441 self.assertEqual(repr(Perm.X), '<Perm.X: 1>')
2442 self.assertEqual(repr(Perm.R | Perm.W), '<Perm.R|W: 6>')
2443 self.assertEqual(repr(Perm.R | Perm.W | Perm.X), '<Perm.R|W|X: 7>')
2444 self.assertEqual(repr(Perm.R | 8), '<Perm.8|R: 12>')
Ethan Furman27682d22016-09-04 11:39:01 -07002445 self.assertEqual(repr(Perm(0)), '<Perm.0: 0>')
2446 self.assertEqual(repr(Perm(8)), '<Perm.8: 8>')
Ethan Furman3515dcc2016-09-18 13:15:41 -07002447 self.assertEqual(repr(~Perm.R), '<Perm.W|X: -5>')
2448 self.assertEqual(repr(~Perm.W), '<Perm.R|X: -3>')
2449 self.assertEqual(repr(~Perm.X), '<Perm.R|W: -2>')
2450 self.assertEqual(repr(~(Perm.R | Perm.W)), '<Perm.X: -7>')
Ethan Furman27682d22016-09-04 11:39:01 -07002451 self.assertEqual(repr(~(Perm.R | Perm.W | Perm.X)), '<Perm.-8: -8>')
Ethan Furman3515dcc2016-09-18 13:15:41 -07002452 self.assertEqual(repr(~(Perm.R | 8)), '<Perm.W|X: -13>')
2453 self.assertEqual(repr(Perm(~0)), '<Perm.R|W|X: -1>')
2454 self.assertEqual(repr(Perm(~8)), '<Perm.R|W|X: -9>')
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002455
2456 Open = self.Open
2457 self.assertEqual(repr(Open.RO), '<Open.RO: 0>')
2458 self.assertEqual(repr(Open.WO), '<Open.WO: 1>')
2459 self.assertEqual(repr(Open.AC), '<Open.AC: 3>')
2460 self.assertEqual(repr(Open.RO | Open.CE), '<Open.CE: 524288>')
2461 self.assertEqual(repr(Open.WO | Open.CE), '<Open.CE|WO: 524289>')
Ethan Furman27682d22016-09-04 11:39:01 -07002462 self.assertEqual(repr(Open(4)), '<Open.4: 4>')
Ethan Furman3515dcc2016-09-18 13:15:41 -07002463 self.assertEqual(repr(~Open.RO), '<Open.CE|AC|RW|WO: -1>')
2464 self.assertEqual(repr(~Open.WO), '<Open.CE|RW: -2>')
2465 self.assertEqual(repr(~Open.AC), '<Open.CE: -4>')
2466 self.assertEqual(repr(~(Open.RO | Open.CE)), '<Open.AC|RW|WO: -524289>')
2467 self.assertEqual(repr(~(Open.WO | Open.CE)), '<Open.RW: -524290>')
2468 self.assertEqual(repr(Open(~4)), '<Open.CE|AC|RW|WO: -5>')
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002469
2470 def test_or(self):
2471 Perm = self.Perm
2472 for i in Perm:
2473 for j in Perm:
2474 self.assertEqual(i | j, i.value | j.value)
2475 self.assertEqual((i | j).value, i.value | j.value)
2476 self.assertIs(type(i | j), Perm)
2477 for j in range(8):
2478 self.assertEqual(i | j, i.value | j)
2479 self.assertEqual((i | j).value, i.value | j)
2480 self.assertIs(type(i | j), Perm)
2481 self.assertEqual(j | i, j | i.value)
2482 self.assertEqual((j | i).value, j | i.value)
2483 self.assertIs(type(j | i), Perm)
2484 for i in Perm:
2485 self.assertIs(i | i, i)
2486 self.assertIs(i | 0, i)
2487 self.assertIs(0 | i, i)
2488 Open = self.Open
2489 self.assertIs(Open.RO | Open.CE, Open.CE)
2490
2491 def test_and(self):
2492 Perm = self.Perm
2493 RW = Perm.R | Perm.W
2494 RX = Perm.R | Perm.X
2495 WX = Perm.W | Perm.X
2496 RWX = Perm.R | Perm.W | Perm.X
2497 values = list(Perm) + [RW, RX, WX, RWX, Perm(0)]
2498 for i in values:
2499 for j in values:
2500 self.assertEqual(i & j, i.value & j.value, 'i is %r, j is %r' % (i, j))
2501 self.assertEqual((i & j).value, i.value & j.value, 'i is %r, j is %r' % (i, j))
2502 self.assertIs(type(i & j), Perm, 'i is %r, j is %r' % (i, j))
2503 for j in range(8):
2504 self.assertEqual(i & j, i.value & j)
2505 self.assertEqual((i & j).value, i.value & j)
2506 self.assertIs(type(i & j), Perm)
2507 self.assertEqual(j & i, j & i.value)
2508 self.assertEqual((j & i).value, j & i.value)
2509 self.assertIs(type(j & i), Perm)
2510 for i in Perm:
2511 self.assertIs(i & i, i)
2512 self.assertIs(i & 7, i)
2513 self.assertIs(7 & i, i)
2514 Open = self.Open
2515 self.assertIs(Open.RO & Open.CE, Open.RO)
2516
2517 def test_xor(self):
2518 Perm = self.Perm
2519 for i in Perm:
2520 for j in Perm:
2521 self.assertEqual(i ^ j, i.value ^ j.value)
2522 self.assertEqual((i ^ j).value, i.value ^ j.value)
2523 self.assertIs(type(i ^ j), Perm)
2524 for j in range(8):
2525 self.assertEqual(i ^ j, i.value ^ j)
2526 self.assertEqual((i ^ j).value, i.value ^ j)
2527 self.assertIs(type(i ^ j), Perm)
2528 self.assertEqual(j ^ i, j ^ i.value)
2529 self.assertEqual((j ^ i).value, j ^ i.value)
2530 self.assertIs(type(j ^ i), Perm)
2531 for i in Perm:
2532 self.assertIs(i ^ 0, i)
2533 self.assertIs(0 ^ i, i)
2534 Open = self.Open
2535 self.assertIs(Open.RO ^ Open.CE, Open.CE)
2536 self.assertIs(Open.CE ^ Open.CE, Open.RO)
2537
2538 def test_invert(self):
2539 Perm = self.Perm
2540 RW = Perm.R | Perm.W
2541 RX = Perm.R | Perm.X
2542 WX = Perm.W | Perm.X
2543 RWX = Perm.R | Perm.W | Perm.X
2544 values = list(Perm) + [RW, RX, WX, RWX, Perm(0)]
2545 for i in values:
2546 self.assertEqual(~i, ~i.value)
2547 self.assertEqual((~i).value, ~i.value)
2548 self.assertIs(type(~i), Perm)
2549 self.assertEqual(~~i, i)
2550 for i in Perm:
2551 self.assertIs(~~i, i)
2552 Open = self.Open
2553 self.assertIs(Open.WO & ~Open.WO, Open.RO)
2554 self.assertIs((Open.WO|Open.CE) & ~Open.WO, Open.CE)
2555
2556 def test_programatic_function_string(self):
Ethan Furman65a5a472016-09-01 23:55:19 -07002557 Perm = IntFlag('Perm', 'R W X')
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002558 lst = list(Perm)
2559 self.assertEqual(len(lst), len(Perm))
2560 self.assertEqual(len(Perm), 3, Perm)
2561 self.assertEqual(lst, [Perm.R, Perm.W, Perm.X])
2562 for i, n in enumerate('R W X'.split()):
2563 v = 1<<i
2564 e = Perm(v)
2565 self.assertEqual(e.value, v)
2566 self.assertEqual(type(e.value), int)
2567 self.assertEqual(e, v)
2568 self.assertEqual(e.name, n)
2569 self.assertIn(e, Perm)
2570 self.assertIs(type(e), Perm)
2571
2572 def test_programatic_function_string_with_start(self):
Ethan Furman65a5a472016-09-01 23:55:19 -07002573 Perm = IntFlag('Perm', 'R W X', start=8)
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002574 lst = list(Perm)
2575 self.assertEqual(len(lst), len(Perm))
2576 self.assertEqual(len(Perm), 3, Perm)
2577 self.assertEqual(lst, [Perm.R, Perm.W, Perm.X])
2578 for i, n in enumerate('R W X'.split()):
2579 v = 8<<i
2580 e = Perm(v)
2581 self.assertEqual(e.value, v)
2582 self.assertEqual(type(e.value), int)
2583 self.assertEqual(e, v)
2584 self.assertEqual(e.name, n)
2585 self.assertIn(e, Perm)
2586 self.assertIs(type(e), Perm)
2587
2588 def test_programatic_function_string_list(self):
Ethan Furman65a5a472016-09-01 23:55:19 -07002589 Perm = IntFlag('Perm', ['R', 'W', 'X'])
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002590 lst = list(Perm)
2591 self.assertEqual(len(lst), len(Perm))
2592 self.assertEqual(len(Perm), 3, Perm)
2593 self.assertEqual(lst, [Perm.R, Perm.W, Perm.X])
2594 for i, n in enumerate('R W X'.split()):
2595 v = 1<<i
2596 e = Perm(v)
2597 self.assertEqual(e.value, v)
2598 self.assertEqual(type(e.value), int)
2599 self.assertEqual(e, v)
2600 self.assertEqual(e.name, n)
2601 self.assertIn(e, Perm)
2602 self.assertIs(type(e), Perm)
2603
2604 def test_programatic_function_iterable(self):
Ethan Furman65a5a472016-09-01 23:55:19 -07002605 Perm = IntFlag('Perm', (('R', 2), ('W', 8), ('X', 32)))
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002606 lst = list(Perm)
2607 self.assertEqual(len(lst), len(Perm))
2608 self.assertEqual(len(Perm), 3, Perm)
2609 self.assertEqual(lst, [Perm.R, Perm.W, Perm.X])
2610 for i, n in enumerate('R W X'.split()):
2611 v = 1<<(2*i+1)
2612 e = Perm(v)
2613 self.assertEqual(e.value, v)
2614 self.assertEqual(type(e.value), int)
2615 self.assertEqual(e, v)
2616 self.assertEqual(e.name, n)
2617 self.assertIn(e, Perm)
2618 self.assertIs(type(e), Perm)
2619
2620 def test_programatic_function_from_dict(self):
Ethan Furman65a5a472016-09-01 23:55:19 -07002621 Perm = IntFlag('Perm', OrderedDict((('R', 2), ('W', 8), ('X', 32))))
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002622 lst = list(Perm)
2623 self.assertEqual(len(lst), len(Perm))
2624 self.assertEqual(len(Perm), 3, Perm)
2625 self.assertEqual(lst, [Perm.R, Perm.W, Perm.X])
2626 for i, n in enumerate('R W X'.split()):
2627 v = 1<<(2*i+1)
2628 e = Perm(v)
2629 self.assertEqual(e.value, v)
2630 self.assertEqual(type(e.value), int)
2631 self.assertEqual(e, v)
2632 self.assertEqual(e.name, n)
2633 self.assertIn(e, Perm)
2634 self.assertIs(type(e), Perm)
2635
2636
Dong-hee Nadcc8ce42017-06-22 01:52:32 +09002637 def test_programatic_function_from_empty_list(self):
2638 Perm = enum.IntFlag('Perm', [])
2639 lst = list(Perm)
2640 self.assertEqual(len(lst), len(Perm))
2641 self.assertEqual(len(Perm), 0, Perm)
2642 Thing = enum.Enum('Thing', [])
2643 lst = list(Thing)
2644 self.assertEqual(len(lst), len(Thing))
2645 self.assertEqual(len(Thing), 0, Thing)
2646
2647
2648 def test_programatic_function_from_empty_tuple(self):
2649 Perm = enum.IntFlag('Perm', ())
2650 lst = list(Perm)
2651 self.assertEqual(len(lst), len(Perm))
2652 self.assertEqual(len(Perm), 0, Perm)
2653 Thing = enum.Enum('Thing', ())
2654 self.assertEqual(len(lst), len(Thing))
2655 self.assertEqual(len(Thing), 0, Thing)
2656
Rahul Jha94306522018-09-10 23:51:04 +05302657 def test_contains(self):
2658 Open = self.Open
2659 Color = self.Color
2660 self.assertTrue(Color.GREEN in Color)
2661 self.assertTrue(Open.RW in Open)
2662 self.assertFalse(Color.GREEN in Open)
2663 self.assertFalse(Open.RW in Color)
2664 with self.assertRaises(TypeError):
2665 'GREEN' in Color
2666 with self.assertRaises(TypeError):
2667 'RW' in Open
2668 with self.assertRaises(TypeError):
2669 2 in Color
2670 with self.assertRaises(TypeError):
2671 2 in Open
2672
2673 def test_member_contains(self):
Ethan Furman65a5a472016-09-01 23:55:19 -07002674 Perm = self.Perm
2675 R, W, X = Perm
2676 RW = R | W
2677 RX = R | X
2678 WX = W | X
2679 RWX = R | W | X
2680 self.assertTrue(R in RW)
2681 self.assertTrue(R in RX)
2682 self.assertTrue(R in RWX)
2683 self.assertTrue(W in RW)
2684 self.assertTrue(W in WX)
2685 self.assertTrue(W in RWX)
2686 self.assertTrue(X in RX)
2687 self.assertTrue(X in WX)
2688 self.assertTrue(X in RWX)
2689 self.assertFalse(R in WX)
2690 self.assertFalse(W in RX)
2691 self.assertFalse(X in RW)
Rahul Jha94306522018-09-10 23:51:04 +05302692 with self.assertRaises(TypeError):
2693 self.assertFalse('test' in RW)
Ethan Furman65a5a472016-09-01 23:55:19 -07002694
Ethan Furman25d94bb2016-09-02 16:32:32 -07002695 def test_bool(self):
2696 Perm = self.Perm
2697 for f in Perm:
2698 self.assertTrue(f)
2699 Open = self.Open
2700 for f in Open:
2701 self.assertEqual(bool(f.value), bool(f))
2702
Ethan Furman5bdab642018-09-21 19:03:09 -07002703 def test_multiple_mixin(self):
2704 class AllMixin:
2705 @classproperty
2706 def ALL(cls):
2707 members = list(cls)
2708 all_value = None
2709 if members:
2710 all_value = members[0]
2711 for member in members[1:]:
2712 all_value |= member
2713 cls.ALL = all_value
2714 return all_value
2715 class StrMixin:
2716 def __str__(self):
2717 return self._name_.lower()
2718 class Color(AllMixin, IntFlag):
2719 RED = auto()
2720 GREEN = auto()
2721 BLUE = auto()
2722 self.assertEqual(Color.RED.value, 1)
2723 self.assertEqual(Color.GREEN.value, 2)
2724 self.assertEqual(Color.BLUE.value, 4)
2725 self.assertEqual(Color.ALL.value, 7)
2726 self.assertEqual(str(Color.BLUE), 'Color.BLUE')
2727 class Color(AllMixin, StrMixin, IntFlag):
2728 RED = auto()
2729 GREEN = auto()
2730 BLUE = auto()
2731 self.assertEqual(Color.RED.value, 1)
2732 self.assertEqual(Color.GREEN.value, 2)
2733 self.assertEqual(Color.BLUE.value, 4)
2734 self.assertEqual(Color.ALL.value, 7)
2735 self.assertEqual(str(Color.BLUE), 'blue')
2736 class Color(StrMixin, AllMixin, IntFlag):
2737 RED = auto()
2738 GREEN = auto()
2739 BLUE = auto()
2740 self.assertEqual(Color.RED.value, 1)
2741 self.assertEqual(Color.GREEN.value, 2)
2742 self.assertEqual(Color.BLUE.value, 4)
2743 self.assertEqual(Color.ALL.value, 7)
2744 self.assertEqual(str(Color.BLUE), 'blue')
2745
Ethan Furman28cf6632017-01-24 12:12:06 -08002746 @support.reap_threads
2747 def test_unique_composite(self):
2748 # override __eq__ to be identity only
2749 class TestFlag(IntFlag):
2750 one = auto()
2751 two = auto()
2752 three = auto()
2753 four = auto()
2754 five = auto()
2755 six = auto()
2756 seven = auto()
2757 eight = auto()
2758 def __eq__(self, other):
2759 return self is other
2760 def __hash__(self):
2761 return hash(self._value_)
2762 # have multiple threads competing to complete the composite members
2763 seen = set()
2764 failed = False
2765 def cycle_enum():
2766 nonlocal failed
2767 try:
2768 for i in range(256):
2769 seen.add(TestFlag(i))
2770 except Exception:
2771 failed = True
2772 threads = [
2773 threading.Thread(target=cycle_enum)
2774 for _ in range(8)
2775 ]
2776 with support.start_threads(threads):
2777 pass
2778 # check that only 248 members were created
2779 self.assertFalse(
2780 failed,
2781 'at least one thread failed while creating composite members')
2782 self.assertEqual(256, len(seen), 'too many composite members created')
2783
2784
Brennan D Baraban8b914d22019-03-03 14:09:11 -08002785class TestEmptyAndNonLatinStrings(unittest.TestCase):
2786
2787 def test_empty_string(self):
2788 with self.assertRaises(ValueError):
2789 empty_abc = Enum('empty_abc', ('', 'B', 'C'))
2790
2791 def test_non_latin_character_string(self):
2792 greek_abc = Enum('greek_abc', ('\u03B1', 'B', 'C'))
2793 item = getattr(greek_abc, '\u03B1')
2794 self.assertEqual(item.value, 1)
2795
2796 def test_non_latin_number_string(self):
2797 hebrew_123 = Enum('hebrew_123', ('\u05D0', '2', '3'))
2798 item = getattr(hebrew_123, '\u05D0')
2799 self.assertEqual(item.value, 1)
2800
2801
Ethan Furmanf24bb352013-07-18 17:05:39 -07002802class TestUnique(unittest.TestCase):
2803
2804 def test_unique_clean(self):
2805 @unique
2806 class Clean(Enum):
2807 one = 1
2808 two = 'dos'
2809 tres = 4.0
2810 @unique
2811 class Cleaner(IntEnum):
2812 single = 1
2813 double = 2
2814 triple = 3
2815
2816 def test_unique_dirty(self):
2817 with self.assertRaisesRegex(ValueError, 'tres.*one'):
2818 @unique
2819 class Dirty(Enum):
2820 one = 1
2821 two = 'dos'
2822 tres = 1
2823 with self.assertRaisesRegex(
2824 ValueError,
2825 'double.*single.*turkey.*triple',
2826 ):
2827 @unique
2828 class Dirtier(IntEnum):
2829 single = 1
2830 double = 1
2831 triple = 3
2832 turkey = 3
2833
Ethan Furman3803ad42016-05-01 10:03:53 -07002834 def test_unique_with_name(self):
2835 @unique
2836 class Silly(Enum):
2837 one = 1
2838 two = 'dos'
2839 name = 3
2840 @unique
2841 class Sillier(IntEnum):
2842 single = 1
2843 name = 2
2844 triple = 3
2845 value = 4
2846
Ethan Furmanf24bb352013-07-18 17:05:39 -07002847
Ethan Furman5bdab642018-09-21 19:03:09 -07002848
Ethan Furman3323da92015-04-11 09:39:59 -07002849expected_help_output_with_docs = """\
Ethan Furman5875d742013-10-21 20:45:55 -07002850Help on class Color in module %s:
2851
2852class Color(enum.Enum)
Serhiy Storchaka90f63322017-01-24 09:06:22 +02002853 | Color(value, names=None, *, module=None, qualname=None, type=None, start=1)
2854 |\x20\x20
Ethan Furman48a724f2015-04-11 23:23:06 -07002855 | An enumeration.
Serhiy Storchakab599ca82015-04-04 12:48:04 +03002856 |\x20\x20
Ethan Furman5875d742013-10-21 20:45:55 -07002857 | Method resolution order:
2858 | Color
2859 | enum.Enum
2860 | builtins.object
2861 |\x20\x20
2862 | Data and other attributes defined here:
2863 |\x20\x20
2864 | blue = <Color.blue: 3>
2865 |\x20\x20
2866 | green = <Color.green: 2>
2867 |\x20\x20
2868 | red = <Color.red: 1>
2869 |\x20\x20
2870 | ----------------------------------------------------------------------
2871 | Data descriptors inherited from enum.Enum:
2872 |\x20\x20
2873 | name
2874 | The name of the Enum member.
2875 |\x20\x20
2876 | value
2877 | The value of the Enum member.
2878 |\x20\x20
2879 | ----------------------------------------------------------------------
Raymond Hettinger62be3382019-03-24 17:07:47 -07002880 | Readonly properties inherited from enum.EnumMeta:
Ethan Furman5875d742013-10-21 20:45:55 -07002881 |\x20\x20
2882 | __members__
2883 | Returns a mapping of member name->value.
2884 |\x20\x20\x20\x20\x20\x20
2885 | This mapping lists all enum members, including aliases. Note that this
Ethan Furman3323da92015-04-11 09:39:59 -07002886 | is a read-only view of the internal mapping."""
2887
2888expected_help_output_without_docs = """\
2889Help on class Color in module %s:
2890
2891class Color(enum.Enum)
Serhiy Storchaka90f63322017-01-24 09:06:22 +02002892 | Color(value, names=None, *, module=None, qualname=None, type=None, start=1)
2893 |\x20\x20
Ethan Furman3323da92015-04-11 09:39:59 -07002894 | Method resolution order:
2895 | Color
2896 | enum.Enum
2897 | builtins.object
2898 |\x20\x20
2899 | Data and other attributes defined here:
2900 |\x20\x20
2901 | blue = <Color.blue: 3>
2902 |\x20\x20
2903 | green = <Color.green: 2>
2904 |\x20\x20
2905 | red = <Color.red: 1>
2906 |\x20\x20
2907 | ----------------------------------------------------------------------
2908 | Data descriptors inherited from enum.Enum:
2909 |\x20\x20
2910 | name
2911 |\x20\x20
2912 | value
2913 |\x20\x20
2914 | ----------------------------------------------------------------------
2915 | Data descriptors inherited from enum.EnumMeta:
2916 |\x20\x20
2917 | __members__"""
Ethan Furman5875d742013-10-21 20:45:55 -07002918
2919class TestStdLib(unittest.TestCase):
2920
Ethan Furman48a724f2015-04-11 23:23:06 -07002921 maxDiff = None
2922
Ethan Furman5875d742013-10-21 20:45:55 -07002923 class Color(Enum):
2924 red = 1
2925 green = 2
2926 blue = 3
2927
2928 def test_pydoc(self):
2929 # indirectly test __objclass__
Ethan Furman3323da92015-04-11 09:39:59 -07002930 if StrEnum.__doc__ is None:
2931 expected_text = expected_help_output_without_docs % __name__
2932 else:
2933 expected_text = expected_help_output_with_docs % __name__
Ethan Furman5875d742013-10-21 20:45:55 -07002934 output = StringIO()
2935 helper = pydoc.Helper(output=output)
2936 helper(self.Color)
2937 result = output.getvalue().strip()
Victor Stinner4b0432d2014-06-16 22:48:43 +02002938 self.assertEqual(result, expected_text)
Ethan Furman5875d742013-10-21 20:45:55 -07002939
2940 def test_inspect_getmembers(self):
2941 values = dict((
2942 ('__class__', EnumMeta),
Ethan Furman48a724f2015-04-11 23:23:06 -07002943 ('__doc__', 'An enumeration.'),
Ethan Furman5875d742013-10-21 20:45:55 -07002944 ('__members__', self.Color.__members__),
2945 ('__module__', __name__),
2946 ('blue', self.Color.blue),
2947 ('green', self.Color.green),
2948 ('name', Enum.__dict__['name']),
2949 ('red', self.Color.red),
2950 ('value', Enum.__dict__['value']),
2951 ))
2952 result = dict(inspect.getmembers(self.Color))
2953 self.assertEqual(values.keys(), result.keys())
2954 failed = False
2955 for k in values.keys():
2956 if result[k] != values[k]:
2957 print()
2958 print('\n%s\n key: %s\n result: %s\nexpected: %s\n%s\n' %
2959 ('=' * 75, k, result[k], values[k], '=' * 75), sep='')
2960 failed = True
2961 if failed:
2962 self.fail("result does not equal expected, see print above")
2963
2964 def test_inspect_classify_class_attrs(self):
2965 # indirectly test __objclass__
2966 from inspect import Attribute
2967 values = [
2968 Attribute(name='__class__', kind='data',
2969 defining_class=object, object=EnumMeta),
2970 Attribute(name='__doc__', kind='data',
Ethan Furman48a724f2015-04-11 23:23:06 -07002971 defining_class=self.Color, object='An enumeration.'),
Ethan Furman5875d742013-10-21 20:45:55 -07002972 Attribute(name='__members__', kind='property',
2973 defining_class=EnumMeta, object=EnumMeta.__members__),
2974 Attribute(name='__module__', kind='data',
2975 defining_class=self.Color, object=__name__),
2976 Attribute(name='blue', kind='data',
2977 defining_class=self.Color, object=self.Color.blue),
2978 Attribute(name='green', kind='data',
2979 defining_class=self.Color, object=self.Color.green),
2980 Attribute(name='red', kind='data',
2981 defining_class=self.Color, object=self.Color.red),
2982 Attribute(name='name', kind='data',
2983 defining_class=Enum, object=Enum.__dict__['name']),
2984 Attribute(name='value', kind='data',
2985 defining_class=Enum, object=Enum.__dict__['value']),
2986 ]
2987 values.sort(key=lambda item: item.name)
2988 result = list(inspect.classify_class_attrs(self.Color))
2989 result.sort(key=lambda item: item.name)
2990 failed = False
2991 for v, r in zip(values, result):
2992 if r != v:
2993 print('\n%s\n%s\n%s\n%s\n' % ('=' * 75, r, v, '=' * 75), sep='')
2994 failed = True
2995 if failed:
2996 self.fail("result does not equal expected, see print above")
2997
Martin Panter19e69c52015-11-14 12:46:42 +00002998
2999class MiscTestCase(unittest.TestCase):
3000 def test__all__(self):
3001 support.check__all__(self, enum)
3002
3003
Gregory P. Smith ext:(%20%5BGoogle%20Inc.%5D)6f20bd62016-06-03 19:14:52 +00003004# These are unordered here on purpose to ensure that declaration order
3005# makes no difference.
3006CONVERT_TEST_NAME_D = 5
3007CONVERT_TEST_NAME_C = 5
3008CONVERT_TEST_NAME_B = 5
3009CONVERT_TEST_NAME_A = 5 # This one should sort first.
3010CONVERT_TEST_NAME_E = 5
3011CONVERT_TEST_NAME_F = 5
3012
3013class TestIntEnumConvert(unittest.TestCase):
3014 def test_convert_value_lookup_priority(self):
orlnub1230fb9fad2018-09-12 20:28:53 +03003015 test_type = enum.IntEnum._convert_(
Ethan Furman28cf6632017-01-24 12:12:06 -08003016 'UnittestConvert',
3017 ('test.test_enum', '__main__')[__name__=='__main__'],
Gregory P. Smith ext:(%20%5BGoogle%20Inc.%5D)6f20bd62016-06-03 19:14:52 +00003018 filter=lambda x: x.startswith('CONVERT_TEST_'))
3019 # We don't want the reverse lookup value to vary when there are
3020 # multiple possible names for a given value. It should always
3021 # report the first lexigraphical name in that case.
3022 self.assertEqual(test_type(5).name, 'CONVERT_TEST_NAME_A')
3023
3024 def test_convert(self):
orlnub1230fb9fad2018-09-12 20:28:53 +03003025 test_type = enum.IntEnum._convert_(
Ethan Furman28cf6632017-01-24 12:12:06 -08003026 'UnittestConvert',
3027 ('test.test_enum', '__main__')[__name__=='__main__'],
Gregory P. Smith ext:(%20%5BGoogle%20Inc.%5D)6f20bd62016-06-03 19:14:52 +00003028 filter=lambda x: x.startswith('CONVERT_TEST_'))
3029 # Ensure that test_type has all of the desired names and values.
3030 self.assertEqual(test_type.CONVERT_TEST_NAME_F,
3031 test_type.CONVERT_TEST_NAME_A)
3032 self.assertEqual(test_type.CONVERT_TEST_NAME_B, 5)
3033 self.assertEqual(test_type.CONVERT_TEST_NAME_C, 5)
3034 self.assertEqual(test_type.CONVERT_TEST_NAME_D, 5)
3035 self.assertEqual(test_type.CONVERT_TEST_NAME_E, 5)
3036 # Ensure that test_type only picked up names matching the filter.
3037 self.assertEqual([name for name in dir(test_type)
3038 if name[0:2] not in ('CO', '__')],
3039 [], msg='Names other than CONVERT_TEST_* found.')
3040
orlnub1230fb9fad2018-09-12 20:28:53 +03003041 @unittest.skipUnless(sys.version_info[:2] == (3, 8),
3042 '_convert was deprecated in 3.8')
3043 def test_convert_warn(self):
3044 with self.assertWarns(DeprecationWarning):
3045 enum.IntEnum._convert(
3046 'UnittestConvert',
3047 ('test.test_enum', '__main__')[__name__=='__main__'],
3048 filter=lambda x: x.startswith('CONVERT_TEST_'))
3049
3050 @unittest.skipUnless(sys.version_info >= (3, 9),
3051 '_convert was removed in 3.9')
3052 def test_convert_raise(self):
3053 with self.assertRaises(AttributeError):
3054 enum.IntEnum._convert(
3055 'UnittestConvert',
3056 ('test.test_enum', '__main__')[__name__=='__main__'],
3057 filter=lambda x: x.startswith('CONVERT_TEST_'))
3058
Gregory P. Smith ext:(%20%5BGoogle%20Inc.%5D)6f20bd62016-06-03 19:14:52 +00003059
Ethan Furman6b3d64a2013-06-14 16:55:46 -07003060if __name__ == '__main__':
3061 unittest.main()