blob: 8e84d929429ebf0bb6ecfe0abe1953f344d84fe3 [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'
2039 with self.assertRaisesRegex(TypeError, '1 is not a string'):
2040 class FirstFailedStrEnum(StrEnum):
2041 one = 1
2042 two = '2'
2043 with self.assertRaisesRegex(TypeError, "2 is not a string"):
2044 class SecondFailedStrEnum(StrEnum):
2045 one = '1'
2046 two = 2,
2047 three = '3'
2048 with self.assertRaisesRegex(TypeError, '2 is not a string'):
2049 class ThirdFailedStrEnum(StrEnum):
2050 one = '1'
2051 two = 2
2052 with self.assertRaisesRegex(TypeError, 'encoding must be a string, not %r' % (sys.getdefaultencoding, )):
2053 class ThirdFailedStrEnum(StrEnum):
2054 one = '1'
2055 two = b'2', sys.getdefaultencoding
2056 with self.assertRaisesRegex(TypeError, 'errors must be a string, not 9'):
2057 class ThirdFailedStrEnum(StrEnum):
2058 one = '1'
2059 two = b'2', 'ascii', 9
Ethan Furman6b3d64a2013-06-14 16:55:46 -07002060
Ethan Furmane8e61272016-08-20 07:19:31 -07002061class TestOrder(unittest.TestCase):
2062
2063 def test_same_members(self):
2064 class Color(Enum):
2065 _order_ = 'red green blue'
2066 red = 1
2067 green = 2
2068 blue = 3
2069
2070 def test_same_members_with_aliases(self):
2071 class Color(Enum):
2072 _order_ = 'red green blue'
2073 red = 1
2074 green = 2
2075 blue = 3
2076 verde = green
2077
2078 def test_same_members_wrong_order(self):
2079 with self.assertRaisesRegex(TypeError, 'member order does not match _order_'):
2080 class Color(Enum):
2081 _order_ = 'red green blue'
2082 red = 1
2083 blue = 3
2084 green = 2
2085
2086 def test_order_has_extra_members(self):
2087 with self.assertRaisesRegex(TypeError, 'member order does not match _order_'):
2088 class Color(Enum):
2089 _order_ = 'red green blue purple'
2090 red = 1
2091 green = 2
2092 blue = 3
2093
2094 def test_order_has_extra_members_with_aliases(self):
2095 with self.assertRaisesRegex(TypeError, 'member order does not match _order_'):
2096 class Color(Enum):
2097 _order_ = 'red green blue purple'
2098 red = 1
2099 green = 2
2100 blue = 3
2101 verde = green
2102
2103 def test_enum_has_extra_members(self):
2104 with self.assertRaisesRegex(TypeError, 'member order does not match _order_'):
2105 class Color(Enum):
2106 _order_ = 'red green blue'
2107 red = 1
2108 green = 2
2109 blue = 3
2110 purple = 4
2111
2112 def test_enum_has_extra_members_with_aliases(self):
2113 with self.assertRaisesRegex(TypeError, 'member order does not match _order_'):
2114 class Color(Enum):
2115 _order_ = 'red green blue'
2116 red = 1
2117 green = 2
2118 blue = 3
2119 purple = 4
2120 verde = green
2121
2122
Ethan Furman65a5a472016-09-01 23:55:19 -07002123class TestFlag(unittest.TestCase):
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002124 """Tests of the Flags."""
2125
Ethan Furman65a5a472016-09-01 23:55:19 -07002126 class Perm(Flag):
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002127 R, W, X = 4, 2, 1
2128
Ethan Furman65a5a472016-09-01 23:55:19 -07002129 class Open(Flag):
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002130 RO = 0
2131 WO = 1
2132 RW = 2
2133 AC = 3
2134 CE = 1<<19
2135
Rahul Jha94306522018-09-10 23:51:04 +05302136 class Color(Flag):
2137 BLACK = 0
2138 RED = 1
2139 GREEN = 2
2140 BLUE = 4
2141 PURPLE = RED|BLUE
2142
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002143 def test_str(self):
2144 Perm = self.Perm
2145 self.assertEqual(str(Perm.R), 'Perm.R')
2146 self.assertEqual(str(Perm.W), 'Perm.W')
2147 self.assertEqual(str(Perm.X), 'Perm.X')
2148 self.assertEqual(str(Perm.R | Perm.W), 'Perm.R|W')
2149 self.assertEqual(str(Perm.R | Perm.W | Perm.X), 'Perm.R|W|X')
2150 self.assertEqual(str(Perm(0)), 'Perm.0')
2151 self.assertEqual(str(~Perm.R), 'Perm.W|X')
2152 self.assertEqual(str(~Perm.W), 'Perm.R|X')
2153 self.assertEqual(str(~Perm.X), 'Perm.R|W')
2154 self.assertEqual(str(~(Perm.R | Perm.W)), 'Perm.X')
2155 self.assertEqual(str(~(Perm.R | Perm.W | Perm.X)), 'Perm.0')
2156 self.assertEqual(str(Perm(~0)), 'Perm.R|W|X')
2157
2158 Open = self.Open
2159 self.assertEqual(str(Open.RO), 'Open.RO')
2160 self.assertEqual(str(Open.WO), 'Open.WO')
2161 self.assertEqual(str(Open.AC), 'Open.AC')
2162 self.assertEqual(str(Open.RO | Open.CE), 'Open.CE')
2163 self.assertEqual(str(Open.WO | Open.CE), 'Open.CE|WO')
Ethan Furman3515dcc2016-09-18 13:15:41 -07002164 self.assertEqual(str(~Open.RO), 'Open.CE|AC|RW|WO')
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002165 self.assertEqual(str(~Open.WO), 'Open.CE|RW')
2166 self.assertEqual(str(~Open.AC), 'Open.CE')
2167 self.assertEqual(str(~(Open.RO | Open.CE)), 'Open.AC')
2168 self.assertEqual(str(~(Open.WO | Open.CE)), 'Open.RW')
2169
2170 def test_repr(self):
2171 Perm = self.Perm
2172 self.assertEqual(repr(Perm.R), '<Perm.R: 4>')
2173 self.assertEqual(repr(Perm.W), '<Perm.W: 2>')
2174 self.assertEqual(repr(Perm.X), '<Perm.X: 1>')
2175 self.assertEqual(repr(Perm.R | Perm.W), '<Perm.R|W: 6>')
2176 self.assertEqual(repr(Perm.R | Perm.W | Perm.X), '<Perm.R|W|X: 7>')
Ethan Furman27682d22016-09-04 11:39:01 -07002177 self.assertEqual(repr(Perm(0)), '<Perm.0: 0>')
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002178 self.assertEqual(repr(~Perm.R), '<Perm.W|X: 3>')
2179 self.assertEqual(repr(~Perm.W), '<Perm.R|X: 5>')
2180 self.assertEqual(repr(~Perm.X), '<Perm.R|W: 6>')
2181 self.assertEqual(repr(~(Perm.R | Perm.W)), '<Perm.X: 1>')
Ethan Furman27682d22016-09-04 11:39:01 -07002182 self.assertEqual(repr(~(Perm.R | Perm.W | Perm.X)), '<Perm.0: 0>')
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002183 self.assertEqual(repr(Perm(~0)), '<Perm.R|W|X: 7>')
2184
2185 Open = self.Open
2186 self.assertEqual(repr(Open.RO), '<Open.RO: 0>')
2187 self.assertEqual(repr(Open.WO), '<Open.WO: 1>')
2188 self.assertEqual(repr(Open.AC), '<Open.AC: 3>')
2189 self.assertEqual(repr(Open.RO | Open.CE), '<Open.CE: 524288>')
2190 self.assertEqual(repr(Open.WO | Open.CE), '<Open.CE|WO: 524289>')
Ethan Furman3515dcc2016-09-18 13:15:41 -07002191 self.assertEqual(repr(~Open.RO), '<Open.CE|AC|RW|WO: 524291>')
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002192 self.assertEqual(repr(~Open.WO), '<Open.CE|RW: 524290>')
2193 self.assertEqual(repr(~Open.AC), '<Open.CE: 524288>')
2194 self.assertEqual(repr(~(Open.RO | Open.CE)), '<Open.AC: 3>')
2195 self.assertEqual(repr(~(Open.WO | Open.CE)), '<Open.RW: 2>')
2196
2197 def test_or(self):
2198 Perm = self.Perm
2199 for i in Perm:
2200 for j in Perm:
2201 self.assertEqual((i | j), Perm(i.value | j.value))
2202 self.assertEqual((i | j).value, i.value | j.value)
2203 self.assertIs(type(i | j), Perm)
2204 for i in Perm:
2205 self.assertIs(i | i, i)
2206 Open = self.Open
2207 self.assertIs(Open.RO | Open.CE, Open.CE)
2208
2209 def test_and(self):
2210 Perm = self.Perm
2211 RW = Perm.R | Perm.W
2212 RX = Perm.R | Perm.X
2213 WX = Perm.W | Perm.X
2214 RWX = Perm.R | Perm.W | Perm.X
2215 values = list(Perm) + [RW, RX, WX, RWX, Perm(0)]
2216 for i in values:
2217 for j in values:
2218 self.assertEqual((i & j).value, i.value & j.value)
2219 self.assertIs(type(i & j), Perm)
2220 for i in Perm:
2221 self.assertIs(i & i, i)
2222 self.assertIs(i & RWX, i)
2223 self.assertIs(RWX & i, i)
2224 Open = self.Open
2225 self.assertIs(Open.RO & Open.CE, Open.RO)
2226
2227 def test_xor(self):
2228 Perm = self.Perm
2229 for i in Perm:
2230 for j in Perm:
2231 self.assertEqual((i ^ j).value, i.value ^ j.value)
2232 self.assertIs(type(i ^ j), Perm)
2233 for i in Perm:
2234 self.assertIs(i ^ Perm(0), i)
2235 self.assertIs(Perm(0) ^ i, i)
2236 Open = self.Open
2237 self.assertIs(Open.RO ^ Open.CE, Open.CE)
2238 self.assertIs(Open.CE ^ Open.CE, Open.RO)
2239
2240 def test_invert(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 self.assertIs(type(~i), Perm)
2249 self.assertEqual(~~i, i)
2250 for i in Perm:
2251 self.assertIs(~~i, i)
2252 Open = self.Open
2253 self.assertIs(Open.WO & ~Open.WO, Open.RO)
2254 self.assertIs((Open.WO|Open.CE) & ~Open.WO, Open.CE)
2255
Ethan Furman25d94bb2016-09-02 16:32:32 -07002256 def test_bool(self):
2257 Perm = self.Perm
2258 for f in Perm:
2259 self.assertTrue(f)
2260 Open = self.Open
2261 for f in Open:
2262 self.assertEqual(bool(f.value), bool(f))
2263
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002264 def test_programatic_function_string(self):
Ethan Furman65a5a472016-09-01 23:55:19 -07002265 Perm = Flag('Perm', 'R W X')
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002266 lst = list(Perm)
2267 self.assertEqual(len(lst), len(Perm))
2268 self.assertEqual(len(Perm), 3, Perm)
2269 self.assertEqual(lst, [Perm.R, Perm.W, Perm.X])
2270 for i, n in enumerate('R W X'.split()):
2271 v = 1<<i
2272 e = Perm(v)
2273 self.assertEqual(e.value, v)
2274 self.assertEqual(type(e.value), int)
2275 self.assertEqual(e.name, n)
2276 self.assertIn(e, Perm)
2277 self.assertIs(type(e), Perm)
2278
2279 def test_programatic_function_string_with_start(self):
Ethan Furman65a5a472016-09-01 23:55:19 -07002280 Perm = Flag('Perm', 'R W X', start=8)
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002281 lst = list(Perm)
2282 self.assertEqual(len(lst), len(Perm))
2283 self.assertEqual(len(Perm), 3, Perm)
2284 self.assertEqual(lst, [Perm.R, Perm.W, Perm.X])
2285 for i, n in enumerate('R W X'.split()):
2286 v = 8<<i
2287 e = Perm(v)
2288 self.assertEqual(e.value, v)
2289 self.assertEqual(type(e.value), int)
2290 self.assertEqual(e.name, n)
2291 self.assertIn(e, Perm)
2292 self.assertIs(type(e), Perm)
2293
2294 def test_programatic_function_string_list(self):
Ethan Furman65a5a472016-09-01 23:55:19 -07002295 Perm = Flag('Perm', ['R', 'W', 'X'])
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002296 lst = list(Perm)
2297 self.assertEqual(len(lst), len(Perm))
2298 self.assertEqual(len(Perm), 3, Perm)
2299 self.assertEqual(lst, [Perm.R, Perm.W, Perm.X])
2300 for i, n in enumerate('R W X'.split()):
2301 v = 1<<i
2302 e = Perm(v)
2303 self.assertEqual(e.value, v)
2304 self.assertEqual(type(e.value), int)
2305 self.assertEqual(e.name, n)
2306 self.assertIn(e, Perm)
2307 self.assertIs(type(e), Perm)
2308
2309 def test_programatic_function_iterable(self):
Ethan Furman65a5a472016-09-01 23:55:19 -07002310 Perm = Flag('Perm', (('R', 2), ('W', 8), ('X', 32)))
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002311 lst = list(Perm)
2312 self.assertEqual(len(lst), len(Perm))
2313 self.assertEqual(len(Perm), 3, Perm)
2314 self.assertEqual(lst, [Perm.R, Perm.W, Perm.X])
2315 for i, n in enumerate('R W X'.split()):
2316 v = 1<<(2*i+1)
2317 e = Perm(v)
2318 self.assertEqual(e.value, v)
2319 self.assertEqual(type(e.value), int)
2320 self.assertEqual(e.name, n)
2321 self.assertIn(e, Perm)
2322 self.assertIs(type(e), Perm)
2323
2324 def test_programatic_function_from_dict(self):
Ethan Furman65a5a472016-09-01 23:55:19 -07002325 Perm = Flag('Perm', OrderedDict((('R', 2), ('W', 8), ('X', 32))))
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002326 lst = list(Perm)
2327 self.assertEqual(len(lst), len(Perm))
2328 self.assertEqual(len(Perm), 3, Perm)
2329 self.assertEqual(lst, [Perm.R, Perm.W, Perm.X])
2330 for i, n in enumerate('R W X'.split()):
2331 v = 1<<(2*i+1)
2332 e = Perm(v)
2333 self.assertEqual(e.value, v)
2334 self.assertEqual(type(e.value), int)
2335 self.assertEqual(e.name, n)
2336 self.assertIn(e, Perm)
2337 self.assertIs(type(e), Perm)
2338
Ethan Furman65a5a472016-09-01 23:55:19 -07002339 def test_pickle(self):
2340 if isinstance(FlagStooges, Exception):
2341 raise FlagStooges
2342 test_pickle_dump_load(self.assertIs, FlagStooges.CURLY|FlagStooges.MOE)
2343 test_pickle_dump_load(self.assertIs, FlagStooges)
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002344
Rahul Jha94306522018-09-10 23:51:04 +05302345 def test_contains(self):
2346 Open = self.Open
2347 Color = self.Color
2348 self.assertFalse(Color.BLACK in Open)
2349 self.assertFalse(Open.RO in Color)
2350 with self.assertRaises(TypeError):
2351 'BLACK' in Color
2352 with self.assertRaises(TypeError):
2353 'RO' in Open
2354 with self.assertRaises(TypeError):
2355 1 in Color
2356 with self.assertRaises(TypeError):
2357 1 in Open
2358
2359 def test_member_contains(self):
Ethan Furman65a5a472016-09-01 23:55:19 -07002360 Perm = self.Perm
2361 R, W, X = Perm
2362 RW = R | W
2363 RX = R | X
2364 WX = W | X
2365 RWX = R | W | X
2366 self.assertTrue(R in RW)
2367 self.assertTrue(R in RX)
2368 self.assertTrue(R in RWX)
2369 self.assertTrue(W in RW)
2370 self.assertTrue(W in WX)
2371 self.assertTrue(W in RWX)
2372 self.assertTrue(X in RX)
2373 self.assertTrue(X in WX)
2374 self.assertTrue(X in RWX)
2375 self.assertFalse(R in WX)
2376 self.assertFalse(W in RX)
2377 self.assertFalse(X in RW)
2378
Ethan Furman7219e272020-09-16 13:01:00 -07002379 def test_member_iter(self):
2380 Color = self.Color
2381 self.assertEqual(list(Color.PURPLE), [Color.BLUE, Color.RED])
2382 self.assertEqual(list(Color.BLUE), [Color.BLUE])
2383 self.assertEqual(list(Color.GREEN), [Color.GREEN])
2384
Ethan Furmanc16595e2016-09-10 23:36:59 -07002385 def test_auto_number(self):
2386 class Color(Flag):
2387 red = auto()
2388 blue = auto()
2389 green = auto()
2390
2391 self.assertEqual(list(Color), [Color.red, Color.blue, Color.green])
2392 self.assertEqual(Color.red.value, 1)
2393 self.assertEqual(Color.blue.value, 2)
2394 self.assertEqual(Color.green.value, 4)
2395
2396 def test_auto_number_garbage(self):
2397 with self.assertRaisesRegex(TypeError, 'Invalid Flag value: .not an int.'):
2398 class Color(Flag):
2399 red = 'not an int'
2400 blue = auto()
2401
Ethan Furman3515dcc2016-09-18 13:15:41 -07002402 def test_cascading_failure(self):
2403 class Bizarre(Flag):
2404 c = 3
2405 d = 4
2406 f = 6
2407 # Bizarre.c | Bizarre.d
Walter Dörwald323842c2019-07-18 20:37:13 +02002408 name = "TestFlag.test_cascading_failure.<locals>.Bizarre"
2409 self.assertRaisesRegex(ValueError, "5 is not a valid " + name, Bizarre, 5)
2410 self.assertRaisesRegex(ValueError, "5 is not a valid " + name, Bizarre, 5)
2411 self.assertRaisesRegex(ValueError, "2 is not a valid " + name, Bizarre, 2)
2412 self.assertRaisesRegex(ValueError, "2 is not a valid " + name, Bizarre, 2)
2413 self.assertRaisesRegex(ValueError, "1 is not a valid " + name, Bizarre, 1)
2414 self.assertRaisesRegex(ValueError, "1 is not a valid " + name, Bizarre, 1)
Ethan Furman3515dcc2016-09-18 13:15:41 -07002415
2416 def test_duplicate_auto(self):
2417 class Dupes(Enum):
2418 first = primero = auto()
2419 second = auto()
2420 third = auto()
2421 self.assertEqual([Dupes.first, Dupes.second, Dupes.third], list(Dupes))
2422
2423 def test_bizarre(self):
2424 class Bizarre(Flag):
2425 b = 3
2426 c = 4
2427 d = 6
2428 self.assertEqual(repr(Bizarre(7)), '<Bizarre.d|c|b: 7>')
2429
Ethan Furman5bdab642018-09-21 19:03:09 -07002430 def test_multiple_mixin(self):
2431 class AllMixin:
2432 @classproperty
2433 def ALL(cls):
2434 members = list(cls)
2435 all_value = None
2436 if members:
2437 all_value = members[0]
2438 for member in members[1:]:
2439 all_value |= member
2440 cls.ALL = all_value
2441 return all_value
2442 class StrMixin:
2443 def __str__(self):
2444 return self._name_.lower()
2445 class Color(AllMixin, Flag):
2446 RED = auto()
2447 GREEN = auto()
2448 BLUE = auto()
2449 self.assertEqual(Color.RED.value, 1)
2450 self.assertEqual(Color.GREEN.value, 2)
2451 self.assertEqual(Color.BLUE.value, 4)
2452 self.assertEqual(Color.ALL.value, 7)
2453 self.assertEqual(str(Color.BLUE), 'Color.BLUE')
2454 class Color(AllMixin, StrMixin, Flag):
2455 RED = auto()
2456 GREEN = auto()
2457 BLUE = auto()
2458 self.assertEqual(Color.RED.value, 1)
2459 self.assertEqual(Color.GREEN.value, 2)
2460 self.assertEqual(Color.BLUE.value, 4)
2461 self.assertEqual(Color.ALL.value, 7)
2462 self.assertEqual(str(Color.BLUE), 'blue')
2463 class Color(StrMixin, AllMixin, Flag):
2464 RED = auto()
2465 GREEN = auto()
2466 BLUE = auto()
2467 self.assertEqual(Color.RED.value, 1)
2468 self.assertEqual(Color.GREEN.value, 2)
2469 self.assertEqual(Color.BLUE.value, 4)
2470 self.assertEqual(Color.ALL.value, 7)
2471 self.assertEqual(str(Color.BLUE), 'blue')
2472
Hai Shie80697d2020-05-28 06:10:27 +08002473 @threading_helper.reap_threads
Ethan Furman28cf6632017-01-24 12:12:06 -08002474 def test_unique_composite(self):
2475 # override __eq__ to be identity only
2476 class TestFlag(Flag):
2477 one = auto()
2478 two = auto()
2479 three = auto()
2480 four = auto()
2481 five = auto()
2482 six = auto()
2483 seven = auto()
2484 eight = auto()
2485 def __eq__(self, other):
2486 return self is other
2487 def __hash__(self):
2488 return hash(self._value_)
2489 # have multiple threads competing to complete the composite members
2490 seen = set()
2491 failed = False
2492 def cycle_enum():
2493 nonlocal failed
2494 try:
2495 for i in range(256):
2496 seen.add(TestFlag(i))
2497 except Exception:
2498 failed = True
2499 threads = [
2500 threading.Thread(target=cycle_enum)
2501 for _ in range(8)
2502 ]
Hai Shie80697d2020-05-28 06:10:27 +08002503 with threading_helper.start_threads(threads):
Ethan Furman28cf6632017-01-24 12:12:06 -08002504 pass
2505 # check that only 248 members were created
2506 self.assertFalse(
2507 failed,
2508 'at least one thread failed while creating composite members')
2509 self.assertEqual(256, len(seen), 'too many composite members created')
2510
Ethan Furmanc16595e2016-09-10 23:36:59 -07002511
Ethan Furman65a5a472016-09-01 23:55:19 -07002512class TestIntFlag(unittest.TestCase):
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002513 """Tests of the IntFlags."""
2514
Ethan Furman65a5a472016-09-01 23:55:19 -07002515 class Perm(IntFlag):
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002516 X = 1 << 0
2517 W = 1 << 1
2518 R = 1 << 2
2519
Ethan Furman65a5a472016-09-01 23:55:19 -07002520 class Open(IntFlag):
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002521 RO = 0
2522 WO = 1
2523 RW = 2
2524 AC = 3
2525 CE = 1<<19
2526
Rahul Jha94306522018-09-10 23:51:04 +05302527 class Color(IntFlag):
2528 BLACK = 0
2529 RED = 1
2530 GREEN = 2
2531 BLUE = 4
2532 PURPLE = RED|BLUE
2533
Ethan Furman3515dcc2016-09-18 13:15:41 -07002534 def test_type(self):
2535 Perm = self.Perm
2536 Open = self.Open
2537 for f in Perm:
2538 self.assertTrue(isinstance(f, Perm))
2539 self.assertEqual(f, f.value)
2540 self.assertTrue(isinstance(Perm.W | Perm.X, Perm))
2541 self.assertEqual(Perm.W | Perm.X, 3)
2542 for f in Open:
2543 self.assertTrue(isinstance(f, Open))
2544 self.assertEqual(f, f.value)
2545 self.assertTrue(isinstance(Open.WO | Open.RW, Open))
2546 self.assertEqual(Open.WO | Open.RW, 3)
2547
2548
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002549 def test_str(self):
2550 Perm = self.Perm
2551 self.assertEqual(str(Perm.R), 'Perm.R')
2552 self.assertEqual(str(Perm.W), 'Perm.W')
2553 self.assertEqual(str(Perm.X), 'Perm.X')
2554 self.assertEqual(str(Perm.R | Perm.W), 'Perm.R|W')
2555 self.assertEqual(str(Perm.R | Perm.W | Perm.X), 'Perm.R|W|X')
2556 self.assertEqual(str(Perm.R | 8), 'Perm.8|R')
2557 self.assertEqual(str(Perm(0)), 'Perm.0')
2558 self.assertEqual(str(Perm(8)), 'Perm.8')
Ethan Furman3515dcc2016-09-18 13:15:41 -07002559 self.assertEqual(str(~Perm.R), 'Perm.W|X')
2560 self.assertEqual(str(~Perm.W), 'Perm.R|X')
2561 self.assertEqual(str(~Perm.X), 'Perm.R|W')
2562 self.assertEqual(str(~(Perm.R | Perm.W)), 'Perm.X')
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002563 self.assertEqual(str(~(Perm.R | Perm.W | Perm.X)), 'Perm.-8')
Ethan Furman3515dcc2016-09-18 13:15:41 -07002564 self.assertEqual(str(~(Perm.R | 8)), 'Perm.W|X')
2565 self.assertEqual(str(Perm(~0)), 'Perm.R|W|X')
2566 self.assertEqual(str(Perm(~8)), 'Perm.R|W|X')
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002567
2568 Open = self.Open
2569 self.assertEqual(str(Open.RO), 'Open.RO')
2570 self.assertEqual(str(Open.WO), 'Open.WO')
2571 self.assertEqual(str(Open.AC), 'Open.AC')
2572 self.assertEqual(str(Open.RO | Open.CE), 'Open.CE')
2573 self.assertEqual(str(Open.WO | Open.CE), 'Open.CE|WO')
2574 self.assertEqual(str(Open(4)), 'Open.4')
Ethan Furman3515dcc2016-09-18 13:15:41 -07002575 self.assertEqual(str(~Open.RO), 'Open.CE|AC|RW|WO')
2576 self.assertEqual(str(~Open.WO), 'Open.CE|RW')
2577 self.assertEqual(str(~Open.AC), 'Open.CE')
2578 self.assertEqual(str(~(Open.RO | Open.CE)), 'Open.AC|RW|WO')
2579 self.assertEqual(str(~(Open.WO | Open.CE)), 'Open.RW')
2580 self.assertEqual(str(Open(~4)), 'Open.CE|AC|RW|WO')
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002581
2582 def test_repr(self):
2583 Perm = self.Perm
2584 self.assertEqual(repr(Perm.R), '<Perm.R: 4>')
2585 self.assertEqual(repr(Perm.W), '<Perm.W: 2>')
2586 self.assertEqual(repr(Perm.X), '<Perm.X: 1>')
2587 self.assertEqual(repr(Perm.R | Perm.W), '<Perm.R|W: 6>')
2588 self.assertEqual(repr(Perm.R | Perm.W | Perm.X), '<Perm.R|W|X: 7>')
2589 self.assertEqual(repr(Perm.R | 8), '<Perm.8|R: 12>')
Ethan Furman27682d22016-09-04 11:39:01 -07002590 self.assertEqual(repr(Perm(0)), '<Perm.0: 0>')
2591 self.assertEqual(repr(Perm(8)), '<Perm.8: 8>')
Ethan Furman3515dcc2016-09-18 13:15:41 -07002592 self.assertEqual(repr(~Perm.R), '<Perm.W|X: -5>')
2593 self.assertEqual(repr(~Perm.W), '<Perm.R|X: -3>')
2594 self.assertEqual(repr(~Perm.X), '<Perm.R|W: -2>')
2595 self.assertEqual(repr(~(Perm.R | Perm.W)), '<Perm.X: -7>')
Ethan Furman27682d22016-09-04 11:39:01 -07002596 self.assertEqual(repr(~(Perm.R | Perm.W | Perm.X)), '<Perm.-8: -8>')
Ethan Furman3515dcc2016-09-18 13:15:41 -07002597 self.assertEqual(repr(~(Perm.R | 8)), '<Perm.W|X: -13>')
2598 self.assertEqual(repr(Perm(~0)), '<Perm.R|W|X: -1>')
2599 self.assertEqual(repr(Perm(~8)), '<Perm.R|W|X: -9>')
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002600
2601 Open = self.Open
2602 self.assertEqual(repr(Open.RO), '<Open.RO: 0>')
2603 self.assertEqual(repr(Open.WO), '<Open.WO: 1>')
2604 self.assertEqual(repr(Open.AC), '<Open.AC: 3>')
2605 self.assertEqual(repr(Open.RO | Open.CE), '<Open.CE: 524288>')
2606 self.assertEqual(repr(Open.WO | Open.CE), '<Open.CE|WO: 524289>')
Ethan Furman27682d22016-09-04 11:39:01 -07002607 self.assertEqual(repr(Open(4)), '<Open.4: 4>')
Ethan Furman3515dcc2016-09-18 13:15:41 -07002608 self.assertEqual(repr(~Open.RO), '<Open.CE|AC|RW|WO: -1>')
2609 self.assertEqual(repr(~Open.WO), '<Open.CE|RW: -2>')
2610 self.assertEqual(repr(~Open.AC), '<Open.CE: -4>')
2611 self.assertEqual(repr(~(Open.RO | Open.CE)), '<Open.AC|RW|WO: -524289>')
2612 self.assertEqual(repr(~(Open.WO | Open.CE)), '<Open.RW: -524290>')
2613 self.assertEqual(repr(Open(~4)), '<Open.CE|AC|RW|WO: -5>')
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002614
2615 def test_or(self):
2616 Perm = self.Perm
2617 for i in Perm:
2618 for j in Perm:
2619 self.assertEqual(i | j, i.value | j.value)
2620 self.assertEqual((i | j).value, i.value | j.value)
2621 self.assertIs(type(i | j), Perm)
2622 for j in range(8):
2623 self.assertEqual(i | j, i.value | j)
2624 self.assertEqual((i | j).value, i.value | j)
2625 self.assertIs(type(i | j), Perm)
2626 self.assertEqual(j | i, j | i.value)
2627 self.assertEqual((j | i).value, j | i.value)
2628 self.assertIs(type(j | i), Perm)
2629 for i in Perm:
2630 self.assertIs(i | i, i)
2631 self.assertIs(i | 0, i)
2632 self.assertIs(0 | i, i)
2633 Open = self.Open
2634 self.assertIs(Open.RO | Open.CE, Open.CE)
2635
2636 def test_and(self):
2637 Perm = self.Perm
2638 RW = Perm.R | Perm.W
2639 RX = Perm.R | Perm.X
2640 WX = Perm.W | Perm.X
2641 RWX = Perm.R | Perm.W | Perm.X
2642 values = list(Perm) + [RW, RX, WX, RWX, Perm(0)]
2643 for i in values:
2644 for j in values:
2645 self.assertEqual(i & j, i.value & j.value, 'i is %r, j is %r' % (i, j))
2646 self.assertEqual((i & j).value, i.value & j.value, 'i is %r, j is %r' % (i, j))
2647 self.assertIs(type(i & j), Perm, 'i is %r, j is %r' % (i, j))
2648 for j in range(8):
2649 self.assertEqual(i & j, i.value & j)
2650 self.assertEqual((i & j).value, i.value & j)
2651 self.assertIs(type(i & j), Perm)
2652 self.assertEqual(j & i, j & i.value)
2653 self.assertEqual((j & i).value, j & i.value)
2654 self.assertIs(type(j & i), Perm)
2655 for i in Perm:
2656 self.assertIs(i & i, i)
2657 self.assertIs(i & 7, i)
2658 self.assertIs(7 & i, i)
2659 Open = self.Open
2660 self.assertIs(Open.RO & Open.CE, Open.RO)
2661
2662 def test_xor(self):
2663 Perm = self.Perm
2664 for i in Perm:
2665 for j in Perm:
2666 self.assertEqual(i ^ j, i.value ^ j.value)
2667 self.assertEqual((i ^ j).value, i.value ^ j.value)
2668 self.assertIs(type(i ^ j), Perm)
2669 for j in range(8):
2670 self.assertEqual(i ^ j, i.value ^ j)
2671 self.assertEqual((i ^ j).value, i.value ^ j)
2672 self.assertIs(type(i ^ j), Perm)
2673 self.assertEqual(j ^ i, j ^ i.value)
2674 self.assertEqual((j ^ i).value, j ^ i.value)
2675 self.assertIs(type(j ^ i), Perm)
2676 for i in Perm:
2677 self.assertIs(i ^ 0, i)
2678 self.assertIs(0 ^ i, i)
2679 Open = self.Open
2680 self.assertIs(Open.RO ^ Open.CE, Open.CE)
2681 self.assertIs(Open.CE ^ Open.CE, Open.RO)
2682
2683 def test_invert(self):
2684 Perm = self.Perm
2685 RW = Perm.R | Perm.W
2686 RX = Perm.R | Perm.X
2687 WX = Perm.W | Perm.X
2688 RWX = Perm.R | Perm.W | Perm.X
2689 values = list(Perm) + [RW, RX, WX, RWX, Perm(0)]
2690 for i in values:
2691 self.assertEqual(~i, ~i.value)
2692 self.assertEqual((~i).value, ~i.value)
2693 self.assertIs(type(~i), Perm)
2694 self.assertEqual(~~i, i)
2695 for i in Perm:
2696 self.assertIs(~~i, i)
2697 Open = self.Open
2698 self.assertIs(Open.WO & ~Open.WO, Open.RO)
2699 self.assertIs((Open.WO|Open.CE) & ~Open.WO, Open.CE)
2700
2701 def test_programatic_function_string(self):
Ethan Furman65a5a472016-09-01 23:55:19 -07002702 Perm = IntFlag('Perm', 'R W X')
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002703 lst = list(Perm)
2704 self.assertEqual(len(lst), len(Perm))
2705 self.assertEqual(len(Perm), 3, Perm)
2706 self.assertEqual(lst, [Perm.R, Perm.W, Perm.X])
2707 for i, n in enumerate('R W X'.split()):
2708 v = 1<<i
2709 e = Perm(v)
2710 self.assertEqual(e.value, v)
2711 self.assertEqual(type(e.value), int)
2712 self.assertEqual(e, v)
2713 self.assertEqual(e.name, n)
2714 self.assertIn(e, Perm)
2715 self.assertIs(type(e), Perm)
2716
2717 def test_programatic_function_string_with_start(self):
Ethan Furman65a5a472016-09-01 23:55:19 -07002718 Perm = IntFlag('Perm', 'R W X', start=8)
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002719 lst = list(Perm)
2720 self.assertEqual(len(lst), len(Perm))
2721 self.assertEqual(len(Perm), 3, Perm)
2722 self.assertEqual(lst, [Perm.R, Perm.W, Perm.X])
2723 for i, n in enumerate('R W X'.split()):
2724 v = 8<<i
2725 e = Perm(v)
2726 self.assertEqual(e.value, v)
2727 self.assertEqual(type(e.value), int)
2728 self.assertEqual(e, v)
2729 self.assertEqual(e.name, n)
2730 self.assertIn(e, Perm)
2731 self.assertIs(type(e), Perm)
2732
2733 def test_programatic_function_string_list(self):
Ethan Furman65a5a472016-09-01 23:55:19 -07002734 Perm = IntFlag('Perm', ['R', 'W', 'X'])
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002735 lst = list(Perm)
2736 self.assertEqual(len(lst), len(Perm))
2737 self.assertEqual(len(Perm), 3, Perm)
2738 self.assertEqual(lst, [Perm.R, Perm.W, Perm.X])
2739 for i, n in enumerate('R W X'.split()):
2740 v = 1<<i
2741 e = Perm(v)
2742 self.assertEqual(e.value, v)
2743 self.assertEqual(type(e.value), int)
2744 self.assertEqual(e, v)
2745 self.assertEqual(e.name, n)
2746 self.assertIn(e, Perm)
2747 self.assertIs(type(e), Perm)
2748
2749 def test_programatic_function_iterable(self):
Ethan Furman65a5a472016-09-01 23:55:19 -07002750 Perm = IntFlag('Perm', (('R', 2), ('W', 8), ('X', 32)))
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002751 lst = list(Perm)
2752 self.assertEqual(len(lst), len(Perm))
2753 self.assertEqual(len(Perm), 3, Perm)
2754 self.assertEqual(lst, [Perm.R, Perm.W, Perm.X])
2755 for i, n in enumerate('R W X'.split()):
2756 v = 1<<(2*i+1)
2757 e = Perm(v)
2758 self.assertEqual(e.value, v)
2759 self.assertEqual(type(e.value), int)
2760 self.assertEqual(e, v)
2761 self.assertEqual(e.name, n)
2762 self.assertIn(e, Perm)
2763 self.assertIs(type(e), Perm)
2764
2765 def test_programatic_function_from_dict(self):
Ethan Furman65a5a472016-09-01 23:55:19 -07002766 Perm = IntFlag('Perm', OrderedDict((('R', 2), ('W', 8), ('X', 32))))
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002767 lst = list(Perm)
2768 self.assertEqual(len(lst), len(Perm))
2769 self.assertEqual(len(Perm), 3, Perm)
2770 self.assertEqual(lst, [Perm.R, Perm.W, Perm.X])
2771 for i, n in enumerate('R W X'.split()):
2772 v = 1<<(2*i+1)
2773 e = Perm(v)
2774 self.assertEqual(e.value, v)
2775 self.assertEqual(type(e.value), int)
2776 self.assertEqual(e, v)
2777 self.assertEqual(e.name, n)
2778 self.assertIn(e, Perm)
2779 self.assertIs(type(e), Perm)
2780
2781
Dong-hee Nadcc8ce42017-06-22 01:52:32 +09002782 def test_programatic_function_from_empty_list(self):
2783 Perm = enum.IntFlag('Perm', [])
2784 lst = list(Perm)
2785 self.assertEqual(len(lst), len(Perm))
2786 self.assertEqual(len(Perm), 0, Perm)
2787 Thing = enum.Enum('Thing', [])
2788 lst = list(Thing)
2789 self.assertEqual(len(lst), len(Thing))
2790 self.assertEqual(len(Thing), 0, Thing)
2791
2792
2793 def test_programatic_function_from_empty_tuple(self):
2794 Perm = enum.IntFlag('Perm', ())
2795 lst = list(Perm)
2796 self.assertEqual(len(lst), len(Perm))
2797 self.assertEqual(len(Perm), 0, Perm)
2798 Thing = enum.Enum('Thing', ())
2799 self.assertEqual(len(lst), len(Thing))
2800 self.assertEqual(len(Thing), 0, Thing)
2801
Rahul Jha94306522018-09-10 23:51:04 +05302802 def test_contains(self):
2803 Open = self.Open
2804 Color = self.Color
2805 self.assertTrue(Color.GREEN in Color)
2806 self.assertTrue(Open.RW in Open)
2807 self.assertFalse(Color.GREEN in Open)
2808 self.assertFalse(Open.RW in Color)
2809 with self.assertRaises(TypeError):
2810 'GREEN' in Color
2811 with self.assertRaises(TypeError):
2812 'RW' in Open
2813 with self.assertRaises(TypeError):
2814 2 in Color
2815 with self.assertRaises(TypeError):
2816 2 in Open
2817
2818 def test_member_contains(self):
Ethan Furman65a5a472016-09-01 23:55:19 -07002819 Perm = self.Perm
2820 R, W, X = Perm
2821 RW = R | W
2822 RX = R | X
2823 WX = W | X
2824 RWX = R | W | X
2825 self.assertTrue(R in RW)
2826 self.assertTrue(R in RX)
2827 self.assertTrue(R in RWX)
2828 self.assertTrue(W in RW)
2829 self.assertTrue(W in WX)
2830 self.assertTrue(W in RWX)
2831 self.assertTrue(X in RX)
2832 self.assertTrue(X in WX)
2833 self.assertTrue(X in RWX)
2834 self.assertFalse(R in WX)
2835 self.assertFalse(W in RX)
2836 self.assertFalse(X in RW)
Rahul Jha94306522018-09-10 23:51:04 +05302837 with self.assertRaises(TypeError):
2838 self.assertFalse('test' in RW)
Ethan Furman65a5a472016-09-01 23:55:19 -07002839
Ethan Furman7219e272020-09-16 13:01:00 -07002840 def test_member_iter(self):
2841 Color = self.Color
2842 self.assertEqual(list(Color.PURPLE), [Color.BLUE, Color.RED])
2843 self.assertEqual(list(Color.BLUE), [Color.BLUE])
2844 self.assertEqual(list(Color.GREEN), [Color.GREEN])
2845
Ethan Furman25d94bb2016-09-02 16:32:32 -07002846 def test_bool(self):
2847 Perm = self.Perm
2848 for f in Perm:
2849 self.assertTrue(f)
2850 Open = self.Open
2851 for f in Open:
2852 self.assertEqual(bool(f.value), bool(f))
2853
Ethan Furman5bdab642018-09-21 19:03:09 -07002854 def test_multiple_mixin(self):
2855 class AllMixin:
2856 @classproperty
2857 def ALL(cls):
2858 members = list(cls)
2859 all_value = None
2860 if members:
2861 all_value = members[0]
2862 for member in members[1:]:
2863 all_value |= member
2864 cls.ALL = all_value
2865 return all_value
2866 class StrMixin:
2867 def __str__(self):
2868 return self._name_.lower()
2869 class Color(AllMixin, IntFlag):
2870 RED = auto()
2871 GREEN = auto()
2872 BLUE = auto()
2873 self.assertEqual(Color.RED.value, 1)
2874 self.assertEqual(Color.GREEN.value, 2)
2875 self.assertEqual(Color.BLUE.value, 4)
2876 self.assertEqual(Color.ALL.value, 7)
2877 self.assertEqual(str(Color.BLUE), 'Color.BLUE')
2878 class Color(AllMixin, StrMixin, IntFlag):
2879 RED = auto()
2880 GREEN = auto()
2881 BLUE = auto()
2882 self.assertEqual(Color.RED.value, 1)
2883 self.assertEqual(Color.GREEN.value, 2)
2884 self.assertEqual(Color.BLUE.value, 4)
2885 self.assertEqual(Color.ALL.value, 7)
2886 self.assertEqual(str(Color.BLUE), 'blue')
2887 class Color(StrMixin, AllMixin, IntFlag):
2888 RED = auto()
2889 GREEN = auto()
2890 BLUE = auto()
2891 self.assertEqual(Color.RED.value, 1)
2892 self.assertEqual(Color.GREEN.value, 2)
2893 self.assertEqual(Color.BLUE.value, 4)
2894 self.assertEqual(Color.ALL.value, 7)
2895 self.assertEqual(str(Color.BLUE), 'blue')
2896
Hai Shie80697d2020-05-28 06:10:27 +08002897 @threading_helper.reap_threads
Ethan Furman28cf6632017-01-24 12:12:06 -08002898 def test_unique_composite(self):
2899 # override __eq__ to be identity only
2900 class TestFlag(IntFlag):
2901 one = auto()
2902 two = auto()
2903 three = auto()
2904 four = auto()
2905 five = auto()
2906 six = auto()
2907 seven = auto()
2908 eight = auto()
2909 def __eq__(self, other):
2910 return self is other
2911 def __hash__(self):
2912 return hash(self._value_)
2913 # have multiple threads competing to complete the composite members
2914 seen = set()
2915 failed = False
2916 def cycle_enum():
2917 nonlocal failed
2918 try:
2919 for i in range(256):
2920 seen.add(TestFlag(i))
2921 except Exception:
2922 failed = True
2923 threads = [
2924 threading.Thread(target=cycle_enum)
2925 for _ in range(8)
2926 ]
Hai Shie80697d2020-05-28 06:10:27 +08002927 with threading_helper.start_threads(threads):
Ethan Furman28cf6632017-01-24 12:12:06 -08002928 pass
2929 # check that only 248 members were created
2930 self.assertFalse(
2931 failed,
2932 'at least one thread failed while creating composite members')
2933 self.assertEqual(256, len(seen), 'too many composite members created')
2934
2935
Brennan D Baraban8b914d22019-03-03 14:09:11 -08002936class TestEmptyAndNonLatinStrings(unittest.TestCase):
2937
2938 def test_empty_string(self):
2939 with self.assertRaises(ValueError):
2940 empty_abc = Enum('empty_abc', ('', 'B', 'C'))
2941
2942 def test_non_latin_character_string(self):
2943 greek_abc = Enum('greek_abc', ('\u03B1', 'B', 'C'))
2944 item = getattr(greek_abc, '\u03B1')
2945 self.assertEqual(item.value, 1)
2946
2947 def test_non_latin_number_string(self):
2948 hebrew_123 = Enum('hebrew_123', ('\u05D0', '2', '3'))
2949 item = getattr(hebrew_123, '\u05D0')
2950 self.assertEqual(item.value, 1)
2951
2952
Ethan Furmanf24bb352013-07-18 17:05:39 -07002953class TestUnique(unittest.TestCase):
2954
2955 def test_unique_clean(self):
2956 @unique
2957 class Clean(Enum):
2958 one = 1
2959 two = 'dos'
2960 tres = 4.0
2961 @unique
2962 class Cleaner(IntEnum):
2963 single = 1
2964 double = 2
2965 triple = 3
2966
2967 def test_unique_dirty(self):
2968 with self.assertRaisesRegex(ValueError, 'tres.*one'):
2969 @unique
2970 class Dirty(Enum):
2971 one = 1
2972 two = 'dos'
2973 tres = 1
2974 with self.assertRaisesRegex(
2975 ValueError,
2976 'double.*single.*turkey.*triple',
2977 ):
2978 @unique
2979 class Dirtier(IntEnum):
2980 single = 1
2981 double = 1
2982 triple = 3
2983 turkey = 3
2984
Ethan Furman3803ad42016-05-01 10:03:53 -07002985 def test_unique_with_name(self):
2986 @unique
2987 class Silly(Enum):
2988 one = 1
2989 two = 'dos'
2990 name = 3
2991 @unique
2992 class Sillier(IntEnum):
2993 single = 1
2994 name = 2
2995 triple = 3
2996 value = 4
2997
Ethan Furmanf24bb352013-07-18 17:05:39 -07002998
Ethan Furman5bdab642018-09-21 19:03:09 -07002999
Ethan Furman3323da92015-04-11 09:39:59 -07003000expected_help_output_with_docs = """\
Ethan Furman5875d742013-10-21 20:45:55 -07003001Help on class Color in module %s:
3002
3003class Color(enum.Enum)
Serhiy Storchaka90f63322017-01-24 09:06:22 +02003004 | Color(value, names=None, *, module=None, qualname=None, type=None, start=1)
3005 |\x20\x20
Ethan Furman48a724f2015-04-11 23:23:06 -07003006 | An enumeration.
Serhiy Storchakab599ca82015-04-04 12:48:04 +03003007 |\x20\x20
Ethan Furman5875d742013-10-21 20:45:55 -07003008 | Method resolution order:
3009 | Color
3010 | enum.Enum
3011 | builtins.object
3012 |\x20\x20
3013 | Data and other attributes defined here:
3014 |\x20\x20
3015 | blue = <Color.blue: 3>
3016 |\x20\x20
3017 | green = <Color.green: 2>
3018 |\x20\x20
3019 | red = <Color.red: 1>
3020 |\x20\x20
3021 | ----------------------------------------------------------------------
3022 | Data descriptors inherited from enum.Enum:
3023 |\x20\x20
3024 | name
3025 | The name of the Enum member.
3026 |\x20\x20
3027 | value
3028 | The value of the Enum member.
3029 |\x20\x20
3030 | ----------------------------------------------------------------------
Raymond Hettinger62be3382019-03-24 17:07:47 -07003031 | Readonly properties inherited from enum.EnumMeta:
Ethan Furman5875d742013-10-21 20:45:55 -07003032 |\x20\x20
3033 | __members__
3034 | Returns a mapping of member name->value.
3035 |\x20\x20\x20\x20\x20\x20
3036 | This mapping lists all enum members, including aliases. Note that this
Ethan Furman3323da92015-04-11 09:39:59 -07003037 | is a read-only view of the internal mapping."""
3038
3039expected_help_output_without_docs = """\
3040Help on class Color in module %s:
3041
3042class Color(enum.Enum)
Serhiy Storchaka90f63322017-01-24 09:06:22 +02003043 | Color(value, names=None, *, module=None, qualname=None, type=None, start=1)
3044 |\x20\x20
Ethan Furman3323da92015-04-11 09:39:59 -07003045 | Method resolution order:
3046 | Color
3047 | enum.Enum
3048 | builtins.object
3049 |\x20\x20
3050 | Data and other attributes defined here:
3051 |\x20\x20
3052 | blue = <Color.blue: 3>
3053 |\x20\x20
3054 | green = <Color.green: 2>
3055 |\x20\x20
3056 | red = <Color.red: 1>
3057 |\x20\x20
3058 | ----------------------------------------------------------------------
3059 | Data descriptors inherited from enum.Enum:
3060 |\x20\x20
3061 | name
3062 |\x20\x20
3063 | value
3064 |\x20\x20
3065 | ----------------------------------------------------------------------
3066 | Data descriptors inherited from enum.EnumMeta:
3067 |\x20\x20
3068 | __members__"""
Ethan Furman5875d742013-10-21 20:45:55 -07003069
3070class TestStdLib(unittest.TestCase):
3071
Ethan Furman48a724f2015-04-11 23:23:06 -07003072 maxDiff = None
3073
Ethan Furman5875d742013-10-21 20:45:55 -07003074 class Color(Enum):
3075 red = 1
3076 green = 2
3077 blue = 3
3078
3079 def test_pydoc(self):
3080 # indirectly test __objclass__
Ethan Furman3323da92015-04-11 09:39:59 -07003081 if StrEnum.__doc__ is None:
3082 expected_text = expected_help_output_without_docs % __name__
3083 else:
3084 expected_text = expected_help_output_with_docs % __name__
Ethan Furman5875d742013-10-21 20:45:55 -07003085 output = StringIO()
3086 helper = pydoc.Helper(output=output)
3087 helper(self.Color)
3088 result = output.getvalue().strip()
Victor Stinner4b0432d2014-06-16 22:48:43 +02003089 self.assertEqual(result, expected_text)
Ethan Furman5875d742013-10-21 20:45:55 -07003090
3091 def test_inspect_getmembers(self):
3092 values = dict((
3093 ('__class__', EnumMeta),
Ethan Furman48a724f2015-04-11 23:23:06 -07003094 ('__doc__', 'An enumeration.'),
Ethan Furman5875d742013-10-21 20:45:55 -07003095 ('__members__', self.Color.__members__),
3096 ('__module__', __name__),
3097 ('blue', self.Color.blue),
3098 ('green', self.Color.green),
3099 ('name', Enum.__dict__['name']),
3100 ('red', self.Color.red),
3101 ('value', Enum.__dict__['value']),
3102 ))
3103 result = dict(inspect.getmembers(self.Color))
3104 self.assertEqual(values.keys(), result.keys())
3105 failed = False
3106 for k in values.keys():
3107 if result[k] != values[k]:
3108 print()
3109 print('\n%s\n key: %s\n result: %s\nexpected: %s\n%s\n' %
3110 ('=' * 75, k, result[k], values[k], '=' * 75), sep='')
3111 failed = True
3112 if failed:
3113 self.fail("result does not equal expected, see print above")
3114
3115 def test_inspect_classify_class_attrs(self):
3116 # indirectly test __objclass__
3117 from inspect import Attribute
3118 values = [
3119 Attribute(name='__class__', kind='data',
3120 defining_class=object, object=EnumMeta),
3121 Attribute(name='__doc__', kind='data',
Ethan Furman48a724f2015-04-11 23:23:06 -07003122 defining_class=self.Color, object='An enumeration.'),
Ethan Furman5875d742013-10-21 20:45:55 -07003123 Attribute(name='__members__', kind='property',
3124 defining_class=EnumMeta, object=EnumMeta.__members__),
3125 Attribute(name='__module__', kind='data',
3126 defining_class=self.Color, object=__name__),
3127 Attribute(name='blue', kind='data',
3128 defining_class=self.Color, object=self.Color.blue),
3129 Attribute(name='green', kind='data',
3130 defining_class=self.Color, object=self.Color.green),
3131 Attribute(name='red', kind='data',
3132 defining_class=self.Color, object=self.Color.red),
3133 Attribute(name='name', kind='data',
3134 defining_class=Enum, object=Enum.__dict__['name']),
3135 Attribute(name='value', kind='data',
3136 defining_class=Enum, object=Enum.__dict__['value']),
3137 ]
3138 values.sort(key=lambda item: item.name)
3139 result = list(inspect.classify_class_attrs(self.Color))
3140 result.sort(key=lambda item: item.name)
3141 failed = False
3142 for v, r in zip(values, result):
3143 if r != v:
3144 print('\n%s\n%s\n%s\n%s\n' % ('=' * 75, r, v, '=' * 75), sep='')
3145 failed = True
3146 if failed:
3147 self.fail("result does not equal expected, see print above")
3148
Martin Panter19e69c52015-11-14 12:46:42 +00003149
3150class MiscTestCase(unittest.TestCase):
3151 def test__all__(self):
3152 support.check__all__(self, enum)
3153
3154
Gregory P. Smith ext:(%20%5BGoogle%20Inc.%5D)6f20bd62016-06-03 19:14:52 +00003155# These are unordered here on purpose to ensure that declaration order
3156# makes no difference.
3157CONVERT_TEST_NAME_D = 5
3158CONVERT_TEST_NAME_C = 5
3159CONVERT_TEST_NAME_B = 5
3160CONVERT_TEST_NAME_A = 5 # This one should sort first.
3161CONVERT_TEST_NAME_E = 5
3162CONVERT_TEST_NAME_F = 5
3163
3164class TestIntEnumConvert(unittest.TestCase):
3165 def test_convert_value_lookup_priority(self):
orlnub1230fb9fad2018-09-12 20:28:53 +03003166 test_type = enum.IntEnum._convert_(
Ethan Furman28cf6632017-01-24 12:12:06 -08003167 'UnittestConvert',
3168 ('test.test_enum', '__main__')[__name__=='__main__'],
Gregory P. Smith ext:(%20%5BGoogle%20Inc.%5D)6f20bd62016-06-03 19:14:52 +00003169 filter=lambda x: x.startswith('CONVERT_TEST_'))
3170 # We don't want the reverse lookup value to vary when there are
3171 # multiple possible names for a given value. It should always
3172 # report the first lexigraphical name in that case.
3173 self.assertEqual(test_type(5).name, 'CONVERT_TEST_NAME_A')
3174
3175 def test_convert(self):
orlnub1230fb9fad2018-09-12 20:28:53 +03003176 test_type = enum.IntEnum._convert_(
Ethan Furman28cf6632017-01-24 12:12:06 -08003177 'UnittestConvert',
3178 ('test.test_enum', '__main__')[__name__=='__main__'],
Gregory P. Smith ext:(%20%5BGoogle%20Inc.%5D)6f20bd62016-06-03 19:14:52 +00003179 filter=lambda x: x.startswith('CONVERT_TEST_'))
3180 # Ensure that test_type has all of the desired names and values.
3181 self.assertEqual(test_type.CONVERT_TEST_NAME_F,
3182 test_type.CONVERT_TEST_NAME_A)
3183 self.assertEqual(test_type.CONVERT_TEST_NAME_B, 5)
3184 self.assertEqual(test_type.CONVERT_TEST_NAME_C, 5)
3185 self.assertEqual(test_type.CONVERT_TEST_NAME_D, 5)
3186 self.assertEqual(test_type.CONVERT_TEST_NAME_E, 5)
3187 # Ensure that test_type only picked up names matching the filter.
3188 self.assertEqual([name for name in dir(test_type)
3189 if name[0:2] not in ('CO', '__')],
3190 [], msg='Names other than CONVERT_TEST_* found.')
3191
orlnub1230fb9fad2018-09-12 20:28:53 +03003192 @unittest.skipUnless(sys.version_info[:2] == (3, 8),
3193 '_convert was deprecated in 3.8')
3194 def test_convert_warn(self):
3195 with self.assertWarns(DeprecationWarning):
3196 enum.IntEnum._convert(
3197 'UnittestConvert',
3198 ('test.test_enum', '__main__')[__name__=='__main__'],
3199 filter=lambda x: x.startswith('CONVERT_TEST_'))
3200
3201 @unittest.skipUnless(sys.version_info >= (3, 9),
3202 '_convert was removed in 3.9')
3203 def test_convert_raise(self):
3204 with self.assertRaises(AttributeError):
3205 enum.IntEnum._convert(
3206 'UnittestConvert',
3207 ('test.test_enum', '__main__')[__name__=='__main__'],
3208 filter=lambda x: x.startswith('CONVERT_TEST_'))
3209
Gregory P. Smith ext:(%20%5BGoogle%20Inc.%5D)6f20bd62016-06-03 19:14:52 +00003210
Ethan Furman6b3d64a2013-06-14 16:55:46 -07003211if __name__ == '__main__':
3212 unittest.main()