blob: 3431040f98a726d28f737e30c47b10df8075c61b [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 Furman0063ff42020-09-21 17:23:13 -07008from enum import Enum, IntEnum, StrEnum, 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
Hai Shie80697d2020-05-28 06:10:27 +080013from test.support import threading_helper
Ethan Furmana4b1bb42018-01-22 07:56:37 -080014from datetime import timedelta
Ethan Furman28cf6632017-01-24 12:12:06 -080015
Ethan Furman6b3d64a2013-06-14 16:55:46 -070016
17# for pickle tests
18try:
19 class Stooges(Enum):
20 LARRY = 1
21 CURLY = 2
22 MOE = 3
23except Exception as exc:
24 Stooges = exc
25
26try:
27 class IntStooges(int, Enum):
28 LARRY = 1
29 CURLY = 2
30 MOE = 3
31except Exception as exc:
32 IntStooges = exc
33
34try:
35 class FloatStooges(float, Enum):
36 LARRY = 1.39
37 CURLY = 2.72
38 MOE = 3.142596
39except Exception as exc:
40 FloatStooges = exc
41
Ethan Furman65a5a472016-09-01 23:55:19 -070042try:
43 class FlagStooges(Flag):
44 LARRY = 1
45 CURLY = 2
46 MOE = 3
47except Exception as exc:
48 FlagStooges = exc
49
Ethan Furman6b3d64a2013-06-14 16:55:46 -070050# for pickle test and subclass tests
Ethan Furman0063ff42020-09-21 17:23:13 -070051class Name(StrEnum):
52 BDFL = 'Guido van Rossum'
53 FLUFL = 'Barry Warsaw'
Ethan Furman6b3d64a2013-06-14 16:55:46 -070054
55try:
56 Question = Enum('Question', 'who what when where why', module=__name__)
57except Exception as exc:
58 Question = exc
59
60try:
61 Answer = Enum('Answer', 'him this then there because')
62except Exception as exc:
63 Answer = exc
64
Ethan Furmanca1b7942014-02-08 11:36:27 -080065try:
66 Theory = Enum('Theory', 'rule law supposition', qualname='spanish_inquisition')
67except Exception as exc:
68 Theory = exc
69
Ethan Furman6b3d64a2013-06-14 16:55:46 -070070# for doctests
71try:
72 class Fruit(Enum):
Ethan Furman23bb6f42016-11-21 09:22:05 -080073 TOMATO = 1
74 BANANA = 2
75 CHERRY = 3
Ethan Furman6b3d64a2013-06-14 16:55:46 -070076except Exception:
77 pass
78
Serhiy Storchakae50e7802015-03-31 16:56:49 +030079def test_pickle_dump_load(assertion, source, target=None):
Ethan Furman2ddb39a2014-02-06 17:28:50 -080080 if target is None:
81 target = source
Serhiy Storchakae50e7802015-03-31 16:56:49 +030082 for protocol in range(HIGHEST_PROTOCOL + 1):
Ethan Furman2ddb39a2014-02-06 17:28:50 -080083 assertion(loads(dumps(source, protocol=protocol)), target)
84
Serhiy Storchakae50e7802015-03-31 16:56:49 +030085def test_pickle_exception(assertion, exception, obj):
86 for protocol in range(HIGHEST_PROTOCOL + 1):
Ethan Furman2ddb39a2014-02-06 17:28:50 -080087 with assertion(exception):
88 dumps(obj, protocol=protocol)
Ethan Furman648f8602013-10-06 17:19:54 -070089
90class TestHelpers(unittest.TestCase):
91 # _is_descriptor, _is_sunder, _is_dunder
92
93 def test_is_descriptor(self):
94 class foo:
95 pass
96 for attr in ('__get__','__set__','__delete__'):
97 obj = foo()
98 self.assertFalse(enum._is_descriptor(obj))
99 setattr(obj, attr, 1)
100 self.assertTrue(enum._is_descriptor(obj))
101
102 def test_is_sunder(self):
103 for s in ('_a_', '_aa_'):
104 self.assertTrue(enum._is_sunder(s))
105
106 for s in ('a', 'a_', '_a', '__a', 'a__', '__a__', '_a__', '__a_', '_',
107 '__', '___', '____', '_____',):
108 self.assertFalse(enum._is_sunder(s))
109
110 def test_is_dunder(self):
111 for s in ('__a__', '__aa__'):
112 self.assertTrue(enum._is_dunder(s))
113 for s in ('a', 'a_', '_a', '__a', 'a__', '_a_', '_a__', '__a_', '_',
114 '__', '___', '____', '_____',):
115 self.assertFalse(enum._is_dunder(s))
116
Ethan Furman5bdab642018-09-21 19:03:09 -0700117# for subclassing tests
118
119class classproperty:
120
121 def __init__(self, fget=None, fset=None, fdel=None, doc=None):
122 self.fget = fget
123 self.fset = fset
124 self.fdel = fdel
125 if doc is None and fget is not None:
126 doc = fget.__doc__
127 self.__doc__ = doc
128
129 def __get__(self, instance, ownerclass):
130 return self.fget(ownerclass)
131
132
Ethan Furmanc16595e2016-09-10 23:36:59 -0700133# tests
Ethan Furman648f8602013-10-06 17:19:54 -0700134
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700135class TestEnum(unittest.TestCase):
Ethan Furmanca1b7942014-02-08 11:36:27 -0800136
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700137 def setUp(self):
138 class Season(Enum):
139 SPRING = 1
140 SUMMER = 2
141 AUTUMN = 3
142 WINTER = 4
143 self.Season = Season
144
Ethan Furmanec15a822013-08-31 19:17:41 -0700145 class Konstants(float, Enum):
146 E = 2.7182818
147 PI = 3.1415926
148 TAU = 2 * PI
149 self.Konstants = Konstants
150
151 class Grades(IntEnum):
152 A = 5
153 B = 4
154 C = 3
155 D = 2
156 F = 0
157 self.Grades = Grades
158
159 class Directional(str, Enum):
160 EAST = 'east'
161 WEST = 'west'
162 NORTH = 'north'
163 SOUTH = 'south'
164 self.Directional = Directional
165
166 from datetime import date
167 class Holiday(date, Enum):
168 NEW_YEAR = 2013, 1, 1
169 IDES_OF_MARCH = 2013, 3, 15
170 self.Holiday = Holiday
171
Ethan Furman388a3922013-08-12 06:51:41 -0700172 def test_dir_on_class(self):
173 Season = self.Season
174 self.assertEqual(
175 set(dir(Season)),
Ethan Furmanc850f342013-09-15 16:59:35 -0700176 set(['__class__', '__doc__', '__members__', '__module__',
Ethan Furman388a3922013-08-12 06:51:41 -0700177 'SPRING', 'SUMMER', 'AUTUMN', 'WINTER']),
178 )
179
180 def test_dir_on_item(self):
181 Season = self.Season
182 self.assertEqual(
183 set(dir(Season.WINTER)),
Ethan Furmanc850f342013-09-15 16:59:35 -0700184 set(['__class__', '__doc__', '__module__', 'name', 'value']),
Ethan Furman388a3922013-08-12 06:51:41 -0700185 )
186
Ethan Furmanc850f342013-09-15 16:59:35 -0700187 def test_dir_with_added_behavior(self):
188 class Test(Enum):
189 this = 'that'
190 these = 'those'
191 def wowser(self):
192 return ("Wowser! I'm %s!" % self.name)
193 self.assertEqual(
194 set(dir(Test)),
195 set(['__class__', '__doc__', '__members__', '__module__', 'this', 'these']),
196 )
197 self.assertEqual(
198 set(dir(Test.this)),
199 set(['__class__', '__doc__', '__module__', 'name', 'value', 'wowser']),
200 )
201
Ethan Furman0ae550b2014-10-14 08:58:32 -0700202 def test_dir_on_sub_with_behavior_on_super(self):
203 # see issue22506
204 class SuperEnum(Enum):
205 def invisible(self):
206 return "did you see me?"
207 class SubEnum(SuperEnum):
208 sample = 5
209 self.assertEqual(
210 set(dir(SubEnum.sample)),
211 set(['__class__', '__doc__', '__module__', 'name', 'value', 'invisible']),
212 )
213
Angelin BOOZ68526fe2020-09-21 15:11:06 +0200214 def test_dir_on_sub_with_behavior_including_instance_dict_on_super(self):
215 # see issue40084
216 class SuperEnum(IntEnum):
217 def __new__(cls, value, description=""):
218 obj = int.__new__(cls, value)
219 obj._value_ = value
220 obj.description = description
221 return obj
222 class SubEnum(SuperEnum):
223 sample = 5
224 self.assertTrue({'description'} <= set(dir(SubEnum.sample)))
225
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700226 def test_enum_in_enum_out(self):
227 Season = self.Season
228 self.assertIs(Season(Season.WINTER), Season.WINTER)
229
230 def test_enum_value(self):
231 Season = self.Season
232 self.assertEqual(Season.SPRING.value, 1)
233
234 def test_intenum_value(self):
235 self.assertEqual(IntStooges.CURLY.value, 2)
236
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700237 def test_enum(self):
238 Season = self.Season
239 lst = list(Season)
240 self.assertEqual(len(lst), len(Season))
241 self.assertEqual(len(Season), 4, Season)
242 self.assertEqual(
243 [Season.SPRING, Season.SUMMER, Season.AUTUMN, Season.WINTER], lst)
244
245 for i, season in enumerate('SPRING SUMMER AUTUMN WINTER'.split(), 1):
246 e = Season(i)
247 self.assertEqual(e, getattr(Season, season))
248 self.assertEqual(e.value, i)
249 self.assertNotEqual(e, i)
250 self.assertEqual(e.name, season)
251 self.assertIn(e, Season)
252 self.assertIs(type(e), Season)
253 self.assertIsInstance(e, Season)
254 self.assertEqual(str(e), 'Season.' + season)
255 self.assertEqual(
256 repr(e),
257 '<Season.{0}: {1}>'.format(season, i),
258 )
259
260 def test_value_name(self):
261 Season = self.Season
262 self.assertEqual(Season.SPRING.name, 'SPRING')
263 self.assertEqual(Season.SPRING.value, 1)
264 with self.assertRaises(AttributeError):
265 Season.SPRING.name = 'invierno'
266 with self.assertRaises(AttributeError):
267 Season.SPRING.value = 2
268
Ethan Furmanf203f2d2013-09-06 07:16:48 -0700269 def test_changing_member(self):
270 Season = self.Season
271 with self.assertRaises(AttributeError):
272 Season.WINTER = 'really cold'
273
Ethan Furman64a99722013-09-22 16:18:19 -0700274 def test_attribute_deletion(self):
275 class Season(Enum):
276 SPRING = 1
277 SUMMER = 2
278 AUTUMN = 3
279 WINTER = 4
280
281 def spam(cls):
282 pass
283
284 self.assertTrue(hasattr(Season, 'spam'))
285 del Season.spam
286 self.assertFalse(hasattr(Season, 'spam'))
287
288 with self.assertRaises(AttributeError):
289 del Season.SPRING
290 with self.assertRaises(AttributeError):
291 del Season.DRY
292 with self.assertRaises(AttributeError):
293 del Season.SPRING.name
294
Ethan Furman5de67b12016-04-13 23:52:09 -0700295 def test_bool_of_class(self):
296 class Empty(Enum):
297 pass
298 self.assertTrue(bool(Empty))
299
300 def test_bool_of_member(self):
301 class Count(Enum):
302 zero = 0
303 one = 1
304 two = 2
305 for member in Count:
306 self.assertTrue(bool(member))
307
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700308 def test_invalid_names(self):
309 with self.assertRaises(ValueError):
310 class Wrong(Enum):
311 mro = 9
312 with self.assertRaises(ValueError):
313 class Wrong(Enum):
314 _create_= 11
315 with self.assertRaises(ValueError):
316 class Wrong(Enum):
317 _get_mixins_ = 9
318 with self.assertRaises(ValueError):
319 class Wrong(Enum):
320 _find_new_ = 1
321 with self.assertRaises(ValueError):
322 class Wrong(Enum):
323 _any_name_ = 9
324
Ethan Furman6db1fd52015-09-17 21:49:12 -0700325 def test_bool(self):
Ethan Furman60255b62016-01-15 15:01:33 -0800326 # plain Enum members are always True
Ethan Furman6db1fd52015-09-17 21:49:12 -0700327 class Logic(Enum):
328 true = True
329 false = False
330 self.assertTrue(Logic.true)
Ethan Furman60255b62016-01-15 15:01:33 -0800331 self.assertTrue(Logic.false)
332 # unless overridden
333 class RealLogic(Enum):
334 true = True
335 false = False
336 def __bool__(self):
337 return bool(self._value_)
338 self.assertTrue(RealLogic.true)
339 self.assertFalse(RealLogic.false)
340 # mixed Enums depend on mixed-in type
341 class IntLogic(int, Enum):
342 true = 1
343 false = 0
344 self.assertTrue(IntLogic.true)
345 self.assertFalse(IntLogic.false)
Ethan Furman6db1fd52015-09-17 21:49:12 -0700346
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700347 def test_contains(self):
348 Season = self.Season
349 self.assertIn(Season.AUTUMN, Season)
Rahul Jha94306522018-09-10 23:51:04 +0530350 with self.assertRaises(TypeError):
351 3 in Season
352 with self.assertRaises(TypeError):
353 'AUTUMN' in Season
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700354
355 val = Season(3)
356 self.assertIn(val, Season)
357
358 class OtherEnum(Enum):
359 one = 1; two = 2
360 self.assertNotIn(OtherEnum.two, Season)
361
362 def test_comparisons(self):
363 Season = self.Season
364 with self.assertRaises(TypeError):
365 Season.SPRING < Season.WINTER
366 with self.assertRaises(TypeError):
367 Season.SPRING > 4
368
369 self.assertNotEqual(Season.SPRING, 1)
370
371 class Part(Enum):
372 SPRING = 1
373 CLIP = 2
374 BARREL = 3
375
376 self.assertNotEqual(Season.SPRING, Part.SPRING)
377 with self.assertRaises(TypeError):
378 Season.SPRING < Part.CLIP
379
380 def test_enum_duplicates(self):
381 class Season(Enum):
382 SPRING = 1
383 SUMMER = 2
384 AUTUMN = FALL = 3
385 WINTER = 4
386 ANOTHER_SPRING = 1
387 lst = list(Season)
388 self.assertEqual(
389 lst,
390 [Season.SPRING, Season.SUMMER,
391 Season.AUTUMN, Season.WINTER,
392 ])
393 self.assertIs(Season.FALL, Season.AUTUMN)
394 self.assertEqual(Season.FALL.value, 3)
395 self.assertEqual(Season.AUTUMN.value, 3)
396 self.assertIs(Season(3), Season.AUTUMN)
397 self.assertIs(Season(1), Season.SPRING)
398 self.assertEqual(Season.FALL.name, 'AUTUMN')
399 self.assertEqual(
400 [k for k,v in Season.__members__.items() if v.name != k],
401 ['FALL', 'ANOTHER_SPRING'],
402 )
403
Ethan Furman101e0742013-09-15 12:34:36 -0700404 def test_duplicate_name(self):
405 with self.assertRaises(TypeError):
406 class Color(Enum):
407 red = 1
408 green = 2
409 blue = 3
410 red = 4
411
412 with self.assertRaises(TypeError):
413 class Color(Enum):
414 red = 1
415 green = 2
416 blue = 3
417 def red(self):
418 return 'red'
419
420 with self.assertRaises(TypeError):
421 class Color(Enum):
422 @property
423 def red(self):
424 return 'redder'
425 red = 1
426 green = 2
427 blue = 3
428
Zackery Spytz2ec67522020-09-13 14:27:51 -0600429 def test_reserved__sunder_(self):
Ethan Furman5a565b32020-09-15 12:27:06 -0700430 with self.assertRaisesRegex(
431 ValueError,
432 '_sunder_ names, such as "_bad_", are reserved',
433 ):
Zackery Spytz2ec67522020-09-13 14:27:51 -0600434 class Bad(Enum):
435 _bad_ = 1
Ethan Furman101e0742013-09-15 12:34:36 -0700436
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700437 def test_enum_with_value_name(self):
438 class Huh(Enum):
439 name = 1
440 value = 2
441 self.assertEqual(
442 list(Huh),
443 [Huh.name, Huh.value],
444 )
445 self.assertIs(type(Huh.name), Huh)
446 self.assertEqual(Huh.name.name, 'name')
447 self.assertEqual(Huh.name.value, 1)
Ethan Furmanec15a822013-08-31 19:17:41 -0700448
449 def test_format_enum(self):
450 Season = self.Season
451 self.assertEqual('{}'.format(Season.SPRING),
452 '{}'.format(str(Season.SPRING)))
453 self.assertEqual( '{:}'.format(Season.SPRING),
454 '{:}'.format(str(Season.SPRING)))
455 self.assertEqual('{:20}'.format(Season.SPRING),
456 '{:20}'.format(str(Season.SPRING)))
457 self.assertEqual('{:^20}'.format(Season.SPRING),
458 '{:^20}'.format(str(Season.SPRING)))
459 self.assertEqual('{:>20}'.format(Season.SPRING),
460 '{:>20}'.format(str(Season.SPRING)))
461 self.assertEqual('{:<20}'.format(Season.SPRING),
462 '{:<20}'.format(str(Season.SPRING)))
463
thatneat2f19e822019-07-04 11:28:37 -0700464 def test_str_override_enum(self):
465 class EnumWithStrOverrides(Enum):
466 one = auto()
467 two = auto()
468
469 def __str__(self):
470 return 'Str!'
471 self.assertEqual(str(EnumWithStrOverrides.one), 'Str!')
472 self.assertEqual('{}'.format(EnumWithStrOverrides.one), 'Str!')
473
474 def test_format_override_enum(self):
475 class EnumWithFormatOverride(Enum):
476 one = 1.0
477 two = 2.0
478 def __format__(self, spec):
479 return 'Format!!'
480 self.assertEqual(str(EnumWithFormatOverride.one), 'EnumWithFormatOverride.one')
481 self.assertEqual('{}'.format(EnumWithFormatOverride.one), 'Format!!')
482
483 def test_str_and_format_override_enum(self):
484 class EnumWithStrFormatOverrides(Enum):
485 one = auto()
486 two = auto()
487 def __str__(self):
488 return 'Str!'
489 def __format__(self, spec):
490 return 'Format!'
491 self.assertEqual(str(EnumWithStrFormatOverrides.one), 'Str!')
492 self.assertEqual('{}'.format(EnumWithStrFormatOverrides.one), 'Format!')
493
494 def test_str_override_mixin(self):
495 class MixinEnumWithStrOverride(float, Enum):
496 one = 1.0
497 two = 2.0
498 def __str__(self):
499 return 'Overridden!'
500 self.assertEqual(str(MixinEnumWithStrOverride.one), 'Overridden!')
501 self.assertEqual('{}'.format(MixinEnumWithStrOverride.one), 'Overridden!')
502
503 def test_str_and_format_override_mixin(self):
504 class MixinWithStrFormatOverrides(float, Enum):
505 one = 1.0
506 two = 2.0
507 def __str__(self):
508 return 'Str!'
509 def __format__(self, spec):
510 return 'Format!'
511 self.assertEqual(str(MixinWithStrFormatOverrides.one), 'Str!')
512 self.assertEqual('{}'.format(MixinWithStrFormatOverrides.one), 'Format!')
513
514 def test_format_override_mixin(self):
Ethan Furmanec15a822013-08-31 19:17:41 -0700515 class TestFloat(float, Enum):
516 one = 1.0
517 two = 2.0
518 def __format__(self, spec):
519 return 'TestFloat success!'
thatneat2f19e822019-07-04 11:28:37 -0700520 self.assertEqual(str(TestFloat.one), 'TestFloat.one')
Ethan Furmanec15a822013-08-31 19:17:41 -0700521 self.assertEqual('{}'.format(TestFloat.one), 'TestFloat success!')
522
523 def assertFormatIsValue(self, spec, member):
524 self.assertEqual(spec.format(member), spec.format(member.value))
525
526 def test_format_enum_date(self):
527 Holiday = self.Holiday
528 self.assertFormatIsValue('{}', Holiday.IDES_OF_MARCH)
529 self.assertFormatIsValue('{:}', Holiday.IDES_OF_MARCH)
530 self.assertFormatIsValue('{:20}', Holiday.IDES_OF_MARCH)
531 self.assertFormatIsValue('{:^20}', Holiday.IDES_OF_MARCH)
532 self.assertFormatIsValue('{:>20}', Holiday.IDES_OF_MARCH)
533 self.assertFormatIsValue('{:<20}', Holiday.IDES_OF_MARCH)
534 self.assertFormatIsValue('{:%Y %m}', Holiday.IDES_OF_MARCH)
535 self.assertFormatIsValue('{:%Y %m %M:00}', Holiday.IDES_OF_MARCH)
536
537 def test_format_enum_float(self):
538 Konstants = self.Konstants
539 self.assertFormatIsValue('{}', Konstants.TAU)
540 self.assertFormatIsValue('{:}', Konstants.TAU)
541 self.assertFormatIsValue('{:20}', Konstants.TAU)
542 self.assertFormatIsValue('{:^20}', Konstants.TAU)
543 self.assertFormatIsValue('{:>20}', Konstants.TAU)
544 self.assertFormatIsValue('{:<20}', Konstants.TAU)
545 self.assertFormatIsValue('{:n}', Konstants.TAU)
546 self.assertFormatIsValue('{:5.2}', Konstants.TAU)
547 self.assertFormatIsValue('{:f}', Konstants.TAU)
548
549 def test_format_enum_int(self):
550 Grades = self.Grades
551 self.assertFormatIsValue('{}', Grades.C)
552 self.assertFormatIsValue('{:}', Grades.C)
553 self.assertFormatIsValue('{:20}', Grades.C)
554 self.assertFormatIsValue('{:^20}', Grades.C)
555 self.assertFormatIsValue('{:>20}', Grades.C)
556 self.assertFormatIsValue('{:<20}', Grades.C)
557 self.assertFormatIsValue('{:+}', Grades.C)
558 self.assertFormatIsValue('{:08X}', Grades.C)
559 self.assertFormatIsValue('{:b}', Grades.C)
560
561 def test_format_enum_str(self):
562 Directional = self.Directional
563 self.assertFormatIsValue('{}', Directional.WEST)
564 self.assertFormatIsValue('{:}', Directional.WEST)
565 self.assertFormatIsValue('{:20}', Directional.WEST)
566 self.assertFormatIsValue('{:^20}', Directional.WEST)
567 self.assertFormatIsValue('{:>20}', Directional.WEST)
568 self.assertFormatIsValue('{:<20}', Directional.WEST)
569
Ethan Furman22415ad2020-09-15 16:28:25 -0700570 def test_object_str_override(self):
571 class Colors(Enum):
572 RED, GREEN, BLUE = 1, 2, 3
573 def __repr__(self):
574 return "test.%s" % (self._name_, )
575 __str__ = object.__str__
576 self.assertEqual(str(Colors.RED), 'test.RED')
577
Ethan Furmanbff01f32020-09-15 15:56:26 -0700578 def test_enum_str_override(self):
579 class MyStrEnum(Enum):
580 def __str__(self):
581 return 'MyStr'
582 class MyMethodEnum(Enum):
583 def hello(self):
584 return 'Hello! My name is %s' % self.name
585 class Test1Enum(MyMethodEnum, int, MyStrEnum):
586 One = 1
587 Two = 2
588 self.assertEqual(str(Test1Enum.One), 'MyStr')
589 #
590 class Test2Enum(MyStrEnum, MyMethodEnum):
591 One = 1
592 Two = 2
593 self.assertEqual(str(Test2Enum.One), 'MyStr')
594
595 def test_inherited_data_type(self):
596 class HexInt(int):
597 def __repr__(self):
598 return hex(self)
599 class MyEnum(HexInt, enum.Enum):
600 A = 1
601 B = 2
602 C = 3
603 self.assertEqual(repr(MyEnum.A), '<MyEnum.A: 0x1>')
604
605 def test_too_many_data_types(self):
606 with self.assertRaisesRegex(TypeError, 'too many data types'):
607 class Huh(str, int, Enum):
608 One = 1
609
610 class MyStr(str):
611 def hello(self):
612 return 'hello, %s' % self
613 class MyInt(int):
614 def repr(self):
615 return hex(self)
616 with self.assertRaisesRegex(TypeError, 'too many data types'):
617 class Huh(MyStr, MyInt, Enum):
618 One = 1
619
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700620 def test_hash(self):
621 Season = self.Season
622 dates = {}
623 dates[Season.WINTER] = '1225'
624 dates[Season.SPRING] = '0315'
625 dates[Season.SUMMER] = '0704'
626 dates[Season.AUTUMN] = '1031'
627 self.assertEqual(dates[Season.AUTUMN], '1031')
628
629 def test_intenum_from_scratch(self):
630 class phy(int, Enum):
631 pi = 3
632 tau = 2 * pi
633 self.assertTrue(phy.pi < phy.tau)
634
635 def test_intenum_inherited(self):
636 class IntEnum(int, Enum):
637 pass
638 class phy(IntEnum):
639 pi = 3
640 tau = 2 * pi
641 self.assertTrue(phy.pi < phy.tau)
642
643 def test_floatenum_from_scratch(self):
644 class phy(float, Enum):
Ethan Furmanec15a822013-08-31 19:17:41 -0700645 pi = 3.1415926
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700646 tau = 2 * pi
647 self.assertTrue(phy.pi < phy.tau)
648
649 def test_floatenum_inherited(self):
650 class FloatEnum(float, Enum):
651 pass
652 class phy(FloatEnum):
Ethan Furmanec15a822013-08-31 19:17:41 -0700653 pi = 3.1415926
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700654 tau = 2 * pi
655 self.assertTrue(phy.pi < phy.tau)
656
657 def test_strenum_from_scratch(self):
658 class phy(str, Enum):
659 pi = 'Pi'
660 tau = 'Tau'
661 self.assertTrue(phy.pi < phy.tau)
662
Ethan Furman0063ff42020-09-21 17:23:13 -0700663 def test_strenum_inherited_methods(self):
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700664 class phy(StrEnum):
665 pi = 'Pi'
666 tau = 'Tau'
667 self.assertTrue(phy.pi < phy.tau)
Ethan Furman0063ff42020-09-21 17:23:13 -0700668 self.assertEqual(phy.pi.upper(), 'PI')
669 self.assertEqual(phy.tau.count('a'), 1)
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700670
671 def test_intenum(self):
672 class WeekDay(IntEnum):
673 SUNDAY = 1
674 MONDAY = 2
675 TUESDAY = 3
676 WEDNESDAY = 4
677 THURSDAY = 5
678 FRIDAY = 6
679 SATURDAY = 7
680
681 self.assertEqual(['a', 'b', 'c'][WeekDay.MONDAY], 'c')
682 self.assertEqual([i for i in range(WeekDay.TUESDAY)], [0, 1, 2])
683
684 lst = list(WeekDay)
685 self.assertEqual(len(lst), len(WeekDay))
686 self.assertEqual(len(WeekDay), 7)
687 target = 'SUNDAY MONDAY TUESDAY WEDNESDAY THURSDAY FRIDAY SATURDAY'
688 target = target.split()
689 for i, weekday in enumerate(target, 1):
690 e = WeekDay(i)
691 self.assertEqual(e, i)
692 self.assertEqual(int(e), i)
693 self.assertEqual(e.name, weekday)
694 self.assertIn(e, WeekDay)
695 self.assertEqual(lst.index(e)+1, i)
696 self.assertTrue(0 < e < 8)
697 self.assertIs(type(e), WeekDay)
698 self.assertIsInstance(e, int)
699 self.assertIsInstance(e, Enum)
700
701 def test_intenum_duplicates(self):
702 class WeekDay(IntEnum):
703 SUNDAY = 1
704 MONDAY = 2
705 TUESDAY = TEUSDAY = 3
706 WEDNESDAY = 4
707 THURSDAY = 5
708 FRIDAY = 6
709 SATURDAY = 7
710 self.assertIs(WeekDay.TEUSDAY, WeekDay.TUESDAY)
711 self.assertEqual(WeekDay(3).name, 'TUESDAY')
712 self.assertEqual([k for k,v in WeekDay.__members__.items()
713 if v.name != k], ['TEUSDAY', ])
714
Serhiy Storchakaea36c942016-05-12 10:37:58 +0300715 def test_intenum_from_bytes(self):
716 self.assertIs(IntStooges.from_bytes(b'\x00\x03', 'big'), IntStooges.MOE)
717 with self.assertRaises(ValueError):
718 IntStooges.from_bytes(b'\x00\x05', 'big')
719
720 def test_floatenum_fromhex(self):
721 h = float.hex(FloatStooges.MOE.value)
722 self.assertIs(FloatStooges.fromhex(h), FloatStooges.MOE)
723 h = float.hex(FloatStooges.MOE.value + 0.01)
724 with self.assertRaises(ValueError):
725 FloatStooges.fromhex(h)
726
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700727 def test_pickle_enum(self):
728 if isinstance(Stooges, Exception):
729 raise Stooges
Ethan Furman2ddb39a2014-02-06 17:28:50 -0800730 test_pickle_dump_load(self.assertIs, Stooges.CURLY)
731 test_pickle_dump_load(self.assertIs, Stooges)
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700732
733 def test_pickle_int(self):
734 if isinstance(IntStooges, Exception):
735 raise IntStooges
Ethan Furman2ddb39a2014-02-06 17:28:50 -0800736 test_pickle_dump_load(self.assertIs, IntStooges.CURLY)
737 test_pickle_dump_load(self.assertIs, IntStooges)
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700738
739 def test_pickle_float(self):
740 if isinstance(FloatStooges, Exception):
741 raise FloatStooges
Ethan Furman2ddb39a2014-02-06 17:28:50 -0800742 test_pickle_dump_load(self.assertIs, FloatStooges.CURLY)
743 test_pickle_dump_load(self.assertIs, FloatStooges)
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700744
745 def test_pickle_enum_function(self):
746 if isinstance(Answer, Exception):
747 raise Answer
Ethan Furman2ddb39a2014-02-06 17:28:50 -0800748 test_pickle_dump_load(self.assertIs, Answer.him)
749 test_pickle_dump_load(self.assertIs, Answer)
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700750
751 def test_pickle_enum_function_with_module(self):
752 if isinstance(Question, Exception):
753 raise Question
Ethan Furman2ddb39a2014-02-06 17:28:50 -0800754 test_pickle_dump_load(self.assertIs, Question.who)
755 test_pickle_dump_load(self.assertIs, Question)
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700756
Ethan Furmanca1b7942014-02-08 11:36:27 -0800757 def test_enum_function_with_qualname(self):
758 if isinstance(Theory, Exception):
759 raise Theory
760 self.assertEqual(Theory.__qualname__, 'spanish_inquisition')
761
762 def test_class_nested_enum_and_pickle_protocol_four(self):
763 # would normally just have this directly in the class namespace
764 class NestedEnum(Enum):
765 twigs = 'common'
766 shiny = 'rare'
767
768 self.__class__.NestedEnum = NestedEnum
769 self.NestedEnum.__qualname__ = '%s.NestedEnum' % self.__class__.__name__
Serhiy Storchakae50e7802015-03-31 16:56:49 +0300770 test_pickle_dump_load(self.assertIs, self.NestedEnum.twigs)
Ethan Furmanca1b7942014-02-08 11:36:27 -0800771
Ethan Furman24e837f2015-03-18 17:27:57 -0700772 def test_pickle_by_name(self):
773 class ReplaceGlobalInt(IntEnum):
774 ONE = 1
775 TWO = 2
776 ReplaceGlobalInt.__reduce_ex__ = enum._reduce_ex_by_name
777 for proto in range(HIGHEST_PROTOCOL):
778 self.assertEqual(ReplaceGlobalInt.TWO.__reduce_ex__(proto), 'TWO')
779
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700780 def test_exploding_pickle(self):
Ethan Furmanca1b7942014-02-08 11:36:27 -0800781 BadPickle = Enum(
782 'BadPickle', 'dill sweet bread-n-butter', module=__name__)
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700783 globals()['BadPickle'] = BadPickle
Ethan Furmanca1b7942014-02-08 11:36:27 -0800784 # now break BadPickle to test exception raising
785 enum._make_class_unpicklable(BadPickle)
Ethan Furman2ddb39a2014-02-06 17:28:50 -0800786 test_pickle_exception(self.assertRaises, TypeError, BadPickle.dill)
787 test_pickle_exception(self.assertRaises, PicklingError, BadPickle)
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700788
789 def test_string_enum(self):
790 class SkillLevel(str, Enum):
791 master = 'what is the sound of one hand clapping?'
792 journeyman = 'why did the chicken cross the road?'
793 apprentice = 'knock, knock!'
794 self.assertEqual(SkillLevel.apprentice, 'knock, knock!')
795
796 def test_getattr_getitem(self):
797 class Period(Enum):
798 morning = 1
799 noon = 2
800 evening = 3
801 night = 4
802 self.assertIs(Period(2), Period.noon)
803 self.assertIs(getattr(Period, 'night'), Period.night)
804 self.assertIs(Period['morning'], Period.morning)
805
806 def test_getattr_dunder(self):
807 Season = self.Season
808 self.assertTrue(getattr(Season, '__eq__'))
809
810 def test_iteration_order(self):
811 class Season(Enum):
812 SUMMER = 2
813 WINTER = 4
814 AUTUMN = 3
815 SPRING = 1
816 self.assertEqual(
817 list(Season),
818 [Season.SUMMER, Season.WINTER, Season.AUTUMN, Season.SPRING],
819 )
820
Ethan Furman2131a4a2013-09-14 18:11:24 -0700821 def test_reversed_iteration_order(self):
822 self.assertEqual(
823 list(reversed(self.Season)),
824 [self.Season.WINTER, self.Season.AUTUMN, self.Season.SUMMER,
825 self.Season.SPRING]
826 )
827
Martin Pantereb995702016-07-28 01:11:04 +0000828 def test_programmatic_function_string(self):
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700829 SummerMonth = Enum('SummerMonth', 'june july august')
830 lst = list(SummerMonth)
831 self.assertEqual(len(lst), len(SummerMonth))
832 self.assertEqual(len(SummerMonth), 3, SummerMonth)
833 self.assertEqual(
834 [SummerMonth.june, SummerMonth.july, SummerMonth.august],
835 lst,
836 )
837 for i, month in enumerate('june july august'.split(), 1):
838 e = SummerMonth(i)
839 self.assertEqual(int(e.value), i)
840 self.assertNotEqual(e, i)
841 self.assertEqual(e.name, month)
842 self.assertIn(e, SummerMonth)
843 self.assertIs(type(e), SummerMonth)
844
Martin Pantereb995702016-07-28 01:11:04 +0000845 def test_programmatic_function_string_with_start(self):
Ethan Furmand9925a12014-09-16 20:35:55 -0700846 SummerMonth = Enum('SummerMonth', 'june july august', start=10)
847 lst = list(SummerMonth)
848 self.assertEqual(len(lst), len(SummerMonth))
849 self.assertEqual(len(SummerMonth), 3, SummerMonth)
850 self.assertEqual(
851 [SummerMonth.june, SummerMonth.july, SummerMonth.august],
852 lst,
853 )
854 for i, month in enumerate('june july august'.split(), 10):
855 e = SummerMonth(i)
856 self.assertEqual(int(e.value), i)
857 self.assertNotEqual(e, i)
858 self.assertEqual(e.name, month)
859 self.assertIn(e, SummerMonth)
860 self.assertIs(type(e), SummerMonth)
861
Martin Pantereb995702016-07-28 01:11:04 +0000862 def test_programmatic_function_string_list(self):
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700863 SummerMonth = Enum('SummerMonth', ['june', 'july', 'august'])
864 lst = list(SummerMonth)
865 self.assertEqual(len(lst), len(SummerMonth))
866 self.assertEqual(len(SummerMonth), 3, SummerMonth)
867 self.assertEqual(
868 [SummerMonth.june, SummerMonth.july, SummerMonth.august],
869 lst,
870 )
871 for i, month in enumerate('june july august'.split(), 1):
872 e = SummerMonth(i)
873 self.assertEqual(int(e.value), i)
874 self.assertNotEqual(e, i)
875 self.assertEqual(e.name, month)
876 self.assertIn(e, SummerMonth)
877 self.assertIs(type(e), SummerMonth)
878
Martin Pantereb995702016-07-28 01:11:04 +0000879 def test_programmatic_function_string_list_with_start(self):
Ethan Furmand9925a12014-09-16 20:35:55 -0700880 SummerMonth = Enum('SummerMonth', ['june', 'july', 'august'], start=20)
881 lst = list(SummerMonth)
882 self.assertEqual(len(lst), len(SummerMonth))
883 self.assertEqual(len(SummerMonth), 3, SummerMonth)
884 self.assertEqual(
885 [SummerMonth.june, SummerMonth.july, SummerMonth.august],
886 lst,
887 )
888 for i, month in enumerate('june july august'.split(), 20):
889 e = SummerMonth(i)
890 self.assertEqual(int(e.value), i)
891 self.assertNotEqual(e, i)
892 self.assertEqual(e.name, month)
893 self.assertIn(e, SummerMonth)
894 self.assertIs(type(e), SummerMonth)
895
Martin Pantereb995702016-07-28 01:11:04 +0000896 def test_programmatic_function_iterable(self):
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700897 SummerMonth = Enum(
898 'SummerMonth',
899 (('june', 1), ('july', 2), ('august', 3))
900 )
901 lst = list(SummerMonth)
902 self.assertEqual(len(lst), len(SummerMonth))
903 self.assertEqual(len(SummerMonth), 3, SummerMonth)
904 self.assertEqual(
905 [SummerMonth.june, SummerMonth.july, SummerMonth.august],
906 lst,
907 )
908 for i, month in enumerate('june july august'.split(), 1):
909 e = SummerMonth(i)
910 self.assertEqual(int(e.value), i)
911 self.assertNotEqual(e, i)
912 self.assertEqual(e.name, month)
913 self.assertIn(e, SummerMonth)
914 self.assertIs(type(e), SummerMonth)
915
Martin Pantereb995702016-07-28 01:11:04 +0000916 def test_programmatic_function_from_dict(self):
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700917 SummerMonth = Enum(
918 'SummerMonth',
919 OrderedDict((('june', 1), ('july', 2), ('august', 3)))
920 )
921 lst = list(SummerMonth)
922 self.assertEqual(len(lst), len(SummerMonth))
923 self.assertEqual(len(SummerMonth), 3, SummerMonth)
924 self.assertEqual(
925 [SummerMonth.june, SummerMonth.july, SummerMonth.august],
926 lst,
927 )
928 for i, month in enumerate('june july august'.split(), 1):
929 e = SummerMonth(i)
930 self.assertEqual(int(e.value), i)
931 self.assertNotEqual(e, i)
932 self.assertEqual(e.name, month)
933 self.assertIn(e, SummerMonth)
934 self.assertIs(type(e), SummerMonth)
935
Martin Pantereb995702016-07-28 01:11:04 +0000936 def test_programmatic_function_type(self):
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700937 SummerMonth = Enum('SummerMonth', 'june july august', type=int)
938 lst = list(SummerMonth)
939 self.assertEqual(len(lst), len(SummerMonth))
940 self.assertEqual(len(SummerMonth), 3, SummerMonth)
941 self.assertEqual(
942 [SummerMonth.june, SummerMonth.july, SummerMonth.august],
943 lst,
944 )
945 for i, month in enumerate('june july august'.split(), 1):
946 e = SummerMonth(i)
947 self.assertEqual(e, i)
948 self.assertEqual(e.name, month)
949 self.assertIn(e, SummerMonth)
950 self.assertIs(type(e), SummerMonth)
951
Martin Pantereb995702016-07-28 01:11:04 +0000952 def test_programmatic_function_type_with_start(self):
Ethan Furmand9925a12014-09-16 20:35:55 -0700953 SummerMonth = Enum('SummerMonth', 'june july august', type=int, start=30)
954 lst = list(SummerMonth)
955 self.assertEqual(len(lst), len(SummerMonth))
956 self.assertEqual(len(SummerMonth), 3, SummerMonth)
957 self.assertEqual(
958 [SummerMonth.june, SummerMonth.july, SummerMonth.august],
959 lst,
960 )
961 for i, month in enumerate('june july august'.split(), 30):
962 e = SummerMonth(i)
963 self.assertEqual(e, i)
964 self.assertEqual(e.name, month)
965 self.assertIn(e, SummerMonth)
966 self.assertIs(type(e), SummerMonth)
967
Martin Pantereb995702016-07-28 01:11:04 +0000968 def test_programmatic_function_type_from_subclass(self):
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700969 SummerMonth = IntEnum('SummerMonth', 'june july august')
970 lst = list(SummerMonth)
971 self.assertEqual(len(lst), len(SummerMonth))
972 self.assertEqual(len(SummerMonth), 3, SummerMonth)
973 self.assertEqual(
974 [SummerMonth.june, SummerMonth.july, SummerMonth.august],
975 lst,
976 )
977 for i, month in enumerate('june july august'.split(), 1):
978 e = SummerMonth(i)
979 self.assertEqual(e, i)
980 self.assertEqual(e.name, month)
981 self.assertIn(e, SummerMonth)
982 self.assertIs(type(e), SummerMonth)
983
Martin Pantereb995702016-07-28 01:11:04 +0000984 def test_programmatic_function_type_from_subclass_with_start(self):
Ethan Furmand9925a12014-09-16 20:35:55 -0700985 SummerMonth = IntEnum('SummerMonth', 'june july august', start=40)
986 lst = list(SummerMonth)
987 self.assertEqual(len(lst), len(SummerMonth))
988 self.assertEqual(len(SummerMonth), 3, SummerMonth)
989 self.assertEqual(
990 [SummerMonth.june, SummerMonth.july, SummerMonth.august],
991 lst,
992 )
993 for i, month in enumerate('june july august'.split(), 40):
994 e = SummerMonth(i)
995 self.assertEqual(e, i)
996 self.assertEqual(e.name, month)
997 self.assertIn(e, SummerMonth)
998 self.assertIs(type(e), SummerMonth)
999
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001000 def test_subclassing(self):
1001 if isinstance(Name, Exception):
1002 raise Name
1003 self.assertEqual(Name.BDFL, 'Guido van Rossum')
1004 self.assertTrue(Name.BDFL, Name('Guido van Rossum'))
1005 self.assertIs(Name.BDFL, getattr(Name, 'BDFL'))
Ethan Furman2ddb39a2014-02-06 17:28:50 -08001006 test_pickle_dump_load(self.assertIs, Name.BDFL)
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001007
1008 def test_extending(self):
1009 class Color(Enum):
1010 red = 1
1011 green = 2
1012 blue = 3
1013 with self.assertRaises(TypeError):
1014 class MoreColor(Color):
1015 cyan = 4
1016 magenta = 5
1017 yellow = 6
Ethan Furman3064dbf2020-09-16 07:11:57 -07001018 with self.assertRaisesRegex(TypeError, "EvenMoreColor: cannot extend enumeration 'Color'"):
1019 class EvenMoreColor(Color, IntEnum):
1020 chartruese = 7
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001021
1022 def test_exclude_methods(self):
1023 class whatever(Enum):
1024 this = 'that'
1025 these = 'those'
1026 def really(self):
1027 return 'no, not %s' % self.value
1028 self.assertIsNot(type(whatever.really), whatever)
1029 self.assertEqual(whatever.this.really(), 'no, not that')
1030
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001031 def test_wrong_inheritance_order(self):
1032 with self.assertRaises(TypeError):
1033 class Wrong(Enum, str):
1034 NotHere = 'error before this point'
1035
1036 def test_intenum_transitivity(self):
1037 class number(IntEnum):
1038 one = 1
1039 two = 2
1040 three = 3
1041 class numero(IntEnum):
1042 uno = 1
1043 dos = 2
1044 tres = 3
1045 self.assertEqual(number.one, numero.uno)
1046 self.assertEqual(number.two, numero.dos)
1047 self.assertEqual(number.three, numero.tres)
1048
1049 def test_wrong_enum_in_call(self):
1050 class Monochrome(Enum):
1051 black = 0
1052 white = 1
1053 class Gender(Enum):
1054 male = 0
1055 female = 1
1056 self.assertRaises(ValueError, Monochrome, Gender.male)
1057
1058 def test_wrong_enum_in_mixed_call(self):
1059 class Monochrome(IntEnum):
1060 black = 0
1061 white = 1
1062 class Gender(Enum):
1063 male = 0
1064 female = 1
1065 self.assertRaises(ValueError, Monochrome, Gender.male)
1066
1067 def test_mixed_enum_in_call_1(self):
1068 class Monochrome(IntEnum):
1069 black = 0
1070 white = 1
1071 class Gender(IntEnum):
1072 male = 0
1073 female = 1
1074 self.assertIs(Monochrome(Gender.female), Monochrome.white)
1075
1076 def test_mixed_enum_in_call_2(self):
1077 class Monochrome(Enum):
1078 black = 0
1079 white = 1
1080 class Gender(IntEnum):
1081 male = 0
1082 female = 1
1083 self.assertIs(Monochrome(Gender.male), Monochrome.black)
1084
1085 def test_flufl_enum(self):
1086 class Fluflnum(Enum):
1087 def __int__(self):
1088 return int(self.value)
1089 class MailManOptions(Fluflnum):
1090 option1 = 1
1091 option2 = 2
1092 option3 = 3
1093 self.assertEqual(int(MailManOptions.option1), 1)
1094
Ethan Furman5e5a8232013-08-04 08:42:23 -07001095 def test_introspection(self):
1096 class Number(IntEnum):
1097 one = 100
1098 two = 200
1099 self.assertIs(Number.one._member_type_, int)
1100 self.assertIs(Number._member_type_, int)
1101 class String(str, Enum):
1102 yarn = 'soft'
1103 rope = 'rough'
1104 wire = 'hard'
1105 self.assertIs(String.yarn._member_type_, str)
1106 self.assertIs(String._member_type_, str)
1107 class Plain(Enum):
1108 vanilla = 'white'
1109 one = 1
1110 self.assertIs(Plain.vanilla._member_type_, object)
1111 self.assertIs(Plain._member_type_, object)
1112
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001113 def test_no_such_enum_member(self):
1114 class Color(Enum):
1115 red = 1
1116 green = 2
1117 blue = 3
1118 with self.assertRaises(ValueError):
1119 Color(4)
1120 with self.assertRaises(KeyError):
1121 Color['chartreuse']
1122
1123 def test_new_repr(self):
1124 class Color(Enum):
1125 red = 1
1126 green = 2
1127 blue = 3
1128 def __repr__(self):
1129 return "don't you just love shades of %s?" % self.name
1130 self.assertEqual(
1131 repr(Color.blue),
1132 "don't you just love shades of blue?",
1133 )
1134
1135 def test_inherited_repr(self):
1136 class MyEnum(Enum):
1137 def __repr__(self):
1138 return "My name is %s." % self.name
1139 class MyIntEnum(int, MyEnum):
1140 this = 1
1141 that = 2
1142 theother = 3
1143 self.assertEqual(repr(MyIntEnum.that), "My name is that.")
1144
1145 def test_multiple_mixin_mro(self):
1146 class auto_enum(type(Enum)):
1147 def __new__(metacls, cls, bases, classdict):
1148 temp = type(classdict)()
1149 names = set(classdict._member_names)
1150 i = 0
1151 for k in classdict._member_names:
1152 v = classdict[k]
1153 if v is Ellipsis:
1154 v = i
1155 else:
1156 i = v
1157 i += 1
1158 temp[k] = v
1159 for k, v in classdict.items():
1160 if k not in names:
1161 temp[k] = v
1162 return super(auto_enum, metacls).__new__(
1163 metacls, cls, bases, temp)
1164
1165 class AutoNumberedEnum(Enum, metaclass=auto_enum):
1166 pass
1167
1168 class AutoIntEnum(IntEnum, metaclass=auto_enum):
1169 pass
1170
1171 class TestAutoNumber(AutoNumberedEnum):
1172 a = ...
1173 b = 3
1174 c = ...
1175
1176 class TestAutoInt(AutoIntEnum):
1177 a = ...
1178 b = 3
1179 c = ...
1180
1181 def test_subclasses_with_getnewargs(self):
1182 class NamedInt(int):
Ethan Furman2ddb39a2014-02-06 17:28:50 -08001183 __qualname__ = 'NamedInt' # needed for pickle protocol 4
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001184 def __new__(cls, *args):
1185 _args = args
1186 name, *args = args
1187 if len(args) == 0:
1188 raise TypeError("name and value must be specified")
1189 self = int.__new__(cls, *args)
1190 self._intname = name
1191 self._args = _args
1192 return self
1193 def __getnewargs__(self):
1194 return self._args
1195 @property
1196 def __name__(self):
1197 return self._intname
1198 def __repr__(self):
1199 # repr() is updated to include the name and type info
Ethan Furman5a565b32020-09-15 12:27:06 -07001200 return "{}({!r}, {})".format(
1201 type(self).__name__,
1202 self.__name__,
1203 int.__repr__(self),
1204 )
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001205 def __str__(self):
1206 # str() is unchanged, even if it relies on the repr() fallback
1207 base = int
1208 base_str = base.__str__
1209 if base_str.__objclass__ is object:
1210 return base.__repr__(self)
1211 return base_str(self)
1212 # for simplicity, we only define one operator that
1213 # propagates expressions
1214 def __add__(self, other):
1215 temp = int(self) + int( other)
1216 if isinstance(self, NamedInt) and isinstance(other, NamedInt):
1217 return NamedInt(
1218 '({0} + {1})'.format(self.__name__, other.__name__),
Ethan Furman5a565b32020-09-15 12:27:06 -07001219 temp,
1220 )
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001221 else:
1222 return temp
1223
1224 class NEI(NamedInt, Enum):
Ethan Furman2ddb39a2014-02-06 17:28:50 -08001225 __qualname__ = 'NEI' # needed for pickle protocol 4
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001226 x = ('the-x', 1)
1227 y = ('the-y', 2)
1228
Ethan Furman2aa27322013-07-19 19:35:56 -07001229
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001230 self.assertIs(NEI.__new__, Enum.__new__)
1231 self.assertEqual(repr(NEI.x + NEI.y), "NamedInt('(the-x + the-y)', 3)")
1232 globals()['NamedInt'] = NamedInt
1233 globals()['NEI'] = NEI
1234 NI5 = NamedInt('test', 5)
1235 self.assertEqual(NI5, 5)
Ethan Furman2ddb39a2014-02-06 17:28:50 -08001236 test_pickle_dump_load(self.assertEqual, NI5, 5)
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001237 self.assertEqual(NEI.y.value, 2)
Ethan Furman2ddb39a2014-02-06 17:28:50 -08001238 test_pickle_dump_load(self.assertIs, NEI.y)
Ethan Furmandc870522014-02-18 12:37:12 -08001239 test_pickle_dump_load(self.assertIs, NEI)
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001240
Ethan Furmanca1b7942014-02-08 11:36:27 -08001241 def test_subclasses_with_getnewargs_ex(self):
1242 class NamedInt(int):
1243 __qualname__ = 'NamedInt' # needed for pickle protocol 4
1244 def __new__(cls, *args):
1245 _args = args
1246 name, *args = args
1247 if len(args) == 0:
1248 raise TypeError("name and value must be specified")
1249 self = int.__new__(cls, *args)
1250 self._intname = name
1251 self._args = _args
1252 return self
1253 def __getnewargs_ex__(self):
1254 return self._args, {}
1255 @property
1256 def __name__(self):
1257 return self._intname
1258 def __repr__(self):
1259 # repr() is updated to include the name and type info
Ethan Furman5a565b32020-09-15 12:27:06 -07001260 return "{}({!r}, {})".format(
1261 type(self).__name__,
1262 self.__name__,
1263 int.__repr__(self),
1264 )
Ethan Furmanca1b7942014-02-08 11:36:27 -08001265 def __str__(self):
1266 # str() is unchanged, even if it relies on the repr() fallback
1267 base = int
1268 base_str = base.__str__
1269 if base_str.__objclass__ is object:
1270 return base.__repr__(self)
1271 return base_str(self)
1272 # for simplicity, we only define one operator that
1273 # propagates expressions
1274 def __add__(self, other):
1275 temp = int(self) + int( other)
1276 if isinstance(self, NamedInt) and isinstance(other, NamedInt):
1277 return NamedInt(
1278 '({0} + {1})'.format(self.__name__, other.__name__),
Ethan Furman5a565b32020-09-15 12:27:06 -07001279 temp,
1280 )
Ethan Furmanca1b7942014-02-08 11:36:27 -08001281 else:
1282 return temp
1283
1284 class NEI(NamedInt, Enum):
1285 __qualname__ = 'NEI' # needed for pickle protocol 4
1286 x = ('the-x', 1)
1287 y = ('the-y', 2)
1288
1289
1290 self.assertIs(NEI.__new__, Enum.__new__)
1291 self.assertEqual(repr(NEI.x + NEI.y), "NamedInt('(the-x + the-y)', 3)")
1292 globals()['NamedInt'] = NamedInt
1293 globals()['NEI'] = NEI
1294 NI5 = NamedInt('test', 5)
1295 self.assertEqual(NI5, 5)
Serhiy Storchakae50e7802015-03-31 16:56:49 +03001296 test_pickle_dump_load(self.assertEqual, NI5, 5)
Ethan Furmanca1b7942014-02-08 11:36:27 -08001297 self.assertEqual(NEI.y.value, 2)
Serhiy Storchakae50e7802015-03-31 16:56:49 +03001298 test_pickle_dump_load(self.assertIs, NEI.y)
Ethan Furmandc870522014-02-18 12:37:12 -08001299 test_pickle_dump_load(self.assertIs, NEI)
Ethan Furmanca1b7942014-02-08 11:36:27 -08001300
1301 def test_subclasses_with_reduce(self):
1302 class NamedInt(int):
1303 __qualname__ = 'NamedInt' # needed for pickle protocol 4
1304 def __new__(cls, *args):
1305 _args = args
1306 name, *args = args
1307 if len(args) == 0:
1308 raise TypeError("name and value must be specified")
1309 self = int.__new__(cls, *args)
1310 self._intname = name
1311 self._args = _args
1312 return self
1313 def __reduce__(self):
1314 return self.__class__, self._args
1315 @property
1316 def __name__(self):
1317 return self._intname
1318 def __repr__(self):
1319 # repr() is updated to include the name and type info
Ethan Furman5a565b32020-09-15 12:27:06 -07001320 return "{}({!r}, {})".format(
1321 type(self).__name__,
1322 self.__name__,
1323 int.__repr__(self),
1324 )
Ethan Furmanca1b7942014-02-08 11:36:27 -08001325 def __str__(self):
1326 # str() is unchanged, even if it relies on the repr() fallback
1327 base = int
1328 base_str = base.__str__
1329 if base_str.__objclass__ is object:
1330 return base.__repr__(self)
1331 return base_str(self)
1332 # for simplicity, we only define one operator that
1333 # propagates expressions
1334 def __add__(self, other):
1335 temp = int(self) + int( other)
1336 if isinstance(self, NamedInt) and isinstance(other, NamedInt):
1337 return NamedInt(
1338 '({0} + {1})'.format(self.__name__, other.__name__),
Ethan Furman5a565b32020-09-15 12:27:06 -07001339 temp,
1340 )
Ethan Furmanca1b7942014-02-08 11:36:27 -08001341 else:
1342 return temp
1343
1344 class NEI(NamedInt, Enum):
1345 __qualname__ = 'NEI' # needed for pickle protocol 4
1346 x = ('the-x', 1)
1347 y = ('the-y', 2)
1348
1349
1350 self.assertIs(NEI.__new__, Enum.__new__)
1351 self.assertEqual(repr(NEI.x + NEI.y), "NamedInt('(the-x + the-y)', 3)")
1352 globals()['NamedInt'] = NamedInt
1353 globals()['NEI'] = NEI
1354 NI5 = NamedInt('test', 5)
1355 self.assertEqual(NI5, 5)
1356 test_pickle_dump_load(self.assertEqual, NI5, 5)
1357 self.assertEqual(NEI.y.value, 2)
1358 test_pickle_dump_load(self.assertIs, NEI.y)
Ethan Furmandc870522014-02-18 12:37:12 -08001359 test_pickle_dump_load(self.assertIs, NEI)
Ethan Furmanca1b7942014-02-08 11:36:27 -08001360
1361 def test_subclasses_with_reduce_ex(self):
1362 class NamedInt(int):
1363 __qualname__ = 'NamedInt' # needed for pickle protocol 4
1364 def __new__(cls, *args):
1365 _args = args
1366 name, *args = args
1367 if len(args) == 0:
1368 raise TypeError("name and value must be specified")
1369 self = int.__new__(cls, *args)
1370 self._intname = name
1371 self._args = _args
1372 return self
1373 def __reduce_ex__(self, proto):
1374 return self.__class__, self._args
1375 @property
1376 def __name__(self):
1377 return self._intname
1378 def __repr__(self):
1379 # repr() is updated to include the name and type info
Ethan Furman5a565b32020-09-15 12:27:06 -07001380 return "{}({!r}, {})".format(
1381 type(self).__name__,
1382 self.__name__,
1383 int.__repr__(self),
1384 )
Ethan Furmanca1b7942014-02-08 11:36:27 -08001385 def __str__(self):
1386 # str() is unchanged, even if it relies on the repr() fallback
1387 base = int
1388 base_str = base.__str__
1389 if base_str.__objclass__ is object:
1390 return base.__repr__(self)
1391 return base_str(self)
1392 # for simplicity, we only define one operator that
1393 # propagates expressions
1394 def __add__(self, other):
1395 temp = int(self) + int( other)
1396 if isinstance(self, NamedInt) and isinstance(other, NamedInt):
1397 return NamedInt(
1398 '({0} + {1})'.format(self.__name__, other.__name__),
Ethan Furman5a565b32020-09-15 12:27:06 -07001399 temp,
1400 )
Ethan Furmanca1b7942014-02-08 11:36:27 -08001401 else:
1402 return temp
1403
1404 class NEI(NamedInt, Enum):
1405 __qualname__ = 'NEI' # needed for pickle protocol 4
1406 x = ('the-x', 1)
1407 y = ('the-y', 2)
1408
Ethan Furmanca1b7942014-02-08 11:36:27 -08001409 self.assertIs(NEI.__new__, Enum.__new__)
1410 self.assertEqual(repr(NEI.x + NEI.y), "NamedInt('(the-x + the-y)', 3)")
1411 globals()['NamedInt'] = NamedInt
1412 globals()['NEI'] = NEI
1413 NI5 = NamedInt('test', 5)
1414 self.assertEqual(NI5, 5)
1415 test_pickle_dump_load(self.assertEqual, NI5, 5)
1416 self.assertEqual(NEI.y.value, 2)
1417 test_pickle_dump_load(self.assertIs, NEI.y)
Ethan Furmandc870522014-02-18 12:37:12 -08001418 test_pickle_dump_load(self.assertIs, NEI)
Ethan Furmanca1b7942014-02-08 11:36:27 -08001419
Ethan Furmandc870522014-02-18 12:37:12 -08001420 def test_subclasses_without_direct_pickle_support(self):
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001421 class NamedInt(int):
Ethan Furman2ddb39a2014-02-06 17:28:50 -08001422 __qualname__ = 'NamedInt'
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001423 def __new__(cls, *args):
1424 _args = args
1425 name, *args = args
1426 if len(args) == 0:
1427 raise TypeError("name and value must be specified")
1428 self = int.__new__(cls, *args)
1429 self._intname = name
1430 self._args = _args
1431 return self
1432 @property
1433 def __name__(self):
1434 return self._intname
1435 def __repr__(self):
1436 # repr() is updated to include the name and type info
Ethan Furman5a565b32020-09-15 12:27:06 -07001437 return "{}({!r}, {})".format(
1438 type(self).__name__,
1439 self.__name__,
1440 int.__repr__(self),
1441 )
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001442 def __str__(self):
1443 # str() is unchanged, even if it relies on the repr() fallback
1444 base = int
1445 base_str = base.__str__
1446 if base_str.__objclass__ is object:
1447 return base.__repr__(self)
1448 return base_str(self)
1449 # for simplicity, we only define one operator that
1450 # propagates expressions
1451 def __add__(self, other):
1452 temp = int(self) + int( other)
1453 if isinstance(self, NamedInt) and isinstance(other, NamedInt):
1454 return NamedInt(
1455 '({0} + {1})'.format(self.__name__, other.__name__),
1456 temp )
1457 else:
1458 return temp
1459
1460 class NEI(NamedInt, Enum):
Ethan Furman2ddb39a2014-02-06 17:28:50 -08001461 __qualname__ = 'NEI'
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001462 x = ('the-x', 1)
1463 y = ('the-y', 2)
1464
1465 self.assertIs(NEI.__new__, Enum.__new__)
1466 self.assertEqual(repr(NEI.x + NEI.y), "NamedInt('(the-x + the-y)', 3)")
1467 globals()['NamedInt'] = NamedInt
1468 globals()['NEI'] = NEI
1469 NI5 = NamedInt('test', 5)
1470 self.assertEqual(NI5, 5)
1471 self.assertEqual(NEI.y.value, 2)
Ethan Furman2ddb39a2014-02-06 17:28:50 -08001472 test_pickle_exception(self.assertRaises, TypeError, NEI.x)
1473 test_pickle_exception(self.assertRaises, PicklingError, NEI)
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001474
Ethan Furmandc870522014-02-18 12:37:12 -08001475 def test_subclasses_without_direct_pickle_support_using_name(self):
1476 class NamedInt(int):
1477 __qualname__ = 'NamedInt'
1478 def __new__(cls, *args):
1479 _args = args
1480 name, *args = args
1481 if len(args) == 0:
1482 raise TypeError("name and value must be specified")
1483 self = int.__new__(cls, *args)
1484 self._intname = name
1485 self._args = _args
1486 return self
1487 @property
1488 def __name__(self):
1489 return self._intname
1490 def __repr__(self):
1491 # repr() is updated to include the name and type info
Ethan Furman5a565b32020-09-15 12:27:06 -07001492 return "{}({!r}, {})".format(
1493 type(self).__name__,
1494 self.__name__,
1495 int.__repr__(self),
1496 )
Ethan Furmandc870522014-02-18 12:37:12 -08001497 def __str__(self):
1498 # str() is unchanged, even if it relies on the repr() fallback
1499 base = int
1500 base_str = base.__str__
1501 if base_str.__objclass__ is object:
1502 return base.__repr__(self)
1503 return base_str(self)
1504 # for simplicity, we only define one operator that
1505 # propagates expressions
1506 def __add__(self, other):
1507 temp = int(self) + int( other)
1508 if isinstance(self, NamedInt) and isinstance(other, NamedInt):
1509 return NamedInt(
1510 '({0} + {1})'.format(self.__name__, other.__name__),
Ethan Furman5a565b32020-09-15 12:27:06 -07001511 temp,
1512 )
Ethan Furmandc870522014-02-18 12:37:12 -08001513 else:
1514 return temp
1515
1516 class NEI(NamedInt, Enum):
1517 __qualname__ = 'NEI'
1518 x = ('the-x', 1)
1519 y = ('the-y', 2)
1520 def __reduce_ex__(self, proto):
1521 return getattr, (self.__class__, self._name_)
1522
1523 self.assertIs(NEI.__new__, Enum.__new__)
1524 self.assertEqual(repr(NEI.x + NEI.y), "NamedInt('(the-x + the-y)', 3)")
1525 globals()['NamedInt'] = NamedInt
1526 globals()['NEI'] = NEI
1527 NI5 = NamedInt('test', 5)
1528 self.assertEqual(NI5, 5)
1529 self.assertEqual(NEI.y.value, 2)
1530 test_pickle_dump_load(self.assertIs, NEI.y)
1531 test_pickle_dump_load(self.assertIs, NEI)
1532
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001533 def test_tuple_subclass(self):
1534 class SomeTuple(tuple, Enum):
Ethan Furman2ddb39a2014-02-06 17:28:50 -08001535 __qualname__ = 'SomeTuple' # needed for pickle protocol 4
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001536 first = (1, 'for the money')
1537 second = (2, 'for the show')
1538 third = (3, 'for the music')
1539 self.assertIs(type(SomeTuple.first), SomeTuple)
1540 self.assertIsInstance(SomeTuple.second, tuple)
1541 self.assertEqual(SomeTuple.third, (3, 'for the music'))
1542 globals()['SomeTuple'] = SomeTuple
Ethan Furman2ddb39a2014-02-06 17:28:50 -08001543 test_pickle_dump_load(self.assertIs, SomeTuple.first)
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001544
1545 def test_duplicate_values_give_unique_enum_items(self):
1546 class AutoNumber(Enum):
1547 first = ()
1548 second = ()
1549 third = ()
1550 def __new__(cls):
1551 value = len(cls.__members__) + 1
1552 obj = object.__new__(cls)
Ethan Furman520ad572013-07-19 19:47:21 -07001553 obj._value_ = value
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001554 return obj
1555 def __int__(self):
Ethan Furman520ad572013-07-19 19:47:21 -07001556 return int(self._value_)
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001557 self.assertEqual(
1558 list(AutoNumber),
1559 [AutoNumber.first, AutoNumber.second, AutoNumber.third],
1560 )
1561 self.assertEqual(int(AutoNumber.second), 2)
Ethan Furman2aa27322013-07-19 19:35:56 -07001562 self.assertEqual(AutoNumber.third.value, 3)
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001563 self.assertIs(AutoNumber(1), AutoNumber.first)
1564
1565 def test_inherited_new_from_enhanced_enum(self):
1566 class AutoNumber(Enum):
1567 def __new__(cls):
1568 value = len(cls.__members__) + 1
1569 obj = object.__new__(cls)
Ethan Furman520ad572013-07-19 19:47:21 -07001570 obj._value_ = value
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001571 return obj
1572 def __int__(self):
Ethan Furman520ad572013-07-19 19:47:21 -07001573 return int(self._value_)
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001574 class Color(AutoNumber):
1575 red = ()
1576 green = ()
1577 blue = ()
1578 self.assertEqual(list(Color), [Color.red, Color.green, Color.blue])
1579 self.assertEqual(list(map(int, Color)), [1, 2, 3])
1580
1581 def test_inherited_new_from_mixed_enum(self):
1582 class AutoNumber(IntEnum):
1583 def __new__(cls):
1584 value = len(cls.__members__) + 1
1585 obj = int.__new__(cls, value)
Ethan Furman520ad572013-07-19 19:47:21 -07001586 obj._value_ = value
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001587 return obj
1588 class Color(AutoNumber):
1589 red = ()
1590 green = ()
1591 blue = ()
1592 self.assertEqual(list(Color), [Color.red, Color.green, Color.blue])
1593 self.assertEqual(list(map(int, Color)), [1, 2, 3])
1594
Ethan Furmanbe3c2fe2013-11-13 14:25:45 -08001595 def test_equality(self):
Ethan Furmanbe3c2fe2013-11-13 14:25:45 -08001596 class OrdinaryEnum(Enum):
1597 a = 1
Serhiy Storchaka7d44e7a2019-08-08 08:43:18 +03001598 self.assertEqual(ALWAYS_EQ, OrdinaryEnum.a)
1599 self.assertEqual(OrdinaryEnum.a, ALWAYS_EQ)
Ethan Furmanbe3c2fe2013-11-13 14:25:45 -08001600
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001601 def test_ordered_mixin(self):
1602 class OrderedEnum(Enum):
1603 def __ge__(self, other):
1604 if self.__class__ is other.__class__:
Ethan Furman520ad572013-07-19 19:47:21 -07001605 return self._value_ >= other._value_
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001606 return NotImplemented
1607 def __gt__(self, other):
1608 if self.__class__ is other.__class__:
Ethan Furman520ad572013-07-19 19:47:21 -07001609 return self._value_ > other._value_
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001610 return NotImplemented
1611 def __le__(self, other):
1612 if self.__class__ is other.__class__:
Ethan Furman520ad572013-07-19 19:47:21 -07001613 return self._value_ <= other._value_
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001614 return NotImplemented
1615 def __lt__(self, other):
1616 if self.__class__ is other.__class__:
Ethan Furman520ad572013-07-19 19:47:21 -07001617 return self._value_ < other._value_
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001618 return NotImplemented
1619 class Grade(OrderedEnum):
1620 A = 5
1621 B = 4
1622 C = 3
1623 D = 2
1624 F = 1
1625 self.assertGreater(Grade.A, Grade.B)
1626 self.assertLessEqual(Grade.F, Grade.C)
1627 self.assertLess(Grade.D, Grade.A)
1628 self.assertGreaterEqual(Grade.B, Grade.B)
Ethan Furmanbe3c2fe2013-11-13 14:25:45 -08001629 self.assertEqual(Grade.B, Grade.B)
1630 self.assertNotEqual(Grade.C, Grade.D)
Ethan Furman520ad572013-07-19 19:47:21 -07001631
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001632 def test_extending2(self):
1633 class Shade(Enum):
1634 def shade(self):
1635 print(self.name)
1636 class Color(Shade):
1637 red = 1
1638 green = 2
1639 blue = 3
1640 with self.assertRaises(TypeError):
1641 class MoreColor(Color):
1642 cyan = 4
1643 magenta = 5
1644 yellow = 6
1645
1646 def test_extending3(self):
1647 class Shade(Enum):
1648 def shade(self):
1649 return self.name
1650 class Color(Shade):
1651 def hex(self):
1652 return '%s hexlified!' % self.value
1653 class MoreColor(Color):
1654 cyan = 4
1655 magenta = 5
1656 yellow = 6
1657 self.assertEqual(MoreColor.magenta.hex(), '5 hexlified!')
1658
orlnub1230fb9fad2018-09-12 20:28:53 +03001659 def test_subclass_duplicate_name(self):
1660 class Base(Enum):
1661 def test(self):
1662 pass
1663 class Test(Base):
1664 test = 1
1665 self.assertIs(type(Test.test), Test)
1666
1667 def test_subclass_duplicate_name_dynamic(self):
1668 from types import DynamicClassAttribute
1669 class Base(Enum):
1670 @DynamicClassAttribute
1671 def test(self):
1672 return 'dynamic'
1673 class Test(Base):
1674 test = 1
1675 self.assertEqual(Test.test.test, 'dynamic')
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001676
1677 def test_no_duplicates(self):
1678 class UniqueEnum(Enum):
1679 def __init__(self, *args):
1680 cls = self.__class__
1681 if any(self.value == e.value for e in cls):
1682 a = self.name
1683 e = cls(self.value).name
1684 raise ValueError(
1685 "aliases not allowed in UniqueEnum: %r --> %r"
1686 % (a, e)
1687 )
1688 class Color(UniqueEnum):
1689 red = 1
1690 green = 2
1691 blue = 3
1692 with self.assertRaises(ValueError):
1693 class Color(UniqueEnum):
1694 red = 1
1695 green = 2
1696 blue = 3
1697 grene = 2
1698
1699 def test_init(self):
1700 class Planet(Enum):
1701 MERCURY = (3.303e+23, 2.4397e6)
1702 VENUS = (4.869e+24, 6.0518e6)
1703 EARTH = (5.976e+24, 6.37814e6)
1704 MARS = (6.421e+23, 3.3972e6)
1705 JUPITER = (1.9e+27, 7.1492e7)
1706 SATURN = (5.688e+26, 6.0268e7)
1707 URANUS = (8.686e+25, 2.5559e7)
1708 NEPTUNE = (1.024e+26, 2.4746e7)
1709 def __init__(self, mass, radius):
1710 self.mass = mass # in kilograms
1711 self.radius = radius # in meters
1712 @property
1713 def surface_gravity(self):
1714 # universal gravitational constant (m3 kg-1 s-2)
1715 G = 6.67300E-11
1716 return G * self.mass / (self.radius * self.radius)
1717 self.assertEqual(round(Planet.EARTH.surface_gravity, 2), 9.80)
1718 self.assertEqual(Planet.EARTH.value, (5.976e+24, 6.37814e6))
1719
Ethan Furmana4b1bb42018-01-22 07:56:37 -08001720 def test_ignore(self):
1721 class Period(timedelta, Enum):
1722 '''
1723 different lengths of time
1724 '''
1725 def __new__(cls, value, period):
1726 obj = timedelta.__new__(cls, value)
1727 obj._value_ = value
1728 obj.period = period
1729 return obj
1730 _ignore_ = 'Period i'
1731 Period = vars()
1732 for i in range(13):
1733 Period['month_%d' % i] = i*30, 'month'
1734 for i in range(53):
1735 Period['week_%d' % i] = i*7, 'week'
1736 for i in range(32):
1737 Period['day_%d' % i] = i, 'day'
1738 OneDay = day_1
1739 OneWeek = week_1
1740 OneMonth = month_1
1741 self.assertFalse(hasattr(Period, '_ignore_'))
1742 self.assertFalse(hasattr(Period, 'Period'))
1743 self.assertFalse(hasattr(Period, 'i'))
1744 self.assertTrue(isinstance(Period.day_1, timedelta))
1745 self.assertTrue(Period.month_1 is Period.day_30)
1746 self.assertTrue(Period.week_4 is Period.day_28)
1747
Ethan Furman2aa27322013-07-19 19:35:56 -07001748 def test_nonhash_value(self):
1749 class AutoNumberInAList(Enum):
1750 def __new__(cls):
1751 value = [len(cls.__members__) + 1]
1752 obj = object.__new__(cls)
Ethan Furman520ad572013-07-19 19:47:21 -07001753 obj._value_ = value
Ethan Furman2aa27322013-07-19 19:35:56 -07001754 return obj
1755 class ColorInAList(AutoNumberInAList):
1756 red = ()
1757 green = ()
1758 blue = ()
1759 self.assertEqual(list(ColorInAList), [ColorInAList.red, ColorInAList.green, ColorInAList.blue])
Ethan Furman1a162882013-10-16 19:09:31 -07001760 for enum, value in zip(ColorInAList, range(3)):
1761 value += 1
1762 self.assertEqual(enum.value, [value])
1763 self.assertIs(ColorInAList([value]), enum)
Ethan Furman2aa27322013-07-19 19:35:56 -07001764
Ethan Furmanb41803e2013-07-25 13:50:45 -07001765 def test_conflicting_types_resolved_in_new(self):
1766 class LabelledIntEnum(int, Enum):
1767 def __new__(cls, *args):
1768 value, label = args
1769 obj = int.__new__(cls, value)
1770 obj.label = label
1771 obj._value_ = value
1772 return obj
1773
1774 class LabelledList(LabelledIntEnum):
1775 unprocessed = (1, "Unprocessed")
1776 payment_complete = (2, "Payment Complete")
1777
1778 self.assertEqual(list(LabelledList), [LabelledList.unprocessed, LabelledList.payment_complete])
1779 self.assertEqual(LabelledList.unprocessed, 1)
1780 self.assertEqual(LabelledList(1), LabelledList.unprocessed)
Ethan Furman2aa27322013-07-19 19:35:56 -07001781
Ethan Furmanc16595e2016-09-10 23:36:59 -07001782 def test_auto_number(self):
1783 class Color(Enum):
1784 red = auto()
1785 blue = auto()
1786 green = auto()
1787
1788 self.assertEqual(list(Color), [Color.red, Color.blue, Color.green])
1789 self.assertEqual(Color.red.value, 1)
1790 self.assertEqual(Color.blue.value, 2)
1791 self.assertEqual(Color.green.value, 3)
1792
1793 def test_auto_name(self):
1794 class Color(Enum):
1795 def _generate_next_value_(name, start, count, last):
1796 return name
1797 red = auto()
1798 blue = auto()
1799 green = auto()
1800
1801 self.assertEqual(list(Color), [Color.red, Color.blue, Color.green])
1802 self.assertEqual(Color.red.value, 'red')
1803 self.assertEqual(Color.blue.value, 'blue')
1804 self.assertEqual(Color.green.value, 'green')
1805
1806 def test_auto_name_inherit(self):
1807 class AutoNameEnum(Enum):
1808 def _generate_next_value_(name, start, count, last):
1809 return name
1810 class Color(AutoNameEnum):
1811 red = auto()
1812 blue = auto()
1813 green = auto()
1814
1815 self.assertEqual(list(Color), [Color.red, Color.blue, Color.green])
1816 self.assertEqual(Color.red.value, 'red')
1817 self.assertEqual(Color.blue.value, 'blue')
1818 self.assertEqual(Color.green.value, 'green')
1819
1820 def test_auto_garbage(self):
1821 class Color(Enum):
1822 red = 'red'
1823 blue = auto()
1824 self.assertEqual(Color.blue.value, 1)
1825
1826 def test_auto_garbage_corrected(self):
1827 class Color(Enum):
1828 red = 'red'
1829 blue = 2
1830 green = auto()
1831
1832 self.assertEqual(list(Color), [Color.red, Color.blue, Color.green])
1833 self.assertEqual(Color.red.value, 'red')
1834 self.assertEqual(Color.blue.value, 2)
1835 self.assertEqual(Color.green.value, 3)
1836
Ethan Onstottd9a43e22020-04-28 13:20:55 -04001837 def test_auto_order(self):
1838 with self.assertRaises(TypeError):
1839 class Color(Enum):
1840 red = auto()
1841 green = auto()
1842 blue = auto()
1843 def _generate_next_value_(name, start, count, last):
1844 return name
1845
Ethan Furmanfc23a942020-09-16 12:37:54 -07001846 def test_auto_order_wierd(self):
1847 weird_auto = auto()
1848 weird_auto.value = 'pathological case'
1849 class Color(Enum):
1850 red = weird_auto
1851 def _generate_next_value_(name, start, count, last):
1852 return name
1853 blue = auto()
1854 self.assertEqual(list(Color), [Color.red, Color.blue])
1855 self.assertEqual(Color.red.value, 'pathological case')
1856 self.assertEqual(Color.blue.value, 'blue')
Ethan Onstottd9a43e22020-04-28 13:20:55 -04001857
Ethan Furman3515dcc2016-09-18 13:15:41 -07001858 def test_duplicate_auto(self):
1859 class Dupes(Enum):
1860 first = primero = auto()
1861 second = auto()
1862 third = auto()
1863 self.assertEqual([Dupes.first, Dupes.second, Dupes.third], list(Dupes))
1864
Ethan Furmanc95ad7a2020-09-16 10:26:50 -07001865 def test_default_missing(self):
1866 class Color(Enum):
1867 RED = 1
1868 GREEN = 2
1869 BLUE = 3
1870 try:
1871 Color(7)
1872 except ValueError as exc:
1873 self.assertTrue(exc.__context__ is None)
1874 else:
1875 raise Exception('Exception not raised.')
1876
Ethan Furman019f0a02018-09-12 11:43:34 -07001877 def test_missing(self):
1878 class Color(Enum):
1879 red = 1
1880 green = 2
1881 blue = 3
1882 @classmethod
1883 def _missing_(cls, item):
1884 if item == 'three':
1885 return cls.blue
1886 elif item == 'bad return':
1887 # trigger internal error
1888 return 5
1889 elif item == 'error out':
1890 raise ZeroDivisionError
1891 else:
1892 # trigger not found
1893 return None
1894 self.assertIs(Color('three'), Color.blue)
Ethan Furmanc95ad7a2020-09-16 10:26:50 -07001895 try:
1896 Color(7)
1897 except ValueError as exc:
1898 self.assertTrue(exc.__context__ is None)
1899 else:
1900 raise Exception('Exception not raised.')
Ethan Furman019f0a02018-09-12 11:43:34 -07001901 try:
1902 Color('bad return')
1903 except TypeError as exc:
1904 self.assertTrue(isinstance(exc.__context__, ValueError))
1905 else:
1906 raise Exception('Exception not raised.')
1907 try:
1908 Color('error out')
1909 except ZeroDivisionError as exc:
1910 self.assertTrue(isinstance(exc.__context__, ValueError))
1911 else:
1912 raise Exception('Exception not raised.')
1913
Ethan Furman5bdab642018-09-21 19:03:09 -07001914 def test_multiple_mixin(self):
1915 class MaxMixin:
1916 @classproperty
1917 def MAX(cls):
1918 max = len(cls)
1919 cls.MAX = max
1920 return max
1921 class StrMixin:
1922 def __str__(self):
1923 return self._name_.lower()
1924 class SomeEnum(Enum):
1925 def behavior(self):
1926 return 'booyah'
1927 class AnotherEnum(Enum):
1928 def behavior(self):
1929 return 'nuhuh!'
1930 def social(self):
1931 return "what's up?"
1932 class Color(MaxMixin, Enum):
1933 RED = auto()
1934 GREEN = auto()
1935 BLUE = auto()
1936 self.assertEqual(Color.RED.value, 1)
1937 self.assertEqual(Color.GREEN.value, 2)
1938 self.assertEqual(Color.BLUE.value, 3)
1939 self.assertEqual(Color.MAX, 3)
1940 self.assertEqual(str(Color.BLUE), 'Color.BLUE')
1941 class Color(MaxMixin, StrMixin, Enum):
1942 RED = auto()
1943 GREEN = auto()
1944 BLUE = auto()
1945 self.assertEqual(Color.RED.value, 1)
1946 self.assertEqual(Color.GREEN.value, 2)
1947 self.assertEqual(Color.BLUE.value, 3)
1948 self.assertEqual(Color.MAX, 3)
1949 self.assertEqual(str(Color.BLUE), 'blue')
1950 class Color(StrMixin, MaxMixin, Enum):
1951 RED = auto()
1952 GREEN = auto()
1953 BLUE = auto()
1954 self.assertEqual(Color.RED.value, 1)
1955 self.assertEqual(Color.GREEN.value, 2)
1956 self.assertEqual(Color.BLUE.value, 3)
1957 self.assertEqual(Color.MAX, 3)
1958 self.assertEqual(str(Color.BLUE), 'blue')
1959 class CoolColor(StrMixin, SomeEnum, Enum):
1960 RED = auto()
1961 GREEN = auto()
1962 BLUE = auto()
1963 self.assertEqual(CoolColor.RED.value, 1)
1964 self.assertEqual(CoolColor.GREEN.value, 2)
1965 self.assertEqual(CoolColor.BLUE.value, 3)
1966 self.assertEqual(str(CoolColor.BLUE), 'blue')
1967 self.assertEqual(CoolColor.RED.behavior(), 'booyah')
1968 class CoolerColor(StrMixin, AnotherEnum, Enum):
1969 RED = auto()
1970 GREEN = auto()
1971 BLUE = auto()
1972 self.assertEqual(CoolerColor.RED.value, 1)
1973 self.assertEqual(CoolerColor.GREEN.value, 2)
1974 self.assertEqual(CoolerColor.BLUE.value, 3)
1975 self.assertEqual(str(CoolerColor.BLUE), 'blue')
1976 self.assertEqual(CoolerColor.RED.behavior(), 'nuhuh!')
1977 self.assertEqual(CoolerColor.RED.social(), "what's up?")
1978 class CoolestColor(StrMixin, SomeEnum, AnotherEnum):
1979 RED = auto()
1980 GREEN = auto()
1981 BLUE = auto()
1982 self.assertEqual(CoolestColor.RED.value, 1)
1983 self.assertEqual(CoolestColor.GREEN.value, 2)
1984 self.assertEqual(CoolestColor.BLUE.value, 3)
1985 self.assertEqual(str(CoolestColor.BLUE), 'blue')
1986 self.assertEqual(CoolestColor.RED.behavior(), 'booyah')
1987 self.assertEqual(CoolestColor.RED.social(), "what's up?")
1988 class ConfusedColor(StrMixin, AnotherEnum, SomeEnum):
1989 RED = auto()
1990 GREEN = auto()
1991 BLUE = auto()
1992 self.assertEqual(ConfusedColor.RED.value, 1)
1993 self.assertEqual(ConfusedColor.GREEN.value, 2)
1994 self.assertEqual(ConfusedColor.BLUE.value, 3)
1995 self.assertEqual(str(ConfusedColor.BLUE), 'blue')
1996 self.assertEqual(ConfusedColor.RED.behavior(), 'nuhuh!')
1997 self.assertEqual(ConfusedColor.RED.social(), "what's up?")
1998 class ReformedColor(StrMixin, IntEnum, SomeEnum, AnotherEnum):
1999 RED = auto()
2000 GREEN = auto()
2001 BLUE = auto()
2002 self.assertEqual(ReformedColor.RED.value, 1)
2003 self.assertEqual(ReformedColor.GREEN.value, 2)
2004 self.assertEqual(ReformedColor.BLUE.value, 3)
2005 self.assertEqual(str(ReformedColor.BLUE), 'blue')
2006 self.assertEqual(ReformedColor.RED.behavior(), 'booyah')
2007 self.assertEqual(ConfusedColor.RED.social(), "what's up?")
2008 self.assertTrue(issubclass(ReformedColor, int))
2009
Ethan Furmancd453852018-10-05 23:29:36 -07002010 def test_multiple_inherited_mixin(self):
Ethan Furmancd453852018-10-05 23:29:36 -07002011 @unique
2012 class Decision1(StrEnum):
2013 REVERT = "REVERT"
2014 REVERT_ALL = "REVERT_ALL"
2015 RETRY = "RETRY"
2016 class MyEnum(StrEnum):
2017 pass
2018 @unique
2019 class Decision2(MyEnum):
2020 REVERT = "REVERT"
2021 REVERT_ALL = "REVERT_ALL"
2022 RETRY = "RETRY"
2023
Rémi Lapeyre1fd06f12019-01-24 20:43:13 +01002024 def test_empty_globals(self):
2025 # bpo-35717: sys._getframe(2).f_globals['__name__'] fails with KeyError
2026 # when using compile and exec because f_globals is empty
2027 code = "from enum import Enum; Enum('Animal', 'ANT BEE CAT DOG')"
2028 code = compile(code, "<string>", "exec")
2029 global_ns = {}
2030 local_ls = {}
2031 exec(code, global_ns, local_ls)
2032
Ethan Furman0063ff42020-09-21 17:23:13 -07002033 def test_strenum(self):
2034 class GoodStrEnum(StrEnum):
2035 one = '1'
2036 two = '2'
2037 three = b'3', 'ascii'
2038 four = b'4', 'latin1', 'strict'
Ethan Furmand986d162020-09-22 13:00:07 -07002039 self.assertEqual(GoodStrEnum.one, '1')
2040 self.assertEqual(str(GoodStrEnum.one), '1')
2041 self.assertEqual(GoodStrEnum.one, str(GoodStrEnum.one))
2042 self.assertEqual(GoodStrEnum.one, '{}'.format(GoodStrEnum.one))
2043 #
2044 class DumbMixin:
2045 def __str__(self):
2046 return "don't do this"
2047 class DumbStrEnum(DumbMixin, StrEnum):
2048 five = '5'
2049 six = '6'
2050 seven = '7'
2051 self.assertEqual(DumbStrEnum.seven, '7')
2052 self.assertEqual(str(DumbStrEnum.seven), "don't do this")
2053 #
2054 class EnumMixin(Enum):
2055 def hello(self):
2056 print('hello from %s' % (self, ))
2057 class HelloEnum(EnumMixin, StrEnum):
2058 eight = '8'
2059 self.assertEqual(HelloEnum.eight, '8')
2060 self.assertEqual(HelloEnum.eight, str(HelloEnum.eight))
2061 #
2062 class GoodbyeMixin:
2063 def goodbye(self):
2064 print('%s wishes you a fond farewell')
2065 class GoodbyeEnum(GoodbyeMixin, EnumMixin, StrEnum):
2066 nine = '9'
2067 self.assertEqual(GoodbyeEnum.nine, '9')
2068 self.assertEqual(GoodbyeEnum.nine, str(GoodbyeEnum.nine))
2069 #
Ethan Furman0063ff42020-09-21 17:23:13 -07002070 with self.assertRaisesRegex(TypeError, '1 is not a string'):
2071 class FirstFailedStrEnum(StrEnum):
2072 one = 1
2073 two = '2'
2074 with self.assertRaisesRegex(TypeError, "2 is not a string"):
2075 class SecondFailedStrEnum(StrEnum):
2076 one = '1'
2077 two = 2,
2078 three = '3'
2079 with self.assertRaisesRegex(TypeError, '2 is not a string'):
2080 class ThirdFailedStrEnum(StrEnum):
2081 one = '1'
2082 two = 2
2083 with self.assertRaisesRegex(TypeError, 'encoding must be a string, not %r' % (sys.getdefaultencoding, )):
2084 class ThirdFailedStrEnum(StrEnum):
2085 one = '1'
2086 two = b'2', sys.getdefaultencoding
2087 with self.assertRaisesRegex(TypeError, 'errors must be a string, not 9'):
2088 class ThirdFailedStrEnum(StrEnum):
2089 one = '1'
2090 two = b'2', 'ascii', 9
Ethan Furman6b3d64a2013-06-14 16:55:46 -07002091
Ethan Furmane8e61272016-08-20 07:19:31 -07002092class TestOrder(unittest.TestCase):
2093
2094 def test_same_members(self):
2095 class Color(Enum):
2096 _order_ = 'red green blue'
2097 red = 1
2098 green = 2
2099 blue = 3
2100
2101 def test_same_members_with_aliases(self):
2102 class Color(Enum):
2103 _order_ = 'red green blue'
2104 red = 1
2105 green = 2
2106 blue = 3
2107 verde = green
2108
2109 def test_same_members_wrong_order(self):
2110 with self.assertRaisesRegex(TypeError, 'member order does not match _order_'):
2111 class Color(Enum):
2112 _order_ = 'red green blue'
2113 red = 1
2114 blue = 3
2115 green = 2
2116
2117 def test_order_has_extra_members(self):
2118 with self.assertRaisesRegex(TypeError, 'member order does not match _order_'):
2119 class Color(Enum):
2120 _order_ = 'red green blue purple'
2121 red = 1
2122 green = 2
2123 blue = 3
2124
2125 def test_order_has_extra_members_with_aliases(self):
2126 with self.assertRaisesRegex(TypeError, 'member order does not match _order_'):
2127 class Color(Enum):
2128 _order_ = 'red green blue purple'
2129 red = 1
2130 green = 2
2131 blue = 3
2132 verde = green
2133
2134 def test_enum_has_extra_members(self):
2135 with self.assertRaisesRegex(TypeError, 'member order does not match _order_'):
2136 class Color(Enum):
2137 _order_ = 'red green blue'
2138 red = 1
2139 green = 2
2140 blue = 3
2141 purple = 4
2142
2143 def test_enum_has_extra_members_with_aliases(self):
2144 with self.assertRaisesRegex(TypeError, 'member order does not match _order_'):
2145 class Color(Enum):
2146 _order_ = 'red green blue'
2147 red = 1
2148 green = 2
2149 blue = 3
2150 purple = 4
2151 verde = green
2152
2153
Ethan Furman65a5a472016-09-01 23:55:19 -07002154class TestFlag(unittest.TestCase):
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002155 """Tests of the Flags."""
2156
Ethan Furman65a5a472016-09-01 23:55:19 -07002157 class Perm(Flag):
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002158 R, W, X = 4, 2, 1
2159
Ethan Furman65a5a472016-09-01 23:55:19 -07002160 class Open(Flag):
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002161 RO = 0
2162 WO = 1
2163 RW = 2
2164 AC = 3
2165 CE = 1<<19
2166
Rahul Jha94306522018-09-10 23:51:04 +05302167 class Color(Flag):
2168 BLACK = 0
2169 RED = 1
2170 GREEN = 2
2171 BLUE = 4
2172 PURPLE = RED|BLUE
2173
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002174 def test_str(self):
2175 Perm = self.Perm
2176 self.assertEqual(str(Perm.R), 'Perm.R')
2177 self.assertEqual(str(Perm.W), 'Perm.W')
2178 self.assertEqual(str(Perm.X), 'Perm.X')
2179 self.assertEqual(str(Perm.R | Perm.W), 'Perm.R|W')
2180 self.assertEqual(str(Perm.R | Perm.W | Perm.X), 'Perm.R|W|X')
2181 self.assertEqual(str(Perm(0)), 'Perm.0')
2182 self.assertEqual(str(~Perm.R), 'Perm.W|X')
2183 self.assertEqual(str(~Perm.W), 'Perm.R|X')
2184 self.assertEqual(str(~Perm.X), 'Perm.R|W')
2185 self.assertEqual(str(~(Perm.R | Perm.W)), 'Perm.X')
2186 self.assertEqual(str(~(Perm.R | Perm.W | Perm.X)), 'Perm.0')
2187 self.assertEqual(str(Perm(~0)), 'Perm.R|W|X')
2188
2189 Open = self.Open
2190 self.assertEqual(str(Open.RO), 'Open.RO')
2191 self.assertEqual(str(Open.WO), 'Open.WO')
2192 self.assertEqual(str(Open.AC), 'Open.AC')
2193 self.assertEqual(str(Open.RO | Open.CE), 'Open.CE')
2194 self.assertEqual(str(Open.WO | Open.CE), 'Open.CE|WO')
Ethan Furman3515dcc2016-09-18 13:15:41 -07002195 self.assertEqual(str(~Open.RO), 'Open.CE|AC|RW|WO')
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002196 self.assertEqual(str(~Open.WO), 'Open.CE|RW')
2197 self.assertEqual(str(~Open.AC), 'Open.CE')
2198 self.assertEqual(str(~(Open.RO | Open.CE)), 'Open.AC')
2199 self.assertEqual(str(~(Open.WO | Open.CE)), 'Open.RW')
2200
2201 def test_repr(self):
2202 Perm = self.Perm
2203 self.assertEqual(repr(Perm.R), '<Perm.R: 4>')
2204 self.assertEqual(repr(Perm.W), '<Perm.W: 2>')
2205 self.assertEqual(repr(Perm.X), '<Perm.X: 1>')
2206 self.assertEqual(repr(Perm.R | Perm.W), '<Perm.R|W: 6>')
2207 self.assertEqual(repr(Perm.R | Perm.W | Perm.X), '<Perm.R|W|X: 7>')
Ethan Furman27682d22016-09-04 11:39:01 -07002208 self.assertEqual(repr(Perm(0)), '<Perm.0: 0>')
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002209 self.assertEqual(repr(~Perm.R), '<Perm.W|X: 3>')
2210 self.assertEqual(repr(~Perm.W), '<Perm.R|X: 5>')
2211 self.assertEqual(repr(~Perm.X), '<Perm.R|W: 6>')
2212 self.assertEqual(repr(~(Perm.R | Perm.W)), '<Perm.X: 1>')
Ethan Furman27682d22016-09-04 11:39:01 -07002213 self.assertEqual(repr(~(Perm.R | Perm.W | Perm.X)), '<Perm.0: 0>')
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002214 self.assertEqual(repr(Perm(~0)), '<Perm.R|W|X: 7>')
2215
2216 Open = self.Open
2217 self.assertEqual(repr(Open.RO), '<Open.RO: 0>')
2218 self.assertEqual(repr(Open.WO), '<Open.WO: 1>')
2219 self.assertEqual(repr(Open.AC), '<Open.AC: 3>')
2220 self.assertEqual(repr(Open.RO | Open.CE), '<Open.CE: 524288>')
2221 self.assertEqual(repr(Open.WO | Open.CE), '<Open.CE|WO: 524289>')
Ethan Furman3515dcc2016-09-18 13:15:41 -07002222 self.assertEqual(repr(~Open.RO), '<Open.CE|AC|RW|WO: 524291>')
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002223 self.assertEqual(repr(~Open.WO), '<Open.CE|RW: 524290>')
2224 self.assertEqual(repr(~Open.AC), '<Open.CE: 524288>')
2225 self.assertEqual(repr(~(Open.RO | Open.CE)), '<Open.AC: 3>')
2226 self.assertEqual(repr(~(Open.WO | Open.CE)), '<Open.RW: 2>')
2227
2228 def test_or(self):
2229 Perm = self.Perm
2230 for i in Perm:
2231 for j in Perm:
2232 self.assertEqual((i | j), Perm(i.value | j.value))
2233 self.assertEqual((i | j).value, i.value | j.value)
2234 self.assertIs(type(i | j), Perm)
2235 for i in Perm:
2236 self.assertIs(i | i, i)
2237 Open = self.Open
2238 self.assertIs(Open.RO | Open.CE, Open.CE)
2239
2240 def test_and(self):
2241 Perm = self.Perm
2242 RW = Perm.R | Perm.W
2243 RX = Perm.R | Perm.X
2244 WX = Perm.W | Perm.X
2245 RWX = Perm.R | Perm.W | Perm.X
2246 values = list(Perm) + [RW, RX, WX, RWX, Perm(0)]
2247 for i in values:
2248 for j in values:
2249 self.assertEqual((i & j).value, i.value & j.value)
2250 self.assertIs(type(i & j), Perm)
2251 for i in Perm:
2252 self.assertIs(i & i, i)
2253 self.assertIs(i & RWX, i)
2254 self.assertIs(RWX & i, i)
2255 Open = self.Open
2256 self.assertIs(Open.RO & Open.CE, Open.RO)
2257
2258 def test_xor(self):
2259 Perm = self.Perm
2260 for i in Perm:
2261 for j in Perm:
2262 self.assertEqual((i ^ j).value, i.value ^ j.value)
2263 self.assertIs(type(i ^ j), Perm)
2264 for i in Perm:
2265 self.assertIs(i ^ Perm(0), i)
2266 self.assertIs(Perm(0) ^ i, i)
2267 Open = self.Open
2268 self.assertIs(Open.RO ^ Open.CE, Open.CE)
2269 self.assertIs(Open.CE ^ Open.CE, Open.RO)
2270
2271 def test_invert(self):
2272 Perm = self.Perm
2273 RW = Perm.R | Perm.W
2274 RX = Perm.R | Perm.X
2275 WX = Perm.W | Perm.X
2276 RWX = Perm.R | Perm.W | Perm.X
2277 values = list(Perm) + [RW, RX, WX, RWX, Perm(0)]
2278 for i in values:
2279 self.assertIs(type(~i), Perm)
2280 self.assertEqual(~~i, i)
2281 for i in Perm:
2282 self.assertIs(~~i, i)
2283 Open = self.Open
2284 self.assertIs(Open.WO & ~Open.WO, Open.RO)
2285 self.assertIs((Open.WO|Open.CE) & ~Open.WO, Open.CE)
2286
Ethan Furman25d94bb2016-09-02 16:32:32 -07002287 def test_bool(self):
2288 Perm = self.Perm
2289 for f in Perm:
2290 self.assertTrue(f)
2291 Open = self.Open
2292 for f in Open:
2293 self.assertEqual(bool(f.value), bool(f))
2294
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002295 def test_programatic_function_string(self):
Ethan Furman65a5a472016-09-01 23:55:19 -07002296 Perm = Flag('Perm', 'R W X')
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002297 lst = list(Perm)
2298 self.assertEqual(len(lst), len(Perm))
2299 self.assertEqual(len(Perm), 3, Perm)
2300 self.assertEqual(lst, [Perm.R, Perm.W, Perm.X])
2301 for i, n in enumerate('R W X'.split()):
2302 v = 1<<i
2303 e = Perm(v)
2304 self.assertEqual(e.value, v)
2305 self.assertEqual(type(e.value), int)
2306 self.assertEqual(e.name, n)
2307 self.assertIn(e, Perm)
2308 self.assertIs(type(e), Perm)
2309
2310 def test_programatic_function_string_with_start(self):
Ethan Furman65a5a472016-09-01 23:55:19 -07002311 Perm = Flag('Perm', 'R W X', start=8)
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002312 lst = list(Perm)
2313 self.assertEqual(len(lst), len(Perm))
2314 self.assertEqual(len(Perm), 3, Perm)
2315 self.assertEqual(lst, [Perm.R, Perm.W, Perm.X])
2316 for i, n in enumerate('R W X'.split()):
2317 v = 8<<i
2318 e = Perm(v)
2319 self.assertEqual(e.value, v)
2320 self.assertEqual(type(e.value), int)
2321 self.assertEqual(e.name, n)
2322 self.assertIn(e, Perm)
2323 self.assertIs(type(e), Perm)
2324
2325 def test_programatic_function_string_list(self):
Ethan Furman65a5a472016-09-01 23:55:19 -07002326 Perm = Flag('Perm', ['R', 'W', 'X'])
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002327 lst = list(Perm)
2328 self.assertEqual(len(lst), len(Perm))
2329 self.assertEqual(len(Perm), 3, Perm)
2330 self.assertEqual(lst, [Perm.R, Perm.W, Perm.X])
2331 for i, n in enumerate('R W X'.split()):
2332 v = 1<<i
2333 e = Perm(v)
2334 self.assertEqual(e.value, v)
2335 self.assertEqual(type(e.value), int)
2336 self.assertEqual(e.name, n)
2337 self.assertIn(e, Perm)
2338 self.assertIs(type(e), Perm)
2339
2340 def test_programatic_function_iterable(self):
Ethan Furman65a5a472016-09-01 23:55:19 -07002341 Perm = Flag('Perm', (('R', 2), ('W', 8), ('X', 32)))
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002342 lst = list(Perm)
2343 self.assertEqual(len(lst), len(Perm))
2344 self.assertEqual(len(Perm), 3, Perm)
2345 self.assertEqual(lst, [Perm.R, Perm.W, Perm.X])
2346 for i, n in enumerate('R W X'.split()):
2347 v = 1<<(2*i+1)
2348 e = Perm(v)
2349 self.assertEqual(e.value, v)
2350 self.assertEqual(type(e.value), int)
2351 self.assertEqual(e.name, n)
2352 self.assertIn(e, Perm)
2353 self.assertIs(type(e), Perm)
2354
2355 def test_programatic_function_from_dict(self):
Ethan Furman65a5a472016-09-01 23:55:19 -07002356 Perm = Flag('Perm', OrderedDict((('R', 2), ('W', 8), ('X', 32))))
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002357 lst = list(Perm)
2358 self.assertEqual(len(lst), len(Perm))
2359 self.assertEqual(len(Perm), 3, Perm)
2360 self.assertEqual(lst, [Perm.R, Perm.W, Perm.X])
2361 for i, n in enumerate('R W X'.split()):
2362 v = 1<<(2*i+1)
2363 e = Perm(v)
2364 self.assertEqual(e.value, v)
2365 self.assertEqual(type(e.value), int)
2366 self.assertEqual(e.name, n)
2367 self.assertIn(e, Perm)
2368 self.assertIs(type(e), Perm)
2369
Ethan Furman65a5a472016-09-01 23:55:19 -07002370 def test_pickle(self):
2371 if isinstance(FlagStooges, Exception):
2372 raise FlagStooges
2373 test_pickle_dump_load(self.assertIs, FlagStooges.CURLY|FlagStooges.MOE)
2374 test_pickle_dump_load(self.assertIs, FlagStooges)
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002375
Rahul Jha94306522018-09-10 23:51:04 +05302376 def test_contains(self):
2377 Open = self.Open
2378 Color = self.Color
2379 self.assertFalse(Color.BLACK in Open)
2380 self.assertFalse(Open.RO in Color)
2381 with self.assertRaises(TypeError):
2382 'BLACK' in Color
2383 with self.assertRaises(TypeError):
2384 'RO' in Open
2385 with self.assertRaises(TypeError):
2386 1 in Color
2387 with self.assertRaises(TypeError):
2388 1 in Open
2389
2390 def test_member_contains(self):
Ethan Furman65a5a472016-09-01 23:55:19 -07002391 Perm = self.Perm
2392 R, W, X = Perm
2393 RW = R | W
2394 RX = R | X
2395 WX = W | X
2396 RWX = R | W | X
2397 self.assertTrue(R in RW)
2398 self.assertTrue(R in RX)
2399 self.assertTrue(R in RWX)
2400 self.assertTrue(W in RW)
2401 self.assertTrue(W in WX)
2402 self.assertTrue(W in RWX)
2403 self.assertTrue(X in RX)
2404 self.assertTrue(X in WX)
2405 self.assertTrue(X in RWX)
2406 self.assertFalse(R in WX)
2407 self.assertFalse(W in RX)
2408 self.assertFalse(X in RW)
2409
Ethan Furman7219e272020-09-16 13:01:00 -07002410 def test_member_iter(self):
2411 Color = self.Color
2412 self.assertEqual(list(Color.PURPLE), [Color.BLUE, Color.RED])
2413 self.assertEqual(list(Color.BLUE), [Color.BLUE])
2414 self.assertEqual(list(Color.GREEN), [Color.GREEN])
2415
Ethan Furmanc16595e2016-09-10 23:36:59 -07002416 def test_auto_number(self):
2417 class Color(Flag):
2418 red = auto()
2419 blue = auto()
2420 green = auto()
2421
2422 self.assertEqual(list(Color), [Color.red, Color.blue, Color.green])
2423 self.assertEqual(Color.red.value, 1)
2424 self.assertEqual(Color.blue.value, 2)
2425 self.assertEqual(Color.green.value, 4)
2426
2427 def test_auto_number_garbage(self):
2428 with self.assertRaisesRegex(TypeError, 'Invalid Flag value: .not an int.'):
2429 class Color(Flag):
2430 red = 'not an int'
2431 blue = auto()
2432
Ethan Furman3515dcc2016-09-18 13:15:41 -07002433 def test_cascading_failure(self):
2434 class Bizarre(Flag):
2435 c = 3
2436 d = 4
2437 f = 6
2438 # Bizarre.c | Bizarre.d
Walter Dörwald323842c2019-07-18 20:37:13 +02002439 name = "TestFlag.test_cascading_failure.<locals>.Bizarre"
2440 self.assertRaisesRegex(ValueError, "5 is not a valid " + name, Bizarre, 5)
2441 self.assertRaisesRegex(ValueError, "5 is not a valid " + name, Bizarre, 5)
2442 self.assertRaisesRegex(ValueError, "2 is not a valid " + name, Bizarre, 2)
2443 self.assertRaisesRegex(ValueError, "2 is not a valid " + name, Bizarre, 2)
2444 self.assertRaisesRegex(ValueError, "1 is not a valid " + name, Bizarre, 1)
2445 self.assertRaisesRegex(ValueError, "1 is not a valid " + name, Bizarre, 1)
Ethan Furman3515dcc2016-09-18 13:15:41 -07002446
2447 def test_duplicate_auto(self):
2448 class Dupes(Enum):
2449 first = primero = auto()
2450 second = auto()
2451 third = auto()
2452 self.assertEqual([Dupes.first, Dupes.second, Dupes.third], list(Dupes))
2453
2454 def test_bizarre(self):
2455 class Bizarre(Flag):
2456 b = 3
2457 c = 4
2458 d = 6
2459 self.assertEqual(repr(Bizarre(7)), '<Bizarre.d|c|b: 7>')
2460
Ethan Furman5bdab642018-09-21 19:03:09 -07002461 def test_multiple_mixin(self):
2462 class AllMixin:
2463 @classproperty
2464 def ALL(cls):
2465 members = list(cls)
2466 all_value = None
2467 if members:
2468 all_value = members[0]
2469 for member in members[1:]:
2470 all_value |= member
2471 cls.ALL = all_value
2472 return all_value
2473 class StrMixin:
2474 def __str__(self):
2475 return self._name_.lower()
2476 class Color(AllMixin, Flag):
2477 RED = auto()
2478 GREEN = auto()
2479 BLUE = auto()
2480 self.assertEqual(Color.RED.value, 1)
2481 self.assertEqual(Color.GREEN.value, 2)
2482 self.assertEqual(Color.BLUE.value, 4)
2483 self.assertEqual(Color.ALL.value, 7)
2484 self.assertEqual(str(Color.BLUE), 'Color.BLUE')
2485 class Color(AllMixin, StrMixin, Flag):
2486 RED = auto()
2487 GREEN = auto()
2488 BLUE = auto()
2489 self.assertEqual(Color.RED.value, 1)
2490 self.assertEqual(Color.GREEN.value, 2)
2491 self.assertEqual(Color.BLUE.value, 4)
2492 self.assertEqual(Color.ALL.value, 7)
2493 self.assertEqual(str(Color.BLUE), 'blue')
2494 class Color(StrMixin, AllMixin, Flag):
2495 RED = auto()
2496 GREEN = auto()
2497 BLUE = auto()
2498 self.assertEqual(Color.RED.value, 1)
2499 self.assertEqual(Color.GREEN.value, 2)
2500 self.assertEqual(Color.BLUE.value, 4)
2501 self.assertEqual(Color.ALL.value, 7)
2502 self.assertEqual(str(Color.BLUE), 'blue')
2503
Hai Shie80697d2020-05-28 06:10:27 +08002504 @threading_helper.reap_threads
Ethan Furman28cf6632017-01-24 12:12:06 -08002505 def test_unique_composite(self):
2506 # override __eq__ to be identity only
2507 class TestFlag(Flag):
2508 one = auto()
2509 two = auto()
2510 three = auto()
2511 four = auto()
2512 five = auto()
2513 six = auto()
2514 seven = auto()
2515 eight = auto()
2516 def __eq__(self, other):
2517 return self is other
2518 def __hash__(self):
2519 return hash(self._value_)
2520 # have multiple threads competing to complete the composite members
2521 seen = set()
2522 failed = False
2523 def cycle_enum():
2524 nonlocal failed
2525 try:
2526 for i in range(256):
2527 seen.add(TestFlag(i))
2528 except Exception:
2529 failed = True
2530 threads = [
2531 threading.Thread(target=cycle_enum)
2532 for _ in range(8)
2533 ]
Hai Shie80697d2020-05-28 06:10:27 +08002534 with threading_helper.start_threads(threads):
Ethan Furman28cf6632017-01-24 12:12:06 -08002535 pass
2536 # check that only 248 members were created
2537 self.assertFalse(
2538 failed,
2539 'at least one thread failed while creating composite members')
2540 self.assertEqual(256, len(seen), 'too many composite members created')
2541
Ethan Furmanc16595e2016-09-10 23:36:59 -07002542
Ethan Furman65a5a472016-09-01 23:55:19 -07002543class TestIntFlag(unittest.TestCase):
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002544 """Tests of the IntFlags."""
2545
Ethan Furman65a5a472016-09-01 23:55:19 -07002546 class Perm(IntFlag):
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002547 X = 1 << 0
2548 W = 1 << 1
2549 R = 1 << 2
2550
Ethan Furman65a5a472016-09-01 23:55:19 -07002551 class Open(IntFlag):
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002552 RO = 0
2553 WO = 1
2554 RW = 2
2555 AC = 3
2556 CE = 1<<19
2557
Rahul Jha94306522018-09-10 23:51:04 +05302558 class Color(IntFlag):
2559 BLACK = 0
2560 RED = 1
2561 GREEN = 2
2562 BLUE = 4
2563 PURPLE = RED|BLUE
2564
Ethan Furman3515dcc2016-09-18 13:15:41 -07002565 def test_type(self):
2566 Perm = self.Perm
2567 Open = self.Open
2568 for f in Perm:
2569 self.assertTrue(isinstance(f, Perm))
2570 self.assertEqual(f, f.value)
2571 self.assertTrue(isinstance(Perm.W | Perm.X, Perm))
2572 self.assertEqual(Perm.W | Perm.X, 3)
2573 for f in Open:
2574 self.assertTrue(isinstance(f, Open))
2575 self.assertEqual(f, f.value)
2576 self.assertTrue(isinstance(Open.WO | Open.RW, Open))
2577 self.assertEqual(Open.WO | Open.RW, 3)
2578
2579
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002580 def test_str(self):
2581 Perm = self.Perm
2582 self.assertEqual(str(Perm.R), 'Perm.R')
2583 self.assertEqual(str(Perm.W), 'Perm.W')
2584 self.assertEqual(str(Perm.X), 'Perm.X')
2585 self.assertEqual(str(Perm.R | Perm.W), 'Perm.R|W')
2586 self.assertEqual(str(Perm.R | Perm.W | Perm.X), 'Perm.R|W|X')
2587 self.assertEqual(str(Perm.R | 8), 'Perm.8|R')
2588 self.assertEqual(str(Perm(0)), 'Perm.0')
2589 self.assertEqual(str(Perm(8)), 'Perm.8')
Ethan Furman3515dcc2016-09-18 13:15:41 -07002590 self.assertEqual(str(~Perm.R), 'Perm.W|X')
2591 self.assertEqual(str(~Perm.W), 'Perm.R|X')
2592 self.assertEqual(str(~Perm.X), 'Perm.R|W')
2593 self.assertEqual(str(~(Perm.R | Perm.W)), 'Perm.X')
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002594 self.assertEqual(str(~(Perm.R | Perm.W | Perm.X)), 'Perm.-8')
Ethan Furman3515dcc2016-09-18 13:15:41 -07002595 self.assertEqual(str(~(Perm.R | 8)), 'Perm.W|X')
2596 self.assertEqual(str(Perm(~0)), 'Perm.R|W|X')
2597 self.assertEqual(str(Perm(~8)), 'Perm.R|W|X')
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002598
2599 Open = self.Open
2600 self.assertEqual(str(Open.RO), 'Open.RO')
2601 self.assertEqual(str(Open.WO), 'Open.WO')
2602 self.assertEqual(str(Open.AC), 'Open.AC')
2603 self.assertEqual(str(Open.RO | Open.CE), 'Open.CE')
2604 self.assertEqual(str(Open.WO | Open.CE), 'Open.CE|WO')
2605 self.assertEqual(str(Open(4)), 'Open.4')
Ethan Furman3515dcc2016-09-18 13:15:41 -07002606 self.assertEqual(str(~Open.RO), 'Open.CE|AC|RW|WO')
2607 self.assertEqual(str(~Open.WO), 'Open.CE|RW')
2608 self.assertEqual(str(~Open.AC), 'Open.CE')
2609 self.assertEqual(str(~(Open.RO | Open.CE)), 'Open.AC|RW|WO')
2610 self.assertEqual(str(~(Open.WO | Open.CE)), 'Open.RW')
2611 self.assertEqual(str(Open(~4)), 'Open.CE|AC|RW|WO')
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002612
2613 def test_repr(self):
2614 Perm = self.Perm
2615 self.assertEqual(repr(Perm.R), '<Perm.R: 4>')
2616 self.assertEqual(repr(Perm.W), '<Perm.W: 2>')
2617 self.assertEqual(repr(Perm.X), '<Perm.X: 1>')
2618 self.assertEqual(repr(Perm.R | Perm.W), '<Perm.R|W: 6>')
2619 self.assertEqual(repr(Perm.R | Perm.W | Perm.X), '<Perm.R|W|X: 7>')
2620 self.assertEqual(repr(Perm.R | 8), '<Perm.8|R: 12>')
Ethan Furman27682d22016-09-04 11:39:01 -07002621 self.assertEqual(repr(Perm(0)), '<Perm.0: 0>')
2622 self.assertEqual(repr(Perm(8)), '<Perm.8: 8>')
Ethan Furman3515dcc2016-09-18 13:15:41 -07002623 self.assertEqual(repr(~Perm.R), '<Perm.W|X: -5>')
2624 self.assertEqual(repr(~Perm.W), '<Perm.R|X: -3>')
2625 self.assertEqual(repr(~Perm.X), '<Perm.R|W: -2>')
2626 self.assertEqual(repr(~(Perm.R | Perm.W)), '<Perm.X: -7>')
Ethan Furman27682d22016-09-04 11:39:01 -07002627 self.assertEqual(repr(~(Perm.R | Perm.W | Perm.X)), '<Perm.-8: -8>')
Ethan Furman3515dcc2016-09-18 13:15:41 -07002628 self.assertEqual(repr(~(Perm.R | 8)), '<Perm.W|X: -13>')
2629 self.assertEqual(repr(Perm(~0)), '<Perm.R|W|X: -1>')
2630 self.assertEqual(repr(Perm(~8)), '<Perm.R|W|X: -9>')
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002631
2632 Open = self.Open
2633 self.assertEqual(repr(Open.RO), '<Open.RO: 0>')
2634 self.assertEqual(repr(Open.WO), '<Open.WO: 1>')
2635 self.assertEqual(repr(Open.AC), '<Open.AC: 3>')
2636 self.assertEqual(repr(Open.RO | Open.CE), '<Open.CE: 524288>')
2637 self.assertEqual(repr(Open.WO | Open.CE), '<Open.CE|WO: 524289>')
Ethan Furman27682d22016-09-04 11:39:01 -07002638 self.assertEqual(repr(Open(4)), '<Open.4: 4>')
Ethan Furman3515dcc2016-09-18 13:15:41 -07002639 self.assertEqual(repr(~Open.RO), '<Open.CE|AC|RW|WO: -1>')
2640 self.assertEqual(repr(~Open.WO), '<Open.CE|RW: -2>')
2641 self.assertEqual(repr(~Open.AC), '<Open.CE: -4>')
2642 self.assertEqual(repr(~(Open.RO | Open.CE)), '<Open.AC|RW|WO: -524289>')
2643 self.assertEqual(repr(~(Open.WO | Open.CE)), '<Open.RW: -524290>')
2644 self.assertEqual(repr(Open(~4)), '<Open.CE|AC|RW|WO: -5>')
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002645
2646 def test_or(self):
2647 Perm = self.Perm
2648 for i in Perm:
2649 for j in Perm:
2650 self.assertEqual(i | j, i.value | j.value)
2651 self.assertEqual((i | j).value, i.value | j.value)
2652 self.assertIs(type(i | j), Perm)
2653 for j in range(8):
2654 self.assertEqual(i | j, i.value | j)
2655 self.assertEqual((i | j).value, i.value | j)
2656 self.assertIs(type(i | j), Perm)
2657 self.assertEqual(j | i, j | i.value)
2658 self.assertEqual((j | i).value, j | i.value)
2659 self.assertIs(type(j | i), Perm)
2660 for i in Perm:
2661 self.assertIs(i | i, i)
2662 self.assertIs(i | 0, i)
2663 self.assertIs(0 | i, i)
2664 Open = self.Open
2665 self.assertIs(Open.RO | Open.CE, Open.CE)
2666
2667 def test_and(self):
2668 Perm = self.Perm
2669 RW = Perm.R | Perm.W
2670 RX = Perm.R | Perm.X
2671 WX = Perm.W | Perm.X
2672 RWX = Perm.R | Perm.W | Perm.X
2673 values = list(Perm) + [RW, RX, WX, RWX, Perm(0)]
2674 for i in values:
2675 for j in values:
2676 self.assertEqual(i & j, i.value & j.value, 'i is %r, j is %r' % (i, j))
2677 self.assertEqual((i & j).value, i.value & j.value, 'i is %r, j is %r' % (i, j))
2678 self.assertIs(type(i & j), Perm, 'i is %r, j is %r' % (i, j))
2679 for j in range(8):
2680 self.assertEqual(i & j, i.value & j)
2681 self.assertEqual((i & j).value, i.value & j)
2682 self.assertIs(type(i & j), Perm)
2683 self.assertEqual(j & i, j & i.value)
2684 self.assertEqual((j & i).value, j & i.value)
2685 self.assertIs(type(j & i), Perm)
2686 for i in Perm:
2687 self.assertIs(i & i, i)
2688 self.assertIs(i & 7, i)
2689 self.assertIs(7 & i, i)
2690 Open = self.Open
2691 self.assertIs(Open.RO & Open.CE, Open.RO)
2692
2693 def test_xor(self):
2694 Perm = self.Perm
2695 for i in Perm:
2696 for j in Perm:
2697 self.assertEqual(i ^ j, i.value ^ j.value)
2698 self.assertEqual((i ^ j).value, i.value ^ j.value)
2699 self.assertIs(type(i ^ j), Perm)
2700 for j in range(8):
2701 self.assertEqual(i ^ j, i.value ^ j)
2702 self.assertEqual((i ^ j).value, i.value ^ j)
2703 self.assertIs(type(i ^ j), Perm)
2704 self.assertEqual(j ^ i, j ^ i.value)
2705 self.assertEqual((j ^ i).value, j ^ i.value)
2706 self.assertIs(type(j ^ i), Perm)
2707 for i in Perm:
2708 self.assertIs(i ^ 0, i)
2709 self.assertIs(0 ^ i, i)
2710 Open = self.Open
2711 self.assertIs(Open.RO ^ Open.CE, Open.CE)
2712 self.assertIs(Open.CE ^ Open.CE, Open.RO)
2713
2714 def test_invert(self):
2715 Perm = self.Perm
2716 RW = Perm.R | Perm.W
2717 RX = Perm.R | Perm.X
2718 WX = Perm.W | Perm.X
2719 RWX = Perm.R | Perm.W | Perm.X
2720 values = list(Perm) + [RW, RX, WX, RWX, Perm(0)]
2721 for i in values:
2722 self.assertEqual(~i, ~i.value)
2723 self.assertEqual((~i).value, ~i.value)
2724 self.assertIs(type(~i), Perm)
2725 self.assertEqual(~~i, i)
2726 for i in Perm:
2727 self.assertIs(~~i, i)
2728 Open = self.Open
2729 self.assertIs(Open.WO & ~Open.WO, Open.RO)
2730 self.assertIs((Open.WO|Open.CE) & ~Open.WO, Open.CE)
2731
2732 def test_programatic_function_string(self):
Ethan Furman65a5a472016-09-01 23:55:19 -07002733 Perm = IntFlag('Perm', 'R W X')
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002734 lst = list(Perm)
2735 self.assertEqual(len(lst), len(Perm))
2736 self.assertEqual(len(Perm), 3, Perm)
2737 self.assertEqual(lst, [Perm.R, Perm.W, Perm.X])
2738 for i, n in enumerate('R W X'.split()):
2739 v = 1<<i
2740 e = Perm(v)
2741 self.assertEqual(e.value, v)
2742 self.assertEqual(type(e.value), int)
2743 self.assertEqual(e, v)
2744 self.assertEqual(e.name, n)
2745 self.assertIn(e, Perm)
2746 self.assertIs(type(e), Perm)
2747
2748 def test_programatic_function_string_with_start(self):
Ethan Furman65a5a472016-09-01 23:55:19 -07002749 Perm = IntFlag('Perm', 'R W X', start=8)
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002750 lst = list(Perm)
2751 self.assertEqual(len(lst), len(Perm))
2752 self.assertEqual(len(Perm), 3, Perm)
2753 self.assertEqual(lst, [Perm.R, Perm.W, Perm.X])
2754 for i, n in enumerate('R W X'.split()):
2755 v = 8<<i
2756 e = Perm(v)
2757 self.assertEqual(e.value, v)
2758 self.assertEqual(type(e.value), int)
2759 self.assertEqual(e, v)
2760 self.assertEqual(e.name, n)
2761 self.assertIn(e, Perm)
2762 self.assertIs(type(e), Perm)
2763
2764 def test_programatic_function_string_list(self):
Ethan Furman65a5a472016-09-01 23:55:19 -07002765 Perm = IntFlag('Perm', ['R', 'W', 'X'])
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002766 lst = list(Perm)
2767 self.assertEqual(len(lst), len(Perm))
2768 self.assertEqual(len(Perm), 3, Perm)
2769 self.assertEqual(lst, [Perm.R, Perm.W, Perm.X])
2770 for i, n in enumerate('R W X'.split()):
2771 v = 1<<i
2772 e = Perm(v)
2773 self.assertEqual(e.value, v)
2774 self.assertEqual(type(e.value), int)
2775 self.assertEqual(e, v)
2776 self.assertEqual(e.name, n)
2777 self.assertIn(e, Perm)
2778 self.assertIs(type(e), Perm)
2779
2780 def test_programatic_function_iterable(self):
Ethan Furman65a5a472016-09-01 23:55:19 -07002781 Perm = IntFlag('Perm', (('R', 2), ('W', 8), ('X', 32)))
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002782 lst = list(Perm)
2783 self.assertEqual(len(lst), len(Perm))
2784 self.assertEqual(len(Perm), 3, Perm)
2785 self.assertEqual(lst, [Perm.R, Perm.W, Perm.X])
2786 for i, n in enumerate('R W X'.split()):
2787 v = 1<<(2*i+1)
2788 e = Perm(v)
2789 self.assertEqual(e.value, v)
2790 self.assertEqual(type(e.value), int)
2791 self.assertEqual(e, v)
2792 self.assertEqual(e.name, n)
2793 self.assertIn(e, Perm)
2794 self.assertIs(type(e), Perm)
2795
2796 def test_programatic_function_from_dict(self):
Ethan Furman65a5a472016-09-01 23:55:19 -07002797 Perm = IntFlag('Perm', OrderedDict((('R', 2), ('W', 8), ('X', 32))))
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002798 lst = list(Perm)
2799 self.assertEqual(len(lst), len(Perm))
2800 self.assertEqual(len(Perm), 3, Perm)
2801 self.assertEqual(lst, [Perm.R, Perm.W, Perm.X])
2802 for i, n in enumerate('R W X'.split()):
2803 v = 1<<(2*i+1)
2804 e = Perm(v)
2805 self.assertEqual(e.value, v)
2806 self.assertEqual(type(e.value), int)
2807 self.assertEqual(e, v)
2808 self.assertEqual(e.name, n)
2809 self.assertIn(e, Perm)
2810 self.assertIs(type(e), Perm)
2811
2812
Dong-hee Nadcc8ce42017-06-22 01:52:32 +09002813 def test_programatic_function_from_empty_list(self):
2814 Perm = enum.IntFlag('Perm', [])
2815 lst = list(Perm)
2816 self.assertEqual(len(lst), len(Perm))
2817 self.assertEqual(len(Perm), 0, Perm)
2818 Thing = enum.Enum('Thing', [])
2819 lst = list(Thing)
2820 self.assertEqual(len(lst), len(Thing))
2821 self.assertEqual(len(Thing), 0, Thing)
2822
2823
2824 def test_programatic_function_from_empty_tuple(self):
2825 Perm = enum.IntFlag('Perm', ())
2826 lst = list(Perm)
2827 self.assertEqual(len(lst), len(Perm))
2828 self.assertEqual(len(Perm), 0, Perm)
2829 Thing = enum.Enum('Thing', ())
2830 self.assertEqual(len(lst), len(Thing))
2831 self.assertEqual(len(Thing), 0, Thing)
2832
Rahul Jha94306522018-09-10 23:51:04 +05302833 def test_contains(self):
2834 Open = self.Open
2835 Color = self.Color
2836 self.assertTrue(Color.GREEN in Color)
2837 self.assertTrue(Open.RW in Open)
2838 self.assertFalse(Color.GREEN in Open)
2839 self.assertFalse(Open.RW in Color)
2840 with self.assertRaises(TypeError):
2841 'GREEN' in Color
2842 with self.assertRaises(TypeError):
2843 'RW' in Open
2844 with self.assertRaises(TypeError):
2845 2 in Color
2846 with self.assertRaises(TypeError):
2847 2 in Open
2848
2849 def test_member_contains(self):
Ethan Furman65a5a472016-09-01 23:55:19 -07002850 Perm = self.Perm
2851 R, W, X = Perm
2852 RW = R | W
2853 RX = R | X
2854 WX = W | X
2855 RWX = R | W | X
2856 self.assertTrue(R in RW)
2857 self.assertTrue(R in RX)
2858 self.assertTrue(R in RWX)
2859 self.assertTrue(W in RW)
2860 self.assertTrue(W in WX)
2861 self.assertTrue(W in RWX)
2862 self.assertTrue(X in RX)
2863 self.assertTrue(X in WX)
2864 self.assertTrue(X in RWX)
2865 self.assertFalse(R in WX)
2866 self.assertFalse(W in RX)
2867 self.assertFalse(X in RW)
Rahul Jha94306522018-09-10 23:51:04 +05302868 with self.assertRaises(TypeError):
2869 self.assertFalse('test' in RW)
Ethan Furman65a5a472016-09-01 23:55:19 -07002870
Ethan Furman7219e272020-09-16 13:01:00 -07002871 def test_member_iter(self):
2872 Color = self.Color
2873 self.assertEqual(list(Color.PURPLE), [Color.BLUE, Color.RED])
2874 self.assertEqual(list(Color.BLUE), [Color.BLUE])
2875 self.assertEqual(list(Color.GREEN), [Color.GREEN])
2876
Ethan Furman25d94bb2016-09-02 16:32:32 -07002877 def test_bool(self):
2878 Perm = self.Perm
2879 for f in Perm:
2880 self.assertTrue(f)
2881 Open = self.Open
2882 for f in Open:
2883 self.assertEqual(bool(f.value), bool(f))
2884
Ethan Furman5bdab642018-09-21 19:03:09 -07002885 def test_multiple_mixin(self):
2886 class AllMixin:
2887 @classproperty
2888 def ALL(cls):
2889 members = list(cls)
2890 all_value = None
2891 if members:
2892 all_value = members[0]
2893 for member in members[1:]:
2894 all_value |= member
2895 cls.ALL = all_value
2896 return all_value
2897 class StrMixin:
2898 def __str__(self):
2899 return self._name_.lower()
2900 class Color(AllMixin, IntFlag):
2901 RED = auto()
2902 GREEN = auto()
2903 BLUE = auto()
2904 self.assertEqual(Color.RED.value, 1)
2905 self.assertEqual(Color.GREEN.value, 2)
2906 self.assertEqual(Color.BLUE.value, 4)
2907 self.assertEqual(Color.ALL.value, 7)
2908 self.assertEqual(str(Color.BLUE), 'Color.BLUE')
2909 class Color(AllMixin, StrMixin, IntFlag):
2910 RED = auto()
2911 GREEN = auto()
2912 BLUE = auto()
2913 self.assertEqual(Color.RED.value, 1)
2914 self.assertEqual(Color.GREEN.value, 2)
2915 self.assertEqual(Color.BLUE.value, 4)
2916 self.assertEqual(Color.ALL.value, 7)
2917 self.assertEqual(str(Color.BLUE), 'blue')
2918 class Color(StrMixin, AllMixin, IntFlag):
2919 RED = auto()
2920 GREEN = auto()
2921 BLUE = auto()
2922 self.assertEqual(Color.RED.value, 1)
2923 self.assertEqual(Color.GREEN.value, 2)
2924 self.assertEqual(Color.BLUE.value, 4)
2925 self.assertEqual(Color.ALL.value, 7)
2926 self.assertEqual(str(Color.BLUE), 'blue')
2927
Hai Shie80697d2020-05-28 06:10:27 +08002928 @threading_helper.reap_threads
Ethan Furman28cf6632017-01-24 12:12:06 -08002929 def test_unique_composite(self):
2930 # override __eq__ to be identity only
2931 class TestFlag(IntFlag):
2932 one = auto()
2933 two = auto()
2934 three = auto()
2935 four = auto()
2936 five = auto()
2937 six = auto()
2938 seven = auto()
2939 eight = auto()
2940 def __eq__(self, other):
2941 return self is other
2942 def __hash__(self):
2943 return hash(self._value_)
2944 # have multiple threads competing to complete the composite members
2945 seen = set()
2946 failed = False
2947 def cycle_enum():
2948 nonlocal failed
2949 try:
2950 for i in range(256):
2951 seen.add(TestFlag(i))
2952 except Exception:
2953 failed = True
2954 threads = [
2955 threading.Thread(target=cycle_enum)
2956 for _ in range(8)
2957 ]
Hai Shie80697d2020-05-28 06:10:27 +08002958 with threading_helper.start_threads(threads):
Ethan Furman28cf6632017-01-24 12:12:06 -08002959 pass
2960 # check that only 248 members were created
2961 self.assertFalse(
2962 failed,
2963 'at least one thread failed while creating composite members')
2964 self.assertEqual(256, len(seen), 'too many composite members created')
2965
2966
Brennan D Baraban8b914d22019-03-03 14:09:11 -08002967class TestEmptyAndNonLatinStrings(unittest.TestCase):
2968
2969 def test_empty_string(self):
2970 with self.assertRaises(ValueError):
2971 empty_abc = Enum('empty_abc', ('', 'B', 'C'))
2972
2973 def test_non_latin_character_string(self):
2974 greek_abc = Enum('greek_abc', ('\u03B1', 'B', 'C'))
2975 item = getattr(greek_abc, '\u03B1')
2976 self.assertEqual(item.value, 1)
2977
2978 def test_non_latin_number_string(self):
2979 hebrew_123 = Enum('hebrew_123', ('\u05D0', '2', '3'))
2980 item = getattr(hebrew_123, '\u05D0')
2981 self.assertEqual(item.value, 1)
2982
2983
Ethan Furmanf24bb352013-07-18 17:05:39 -07002984class TestUnique(unittest.TestCase):
2985
2986 def test_unique_clean(self):
2987 @unique
2988 class Clean(Enum):
2989 one = 1
2990 two = 'dos'
2991 tres = 4.0
2992 @unique
2993 class Cleaner(IntEnum):
2994 single = 1
2995 double = 2
2996 triple = 3
2997
2998 def test_unique_dirty(self):
2999 with self.assertRaisesRegex(ValueError, 'tres.*one'):
3000 @unique
3001 class Dirty(Enum):
3002 one = 1
3003 two = 'dos'
3004 tres = 1
3005 with self.assertRaisesRegex(
3006 ValueError,
3007 'double.*single.*turkey.*triple',
3008 ):
3009 @unique
3010 class Dirtier(IntEnum):
3011 single = 1
3012 double = 1
3013 triple = 3
3014 turkey = 3
3015
Ethan Furman3803ad42016-05-01 10:03:53 -07003016 def test_unique_with_name(self):
3017 @unique
3018 class Silly(Enum):
3019 one = 1
3020 two = 'dos'
3021 name = 3
3022 @unique
3023 class Sillier(IntEnum):
3024 single = 1
3025 name = 2
3026 triple = 3
3027 value = 4
3028
Ethan Furmanf24bb352013-07-18 17:05:39 -07003029
Ethan Furman5bdab642018-09-21 19:03:09 -07003030
Ethan Furman3323da92015-04-11 09:39:59 -07003031expected_help_output_with_docs = """\
Ethan Furman5875d742013-10-21 20:45:55 -07003032Help on class Color in module %s:
3033
3034class Color(enum.Enum)
Serhiy Storchaka90f63322017-01-24 09:06:22 +02003035 | Color(value, names=None, *, module=None, qualname=None, type=None, start=1)
3036 |\x20\x20
Ethan Furman48a724f2015-04-11 23:23:06 -07003037 | An enumeration.
Serhiy Storchakab599ca82015-04-04 12:48:04 +03003038 |\x20\x20
Ethan Furman5875d742013-10-21 20:45:55 -07003039 | Method resolution order:
3040 | Color
3041 | enum.Enum
3042 | builtins.object
3043 |\x20\x20
3044 | Data and other attributes defined here:
3045 |\x20\x20
3046 | blue = <Color.blue: 3>
3047 |\x20\x20
3048 | green = <Color.green: 2>
3049 |\x20\x20
3050 | red = <Color.red: 1>
3051 |\x20\x20
3052 | ----------------------------------------------------------------------
3053 | Data descriptors inherited from enum.Enum:
3054 |\x20\x20
3055 | name
3056 | The name of the Enum member.
3057 |\x20\x20
3058 | value
3059 | The value of the Enum member.
3060 |\x20\x20
3061 | ----------------------------------------------------------------------
Raymond Hettinger62be3382019-03-24 17:07:47 -07003062 | Readonly properties inherited from enum.EnumMeta:
Ethan Furman5875d742013-10-21 20:45:55 -07003063 |\x20\x20
3064 | __members__
3065 | Returns a mapping of member name->value.
3066 |\x20\x20\x20\x20\x20\x20
3067 | This mapping lists all enum members, including aliases. Note that this
Ethan Furman3323da92015-04-11 09:39:59 -07003068 | is a read-only view of the internal mapping."""
3069
3070expected_help_output_without_docs = """\
3071Help on class Color in module %s:
3072
3073class Color(enum.Enum)
Serhiy Storchaka90f63322017-01-24 09:06:22 +02003074 | Color(value, names=None, *, module=None, qualname=None, type=None, start=1)
3075 |\x20\x20
Ethan Furman3323da92015-04-11 09:39:59 -07003076 | Method resolution order:
3077 | Color
3078 | enum.Enum
3079 | builtins.object
3080 |\x20\x20
3081 | Data and other attributes defined here:
3082 |\x20\x20
3083 | blue = <Color.blue: 3>
3084 |\x20\x20
3085 | green = <Color.green: 2>
3086 |\x20\x20
3087 | red = <Color.red: 1>
3088 |\x20\x20
3089 | ----------------------------------------------------------------------
3090 | Data descriptors inherited from enum.Enum:
3091 |\x20\x20
3092 | name
3093 |\x20\x20
3094 | value
3095 |\x20\x20
3096 | ----------------------------------------------------------------------
3097 | Data descriptors inherited from enum.EnumMeta:
3098 |\x20\x20
3099 | __members__"""
Ethan Furman5875d742013-10-21 20:45:55 -07003100
3101class TestStdLib(unittest.TestCase):
3102
Ethan Furman48a724f2015-04-11 23:23:06 -07003103 maxDiff = None
3104
Ethan Furman5875d742013-10-21 20:45:55 -07003105 class Color(Enum):
3106 red = 1
3107 green = 2
3108 blue = 3
3109
3110 def test_pydoc(self):
3111 # indirectly test __objclass__
Ethan Furman3323da92015-04-11 09:39:59 -07003112 if StrEnum.__doc__ is None:
3113 expected_text = expected_help_output_without_docs % __name__
3114 else:
3115 expected_text = expected_help_output_with_docs % __name__
Ethan Furman5875d742013-10-21 20:45:55 -07003116 output = StringIO()
3117 helper = pydoc.Helper(output=output)
3118 helper(self.Color)
3119 result = output.getvalue().strip()
Victor Stinner4b0432d2014-06-16 22:48:43 +02003120 self.assertEqual(result, expected_text)
Ethan Furman5875d742013-10-21 20:45:55 -07003121
3122 def test_inspect_getmembers(self):
3123 values = dict((
3124 ('__class__', EnumMeta),
Ethan Furman48a724f2015-04-11 23:23:06 -07003125 ('__doc__', 'An enumeration.'),
Ethan Furman5875d742013-10-21 20:45:55 -07003126 ('__members__', self.Color.__members__),
3127 ('__module__', __name__),
3128 ('blue', self.Color.blue),
3129 ('green', self.Color.green),
3130 ('name', Enum.__dict__['name']),
3131 ('red', self.Color.red),
3132 ('value', Enum.__dict__['value']),
3133 ))
3134 result = dict(inspect.getmembers(self.Color))
3135 self.assertEqual(values.keys(), result.keys())
3136 failed = False
3137 for k in values.keys():
3138 if result[k] != values[k]:
3139 print()
3140 print('\n%s\n key: %s\n result: %s\nexpected: %s\n%s\n' %
3141 ('=' * 75, k, result[k], values[k], '=' * 75), sep='')
3142 failed = True
3143 if failed:
3144 self.fail("result does not equal expected, see print above")
3145
3146 def test_inspect_classify_class_attrs(self):
3147 # indirectly test __objclass__
3148 from inspect import Attribute
3149 values = [
3150 Attribute(name='__class__', kind='data',
3151 defining_class=object, object=EnumMeta),
3152 Attribute(name='__doc__', kind='data',
Ethan Furman48a724f2015-04-11 23:23:06 -07003153 defining_class=self.Color, object='An enumeration.'),
Ethan Furman5875d742013-10-21 20:45:55 -07003154 Attribute(name='__members__', kind='property',
3155 defining_class=EnumMeta, object=EnumMeta.__members__),
3156 Attribute(name='__module__', kind='data',
3157 defining_class=self.Color, object=__name__),
3158 Attribute(name='blue', kind='data',
3159 defining_class=self.Color, object=self.Color.blue),
3160 Attribute(name='green', kind='data',
3161 defining_class=self.Color, object=self.Color.green),
3162 Attribute(name='red', kind='data',
3163 defining_class=self.Color, object=self.Color.red),
3164 Attribute(name='name', kind='data',
3165 defining_class=Enum, object=Enum.__dict__['name']),
3166 Attribute(name='value', kind='data',
3167 defining_class=Enum, object=Enum.__dict__['value']),
3168 ]
3169 values.sort(key=lambda item: item.name)
3170 result = list(inspect.classify_class_attrs(self.Color))
3171 result.sort(key=lambda item: item.name)
3172 failed = False
3173 for v, r in zip(values, result):
3174 if r != v:
3175 print('\n%s\n%s\n%s\n%s\n' % ('=' * 75, r, v, '=' * 75), sep='')
3176 failed = True
3177 if failed:
3178 self.fail("result does not equal expected, see print above")
3179
Martin Panter19e69c52015-11-14 12:46:42 +00003180
3181class MiscTestCase(unittest.TestCase):
3182 def test__all__(self):
3183 support.check__all__(self, enum)
3184
3185
Gregory P. Smith ext:(%20%5BGoogle%20Inc.%5D)6f20bd62016-06-03 19:14:52 +00003186# These are unordered here on purpose to ensure that declaration order
3187# makes no difference.
3188CONVERT_TEST_NAME_D = 5
3189CONVERT_TEST_NAME_C = 5
3190CONVERT_TEST_NAME_B = 5
3191CONVERT_TEST_NAME_A = 5 # This one should sort first.
3192CONVERT_TEST_NAME_E = 5
3193CONVERT_TEST_NAME_F = 5
3194
3195class TestIntEnumConvert(unittest.TestCase):
3196 def test_convert_value_lookup_priority(self):
orlnub1230fb9fad2018-09-12 20:28:53 +03003197 test_type = enum.IntEnum._convert_(
Ethan Furman28cf6632017-01-24 12:12:06 -08003198 'UnittestConvert',
3199 ('test.test_enum', '__main__')[__name__=='__main__'],
Gregory P. Smith ext:(%20%5BGoogle%20Inc.%5D)6f20bd62016-06-03 19:14:52 +00003200 filter=lambda x: x.startswith('CONVERT_TEST_'))
3201 # We don't want the reverse lookup value to vary when there are
3202 # multiple possible names for a given value. It should always
3203 # report the first lexigraphical name in that case.
3204 self.assertEqual(test_type(5).name, 'CONVERT_TEST_NAME_A')
3205
3206 def test_convert(self):
orlnub1230fb9fad2018-09-12 20:28:53 +03003207 test_type = enum.IntEnum._convert_(
Ethan Furman28cf6632017-01-24 12:12:06 -08003208 'UnittestConvert',
3209 ('test.test_enum', '__main__')[__name__=='__main__'],
Gregory P. Smith ext:(%20%5BGoogle%20Inc.%5D)6f20bd62016-06-03 19:14:52 +00003210 filter=lambda x: x.startswith('CONVERT_TEST_'))
3211 # Ensure that test_type has all of the desired names and values.
3212 self.assertEqual(test_type.CONVERT_TEST_NAME_F,
3213 test_type.CONVERT_TEST_NAME_A)
3214 self.assertEqual(test_type.CONVERT_TEST_NAME_B, 5)
3215 self.assertEqual(test_type.CONVERT_TEST_NAME_C, 5)
3216 self.assertEqual(test_type.CONVERT_TEST_NAME_D, 5)
3217 self.assertEqual(test_type.CONVERT_TEST_NAME_E, 5)
3218 # Ensure that test_type only picked up names matching the filter.
3219 self.assertEqual([name for name in dir(test_type)
3220 if name[0:2] not in ('CO', '__')],
3221 [], msg='Names other than CONVERT_TEST_* found.')
3222
orlnub1230fb9fad2018-09-12 20:28:53 +03003223 @unittest.skipUnless(sys.version_info[:2] == (3, 8),
3224 '_convert was deprecated in 3.8')
3225 def test_convert_warn(self):
3226 with self.assertWarns(DeprecationWarning):
3227 enum.IntEnum._convert(
3228 'UnittestConvert',
3229 ('test.test_enum', '__main__')[__name__=='__main__'],
3230 filter=lambda x: x.startswith('CONVERT_TEST_'))
3231
3232 @unittest.skipUnless(sys.version_info >= (3, 9),
3233 '_convert was removed in 3.9')
3234 def test_convert_raise(self):
3235 with self.assertRaises(AttributeError):
3236 enum.IntEnum._convert(
3237 'UnittestConvert',
3238 ('test.test_enum', '__main__')[__name__=='__main__'],
3239 filter=lambda x: x.startswith('CONVERT_TEST_'))
3240
Gregory P. Smith ext:(%20%5BGoogle%20Inc.%5D)6f20bd62016-06-03 19:14:52 +00003241
Ethan Furman6b3d64a2013-06-14 16:55:46 -07003242if __name__ == '__main__':
3243 unittest.main()