blob: ec1cfeab12d7b668398967cbf5e5d581871282b8 [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
Serhiy Storchaka7d44e7a2019-08-08 08:43:18 +030012from test.support import ALWAYS_EQ
Ethan Furmana4b1bb42018-01-22 07:56:37 -080013from datetime import timedelta
Ethan Furman28cf6632017-01-24 12:12:06 -080014
Ethan Furman6b3d64a2013-06-14 16:55:46 -070015
16# for pickle tests
17try:
18 class Stooges(Enum):
19 LARRY = 1
20 CURLY = 2
21 MOE = 3
22except Exception as exc:
23 Stooges = exc
24
25try:
26 class IntStooges(int, Enum):
27 LARRY = 1
28 CURLY = 2
29 MOE = 3
30except Exception as exc:
31 IntStooges = exc
32
33try:
34 class FloatStooges(float, Enum):
35 LARRY = 1.39
36 CURLY = 2.72
37 MOE = 3.142596
38except Exception as exc:
39 FloatStooges = exc
40
Ethan Furman65a5a472016-09-01 23:55:19 -070041try:
42 class FlagStooges(Flag):
43 LARRY = 1
44 CURLY = 2
45 MOE = 3
46except Exception as exc:
47 FlagStooges = exc
48
Ethan Furman6b3d64a2013-06-14 16:55:46 -070049# for pickle test and subclass tests
50try:
51 class StrEnum(str, Enum):
52 'accepts only string values'
53 class Name(StrEnum):
54 BDFL = 'Guido van Rossum'
55 FLUFL = 'Barry Warsaw'
56except Exception as exc:
57 Name = exc
58
59try:
60 Question = Enum('Question', 'who what when where why', module=__name__)
61except Exception as exc:
62 Question = exc
63
64try:
65 Answer = Enum('Answer', 'him this then there because')
66except Exception as exc:
67 Answer = exc
68
Ethan Furmanca1b7942014-02-08 11:36:27 -080069try:
70 Theory = Enum('Theory', 'rule law supposition', qualname='spanish_inquisition')
71except Exception as exc:
72 Theory = exc
73
Ethan Furman6b3d64a2013-06-14 16:55:46 -070074# for doctests
75try:
76 class Fruit(Enum):
Ethan Furman23bb6f42016-11-21 09:22:05 -080077 TOMATO = 1
78 BANANA = 2
79 CHERRY = 3
Ethan Furman6b3d64a2013-06-14 16:55:46 -070080except Exception:
81 pass
82
Serhiy Storchakae50e7802015-03-31 16:56:49 +030083def test_pickle_dump_load(assertion, source, target=None):
Ethan Furman2ddb39a2014-02-06 17:28:50 -080084 if target is None:
85 target = source
Serhiy Storchakae50e7802015-03-31 16:56:49 +030086 for protocol in range(HIGHEST_PROTOCOL + 1):
Ethan Furman2ddb39a2014-02-06 17:28:50 -080087 assertion(loads(dumps(source, protocol=protocol)), target)
88
Serhiy Storchakae50e7802015-03-31 16:56:49 +030089def test_pickle_exception(assertion, exception, obj):
90 for protocol in range(HIGHEST_PROTOCOL + 1):
Ethan Furman2ddb39a2014-02-06 17:28:50 -080091 with assertion(exception):
92 dumps(obj, protocol=protocol)
Ethan Furman648f8602013-10-06 17:19:54 -070093
94class TestHelpers(unittest.TestCase):
95 # _is_descriptor, _is_sunder, _is_dunder
96
97 def test_is_descriptor(self):
98 class foo:
99 pass
100 for attr in ('__get__','__set__','__delete__'):
101 obj = foo()
102 self.assertFalse(enum._is_descriptor(obj))
103 setattr(obj, attr, 1)
104 self.assertTrue(enum._is_descriptor(obj))
105
106 def test_is_sunder(self):
107 for s in ('_a_', '_aa_'):
108 self.assertTrue(enum._is_sunder(s))
109
110 for s in ('a', 'a_', '_a', '__a', 'a__', '__a__', '_a__', '__a_', '_',
111 '__', '___', '____', '_____',):
112 self.assertFalse(enum._is_sunder(s))
113
114 def test_is_dunder(self):
115 for s in ('__a__', '__aa__'):
116 self.assertTrue(enum._is_dunder(s))
117 for s in ('a', 'a_', '_a', '__a', 'a__', '_a_', '_a__', '__a_', '_',
118 '__', '___', '____', '_____',):
119 self.assertFalse(enum._is_dunder(s))
120
Ethan Furman5bdab642018-09-21 19:03:09 -0700121# for subclassing tests
122
123class classproperty:
124
125 def __init__(self, fget=None, fset=None, fdel=None, doc=None):
126 self.fget = fget
127 self.fset = fset
128 self.fdel = fdel
129 if doc is None and fget is not None:
130 doc = fget.__doc__
131 self.__doc__ = doc
132
133 def __get__(self, instance, ownerclass):
134 return self.fget(ownerclass)
135
136
Ethan Furmanc16595e2016-09-10 23:36:59 -0700137# tests
Ethan Furman648f8602013-10-06 17:19:54 -0700138
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700139class TestEnum(unittest.TestCase):
Ethan Furmanca1b7942014-02-08 11:36:27 -0800140
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700141 def setUp(self):
142 class Season(Enum):
143 SPRING = 1
144 SUMMER = 2
145 AUTUMN = 3
146 WINTER = 4
147 self.Season = Season
148
Ethan Furmanec15a822013-08-31 19:17:41 -0700149 class Konstants(float, Enum):
150 E = 2.7182818
151 PI = 3.1415926
152 TAU = 2 * PI
153 self.Konstants = Konstants
154
155 class Grades(IntEnum):
156 A = 5
157 B = 4
158 C = 3
159 D = 2
160 F = 0
161 self.Grades = Grades
162
163 class Directional(str, Enum):
164 EAST = 'east'
165 WEST = 'west'
166 NORTH = 'north'
167 SOUTH = 'south'
168 self.Directional = Directional
169
170 from datetime import date
171 class Holiday(date, Enum):
172 NEW_YEAR = 2013, 1, 1
173 IDES_OF_MARCH = 2013, 3, 15
174 self.Holiday = Holiday
175
Ethan Furman388a3922013-08-12 06:51:41 -0700176 def test_dir_on_class(self):
177 Season = self.Season
178 self.assertEqual(
179 set(dir(Season)),
Ethan Furmanc850f342013-09-15 16:59:35 -0700180 set(['__class__', '__doc__', '__members__', '__module__',
Ethan Furman388a3922013-08-12 06:51:41 -0700181 'SPRING', 'SUMMER', 'AUTUMN', 'WINTER']),
182 )
183
184 def test_dir_on_item(self):
185 Season = self.Season
186 self.assertEqual(
187 set(dir(Season.WINTER)),
Ethan Furmanc850f342013-09-15 16:59:35 -0700188 set(['__class__', '__doc__', '__module__', 'name', 'value']),
Ethan Furman388a3922013-08-12 06:51:41 -0700189 )
190
Ethan Furmanc850f342013-09-15 16:59:35 -0700191 def test_dir_with_added_behavior(self):
192 class Test(Enum):
193 this = 'that'
194 these = 'those'
195 def wowser(self):
196 return ("Wowser! I'm %s!" % self.name)
197 self.assertEqual(
198 set(dir(Test)),
199 set(['__class__', '__doc__', '__members__', '__module__', 'this', 'these']),
200 )
201 self.assertEqual(
202 set(dir(Test.this)),
203 set(['__class__', '__doc__', '__module__', 'name', 'value', 'wowser']),
204 )
205
Ethan Furman0ae550b2014-10-14 08:58:32 -0700206 def test_dir_on_sub_with_behavior_on_super(self):
207 # see issue22506
208 class SuperEnum(Enum):
209 def invisible(self):
210 return "did you see me?"
211 class SubEnum(SuperEnum):
212 sample = 5
213 self.assertEqual(
214 set(dir(SubEnum.sample)),
215 set(['__class__', '__doc__', '__module__', 'name', 'value', 'invisible']),
216 )
217
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700218 def test_enum_in_enum_out(self):
219 Season = self.Season
220 self.assertIs(Season(Season.WINTER), Season.WINTER)
221
222 def test_enum_value(self):
223 Season = self.Season
224 self.assertEqual(Season.SPRING.value, 1)
225
226 def test_intenum_value(self):
227 self.assertEqual(IntStooges.CURLY.value, 2)
228
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700229 def test_enum(self):
230 Season = self.Season
231 lst = list(Season)
232 self.assertEqual(len(lst), len(Season))
233 self.assertEqual(len(Season), 4, Season)
234 self.assertEqual(
235 [Season.SPRING, Season.SUMMER, Season.AUTUMN, Season.WINTER], lst)
236
237 for i, season in enumerate('SPRING SUMMER AUTUMN WINTER'.split(), 1):
238 e = Season(i)
239 self.assertEqual(e, getattr(Season, season))
240 self.assertEqual(e.value, i)
241 self.assertNotEqual(e, i)
242 self.assertEqual(e.name, season)
243 self.assertIn(e, Season)
244 self.assertIs(type(e), Season)
245 self.assertIsInstance(e, Season)
246 self.assertEqual(str(e), 'Season.' + season)
247 self.assertEqual(
248 repr(e),
249 '<Season.{0}: {1}>'.format(season, i),
250 )
251
252 def test_value_name(self):
253 Season = self.Season
254 self.assertEqual(Season.SPRING.name, 'SPRING')
255 self.assertEqual(Season.SPRING.value, 1)
256 with self.assertRaises(AttributeError):
257 Season.SPRING.name = 'invierno'
258 with self.assertRaises(AttributeError):
259 Season.SPRING.value = 2
260
Ethan Furmanf203f2d2013-09-06 07:16:48 -0700261 def test_changing_member(self):
262 Season = self.Season
263 with self.assertRaises(AttributeError):
264 Season.WINTER = 'really cold'
265
Ethan Furman64a99722013-09-22 16:18:19 -0700266 def test_attribute_deletion(self):
267 class Season(Enum):
268 SPRING = 1
269 SUMMER = 2
270 AUTUMN = 3
271 WINTER = 4
272
273 def spam(cls):
274 pass
275
276 self.assertTrue(hasattr(Season, 'spam'))
277 del Season.spam
278 self.assertFalse(hasattr(Season, 'spam'))
279
280 with self.assertRaises(AttributeError):
281 del Season.SPRING
282 with self.assertRaises(AttributeError):
283 del Season.DRY
284 with self.assertRaises(AttributeError):
285 del Season.SPRING.name
286
Ethan Furman5de67b12016-04-13 23:52:09 -0700287 def test_bool_of_class(self):
288 class Empty(Enum):
289 pass
290 self.assertTrue(bool(Empty))
291
292 def test_bool_of_member(self):
293 class Count(Enum):
294 zero = 0
295 one = 1
296 two = 2
297 for member in Count:
298 self.assertTrue(bool(member))
299
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700300 def test_invalid_names(self):
301 with self.assertRaises(ValueError):
302 class Wrong(Enum):
303 mro = 9
304 with self.assertRaises(ValueError):
305 class Wrong(Enum):
306 _create_= 11
307 with self.assertRaises(ValueError):
308 class Wrong(Enum):
309 _get_mixins_ = 9
310 with self.assertRaises(ValueError):
311 class Wrong(Enum):
312 _find_new_ = 1
313 with self.assertRaises(ValueError):
314 class Wrong(Enum):
315 _any_name_ = 9
316
Ethan Furman6db1fd52015-09-17 21:49:12 -0700317 def test_bool(self):
Ethan Furman60255b62016-01-15 15:01:33 -0800318 # plain Enum members are always True
Ethan Furman6db1fd52015-09-17 21:49:12 -0700319 class Logic(Enum):
320 true = True
321 false = False
322 self.assertTrue(Logic.true)
Ethan Furman60255b62016-01-15 15:01:33 -0800323 self.assertTrue(Logic.false)
324 # unless overridden
325 class RealLogic(Enum):
326 true = True
327 false = False
328 def __bool__(self):
329 return bool(self._value_)
330 self.assertTrue(RealLogic.true)
331 self.assertFalse(RealLogic.false)
332 # mixed Enums depend on mixed-in type
333 class IntLogic(int, Enum):
334 true = 1
335 false = 0
336 self.assertTrue(IntLogic.true)
337 self.assertFalse(IntLogic.false)
Ethan Furman6db1fd52015-09-17 21:49:12 -0700338
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700339 def test_contains(self):
340 Season = self.Season
341 self.assertIn(Season.AUTUMN, Season)
Rahul Jha94306522018-09-10 23:51:04 +0530342 with self.assertRaises(TypeError):
343 3 in Season
344 with self.assertRaises(TypeError):
345 'AUTUMN' in Season
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700346
347 val = Season(3)
348 self.assertIn(val, Season)
349
350 class OtherEnum(Enum):
351 one = 1; two = 2
352 self.assertNotIn(OtherEnum.two, Season)
353
354 def test_comparisons(self):
355 Season = self.Season
356 with self.assertRaises(TypeError):
357 Season.SPRING < Season.WINTER
358 with self.assertRaises(TypeError):
359 Season.SPRING > 4
360
361 self.assertNotEqual(Season.SPRING, 1)
362
363 class Part(Enum):
364 SPRING = 1
365 CLIP = 2
366 BARREL = 3
367
368 self.assertNotEqual(Season.SPRING, Part.SPRING)
369 with self.assertRaises(TypeError):
370 Season.SPRING < Part.CLIP
371
372 def test_enum_duplicates(self):
373 class Season(Enum):
374 SPRING = 1
375 SUMMER = 2
376 AUTUMN = FALL = 3
377 WINTER = 4
378 ANOTHER_SPRING = 1
379 lst = list(Season)
380 self.assertEqual(
381 lst,
382 [Season.SPRING, Season.SUMMER,
383 Season.AUTUMN, Season.WINTER,
384 ])
385 self.assertIs(Season.FALL, Season.AUTUMN)
386 self.assertEqual(Season.FALL.value, 3)
387 self.assertEqual(Season.AUTUMN.value, 3)
388 self.assertIs(Season(3), Season.AUTUMN)
389 self.assertIs(Season(1), Season.SPRING)
390 self.assertEqual(Season.FALL.name, 'AUTUMN')
391 self.assertEqual(
392 [k for k,v in Season.__members__.items() if v.name != k],
393 ['FALL', 'ANOTHER_SPRING'],
394 )
395
Ethan Furman101e0742013-09-15 12:34:36 -0700396 def test_duplicate_name(self):
397 with self.assertRaises(TypeError):
398 class Color(Enum):
399 red = 1
400 green = 2
401 blue = 3
402 red = 4
403
404 with self.assertRaises(TypeError):
405 class Color(Enum):
406 red = 1
407 green = 2
408 blue = 3
409 def red(self):
410 return 'red'
411
412 with self.assertRaises(TypeError):
413 class Color(Enum):
414 @property
415 def red(self):
416 return 'redder'
417 red = 1
418 green = 2
419 blue = 3
420
421
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700422 def test_enum_with_value_name(self):
423 class Huh(Enum):
424 name = 1
425 value = 2
426 self.assertEqual(
427 list(Huh),
428 [Huh.name, Huh.value],
429 )
430 self.assertIs(type(Huh.name), Huh)
431 self.assertEqual(Huh.name.name, 'name')
432 self.assertEqual(Huh.name.value, 1)
Ethan Furmanec15a822013-08-31 19:17:41 -0700433
434 def test_format_enum(self):
435 Season = self.Season
436 self.assertEqual('{}'.format(Season.SPRING),
437 '{}'.format(str(Season.SPRING)))
438 self.assertEqual( '{:}'.format(Season.SPRING),
439 '{:}'.format(str(Season.SPRING)))
440 self.assertEqual('{:20}'.format(Season.SPRING),
441 '{:20}'.format(str(Season.SPRING)))
442 self.assertEqual('{:^20}'.format(Season.SPRING),
443 '{:^20}'.format(str(Season.SPRING)))
444 self.assertEqual('{:>20}'.format(Season.SPRING),
445 '{:>20}'.format(str(Season.SPRING)))
446 self.assertEqual('{:<20}'.format(Season.SPRING),
447 '{:<20}'.format(str(Season.SPRING)))
448
thatneat2f19e822019-07-04 11:28:37 -0700449 def test_str_override_enum(self):
450 class EnumWithStrOverrides(Enum):
451 one = auto()
452 two = auto()
453
454 def __str__(self):
455 return 'Str!'
456 self.assertEqual(str(EnumWithStrOverrides.one), 'Str!')
457 self.assertEqual('{}'.format(EnumWithStrOverrides.one), 'Str!')
458
459 def test_format_override_enum(self):
460 class EnumWithFormatOverride(Enum):
461 one = 1.0
462 two = 2.0
463 def __format__(self, spec):
464 return 'Format!!'
465 self.assertEqual(str(EnumWithFormatOverride.one), 'EnumWithFormatOverride.one')
466 self.assertEqual('{}'.format(EnumWithFormatOverride.one), 'Format!!')
467
468 def test_str_and_format_override_enum(self):
469 class EnumWithStrFormatOverrides(Enum):
470 one = auto()
471 two = auto()
472 def __str__(self):
473 return 'Str!'
474 def __format__(self, spec):
475 return 'Format!'
476 self.assertEqual(str(EnumWithStrFormatOverrides.one), 'Str!')
477 self.assertEqual('{}'.format(EnumWithStrFormatOverrides.one), 'Format!')
478
479 def test_str_override_mixin(self):
480 class MixinEnumWithStrOverride(float, Enum):
481 one = 1.0
482 two = 2.0
483 def __str__(self):
484 return 'Overridden!'
485 self.assertEqual(str(MixinEnumWithStrOverride.one), 'Overridden!')
486 self.assertEqual('{}'.format(MixinEnumWithStrOverride.one), 'Overridden!')
487
488 def test_str_and_format_override_mixin(self):
489 class MixinWithStrFormatOverrides(float, Enum):
490 one = 1.0
491 two = 2.0
492 def __str__(self):
493 return 'Str!'
494 def __format__(self, spec):
495 return 'Format!'
496 self.assertEqual(str(MixinWithStrFormatOverrides.one), 'Str!')
497 self.assertEqual('{}'.format(MixinWithStrFormatOverrides.one), 'Format!')
498
499 def test_format_override_mixin(self):
Ethan Furmanec15a822013-08-31 19:17:41 -0700500 class TestFloat(float, Enum):
501 one = 1.0
502 two = 2.0
503 def __format__(self, spec):
504 return 'TestFloat success!'
thatneat2f19e822019-07-04 11:28:37 -0700505 self.assertEqual(str(TestFloat.one), 'TestFloat.one')
Ethan Furmanec15a822013-08-31 19:17:41 -0700506 self.assertEqual('{}'.format(TestFloat.one), 'TestFloat success!')
507
508 def assertFormatIsValue(self, spec, member):
509 self.assertEqual(spec.format(member), spec.format(member.value))
510
511 def test_format_enum_date(self):
512 Holiday = self.Holiday
513 self.assertFormatIsValue('{}', Holiday.IDES_OF_MARCH)
514 self.assertFormatIsValue('{:}', 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('{:<20}', Holiday.IDES_OF_MARCH)
519 self.assertFormatIsValue('{:%Y %m}', Holiday.IDES_OF_MARCH)
520 self.assertFormatIsValue('{:%Y %m %M:00}', Holiday.IDES_OF_MARCH)
521
522 def test_format_enum_float(self):
523 Konstants = self.Konstants
524 self.assertFormatIsValue('{}', Konstants.TAU)
525 self.assertFormatIsValue('{:}', Konstants.TAU)
526 self.assertFormatIsValue('{:20}', Konstants.TAU)
527 self.assertFormatIsValue('{:^20}', Konstants.TAU)
528 self.assertFormatIsValue('{:>20}', Konstants.TAU)
529 self.assertFormatIsValue('{:<20}', Konstants.TAU)
530 self.assertFormatIsValue('{:n}', Konstants.TAU)
531 self.assertFormatIsValue('{:5.2}', Konstants.TAU)
532 self.assertFormatIsValue('{:f}', Konstants.TAU)
533
534 def test_format_enum_int(self):
535 Grades = self.Grades
536 self.assertFormatIsValue('{}', Grades.C)
537 self.assertFormatIsValue('{:}', Grades.C)
538 self.assertFormatIsValue('{:20}', Grades.C)
539 self.assertFormatIsValue('{:^20}', Grades.C)
540 self.assertFormatIsValue('{:>20}', Grades.C)
541 self.assertFormatIsValue('{:<20}', Grades.C)
542 self.assertFormatIsValue('{:+}', Grades.C)
543 self.assertFormatIsValue('{:08X}', Grades.C)
544 self.assertFormatIsValue('{:b}', Grades.C)
545
546 def test_format_enum_str(self):
547 Directional = self.Directional
548 self.assertFormatIsValue('{}', Directional.WEST)
549 self.assertFormatIsValue('{:}', Directional.WEST)
550 self.assertFormatIsValue('{:20}', Directional.WEST)
551 self.assertFormatIsValue('{:^20}', Directional.WEST)
552 self.assertFormatIsValue('{:>20}', Directional.WEST)
553 self.assertFormatIsValue('{:<20}', Directional.WEST)
554
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700555 def test_hash(self):
556 Season = self.Season
557 dates = {}
558 dates[Season.WINTER] = '1225'
559 dates[Season.SPRING] = '0315'
560 dates[Season.SUMMER] = '0704'
561 dates[Season.AUTUMN] = '1031'
562 self.assertEqual(dates[Season.AUTUMN], '1031')
563
564 def test_intenum_from_scratch(self):
565 class phy(int, Enum):
566 pi = 3
567 tau = 2 * pi
568 self.assertTrue(phy.pi < phy.tau)
569
570 def test_intenum_inherited(self):
571 class IntEnum(int, Enum):
572 pass
573 class phy(IntEnum):
574 pi = 3
575 tau = 2 * pi
576 self.assertTrue(phy.pi < phy.tau)
577
578 def test_floatenum_from_scratch(self):
579 class phy(float, Enum):
Ethan Furmanec15a822013-08-31 19:17:41 -0700580 pi = 3.1415926
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700581 tau = 2 * pi
582 self.assertTrue(phy.pi < phy.tau)
583
584 def test_floatenum_inherited(self):
585 class FloatEnum(float, Enum):
586 pass
587 class phy(FloatEnum):
Ethan Furmanec15a822013-08-31 19:17:41 -0700588 pi = 3.1415926
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700589 tau = 2 * pi
590 self.assertTrue(phy.pi < phy.tau)
591
592 def test_strenum_from_scratch(self):
593 class phy(str, Enum):
594 pi = 'Pi'
595 tau = 'Tau'
596 self.assertTrue(phy.pi < phy.tau)
597
598 def test_strenum_inherited(self):
599 class StrEnum(str, Enum):
600 pass
601 class phy(StrEnum):
602 pi = 'Pi'
603 tau = 'Tau'
604 self.assertTrue(phy.pi < phy.tau)
605
606
607 def test_intenum(self):
608 class WeekDay(IntEnum):
609 SUNDAY = 1
610 MONDAY = 2
611 TUESDAY = 3
612 WEDNESDAY = 4
613 THURSDAY = 5
614 FRIDAY = 6
615 SATURDAY = 7
616
617 self.assertEqual(['a', 'b', 'c'][WeekDay.MONDAY], 'c')
618 self.assertEqual([i for i in range(WeekDay.TUESDAY)], [0, 1, 2])
619
620 lst = list(WeekDay)
621 self.assertEqual(len(lst), len(WeekDay))
622 self.assertEqual(len(WeekDay), 7)
623 target = 'SUNDAY MONDAY TUESDAY WEDNESDAY THURSDAY FRIDAY SATURDAY'
624 target = target.split()
625 for i, weekday in enumerate(target, 1):
626 e = WeekDay(i)
627 self.assertEqual(e, i)
628 self.assertEqual(int(e), i)
629 self.assertEqual(e.name, weekday)
630 self.assertIn(e, WeekDay)
631 self.assertEqual(lst.index(e)+1, i)
632 self.assertTrue(0 < e < 8)
633 self.assertIs(type(e), WeekDay)
634 self.assertIsInstance(e, int)
635 self.assertIsInstance(e, Enum)
636
637 def test_intenum_duplicates(self):
638 class WeekDay(IntEnum):
639 SUNDAY = 1
640 MONDAY = 2
641 TUESDAY = TEUSDAY = 3
642 WEDNESDAY = 4
643 THURSDAY = 5
644 FRIDAY = 6
645 SATURDAY = 7
646 self.assertIs(WeekDay.TEUSDAY, WeekDay.TUESDAY)
647 self.assertEqual(WeekDay(3).name, 'TUESDAY')
648 self.assertEqual([k for k,v in WeekDay.__members__.items()
649 if v.name != k], ['TEUSDAY', ])
650
Serhiy Storchakaea36c942016-05-12 10:37:58 +0300651 def test_intenum_from_bytes(self):
652 self.assertIs(IntStooges.from_bytes(b'\x00\x03', 'big'), IntStooges.MOE)
653 with self.assertRaises(ValueError):
654 IntStooges.from_bytes(b'\x00\x05', 'big')
655
656 def test_floatenum_fromhex(self):
657 h = float.hex(FloatStooges.MOE.value)
658 self.assertIs(FloatStooges.fromhex(h), FloatStooges.MOE)
659 h = float.hex(FloatStooges.MOE.value + 0.01)
660 with self.assertRaises(ValueError):
661 FloatStooges.fromhex(h)
662
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700663 def test_pickle_enum(self):
664 if isinstance(Stooges, Exception):
665 raise Stooges
Ethan Furman2ddb39a2014-02-06 17:28:50 -0800666 test_pickle_dump_load(self.assertIs, Stooges.CURLY)
667 test_pickle_dump_load(self.assertIs, Stooges)
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700668
669 def test_pickle_int(self):
670 if isinstance(IntStooges, Exception):
671 raise IntStooges
Ethan Furman2ddb39a2014-02-06 17:28:50 -0800672 test_pickle_dump_load(self.assertIs, IntStooges.CURLY)
673 test_pickle_dump_load(self.assertIs, IntStooges)
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700674
675 def test_pickle_float(self):
676 if isinstance(FloatStooges, Exception):
677 raise FloatStooges
Ethan Furman2ddb39a2014-02-06 17:28:50 -0800678 test_pickle_dump_load(self.assertIs, FloatStooges.CURLY)
679 test_pickle_dump_load(self.assertIs, FloatStooges)
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700680
681 def test_pickle_enum_function(self):
682 if isinstance(Answer, Exception):
683 raise Answer
Ethan Furman2ddb39a2014-02-06 17:28:50 -0800684 test_pickle_dump_load(self.assertIs, Answer.him)
685 test_pickle_dump_load(self.assertIs, Answer)
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700686
687 def test_pickle_enum_function_with_module(self):
688 if isinstance(Question, Exception):
689 raise Question
Ethan Furman2ddb39a2014-02-06 17:28:50 -0800690 test_pickle_dump_load(self.assertIs, Question.who)
691 test_pickle_dump_load(self.assertIs, Question)
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700692
Ethan Furmanca1b7942014-02-08 11:36:27 -0800693 def test_enum_function_with_qualname(self):
694 if isinstance(Theory, Exception):
695 raise Theory
696 self.assertEqual(Theory.__qualname__, 'spanish_inquisition')
697
698 def test_class_nested_enum_and_pickle_protocol_four(self):
699 # would normally just have this directly in the class namespace
700 class NestedEnum(Enum):
701 twigs = 'common'
702 shiny = 'rare'
703
704 self.__class__.NestedEnum = NestedEnum
705 self.NestedEnum.__qualname__ = '%s.NestedEnum' % self.__class__.__name__
Serhiy Storchakae50e7802015-03-31 16:56:49 +0300706 test_pickle_dump_load(self.assertIs, self.NestedEnum.twigs)
Ethan Furmanca1b7942014-02-08 11:36:27 -0800707
Ethan Furman24e837f2015-03-18 17:27:57 -0700708 def test_pickle_by_name(self):
709 class ReplaceGlobalInt(IntEnum):
710 ONE = 1
711 TWO = 2
712 ReplaceGlobalInt.__reduce_ex__ = enum._reduce_ex_by_name
713 for proto in range(HIGHEST_PROTOCOL):
714 self.assertEqual(ReplaceGlobalInt.TWO.__reduce_ex__(proto), 'TWO')
715
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700716 def test_exploding_pickle(self):
Ethan Furmanca1b7942014-02-08 11:36:27 -0800717 BadPickle = Enum(
718 'BadPickle', 'dill sweet bread-n-butter', module=__name__)
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700719 globals()['BadPickle'] = BadPickle
Ethan Furmanca1b7942014-02-08 11:36:27 -0800720 # now break BadPickle to test exception raising
721 enum._make_class_unpicklable(BadPickle)
Ethan Furman2ddb39a2014-02-06 17:28:50 -0800722 test_pickle_exception(self.assertRaises, TypeError, BadPickle.dill)
723 test_pickle_exception(self.assertRaises, PicklingError, BadPickle)
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700724
725 def test_string_enum(self):
726 class SkillLevel(str, Enum):
727 master = 'what is the sound of one hand clapping?'
728 journeyman = 'why did the chicken cross the road?'
729 apprentice = 'knock, knock!'
730 self.assertEqual(SkillLevel.apprentice, 'knock, knock!')
731
732 def test_getattr_getitem(self):
733 class Period(Enum):
734 morning = 1
735 noon = 2
736 evening = 3
737 night = 4
738 self.assertIs(Period(2), Period.noon)
739 self.assertIs(getattr(Period, 'night'), Period.night)
740 self.assertIs(Period['morning'], Period.morning)
741
742 def test_getattr_dunder(self):
743 Season = self.Season
744 self.assertTrue(getattr(Season, '__eq__'))
745
746 def test_iteration_order(self):
747 class Season(Enum):
748 SUMMER = 2
749 WINTER = 4
750 AUTUMN = 3
751 SPRING = 1
752 self.assertEqual(
753 list(Season),
754 [Season.SUMMER, Season.WINTER, Season.AUTUMN, Season.SPRING],
755 )
756
Ethan Furman2131a4a2013-09-14 18:11:24 -0700757 def test_reversed_iteration_order(self):
758 self.assertEqual(
759 list(reversed(self.Season)),
760 [self.Season.WINTER, self.Season.AUTUMN, self.Season.SUMMER,
761 self.Season.SPRING]
762 )
763
Martin Pantereb995702016-07-28 01:11:04 +0000764 def test_programmatic_function_string(self):
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700765 SummerMonth = Enum('SummerMonth', 'june july august')
766 lst = list(SummerMonth)
767 self.assertEqual(len(lst), len(SummerMonth))
768 self.assertEqual(len(SummerMonth), 3, SummerMonth)
769 self.assertEqual(
770 [SummerMonth.june, SummerMonth.july, SummerMonth.august],
771 lst,
772 )
773 for i, month in enumerate('june july august'.split(), 1):
774 e = SummerMonth(i)
775 self.assertEqual(int(e.value), i)
776 self.assertNotEqual(e, i)
777 self.assertEqual(e.name, month)
778 self.assertIn(e, SummerMonth)
779 self.assertIs(type(e), SummerMonth)
780
Martin Pantereb995702016-07-28 01:11:04 +0000781 def test_programmatic_function_string_with_start(self):
Ethan Furmand9925a12014-09-16 20:35:55 -0700782 SummerMonth = Enum('SummerMonth', 'june july august', start=10)
783 lst = list(SummerMonth)
784 self.assertEqual(len(lst), len(SummerMonth))
785 self.assertEqual(len(SummerMonth), 3, SummerMonth)
786 self.assertEqual(
787 [SummerMonth.june, SummerMonth.july, SummerMonth.august],
788 lst,
789 )
790 for i, month in enumerate('june july august'.split(), 10):
791 e = SummerMonth(i)
792 self.assertEqual(int(e.value), i)
793 self.assertNotEqual(e, i)
794 self.assertEqual(e.name, month)
795 self.assertIn(e, SummerMonth)
796 self.assertIs(type(e), SummerMonth)
797
Martin Pantereb995702016-07-28 01:11:04 +0000798 def test_programmatic_function_string_list(self):
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700799 SummerMonth = Enum('SummerMonth', ['june', 'july', 'august'])
800 lst = list(SummerMonth)
801 self.assertEqual(len(lst), len(SummerMonth))
802 self.assertEqual(len(SummerMonth), 3, SummerMonth)
803 self.assertEqual(
804 [SummerMonth.june, SummerMonth.july, SummerMonth.august],
805 lst,
806 )
807 for i, month in enumerate('june july august'.split(), 1):
808 e = SummerMonth(i)
809 self.assertEqual(int(e.value), i)
810 self.assertNotEqual(e, i)
811 self.assertEqual(e.name, month)
812 self.assertIn(e, SummerMonth)
813 self.assertIs(type(e), SummerMonth)
814
Martin Pantereb995702016-07-28 01:11:04 +0000815 def test_programmatic_function_string_list_with_start(self):
Ethan Furmand9925a12014-09-16 20:35:55 -0700816 SummerMonth = Enum('SummerMonth', ['june', 'july', 'august'], start=20)
817 lst = list(SummerMonth)
818 self.assertEqual(len(lst), len(SummerMonth))
819 self.assertEqual(len(SummerMonth), 3, SummerMonth)
820 self.assertEqual(
821 [SummerMonth.june, SummerMonth.july, SummerMonth.august],
822 lst,
823 )
824 for i, month in enumerate('june july august'.split(), 20):
825 e = SummerMonth(i)
826 self.assertEqual(int(e.value), i)
827 self.assertNotEqual(e, i)
828 self.assertEqual(e.name, month)
829 self.assertIn(e, SummerMonth)
830 self.assertIs(type(e), SummerMonth)
831
Martin Pantereb995702016-07-28 01:11:04 +0000832 def test_programmatic_function_iterable(self):
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700833 SummerMonth = Enum(
834 'SummerMonth',
835 (('june', 1), ('july', 2), ('august', 3))
836 )
837 lst = list(SummerMonth)
838 self.assertEqual(len(lst), len(SummerMonth))
839 self.assertEqual(len(SummerMonth), 3, SummerMonth)
840 self.assertEqual(
841 [SummerMonth.june, SummerMonth.july, SummerMonth.august],
842 lst,
843 )
844 for i, month in enumerate('june july august'.split(), 1):
845 e = SummerMonth(i)
846 self.assertEqual(int(e.value), i)
847 self.assertNotEqual(e, i)
848 self.assertEqual(e.name, month)
849 self.assertIn(e, SummerMonth)
850 self.assertIs(type(e), SummerMonth)
851
Martin Pantereb995702016-07-28 01:11:04 +0000852 def test_programmatic_function_from_dict(self):
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700853 SummerMonth = Enum(
854 'SummerMonth',
855 OrderedDict((('june', 1), ('july', 2), ('august', 3)))
856 )
857 lst = list(SummerMonth)
858 self.assertEqual(len(lst), len(SummerMonth))
859 self.assertEqual(len(SummerMonth), 3, SummerMonth)
860 self.assertEqual(
861 [SummerMonth.june, SummerMonth.july, SummerMonth.august],
862 lst,
863 )
864 for i, month in enumerate('june july august'.split(), 1):
865 e = SummerMonth(i)
866 self.assertEqual(int(e.value), i)
867 self.assertNotEqual(e, i)
868 self.assertEqual(e.name, month)
869 self.assertIn(e, SummerMonth)
870 self.assertIs(type(e), SummerMonth)
871
Martin Pantereb995702016-07-28 01:11:04 +0000872 def test_programmatic_function_type(self):
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700873 SummerMonth = Enum('SummerMonth', 'june july august', type=int)
874 lst = list(SummerMonth)
875 self.assertEqual(len(lst), len(SummerMonth))
876 self.assertEqual(len(SummerMonth), 3, SummerMonth)
877 self.assertEqual(
878 [SummerMonth.june, SummerMonth.july, SummerMonth.august],
879 lst,
880 )
881 for i, month in enumerate('june july august'.split(), 1):
882 e = SummerMonth(i)
883 self.assertEqual(e, i)
884 self.assertEqual(e.name, month)
885 self.assertIn(e, SummerMonth)
886 self.assertIs(type(e), SummerMonth)
887
Martin Pantereb995702016-07-28 01:11:04 +0000888 def test_programmatic_function_type_with_start(self):
Ethan Furmand9925a12014-09-16 20:35:55 -0700889 SummerMonth = Enum('SummerMonth', 'june july august', type=int, start=30)
890 lst = list(SummerMonth)
891 self.assertEqual(len(lst), len(SummerMonth))
892 self.assertEqual(len(SummerMonth), 3, SummerMonth)
893 self.assertEqual(
894 [SummerMonth.june, SummerMonth.july, SummerMonth.august],
895 lst,
896 )
897 for i, month in enumerate('june july august'.split(), 30):
898 e = SummerMonth(i)
899 self.assertEqual(e, i)
900 self.assertEqual(e.name, month)
901 self.assertIn(e, SummerMonth)
902 self.assertIs(type(e), SummerMonth)
903
Martin Pantereb995702016-07-28 01:11:04 +0000904 def test_programmatic_function_type_from_subclass(self):
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700905 SummerMonth = IntEnum('SummerMonth', 'june july august')
906 lst = list(SummerMonth)
907 self.assertEqual(len(lst), len(SummerMonth))
908 self.assertEqual(len(SummerMonth), 3, SummerMonth)
909 self.assertEqual(
910 [SummerMonth.june, SummerMonth.july, SummerMonth.august],
911 lst,
912 )
913 for i, month in enumerate('june july august'.split(), 1):
914 e = SummerMonth(i)
915 self.assertEqual(e, i)
916 self.assertEqual(e.name, month)
917 self.assertIn(e, SummerMonth)
918 self.assertIs(type(e), SummerMonth)
919
Martin Pantereb995702016-07-28 01:11:04 +0000920 def test_programmatic_function_type_from_subclass_with_start(self):
Ethan Furmand9925a12014-09-16 20:35:55 -0700921 SummerMonth = IntEnum('SummerMonth', 'june july august', start=40)
922 lst = list(SummerMonth)
923 self.assertEqual(len(lst), len(SummerMonth))
924 self.assertEqual(len(SummerMonth), 3, SummerMonth)
925 self.assertEqual(
926 [SummerMonth.june, SummerMonth.july, SummerMonth.august],
927 lst,
928 )
929 for i, month in enumerate('june july august'.split(), 40):
930 e = SummerMonth(i)
931 self.assertEqual(e, i)
932 self.assertEqual(e.name, month)
933 self.assertIn(e, SummerMonth)
934 self.assertIs(type(e), SummerMonth)
935
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700936 def test_subclassing(self):
937 if isinstance(Name, Exception):
938 raise Name
939 self.assertEqual(Name.BDFL, 'Guido van Rossum')
940 self.assertTrue(Name.BDFL, Name('Guido van Rossum'))
941 self.assertIs(Name.BDFL, getattr(Name, 'BDFL'))
Ethan Furman2ddb39a2014-02-06 17:28:50 -0800942 test_pickle_dump_load(self.assertIs, Name.BDFL)
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700943
944 def test_extending(self):
945 class Color(Enum):
946 red = 1
947 green = 2
948 blue = 3
949 with self.assertRaises(TypeError):
950 class MoreColor(Color):
951 cyan = 4
952 magenta = 5
953 yellow = 6
954
955 def test_exclude_methods(self):
956 class whatever(Enum):
957 this = 'that'
958 these = 'those'
959 def really(self):
960 return 'no, not %s' % self.value
961 self.assertIsNot(type(whatever.really), whatever)
962 self.assertEqual(whatever.this.really(), 'no, not that')
963
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700964 def test_wrong_inheritance_order(self):
965 with self.assertRaises(TypeError):
966 class Wrong(Enum, str):
967 NotHere = 'error before this point'
968
969 def test_intenum_transitivity(self):
970 class number(IntEnum):
971 one = 1
972 two = 2
973 three = 3
974 class numero(IntEnum):
975 uno = 1
976 dos = 2
977 tres = 3
978 self.assertEqual(number.one, numero.uno)
979 self.assertEqual(number.two, numero.dos)
980 self.assertEqual(number.three, numero.tres)
981
982 def test_wrong_enum_in_call(self):
983 class Monochrome(Enum):
984 black = 0
985 white = 1
986 class Gender(Enum):
987 male = 0
988 female = 1
989 self.assertRaises(ValueError, Monochrome, Gender.male)
990
991 def test_wrong_enum_in_mixed_call(self):
992 class Monochrome(IntEnum):
993 black = 0
994 white = 1
995 class Gender(Enum):
996 male = 0
997 female = 1
998 self.assertRaises(ValueError, Monochrome, Gender.male)
999
1000 def test_mixed_enum_in_call_1(self):
1001 class Monochrome(IntEnum):
1002 black = 0
1003 white = 1
1004 class Gender(IntEnum):
1005 male = 0
1006 female = 1
1007 self.assertIs(Monochrome(Gender.female), Monochrome.white)
1008
1009 def test_mixed_enum_in_call_2(self):
1010 class Monochrome(Enum):
1011 black = 0
1012 white = 1
1013 class Gender(IntEnum):
1014 male = 0
1015 female = 1
1016 self.assertIs(Monochrome(Gender.male), Monochrome.black)
1017
1018 def test_flufl_enum(self):
1019 class Fluflnum(Enum):
1020 def __int__(self):
1021 return int(self.value)
1022 class MailManOptions(Fluflnum):
1023 option1 = 1
1024 option2 = 2
1025 option3 = 3
1026 self.assertEqual(int(MailManOptions.option1), 1)
1027
Ethan Furman5e5a8232013-08-04 08:42:23 -07001028 def test_introspection(self):
1029 class Number(IntEnum):
1030 one = 100
1031 two = 200
1032 self.assertIs(Number.one._member_type_, int)
1033 self.assertIs(Number._member_type_, int)
1034 class String(str, Enum):
1035 yarn = 'soft'
1036 rope = 'rough'
1037 wire = 'hard'
1038 self.assertIs(String.yarn._member_type_, str)
1039 self.assertIs(String._member_type_, str)
1040 class Plain(Enum):
1041 vanilla = 'white'
1042 one = 1
1043 self.assertIs(Plain.vanilla._member_type_, object)
1044 self.assertIs(Plain._member_type_, object)
1045
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001046 def test_no_such_enum_member(self):
1047 class Color(Enum):
1048 red = 1
1049 green = 2
1050 blue = 3
1051 with self.assertRaises(ValueError):
1052 Color(4)
1053 with self.assertRaises(KeyError):
1054 Color['chartreuse']
1055
1056 def test_new_repr(self):
1057 class Color(Enum):
1058 red = 1
1059 green = 2
1060 blue = 3
1061 def __repr__(self):
1062 return "don't you just love shades of %s?" % self.name
1063 self.assertEqual(
1064 repr(Color.blue),
1065 "don't you just love shades of blue?",
1066 )
1067
1068 def test_inherited_repr(self):
1069 class MyEnum(Enum):
1070 def __repr__(self):
1071 return "My name is %s." % self.name
1072 class MyIntEnum(int, MyEnum):
1073 this = 1
1074 that = 2
1075 theother = 3
1076 self.assertEqual(repr(MyIntEnum.that), "My name is that.")
1077
1078 def test_multiple_mixin_mro(self):
1079 class auto_enum(type(Enum)):
1080 def __new__(metacls, cls, bases, classdict):
1081 temp = type(classdict)()
1082 names = set(classdict._member_names)
1083 i = 0
1084 for k in classdict._member_names:
1085 v = classdict[k]
1086 if v is Ellipsis:
1087 v = i
1088 else:
1089 i = v
1090 i += 1
1091 temp[k] = v
1092 for k, v in classdict.items():
1093 if k not in names:
1094 temp[k] = v
1095 return super(auto_enum, metacls).__new__(
1096 metacls, cls, bases, temp)
1097
1098 class AutoNumberedEnum(Enum, metaclass=auto_enum):
1099 pass
1100
1101 class AutoIntEnum(IntEnum, metaclass=auto_enum):
1102 pass
1103
1104 class TestAutoNumber(AutoNumberedEnum):
1105 a = ...
1106 b = 3
1107 c = ...
1108
1109 class TestAutoInt(AutoIntEnum):
1110 a = ...
1111 b = 3
1112 c = ...
1113
1114 def test_subclasses_with_getnewargs(self):
1115 class NamedInt(int):
Ethan Furman2ddb39a2014-02-06 17:28:50 -08001116 __qualname__ = 'NamedInt' # needed for pickle protocol 4
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001117 def __new__(cls, *args):
1118 _args = args
1119 name, *args = args
1120 if len(args) == 0:
1121 raise TypeError("name and value must be specified")
1122 self = int.__new__(cls, *args)
1123 self._intname = name
1124 self._args = _args
1125 return self
1126 def __getnewargs__(self):
1127 return self._args
1128 @property
1129 def __name__(self):
1130 return self._intname
1131 def __repr__(self):
1132 # repr() is updated to include the name and type info
1133 return "{}({!r}, {})".format(type(self).__name__,
1134 self.__name__,
1135 int.__repr__(self))
1136 def __str__(self):
1137 # str() is unchanged, even if it relies on the repr() fallback
1138 base = int
1139 base_str = base.__str__
1140 if base_str.__objclass__ is object:
1141 return base.__repr__(self)
1142 return base_str(self)
1143 # for simplicity, we only define one operator that
1144 # propagates expressions
1145 def __add__(self, other):
1146 temp = int(self) + int( other)
1147 if isinstance(self, NamedInt) and isinstance(other, NamedInt):
1148 return NamedInt(
1149 '({0} + {1})'.format(self.__name__, other.__name__),
1150 temp )
1151 else:
1152 return temp
1153
1154 class NEI(NamedInt, Enum):
Ethan Furman2ddb39a2014-02-06 17:28:50 -08001155 __qualname__ = 'NEI' # needed for pickle protocol 4
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001156 x = ('the-x', 1)
1157 y = ('the-y', 2)
1158
Ethan Furman2aa27322013-07-19 19:35:56 -07001159
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001160 self.assertIs(NEI.__new__, Enum.__new__)
1161 self.assertEqual(repr(NEI.x + NEI.y), "NamedInt('(the-x + the-y)', 3)")
1162 globals()['NamedInt'] = NamedInt
1163 globals()['NEI'] = NEI
1164 NI5 = NamedInt('test', 5)
1165 self.assertEqual(NI5, 5)
Ethan Furman2ddb39a2014-02-06 17:28:50 -08001166 test_pickle_dump_load(self.assertEqual, NI5, 5)
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001167 self.assertEqual(NEI.y.value, 2)
Ethan Furman2ddb39a2014-02-06 17:28:50 -08001168 test_pickle_dump_load(self.assertIs, NEI.y)
Ethan Furmandc870522014-02-18 12:37:12 -08001169 test_pickle_dump_load(self.assertIs, NEI)
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001170
Ethan Furmanca1b7942014-02-08 11:36:27 -08001171 def test_subclasses_with_getnewargs_ex(self):
1172 class NamedInt(int):
1173 __qualname__ = 'NamedInt' # needed for pickle protocol 4
1174 def __new__(cls, *args):
1175 _args = args
1176 name, *args = args
1177 if len(args) == 0:
1178 raise TypeError("name and value must be specified")
1179 self = int.__new__(cls, *args)
1180 self._intname = name
1181 self._args = _args
1182 return self
1183 def __getnewargs_ex__(self):
1184 return self._args, {}
1185 @property
1186 def __name__(self):
1187 return self._intname
1188 def __repr__(self):
1189 # repr() is updated to include the name and type info
1190 return "{}({!r}, {})".format(type(self).__name__,
1191 self.__name__,
1192 int.__repr__(self))
1193 def __str__(self):
1194 # str() is unchanged, even if it relies on the repr() fallback
1195 base = int
1196 base_str = base.__str__
1197 if base_str.__objclass__ is object:
1198 return base.__repr__(self)
1199 return base_str(self)
1200 # for simplicity, we only define one operator that
1201 # propagates expressions
1202 def __add__(self, other):
1203 temp = int(self) + int( other)
1204 if isinstance(self, NamedInt) and isinstance(other, NamedInt):
1205 return NamedInt(
1206 '({0} + {1})'.format(self.__name__, other.__name__),
1207 temp )
1208 else:
1209 return temp
1210
1211 class NEI(NamedInt, Enum):
1212 __qualname__ = 'NEI' # needed for pickle protocol 4
1213 x = ('the-x', 1)
1214 y = ('the-y', 2)
1215
1216
1217 self.assertIs(NEI.__new__, Enum.__new__)
1218 self.assertEqual(repr(NEI.x + NEI.y), "NamedInt('(the-x + the-y)', 3)")
1219 globals()['NamedInt'] = NamedInt
1220 globals()['NEI'] = NEI
1221 NI5 = NamedInt('test', 5)
1222 self.assertEqual(NI5, 5)
Serhiy Storchakae50e7802015-03-31 16:56:49 +03001223 test_pickle_dump_load(self.assertEqual, NI5, 5)
Ethan Furmanca1b7942014-02-08 11:36:27 -08001224 self.assertEqual(NEI.y.value, 2)
Serhiy Storchakae50e7802015-03-31 16:56:49 +03001225 test_pickle_dump_load(self.assertIs, NEI.y)
Ethan Furmandc870522014-02-18 12:37:12 -08001226 test_pickle_dump_load(self.assertIs, NEI)
Ethan Furmanca1b7942014-02-08 11:36:27 -08001227
1228 def test_subclasses_with_reduce(self):
1229 class NamedInt(int):
1230 __qualname__ = 'NamedInt' # needed for pickle protocol 4
1231 def __new__(cls, *args):
1232 _args = args
1233 name, *args = args
1234 if len(args) == 0:
1235 raise TypeError("name and value must be specified")
1236 self = int.__new__(cls, *args)
1237 self._intname = name
1238 self._args = _args
1239 return self
1240 def __reduce__(self):
1241 return self.__class__, self._args
1242 @property
1243 def __name__(self):
1244 return self._intname
1245 def __repr__(self):
1246 # repr() is updated to include the name and type info
1247 return "{}({!r}, {})".format(type(self).__name__,
1248 self.__name__,
1249 int.__repr__(self))
1250 def __str__(self):
1251 # str() is unchanged, even if it relies on the repr() fallback
1252 base = int
1253 base_str = base.__str__
1254 if base_str.__objclass__ is object:
1255 return base.__repr__(self)
1256 return base_str(self)
1257 # for simplicity, we only define one operator that
1258 # propagates expressions
1259 def __add__(self, other):
1260 temp = int(self) + int( other)
1261 if isinstance(self, NamedInt) and isinstance(other, NamedInt):
1262 return NamedInt(
1263 '({0} + {1})'.format(self.__name__, other.__name__),
1264 temp )
1265 else:
1266 return temp
1267
1268 class NEI(NamedInt, Enum):
1269 __qualname__ = 'NEI' # needed for pickle protocol 4
1270 x = ('the-x', 1)
1271 y = ('the-y', 2)
1272
1273
1274 self.assertIs(NEI.__new__, Enum.__new__)
1275 self.assertEqual(repr(NEI.x + NEI.y), "NamedInt('(the-x + the-y)', 3)")
1276 globals()['NamedInt'] = NamedInt
1277 globals()['NEI'] = NEI
1278 NI5 = NamedInt('test', 5)
1279 self.assertEqual(NI5, 5)
1280 test_pickle_dump_load(self.assertEqual, NI5, 5)
1281 self.assertEqual(NEI.y.value, 2)
1282 test_pickle_dump_load(self.assertIs, NEI.y)
Ethan Furmandc870522014-02-18 12:37:12 -08001283 test_pickle_dump_load(self.assertIs, NEI)
Ethan Furmanca1b7942014-02-08 11:36:27 -08001284
1285 def test_subclasses_with_reduce_ex(self):
1286 class NamedInt(int):
1287 __qualname__ = 'NamedInt' # needed for pickle protocol 4
1288 def __new__(cls, *args):
1289 _args = args
1290 name, *args = args
1291 if len(args) == 0:
1292 raise TypeError("name and value must be specified")
1293 self = int.__new__(cls, *args)
1294 self._intname = name
1295 self._args = _args
1296 return self
1297 def __reduce_ex__(self, proto):
1298 return self.__class__, self._args
1299 @property
1300 def __name__(self):
1301 return self._intname
1302 def __repr__(self):
1303 # repr() is updated to include the name and type info
1304 return "{}({!r}, {})".format(type(self).__name__,
1305 self.__name__,
1306 int.__repr__(self))
1307 def __str__(self):
1308 # str() is unchanged, even if it relies on the repr() fallback
1309 base = int
1310 base_str = base.__str__
1311 if base_str.__objclass__ is object:
1312 return base.__repr__(self)
1313 return base_str(self)
1314 # for simplicity, we only define one operator that
1315 # propagates expressions
1316 def __add__(self, other):
1317 temp = int(self) + int( other)
1318 if isinstance(self, NamedInt) and isinstance(other, NamedInt):
1319 return NamedInt(
1320 '({0} + {1})'.format(self.__name__, other.__name__),
1321 temp )
1322 else:
1323 return temp
1324
1325 class NEI(NamedInt, Enum):
1326 __qualname__ = 'NEI' # needed for pickle protocol 4
1327 x = ('the-x', 1)
1328 y = ('the-y', 2)
1329
1330
1331 self.assertIs(NEI.__new__, Enum.__new__)
1332 self.assertEqual(repr(NEI.x + NEI.y), "NamedInt('(the-x + the-y)', 3)")
1333 globals()['NamedInt'] = NamedInt
1334 globals()['NEI'] = NEI
1335 NI5 = NamedInt('test', 5)
1336 self.assertEqual(NI5, 5)
1337 test_pickle_dump_load(self.assertEqual, NI5, 5)
1338 self.assertEqual(NEI.y.value, 2)
1339 test_pickle_dump_load(self.assertIs, NEI.y)
Ethan Furmandc870522014-02-18 12:37:12 -08001340 test_pickle_dump_load(self.assertIs, NEI)
Ethan Furmanca1b7942014-02-08 11:36:27 -08001341
Ethan Furmandc870522014-02-18 12:37:12 -08001342 def test_subclasses_without_direct_pickle_support(self):
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001343 class NamedInt(int):
Ethan Furman2ddb39a2014-02-06 17:28:50 -08001344 __qualname__ = 'NamedInt'
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001345 def __new__(cls, *args):
1346 _args = args
1347 name, *args = args
1348 if len(args) == 0:
1349 raise TypeError("name and value must be specified")
1350 self = int.__new__(cls, *args)
1351 self._intname = name
1352 self._args = _args
1353 return self
1354 @property
1355 def __name__(self):
1356 return self._intname
1357 def __repr__(self):
1358 # repr() is updated to include the name and type info
1359 return "{}({!r}, {})".format(type(self).__name__,
1360 self.__name__,
1361 int.__repr__(self))
1362 def __str__(self):
1363 # str() is unchanged, even if it relies on the repr() fallback
1364 base = int
1365 base_str = base.__str__
1366 if base_str.__objclass__ is object:
1367 return base.__repr__(self)
1368 return base_str(self)
1369 # for simplicity, we only define one operator that
1370 # propagates expressions
1371 def __add__(self, other):
1372 temp = int(self) + int( other)
1373 if isinstance(self, NamedInt) and isinstance(other, NamedInt):
1374 return NamedInt(
1375 '({0} + {1})'.format(self.__name__, other.__name__),
1376 temp )
1377 else:
1378 return temp
1379
1380 class NEI(NamedInt, Enum):
Ethan Furman2ddb39a2014-02-06 17:28:50 -08001381 __qualname__ = 'NEI'
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001382 x = ('the-x', 1)
1383 y = ('the-y', 2)
1384
1385 self.assertIs(NEI.__new__, Enum.__new__)
1386 self.assertEqual(repr(NEI.x + NEI.y), "NamedInt('(the-x + the-y)', 3)")
1387 globals()['NamedInt'] = NamedInt
1388 globals()['NEI'] = NEI
1389 NI5 = NamedInt('test', 5)
1390 self.assertEqual(NI5, 5)
1391 self.assertEqual(NEI.y.value, 2)
Ethan Furman2ddb39a2014-02-06 17:28:50 -08001392 test_pickle_exception(self.assertRaises, TypeError, NEI.x)
1393 test_pickle_exception(self.assertRaises, PicklingError, NEI)
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001394
Ethan Furmandc870522014-02-18 12:37:12 -08001395 def test_subclasses_without_direct_pickle_support_using_name(self):
1396 class NamedInt(int):
1397 __qualname__ = 'NamedInt'
1398 def __new__(cls, *args):
1399 _args = args
1400 name, *args = args
1401 if len(args) == 0:
1402 raise TypeError("name and value must be specified")
1403 self = int.__new__(cls, *args)
1404 self._intname = name
1405 self._args = _args
1406 return self
1407 @property
1408 def __name__(self):
1409 return self._intname
1410 def __repr__(self):
1411 # repr() is updated to include the name and type info
1412 return "{}({!r}, {})".format(type(self).__name__,
1413 self.__name__,
1414 int.__repr__(self))
1415 def __str__(self):
1416 # str() is unchanged, even if it relies on the repr() fallback
1417 base = int
1418 base_str = base.__str__
1419 if base_str.__objclass__ is object:
1420 return base.__repr__(self)
1421 return base_str(self)
1422 # for simplicity, we only define one operator that
1423 # propagates expressions
1424 def __add__(self, other):
1425 temp = int(self) + int( other)
1426 if isinstance(self, NamedInt) and isinstance(other, NamedInt):
1427 return NamedInt(
1428 '({0} + {1})'.format(self.__name__, other.__name__),
1429 temp )
1430 else:
1431 return temp
1432
1433 class NEI(NamedInt, Enum):
1434 __qualname__ = 'NEI'
1435 x = ('the-x', 1)
1436 y = ('the-y', 2)
1437 def __reduce_ex__(self, proto):
1438 return getattr, (self.__class__, self._name_)
1439
1440 self.assertIs(NEI.__new__, Enum.__new__)
1441 self.assertEqual(repr(NEI.x + NEI.y), "NamedInt('(the-x + the-y)', 3)")
1442 globals()['NamedInt'] = NamedInt
1443 globals()['NEI'] = NEI
1444 NI5 = NamedInt('test', 5)
1445 self.assertEqual(NI5, 5)
1446 self.assertEqual(NEI.y.value, 2)
1447 test_pickle_dump_load(self.assertIs, NEI.y)
1448 test_pickle_dump_load(self.assertIs, NEI)
1449
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001450 def test_tuple_subclass(self):
1451 class SomeTuple(tuple, Enum):
Ethan Furman2ddb39a2014-02-06 17:28:50 -08001452 __qualname__ = 'SomeTuple' # needed for pickle protocol 4
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001453 first = (1, 'for the money')
1454 second = (2, 'for the show')
1455 third = (3, 'for the music')
1456 self.assertIs(type(SomeTuple.first), SomeTuple)
1457 self.assertIsInstance(SomeTuple.second, tuple)
1458 self.assertEqual(SomeTuple.third, (3, 'for the music'))
1459 globals()['SomeTuple'] = SomeTuple
Ethan Furman2ddb39a2014-02-06 17:28:50 -08001460 test_pickle_dump_load(self.assertIs, SomeTuple.first)
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001461
1462 def test_duplicate_values_give_unique_enum_items(self):
1463 class AutoNumber(Enum):
1464 first = ()
1465 second = ()
1466 third = ()
1467 def __new__(cls):
1468 value = len(cls.__members__) + 1
1469 obj = object.__new__(cls)
Ethan Furman520ad572013-07-19 19:47:21 -07001470 obj._value_ = value
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001471 return obj
1472 def __int__(self):
Ethan Furman520ad572013-07-19 19:47:21 -07001473 return int(self._value_)
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001474 self.assertEqual(
1475 list(AutoNumber),
1476 [AutoNumber.first, AutoNumber.second, AutoNumber.third],
1477 )
1478 self.assertEqual(int(AutoNumber.second), 2)
Ethan Furman2aa27322013-07-19 19:35:56 -07001479 self.assertEqual(AutoNumber.third.value, 3)
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001480 self.assertIs(AutoNumber(1), AutoNumber.first)
1481
1482 def test_inherited_new_from_enhanced_enum(self):
1483 class AutoNumber(Enum):
1484 def __new__(cls):
1485 value = len(cls.__members__) + 1
1486 obj = object.__new__(cls)
Ethan Furman520ad572013-07-19 19:47:21 -07001487 obj._value_ = value
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001488 return obj
1489 def __int__(self):
Ethan Furman520ad572013-07-19 19:47:21 -07001490 return int(self._value_)
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001491 class Color(AutoNumber):
1492 red = ()
1493 green = ()
1494 blue = ()
1495 self.assertEqual(list(Color), [Color.red, Color.green, Color.blue])
1496 self.assertEqual(list(map(int, Color)), [1, 2, 3])
1497
1498 def test_inherited_new_from_mixed_enum(self):
1499 class AutoNumber(IntEnum):
1500 def __new__(cls):
1501 value = len(cls.__members__) + 1
1502 obj = int.__new__(cls, value)
Ethan Furman520ad572013-07-19 19:47:21 -07001503 obj._value_ = value
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001504 return obj
1505 class Color(AutoNumber):
1506 red = ()
1507 green = ()
1508 blue = ()
1509 self.assertEqual(list(Color), [Color.red, Color.green, Color.blue])
1510 self.assertEqual(list(map(int, Color)), [1, 2, 3])
1511
Ethan Furmanbe3c2fe2013-11-13 14:25:45 -08001512 def test_equality(self):
Ethan Furmanbe3c2fe2013-11-13 14:25:45 -08001513 class OrdinaryEnum(Enum):
1514 a = 1
Serhiy Storchaka7d44e7a2019-08-08 08:43:18 +03001515 self.assertEqual(ALWAYS_EQ, OrdinaryEnum.a)
1516 self.assertEqual(OrdinaryEnum.a, ALWAYS_EQ)
Ethan Furmanbe3c2fe2013-11-13 14:25:45 -08001517
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001518 def test_ordered_mixin(self):
1519 class OrderedEnum(Enum):
1520 def __ge__(self, other):
1521 if self.__class__ is other.__class__:
Ethan Furman520ad572013-07-19 19:47:21 -07001522 return self._value_ >= other._value_
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001523 return NotImplemented
1524 def __gt__(self, other):
1525 if self.__class__ is other.__class__:
Ethan Furman520ad572013-07-19 19:47:21 -07001526 return self._value_ > other._value_
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001527 return NotImplemented
1528 def __le__(self, other):
1529 if self.__class__ is other.__class__:
Ethan Furman520ad572013-07-19 19:47:21 -07001530 return self._value_ <= other._value_
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001531 return NotImplemented
1532 def __lt__(self, other):
1533 if self.__class__ is other.__class__:
Ethan Furman520ad572013-07-19 19:47:21 -07001534 return self._value_ < other._value_
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001535 return NotImplemented
1536 class Grade(OrderedEnum):
1537 A = 5
1538 B = 4
1539 C = 3
1540 D = 2
1541 F = 1
1542 self.assertGreater(Grade.A, Grade.B)
1543 self.assertLessEqual(Grade.F, Grade.C)
1544 self.assertLess(Grade.D, Grade.A)
1545 self.assertGreaterEqual(Grade.B, Grade.B)
Ethan Furmanbe3c2fe2013-11-13 14:25:45 -08001546 self.assertEqual(Grade.B, Grade.B)
1547 self.assertNotEqual(Grade.C, Grade.D)
Ethan Furman520ad572013-07-19 19:47:21 -07001548
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001549 def test_extending2(self):
1550 class Shade(Enum):
1551 def shade(self):
1552 print(self.name)
1553 class Color(Shade):
1554 red = 1
1555 green = 2
1556 blue = 3
1557 with self.assertRaises(TypeError):
1558 class MoreColor(Color):
1559 cyan = 4
1560 magenta = 5
1561 yellow = 6
1562
1563 def test_extending3(self):
1564 class Shade(Enum):
1565 def shade(self):
1566 return self.name
1567 class Color(Shade):
1568 def hex(self):
1569 return '%s hexlified!' % self.value
1570 class MoreColor(Color):
1571 cyan = 4
1572 magenta = 5
1573 yellow = 6
1574 self.assertEqual(MoreColor.magenta.hex(), '5 hexlified!')
1575
orlnub1230fb9fad2018-09-12 20:28:53 +03001576 def test_subclass_duplicate_name(self):
1577 class Base(Enum):
1578 def test(self):
1579 pass
1580 class Test(Base):
1581 test = 1
1582 self.assertIs(type(Test.test), Test)
1583
1584 def test_subclass_duplicate_name_dynamic(self):
1585 from types import DynamicClassAttribute
1586 class Base(Enum):
1587 @DynamicClassAttribute
1588 def test(self):
1589 return 'dynamic'
1590 class Test(Base):
1591 test = 1
1592 self.assertEqual(Test.test.test, 'dynamic')
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001593
1594 def test_no_duplicates(self):
1595 class UniqueEnum(Enum):
1596 def __init__(self, *args):
1597 cls = self.__class__
1598 if any(self.value == e.value for e in cls):
1599 a = self.name
1600 e = cls(self.value).name
1601 raise ValueError(
1602 "aliases not allowed in UniqueEnum: %r --> %r"
1603 % (a, e)
1604 )
1605 class Color(UniqueEnum):
1606 red = 1
1607 green = 2
1608 blue = 3
1609 with self.assertRaises(ValueError):
1610 class Color(UniqueEnum):
1611 red = 1
1612 green = 2
1613 blue = 3
1614 grene = 2
1615
1616 def test_init(self):
1617 class Planet(Enum):
1618 MERCURY = (3.303e+23, 2.4397e6)
1619 VENUS = (4.869e+24, 6.0518e6)
1620 EARTH = (5.976e+24, 6.37814e6)
1621 MARS = (6.421e+23, 3.3972e6)
1622 JUPITER = (1.9e+27, 7.1492e7)
1623 SATURN = (5.688e+26, 6.0268e7)
1624 URANUS = (8.686e+25, 2.5559e7)
1625 NEPTUNE = (1.024e+26, 2.4746e7)
1626 def __init__(self, mass, radius):
1627 self.mass = mass # in kilograms
1628 self.radius = radius # in meters
1629 @property
1630 def surface_gravity(self):
1631 # universal gravitational constant (m3 kg-1 s-2)
1632 G = 6.67300E-11
1633 return G * self.mass / (self.radius * self.radius)
1634 self.assertEqual(round(Planet.EARTH.surface_gravity, 2), 9.80)
1635 self.assertEqual(Planet.EARTH.value, (5.976e+24, 6.37814e6))
1636
Ethan Furmana4b1bb42018-01-22 07:56:37 -08001637 def test_ignore(self):
1638 class Period(timedelta, Enum):
1639 '''
1640 different lengths of time
1641 '''
1642 def __new__(cls, value, period):
1643 obj = timedelta.__new__(cls, value)
1644 obj._value_ = value
1645 obj.period = period
1646 return obj
1647 _ignore_ = 'Period i'
1648 Period = vars()
1649 for i in range(13):
1650 Period['month_%d' % i] = i*30, 'month'
1651 for i in range(53):
1652 Period['week_%d' % i] = i*7, 'week'
1653 for i in range(32):
1654 Period['day_%d' % i] = i, 'day'
1655 OneDay = day_1
1656 OneWeek = week_1
1657 OneMonth = month_1
1658 self.assertFalse(hasattr(Period, '_ignore_'))
1659 self.assertFalse(hasattr(Period, 'Period'))
1660 self.assertFalse(hasattr(Period, 'i'))
1661 self.assertTrue(isinstance(Period.day_1, timedelta))
1662 self.assertTrue(Period.month_1 is Period.day_30)
1663 self.assertTrue(Period.week_4 is Period.day_28)
1664
Ethan Furman2aa27322013-07-19 19:35:56 -07001665 def test_nonhash_value(self):
1666 class AutoNumberInAList(Enum):
1667 def __new__(cls):
1668 value = [len(cls.__members__) + 1]
1669 obj = object.__new__(cls)
Ethan Furman520ad572013-07-19 19:47:21 -07001670 obj._value_ = value
Ethan Furman2aa27322013-07-19 19:35:56 -07001671 return obj
1672 class ColorInAList(AutoNumberInAList):
1673 red = ()
1674 green = ()
1675 blue = ()
1676 self.assertEqual(list(ColorInAList), [ColorInAList.red, ColorInAList.green, ColorInAList.blue])
Ethan Furman1a162882013-10-16 19:09:31 -07001677 for enum, value in zip(ColorInAList, range(3)):
1678 value += 1
1679 self.assertEqual(enum.value, [value])
1680 self.assertIs(ColorInAList([value]), enum)
Ethan Furman2aa27322013-07-19 19:35:56 -07001681
Ethan Furmanb41803e2013-07-25 13:50:45 -07001682 def test_conflicting_types_resolved_in_new(self):
1683 class LabelledIntEnum(int, Enum):
1684 def __new__(cls, *args):
1685 value, label = args
1686 obj = int.__new__(cls, value)
1687 obj.label = label
1688 obj._value_ = value
1689 return obj
1690
1691 class LabelledList(LabelledIntEnum):
1692 unprocessed = (1, "Unprocessed")
1693 payment_complete = (2, "Payment Complete")
1694
1695 self.assertEqual(list(LabelledList), [LabelledList.unprocessed, LabelledList.payment_complete])
1696 self.assertEqual(LabelledList.unprocessed, 1)
1697 self.assertEqual(LabelledList(1), LabelledList.unprocessed)
Ethan Furman2aa27322013-07-19 19:35:56 -07001698
Ethan Furmanc16595e2016-09-10 23:36:59 -07001699 def test_auto_number(self):
1700 class Color(Enum):
1701 red = auto()
1702 blue = auto()
1703 green = auto()
1704
1705 self.assertEqual(list(Color), [Color.red, Color.blue, Color.green])
1706 self.assertEqual(Color.red.value, 1)
1707 self.assertEqual(Color.blue.value, 2)
1708 self.assertEqual(Color.green.value, 3)
1709
1710 def test_auto_name(self):
1711 class Color(Enum):
1712 def _generate_next_value_(name, start, count, last):
1713 return name
1714 red = auto()
1715 blue = auto()
1716 green = auto()
1717
1718 self.assertEqual(list(Color), [Color.red, Color.blue, Color.green])
1719 self.assertEqual(Color.red.value, 'red')
1720 self.assertEqual(Color.blue.value, 'blue')
1721 self.assertEqual(Color.green.value, 'green')
1722
1723 def test_auto_name_inherit(self):
1724 class AutoNameEnum(Enum):
1725 def _generate_next_value_(name, start, count, last):
1726 return name
1727 class Color(AutoNameEnum):
1728 red = auto()
1729 blue = auto()
1730 green = auto()
1731
1732 self.assertEqual(list(Color), [Color.red, Color.blue, Color.green])
1733 self.assertEqual(Color.red.value, 'red')
1734 self.assertEqual(Color.blue.value, 'blue')
1735 self.assertEqual(Color.green.value, 'green')
1736
1737 def test_auto_garbage(self):
1738 class Color(Enum):
1739 red = 'red'
1740 blue = auto()
1741 self.assertEqual(Color.blue.value, 1)
1742
1743 def test_auto_garbage_corrected(self):
1744 class Color(Enum):
1745 red = 'red'
1746 blue = 2
1747 green = auto()
1748
1749 self.assertEqual(list(Color), [Color.red, Color.blue, Color.green])
1750 self.assertEqual(Color.red.value, 'red')
1751 self.assertEqual(Color.blue.value, 2)
1752 self.assertEqual(Color.green.value, 3)
1753
Ethan Furman3515dcc2016-09-18 13:15:41 -07001754 def test_duplicate_auto(self):
1755 class Dupes(Enum):
1756 first = primero = auto()
1757 second = auto()
1758 third = auto()
1759 self.assertEqual([Dupes.first, Dupes.second, Dupes.third], list(Dupes))
1760
Ethan Furman019f0a02018-09-12 11:43:34 -07001761 def test_missing(self):
1762 class Color(Enum):
1763 red = 1
1764 green = 2
1765 blue = 3
1766 @classmethod
1767 def _missing_(cls, item):
1768 if item == 'three':
1769 return cls.blue
1770 elif item == 'bad return':
1771 # trigger internal error
1772 return 5
1773 elif item == 'error out':
1774 raise ZeroDivisionError
1775 else:
1776 # trigger not found
1777 return None
1778 self.assertIs(Color('three'), Color.blue)
1779 self.assertRaises(ValueError, Color, 7)
1780 try:
1781 Color('bad return')
1782 except TypeError as exc:
1783 self.assertTrue(isinstance(exc.__context__, ValueError))
1784 else:
1785 raise Exception('Exception not raised.')
1786 try:
1787 Color('error out')
1788 except ZeroDivisionError as exc:
1789 self.assertTrue(isinstance(exc.__context__, ValueError))
1790 else:
1791 raise Exception('Exception not raised.')
1792
Ethan Furman5bdab642018-09-21 19:03:09 -07001793 def test_multiple_mixin(self):
1794 class MaxMixin:
1795 @classproperty
1796 def MAX(cls):
1797 max = len(cls)
1798 cls.MAX = max
1799 return max
1800 class StrMixin:
1801 def __str__(self):
1802 return self._name_.lower()
1803 class SomeEnum(Enum):
1804 def behavior(self):
1805 return 'booyah'
1806 class AnotherEnum(Enum):
1807 def behavior(self):
1808 return 'nuhuh!'
1809 def social(self):
1810 return "what's up?"
1811 class Color(MaxMixin, Enum):
1812 RED = auto()
1813 GREEN = auto()
1814 BLUE = auto()
1815 self.assertEqual(Color.RED.value, 1)
1816 self.assertEqual(Color.GREEN.value, 2)
1817 self.assertEqual(Color.BLUE.value, 3)
1818 self.assertEqual(Color.MAX, 3)
1819 self.assertEqual(str(Color.BLUE), 'Color.BLUE')
1820 class Color(MaxMixin, StrMixin, Enum):
1821 RED = auto()
1822 GREEN = auto()
1823 BLUE = auto()
1824 self.assertEqual(Color.RED.value, 1)
1825 self.assertEqual(Color.GREEN.value, 2)
1826 self.assertEqual(Color.BLUE.value, 3)
1827 self.assertEqual(Color.MAX, 3)
1828 self.assertEqual(str(Color.BLUE), 'blue')
1829 class Color(StrMixin, MaxMixin, Enum):
1830 RED = auto()
1831 GREEN = auto()
1832 BLUE = auto()
1833 self.assertEqual(Color.RED.value, 1)
1834 self.assertEqual(Color.GREEN.value, 2)
1835 self.assertEqual(Color.BLUE.value, 3)
1836 self.assertEqual(Color.MAX, 3)
1837 self.assertEqual(str(Color.BLUE), 'blue')
1838 class CoolColor(StrMixin, SomeEnum, Enum):
1839 RED = auto()
1840 GREEN = auto()
1841 BLUE = auto()
1842 self.assertEqual(CoolColor.RED.value, 1)
1843 self.assertEqual(CoolColor.GREEN.value, 2)
1844 self.assertEqual(CoolColor.BLUE.value, 3)
1845 self.assertEqual(str(CoolColor.BLUE), 'blue')
1846 self.assertEqual(CoolColor.RED.behavior(), 'booyah')
1847 class CoolerColor(StrMixin, AnotherEnum, Enum):
1848 RED = auto()
1849 GREEN = auto()
1850 BLUE = auto()
1851 self.assertEqual(CoolerColor.RED.value, 1)
1852 self.assertEqual(CoolerColor.GREEN.value, 2)
1853 self.assertEqual(CoolerColor.BLUE.value, 3)
1854 self.assertEqual(str(CoolerColor.BLUE), 'blue')
1855 self.assertEqual(CoolerColor.RED.behavior(), 'nuhuh!')
1856 self.assertEqual(CoolerColor.RED.social(), "what's up?")
1857 class CoolestColor(StrMixin, SomeEnum, AnotherEnum):
1858 RED = auto()
1859 GREEN = auto()
1860 BLUE = auto()
1861 self.assertEqual(CoolestColor.RED.value, 1)
1862 self.assertEqual(CoolestColor.GREEN.value, 2)
1863 self.assertEqual(CoolestColor.BLUE.value, 3)
1864 self.assertEqual(str(CoolestColor.BLUE), 'blue')
1865 self.assertEqual(CoolestColor.RED.behavior(), 'booyah')
1866 self.assertEqual(CoolestColor.RED.social(), "what's up?")
1867 class ConfusedColor(StrMixin, AnotherEnum, SomeEnum):
1868 RED = auto()
1869 GREEN = auto()
1870 BLUE = auto()
1871 self.assertEqual(ConfusedColor.RED.value, 1)
1872 self.assertEqual(ConfusedColor.GREEN.value, 2)
1873 self.assertEqual(ConfusedColor.BLUE.value, 3)
1874 self.assertEqual(str(ConfusedColor.BLUE), 'blue')
1875 self.assertEqual(ConfusedColor.RED.behavior(), 'nuhuh!')
1876 self.assertEqual(ConfusedColor.RED.social(), "what's up?")
1877 class ReformedColor(StrMixin, IntEnum, SomeEnum, AnotherEnum):
1878 RED = auto()
1879 GREEN = auto()
1880 BLUE = auto()
1881 self.assertEqual(ReformedColor.RED.value, 1)
1882 self.assertEqual(ReformedColor.GREEN.value, 2)
1883 self.assertEqual(ReformedColor.BLUE.value, 3)
1884 self.assertEqual(str(ReformedColor.BLUE), 'blue')
1885 self.assertEqual(ReformedColor.RED.behavior(), 'booyah')
1886 self.assertEqual(ConfusedColor.RED.social(), "what's up?")
1887 self.assertTrue(issubclass(ReformedColor, int))
1888
Ethan Furmancd453852018-10-05 23:29:36 -07001889 def test_multiple_inherited_mixin(self):
1890 class StrEnum(str, Enum):
1891 def __new__(cls, *args, **kwargs):
1892 for a in args:
1893 if not isinstance(a, str):
1894 raise TypeError("Enumeration '%s' (%s) is not"
1895 " a string" % (a, type(a).__name__))
1896 return str.__new__(cls, *args, **kwargs)
1897 @unique
1898 class Decision1(StrEnum):
1899 REVERT = "REVERT"
1900 REVERT_ALL = "REVERT_ALL"
1901 RETRY = "RETRY"
1902 class MyEnum(StrEnum):
1903 pass
1904 @unique
1905 class Decision2(MyEnum):
1906 REVERT = "REVERT"
1907 REVERT_ALL = "REVERT_ALL"
1908 RETRY = "RETRY"
1909
Rémi Lapeyre1fd06f12019-01-24 20:43:13 +01001910 def test_empty_globals(self):
1911 # bpo-35717: sys._getframe(2).f_globals['__name__'] fails with KeyError
1912 # when using compile and exec because f_globals is empty
1913 code = "from enum import Enum; Enum('Animal', 'ANT BEE CAT DOG')"
1914 code = compile(code, "<string>", "exec")
1915 global_ns = {}
1916 local_ls = {}
1917 exec(code, global_ns, local_ls)
1918
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001919
Ethan Furmane8e61272016-08-20 07:19:31 -07001920class TestOrder(unittest.TestCase):
1921
1922 def test_same_members(self):
1923 class Color(Enum):
1924 _order_ = 'red green blue'
1925 red = 1
1926 green = 2
1927 blue = 3
1928
1929 def test_same_members_with_aliases(self):
1930 class Color(Enum):
1931 _order_ = 'red green blue'
1932 red = 1
1933 green = 2
1934 blue = 3
1935 verde = green
1936
1937 def test_same_members_wrong_order(self):
1938 with self.assertRaisesRegex(TypeError, 'member order does not match _order_'):
1939 class Color(Enum):
1940 _order_ = 'red green blue'
1941 red = 1
1942 blue = 3
1943 green = 2
1944
1945 def test_order_has_extra_members(self):
1946 with self.assertRaisesRegex(TypeError, 'member order does not match _order_'):
1947 class Color(Enum):
1948 _order_ = 'red green blue purple'
1949 red = 1
1950 green = 2
1951 blue = 3
1952
1953 def test_order_has_extra_members_with_aliases(self):
1954 with self.assertRaisesRegex(TypeError, 'member order does not match _order_'):
1955 class Color(Enum):
1956 _order_ = 'red green blue purple'
1957 red = 1
1958 green = 2
1959 blue = 3
1960 verde = green
1961
1962 def test_enum_has_extra_members(self):
1963 with self.assertRaisesRegex(TypeError, 'member order does not match _order_'):
1964 class Color(Enum):
1965 _order_ = 'red green blue'
1966 red = 1
1967 green = 2
1968 blue = 3
1969 purple = 4
1970
1971 def test_enum_has_extra_members_with_aliases(self):
1972 with self.assertRaisesRegex(TypeError, 'member order does not match _order_'):
1973 class Color(Enum):
1974 _order_ = 'red green blue'
1975 red = 1
1976 green = 2
1977 blue = 3
1978 purple = 4
1979 verde = green
1980
1981
Ethan Furman65a5a472016-09-01 23:55:19 -07001982class TestFlag(unittest.TestCase):
Ethan Furmanee47e5c2016-08-31 00:12:15 -07001983 """Tests of the Flags."""
1984
Ethan Furman65a5a472016-09-01 23:55:19 -07001985 class Perm(Flag):
Ethan Furmanee47e5c2016-08-31 00:12:15 -07001986 R, W, X = 4, 2, 1
1987
Ethan Furman65a5a472016-09-01 23:55:19 -07001988 class Open(Flag):
Ethan Furmanee47e5c2016-08-31 00:12:15 -07001989 RO = 0
1990 WO = 1
1991 RW = 2
1992 AC = 3
1993 CE = 1<<19
1994
Rahul Jha94306522018-09-10 23:51:04 +05301995 class Color(Flag):
1996 BLACK = 0
1997 RED = 1
1998 GREEN = 2
1999 BLUE = 4
2000 PURPLE = RED|BLUE
2001
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002002 def test_str(self):
2003 Perm = self.Perm
2004 self.assertEqual(str(Perm.R), 'Perm.R')
2005 self.assertEqual(str(Perm.W), 'Perm.W')
2006 self.assertEqual(str(Perm.X), 'Perm.X')
2007 self.assertEqual(str(Perm.R | Perm.W), 'Perm.R|W')
2008 self.assertEqual(str(Perm.R | Perm.W | Perm.X), 'Perm.R|W|X')
2009 self.assertEqual(str(Perm(0)), 'Perm.0')
2010 self.assertEqual(str(~Perm.R), 'Perm.W|X')
2011 self.assertEqual(str(~Perm.W), 'Perm.R|X')
2012 self.assertEqual(str(~Perm.X), 'Perm.R|W')
2013 self.assertEqual(str(~(Perm.R | Perm.W)), 'Perm.X')
2014 self.assertEqual(str(~(Perm.R | Perm.W | Perm.X)), 'Perm.0')
2015 self.assertEqual(str(Perm(~0)), 'Perm.R|W|X')
2016
2017 Open = self.Open
2018 self.assertEqual(str(Open.RO), 'Open.RO')
2019 self.assertEqual(str(Open.WO), 'Open.WO')
2020 self.assertEqual(str(Open.AC), 'Open.AC')
2021 self.assertEqual(str(Open.RO | Open.CE), 'Open.CE')
2022 self.assertEqual(str(Open.WO | Open.CE), 'Open.CE|WO')
Ethan Furman3515dcc2016-09-18 13:15:41 -07002023 self.assertEqual(str(~Open.RO), 'Open.CE|AC|RW|WO')
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002024 self.assertEqual(str(~Open.WO), 'Open.CE|RW')
2025 self.assertEqual(str(~Open.AC), 'Open.CE')
2026 self.assertEqual(str(~(Open.RO | Open.CE)), 'Open.AC')
2027 self.assertEqual(str(~(Open.WO | Open.CE)), 'Open.RW')
2028
2029 def test_repr(self):
2030 Perm = self.Perm
2031 self.assertEqual(repr(Perm.R), '<Perm.R: 4>')
2032 self.assertEqual(repr(Perm.W), '<Perm.W: 2>')
2033 self.assertEqual(repr(Perm.X), '<Perm.X: 1>')
2034 self.assertEqual(repr(Perm.R | Perm.W), '<Perm.R|W: 6>')
2035 self.assertEqual(repr(Perm.R | Perm.W | Perm.X), '<Perm.R|W|X: 7>')
Ethan Furman27682d22016-09-04 11:39:01 -07002036 self.assertEqual(repr(Perm(0)), '<Perm.0: 0>')
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002037 self.assertEqual(repr(~Perm.R), '<Perm.W|X: 3>')
2038 self.assertEqual(repr(~Perm.W), '<Perm.R|X: 5>')
2039 self.assertEqual(repr(~Perm.X), '<Perm.R|W: 6>')
2040 self.assertEqual(repr(~(Perm.R | Perm.W)), '<Perm.X: 1>')
Ethan Furman27682d22016-09-04 11:39:01 -07002041 self.assertEqual(repr(~(Perm.R | Perm.W | Perm.X)), '<Perm.0: 0>')
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002042 self.assertEqual(repr(Perm(~0)), '<Perm.R|W|X: 7>')
2043
2044 Open = self.Open
2045 self.assertEqual(repr(Open.RO), '<Open.RO: 0>')
2046 self.assertEqual(repr(Open.WO), '<Open.WO: 1>')
2047 self.assertEqual(repr(Open.AC), '<Open.AC: 3>')
2048 self.assertEqual(repr(Open.RO | Open.CE), '<Open.CE: 524288>')
2049 self.assertEqual(repr(Open.WO | Open.CE), '<Open.CE|WO: 524289>')
Ethan Furman3515dcc2016-09-18 13:15:41 -07002050 self.assertEqual(repr(~Open.RO), '<Open.CE|AC|RW|WO: 524291>')
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002051 self.assertEqual(repr(~Open.WO), '<Open.CE|RW: 524290>')
2052 self.assertEqual(repr(~Open.AC), '<Open.CE: 524288>')
2053 self.assertEqual(repr(~(Open.RO | Open.CE)), '<Open.AC: 3>')
2054 self.assertEqual(repr(~(Open.WO | Open.CE)), '<Open.RW: 2>')
2055
2056 def test_or(self):
2057 Perm = self.Perm
2058 for i in Perm:
2059 for j in Perm:
2060 self.assertEqual((i | j), Perm(i.value | j.value))
2061 self.assertEqual((i | j).value, i.value | j.value)
2062 self.assertIs(type(i | j), Perm)
2063 for i in Perm:
2064 self.assertIs(i | i, i)
2065 Open = self.Open
2066 self.assertIs(Open.RO | Open.CE, Open.CE)
2067
2068 def test_and(self):
2069 Perm = self.Perm
2070 RW = Perm.R | Perm.W
2071 RX = Perm.R | Perm.X
2072 WX = Perm.W | Perm.X
2073 RWX = Perm.R | Perm.W | Perm.X
2074 values = list(Perm) + [RW, RX, WX, RWX, Perm(0)]
2075 for i in values:
2076 for j in values:
2077 self.assertEqual((i & j).value, i.value & j.value)
2078 self.assertIs(type(i & j), Perm)
2079 for i in Perm:
2080 self.assertIs(i & i, i)
2081 self.assertIs(i & RWX, i)
2082 self.assertIs(RWX & i, i)
2083 Open = self.Open
2084 self.assertIs(Open.RO & Open.CE, Open.RO)
2085
2086 def test_xor(self):
2087 Perm = self.Perm
2088 for i in Perm:
2089 for j in Perm:
2090 self.assertEqual((i ^ j).value, i.value ^ j.value)
2091 self.assertIs(type(i ^ j), Perm)
2092 for i in Perm:
2093 self.assertIs(i ^ Perm(0), i)
2094 self.assertIs(Perm(0) ^ i, i)
2095 Open = self.Open
2096 self.assertIs(Open.RO ^ Open.CE, Open.CE)
2097 self.assertIs(Open.CE ^ Open.CE, Open.RO)
2098
2099 def test_invert(self):
2100 Perm = self.Perm
2101 RW = Perm.R | Perm.W
2102 RX = Perm.R | Perm.X
2103 WX = Perm.W | Perm.X
2104 RWX = Perm.R | Perm.W | Perm.X
2105 values = list(Perm) + [RW, RX, WX, RWX, Perm(0)]
2106 for i in values:
2107 self.assertIs(type(~i), Perm)
2108 self.assertEqual(~~i, i)
2109 for i in Perm:
2110 self.assertIs(~~i, i)
2111 Open = self.Open
2112 self.assertIs(Open.WO & ~Open.WO, Open.RO)
2113 self.assertIs((Open.WO|Open.CE) & ~Open.WO, Open.CE)
2114
Ethan Furman25d94bb2016-09-02 16:32:32 -07002115 def test_bool(self):
2116 Perm = self.Perm
2117 for f in Perm:
2118 self.assertTrue(f)
2119 Open = self.Open
2120 for f in Open:
2121 self.assertEqual(bool(f.value), bool(f))
2122
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002123 def test_programatic_function_string(self):
Ethan Furman65a5a472016-09-01 23:55:19 -07002124 Perm = Flag('Perm', 'R W X')
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002125 lst = list(Perm)
2126 self.assertEqual(len(lst), len(Perm))
2127 self.assertEqual(len(Perm), 3, Perm)
2128 self.assertEqual(lst, [Perm.R, Perm.W, Perm.X])
2129 for i, n in enumerate('R W X'.split()):
2130 v = 1<<i
2131 e = Perm(v)
2132 self.assertEqual(e.value, v)
2133 self.assertEqual(type(e.value), int)
2134 self.assertEqual(e.name, n)
2135 self.assertIn(e, Perm)
2136 self.assertIs(type(e), Perm)
2137
2138 def test_programatic_function_string_with_start(self):
Ethan Furman65a5a472016-09-01 23:55:19 -07002139 Perm = Flag('Perm', 'R W X', start=8)
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002140 lst = list(Perm)
2141 self.assertEqual(len(lst), len(Perm))
2142 self.assertEqual(len(Perm), 3, Perm)
2143 self.assertEqual(lst, [Perm.R, Perm.W, Perm.X])
2144 for i, n in enumerate('R W X'.split()):
2145 v = 8<<i
2146 e = Perm(v)
2147 self.assertEqual(e.value, v)
2148 self.assertEqual(type(e.value), int)
2149 self.assertEqual(e.name, n)
2150 self.assertIn(e, Perm)
2151 self.assertIs(type(e), Perm)
2152
2153 def test_programatic_function_string_list(self):
Ethan Furman65a5a472016-09-01 23:55:19 -07002154 Perm = Flag('Perm', ['R', 'W', 'X'])
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002155 lst = list(Perm)
2156 self.assertEqual(len(lst), len(Perm))
2157 self.assertEqual(len(Perm), 3, Perm)
2158 self.assertEqual(lst, [Perm.R, Perm.W, Perm.X])
2159 for i, n in enumerate('R W X'.split()):
2160 v = 1<<i
2161 e = Perm(v)
2162 self.assertEqual(e.value, v)
2163 self.assertEqual(type(e.value), int)
2164 self.assertEqual(e.name, n)
2165 self.assertIn(e, Perm)
2166 self.assertIs(type(e), Perm)
2167
2168 def test_programatic_function_iterable(self):
Ethan Furman65a5a472016-09-01 23:55:19 -07002169 Perm = Flag('Perm', (('R', 2), ('W', 8), ('X', 32)))
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002170 lst = list(Perm)
2171 self.assertEqual(len(lst), len(Perm))
2172 self.assertEqual(len(Perm), 3, Perm)
2173 self.assertEqual(lst, [Perm.R, Perm.W, Perm.X])
2174 for i, n in enumerate('R W X'.split()):
2175 v = 1<<(2*i+1)
2176 e = Perm(v)
2177 self.assertEqual(e.value, v)
2178 self.assertEqual(type(e.value), int)
2179 self.assertEqual(e.name, n)
2180 self.assertIn(e, Perm)
2181 self.assertIs(type(e), Perm)
2182
2183 def test_programatic_function_from_dict(self):
Ethan Furman65a5a472016-09-01 23:55:19 -07002184 Perm = Flag('Perm', OrderedDict((('R', 2), ('W', 8), ('X', 32))))
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002185 lst = list(Perm)
2186 self.assertEqual(len(lst), len(Perm))
2187 self.assertEqual(len(Perm), 3, Perm)
2188 self.assertEqual(lst, [Perm.R, Perm.W, Perm.X])
2189 for i, n in enumerate('R W X'.split()):
2190 v = 1<<(2*i+1)
2191 e = Perm(v)
2192 self.assertEqual(e.value, v)
2193 self.assertEqual(type(e.value), int)
2194 self.assertEqual(e.name, n)
2195 self.assertIn(e, Perm)
2196 self.assertIs(type(e), Perm)
2197
Ethan Furman65a5a472016-09-01 23:55:19 -07002198 def test_pickle(self):
2199 if isinstance(FlagStooges, Exception):
2200 raise FlagStooges
2201 test_pickle_dump_load(self.assertIs, FlagStooges.CURLY|FlagStooges.MOE)
2202 test_pickle_dump_load(self.assertIs, FlagStooges)
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002203
Rahul Jha94306522018-09-10 23:51:04 +05302204 def test_contains(self):
2205 Open = self.Open
2206 Color = self.Color
2207 self.assertFalse(Color.BLACK in Open)
2208 self.assertFalse(Open.RO in Color)
2209 with self.assertRaises(TypeError):
2210 'BLACK' in Color
2211 with self.assertRaises(TypeError):
2212 'RO' in Open
2213 with self.assertRaises(TypeError):
2214 1 in Color
2215 with self.assertRaises(TypeError):
2216 1 in Open
2217
2218 def test_member_contains(self):
Ethan Furman65a5a472016-09-01 23:55:19 -07002219 Perm = self.Perm
2220 R, W, X = Perm
2221 RW = R | W
2222 RX = R | X
2223 WX = W | X
2224 RWX = R | W | X
2225 self.assertTrue(R in RW)
2226 self.assertTrue(R in RX)
2227 self.assertTrue(R in RWX)
2228 self.assertTrue(W in RW)
2229 self.assertTrue(W in WX)
2230 self.assertTrue(W in RWX)
2231 self.assertTrue(X in RX)
2232 self.assertTrue(X in WX)
2233 self.assertTrue(X in RWX)
2234 self.assertFalse(R in WX)
2235 self.assertFalse(W in RX)
2236 self.assertFalse(X in RW)
2237
Ethan Furmanc16595e2016-09-10 23:36:59 -07002238 def test_auto_number(self):
2239 class Color(Flag):
2240 red = auto()
2241 blue = auto()
2242 green = auto()
2243
2244 self.assertEqual(list(Color), [Color.red, Color.blue, Color.green])
2245 self.assertEqual(Color.red.value, 1)
2246 self.assertEqual(Color.blue.value, 2)
2247 self.assertEqual(Color.green.value, 4)
2248
2249 def test_auto_number_garbage(self):
2250 with self.assertRaisesRegex(TypeError, 'Invalid Flag value: .not an int.'):
2251 class Color(Flag):
2252 red = 'not an int'
2253 blue = auto()
2254
Ethan Furman3515dcc2016-09-18 13:15:41 -07002255 def test_cascading_failure(self):
2256 class Bizarre(Flag):
2257 c = 3
2258 d = 4
2259 f = 6
2260 # Bizarre.c | Bizarre.d
Walter Dörwald323842c2019-07-18 20:37:13 +02002261 name = "TestFlag.test_cascading_failure.<locals>.Bizarre"
2262 self.assertRaisesRegex(ValueError, "5 is not a valid " + name, Bizarre, 5)
2263 self.assertRaisesRegex(ValueError, "5 is not a valid " + name, Bizarre, 5)
2264 self.assertRaisesRegex(ValueError, "2 is not a valid " + name, Bizarre, 2)
2265 self.assertRaisesRegex(ValueError, "2 is not a valid " + name, Bizarre, 2)
2266 self.assertRaisesRegex(ValueError, "1 is not a valid " + name, Bizarre, 1)
2267 self.assertRaisesRegex(ValueError, "1 is not a valid " + name, Bizarre, 1)
Ethan Furman3515dcc2016-09-18 13:15:41 -07002268
2269 def test_duplicate_auto(self):
2270 class Dupes(Enum):
2271 first = primero = auto()
2272 second = auto()
2273 third = auto()
2274 self.assertEqual([Dupes.first, Dupes.second, Dupes.third], list(Dupes))
2275
2276 def test_bizarre(self):
2277 class Bizarre(Flag):
2278 b = 3
2279 c = 4
2280 d = 6
2281 self.assertEqual(repr(Bizarre(7)), '<Bizarre.d|c|b: 7>')
2282
Ethan Furman5bdab642018-09-21 19:03:09 -07002283 def test_multiple_mixin(self):
2284 class AllMixin:
2285 @classproperty
2286 def ALL(cls):
2287 members = list(cls)
2288 all_value = None
2289 if members:
2290 all_value = members[0]
2291 for member in members[1:]:
2292 all_value |= member
2293 cls.ALL = all_value
2294 return all_value
2295 class StrMixin:
2296 def __str__(self):
2297 return self._name_.lower()
2298 class Color(AllMixin, Flag):
2299 RED = auto()
2300 GREEN = auto()
2301 BLUE = auto()
2302 self.assertEqual(Color.RED.value, 1)
2303 self.assertEqual(Color.GREEN.value, 2)
2304 self.assertEqual(Color.BLUE.value, 4)
2305 self.assertEqual(Color.ALL.value, 7)
2306 self.assertEqual(str(Color.BLUE), 'Color.BLUE')
2307 class Color(AllMixin, StrMixin, Flag):
2308 RED = auto()
2309 GREEN = auto()
2310 BLUE = auto()
2311 self.assertEqual(Color.RED.value, 1)
2312 self.assertEqual(Color.GREEN.value, 2)
2313 self.assertEqual(Color.BLUE.value, 4)
2314 self.assertEqual(Color.ALL.value, 7)
2315 self.assertEqual(str(Color.BLUE), 'blue')
2316 class Color(StrMixin, AllMixin, Flag):
2317 RED = auto()
2318 GREEN = auto()
2319 BLUE = auto()
2320 self.assertEqual(Color.RED.value, 1)
2321 self.assertEqual(Color.GREEN.value, 2)
2322 self.assertEqual(Color.BLUE.value, 4)
2323 self.assertEqual(Color.ALL.value, 7)
2324 self.assertEqual(str(Color.BLUE), 'blue')
2325
Ethan Furman28cf6632017-01-24 12:12:06 -08002326 @support.reap_threads
2327 def test_unique_composite(self):
2328 # override __eq__ to be identity only
2329 class TestFlag(Flag):
2330 one = auto()
2331 two = auto()
2332 three = auto()
2333 four = auto()
2334 five = auto()
2335 six = auto()
2336 seven = auto()
2337 eight = auto()
2338 def __eq__(self, other):
2339 return self is other
2340 def __hash__(self):
2341 return hash(self._value_)
2342 # have multiple threads competing to complete the composite members
2343 seen = set()
2344 failed = False
2345 def cycle_enum():
2346 nonlocal failed
2347 try:
2348 for i in range(256):
2349 seen.add(TestFlag(i))
2350 except Exception:
2351 failed = True
2352 threads = [
2353 threading.Thread(target=cycle_enum)
2354 for _ in range(8)
2355 ]
2356 with support.start_threads(threads):
2357 pass
2358 # check that only 248 members were created
2359 self.assertFalse(
2360 failed,
2361 'at least one thread failed while creating composite members')
2362 self.assertEqual(256, len(seen), 'too many composite members created')
2363
Ethan Furmanc16595e2016-09-10 23:36:59 -07002364
Ethan Furman65a5a472016-09-01 23:55:19 -07002365class TestIntFlag(unittest.TestCase):
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002366 """Tests of the IntFlags."""
2367
Ethan Furman65a5a472016-09-01 23:55:19 -07002368 class Perm(IntFlag):
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002369 X = 1 << 0
2370 W = 1 << 1
2371 R = 1 << 2
2372
Ethan Furman65a5a472016-09-01 23:55:19 -07002373 class Open(IntFlag):
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002374 RO = 0
2375 WO = 1
2376 RW = 2
2377 AC = 3
2378 CE = 1<<19
2379
Rahul Jha94306522018-09-10 23:51:04 +05302380 class Color(IntFlag):
2381 BLACK = 0
2382 RED = 1
2383 GREEN = 2
2384 BLUE = 4
2385 PURPLE = RED|BLUE
2386
Ethan Furman3515dcc2016-09-18 13:15:41 -07002387 def test_type(self):
2388 Perm = self.Perm
2389 Open = self.Open
2390 for f in Perm:
2391 self.assertTrue(isinstance(f, Perm))
2392 self.assertEqual(f, f.value)
2393 self.assertTrue(isinstance(Perm.W | Perm.X, Perm))
2394 self.assertEqual(Perm.W | Perm.X, 3)
2395 for f in Open:
2396 self.assertTrue(isinstance(f, Open))
2397 self.assertEqual(f, f.value)
2398 self.assertTrue(isinstance(Open.WO | Open.RW, Open))
2399 self.assertEqual(Open.WO | Open.RW, 3)
2400
2401
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002402 def test_str(self):
2403 Perm = self.Perm
2404 self.assertEqual(str(Perm.R), 'Perm.R')
2405 self.assertEqual(str(Perm.W), 'Perm.W')
2406 self.assertEqual(str(Perm.X), 'Perm.X')
2407 self.assertEqual(str(Perm.R | Perm.W), 'Perm.R|W')
2408 self.assertEqual(str(Perm.R | Perm.W | Perm.X), 'Perm.R|W|X')
2409 self.assertEqual(str(Perm.R | 8), 'Perm.8|R')
2410 self.assertEqual(str(Perm(0)), 'Perm.0')
2411 self.assertEqual(str(Perm(8)), 'Perm.8')
Ethan Furman3515dcc2016-09-18 13:15:41 -07002412 self.assertEqual(str(~Perm.R), 'Perm.W|X')
2413 self.assertEqual(str(~Perm.W), 'Perm.R|X')
2414 self.assertEqual(str(~Perm.X), 'Perm.R|W')
2415 self.assertEqual(str(~(Perm.R | Perm.W)), 'Perm.X')
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002416 self.assertEqual(str(~(Perm.R | Perm.W | Perm.X)), 'Perm.-8')
Ethan Furman3515dcc2016-09-18 13:15:41 -07002417 self.assertEqual(str(~(Perm.R | 8)), 'Perm.W|X')
2418 self.assertEqual(str(Perm(~0)), 'Perm.R|W|X')
2419 self.assertEqual(str(Perm(~8)), 'Perm.R|W|X')
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002420
2421 Open = self.Open
2422 self.assertEqual(str(Open.RO), 'Open.RO')
2423 self.assertEqual(str(Open.WO), 'Open.WO')
2424 self.assertEqual(str(Open.AC), 'Open.AC')
2425 self.assertEqual(str(Open.RO | Open.CE), 'Open.CE')
2426 self.assertEqual(str(Open.WO | Open.CE), 'Open.CE|WO')
2427 self.assertEqual(str(Open(4)), 'Open.4')
Ethan Furman3515dcc2016-09-18 13:15:41 -07002428 self.assertEqual(str(~Open.RO), 'Open.CE|AC|RW|WO')
2429 self.assertEqual(str(~Open.WO), 'Open.CE|RW')
2430 self.assertEqual(str(~Open.AC), 'Open.CE')
2431 self.assertEqual(str(~(Open.RO | Open.CE)), 'Open.AC|RW|WO')
2432 self.assertEqual(str(~(Open.WO | Open.CE)), 'Open.RW')
2433 self.assertEqual(str(Open(~4)), 'Open.CE|AC|RW|WO')
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002434
2435 def test_repr(self):
2436 Perm = self.Perm
2437 self.assertEqual(repr(Perm.R), '<Perm.R: 4>')
2438 self.assertEqual(repr(Perm.W), '<Perm.W: 2>')
2439 self.assertEqual(repr(Perm.X), '<Perm.X: 1>')
2440 self.assertEqual(repr(Perm.R | Perm.W), '<Perm.R|W: 6>')
2441 self.assertEqual(repr(Perm.R | Perm.W | Perm.X), '<Perm.R|W|X: 7>')
2442 self.assertEqual(repr(Perm.R | 8), '<Perm.8|R: 12>')
Ethan Furman27682d22016-09-04 11:39:01 -07002443 self.assertEqual(repr(Perm(0)), '<Perm.0: 0>')
2444 self.assertEqual(repr(Perm(8)), '<Perm.8: 8>')
Ethan Furman3515dcc2016-09-18 13:15:41 -07002445 self.assertEqual(repr(~Perm.R), '<Perm.W|X: -5>')
2446 self.assertEqual(repr(~Perm.W), '<Perm.R|X: -3>')
2447 self.assertEqual(repr(~Perm.X), '<Perm.R|W: -2>')
2448 self.assertEqual(repr(~(Perm.R | Perm.W)), '<Perm.X: -7>')
Ethan Furman27682d22016-09-04 11:39:01 -07002449 self.assertEqual(repr(~(Perm.R | Perm.W | Perm.X)), '<Perm.-8: -8>')
Ethan Furman3515dcc2016-09-18 13:15:41 -07002450 self.assertEqual(repr(~(Perm.R | 8)), '<Perm.W|X: -13>')
2451 self.assertEqual(repr(Perm(~0)), '<Perm.R|W|X: -1>')
2452 self.assertEqual(repr(Perm(~8)), '<Perm.R|W|X: -9>')
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002453
2454 Open = self.Open
2455 self.assertEqual(repr(Open.RO), '<Open.RO: 0>')
2456 self.assertEqual(repr(Open.WO), '<Open.WO: 1>')
2457 self.assertEqual(repr(Open.AC), '<Open.AC: 3>')
2458 self.assertEqual(repr(Open.RO | Open.CE), '<Open.CE: 524288>')
2459 self.assertEqual(repr(Open.WO | Open.CE), '<Open.CE|WO: 524289>')
Ethan Furman27682d22016-09-04 11:39:01 -07002460 self.assertEqual(repr(Open(4)), '<Open.4: 4>')
Ethan Furman3515dcc2016-09-18 13:15:41 -07002461 self.assertEqual(repr(~Open.RO), '<Open.CE|AC|RW|WO: -1>')
2462 self.assertEqual(repr(~Open.WO), '<Open.CE|RW: -2>')
2463 self.assertEqual(repr(~Open.AC), '<Open.CE: -4>')
2464 self.assertEqual(repr(~(Open.RO | Open.CE)), '<Open.AC|RW|WO: -524289>')
2465 self.assertEqual(repr(~(Open.WO | Open.CE)), '<Open.RW: -524290>')
2466 self.assertEqual(repr(Open(~4)), '<Open.CE|AC|RW|WO: -5>')
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002467
2468 def test_or(self):
2469 Perm = self.Perm
2470 for i in Perm:
2471 for j in Perm:
2472 self.assertEqual(i | j, i.value | j.value)
2473 self.assertEqual((i | j).value, i.value | j.value)
2474 self.assertIs(type(i | j), Perm)
2475 for j in range(8):
2476 self.assertEqual(i | j, i.value | j)
2477 self.assertEqual((i | j).value, i.value | j)
2478 self.assertIs(type(i | j), Perm)
2479 self.assertEqual(j | i, j | i.value)
2480 self.assertEqual((j | i).value, j | i.value)
2481 self.assertIs(type(j | i), Perm)
2482 for i in Perm:
2483 self.assertIs(i | i, i)
2484 self.assertIs(i | 0, i)
2485 self.assertIs(0 | i, i)
2486 Open = self.Open
2487 self.assertIs(Open.RO | Open.CE, Open.CE)
2488
2489 def test_and(self):
2490 Perm = self.Perm
2491 RW = Perm.R | Perm.W
2492 RX = Perm.R | Perm.X
2493 WX = Perm.W | Perm.X
2494 RWX = Perm.R | Perm.W | Perm.X
2495 values = list(Perm) + [RW, RX, WX, RWX, Perm(0)]
2496 for i in values:
2497 for j in values:
2498 self.assertEqual(i & j, i.value & j.value, 'i is %r, j is %r' % (i, j))
2499 self.assertEqual((i & j).value, i.value & j.value, 'i is %r, j is %r' % (i, j))
2500 self.assertIs(type(i & j), Perm, 'i is %r, j is %r' % (i, j))
2501 for j in range(8):
2502 self.assertEqual(i & j, i.value & j)
2503 self.assertEqual((i & j).value, i.value & j)
2504 self.assertIs(type(i & j), Perm)
2505 self.assertEqual(j & i, j & i.value)
2506 self.assertEqual((j & i).value, j & i.value)
2507 self.assertIs(type(j & i), Perm)
2508 for i in Perm:
2509 self.assertIs(i & i, i)
2510 self.assertIs(i & 7, i)
2511 self.assertIs(7 & i, i)
2512 Open = self.Open
2513 self.assertIs(Open.RO & Open.CE, Open.RO)
2514
2515 def test_xor(self):
2516 Perm = self.Perm
2517 for i in Perm:
2518 for j in Perm:
2519 self.assertEqual(i ^ j, i.value ^ j.value)
2520 self.assertEqual((i ^ j).value, i.value ^ j.value)
2521 self.assertIs(type(i ^ j), Perm)
2522 for j in range(8):
2523 self.assertEqual(i ^ j, i.value ^ j)
2524 self.assertEqual((i ^ j).value, i.value ^ j)
2525 self.assertIs(type(i ^ j), Perm)
2526 self.assertEqual(j ^ i, j ^ i.value)
2527 self.assertEqual((j ^ i).value, j ^ i.value)
2528 self.assertIs(type(j ^ i), Perm)
2529 for i in Perm:
2530 self.assertIs(i ^ 0, i)
2531 self.assertIs(0 ^ i, i)
2532 Open = self.Open
2533 self.assertIs(Open.RO ^ Open.CE, Open.CE)
2534 self.assertIs(Open.CE ^ Open.CE, Open.RO)
2535
2536 def test_invert(self):
2537 Perm = self.Perm
2538 RW = Perm.R | Perm.W
2539 RX = Perm.R | Perm.X
2540 WX = Perm.W | Perm.X
2541 RWX = Perm.R | Perm.W | Perm.X
2542 values = list(Perm) + [RW, RX, WX, RWX, Perm(0)]
2543 for i in values:
2544 self.assertEqual(~i, ~i.value)
2545 self.assertEqual((~i).value, ~i.value)
2546 self.assertIs(type(~i), Perm)
2547 self.assertEqual(~~i, i)
2548 for i in Perm:
2549 self.assertIs(~~i, i)
2550 Open = self.Open
2551 self.assertIs(Open.WO & ~Open.WO, Open.RO)
2552 self.assertIs((Open.WO|Open.CE) & ~Open.WO, Open.CE)
2553
2554 def test_programatic_function_string(self):
Ethan Furman65a5a472016-09-01 23:55:19 -07002555 Perm = IntFlag('Perm', 'R W X')
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002556 lst = list(Perm)
2557 self.assertEqual(len(lst), len(Perm))
2558 self.assertEqual(len(Perm), 3, Perm)
2559 self.assertEqual(lst, [Perm.R, Perm.W, Perm.X])
2560 for i, n in enumerate('R W X'.split()):
2561 v = 1<<i
2562 e = Perm(v)
2563 self.assertEqual(e.value, v)
2564 self.assertEqual(type(e.value), int)
2565 self.assertEqual(e, v)
2566 self.assertEqual(e.name, n)
2567 self.assertIn(e, Perm)
2568 self.assertIs(type(e), Perm)
2569
2570 def test_programatic_function_string_with_start(self):
Ethan Furman65a5a472016-09-01 23:55:19 -07002571 Perm = IntFlag('Perm', 'R W X', start=8)
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002572 lst = list(Perm)
2573 self.assertEqual(len(lst), len(Perm))
2574 self.assertEqual(len(Perm), 3, Perm)
2575 self.assertEqual(lst, [Perm.R, Perm.W, Perm.X])
2576 for i, n in enumerate('R W X'.split()):
2577 v = 8<<i
2578 e = Perm(v)
2579 self.assertEqual(e.value, v)
2580 self.assertEqual(type(e.value), int)
2581 self.assertEqual(e, v)
2582 self.assertEqual(e.name, n)
2583 self.assertIn(e, Perm)
2584 self.assertIs(type(e), Perm)
2585
2586 def test_programatic_function_string_list(self):
Ethan Furman65a5a472016-09-01 23:55:19 -07002587 Perm = IntFlag('Perm', ['R', 'W', 'X'])
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002588 lst = list(Perm)
2589 self.assertEqual(len(lst), len(Perm))
2590 self.assertEqual(len(Perm), 3, Perm)
2591 self.assertEqual(lst, [Perm.R, Perm.W, Perm.X])
2592 for i, n in enumerate('R W X'.split()):
2593 v = 1<<i
2594 e = Perm(v)
2595 self.assertEqual(e.value, v)
2596 self.assertEqual(type(e.value), int)
2597 self.assertEqual(e, v)
2598 self.assertEqual(e.name, n)
2599 self.assertIn(e, Perm)
2600 self.assertIs(type(e), Perm)
2601
2602 def test_programatic_function_iterable(self):
Ethan Furman65a5a472016-09-01 23:55:19 -07002603 Perm = IntFlag('Perm', (('R', 2), ('W', 8), ('X', 32)))
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002604 lst = list(Perm)
2605 self.assertEqual(len(lst), len(Perm))
2606 self.assertEqual(len(Perm), 3, Perm)
2607 self.assertEqual(lst, [Perm.R, Perm.W, Perm.X])
2608 for i, n in enumerate('R W X'.split()):
2609 v = 1<<(2*i+1)
2610 e = Perm(v)
2611 self.assertEqual(e.value, v)
2612 self.assertEqual(type(e.value), int)
2613 self.assertEqual(e, v)
2614 self.assertEqual(e.name, n)
2615 self.assertIn(e, Perm)
2616 self.assertIs(type(e), Perm)
2617
2618 def test_programatic_function_from_dict(self):
Ethan Furman65a5a472016-09-01 23:55:19 -07002619 Perm = IntFlag('Perm', OrderedDict((('R', 2), ('W', 8), ('X', 32))))
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002620 lst = list(Perm)
2621 self.assertEqual(len(lst), len(Perm))
2622 self.assertEqual(len(Perm), 3, Perm)
2623 self.assertEqual(lst, [Perm.R, Perm.W, Perm.X])
2624 for i, n in enumerate('R W X'.split()):
2625 v = 1<<(2*i+1)
2626 e = Perm(v)
2627 self.assertEqual(e.value, v)
2628 self.assertEqual(type(e.value), int)
2629 self.assertEqual(e, v)
2630 self.assertEqual(e.name, n)
2631 self.assertIn(e, Perm)
2632 self.assertIs(type(e), Perm)
2633
2634
Dong-hee Nadcc8ce42017-06-22 01:52:32 +09002635 def test_programatic_function_from_empty_list(self):
2636 Perm = enum.IntFlag('Perm', [])
2637 lst = list(Perm)
2638 self.assertEqual(len(lst), len(Perm))
2639 self.assertEqual(len(Perm), 0, Perm)
2640 Thing = enum.Enum('Thing', [])
2641 lst = list(Thing)
2642 self.assertEqual(len(lst), len(Thing))
2643 self.assertEqual(len(Thing), 0, Thing)
2644
2645
2646 def test_programatic_function_from_empty_tuple(self):
2647 Perm = enum.IntFlag('Perm', ())
2648 lst = list(Perm)
2649 self.assertEqual(len(lst), len(Perm))
2650 self.assertEqual(len(Perm), 0, Perm)
2651 Thing = enum.Enum('Thing', ())
2652 self.assertEqual(len(lst), len(Thing))
2653 self.assertEqual(len(Thing), 0, Thing)
2654
Rahul Jha94306522018-09-10 23:51:04 +05302655 def test_contains(self):
2656 Open = self.Open
2657 Color = self.Color
2658 self.assertTrue(Color.GREEN in Color)
2659 self.assertTrue(Open.RW in Open)
2660 self.assertFalse(Color.GREEN in Open)
2661 self.assertFalse(Open.RW in Color)
2662 with self.assertRaises(TypeError):
2663 'GREEN' in Color
2664 with self.assertRaises(TypeError):
2665 'RW' in Open
2666 with self.assertRaises(TypeError):
2667 2 in Color
2668 with self.assertRaises(TypeError):
2669 2 in Open
2670
2671 def test_member_contains(self):
Ethan Furman65a5a472016-09-01 23:55:19 -07002672 Perm = self.Perm
2673 R, W, X = Perm
2674 RW = R | W
2675 RX = R | X
2676 WX = W | X
2677 RWX = R | W | X
2678 self.assertTrue(R in RW)
2679 self.assertTrue(R in RX)
2680 self.assertTrue(R in RWX)
2681 self.assertTrue(W in RW)
2682 self.assertTrue(W in WX)
2683 self.assertTrue(W in RWX)
2684 self.assertTrue(X in RX)
2685 self.assertTrue(X in WX)
2686 self.assertTrue(X in RWX)
2687 self.assertFalse(R in WX)
2688 self.assertFalse(W in RX)
2689 self.assertFalse(X in RW)
Rahul Jha94306522018-09-10 23:51:04 +05302690 with self.assertRaises(TypeError):
2691 self.assertFalse('test' in RW)
Ethan Furman65a5a472016-09-01 23:55:19 -07002692
Ethan Furman25d94bb2016-09-02 16:32:32 -07002693 def test_bool(self):
2694 Perm = self.Perm
2695 for f in Perm:
2696 self.assertTrue(f)
2697 Open = self.Open
2698 for f in Open:
2699 self.assertEqual(bool(f.value), bool(f))
2700
Ethan Furman5bdab642018-09-21 19:03:09 -07002701 def test_multiple_mixin(self):
2702 class AllMixin:
2703 @classproperty
2704 def ALL(cls):
2705 members = list(cls)
2706 all_value = None
2707 if members:
2708 all_value = members[0]
2709 for member in members[1:]:
2710 all_value |= member
2711 cls.ALL = all_value
2712 return all_value
2713 class StrMixin:
2714 def __str__(self):
2715 return self._name_.lower()
2716 class Color(AllMixin, IntFlag):
2717 RED = auto()
2718 GREEN = auto()
2719 BLUE = auto()
2720 self.assertEqual(Color.RED.value, 1)
2721 self.assertEqual(Color.GREEN.value, 2)
2722 self.assertEqual(Color.BLUE.value, 4)
2723 self.assertEqual(Color.ALL.value, 7)
2724 self.assertEqual(str(Color.BLUE), 'Color.BLUE')
2725 class Color(AllMixin, StrMixin, IntFlag):
2726 RED = auto()
2727 GREEN = auto()
2728 BLUE = auto()
2729 self.assertEqual(Color.RED.value, 1)
2730 self.assertEqual(Color.GREEN.value, 2)
2731 self.assertEqual(Color.BLUE.value, 4)
2732 self.assertEqual(Color.ALL.value, 7)
2733 self.assertEqual(str(Color.BLUE), 'blue')
2734 class Color(StrMixin, AllMixin, IntFlag):
2735 RED = auto()
2736 GREEN = auto()
2737 BLUE = auto()
2738 self.assertEqual(Color.RED.value, 1)
2739 self.assertEqual(Color.GREEN.value, 2)
2740 self.assertEqual(Color.BLUE.value, 4)
2741 self.assertEqual(Color.ALL.value, 7)
2742 self.assertEqual(str(Color.BLUE), 'blue')
2743
Ethan Furman28cf6632017-01-24 12:12:06 -08002744 @support.reap_threads
2745 def test_unique_composite(self):
2746 # override __eq__ to be identity only
2747 class TestFlag(IntFlag):
2748 one = auto()
2749 two = auto()
2750 three = auto()
2751 four = auto()
2752 five = auto()
2753 six = auto()
2754 seven = auto()
2755 eight = auto()
2756 def __eq__(self, other):
2757 return self is other
2758 def __hash__(self):
2759 return hash(self._value_)
2760 # have multiple threads competing to complete the composite members
2761 seen = set()
2762 failed = False
2763 def cycle_enum():
2764 nonlocal failed
2765 try:
2766 for i in range(256):
2767 seen.add(TestFlag(i))
2768 except Exception:
2769 failed = True
2770 threads = [
2771 threading.Thread(target=cycle_enum)
2772 for _ in range(8)
2773 ]
2774 with support.start_threads(threads):
2775 pass
2776 # check that only 248 members were created
2777 self.assertFalse(
2778 failed,
2779 'at least one thread failed while creating composite members')
2780 self.assertEqual(256, len(seen), 'too many composite members created')
2781
2782
Brennan D Baraban8b914d22019-03-03 14:09:11 -08002783class TestEmptyAndNonLatinStrings(unittest.TestCase):
2784
2785 def test_empty_string(self):
2786 with self.assertRaises(ValueError):
2787 empty_abc = Enum('empty_abc', ('', 'B', 'C'))
2788
2789 def test_non_latin_character_string(self):
2790 greek_abc = Enum('greek_abc', ('\u03B1', 'B', 'C'))
2791 item = getattr(greek_abc, '\u03B1')
2792 self.assertEqual(item.value, 1)
2793
2794 def test_non_latin_number_string(self):
2795 hebrew_123 = Enum('hebrew_123', ('\u05D0', '2', '3'))
2796 item = getattr(hebrew_123, '\u05D0')
2797 self.assertEqual(item.value, 1)
2798
2799
Ethan Furmanf24bb352013-07-18 17:05:39 -07002800class TestUnique(unittest.TestCase):
2801
2802 def test_unique_clean(self):
2803 @unique
2804 class Clean(Enum):
2805 one = 1
2806 two = 'dos'
2807 tres = 4.0
2808 @unique
2809 class Cleaner(IntEnum):
2810 single = 1
2811 double = 2
2812 triple = 3
2813
2814 def test_unique_dirty(self):
2815 with self.assertRaisesRegex(ValueError, 'tres.*one'):
2816 @unique
2817 class Dirty(Enum):
2818 one = 1
2819 two = 'dos'
2820 tres = 1
2821 with self.assertRaisesRegex(
2822 ValueError,
2823 'double.*single.*turkey.*triple',
2824 ):
2825 @unique
2826 class Dirtier(IntEnum):
2827 single = 1
2828 double = 1
2829 triple = 3
2830 turkey = 3
2831
Ethan Furman3803ad42016-05-01 10:03:53 -07002832 def test_unique_with_name(self):
2833 @unique
2834 class Silly(Enum):
2835 one = 1
2836 two = 'dos'
2837 name = 3
2838 @unique
2839 class Sillier(IntEnum):
2840 single = 1
2841 name = 2
2842 triple = 3
2843 value = 4
2844
Ethan Furmanf24bb352013-07-18 17:05:39 -07002845
Ethan Furman5bdab642018-09-21 19:03:09 -07002846
Ethan Furman3323da92015-04-11 09:39:59 -07002847expected_help_output_with_docs = """\
Ethan Furman5875d742013-10-21 20:45:55 -07002848Help on class Color in module %s:
2849
2850class Color(enum.Enum)
Serhiy Storchaka90f63322017-01-24 09:06:22 +02002851 | Color(value, names=None, *, module=None, qualname=None, type=None, start=1)
2852 |\x20\x20
Ethan Furman48a724f2015-04-11 23:23:06 -07002853 | An enumeration.
Serhiy Storchakab599ca82015-04-04 12:48:04 +03002854 |\x20\x20
Ethan Furman5875d742013-10-21 20:45:55 -07002855 | Method resolution order:
2856 | Color
2857 | enum.Enum
2858 | builtins.object
2859 |\x20\x20
2860 | Data and other attributes defined here:
2861 |\x20\x20
2862 | blue = <Color.blue: 3>
2863 |\x20\x20
2864 | green = <Color.green: 2>
2865 |\x20\x20
2866 | red = <Color.red: 1>
2867 |\x20\x20
2868 | ----------------------------------------------------------------------
2869 | Data descriptors inherited from enum.Enum:
2870 |\x20\x20
2871 | name
2872 | The name of the Enum member.
2873 |\x20\x20
2874 | value
2875 | The value of the Enum member.
2876 |\x20\x20
2877 | ----------------------------------------------------------------------
Raymond Hettinger62be3382019-03-24 17:07:47 -07002878 | Readonly properties inherited from enum.EnumMeta:
Ethan Furman5875d742013-10-21 20:45:55 -07002879 |\x20\x20
2880 | __members__
2881 | Returns a mapping of member name->value.
2882 |\x20\x20\x20\x20\x20\x20
2883 | This mapping lists all enum members, including aliases. Note that this
Ethan Furman3323da92015-04-11 09:39:59 -07002884 | is a read-only view of the internal mapping."""
2885
2886expected_help_output_without_docs = """\
2887Help on class Color in module %s:
2888
2889class Color(enum.Enum)
Serhiy Storchaka90f63322017-01-24 09:06:22 +02002890 | Color(value, names=None, *, module=None, qualname=None, type=None, start=1)
2891 |\x20\x20
Ethan Furman3323da92015-04-11 09:39:59 -07002892 | Method resolution order:
2893 | Color
2894 | enum.Enum
2895 | builtins.object
2896 |\x20\x20
2897 | Data and other attributes defined here:
2898 |\x20\x20
2899 | blue = <Color.blue: 3>
2900 |\x20\x20
2901 | green = <Color.green: 2>
2902 |\x20\x20
2903 | red = <Color.red: 1>
2904 |\x20\x20
2905 | ----------------------------------------------------------------------
2906 | Data descriptors inherited from enum.Enum:
2907 |\x20\x20
2908 | name
2909 |\x20\x20
2910 | value
2911 |\x20\x20
2912 | ----------------------------------------------------------------------
2913 | Data descriptors inherited from enum.EnumMeta:
2914 |\x20\x20
2915 | __members__"""
Ethan Furman5875d742013-10-21 20:45:55 -07002916
2917class TestStdLib(unittest.TestCase):
2918
Ethan Furman48a724f2015-04-11 23:23:06 -07002919 maxDiff = None
2920
Ethan Furman5875d742013-10-21 20:45:55 -07002921 class Color(Enum):
2922 red = 1
2923 green = 2
2924 blue = 3
2925
2926 def test_pydoc(self):
2927 # indirectly test __objclass__
Ethan Furman3323da92015-04-11 09:39:59 -07002928 if StrEnum.__doc__ is None:
2929 expected_text = expected_help_output_without_docs % __name__
2930 else:
2931 expected_text = expected_help_output_with_docs % __name__
Ethan Furman5875d742013-10-21 20:45:55 -07002932 output = StringIO()
2933 helper = pydoc.Helper(output=output)
2934 helper(self.Color)
2935 result = output.getvalue().strip()
Victor Stinner4b0432d2014-06-16 22:48:43 +02002936 self.assertEqual(result, expected_text)
Ethan Furman5875d742013-10-21 20:45:55 -07002937
2938 def test_inspect_getmembers(self):
2939 values = dict((
2940 ('__class__', EnumMeta),
Ethan Furman48a724f2015-04-11 23:23:06 -07002941 ('__doc__', 'An enumeration.'),
Ethan Furman5875d742013-10-21 20:45:55 -07002942 ('__members__', self.Color.__members__),
2943 ('__module__', __name__),
2944 ('blue', self.Color.blue),
2945 ('green', self.Color.green),
2946 ('name', Enum.__dict__['name']),
2947 ('red', self.Color.red),
2948 ('value', Enum.__dict__['value']),
2949 ))
2950 result = dict(inspect.getmembers(self.Color))
2951 self.assertEqual(values.keys(), result.keys())
2952 failed = False
2953 for k in values.keys():
2954 if result[k] != values[k]:
2955 print()
2956 print('\n%s\n key: %s\n result: %s\nexpected: %s\n%s\n' %
2957 ('=' * 75, k, result[k], values[k], '=' * 75), sep='')
2958 failed = True
2959 if failed:
2960 self.fail("result does not equal expected, see print above")
2961
2962 def test_inspect_classify_class_attrs(self):
2963 # indirectly test __objclass__
2964 from inspect import Attribute
2965 values = [
2966 Attribute(name='__class__', kind='data',
2967 defining_class=object, object=EnumMeta),
2968 Attribute(name='__doc__', kind='data',
Ethan Furman48a724f2015-04-11 23:23:06 -07002969 defining_class=self.Color, object='An enumeration.'),
Ethan Furman5875d742013-10-21 20:45:55 -07002970 Attribute(name='__members__', kind='property',
2971 defining_class=EnumMeta, object=EnumMeta.__members__),
2972 Attribute(name='__module__', kind='data',
2973 defining_class=self.Color, object=__name__),
2974 Attribute(name='blue', kind='data',
2975 defining_class=self.Color, object=self.Color.blue),
2976 Attribute(name='green', kind='data',
2977 defining_class=self.Color, object=self.Color.green),
2978 Attribute(name='red', kind='data',
2979 defining_class=self.Color, object=self.Color.red),
2980 Attribute(name='name', kind='data',
2981 defining_class=Enum, object=Enum.__dict__['name']),
2982 Attribute(name='value', kind='data',
2983 defining_class=Enum, object=Enum.__dict__['value']),
2984 ]
2985 values.sort(key=lambda item: item.name)
2986 result = list(inspect.classify_class_attrs(self.Color))
2987 result.sort(key=lambda item: item.name)
2988 failed = False
2989 for v, r in zip(values, result):
2990 if r != v:
2991 print('\n%s\n%s\n%s\n%s\n' % ('=' * 75, r, v, '=' * 75), sep='')
2992 failed = True
2993 if failed:
2994 self.fail("result does not equal expected, see print above")
2995
Martin Panter19e69c52015-11-14 12:46:42 +00002996
2997class MiscTestCase(unittest.TestCase):
2998 def test__all__(self):
2999 support.check__all__(self, enum)
3000
3001
Gregory P. Smith ext:(%20%5BGoogle%20Inc.%5D)6f20bd62016-06-03 19:14:52 +00003002# These are unordered here on purpose to ensure that declaration order
3003# makes no difference.
3004CONVERT_TEST_NAME_D = 5
3005CONVERT_TEST_NAME_C = 5
3006CONVERT_TEST_NAME_B = 5
3007CONVERT_TEST_NAME_A = 5 # This one should sort first.
3008CONVERT_TEST_NAME_E = 5
3009CONVERT_TEST_NAME_F = 5
3010
3011class TestIntEnumConvert(unittest.TestCase):
3012 def test_convert_value_lookup_priority(self):
orlnub1230fb9fad2018-09-12 20:28:53 +03003013 test_type = enum.IntEnum._convert_(
Ethan Furman28cf6632017-01-24 12:12:06 -08003014 'UnittestConvert',
3015 ('test.test_enum', '__main__')[__name__=='__main__'],
Gregory P. Smith ext:(%20%5BGoogle%20Inc.%5D)6f20bd62016-06-03 19:14:52 +00003016 filter=lambda x: x.startswith('CONVERT_TEST_'))
3017 # We don't want the reverse lookup value to vary when there are
3018 # multiple possible names for a given value. It should always
3019 # report the first lexigraphical name in that case.
3020 self.assertEqual(test_type(5).name, 'CONVERT_TEST_NAME_A')
3021
3022 def test_convert(self):
orlnub1230fb9fad2018-09-12 20:28:53 +03003023 test_type = enum.IntEnum._convert_(
Ethan Furman28cf6632017-01-24 12:12:06 -08003024 'UnittestConvert',
3025 ('test.test_enum', '__main__')[__name__=='__main__'],
Gregory P. Smith ext:(%20%5BGoogle%20Inc.%5D)6f20bd62016-06-03 19:14:52 +00003026 filter=lambda x: x.startswith('CONVERT_TEST_'))
3027 # Ensure that test_type has all of the desired names and values.
3028 self.assertEqual(test_type.CONVERT_TEST_NAME_F,
3029 test_type.CONVERT_TEST_NAME_A)
3030 self.assertEqual(test_type.CONVERT_TEST_NAME_B, 5)
3031 self.assertEqual(test_type.CONVERT_TEST_NAME_C, 5)
3032 self.assertEqual(test_type.CONVERT_TEST_NAME_D, 5)
3033 self.assertEqual(test_type.CONVERT_TEST_NAME_E, 5)
3034 # Ensure that test_type only picked up names matching the filter.
3035 self.assertEqual([name for name in dir(test_type)
3036 if name[0:2] not in ('CO', '__')],
3037 [], msg='Names other than CONVERT_TEST_* found.')
3038
orlnub1230fb9fad2018-09-12 20:28:53 +03003039 @unittest.skipUnless(sys.version_info[:2] == (3, 8),
3040 '_convert was deprecated in 3.8')
3041 def test_convert_warn(self):
3042 with self.assertWarns(DeprecationWarning):
3043 enum.IntEnum._convert(
3044 'UnittestConvert',
3045 ('test.test_enum', '__main__')[__name__=='__main__'],
3046 filter=lambda x: x.startswith('CONVERT_TEST_'))
3047
3048 @unittest.skipUnless(sys.version_info >= (3, 9),
3049 '_convert was removed in 3.9')
3050 def test_convert_raise(self):
3051 with self.assertRaises(AttributeError):
3052 enum.IntEnum._convert(
3053 'UnittestConvert',
3054 ('test.test_enum', '__main__')[__name__=='__main__'],
3055 filter=lambda x: x.startswith('CONVERT_TEST_'))
3056
Gregory P. Smith ext:(%20%5BGoogle%20Inc.%5D)6f20bd62016-06-03 19:14:52 +00003057
Ethan Furman6b3d64a2013-06-14 16:55:46 -07003058if __name__ == '__main__':
3059 unittest.main()