blob: 698fd307a0e2dea4eff74cefc2be5a2c28c58a3d [file] [log] [blame]
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001import enum
Ethan Furman5875d742013-10-21 20:45:55 -07002import inspect
3import pydoc
Ethan Furman6b3d64a2013-06-14 16:55:46 -07004import unittest
5from collections import OrderedDict
Ethan Furman65a5a472016-09-01 23:55:19 -07006from enum import Enum, IntEnum, EnumMeta, Flag, IntFlag, unique
Ethan Furman5875d742013-10-21 20:45:55 -07007from io import StringIO
Ethan Furman2ddb39a2014-02-06 17:28:50 -08008from pickle import dumps, loads, PicklingError, HIGHEST_PROTOCOL
Martin Panter19e69c52015-11-14 12:46:42 +00009from test import support
Ethan Furman6b3d64a2013-06-14 16:55:46 -070010
11# for pickle tests
12try:
13 class Stooges(Enum):
14 LARRY = 1
15 CURLY = 2
16 MOE = 3
17except Exception as exc:
18 Stooges = exc
19
20try:
21 class IntStooges(int, Enum):
22 LARRY = 1
23 CURLY = 2
24 MOE = 3
25except Exception as exc:
26 IntStooges = exc
27
28try:
29 class FloatStooges(float, Enum):
30 LARRY = 1.39
31 CURLY = 2.72
32 MOE = 3.142596
33except Exception as exc:
34 FloatStooges = exc
35
Ethan Furman65a5a472016-09-01 23:55:19 -070036try:
37 class FlagStooges(Flag):
38 LARRY = 1
39 CURLY = 2
40 MOE = 3
41except Exception as exc:
42 FlagStooges = exc
43
Ethan Furman6b3d64a2013-06-14 16:55:46 -070044# for pickle test and subclass tests
45try:
46 class StrEnum(str, Enum):
47 'accepts only string values'
48 class Name(StrEnum):
49 BDFL = 'Guido van Rossum'
50 FLUFL = 'Barry Warsaw'
51except Exception as exc:
52 Name = exc
53
54try:
55 Question = Enum('Question', 'who what when where why', module=__name__)
56except Exception as exc:
57 Question = exc
58
59try:
60 Answer = Enum('Answer', 'him this then there because')
61except Exception as exc:
62 Answer = exc
63
Ethan Furmanca1b7942014-02-08 11:36:27 -080064try:
65 Theory = Enum('Theory', 'rule law supposition', qualname='spanish_inquisition')
66except Exception as exc:
67 Theory = exc
68
Ethan Furman6b3d64a2013-06-14 16:55:46 -070069# for doctests
70try:
71 class Fruit(Enum):
72 tomato = 1
73 banana = 2
74 cherry = 3
75except Exception:
76 pass
77
Serhiy Storchakae50e7802015-03-31 16:56:49 +030078def test_pickle_dump_load(assertion, source, target=None):
Ethan Furman2ddb39a2014-02-06 17:28:50 -080079 if target is None:
80 target = source
Serhiy Storchakae50e7802015-03-31 16:56:49 +030081 for protocol in range(HIGHEST_PROTOCOL + 1):
Ethan Furman2ddb39a2014-02-06 17:28:50 -080082 assertion(loads(dumps(source, protocol=protocol)), target)
83
Serhiy Storchakae50e7802015-03-31 16:56:49 +030084def test_pickle_exception(assertion, exception, obj):
85 for protocol in range(HIGHEST_PROTOCOL + 1):
Ethan Furman2ddb39a2014-02-06 17:28:50 -080086 with assertion(exception):
87 dumps(obj, protocol=protocol)
Ethan Furman648f8602013-10-06 17:19:54 -070088
89class TestHelpers(unittest.TestCase):
90 # _is_descriptor, _is_sunder, _is_dunder
91
92 def test_is_descriptor(self):
93 class foo:
94 pass
95 for attr in ('__get__','__set__','__delete__'):
96 obj = foo()
97 self.assertFalse(enum._is_descriptor(obj))
98 setattr(obj, attr, 1)
99 self.assertTrue(enum._is_descriptor(obj))
100
101 def test_is_sunder(self):
102 for s in ('_a_', '_aa_'):
103 self.assertTrue(enum._is_sunder(s))
104
105 for s in ('a', 'a_', '_a', '__a', 'a__', '__a__', '_a__', '__a_', '_',
106 '__', '___', '____', '_____',):
107 self.assertFalse(enum._is_sunder(s))
108
109 def test_is_dunder(self):
110 for s in ('__a__', '__aa__'):
111 self.assertTrue(enum._is_dunder(s))
112 for s in ('a', 'a_', '_a', '__a', 'a__', '_a_', '_a__', '__a_', '_',
113 '__', '___', '____', '_____',):
114 self.assertFalse(enum._is_dunder(s))
115
116
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700117class TestEnum(unittest.TestCase):
Ethan Furmanca1b7942014-02-08 11:36:27 -0800118
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700119 def setUp(self):
120 class Season(Enum):
121 SPRING = 1
122 SUMMER = 2
123 AUTUMN = 3
124 WINTER = 4
125 self.Season = Season
126
Ethan Furmanec15a822013-08-31 19:17:41 -0700127 class Konstants(float, Enum):
128 E = 2.7182818
129 PI = 3.1415926
130 TAU = 2 * PI
131 self.Konstants = Konstants
132
133 class Grades(IntEnum):
134 A = 5
135 B = 4
136 C = 3
137 D = 2
138 F = 0
139 self.Grades = Grades
140
141 class Directional(str, Enum):
142 EAST = 'east'
143 WEST = 'west'
144 NORTH = 'north'
145 SOUTH = 'south'
146 self.Directional = Directional
147
148 from datetime import date
149 class Holiday(date, Enum):
150 NEW_YEAR = 2013, 1, 1
151 IDES_OF_MARCH = 2013, 3, 15
152 self.Holiday = Holiday
153
Ethan Furman388a3922013-08-12 06:51:41 -0700154 def test_dir_on_class(self):
155 Season = self.Season
156 self.assertEqual(
157 set(dir(Season)),
Ethan Furmanc850f342013-09-15 16:59:35 -0700158 set(['__class__', '__doc__', '__members__', '__module__',
Ethan Furman388a3922013-08-12 06:51:41 -0700159 'SPRING', 'SUMMER', 'AUTUMN', 'WINTER']),
160 )
161
162 def test_dir_on_item(self):
163 Season = self.Season
164 self.assertEqual(
165 set(dir(Season.WINTER)),
Ethan Furmanc850f342013-09-15 16:59:35 -0700166 set(['__class__', '__doc__', '__module__', 'name', 'value']),
Ethan Furman388a3922013-08-12 06:51:41 -0700167 )
168
Ethan Furmanc850f342013-09-15 16:59:35 -0700169 def test_dir_with_added_behavior(self):
170 class Test(Enum):
171 this = 'that'
172 these = 'those'
173 def wowser(self):
174 return ("Wowser! I'm %s!" % self.name)
175 self.assertEqual(
176 set(dir(Test)),
177 set(['__class__', '__doc__', '__members__', '__module__', 'this', 'these']),
178 )
179 self.assertEqual(
180 set(dir(Test.this)),
181 set(['__class__', '__doc__', '__module__', 'name', 'value', 'wowser']),
182 )
183
Ethan Furman0ae550b2014-10-14 08:58:32 -0700184 def test_dir_on_sub_with_behavior_on_super(self):
185 # see issue22506
186 class SuperEnum(Enum):
187 def invisible(self):
188 return "did you see me?"
189 class SubEnum(SuperEnum):
190 sample = 5
191 self.assertEqual(
192 set(dir(SubEnum.sample)),
193 set(['__class__', '__doc__', '__module__', 'name', 'value', 'invisible']),
194 )
195
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700196 def test_enum_in_enum_out(self):
197 Season = self.Season
198 self.assertIs(Season(Season.WINTER), Season.WINTER)
199
200 def test_enum_value(self):
201 Season = self.Season
202 self.assertEqual(Season.SPRING.value, 1)
203
204 def test_intenum_value(self):
205 self.assertEqual(IntStooges.CURLY.value, 2)
206
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700207 def test_enum(self):
208 Season = self.Season
209 lst = list(Season)
210 self.assertEqual(len(lst), len(Season))
211 self.assertEqual(len(Season), 4, Season)
212 self.assertEqual(
213 [Season.SPRING, Season.SUMMER, Season.AUTUMN, Season.WINTER], lst)
214
215 for i, season in enumerate('SPRING SUMMER AUTUMN WINTER'.split(), 1):
216 e = Season(i)
217 self.assertEqual(e, getattr(Season, season))
218 self.assertEqual(e.value, i)
219 self.assertNotEqual(e, i)
220 self.assertEqual(e.name, season)
221 self.assertIn(e, Season)
222 self.assertIs(type(e), Season)
223 self.assertIsInstance(e, Season)
224 self.assertEqual(str(e), 'Season.' + season)
225 self.assertEqual(
226 repr(e),
227 '<Season.{0}: {1}>'.format(season, i),
228 )
229
230 def test_value_name(self):
231 Season = self.Season
232 self.assertEqual(Season.SPRING.name, 'SPRING')
233 self.assertEqual(Season.SPRING.value, 1)
234 with self.assertRaises(AttributeError):
235 Season.SPRING.name = 'invierno'
236 with self.assertRaises(AttributeError):
237 Season.SPRING.value = 2
238
Ethan Furmanf203f2d2013-09-06 07:16:48 -0700239 def test_changing_member(self):
240 Season = self.Season
241 with self.assertRaises(AttributeError):
242 Season.WINTER = 'really cold'
243
Ethan Furman64a99722013-09-22 16:18:19 -0700244 def test_attribute_deletion(self):
245 class Season(Enum):
246 SPRING = 1
247 SUMMER = 2
248 AUTUMN = 3
249 WINTER = 4
250
251 def spam(cls):
252 pass
253
254 self.assertTrue(hasattr(Season, 'spam'))
255 del Season.spam
256 self.assertFalse(hasattr(Season, 'spam'))
257
258 with self.assertRaises(AttributeError):
259 del Season.SPRING
260 with self.assertRaises(AttributeError):
261 del Season.DRY
262 with self.assertRaises(AttributeError):
263 del Season.SPRING.name
264
Ethan Furman5de67b12016-04-13 23:52:09 -0700265 def test_bool_of_class(self):
266 class Empty(Enum):
267 pass
268 self.assertTrue(bool(Empty))
269
270 def test_bool_of_member(self):
271 class Count(Enum):
272 zero = 0
273 one = 1
274 two = 2
275 for member in Count:
276 self.assertTrue(bool(member))
277
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700278 def test_invalid_names(self):
279 with self.assertRaises(ValueError):
280 class Wrong(Enum):
281 mro = 9
282 with self.assertRaises(ValueError):
283 class Wrong(Enum):
284 _create_= 11
285 with self.assertRaises(ValueError):
286 class Wrong(Enum):
287 _get_mixins_ = 9
288 with self.assertRaises(ValueError):
289 class Wrong(Enum):
290 _find_new_ = 1
291 with self.assertRaises(ValueError):
292 class Wrong(Enum):
293 _any_name_ = 9
294
Ethan Furman6db1fd52015-09-17 21:49:12 -0700295 def test_bool(self):
Ethan Furman60255b62016-01-15 15:01:33 -0800296 # plain Enum members are always True
Ethan Furman6db1fd52015-09-17 21:49:12 -0700297 class Logic(Enum):
298 true = True
299 false = False
300 self.assertTrue(Logic.true)
Ethan Furman60255b62016-01-15 15:01:33 -0800301 self.assertTrue(Logic.false)
302 # unless overridden
303 class RealLogic(Enum):
304 true = True
305 false = False
306 def __bool__(self):
307 return bool(self._value_)
308 self.assertTrue(RealLogic.true)
309 self.assertFalse(RealLogic.false)
310 # mixed Enums depend on mixed-in type
311 class IntLogic(int, Enum):
312 true = 1
313 false = 0
314 self.assertTrue(IntLogic.true)
315 self.assertFalse(IntLogic.false)
Ethan Furman6db1fd52015-09-17 21:49:12 -0700316
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700317 def test_contains(self):
318 Season = self.Season
319 self.assertIn(Season.AUTUMN, Season)
320 self.assertNotIn(3, Season)
321
322 val = Season(3)
323 self.assertIn(val, Season)
324
325 class OtherEnum(Enum):
326 one = 1; two = 2
327 self.assertNotIn(OtherEnum.two, Season)
328
329 def test_comparisons(self):
330 Season = self.Season
331 with self.assertRaises(TypeError):
332 Season.SPRING < Season.WINTER
333 with self.assertRaises(TypeError):
334 Season.SPRING > 4
335
336 self.assertNotEqual(Season.SPRING, 1)
337
338 class Part(Enum):
339 SPRING = 1
340 CLIP = 2
341 BARREL = 3
342
343 self.assertNotEqual(Season.SPRING, Part.SPRING)
344 with self.assertRaises(TypeError):
345 Season.SPRING < Part.CLIP
346
347 def test_enum_duplicates(self):
348 class Season(Enum):
349 SPRING = 1
350 SUMMER = 2
351 AUTUMN = FALL = 3
352 WINTER = 4
353 ANOTHER_SPRING = 1
354 lst = list(Season)
355 self.assertEqual(
356 lst,
357 [Season.SPRING, Season.SUMMER,
358 Season.AUTUMN, Season.WINTER,
359 ])
360 self.assertIs(Season.FALL, Season.AUTUMN)
361 self.assertEqual(Season.FALL.value, 3)
362 self.assertEqual(Season.AUTUMN.value, 3)
363 self.assertIs(Season(3), Season.AUTUMN)
364 self.assertIs(Season(1), Season.SPRING)
365 self.assertEqual(Season.FALL.name, 'AUTUMN')
366 self.assertEqual(
367 [k for k,v in Season.__members__.items() if v.name != k],
368 ['FALL', 'ANOTHER_SPRING'],
369 )
370
Ethan Furman101e0742013-09-15 12:34:36 -0700371 def test_duplicate_name(self):
372 with self.assertRaises(TypeError):
373 class Color(Enum):
374 red = 1
375 green = 2
376 blue = 3
377 red = 4
378
379 with self.assertRaises(TypeError):
380 class Color(Enum):
381 red = 1
382 green = 2
383 blue = 3
384 def red(self):
385 return 'red'
386
387 with self.assertRaises(TypeError):
388 class Color(Enum):
389 @property
390 def red(self):
391 return 'redder'
392 red = 1
393 green = 2
394 blue = 3
395
396
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700397 def test_enum_with_value_name(self):
398 class Huh(Enum):
399 name = 1
400 value = 2
401 self.assertEqual(
402 list(Huh),
403 [Huh.name, Huh.value],
404 )
405 self.assertIs(type(Huh.name), Huh)
406 self.assertEqual(Huh.name.name, 'name')
407 self.assertEqual(Huh.name.value, 1)
Ethan Furmanec15a822013-08-31 19:17:41 -0700408
409 def test_format_enum(self):
410 Season = self.Season
411 self.assertEqual('{}'.format(Season.SPRING),
412 '{}'.format(str(Season.SPRING)))
413 self.assertEqual( '{:}'.format(Season.SPRING),
414 '{:}'.format(str(Season.SPRING)))
415 self.assertEqual('{:20}'.format(Season.SPRING),
416 '{:20}'.format(str(Season.SPRING)))
417 self.assertEqual('{:^20}'.format(Season.SPRING),
418 '{:^20}'.format(str(Season.SPRING)))
419 self.assertEqual('{:>20}'.format(Season.SPRING),
420 '{:>20}'.format(str(Season.SPRING)))
421 self.assertEqual('{:<20}'.format(Season.SPRING),
422 '{:<20}'.format(str(Season.SPRING)))
423
424 def test_format_enum_custom(self):
425 class TestFloat(float, Enum):
426 one = 1.0
427 two = 2.0
428 def __format__(self, spec):
429 return 'TestFloat success!'
430 self.assertEqual('{}'.format(TestFloat.one), 'TestFloat success!')
431
432 def assertFormatIsValue(self, spec, member):
433 self.assertEqual(spec.format(member), spec.format(member.value))
434
435 def test_format_enum_date(self):
436 Holiday = self.Holiday
437 self.assertFormatIsValue('{}', Holiday.IDES_OF_MARCH)
438 self.assertFormatIsValue('{:}', Holiday.IDES_OF_MARCH)
439 self.assertFormatIsValue('{:20}', Holiday.IDES_OF_MARCH)
440 self.assertFormatIsValue('{:^20}', Holiday.IDES_OF_MARCH)
441 self.assertFormatIsValue('{:>20}', Holiday.IDES_OF_MARCH)
442 self.assertFormatIsValue('{:<20}', Holiday.IDES_OF_MARCH)
443 self.assertFormatIsValue('{:%Y %m}', Holiday.IDES_OF_MARCH)
444 self.assertFormatIsValue('{:%Y %m %M:00}', Holiday.IDES_OF_MARCH)
445
446 def test_format_enum_float(self):
447 Konstants = self.Konstants
448 self.assertFormatIsValue('{}', Konstants.TAU)
449 self.assertFormatIsValue('{:}', Konstants.TAU)
450 self.assertFormatIsValue('{:20}', Konstants.TAU)
451 self.assertFormatIsValue('{:^20}', Konstants.TAU)
452 self.assertFormatIsValue('{:>20}', Konstants.TAU)
453 self.assertFormatIsValue('{:<20}', Konstants.TAU)
454 self.assertFormatIsValue('{:n}', Konstants.TAU)
455 self.assertFormatIsValue('{:5.2}', Konstants.TAU)
456 self.assertFormatIsValue('{:f}', Konstants.TAU)
457
458 def test_format_enum_int(self):
459 Grades = self.Grades
460 self.assertFormatIsValue('{}', Grades.C)
461 self.assertFormatIsValue('{:}', Grades.C)
462 self.assertFormatIsValue('{:20}', Grades.C)
463 self.assertFormatIsValue('{:^20}', Grades.C)
464 self.assertFormatIsValue('{:>20}', Grades.C)
465 self.assertFormatIsValue('{:<20}', Grades.C)
466 self.assertFormatIsValue('{:+}', Grades.C)
467 self.assertFormatIsValue('{:08X}', Grades.C)
468 self.assertFormatIsValue('{:b}', Grades.C)
469
470 def test_format_enum_str(self):
471 Directional = self.Directional
472 self.assertFormatIsValue('{}', Directional.WEST)
473 self.assertFormatIsValue('{:}', Directional.WEST)
474 self.assertFormatIsValue('{:20}', Directional.WEST)
475 self.assertFormatIsValue('{:^20}', Directional.WEST)
476 self.assertFormatIsValue('{:>20}', Directional.WEST)
477 self.assertFormatIsValue('{:<20}', Directional.WEST)
478
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700479 def test_hash(self):
480 Season = self.Season
481 dates = {}
482 dates[Season.WINTER] = '1225'
483 dates[Season.SPRING] = '0315'
484 dates[Season.SUMMER] = '0704'
485 dates[Season.AUTUMN] = '1031'
486 self.assertEqual(dates[Season.AUTUMN], '1031')
487
488 def test_intenum_from_scratch(self):
489 class phy(int, Enum):
490 pi = 3
491 tau = 2 * pi
492 self.assertTrue(phy.pi < phy.tau)
493
494 def test_intenum_inherited(self):
495 class IntEnum(int, Enum):
496 pass
497 class phy(IntEnum):
498 pi = 3
499 tau = 2 * pi
500 self.assertTrue(phy.pi < phy.tau)
501
502 def test_floatenum_from_scratch(self):
503 class phy(float, Enum):
Ethan Furmanec15a822013-08-31 19:17:41 -0700504 pi = 3.1415926
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700505 tau = 2 * pi
506 self.assertTrue(phy.pi < phy.tau)
507
508 def test_floatenum_inherited(self):
509 class FloatEnum(float, Enum):
510 pass
511 class phy(FloatEnum):
Ethan Furmanec15a822013-08-31 19:17:41 -0700512 pi = 3.1415926
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700513 tau = 2 * pi
514 self.assertTrue(phy.pi < phy.tau)
515
516 def test_strenum_from_scratch(self):
517 class phy(str, Enum):
518 pi = 'Pi'
519 tau = 'Tau'
520 self.assertTrue(phy.pi < phy.tau)
521
522 def test_strenum_inherited(self):
523 class StrEnum(str, Enum):
524 pass
525 class phy(StrEnum):
526 pi = 'Pi'
527 tau = 'Tau'
528 self.assertTrue(phy.pi < phy.tau)
529
530
531 def test_intenum(self):
532 class WeekDay(IntEnum):
533 SUNDAY = 1
534 MONDAY = 2
535 TUESDAY = 3
536 WEDNESDAY = 4
537 THURSDAY = 5
538 FRIDAY = 6
539 SATURDAY = 7
540
541 self.assertEqual(['a', 'b', 'c'][WeekDay.MONDAY], 'c')
542 self.assertEqual([i for i in range(WeekDay.TUESDAY)], [0, 1, 2])
543
544 lst = list(WeekDay)
545 self.assertEqual(len(lst), len(WeekDay))
546 self.assertEqual(len(WeekDay), 7)
547 target = 'SUNDAY MONDAY TUESDAY WEDNESDAY THURSDAY FRIDAY SATURDAY'
548 target = target.split()
549 for i, weekday in enumerate(target, 1):
550 e = WeekDay(i)
551 self.assertEqual(e, i)
552 self.assertEqual(int(e), i)
553 self.assertEqual(e.name, weekday)
554 self.assertIn(e, WeekDay)
555 self.assertEqual(lst.index(e)+1, i)
556 self.assertTrue(0 < e < 8)
557 self.assertIs(type(e), WeekDay)
558 self.assertIsInstance(e, int)
559 self.assertIsInstance(e, Enum)
560
561 def test_intenum_duplicates(self):
562 class WeekDay(IntEnum):
563 SUNDAY = 1
564 MONDAY = 2
565 TUESDAY = TEUSDAY = 3
566 WEDNESDAY = 4
567 THURSDAY = 5
568 FRIDAY = 6
569 SATURDAY = 7
570 self.assertIs(WeekDay.TEUSDAY, WeekDay.TUESDAY)
571 self.assertEqual(WeekDay(3).name, 'TUESDAY')
572 self.assertEqual([k for k,v in WeekDay.__members__.items()
573 if v.name != k], ['TEUSDAY', ])
574
Serhiy Storchakaea36c942016-05-12 10:37:58 +0300575 def test_intenum_from_bytes(self):
576 self.assertIs(IntStooges.from_bytes(b'\x00\x03', 'big'), IntStooges.MOE)
577 with self.assertRaises(ValueError):
578 IntStooges.from_bytes(b'\x00\x05', 'big')
579
580 def test_floatenum_fromhex(self):
581 h = float.hex(FloatStooges.MOE.value)
582 self.assertIs(FloatStooges.fromhex(h), FloatStooges.MOE)
583 h = float.hex(FloatStooges.MOE.value + 0.01)
584 with self.assertRaises(ValueError):
585 FloatStooges.fromhex(h)
586
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700587 def test_pickle_enum(self):
588 if isinstance(Stooges, Exception):
589 raise Stooges
Ethan Furman2ddb39a2014-02-06 17:28:50 -0800590 test_pickle_dump_load(self.assertIs, Stooges.CURLY)
591 test_pickle_dump_load(self.assertIs, Stooges)
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700592
593 def test_pickle_int(self):
594 if isinstance(IntStooges, Exception):
595 raise IntStooges
Ethan Furman2ddb39a2014-02-06 17:28:50 -0800596 test_pickle_dump_load(self.assertIs, IntStooges.CURLY)
597 test_pickle_dump_load(self.assertIs, IntStooges)
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700598
599 def test_pickle_float(self):
600 if isinstance(FloatStooges, Exception):
601 raise FloatStooges
Ethan Furman2ddb39a2014-02-06 17:28:50 -0800602 test_pickle_dump_load(self.assertIs, FloatStooges.CURLY)
603 test_pickle_dump_load(self.assertIs, FloatStooges)
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700604
605 def test_pickle_enum_function(self):
606 if isinstance(Answer, Exception):
607 raise Answer
Ethan Furman2ddb39a2014-02-06 17:28:50 -0800608 test_pickle_dump_load(self.assertIs, Answer.him)
609 test_pickle_dump_load(self.assertIs, Answer)
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700610
611 def test_pickle_enum_function_with_module(self):
612 if isinstance(Question, Exception):
613 raise Question
Ethan Furman2ddb39a2014-02-06 17:28:50 -0800614 test_pickle_dump_load(self.assertIs, Question.who)
615 test_pickle_dump_load(self.assertIs, Question)
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700616
Ethan Furmanca1b7942014-02-08 11:36:27 -0800617 def test_enum_function_with_qualname(self):
618 if isinstance(Theory, Exception):
619 raise Theory
620 self.assertEqual(Theory.__qualname__, 'spanish_inquisition')
621
622 def test_class_nested_enum_and_pickle_protocol_four(self):
623 # would normally just have this directly in the class namespace
624 class NestedEnum(Enum):
625 twigs = 'common'
626 shiny = 'rare'
627
628 self.__class__.NestedEnum = NestedEnum
629 self.NestedEnum.__qualname__ = '%s.NestedEnum' % self.__class__.__name__
Serhiy Storchakae50e7802015-03-31 16:56:49 +0300630 test_pickle_dump_load(self.assertIs, self.NestedEnum.twigs)
Ethan Furmanca1b7942014-02-08 11:36:27 -0800631
Ethan Furman24e837f2015-03-18 17:27:57 -0700632 def test_pickle_by_name(self):
633 class ReplaceGlobalInt(IntEnum):
634 ONE = 1
635 TWO = 2
636 ReplaceGlobalInt.__reduce_ex__ = enum._reduce_ex_by_name
637 for proto in range(HIGHEST_PROTOCOL):
638 self.assertEqual(ReplaceGlobalInt.TWO.__reduce_ex__(proto), 'TWO')
639
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700640 def test_exploding_pickle(self):
Ethan Furmanca1b7942014-02-08 11:36:27 -0800641 BadPickle = Enum(
642 'BadPickle', 'dill sweet bread-n-butter', module=__name__)
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700643 globals()['BadPickle'] = BadPickle
Ethan Furmanca1b7942014-02-08 11:36:27 -0800644 # now break BadPickle to test exception raising
645 enum._make_class_unpicklable(BadPickle)
Ethan Furman2ddb39a2014-02-06 17:28:50 -0800646 test_pickle_exception(self.assertRaises, TypeError, BadPickle.dill)
647 test_pickle_exception(self.assertRaises, PicklingError, BadPickle)
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700648
649 def test_string_enum(self):
650 class SkillLevel(str, Enum):
651 master = 'what is the sound of one hand clapping?'
652 journeyman = 'why did the chicken cross the road?'
653 apprentice = 'knock, knock!'
654 self.assertEqual(SkillLevel.apprentice, 'knock, knock!')
655
656 def test_getattr_getitem(self):
657 class Period(Enum):
658 morning = 1
659 noon = 2
660 evening = 3
661 night = 4
662 self.assertIs(Period(2), Period.noon)
663 self.assertIs(getattr(Period, 'night'), Period.night)
664 self.assertIs(Period['morning'], Period.morning)
665
666 def test_getattr_dunder(self):
667 Season = self.Season
668 self.assertTrue(getattr(Season, '__eq__'))
669
670 def test_iteration_order(self):
671 class Season(Enum):
672 SUMMER = 2
673 WINTER = 4
674 AUTUMN = 3
675 SPRING = 1
676 self.assertEqual(
677 list(Season),
678 [Season.SUMMER, Season.WINTER, Season.AUTUMN, Season.SPRING],
679 )
680
Ethan Furman2131a4a2013-09-14 18:11:24 -0700681 def test_reversed_iteration_order(self):
682 self.assertEqual(
683 list(reversed(self.Season)),
684 [self.Season.WINTER, self.Season.AUTUMN, self.Season.SUMMER,
685 self.Season.SPRING]
686 )
687
Martin Pantereb995702016-07-28 01:11:04 +0000688 def test_programmatic_function_string(self):
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700689 SummerMonth = Enum('SummerMonth', 'june july august')
690 lst = list(SummerMonth)
691 self.assertEqual(len(lst), len(SummerMonth))
692 self.assertEqual(len(SummerMonth), 3, SummerMonth)
693 self.assertEqual(
694 [SummerMonth.june, SummerMonth.july, SummerMonth.august],
695 lst,
696 )
697 for i, month in enumerate('june july august'.split(), 1):
698 e = SummerMonth(i)
699 self.assertEqual(int(e.value), i)
700 self.assertNotEqual(e, i)
701 self.assertEqual(e.name, month)
702 self.assertIn(e, SummerMonth)
703 self.assertIs(type(e), SummerMonth)
704
Martin Pantereb995702016-07-28 01:11:04 +0000705 def test_programmatic_function_string_with_start(self):
Ethan Furmand9925a12014-09-16 20:35:55 -0700706 SummerMonth = Enum('SummerMonth', 'june july august', start=10)
707 lst = list(SummerMonth)
708 self.assertEqual(len(lst), len(SummerMonth))
709 self.assertEqual(len(SummerMonth), 3, SummerMonth)
710 self.assertEqual(
711 [SummerMonth.june, SummerMonth.july, SummerMonth.august],
712 lst,
713 )
714 for i, month in enumerate('june july august'.split(), 10):
715 e = SummerMonth(i)
716 self.assertEqual(int(e.value), i)
717 self.assertNotEqual(e, i)
718 self.assertEqual(e.name, month)
719 self.assertIn(e, SummerMonth)
720 self.assertIs(type(e), SummerMonth)
721
Martin Pantereb995702016-07-28 01:11:04 +0000722 def test_programmatic_function_string_list(self):
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700723 SummerMonth = Enum('SummerMonth', ['june', 'july', 'august'])
724 lst = list(SummerMonth)
725 self.assertEqual(len(lst), len(SummerMonth))
726 self.assertEqual(len(SummerMonth), 3, SummerMonth)
727 self.assertEqual(
728 [SummerMonth.june, SummerMonth.july, SummerMonth.august],
729 lst,
730 )
731 for i, month in enumerate('june july august'.split(), 1):
732 e = SummerMonth(i)
733 self.assertEqual(int(e.value), i)
734 self.assertNotEqual(e, i)
735 self.assertEqual(e.name, month)
736 self.assertIn(e, SummerMonth)
737 self.assertIs(type(e), SummerMonth)
738
Martin Pantereb995702016-07-28 01:11:04 +0000739 def test_programmatic_function_string_list_with_start(self):
Ethan Furmand9925a12014-09-16 20:35:55 -0700740 SummerMonth = Enum('SummerMonth', ['june', 'july', 'august'], start=20)
741 lst = list(SummerMonth)
742 self.assertEqual(len(lst), len(SummerMonth))
743 self.assertEqual(len(SummerMonth), 3, SummerMonth)
744 self.assertEqual(
745 [SummerMonth.june, SummerMonth.july, SummerMonth.august],
746 lst,
747 )
748 for i, month in enumerate('june july august'.split(), 20):
749 e = SummerMonth(i)
750 self.assertEqual(int(e.value), i)
751 self.assertNotEqual(e, i)
752 self.assertEqual(e.name, month)
753 self.assertIn(e, SummerMonth)
754 self.assertIs(type(e), SummerMonth)
755
Martin Pantereb995702016-07-28 01:11:04 +0000756 def test_programmatic_function_iterable(self):
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700757 SummerMonth = Enum(
758 'SummerMonth',
759 (('june', 1), ('july', 2), ('august', 3))
760 )
761 lst = list(SummerMonth)
762 self.assertEqual(len(lst), len(SummerMonth))
763 self.assertEqual(len(SummerMonth), 3, SummerMonth)
764 self.assertEqual(
765 [SummerMonth.june, SummerMonth.july, SummerMonth.august],
766 lst,
767 )
768 for i, month in enumerate('june july august'.split(), 1):
769 e = SummerMonth(i)
770 self.assertEqual(int(e.value), i)
771 self.assertNotEqual(e, i)
772 self.assertEqual(e.name, month)
773 self.assertIn(e, SummerMonth)
774 self.assertIs(type(e), SummerMonth)
775
Martin Pantereb995702016-07-28 01:11:04 +0000776 def test_programmatic_function_from_dict(self):
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700777 SummerMonth = Enum(
778 'SummerMonth',
779 OrderedDict((('june', 1), ('july', 2), ('august', 3)))
780 )
781 lst = list(SummerMonth)
782 self.assertEqual(len(lst), len(SummerMonth))
783 self.assertEqual(len(SummerMonth), 3, SummerMonth)
784 self.assertEqual(
785 [SummerMonth.june, SummerMonth.july, SummerMonth.august],
786 lst,
787 )
788 for i, month in enumerate('june july august'.split(), 1):
789 e = SummerMonth(i)
790 self.assertEqual(int(e.value), i)
791 self.assertNotEqual(e, i)
792 self.assertEqual(e.name, month)
793 self.assertIn(e, SummerMonth)
794 self.assertIs(type(e), SummerMonth)
795
Martin Pantereb995702016-07-28 01:11:04 +0000796 def test_programmatic_function_type(self):
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700797 SummerMonth = Enum('SummerMonth', 'june july august', type=int)
798 lst = list(SummerMonth)
799 self.assertEqual(len(lst), len(SummerMonth))
800 self.assertEqual(len(SummerMonth), 3, SummerMonth)
801 self.assertEqual(
802 [SummerMonth.june, SummerMonth.july, SummerMonth.august],
803 lst,
804 )
805 for i, month in enumerate('june july august'.split(), 1):
806 e = SummerMonth(i)
807 self.assertEqual(e, i)
808 self.assertEqual(e.name, month)
809 self.assertIn(e, SummerMonth)
810 self.assertIs(type(e), SummerMonth)
811
Martin Pantereb995702016-07-28 01:11:04 +0000812 def test_programmatic_function_type_with_start(self):
Ethan Furmand9925a12014-09-16 20:35:55 -0700813 SummerMonth = Enum('SummerMonth', 'june july august', type=int, start=30)
814 lst = list(SummerMonth)
815 self.assertEqual(len(lst), len(SummerMonth))
816 self.assertEqual(len(SummerMonth), 3, SummerMonth)
817 self.assertEqual(
818 [SummerMonth.june, SummerMonth.july, SummerMonth.august],
819 lst,
820 )
821 for i, month in enumerate('june july august'.split(), 30):
822 e = SummerMonth(i)
823 self.assertEqual(e, i)
824 self.assertEqual(e.name, month)
825 self.assertIn(e, SummerMonth)
826 self.assertIs(type(e), SummerMonth)
827
Martin Pantereb995702016-07-28 01:11:04 +0000828 def test_programmatic_function_type_from_subclass(self):
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700829 SummerMonth = IntEnum('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(e, i)
840 self.assertEqual(e.name, month)
841 self.assertIn(e, SummerMonth)
842 self.assertIs(type(e), SummerMonth)
843
Martin Pantereb995702016-07-28 01:11:04 +0000844 def test_programmatic_function_type_from_subclass_with_start(self):
Ethan Furmand9925a12014-09-16 20:35:55 -0700845 SummerMonth = IntEnum('SummerMonth', 'june july august', start=40)
846 lst = list(SummerMonth)
847 self.assertEqual(len(lst), len(SummerMonth))
848 self.assertEqual(len(SummerMonth), 3, SummerMonth)
849 self.assertEqual(
850 [SummerMonth.june, SummerMonth.july, SummerMonth.august],
851 lst,
852 )
853 for i, month in enumerate('june july august'.split(), 40):
854 e = SummerMonth(i)
855 self.assertEqual(e, i)
856 self.assertEqual(e.name, month)
857 self.assertIn(e, SummerMonth)
858 self.assertIs(type(e), SummerMonth)
859
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700860 def test_subclassing(self):
861 if isinstance(Name, Exception):
862 raise Name
863 self.assertEqual(Name.BDFL, 'Guido van Rossum')
864 self.assertTrue(Name.BDFL, Name('Guido van Rossum'))
865 self.assertIs(Name.BDFL, getattr(Name, 'BDFL'))
Ethan Furman2ddb39a2014-02-06 17:28:50 -0800866 test_pickle_dump_load(self.assertIs, Name.BDFL)
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700867
868 def test_extending(self):
869 class Color(Enum):
870 red = 1
871 green = 2
872 blue = 3
873 with self.assertRaises(TypeError):
874 class MoreColor(Color):
875 cyan = 4
876 magenta = 5
877 yellow = 6
878
879 def test_exclude_methods(self):
880 class whatever(Enum):
881 this = 'that'
882 these = 'those'
883 def really(self):
884 return 'no, not %s' % self.value
885 self.assertIsNot(type(whatever.really), whatever)
886 self.assertEqual(whatever.this.really(), 'no, not that')
887
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700888 def test_wrong_inheritance_order(self):
889 with self.assertRaises(TypeError):
890 class Wrong(Enum, str):
891 NotHere = 'error before this point'
892
893 def test_intenum_transitivity(self):
894 class number(IntEnum):
895 one = 1
896 two = 2
897 three = 3
898 class numero(IntEnum):
899 uno = 1
900 dos = 2
901 tres = 3
902 self.assertEqual(number.one, numero.uno)
903 self.assertEqual(number.two, numero.dos)
904 self.assertEqual(number.three, numero.tres)
905
906 def test_wrong_enum_in_call(self):
907 class Monochrome(Enum):
908 black = 0
909 white = 1
910 class Gender(Enum):
911 male = 0
912 female = 1
913 self.assertRaises(ValueError, Monochrome, Gender.male)
914
915 def test_wrong_enum_in_mixed_call(self):
916 class Monochrome(IntEnum):
917 black = 0
918 white = 1
919 class Gender(Enum):
920 male = 0
921 female = 1
922 self.assertRaises(ValueError, Monochrome, Gender.male)
923
924 def test_mixed_enum_in_call_1(self):
925 class Monochrome(IntEnum):
926 black = 0
927 white = 1
928 class Gender(IntEnum):
929 male = 0
930 female = 1
931 self.assertIs(Monochrome(Gender.female), Monochrome.white)
932
933 def test_mixed_enum_in_call_2(self):
934 class Monochrome(Enum):
935 black = 0
936 white = 1
937 class Gender(IntEnum):
938 male = 0
939 female = 1
940 self.assertIs(Monochrome(Gender.male), Monochrome.black)
941
942 def test_flufl_enum(self):
943 class Fluflnum(Enum):
944 def __int__(self):
945 return int(self.value)
946 class MailManOptions(Fluflnum):
947 option1 = 1
948 option2 = 2
949 option3 = 3
950 self.assertEqual(int(MailManOptions.option1), 1)
951
Ethan Furman5e5a8232013-08-04 08:42:23 -0700952 def test_introspection(self):
953 class Number(IntEnum):
954 one = 100
955 two = 200
956 self.assertIs(Number.one._member_type_, int)
957 self.assertIs(Number._member_type_, int)
958 class String(str, Enum):
959 yarn = 'soft'
960 rope = 'rough'
961 wire = 'hard'
962 self.assertIs(String.yarn._member_type_, str)
963 self.assertIs(String._member_type_, str)
964 class Plain(Enum):
965 vanilla = 'white'
966 one = 1
967 self.assertIs(Plain.vanilla._member_type_, object)
968 self.assertIs(Plain._member_type_, object)
969
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700970 def test_no_such_enum_member(self):
971 class Color(Enum):
972 red = 1
973 green = 2
974 blue = 3
975 with self.assertRaises(ValueError):
976 Color(4)
977 with self.assertRaises(KeyError):
978 Color['chartreuse']
979
980 def test_new_repr(self):
981 class Color(Enum):
982 red = 1
983 green = 2
984 blue = 3
985 def __repr__(self):
986 return "don't you just love shades of %s?" % self.name
987 self.assertEqual(
988 repr(Color.blue),
989 "don't you just love shades of blue?",
990 )
991
992 def test_inherited_repr(self):
993 class MyEnum(Enum):
994 def __repr__(self):
995 return "My name is %s." % self.name
996 class MyIntEnum(int, MyEnum):
997 this = 1
998 that = 2
999 theother = 3
1000 self.assertEqual(repr(MyIntEnum.that), "My name is that.")
1001
1002 def test_multiple_mixin_mro(self):
1003 class auto_enum(type(Enum)):
1004 def __new__(metacls, cls, bases, classdict):
1005 temp = type(classdict)()
1006 names = set(classdict._member_names)
1007 i = 0
1008 for k in classdict._member_names:
1009 v = classdict[k]
1010 if v is Ellipsis:
1011 v = i
1012 else:
1013 i = v
1014 i += 1
1015 temp[k] = v
1016 for k, v in classdict.items():
1017 if k not in names:
1018 temp[k] = v
1019 return super(auto_enum, metacls).__new__(
1020 metacls, cls, bases, temp)
1021
1022 class AutoNumberedEnum(Enum, metaclass=auto_enum):
1023 pass
1024
1025 class AutoIntEnum(IntEnum, metaclass=auto_enum):
1026 pass
1027
1028 class TestAutoNumber(AutoNumberedEnum):
1029 a = ...
1030 b = 3
1031 c = ...
1032
1033 class TestAutoInt(AutoIntEnum):
1034 a = ...
1035 b = 3
1036 c = ...
1037
1038 def test_subclasses_with_getnewargs(self):
1039 class NamedInt(int):
Ethan Furman2ddb39a2014-02-06 17:28:50 -08001040 __qualname__ = 'NamedInt' # needed for pickle protocol 4
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001041 def __new__(cls, *args):
1042 _args = args
1043 name, *args = args
1044 if len(args) == 0:
1045 raise TypeError("name and value must be specified")
1046 self = int.__new__(cls, *args)
1047 self._intname = name
1048 self._args = _args
1049 return self
1050 def __getnewargs__(self):
1051 return self._args
1052 @property
1053 def __name__(self):
1054 return self._intname
1055 def __repr__(self):
1056 # repr() is updated to include the name and type info
1057 return "{}({!r}, {})".format(type(self).__name__,
1058 self.__name__,
1059 int.__repr__(self))
1060 def __str__(self):
1061 # str() is unchanged, even if it relies on the repr() fallback
1062 base = int
1063 base_str = base.__str__
1064 if base_str.__objclass__ is object:
1065 return base.__repr__(self)
1066 return base_str(self)
1067 # for simplicity, we only define one operator that
1068 # propagates expressions
1069 def __add__(self, other):
1070 temp = int(self) + int( other)
1071 if isinstance(self, NamedInt) and isinstance(other, NamedInt):
1072 return NamedInt(
1073 '({0} + {1})'.format(self.__name__, other.__name__),
1074 temp )
1075 else:
1076 return temp
1077
1078 class NEI(NamedInt, Enum):
Ethan Furman2ddb39a2014-02-06 17:28:50 -08001079 __qualname__ = 'NEI' # needed for pickle protocol 4
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001080 x = ('the-x', 1)
1081 y = ('the-y', 2)
1082
Ethan Furman2aa27322013-07-19 19:35:56 -07001083
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001084 self.assertIs(NEI.__new__, Enum.__new__)
1085 self.assertEqual(repr(NEI.x + NEI.y), "NamedInt('(the-x + the-y)', 3)")
1086 globals()['NamedInt'] = NamedInt
1087 globals()['NEI'] = NEI
1088 NI5 = NamedInt('test', 5)
1089 self.assertEqual(NI5, 5)
Ethan Furman2ddb39a2014-02-06 17:28:50 -08001090 test_pickle_dump_load(self.assertEqual, NI5, 5)
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001091 self.assertEqual(NEI.y.value, 2)
Ethan Furman2ddb39a2014-02-06 17:28:50 -08001092 test_pickle_dump_load(self.assertIs, NEI.y)
Ethan Furmandc870522014-02-18 12:37:12 -08001093 test_pickle_dump_load(self.assertIs, NEI)
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001094
Ethan Furmanca1b7942014-02-08 11:36:27 -08001095 def test_subclasses_with_getnewargs_ex(self):
1096 class NamedInt(int):
1097 __qualname__ = 'NamedInt' # needed for pickle protocol 4
1098 def __new__(cls, *args):
1099 _args = args
1100 name, *args = args
1101 if len(args) == 0:
1102 raise TypeError("name and value must be specified")
1103 self = int.__new__(cls, *args)
1104 self._intname = name
1105 self._args = _args
1106 return self
1107 def __getnewargs_ex__(self):
1108 return self._args, {}
1109 @property
1110 def __name__(self):
1111 return self._intname
1112 def __repr__(self):
1113 # repr() is updated to include the name and type info
1114 return "{}({!r}, {})".format(type(self).__name__,
1115 self.__name__,
1116 int.__repr__(self))
1117 def __str__(self):
1118 # str() is unchanged, even if it relies on the repr() fallback
1119 base = int
1120 base_str = base.__str__
1121 if base_str.__objclass__ is object:
1122 return base.__repr__(self)
1123 return base_str(self)
1124 # for simplicity, we only define one operator that
1125 # propagates expressions
1126 def __add__(self, other):
1127 temp = int(self) + int( other)
1128 if isinstance(self, NamedInt) and isinstance(other, NamedInt):
1129 return NamedInt(
1130 '({0} + {1})'.format(self.__name__, other.__name__),
1131 temp )
1132 else:
1133 return temp
1134
1135 class NEI(NamedInt, Enum):
1136 __qualname__ = 'NEI' # needed for pickle protocol 4
1137 x = ('the-x', 1)
1138 y = ('the-y', 2)
1139
1140
1141 self.assertIs(NEI.__new__, Enum.__new__)
1142 self.assertEqual(repr(NEI.x + NEI.y), "NamedInt('(the-x + the-y)', 3)")
1143 globals()['NamedInt'] = NamedInt
1144 globals()['NEI'] = NEI
1145 NI5 = NamedInt('test', 5)
1146 self.assertEqual(NI5, 5)
Serhiy Storchakae50e7802015-03-31 16:56:49 +03001147 test_pickle_dump_load(self.assertEqual, NI5, 5)
Ethan Furmanca1b7942014-02-08 11:36:27 -08001148 self.assertEqual(NEI.y.value, 2)
Serhiy Storchakae50e7802015-03-31 16:56:49 +03001149 test_pickle_dump_load(self.assertIs, NEI.y)
Ethan Furmandc870522014-02-18 12:37:12 -08001150 test_pickle_dump_load(self.assertIs, NEI)
Ethan Furmanca1b7942014-02-08 11:36:27 -08001151
1152 def test_subclasses_with_reduce(self):
1153 class NamedInt(int):
1154 __qualname__ = 'NamedInt' # needed for pickle protocol 4
1155 def __new__(cls, *args):
1156 _args = args
1157 name, *args = args
1158 if len(args) == 0:
1159 raise TypeError("name and value must be specified")
1160 self = int.__new__(cls, *args)
1161 self._intname = name
1162 self._args = _args
1163 return self
1164 def __reduce__(self):
1165 return self.__class__, self._args
1166 @property
1167 def __name__(self):
1168 return self._intname
1169 def __repr__(self):
1170 # repr() is updated to include the name and type info
1171 return "{}({!r}, {})".format(type(self).__name__,
1172 self.__name__,
1173 int.__repr__(self))
1174 def __str__(self):
1175 # str() is unchanged, even if it relies on the repr() fallback
1176 base = int
1177 base_str = base.__str__
1178 if base_str.__objclass__ is object:
1179 return base.__repr__(self)
1180 return base_str(self)
1181 # for simplicity, we only define one operator that
1182 # propagates expressions
1183 def __add__(self, other):
1184 temp = int(self) + int( other)
1185 if isinstance(self, NamedInt) and isinstance(other, NamedInt):
1186 return NamedInt(
1187 '({0} + {1})'.format(self.__name__, other.__name__),
1188 temp )
1189 else:
1190 return temp
1191
1192 class NEI(NamedInt, Enum):
1193 __qualname__ = 'NEI' # needed for pickle protocol 4
1194 x = ('the-x', 1)
1195 y = ('the-y', 2)
1196
1197
1198 self.assertIs(NEI.__new__, Enum.__new__)
1199 self.assertEqual(repr(NEI.x + NEI.y), "NamedInt('(the-x + the-y)', 3)")
1200 globals()['NamedInt'] = NamedInt
1201 globals()['NEI'] = NEI
1202 NI5 = NamedInt('test', 5)
1203 self.assertEqual(NI5, 5)
1204 test_pickle_dump_load(self.assertEqual, NI5, 5)
1205 self.assertEqual(NEI.y.value, 2)
1206 test_pickle_dump_load(self.assertIs, NEI.y)
Ethan Furmandc870522014-02-18 12:37:12 -08001207 test_pickle_dump_load(self.assertIs, NEI)
Ethan Furmanca1b7942014-02-08 11:36:27 -08001208
1209 def test_subclasses_with_reduce_ex(self):
1210 class NamedInt(int):
1211 __qualname__ = 'NamedInt' # needed for pickle protocol 4
1212 def __new__(cls, *args):
1213 _args = args
1214 name, *args = args
1215 if len(args) == 0:
1216 raise TypeError("name and value must be specified")
1217 self = int.__new__(cls, *args)
1218 self._intname = name
1219 self._args = _args
1220 return self
1221 def __reduce_ex__(self, proto):
1222 return self.__class__, self._args
1223 @property
1224 def __name__(self):
1225 return self._intname
1226 def __repr__(self):
1227 # repr() is updated to include the name and type info
1228 return "{}({!r}, {})".format(type(self).__name__,
1229 self.__name__,
1230 int.__repr__(self))
1231 def __str__(self):
1232 # str() is unchanged, even if it relies on the repr() fallback
1233 base = int
1234 base_str = base.__str__
1235 if base_str.__objclass__ is object:
1236 return base.__repr__(self)
1237 return base_str(self)
1238 # for simplicity, we only define one operator that
1239 # propagates expressions
1240 def __add__(self, other):
1241 temp = int(self) + int( other)
1242 if isinstance(self, NamedInt) and isinstance(other, NamedInt):
1243 return NamedInt(
1244 '({0} + {1})'.format(self.__name__, other.__name__),
1245 temp )
1246 else:
1247 return temp
1248
1249 class NEI(NamedInt, Enum):
1250 __qualname__ = 'NEI' # needed for pickle protocol 4
1251 x = ('the-x', 1)
1252 y = ('the-y', 2)
1253
1254
1255 self.assertIs(NEI.__new__, Enum.__new__)
1256 self.assertEqual(repr(NEI.x + NEI.y), "NamedInt('(the-x + the-y)', 3)")
1257 globals()['NamedInt'] = NamedInt
1258 globals()['NEI'] = NEI
1259 NI5 = NamedInt('test', 5)
1260 self.assertEqual(NI5, 5)
1261 test_pickle_dump_load(self.assertEqual, NI5, 5)
1262 self.assertEqual(NEI.y.value, 2)
1263 test_pickle_dump_load(self.assertIs, NEI.y)
Ethan Furmandc870522014-02-18 12:37:12 -08001264 test_pickle_dump_load(self.assertIs, NEI)
Ethan Furmanca1b7942014-02-08 11:36:27 -08001265
Ethan Furmandc870522014-02-18 12:37:12 -08001266 def test_subclasses_without_direct_pickle_support(self):
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001267 class NamedInt(int):
Ethan Furman2ddb39a2014-02-06 17:28:50 -08001268 __qualname__ = 'NamedInt'
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001269 def __new__(cls, *args):
1270 _args = args
1271 name, *args = args
1272 if len(args) == 0:
1273 raise TypeError("name and value must be specified")
1274 self = int.__new__(cls, *args)
1275 self._intname = name
1276 self._args = _args
1277 return self
1278 @property
1279 def __name__(self):
1280 return self._intname
1281 def __repr__(self):
1282 # repr() is updated to include the name and type info
1283 return "{}({!r}, {})".format(type(self).__name__,
1284 self.__name__,
1285 int.__repr__(self))
1286 def __str__(self):
1287 # str() is unchanged, even if it relies on the repr() fallback
1288 base = int
1289 base_str = base.__str__
1290 if base_str.__objclass__ is object:
1291 return base.__repr__(self)
1292 return base_str(self)
1293 # for simplicity, we only define one operator that
1294 # propagates expressions
1295 def __add__(self, other):
1296 temp = int(self) + int( other)
1297 if isinstance(self, NamedInt) and isinstance(other, NamedInt):
1298 return NamedInt(
1299 '({0} + {1})'.format(self.__name__, other.__name__),
1300 temp )
1301 else:
1302 return temp
1303
1304 class NEI(NamedInt, Enum):
Ethan Furman2ddb39a2014-02-06 17:28:50 -08001305 __qualname__ = 'NEI'
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001306 x = ('the-x', 1)
1307 y = ('the-y', 2)
1308
1309 self.assertIs(NEI.__new__, Enum.__new__)
1310 self.assertEqual(repr(NEI.x + NEI.y), "NamedInt('(the-x + the-y)', 3)")
1311 globals()['NamedInt'] = NamedInt
1312 globals()['NEI'] = NEI
1313 NI5 = NamedInt('test', 5)
1314 self.assertEqual(NI5, 5)
1315 self.assertEqual(NEI.y.value, 2)
Ethan Furman2ddb39a2014-02-06 17:28:50 -08001316 test_pickle_exception(self.assertRaises, TypeError, NEI.x)
1317 test_pickle_exception(self.assertRaises, PicklingError, NEI)
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001318
Ethan Furmandc870522014-02-18 12:37:12 -08001319 def test_subclasses_without_direct_pickle_support_using_name(self):
1320 class NamedInt(int):
1321 __qualname__ = 'NamedInt'
1322 def __new__(cls, *args):
1323 _args = args
1324 name, *args = args
1325 if len(args) == 0:
1326 raise TypeError("name and value must be specified")
1327 self = int.__new__(cls, *args)
1328 self._intname = name
1329 self._args = _args
1330 return self
1331 @property
1332 def __name__(self):
1333 return self._intname
1334 def __repr__(self):
1335 # repr() is updated to include the name and type info
1336 return "{}({!r}, {})".format(type(self).__name__,
1337 self.__name__,
1338 int.__repr__(self))
1339 def __str__(self):
1340 # str() is unchanged, even if it relies on the repr() fallback
1341 base = int
1342 base_str = base.__str__
1343 if base_str.__objclass__ is object:
1344 return base.__repr__(self)
1345 return base_str(self)
1346 # for simplicity, we only define one operator that
1347 # propagates expressions
1348 def __add__(self, other):
1349 temp = int(self) + int( other)
1350 if isinstance(self, NamedInt) and isinstance(other, NamedInt):
1351 return NamedInt(
1352 '({0} + {1})'.format(self.__name__, other.__name__),
1353 temp )
1354 else:
1355 return temp
1356
1357 class NEI(NamedInt, Enum):
1358 __qualname__ = 'NEI'
1359 x = ('the-x', 1)
1360 y = ('the-y', 2)
1361 def __reduce_ex__(self, proto):
1362 return getattr, (self.__class__, self._name_)
1363
1364 self.assertIs(NEI.__new__, Enum.__new__)
1365 self.assertEqual(repr(NEI.x + NEI.y), "NamedInt('(the-x + the-y)', 3)")
1366 globals()['NamedInt'] = NamedInt
1367 globals()['NEI'] = NEI
1368 NI5 = NamedInt('test', 5)
1369 self.assertEqual(NI5, 5)
1370 self.assertEqual(NEI.y.value, 2)
1371 test_pickle_dump_load(self.assertIs, NEI.y)
1372 test_pickle_dump_load(self.assertIs, NEI)
1373
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001374 def test_tuple_subclass(self):
1375 class SomeTuple(tuple, Enum):
Ethan Furman2ddb39a2014-02-06 17:28:50 -08001376 __qualname__ = 'SomeTuple' # needed for pickle protocol 4
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001377 first = (1, 'for the money')
1378 second = (2, 'for the show')
1379 third = (3, 'for the music')
1380 self.assertIs(type(SomeTuple.first), SomeTuple)
1381 self.assertIsInstance(SomeTuple.second, tuple)
1382 self.assertEqual(SomeTuple.third, (3, 'for the music'))
1383 globals()['SomeTuple'] = SomeTuple
Ethan Furman2ddb39a2014-02-06 17:28:50 -08001384 test_pickle_dump_load(self.assertIs, SomeTuple.first)
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001385
1386 def test_duplicate_values_give_unique_enum_items(self):
1387 class AutoNumber(Enum):
1388 first = ()
1389 second = ()
1390 third = ()
1391 def __new__(cls):
1392 value = len(cls.__members__) + 1
1393 obj = object.__new__(cls)
Ethan Furman520ad572013-07-19 19:47:21 -07001394 obj._value_ = value
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001395 return obj
1396 def __int__(self):
Ethan Furman520ad572013-07-19 19:47:21 -07001397 return int(self._value_)
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001398 self.assertEqual(
1399 list(AutoNumber),
1400 [AutoNumber.first, AutoNumber.second, AutoNumber.third],
1401 )
1402 self.assertEqual(int(AutoNumber.second), 2)
Ethan Furman2aa27322013-07-19 19:35:56 -07001403 self.assertEqual(AutoNumber.third.value, 3)
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001404 self.assertIs(AutoNumber(1), AutoNumber.first)
1405
1406 def test_inherited_new_from_enhanced_enum(self):
1407 class AutoNumber(Enum):
1408 def __new__(cls):
1409 value = len(cls.__members__) + 1
1410 obj = object.__new__(cls)
Ethan Furman520ad572013-07-19 19:47:21 -07001411 obj._value_ = value
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001412 return obj
1413 def __int__(self):
Ethan Furman520ad572013-07-19 19:47:21 -07001414 return int(self._value_)
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001415 class Color(AutoNumber):
1416 red = ()
1417 green = ()
1418 blue = ()
1419 self.assertEqual(list(Color), [Color.red, Color.green, Color.blue])
1420 self.assertEqual(list(map(int, Color)), [1, 2, 3])
1421
1422 def test_inherited_new_from_mixed_enum(self):
1423 class AutoNumber(IntEnum):
1424 def __new__(cls):
1425 value = len(cls.__members__) + 1
1426 obj = int.__new__(cls, value)
Ethan Furman520ad572013-07-19 19:47:21 -07001427 obj._value_ = value
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001428 return obj
1429 class Color(AutoNumber):
1430 red = ()
1431 green = ()
1432 blue = ()
1433 self.assertEqual(list(Color), [Color.red, Color.green, Color.blue])
1434 self.assertEqual(list(map(int, Color)), [1, 2, 3])
1435
Ethan Furmanbe3c2fe2013-11-13 14:25:45 -08001436 def test_equality(self):
1437 class AlwaysEqual:
1438 def __eq__(self, other):
1439 return True
1440 class OrdinaryEnum(Enum):
1441 a = 1
1442 self.assertEqual(AlwaysEqual(), OrdinaryEnum.a)
1443 self.assertEqual(OrdinaryEnum.a, AlwaysEqual())
1444
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001445 def test_ordered_mixin(self):
1446 class OrderedEnum(Enum):
1447 def __ge__(self, other):
1448 if self.__class__ is other.__class__:
Ethan Furman520ad572013-07-19 19:47:21 -07001449 return self._value_ >= other._value_
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001450 return NotImplemented
1451 def __gt__(self, other):
1452 if self.__class__ is other.__class__:
Ethan Furman520ad572013-07-19 19:47:21 -07001453 return self._value_ > other._value_
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001454 return NotImplemented
1455 def __le__(self, other):
1456 if self.__class__ is other.__class__:
Ethan Furman520ad572013-07-19 19:47:21 -07001457 return self._value_ <= other._value_
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001458 return NotImplemented
1459 def __lt__(self, other):
1460 if self.__class__ is other.__class__:
Ethan Furman520ad572013-07-19 19:47:21 -07001461 return self._value_ < other._value_
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001462 return NotImplemented
1463 class Grade(OrderedEnum):
1464 A = 5
1465 B = 4
1466 C = 3
1467 D = 2
1468 F = 1
1469 self.assertGreater(Grade.A, Grade.B)
1470 self.assertLessEqual(Grade.F, Grade.C)
1471 self.assertLess(Grade.D, Grade.A)
1472 self.assertGreaterEqual(Grade.B, Grade.B)
Ethan Furmanbe3c2fe2013-11-13 14:25:45 -08001473 self.assertEqual(Grade.B, Grade.B)
1474 self.assertNotEqual(Grade.C, Grade.D)
Ethan Furman520ad572013-07-19 19:47:21 -07001475
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001476 def test_extending2(self):
1477 class Shade(Enum):
1478 def shade(self):
1479 print(self.name)
1480 class Color(Shade):
1481 red = 1
1482 green = 2
1483 blue = 3
1484 with self.assertRaises(TypeError):
1485 class MoreColor(Color):
1486 cyan = 4
1487 magenta = 5
1488 yellow = 6
1489
1490 def test_extending3(self):
1491 class Shade(Enum):
1492 def shade(self):
1493 return self.name
1494 class Color(Shade):
1495 def hex(self):
1496 return '%s hexlified!' % self.value
1497 class MoreColor(Color):
1498 cyan = 4
1499 magenta = 5
1500 yellow = 6
1501 self.assertEqual(MoreColor.magenta.hex(), '5 hexlified!')
1502
1503
1504 def test_no_duplicates(self):
1505 class UniqueEnum(Enum):
1506 def __init__(self, *args):
1507 cls = self.__class__
1508 if any(self.value == e.value for e in cls):
1509 a = self.name
1510 e = cls(self.value).name
1511 raise ValueError(
1512 "aliases not allowed in UniqueEnum: %r --> %r"
1513 % (a, e)
1514 )
1515 class Color(UniqueEnum):
1516 red = 1
1517 green = 2
1518 blue = 3
1519 with self.assertRaises(ValueError):
1520 class Color(UniqueEnum):
1521 red = 1
1522 green = 2
1523 blue = 3
1524 grene = 2
1525
1526 def test_init(self):
1527 class Planet(Enum):
1528 MERCURY = (3.303e+23, 2.4397e6)
1529 VENUS = (4.869e+24, 6.0518e6)
1530 EARTH = (5.976e+24, 6.37814e6)
1531 MARS = (6.421e+23, 3.3972e6)
1532 JUPITER = (1.9e+27, 7.1492e7)
1533 SATURN = (5.688e+26, 6.0268e7)
1534 URANUS = (8.686e+25, 2.5559e7)
1535 NEPTUNE = (1.024e+26, 2.4746e7)
1536 def __init__(self, mass, radius):
1537 self.mass = mass # in kilograms
1538 self.radius = radius # in meters
1539 @property
1540 def surface_gravity(self):
1541 # universal gravitational constant (m3 kg-1 s-2)
1542 G = 6.67300E-11
1543 return G * self.mass / (self.radius * self.radius)
1544 self.assertEqual(round(Planet.EARTH.surface_gravity, 2), 9.80)
1545 self.assertEqual(Planet.EARTH.value, (5.976e+24, 6.37814e6))
1546
Ethan Furman2aa27322013-07-19 19:35:56 -07001547 def test_nonhash_value(self):
1548 class AutoNumberInAList(Enum):
1549 def __new__(cls):
1550 value = [len(cls.__members__) + 1]
1551 obj = object.__new__(cls)
Ethan Furman520ad572013-07-19 19:47:21 -07001552 obj._value_ = value
Ethan Furman2aa27322013-07-19 19:35:56 -07001553 return obj
1554 class ColorInAList(AutoNumberInAList):
1555 red = ()
1556 green = ()
1557 blue = ()
1558 self.assertEqual(list(ColorInAList), [ColorInAList.red, ColorInAList.green, ColorInAList.blue])
Ethan Furman1a162882013-10-16 19:09:31 -07001559 for enum, value in zip(ColorInAList, range(3)):
1560 value += 1
1561 self.assertEqual(enum.value, [value])
1562 self.assertIs(ColorInAList([value]), enum)
Ethan Furman2aa27322013-07-19 19:35:56 -07001563
Ethan Furmanb41803e2013-07-25 13:50:45 -07001564 def test_conflicting_types_resolved_in_new(self):
1565 class LabelledIntEnum(int, Enum):
1566 def __new__(cls, *args):
1567 value, label = args
1568 obj = int.__new__(cls, value)
1569 obj.label = label
1570 obj._value_ = value
1571 return obj
1572
1573 class LabelledList(LabelledIntEnum):
1574 unprocessed = (1, "Unprocessed")
1575 payment_complete = (2, "Payment Complete")
1576
1577 self.assertEqual(list(LabelledList), [LabelledList.unprocessed, LabelledList.payment_complete])
1578 self.assertEqual(LabelledList.unprocessed, 1)
1579 self.assertEqual(LabelledList(1), LabelledList.unprocessed)
Ethan Furman2aa27322013-07-19 19:35:56 -07001580
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001581
Ethan Furmane8e61272016-08-20 07:19:31 -07001582class TestOrder(unittest.TestCase):
1583
1584 def test_same_members(self):
1585 class Color(Enum):
1586 _order_ = 'red green blue'
1587 red = 1
1588 green = 2
1589 blue = 3
1590
1591 def test_same_members_with_aliases(self):
1592 class Color(Enum):
1593 _order_ = 'red green blue'
1594 red = 1
1595 green = 2
1596 blue = 3
1597 verde = green
1598
1599 def test_same_members_wrong_order(self):
1600 with self.assertRaisesRegex(TypeError, 'member order does not match _order_'):
1601 class Color(Enum):
1602 _order_ = 'red green blue'
1603 red = 1
1604 blue = 3
1605 green = 2
1606
1607 def test_order_has_extra_members(self):
1608 with self.assertRaisesRegex(TypeError, 'member order does not match _order_'):
1609 class Color(Enum):
1610 _order_ = 'red green blue purple'
1611 red = 1
1612 green = 2
1613 blue = 3
1614
1615 def test_order_has_extra_members_with_aliases(self):
1616 with self.assertRaisesRegex(TypeError, 'member order does not match _order_'):
1617 class Color(Enum):
1618 _order_ = 'red green blue purple'
1619 red = 1
1620 green = 2
1621 blue = 3
1622 verde = green
1623
1624 def test_enum_has_extra_members(self):
1625 with self.assertRaisesRegex(TypeError, 'member order does not match _order_'):
1626 class Color(Enum):
1627 _order_ = 'red green blue'
1628 red = 1
1629 green = 2
1630 blue = 3
1631 purple = 4
1632
1633 def test_enum_has_extra_members_with_aliases(self):
1634 with self.assertRaisesRegex(TypeError, 'member order does not match _order_'):
1635 class Color(Enum):
1636 _order_ = 'red green blue'
1637 red = 1
1638 green = 2
1639 blue = 3
1640 purple = 4
1641 verde = green
1642
1643
Ethan Furman65a5a472016-09-01 23:55:19 -07001644class TestFlag(unittest.TestCase):
Ethan Furmanee47e5c2016-08-31 00:12:15 -07001645 """Tests of the Flags."""
1646
Ethan Furman65a5a472016-09-01 23:55:19 -07001647 class Perm(Flag):
Ethan Furmanee47e5c2016-08-31 00:12:15 -07001648 R, W, X = 4, 2, 1
1649
Ethan Furman65a5a472016-09-01 23:55:19 -07001650 class Open(Flag):
Ethan Furmanee47e5c2016-08-31 00:12:15 -07001651 RO = 0
1652 WO = 1
1653 RW = 2
1654 AC = 3
1655 CE = 1<<19
1656
1657 def test_str(self):
1658 Perm = self.Perm
1659 self.assertEqual(str(Perm.R), 'Perm.R')
1660 self.assertEqual(str(Perm.W), 'Perm.W')
1661 self.assertEqual(str(Perm.X), 'Perm.X')
1662 self.assertEqual(str(Perm.R | Perm.W), 'Perm.R|W')
1663 self.assertEqual(str(Perm.R | Perm.W | Perm.X), 'Perm.R|W|X')
1664 self.assertEqual(str(Perm(0)), 'Perm.0')
1665 self.assertEqual(str(~Perm.R), 'Perm.W|X')
1666 self.assertEqual(str(~Perm.W), 'Perm.R|X')
1667 self.assertEqual(str(~Perm.X), 'Perm.R|W')
1668 self.assertEqual(str(~(Perm.R | Perm.W)), 'Perm.X')
1669 self.assertEqual(str(~(Perm.R | Perm.W | Perm.X)), 'Perm.0')
1670 self.assertEqual(str(Perm(~0)), 'Perm.R|W|X')
1671
1672 Open = self.Open
1673 self.assertEqual(str(Open.RO), 'Open.RO')
1674 self.assertEqual(str(Open.WO), 'Open.WO')
1675 self.assertEqual(str(Open.AC), 'Open.AC')
1676 self.assertEqual(str(Open.RO | Open.CE), 'Open.CE')
1677 self.assertEqual(str(Open.WO | Open.CE), 'Open.CE|WO')
1678 self.assertEqual(str(~Open.RO), 'Open.CE|AC')
1679 self.assertEqual(str(~Open.WO), 'Open.CE|RW')
1680 self.assertEqual(str(~Open.AC), 'Open.CE')
1681 self.assertEqual(str(~(Open.RO | Open.CE)), 'Open.AC')
1682 self.assertEqual(str(~(Open.WO | Open.CE)), 'Open.RW')
1683
1684 def test_repr(self):
1685 Perm = self.Perm
1686 self.assertEqual(repr(Perm.R), '<Perm.R: 4>')
1687 self.assertEqual(repr(Perm.W), '<Perm.W: 2>')
1688 self.assertEqual(repr(Perm.X), '<Perm.X: 1>')
1689 self.assertEqual(repr(Perm.R | Perm.W), '<Perm.R|W: 6>')
1690 self.assertEqual(repr(Perm.R | Perm.W | Perm.X), '<Perm.R|W|X: 7>')
Ethan Furman27682d22016-09-04 11:39:01 -07001691 self.assertEqual(repr(Perm(0)), '<Perm.0: 0>')
Ethan Furmanee47e5c2016-08-31 00:12:15 -07001692 self.assertEqual(repr(~Perm.R), '<Perm.W|X: 3>')
1693 self.assertEqual(repr(~Perm.W), '<Perm.R|X: 5>')
1694 self.assertEqual(repr(~Perm.X), '<Perm.R|W: 6>')
1695 self.assertEqual(repr(~(Perm.R | Perm.W)), '<Perm.X: 1>')
Ethan Furman27682d22016-09-04 11:39:01 -07001696 self.assertEqual(repr(~(Perm.R | Perm.W | Perm.X)), '<Perm.0: 0>')
Ethan Furmanee47e5c2016-08-31 00:12:15 -07001697 self.assertEqual(repr(Perm(~0)), '<Perm.R|W|X: 7>')
1698
1699 Open = self.Open
1700 self.assertEqual(repr(Open.RO), '<Open.RO: 0>')
1701 self.assertEqual(repr(Open.WO), '<Open.WO: 1>')
1702 self.assertEqual(repr(Open.AC), '<Open.AC: 3>')
1703 self.assertEqual(repr(Open.RO | Open.CE), '<Open.CE: 524288>')
1704 self.assertEqual(repr(Open.WO | Open.CE), '<Open.CE|WO: 524289>')
1705 self.assertEqual(repr(~Open.RO), '<Open.CE|AC: 524291>')
1706 self.assertEqual(repr(~Open.WO), '<Open.CE|RW: 524290>')
1707 self.assertEqual(repr(~Open.AC), '<Open.CE: 524288>')
1708 self.assertEqual(repr(~(Open.RO | Open.CE)), '<Open.AC: 3>')
1709 self.assertEqual(repr(~(Open.WO | Open.CE)), '<Open.RW: 2>')
1710
1711 def test_or(self):
1712 Perm = self.Perm
1713 for i in Perm:
1714 for j in Perm:
1715 self.assertEqual((i | j), Perm(i.value | j.value))
1716 self.assertEqual((i | j).value, i.value | j.value)
1717 self.assertIs(type(i | j), Perm)
1718 for i in Perm:
1719 self.assertIs(i | i, i)
1720 Open = self.Open
1721 self.assertIs(Open.RO | Open.CE, Open.CE)
1722
1723 def test_and(self):
1724 Perm = self.Perm
1725 RW = Perm.R | Perm.W
1726 RX = Perm.R | Perm.X
1727 WX = Perm.W | Perm.X
1728 RWX = Perm.R | Perm.W | Perm.X
1729 values = list(Perm) + [RW, RX, WX, RWX, Perm(0)]
1730 for i in values:
1731 for j in values:
1732 self.assertEqual((i & j).value, i.value & j.value)
1733 self.assertIs(type(i & j), Perm)
1734 for i in Perm:
1735 self.assertIs(i & i, i)
1736 self.assertIs(i & RWX, i)
1737 self.assertIs(RWX & i, i)
1738 Open = self.Open
1739 self.assertIs(Open.RO & Open.CE, Open.RO)
1740
1741 def test_xor(self):
1742 Perm = self.Perm
1743 for i in Perm:
1744 for j in Perm:
1745 self.assertEqual((i ^ j).value, i.value ^ j.value)
1746 self.assertIs(type(i ^ j), Perm)
1747 for i in Perm:
1748 self.assertIs(i ^ Perm(0), i)
1749 self.assertIs(Perm(0) ^ i, i)
1750 Open = self.Open
1751 self.assertIs(Open.RO ^ Open.CE, Open.CE)
1752 self.assertIs(Open.CE ^ Open.CE, Open.RO)
1753
1754 def test_invert(self):
1755 Perm = self.Perm
1756 RW = Perm.R | Perm.W
1757 RX = Perm.R | Perm.X
1758 WX = Perm.W | Perm.X
1759 RWX = Perm.R | Perm.W | Perm.X
1760 values = list(Perm) + [RW, RX, WX, RWX, Perm(0)]
1761 for i in values:
1762 self.assertIs(type(~i), Perm)
1763 self.assertEqual(~~i, i)
1764 for i in Perm:
1765 self.assertIs(~~i, i)
1766 Open = self.Open
1767 self.assertIs(Open.WO & ~Open.WO, Open.RO)
1768 self.assertIs((Open.WO|Open.CE) & ~Open.WO, Open.CE)
1769
Ethan Furman25d94bb2016-09-02 16:32:32 -07001770 def test_bool(self):
1771 Perm = self.Perm
1772 for f in Perm:
1773 self.assertTrue(f)
1774 Open = self.Open
1775 for f in Open:
1776 self.assertEqual(bool(f.value), bool(f))
1777
Ethan Furmanee47e5c2016-08-31 00:12:15 -07001778 def test_programatic_function_string(self):
Ethan Furman65a5a472016-09-01 23:55:19 -07001779 Perm = Flag('Perm', 'R W X')
Ethan Furmanee47e5c2016-08-31 00:12:15 -07001780 lst = list(Perm)
1781 self.assertEqual(len(lst), len(Perm))
1782 self.assertEqual(len(Perm), 3, Perm)
1783 self.assertEqual(lst, [Perm.R, Perm.W, Perm.X])
1784 for i, n in enumerate('R W X'.split()):
1785 v = 1<<i
1786 e = Perm(v)
1787 self.assertEqual(e.value, v)
1788 self.assertEqual(type(e.value), int)
1789 self.assertEqual(e.name, n)
1790 self.assertIn(e, Perm)
1791 self.assertIs(type(e), Perm)
1792
1793 def test_programatic_function_string_with_start(self):
Ethan Furman65a5a472016-09-01 23:55:19 -07001794 Perm = Flag('Perm', 'R W X', start=8)
Ethan Furmanee47e5c2016-08-31 00:12:15 -07001795 lst = list(Perm)
1796 self.assertEqual(len(lst), len(Perm))
1797 self.assertEqual(len(Perm), 3, Perm)
1798 self.assertEqual(lst, [Perm.R, Perm.W, Perm.X])
1799 for i, n in enumerate('R W X'.split()):
1800 v = 8<<i
1801 e = Perm(v)
1802 self.assertEqual(e.value, v)
1803 self.assertEqual(type(e.value), int)
1804 self.assertEqual(e.name, n)
1805 self.assertIn(e, Perm)
1806 self.assertIs(type(e), Perm)
1807
1808 def test_programatic_function_string_list(self):
Ethan Furman65a5a472016-09-01 23:55:19 -07001809 Perm = Flag('Perm', ['R', 'W', 'X'])
Ethan Furmanee47e5c2016-08-31 00:12:15 -07001810 lst = list(Perm)
1811 self.assertEqual(len(lst), len(Perm))
1812 self.assertEqual(len(Perm), 3, Perm)
1813 self.assertEqual(lst, [Perm.R, Perm.W, Perm.X])
1814 for i, n in enumerate('R W X'.split()):
1815 v = 1<<i
1816 e = Perm(v)
1817 self.assertEqual(e.value, v)
1818 self.assertEqual(type(e.value), int)
1819 self.assertEqual(e.name, n)
1820 self.assertIn(e, Perm)
1821 self.assertIs(type(e), Perm)
1822
1823 def test_programatic_function_iterable(self):
Ethan Furman65a5a472016-09-01 23:55:19 -07001824 Perm = Flag('Perm', (('R', 2), ('W', 8), ('X', 32)))
Ethan Furmanee47e5c2016-08-31 00:12:15 -07001825 lst = list(Perm)
1826 self.assertEqual(len(lst), len(Perm))
1827 self.assertEqual(len(Perm), 3, Perm)
1828 self.assertEqual(lst, [Perm.R, Perm.W, Perm.X])
1829 for i, n in enumerate('R W X'.split()):
1830 v = 1<<(2*i+1)
1831 e = Perm(v)
1832 self.assertEqual(e.value, v)
1833 self.assertEqual(type(e.value), int)
1834 self.assertEqual(e.name, n)
1835 self.assertIn(e, Perm)
1836 self.assertIs(type(e), Perm)
1837
1838 def test_programatic_function_from_dict(self):
Ethan Furman65a5a472016-09-01 23:55:19 -07001839 Perm = Flag('Perm', OrderedDict((('R', 2), ('W', 8), ('X', 32))))
Ethan Furmanee47e5c2016-08-31 00:12:15 -07001840 lst = list(Perm)
1841 self.assertEqual(len(lst), len(Perm))
1842 self.assertEqual(len(Perm), 3, Perm)
1843 self.assertEqual(lst, [Perm.R, Perm.W, Perm.X])
1844 for i, n in enumerate('R W X'.split()):
1845 v = 1<<(2*i+1)
1846 e = Perm(v)
1847 self.assertEqual(e.value, v)
1848 self.assertEqual(type(e.value), int)
1849 self.assertEqual(e.name, n)
1850 self.assertIn(e, Perm)
1851 self.assertIs(type(e), Perm)
1852
Ethan Furman65a5a472016-09-01 23:55:19 -07001853 def test_pickle(self):
1854 if isinstance(FlagStooges, Exception):
1855 raise FlagStooges
1856 test_pickle_dump_load(self.assertIs, FlagStooges.CURLY|FlagStooges.MOE)
1857 test_pickle_dump_load(self.assertIs, FlagStooges)
Ethan Furmanee47e5c2016-08-31 00:12:15 -07001858
Ethan Furman65a5a472016-09-01 23:55:19 -07001859
1860 def test_containment(self):
1861 Perm = self.Perm
1862 R, W, X = Perm
1863 RW = R | W
1864 RX = R | X
1865 WX = W | X
1866 RWX = R | W | X
1867 self.assertTrue(R in RW)
1868 self.assertTrue(R in RX)
1869 self.assertTrue(R in RWX)
1870 self.assertTrue(W in RW)
1871 self.assertTrue(W in WX)
1872 self.assertTrue(W in RWX)
1873 self.assertTrue(X in RX)
1874 self.assertTrue(X in WX)
1875 self.assertTrue(X in RWX)
1876 self.assertFalse(R in WX)
1877 self.assertFalse(W in RX)
1878 self.assertFalse(X in RW)
1879
1880class TestIntFlag(unittest.TestCase):
Ethan Furmanee47e5c2016-08-31 00:12:15 -07001881 """Tests of the IntFlags."""
1882
Ethan Furman65a5a472016-09-01 23:55:19 -07001883 class Perm(IntFlag):
Ethan Furmanee47e5c2016-08-31 00:12:15 -07001884 X = 1 << 0
1885 W = 1 << 1
1886 R = 1 << 2
1887
Ethan Furman65a5a472016-09-01 23:55:19 -07001888 class Open(IntFlag):
Ethan Furmanee47e5c2016-08-31 00:12:15 -07001889 RO = 0
1890 WO = 1
1891 RW = 2
1892 AC = 3
1893 CE = 1<<19
1894
1895 def test_str(self):
1896 Perm = self.Perm
1897 self.assertEqual(str(Perm.R), 'Perm.R')
1898 self.assertEqual(str(Perm.W), 'Perm.W')
1899 self.assertEqual(str(Perm.X), 'Perm.X')
1900 self.assertEqual(str(Perm.R | Perm.W), 'Perm.R|W')
1901 self.assertEqual(str(Perm.R | Perm.W | Perm.X), 'Perm.R|W|X')
1902 self.assertEqual(str(Perm.R | 8), 'Perm.8|R')
1903 self.assertEqual(str(Perm(0)), 'Perm.0')
1904 self.assertEqual(str(Perm(8)), 'Perm.8')
1905 self.assertEqual(str(~Perm.R), 'Perm.W|X|-8')
1906 self.assertEqual(str(~Perm.W), 'Perm.R|X|-8')
1907 self.assertEqual(str(~Perm.X), 'Perm.R|W|-8')
1908 self.assertEqual(str(~(Perm.R | Perm.W)), 'Perm.X|-8')
1909 self.assertEqual(str(~(Perm.R | Perm.W | Perm.X)), 'Perm.-8')
1910 self.assertEqual(str(~(Perm.R | 8)), 'Perm.W|X|-16')
1911 self.assertEqual(str(Perm(~0)), 'Perm.R|W|X|-8')
1912 self.assertEqual(str(Perm(~8)), 'Perm.R|W|X|-16')
1913
1914 Open = self.Open
1915 self.assertEqual(str(Open.RO), 'Open.RO')
1916 self.assertEqual(str(Open.WO), 'Open.WO')
1917 self.assertEqual(str(Open.AC), 'Open.AC')
1918 self.assertEqual(str(Open.RO | Open.CE), 'Open.CE')
1919 self.assertEqual(str(Open.WO | Open.CE), 'Open.CE|WO')
1920 self.assertEqual(str(Open(4)), 'Open.4')
1921 self.assertEqual(str(~Open.RO), 'Open.CE|AC|-524292')
1922 self.assertEqual(str(~Open.WO), 'Open.CE|RW|-524292')
1923 self.assertEqual(str(~Open.AC), 'Open.CE|-524292')
1924 self.assertEqual(str(~(Open.RO | Open.CE)), 'Open.AC|-524292')
1925 self.assertEqual(str(~(Open.WO | Open.CE)), 'Open.RW|-524292')
1926 self.assertEqual(str(Open(~4)), 'Open.CE|AC|-524296')
1927
1928 def test_repr(self):
1929 Perm = self.Perm
1930 self.assertEqual(repr(Perm.R), '<Perm.R: 4>')
1931 self.assertEqual(repr(Perm.W), '<Perm.W: 2>')
1932 self.assertEqual(repr(Perm.X), '<Perm.X: 1>')
1933 self.assertEqual(repr(Perm.R | Perm.W), '<Perm.R|W: 6>')
1934 self.assertEqual(repr(Perm.R | Perm.W | Perm.X), '<Perm.R|W|X: 7>')
1935 self.assertEqual(repr(Perm.R | 8), '<Perm.8|R: 12>')
Ethan Furman27682d22016-09-04 11:39:01 -07001936 self.assertEqual(repr(Perm(0)), '<Perm.0: 0>')
1937 self.assertEqual(repr(Perm(8)), '<Perm.8: 8>')
Ethan Furmanee47e5c2016-08-31 00:12:15 -07001938 self.assertEqual(repr(~Perm.R), '<Perm.W|X|-8: -5>')
1939 self.assertEqual(repr(~Perm.W), '<Perm.R|X|-8: -3>')
1940 self.assertEqual(repr(~Perm.X), '<Perm.R|W|-8: -2>')
1941 self.assertEqual(repr(~(Perm.R | Perm.W)), '<Perm.X|-8: -7>')
Ethan Furman27682d22016-09-04 11:39:01 -07001942 self.assertEqual(repr(~(Perm.R | Perm.W | Perm.X)), '<Perm.-8: -8>')
Ethan Furmanee47e5c2016-08-31 00:12:15 -07001943 self.assertEqual(repr(~(Perm.R | 8)), '<Perm.W|X|-16: -13>')
1944 self.assertEqual(repr(Perm(~0)), '<Perm.R|W|X|-8: -1>')
1945 self.assertEqual(repr(Perm(~8)), '<Perm.R|W|X|-16: -9>')
1946
1947 Open = self.Open
1948 self.assertEqual(repr(Open.RO), '<Open.RO: 0>')
1949 self.assertEqual(repr(Open.WO), '<Open.WO: 1>')
1950 self.assertEqual(repr(Open.AC), '<Open.AC: 3>')
1951 self.assertEqual(repr(Open.RO | Open.CE), '<Open.CE: 524288>')
1952 self.assertEqual(repr(Open.WO | Open.CE), '<Open.CE|WO: 524289>')
Ethan Furman27682d22016-09-04 11:39:01 -07001953 self.assertEqual(repr(Open(4)), '<Open.4: 4>')
Ethan Furmanee47e5c2016-08-31 00:12:15 -07001954 self.assertEqual(repr(~Open.RO), '<Open.CE|AC|-524292: -1>')
1955 self.assertEqual(repr(~Open.WO), '<Open.CE|RW|-524292: -2>')
1956 self.assertEqual(repr(~Open.AC), '<Open.CE|-524292: -4>')
1957 self.assertEqual(repr(~(Open.RO | Open.CE)), '<Open.AC|-524292: -524289>')
1958 self.assertEqual(repr(~(Open.WO | Open.CE)), '<Open.RW|-524292: -524290>')
1959 self.assertEqual(repr(Open(~4)), '<Open.CE|AC|-524296: -5>')
1960
1961 def test_or(self):
1962 Perm = self.Perm
1963 for i in Perm:
1964 for j in Perm:
1965 self.assertEqual(i | j, i.value | j.value)
1966 self.assertEqual((i | j).value, i.value | j.value)
1967 self.assertIs(type(i | j), Perm)
1968 for j in range(8):
1969 self.assertEqual(i | j, i.value | j)
1970 self.assertEqual((i | j).value, i.value | j)
1971 self.assertIs(type(i | j), Perm)
1972 self.assertEqual(j | i, j | i.value)
1973 self.assertEqual((j | i).value, j | i.value)
1974 self.assertIs(type(j | i), Perm)
1975 for i in Perm:
1976 self.assertIs(i | i, i)
1977 self.assertIs(i | 0, i)
1978 self.assertIs(0 | i, i)
1979 Open = self.Open
1980 self.assertIs(Open.RO | Open.CE, Open.CE)
1981
1982 def test_and(self):
1983 Perm = self.Perm
1984 RW = Perm.R | Perm.W
1985 RX = Perm.R | Perm.X
1986 WX = Perm.W | Perm.X
1987 RWX = Perm.R | Perm.W | Perm.X
1988 values = list(Perm) + [RW, RX, WX, RWX, Perm(0)]
1989 for i in values:
1990 for j in values:
1991 self.assertEqual(i & j, i.value & j.value, 'i is %r, j is %r' % (i, j))
1992 self.assertEqual((i & j).value, i.value & j.value, 'i is %r, j is %r' % (i, j))
1993 self.assertIs(type(i & j), Perm, 'i is %r, j is %r' % (i, j))
1994 for j in range(8):
1995 self.assertEqual(i & j, i.value & j)
1996 self.assertEqual((i & j).value, i.value & j)
1997 self.assertIs(type(i & j), Perm)
1998 self.assertEqual(j & i, j & i.value)
1999 self.assertEqual((j & i).value, j & i.value)
2000 self.assertIs(type(j & i), Perm)
2001 for i in Perm:
2002 self.assertIs(i & i, i)
2003 self.assertIs(i & 7, i)
2004 self.assertIs(7 & i, i)
2005 Open = self.Open
2006 self.assertIs(Open.RO & Open.CE, Open.RO)
2007
2008 def test_xor(self):
2009 Perm = self.Perm
2010 for i in Perm:
2011 for j in Perm:
2012 self.assertEqual(i ^ j, i.value ^ j.value)
2013 self.assertEqual((i ^ j).value, i.value ^ j.value)
2014 self.assertIs(type(i ^ j), Perm)
2015 for j in range(8):
2016 self.assertEqual(i ^ j, i.value ^ j)
2017 self.assertEqual((i ^ j).value, i.value ^ j)
2018 self.assertIs(type(i ^ j), Perm)
2019 self.assertEqual(j ^ i, j ^ i.value)
2020 self.assertEqual((j ^ i).value, j ^ i.value)
2021 self.assertIs(type(j ^ i), Perm)
2022 for i in Perm:
2023 self.assertIs(i ^ 0, i)
2024 self.assertIs(0 ^ i, i)
2025 Open = self.Open
2026 self.assertIs(Open.RO ^ Open.CE, Open.CE)
2027 self.assertIs(Open.CE ^ Open.CE, Open.RO)
2028
2029 def test_invert(self):
2030 Perm = self.Perm
2031 RW = Perm.R | Perm.W
2032 RX = Perm.R | Perm.X
2033 WX = Perm.W | Perm.X
2034 RWX = Perm.R | Perm.W | Perm.X
2035 values = list(Perm) + [RW, RX, WX, RWX, Perm(0)]
2036 for i in values:
2037 self.assertEqual(~i, ~i.value)
2038 self.assertEqual((~i).value, ~i.value)
2039 self.assertIs(type(~i), Perm)
2040 self.assertEqual(~~i, i)
2041 for i in Perm:
2042 self.assertIs(~~i, i)
2043 Open = self.Open
2044 self.assertIs(Open.WO & ~Open.WO, Open.RO)
2045 self.assertIs((Open.WO|Open.CE) & ~Open.WO, Open.CE)
2046
2047 def test_programatic_function_string(self):
Ethan Furman65a5a472016-09-01 23:55:19 -07002048 Perm = IntFlag('Perm', 'R W X')
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002049 lst = list(Perm)
2050 self.assertEqual(len(lst), len(Perm))
2051 self.assertEqual(len(Perm), 3, Perm)
2052 self.assertEqual(lst, [Perm.R, Perm.W, Perm.X])
2053 for i, n in enumerate('R W X'.split()):
2054 v = 1<<i
2055 e = Perm(v)
2056 self.assertEqual(e.value, v)
2057 self.assertEqual(type(e.value), int)
2058 self.assertEqual(e, v)
2059 self.assertEqual(e.name, n)
2060 self.assertIn(e, Perm)
2061 self.assertIs(type(e), Perm)
2062
2063 def test_programatic_function_string_with_start(self):
Ethan Furman65a5a472016-09-01 23:55:19 -07002064 Perm = IntFlag('Perm', 'R W X', start=8)
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002065 lst = list(Perm)
2066 self.assertEqual(len(lst), len(Perm))
2067 self.assertEqual(len(Perm), 3, Perm)
2068 self.assertEqual(lst, [Perm.R, Perm.W, Perm.X])
2069 for i, n in enumerate('R W X'.split()):
2070 v = 8<<i
2071 e = Perm(v)
2072 self.assertEqual(e.value, v)
2073 self.assertEqual(type(e.value), int)
2074 self.assertEqual(e, v)
2075 self.assertEqual(e.name, n)
2076 self.assertIn(e, Perm)
2077 self.assertIs(type(e), Perm)
2078
2079 def test_programatic_function_string_list(self):
Ethan Furman65a5a472016-09-01 23:55:19 -07002080 Perm = IntFlag('Perm', ['R', 'W', 'X'])
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002081 lst = list(Perm)
2082 self.assertEqual(len(lst), len(Perm))
2083 self.assertEqual(len(Perm), 3, Perm)
2084 self.assertEqual(lst, [Perm.R, Perm.W, Perm.X])
2085 for i, n in enumerate('R W X'.split()):
2086 v = 1<<i
2087 e = Perm(v)
2088 self.assertEqual(e.value, v)
2089 self.assertEqual(type(e.value), int)
2090 self.assertEqual(e, v)
2091 self.assertEqual(e.name, n)
2092 self.assertIn(e, Perm)
2093 self.assertIs(type(e), Perm)
2094
2095 def test_programatic_function_iterable(self):
Ethan Furman65a5a472016-09-01 23:55:19 -07002096 Perm = IntFlag('Perm', (('R', 2), ('W', 8), ('X', 32)))
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002097 lst = list(Perm)
2098 self.assertEqual(len(lst), len(Perm))
2099 self.assertEqual(len(Perm), 3, Perm)
2100 self.assertEqual(lst, [Perm.R, Perm.W, Perm.X])
2101 for i, n in enumerate('R W X'.split()):
2102 v = 1<<(2*i+1)
2103 e = Perm(v)
2104 self.assertEqual(e.value, v)
2105 self.assertEqual(type(e.value), int)
2106 self.assertEqual(e, v)
2107 self.assertEqual(e.name, n)
2108 self.assertIn(e, Perm)
2109 self.assertIs(type(e), Perm)
2110
2111 def test_programatic_function_from_dict(self):
Ethan Furman65a5a472016-09-01 23:55:19 -07002112 Perm = IntFlag('Perm', OrderedDict((('R', 2), ('W', 8), ('X', 32))))
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002113 lst = list(Perm)
2114 self.assertEqual(len(lst), len(Perm))
2115 self.assertEqual(len(Perm), 3, Perm)
2116 self.assertEqual(lst, [Perm.R, Perm.W, Perm.X])
2117 for i, n in enumerate('R W X'.split()):
2118 v = 1<<(2*i+1)
2119 e = Perm(v)
2120 self.assertEqual(e.value, v)
2121 self.assertEqual(type(e.value), int)
2122 self.assertEqual(e, v)
2123 self.assertEqual(e.name, n)
2124 self.assertIn(e, Perm)
2125 self.assertIs(type(e), Perm)
2126
2127
Ethan Furman65a5a472016-09-01 23:55:19 -07002128 def test_containment(self):
2129 Perm = self.Perm
2130 R, W, X = Perm
2131 RW = R | W
2132 RX = R | X
2133 WX = W | X
2134 RWX = R | W | X
2135 self.assertTrue(R in RW)
2136 self.assertTrue(R in RX)
2137 self.assertTrue(R in RWX)
2138 self.assertTrue(W in RW)
2139 self.assertTrue(W in WX)
2140 self.assertTrue(W in RWX)
2141 self.assertTrue(X in RX)
2142 self.assertTrue(X in WX)
2143 self.assertTrue(X in RWX)
2144 self.assertFalse(R in WX)
2145 self.assertFalse(W in RX)
2146 self.assertFalse(X in RW)
2147
Ethan Furman25d94bb2016-09-02 16:32:32 -07002148 def test_bool(self):
2149 Perm = self.Perm
2150 for f in Perm:
2151 self.assertTrue(f)
2152 Open = self.Open
2153 for f in Open:
2154 self.assertEqual(bool(f.value), bool(f))
2155
Ethan Furmanf24bb352013-07-18 17:05:39 -07002156class TestUnique(unittest.TestCase):
2157
2158 def test_unique_clean(self):
2159 @unique
2160 class Clean(Enum):
2161 one = 1
2162 two = 'dos'
2163 tres = 4.0
2164 @unique
2165 class Cleaner(IntEnum):
2166 single = 1
2167 double = 2
2168 triple = 3
2169
2170 def test_unique_dirty(self):
2171 with self.assertRaisesRegex(ValueError, 'tres.*one'):
2172 @unique
2173 class Dirty(Enum):
2174 one = 1
2175 two = 'dos'
2176 tres = 1
2177 with self.assertRaisesRegex(
2178 ValueError,
2179 'double.*single.*turkey.*triple',
2180 ):
2181 @unique
2182 class Dirtier(IntEnum):
2183 single = 1
2184 double = 1
2185 triple = 3
2186 turkey = 3
2187
Ethan Furman3803ad42016-05-01 10:03:53 -07002188 def test_unique_with_name(self):
2189 @unique
2190 class Silly(Enum):
2191 one = 1
2192 two = 'dos'
2193 name = 3
2194 @unique
2195 class Sillier(IntEnum):
2196 single = 1
2197 name = 2
2198 triple = 3
2199 value = 4
2200
Ethan Furmanf24bb352013-07-18 17:05:39 -07002201
Ethan Furman3323da92015-04-11 09:39:59 -07002202expected_help_output_with_docs = """\
Ethan Furman5875d742013-10-21 20:45:55 -07002203Help on class Color in module %s:
2204
2205class Color(enum.Enum)
Ethan Furman48a724f2015-04-11 23:23:06 -07002206 | An enumeration.
Serhiy Storchakab599ca82015-04-04 12:48:04 +03002207 |\x20\x20
Ethan Furman5875d742013-10-21 20:45:55 -07002208 | Method resolution order:
2209 | Color
2210 | enum.Enum
2211 | builtins.object
2212 |\x20\x20
2213 | Data and other attributes defined here:
2214 |\x20\x20
2215 | blue = <Color.blue: 3>
2216 |\x20\x20
2217 | green = <Color.green: 2>
2218 |\x20\x20
2219 | red = <Color.red: 1>
2220 |\x20\x20
2221 | ----------------------------------------------------------------------
2222 | Data descriptors inherited from enum.Enum:
2223 |\x20\x20
2224 | name
2225 | The name of the Enum member.
2226 |\x20\x20
2227 | value
2228 | The value of the Enum member.
2229 |\x20\x20
2230 | ----------------------------------------------------------------------
2231 | Data descriptors inherited from enum.EnumMeta:
2232 |\x20\x20
2233 | __members__
2234 | Returns a mapping of member name->value.
2235 |\x20\x20\x20\x20\x20\x20
2236 | This mapping lists all enum members, including aliases. Note that this
Ethan Furman3323da92015-04-11 09:39:59 -07002237 | is a read-only view of the internal mapping."""
2238
2239expected_help_output_without_docs = """\
2240Help on class Color in module %s:
2241
2242class Color(enum.Enum)
2243 | Method resolution order:
2244 | Color
2245 | enum.Enum
2246 | builtins.object
2247 |\x20\x20
2248 | Data and other attributes defined here:
2249 |\x20\x20
2250 | blue = <Color.blue: 3>
2251 |\x20\x20
2252 | green = <Color.green: 2>
2253 |\x20\x20
2254 | red = <Color.red: 1>
2255 |\x20\x20
2256 | ----------------------------------------------------------------------
2257 | Data descriptors inherited from enum.Enum:
2258 |\x20\x20
2259 | name
2260 |\x20\x20
2261 | value
2262 |\x20\x20
2263 | ----------------------------------------------------------------------
2264 | Data descriptors inherited from enum.EnumMeta:
2265 |\x20\x20
2266 | __members__"""
Ethan Furman5875d742013-10-21 20:45:55 -07002267
2268class TestStdLib(unittest.TestCase):
2269
Ethan Furman48a724f2015-04-11 23:23:06 -07002270 maxDiff = None
2271
Ethan Furman5875d742013-10-21 20:45:55 -07002272 class Color(Enum):
2273 red = 1
2274 green = 2
2275 blue = 3
2276
2277 def test_pydoc(self):
2278 # indirectly test __objclass__
Ethan Furman3323da92015-04-11 09:39:59 -07002279 if StrEnum.__doc__ is None:
2280 expected_text = expected_help_output_without_docs % __name__
2281 else:
2282 expected_text = expected_help_output_with_docs % __name__
Ethan Furman5875d742013-10-21 20:45:55 -07002283 output = StringIO()
2284 helper = pydoc.Helper(output=output)
2285 helper(self.Color)
2286 result = output.getvalue().strip()
Victor Stinner4b0432d2014-06-16 22:48:43 +02002287 self.assertEqual(result, expected_text)
Ethan Furman5875d742013-10-21 20:45:55 -07002288
2289 def test_inspect_getmembers(self):
2290 values = dict((
2291 ('__class__', EnumMeta),
Ethan Furman48a724f2015-04-11 23:23:06 -07002292 ('__doc__', 'An enumeration.'),
Ethan Furman5875d742013-10-21 20:45:55 -07002293 ('__members__', self.Color.__members__),
2294 ('__module__', __name__),
2295 ('blue', self.Color.blue),
2296 ('green', self.Color.green),
2297 ('name', Enum.__dict__['name']),
2298 ('red', self.Color.red),
2299 ('value', Enum.__dict__['value']),
2300 ))
2301 result = dict(inspect.getmembers(self.Color))
2302 self.assertEqual(values.keys(), result.keys())
2303 failed = False
2304 for k in values.keys():
2305 if result[k] != values[k]:
2306 print()
2307 print('\n%s\n key: %s\n result: %s\nexpected: %s\n%s\n' %
2308 ('=' * 75, k, result[k], values[k], '=' * 75), sep='')
2309 failed = True
2310 if failed:
2311 self.fail("result does not equal expected, see print above")
2312
2313 def test_inspect_classify_class_attrs(self):
2314 # indirectly test __objclass__
2315 from inspect import Attribute
2316 values = [
2317 Attribute(name='__class__', kind='data',
2318 defining_class=object, object=EnumMeta),
2319 Attribute(name='__doc__', kind='data',
Ethan Furman48a724f2015-04-11 23:23:06 -07002320 defining_class=self.Color, object='An enumeration.'),
Ethan Furman5875d742013-10-21 20:45:55 -07002321 Attribute(name='__members__', kind='property',
2322 defining_class=EnumMeta, object=EnumMeta.__members__),
2323 Attribute(name='__module__', kind='data',
2324 defining_class=self.Color, object=__name__),
2325 Attribute(name='blue', kind='data',
2326 defining_class=self.Color, object=self.Color.blue),
2327 Attribute(name='green', kind='data',
2328 defining_class=self.Color, object=self.Color.green),
2329 Attribute(name='red', kind='data',
2330 defining_class=self.Color, object=self.Color.red),
2331 Attribute(name='name', kind='data',
2332 defining_class=Enum, object=Enum.__dict__['name']),
2333 Attribute(name='value', kind='data',
2334 defining_class=Enum, object=Enum.__dict__['value']),
2335 ]
2336 values.sort(key=lambda item: item.name)
2337 result = list(inspect.classify_class_attrs(self.Color))
2338 result.sort(key=lambda item: item.name)
2339 failed = False
2340 for v, r in zip(values, result):
2341 if r != v:
2342 print('\n%s\n%s\n%s\n%s\n' % ('=' * 75, r, v, '=' * 75), sep='')
2343 failed = True
2344 if failed:
2345 self.fail("result does not equal expected, see print above")
2346
Martin Panter19e69c52015-11-14 12:46:42 +00002347
2348class MiscTestCase(unittest.TestCase):
2349 def test__all__(self):
2350 support.check__all__(self, enum)
2351
2352
Gregory P. Smith ext:(%20%5BGoogle%20Inc.%5D)6f20bd62016-06-03 19:14:52 +00002353# These are unordered here on purpose to ensure that declaration order
2354# makes no difference.
2355CONVERT_TEST_NAME_D = 5
2356CONVERT_TEST_NAME_C = 5
2357CONVERT_TEST_NAME_B = 5
2358CONVERT_TEST_NAME_A = 5 # This one should sort first.
2359CONVERT_TEST_NAME_E = 5
2360CONVERT_TEST_NAME_F = 5
2361
2362class TestIntEnumConvert(unittest.TestCase):
2363 def test_convert_value_lookup_priority(self):
2364 test_type = enum.IntEnum._convert(
2365 'UnittestConvert', 'test.test_enum',
2366 filter=lambda x: x.startswith('CONVERT_TEST_'))
2367 # We don't want the reverse lookup value to vary when there are
2368 # multiple possible names for a given value. It should always
2369 # report the first lexigraphical name in that case.
2370 self.assertEqual(test_type(5).name, 'CONVERT_TEST_NAME_A')
2371
2372 def test_convert(self):
2373 test_type = enum.IntEnum._convert(
2374 'UnittestConvert', 'test.test_enum',
2375 filter=lambda x: x.startswith('CONVERT_TEST_'))
2376 # Ensure that test_type has all of the desired names and values.
2377 self.assertEqual(test_type.CONVERT_TEST_NAME_F,
2378 test_type.CONVERT_TEST_NAME_A)
2379 self.assertEqual(test_type.CONVERT_TEST_NAME_B, 5)
2380 self.assertEqual(test_type.CONVERT_TEST_NAME_C, 5)
2381 self.assertEqual(test_type.CONVERT_TEST_NAME_D, 5)
2382 self.assertEqual(test_type.CONVERT_TEST_NAME_E, 5)
2383 # Ensure that test_type only picked up names matching the filter.
2384 self.assertEqual([name for name in dir(test_type)
2385 if name[0:2] not in ('CO', '__')],
2386 [], msg='Names other than CONVERT_TEST_* found.')
2387
2388
Ethan Furman6b3d64a2013-06-14 16:55:46 -07002389if __name__ == '__main__':
2390 unittest.main()