blob: 153bfb40a79185ab6148b01429ce263c371831d8 [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 Furmanc16595e2016-09-10 23:36:59 -07006from enum import Enum, IntEnum, EnumMeta, Flag, IntFlag, unique, auto
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
Ethan Furmanc16595e2016-09-10 23:36:59 -0700116# tests
Ethan Furman648f8602013-10-06 17:19:54 -0700117
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700118class TestEnum(unittest.TestCase):
Ethan Furmanca1b7942014-02-08 11:36:27 -0800119
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700120 def setUp(self):
121 class Season(Enum):
122 SPRING = 1
123 SUMMER = 2
124 AUTUMN = 3
125 WINTER = 4
126 self.Season = Season
127
Ethan Furmanec15a822013-08-31 19:17:41 -0700128 class Konstants(float, Enum):
129 E = 2.7182818
130 PI = 3.1415926
131 TAU = 2 * PI
132 self.Konstants = Konstants
133
134 class Grades(IntEnum):
135 A = 5
136 B = 4
137 C = 3
138 D = 2
139 F = 0
140 self.Grades = Grades
141
142 class Directional(str, Enum):
143 EAST = 'east'
144 WEST = 'west'
145 NORTH = 'north'
146 SOUTH = 'south'
147 self.Directional = Directional
148
149 from datetime import date
150 class Holiday(date, Enum):
151 NEW_YEAR = 2013, 1, 1
152 IDES_OF_MARCH = 2013, 3, 15
153 self.Holiday = Holiday
154
Ethan Furman388a3922013-08-12 06:51:41 -0700155 def test_dir_on_class(self):
156 Season = self.Season
157 self.assertEqual(
158 set(dir(Season)),
Ethan Furmanc850f342013-09-15 16:59:35 -0700159 set(['__class__', '__doc__', '__members__', '__module__',
Ethan Furman388a3922013-08-12 06:51:41 -0700160 'SPRING', 'SUMMER', 'AUTUMN', 'WINTER']),
161 )
162
163 def test_dir_on_item(self):
164 Season = self.Season
165 self.assertEqual(
166 set(dir(Season.WINTER)),
Ethan Furmanc850f342013-09-15 16:59:35 -0700167 set(['__class__', '__doc__', '__module__', 'name', 'value']),
Ethan Furman388a3922013-08-12 06:51:41 -0700168 )
169
Ethan Furmanc850f342013-09-15 16:59:35 -0700170 def test_dir_with_added_behavior(self):
171 class Test(Enum):
172 this = 'that'
173 these = 'those'
174 def wowser(self):
175 return ("Wowser! I'm %s!" % self.name)
176 self.assertEqual(
177 set(dir(Test)),
178 set(['__class__', '__doc__', '__members__', '__module__', 'this', 'these']),
179 )
180 self.assertEqual(
181 set(dir(Test.this)),
182 set(['__class__', '__doc__', '__module__', 'name', 'value', 'wowser']),
183 )
184
Ethan Furman0ae550b2014-10-14 08:58:32 -0700185 def test_dir_on_sub_with_behavior_on_super(self):
186 # see issue22506
187 class SuperEnum(Enum):
188 def invisible(self):
189 return "did you see me?"
190 class SubEnum(SuperEnum):
191 sample = 5
192 self.assertEqual(
193 set(dir(SubEnum.sample)),
194 set(['__class__', '__doc__', '__module__', 'name', 'value', 'invisible']),
195 )
196
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700197 def test_enum_in_enum_out(self):
198 Season = self.Season
199 self.assertIs(Season(Season.WINTER), Season.WINTER)
200
201 def test_enum_value(self):
202 Season = self.Season
203 self.assertEqual(Season.SPRING.value, 1)
204
205 def test_intenum_value(self):
206 self.assertEqual(IntStooges.CURLY.value, 2)
207
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700208 def test_enum(self):
209 Season = self.Season
210 lst = list(Season)
211 self.assertEqual(len(lst), len(Season))
212 self.assertEqual(len(Season), 4, Season)
213 self.assertEqual(
214 [Season.SPRING, Season.SUMMER, Season.AUTUMN, Season.WINTER], lst)
215
216 for i, season in enumerate('SPRING SUMMER AUTUMN WINTER'.split(), 1):
217 e = Season(i)
218 self.assertEqual(e, getattr(Season, season))
219 self.assertEqual(e.value, i)
220 self.assertNotEqual(e, i)
221 self.assertEqual(e.name, season)
222 self.assertIn(e, Season)
223 self.assertIs(type(e), Season)
224 self.assertIsInstance(e, Season)
225 self.assertEqual(str(e), 'Season.' + season)
226 self.assertEqual(
227 repr(e),
228 '<Season.{0}: {1}>'.format(season, i),
229 )
230
231 def test_value_name(self):
232 Season = self.Season
233 self.assertEqual(Season.SPRING.name, 'SPRING')
234 self.assertEqual(Season.SPRING.value, 1)
235 with self.assertRaises(AttributeError):
236 Season.SPRING.name = 'invierno'
237 with self.assertRaises(AttributeError):
238 Season.SPRING.value = 2
239
Ethan Furmanf203f2d2013-09-06 07:16:48 -0700240 def test_changing_member(self):
241 Season = self.Season
242 with self.assertRaises(AttributeError):
243 Season.WINTER = 'really cold'
244
Ethan Furman64a99722013-09-22 16:18:19 -0700245 def test_attribute_deletion(self):
246 class Season(Enum):
247 SPRING = 1
248 SUMMER = 2
249 AUTUMN = 3
250 WINTER = 4
251
252 def spam(cls):
253 pass
254
255 self.assertTrue(hasattr(Season, 'spam'))
256 del Season.spam
257 self.assertFalse(hasattr(Season, 'spam'))
258
259 with self.assertRaises(AttributeError):
260 del Season.SPRING
261 with self.assertRaises(AttributeError):
262 del Season.DRY
263 with self.assertRaises(AttributeError):
264 del Season.SPRING.name
265
Ethan Furman5de67b12016-04-13 23:52:09 -0700266 def test_bool_of_class(self):
267 class Empty(Enum):
268 pass
269 self.assertTrue(bool(Empty))
270
271 def test_bool_of_member(self):
272 class Count(Enum):
273 zero = 0
274 one = 1
275 two = 2
276 for member in Count:
277 self.assertTrue(bool(member))
278
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700279 def test_invalid_names(self):
280 with self.assertRaises(ValueError):
281 class Wrong(Enum):
282 mro = 9
283 with self.assertRaises(ValueError):
284 class Wrong(Enum):
285 _create_= 11
286 with self.assertRaises(ValueError):
287 class Wrong(Enum):
288 _get_mixins_ = 9
289 with self.assertRaises(ValueError):
290 class Wrong(Enum):
291 _find_new_ = 1
292 with self.assertRaises(ValueError):
293 class Wrong(Enum):
294 _any_name_ = 9
295
Ethan Furman6db1fd52015-09-17 21:49:12 -0700296 def test_bool(self):
Ethan Furman60255b62016-01-15 15:01:33 -0800297 # plain Enum members are always True
Ethan Furman6db1fd52015-09-17 21:49:12 -0700298 class Logic(Enum):
299 true = True
300 false = False
301 self.assertTrue(Logic.true)
Ethan Furman60255b62016-01-15 15:01:33 -0800302 self.assertTrue(Logic.false)
303 # unless overridden
304 class RealLogic(Enum):
305 true = True
306 false = False
307 def __bool__(self):
308 return bool(self._value_)
309 self.assertTrue(RealLogic.true)
310 self.assertFalse(RealLogic.false)
311 # mixed Enums depend on mixed-in type
312 class IntLogic(int, Enum):
313 true = 1
314 false = 0
315 self.assertTrue(IntLogic.true)
316 self.assertFalse(IntLogic.false)
Ethan Furman6db1fd52015-09-17 21:49:12 -0700317
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700318 def test_contains(self):
319 Season = self.Season
320 self.assertIn(Season.AUTUMN, Season)
321 self.assertNotIn(3, Season)
322
323 val = Season(3)
324 self.assertIn(val, Season)
325
326 class OtherEnum(Enum):
327 one = 1; two = 2
328 self.assertNotIn(OtherEnum.two, Season)
329
330 def test_comparisons(self):
331 Season = self.Season
332 with self.assertRaises(TypeError):
333 Season.SPRING < Season.WINTER
334 with self.assertRaises(TypeError):
335 Season.SPRING > 4
336
337 self.assertNotEqual(Season.SPRING, 1)
338
339 class Part(Enum):
340 SPRING = 1
341 CLIP = 2
342 BARREL = 3
343
344 self.assertNotEqual(Season.SPRING, Part.SPRING)
345 with self.assertRaises(TypeError):
346 Season.SPRING < Part.CLIP
347
348 def test_enum_duplicates(self):
349 class Season(Enum):
350 SPRING = 1
351 SUMMER = 2
352 AUTUMN = FALL = 3
353 WINTER = 4
354 ANOTHER_SPRING = 1
355 lst = list(Season)
356 self.assertEqual(
357 lst,
358 [Season.SPRING, Season.SUMMER,
359 Season.AUTUMN, Season.WINTER,
360 ])
361 self.assertIs(Season.FALL, Season.AUTUMN)
362 self.assertEqual(Season.FALL.value, 3)
363 self.assertEqual(Season.AUTUMN.value, 3)
364 self.assertIs(Season(3), Season.AUTUMN)
365 self.assertIs(Season(1), Season.SPRING)
366 self.assertEqual(Season.FALL.name, 'AUTUMN')
367 self.assertEqual(
368 [k for k,v in Season.__members__.items() if v.name != k],
369 ['FALL', 'ANOTHER_SPRING'],
370 )
371
Ethan Furman101e0742013-09-15 12:34:36 -0700372 def test_duplicate_name(self):
373 with self.assertRaises(TypeError):
374 class Color(Enum):
375 red = 1
376 green = 2
377 blue = 3
378 red = 4
379
380 with self.assertRaises(TypeError):
381 class Color(Enum):
382 red = 1
383 green = 2
384 blue = 3
385 def red(self):
386 return 'red'
387
388 with self.assertRaises(TypeError):
389 class Color(Enum):
390 @property
391 def red(self):
392 return 'redder'
393 red = 1
394 green = 2
395 blue = 3
396
397
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700398 def test_enum_with_value_name(self):
399 class Huh(Enum):
400 name = 1
401 value = 2
402 self.assertEqual(
403 list(Huh),
404 [Huh.name, Huh.value],
405 )
406 self.assertIs(type(Huh.name), Huh)
407 self.assertEqual(Huh.name.name, 'name')
408 self.assertEqual(Huh.name.value, 1)
Ethan Furmanec15a822013-08-31 19:17:41 -0700409
410 def test_format_enum(self):
411 Season = self.Season
412 self.assertEqual('{}'.format(Season.SPRING),
413 '{}'.format(str(Season.SPRING)))
414 self.assertEqual( '{:}'.format(Season.SPRING),
415 '{:}'.format(str(Season.SPRING)))
416 self.assertEqual('{:20}'.format(Season.SPRING),
417 '{:20}'.format(str(Season.SPRING)))
418 self.assertEqual('{:^20}'.format(Season.SPRING),
419 '{:^20}'.format(str(Season.SPRING)))
420 self.assertEqual('{:>20}'.format(Season.SPRING),
421 '{:>20}'.format(str(Season.SPRING)))
422 self.assertEqual('{:<20}'.format(Season.SPRING),
423 '{:<20}'.format(str(Season.SPRING)))
424
425 def test_format_enum_custom(self):
426 class TestFloat(float, Enum):
427 one = 1.0
428 two = 2.0
429 def __format__(self, spec):
430 return 'TestFloat success!'
431 self.assertEqual('{}'.format(TestFloat.one), 'TestFloat success!')
432
433 def assertFormatIsValue(self, spec, member):
434 self.assertEqual(spec.format(member), spec.format(member.value))
435
436 def test_format_enum_date(self):
437 Holiday = self.Holiday
438 self.assertFormatIsValue('{}', Holiday.IDES_OF_MARCH)
439 self.assertFormatIsValue('{:}', 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('{:<20}', Holiday.IDES_OF_MARCH)
444 self.assertFormatIsValue('{:%Y %m}', Holiday.IDES_OF_MARCH)
445 self.assertFormatIsValue('{:%Y %m %M:00}', Holiday.IDES_OF_MARCH)
446
447 def test_format_enum_float(self):
448 Konstants = self.Konstants
449 self.assertFormatIsValue('{}', Konstants.TAU)
450 self.assertFormatIsValue('{:}', Konstants.TAU)
451 self.assertFormatIsValue('{:20}', Konstants.TAU)
452 self.assertFormatIsValue('{:^20}', Konstants.TAU)
453 self.assertFormatIsValue('{:>20}', Konstants.TAU)
454 self.assertFormatIsValue('{:<20}', Konstants.TAU)
455 self.assertFormatIsValue('{:n}', Konstants.TAU)
456 self.assertFormatIsValue('{:5.2}', Konstants.TAU)
457 self.assertFormatIsValue('{:f}', Konstants.TAU)
458
459 def test_format_enum_int(self):
460 Grades = self.Grades
461 self.assertFormatIsValue('{}', Grades.C)
462 self.assertFormatIsValue('{:}', Grades.C)
463 self.assertFormatIsValue('{:20}', Grades.C)
464 self.assertFormatIsValue('{:^20}', Grades.C)
465 self.assertFormatIsValue('{:>20}', Grades.C)
466 self.assertFormatIsValue('{:<20}', Grades.C)
467 self.assertFormatIsValue('{:+}', Grades.C)
468 self.assertFormatIsValue('{:08X}', Grades.C)
469 self.assertFormatIsValue('{:b}', Grades.C)
470
471 def test_format_enum_str(self):
472 Directional = self.Directional
473 self.assertFormatIsValue('{}', Directional.WEST)
474 self.assertFormatIsValue('{:}', Directional.WEST)
475 self.assertFormatIsValue('{:20}', Directional.WEST)
476 self.assertFormatIsValue('{:^20}', Directional.WEST)
477 self.assertFormatIsValue('{:>20}', Directional.WEST)
478 self.assertFormatIsValue('{:<20}', Directional.WEST)
479
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700480 def test_hash(self):
481 Season = self.Season
482 dates = {}
483 dates[Season.WINTER] = '1225'
484 dates[Season.SPRING] = '0315'
485 dates[Season.SUMMER] = '0704'
486 dates[Season.AUTUMN] = '1031'
487 self.assertEqual(dates[Season.AUTUMN], '1031')
488
489 def test_intenum_from_scratch(self):
490 class phy(int, Enum):
491 pi = 3
492 tau = 2 * pi
493 self.assertTrue(phy.pi < phy.tau)
494
495 def test_intenum_inherited(self):
496 class IntEnum(int, Enum):
497 pass
498 class phy(IntEnum):
499 pi = 3
500 tau = 2 * pi
501 self.assertTrue(phy.pi < phy.tau)
502
503 def test_floatenum_from_scratch(self):
504 class phy(float, Enum):
Ethan Furmanec15a822013-08-31 19:17:41 -0700505 pi = 3.1415926
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700506 tau = 2 * pi
507 self.assertTrue(phy.pi < phy.tau)
508
509 def test_floatenum_inherited(self):
510 class FloatEnum(float, Enum):
511 pass
512 class phy(FloatEnum):
Ethan Furmanec15a822013-08-31 19:17:41 -0700513 pi = 3.1415926
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700514 tau = 2 * pi
515 self.assertTrue(phy.pi < phy.tau)
516
517 def test_strenum_from_scratch(self):
518 class phy(str, Enum):
519 pi = 'Pi'
520 tau = 'Tau'
521 self.assertTrue(phy.pi < phy.tau)
522
523 def test_strenum_inherited(self):
524 class StrEnum(str, Enum):
525 pass
526 class phy(StrEnum):
527 pi = 'Pi'
528 tau = 'Tau'
529 self.assertTrue(phy.pi < phy.tau)
530
531
532 def test_intenum(self):
533 class WeekDay(IntEnum):
534 SUNDAY = 1
535 MONDAY = 2
536 TUESDAY = 3
537 WEDNESDAY = 4
538 THURSDAY = 5
539 FRIDAY = 6
540 SATURDAY = 7
541
542 self.assertEqual(['a', 'b', 'c'][WeekDay.MONDAY], 'c')
543 self.assertEqual([i for i in range(WeekDay.TUESDAY)], [0, 1, 2])
544
545 lst = list(WeekDay)
546 self.assertEqual(len(lst), len(WeekDay))
547 self.assertEqual(len(WeekDay), 7)
548 target = 'SUNDAY MONDAY TUESDAY WEDNESDAY THURSDAY FRIDAY SATURDAY'
549 target = target.split()
550 for i, weekday in enumerate(target, 1):
551 e = WeekDay(i)
552 self.assertEqual(e, i)
553 self.assertEqual(int(e), i)
554 self.assertEqual(e.name, weekday)
555 self.assertIn(e, WeekDay)
556 self.assertEqual(lst.index(e)+1, i)
557 self.assertTrue(0 < e < 8)
558 self.assertIs(type(e), WeekDay)
559 self.assertIsInstance(e, int)
560 self.assertIsInstance(e, Enum)
561
562 def test_intenum_duplicates(self):
563 class WeekDay(IntEnum):
564 SUNDAY = 1
565 MONDAY = 2
566 TUESDAY = TEUSDAY = 3
567 WEDNESDAY = 4
568 THURSDAY = 5
569 FRIDAY = 6
570 SATURDAY = 7
571 self.assertIs(WeekDay.TEUSDAY, WeekDay.TUESDAY)
572 self.assertEqual(WeekDay(3).name, 'TUESDAY')
573 self.assertEqual([k for k,v in WeekDay.__members__.items()
574 if v.name != k], ['TEUSDAY', ])
575
Serhiy Storchakaea36c942016-05-12 10:37:58 +0300576 def test_intenum_from_bytes(self):
577 self.assertIs(IntStooges.from_bytes(b'\x00\x03', 'big'), IntStooges.MOE)
578 with self.assertRaises(ValueError):
579 IntStooges.from_bytes(b'\x00\x05', 'big')
580
581 def test_floatenum_fromhex(self):
582 h = float.hex(FloatStooges.MOE.value)
583 self.assertIs(FloatStooges.fromhex(h), FloatStooges.MOE)
584 h = float.hex(FloatStooges.MOE.value + 0.01)
585 with self.assertRaises(ValueError):
586 FloatStooges.fromhex(h)
587
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700588 def test_pickle_enum(self):
589 if isinstance(Stooges, Exception):
590 raise Stooges
Ethan Furman2ddb39a2014-02-06 17:28:50 -0800591 test_pickle_dump_load(self.assertIs, Stooges.CURLY)
592 test_pickle_dump_load(self.assertIs, Stooges)
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700593
594 def test_pickle_int(self):
595 if isinstance(IntStooges, Exception):
596 raise IntStooges
Ethan Furman2ddb39a2014-02-06 17:28:50 -0800597 test_pickle_dump_load(self.assertIs, IntStooges.CURLY)
598 test_pickle_dump_load(self.assertIs, IntStooges)
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700599
600 def test_pickle_float(self):
601 if isinstance(FloatStooges, Exception):
602 raise FloatStooges
Ethan Furman2ddb39a2014-02-06 17:28:50 -0800603 test_pickle_dump_load(self.assertIs, FloatStooges.CURLY)
604 test_pickle_dump_load(self.assertIs, FloatStooges)
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700605
606 def test_pickle_enum_function(self):
607 if isinstance(Answer, Exception):
608 raise Answer
Ethan Furman2ddb39a2014-02-06 17:28:50 -0800609 test_pickle_dump_load(self.assertIs, Answer.him)
610 test_pickle_dump_load(self.assertIs, Answer)
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700611
612 def test_pickle_enum_function_with_module(self):
613 if isinstance(Question, Exception):
614 raise Question
Ethan Furman2ddb39a2014-02-06 17:28:50 -0800615 test_pickle_dump_load(self.assertIs, Question.who)
616 test_pickle_dump_load(self.assertIs, Question)
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700617
Ethan Furmanca1b7942014-02-08 11:36:27 -0800618 def test_enum_function_with_qualname(self):
619 if isinstance(Theory, Exception):
620 raise Theory
621 self.assertEqual(Theory.__qualname__, 'spanish_inquisition')
622
623 def test_class_nested_enum_and_pickle_protocol_four(self):
624 # would normally just have this directly in the class namespace
625 class NestedEnum(Enum):
626 twigs = 'common'
627 shiny = 'rare'
628
629 self.__class__.NestedEnum = NestedEnum
630 self.NestedEnum.__qualname__ = '%s.NestedEnum' % self.__class__.__name__
Serhiy Storchakae50e7802015-03-31 16:56:49 +0300631 test_pickle_dump_load(self.assertIs, self.NestedEnum.twigs)
Ethan Furmanca1b7942014-02-08 11:36:27 -0800632
Ethan Furman24e837f2015-03-18 17:27:57 -0700633 def test_pickle_by_name(self):
634 class ReplaceGlobalInt(IntEnum):
635 ONE = 1
636 TWO = 2
637 ReplaceGlobalInt.__reduce_ex__ = enum._reduce_ex_by_name
638 for proto in range(HIGHEST_PROTOCOL):
639 self.assertEqual(ReplaceGlobalInt.TWO.__reduce_ex__(proto), 'TWO')
640
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700641 def test_exploding_pickle(self):
Ethan Furmanca1b7942014-02-08 11:36:27 -0800642 BadPickle = Enum(
643 'BadPickle', 'dill sweet bread-n-butter', module=__name__)
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700644 globals()['BadPickle'] = BadPickle
Ethan Furmanca1b7942014-02-08 11:36:27 -0800645 # now break BadPickle to test exception raising
646 enum._make_class_unpicklable(BadPickle)
Ethan Furman2ddb39a2014-02-06 17:28:50 -0800647 test_pickle_exception(self.assertRaises, TypeError, BadPickle.dill)
648 test_pickle_exception(self.assertRaises, PicklingError, BadPickle)
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700649
650 def test_string_enum(self):
651 class SkillLevel(str, Enum):
652 master = 'what is the sound of one hand clapping?'
653 journeyman = 'why did the chicken cross the road?'
654 apprentice = 'knock, knock!'
655 self.assertEqual(SkillLevel.apprentice, 'knock, knock!')
656
657 def test_getattr_getitem(self):
658 class Period(Enum):
659 morning = 1
660 noon = 2
661 evening = 3
662 night = 4
663 self.assertIs(Period(2), Period.noon)
664 self.assertIs(getattr(Period, 'night'), Period.night)
665 self.assertIs(Period['morning'], Period.morning)
666
667 def test_getattr_dunder(self):
668 Season = self.Season
669 self.assertTrue(getattr(Season, '__eq__'))
670
671 def test_iteration_order(self):
672 class Season(Enum):
673 SUMMER = 2
674 WINTER = 4
675 AUTUMN = 3
676 SPRING = 1
677 self.assertEqual(
678 list(Season),
679 [Season.SUMMER, Season.WINTER, Season.AUTUMN, Season.SPRING],
680 )
681
Ethan Furman2131a4a2013-09-14 18:11:24 -0700682 def test_reversed_iteration_order(self):
683 self.assertEqual(
684 list(reversed(self.Season)),
685 [self.Season.WINTER, self.Season.AUTUMN, self.Season.SUMMER,
686 self.Season.SPRING]
687 )
688
Martin Pantereb995702016-07-28 01:11:04 +0000689 def test_programmatic_function_string(self):
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700690 SummerMonth = Enum('SummerMonth', 'june july august')
691 lst = list(SummerMonth)
692 self.assertEqual(len(lst), len(SummerMonth))
693 self.assertEqual(len(SummerMonth), 3, SummerMonth)
694 self.assertEqual(
695 [SummerMonth.june, SummerMonth.july, SummerMonth.august],
696 lst,
697 )
698 for i, month in enumerate('june july august'.split(), 1):
699 e = SummerMonth(i)
700 self.assertEqual(int(e.value), i)
701 self.assertNotEqual(e, i)
702 self.assertEqual(e.name, month)
703 self.assertIn(e, SummerMonth)
704 self.assertIs(type(e), SummerMonth)
705
Martin Pantereb995702016-07-28 01:11:04 +0000706 def test_programmatic_function_string_with_start(self):
Ethan Furmand9925a12014-09-16 20:35:55 -0700707 SummerMonth = Enum('SummerMonth', 'june july august', start=10)
708 lst = list(SummerMonth)
709 self.assertEqual(len(lst), len(SummerMonth))
710 self.assertEqual(len(SummerMonth), 3, SummerMonth)
711 self.assertEqual(
712 [SummerMonth.june, SummerMonth.july, SummerMonth.august],
713 lst,
714 )
715 for i, month in enumerate('june july august'.split(), 10):
716 e = SummerMonth(i)
717 self.assertEqual(int(e.value), i)
718 self.assertNotEqual(e, i)
719 self.assertEqual(e.name, month)
720 self.assertIn(e, SummerMonth)
721 self.assertIs(type(e), SummerMonth)
722
Martin Pantereb995702016-07-28 01:11:04 +0000723 def test_programmatic_function_string_list(self):
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700724 SummerMonth = Enum('SummerMonth', ['june', 'july', 'august'])
725 lst = list(SummerMonth)
726 self.assertEqual(len(lst), len(SummerMonth))
727 self.assertEqual(len(SummerMonth), 3, SummerMonth)
728 self.assertEqual(
729 [SummerMonth.june, SummerMonth.july, SummerMonth.august],
730 lst,
731 )
732 for i, month in enumerate('june july august'.split(), 1):
733 e = SummerMonth(i)
734 self.assertEqual(int(e.value), i)
735 self.assertNotEqual(e, i)
736 self.assertEqual(e.name, month)
737 self.assertIn(e, SummerMonth)
738 self.assertIs(type(e), SummerMonth)
739
Martin Pantereb995702016-07-28 01:11:04 +0000740 def test_programmatic_function_string_list_with_start(self):
Ethan Furmand9925a12014-09-16 20:35:55 -0700741 SummerMonth = Enum('SummerMonth', ['june', 'july', 'august'], start=20)
742 lst = list(SummerMonth)
743 self.assertEqual(len(lst), len(SummerMonth))
744 self.assertEqual(len(SummerMonth), 3, SummerMonth)
745 self.assertEqual(
746 [SummerMonth.june, SummerMonth.july, SummerMonth.august],
747 lst,
748 )
749 for i, month in enumerate('june july august'.split(), 20):
750 e = SummerMonth(i)
751 self.assertEqual(int(e.value), i)
752 self.assertNotEqual(e, i)
753 self.assertEqual(e.name, month)
754 self.assertIn(e, SummerMonth)
755 self.assertIs(type(e), SummerMonth)
756
Martin Pantereb995702016-07-28 01:11:04 +0000757 def test_programmatic_function_iterable(self):
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700758 SummerMonth = Enum(
759 'SummerMonth',
760 (('june', 1), ('july', 2), ('august', 3))
761 )
762 lst = list(SummerMonth)
763 self.assertEqual(len(lst), len(SummerMonth))
764 self.assertEqual(len(SummerMonth), 3, SummerMonth)
765 self.assertEqual(
766 [SummerMonth.june, SummerMonth.july, SummerMonth.august],
767 lst,
768 )
769 for i, month in enumerate('june july august'.split(), 1):
770 e = SummerMonth(i)
771 self.assertEqual(int(e.value), i)
772 self.assertNotEqual(e, i)
773 self.assertEqual(e.name, month)
774 self.assertIn(e, SummerMonth)
775 self.assertIs(type(e), SummerMonth)
776
Martin Pantereb995702016-07-28 01:11:04 +0000777 def test_programmatic_function_from_dict(self):
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700778 SummerMonth = Enum(
779 'SummerMonth',
780 OrderedDict((('june', 1), ('july', 2), ('august', 3)))
781 )
782 lst = list(SummerMonth)
783 self.assertEqual(len(lst), len(SummerMonth))
784 self.assertEqual(len(SummerMonth), 3, SummerMonth)
785 self.assertEqual(
786 [SummerMonth.june, SummerMonth.july, SummerMonth.august],
787 lst,
788 )
789 for i, month in enumerate('june july august'.split(), 1):
790 e = SummerMonth(i)
791 self.assertEqual(int(e.value), i)
792 self.assertNotEqual(e, i)
793 self.assertEqual(e.name, month)
794 self.assertIn(e, SummerMonth)
795 self.assertIs(type(e), SummerMonth)
796
Martin Pantereb995702016-07-28 01:11:04 +0000797 def test_programmatic_function_type(self):
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700798 SummerMonth = Enum('SummerMonth', 'june july august', type=int)
799 lst = list(SummerMonth)
800 self.assertEqual(len(lst), len(SummerMonth))
801 self.assertEqual(len(SummerMonth), 3, SummerMonth)
802 self.assertEqual(
803 [SummerMonth.june, SummerMonth.july, SummerMonth.august],
804 lst,
805 )
806 for i, month in enumerate('june july august'.split(), 1):
807 e = SummerMonth(i)
808 self.assertEqual(e, i)
809 self.assertEqual(e.name, month)
810 self.assertIn(e, SummerMonth)
811 self.assertIs(type(e), SummerMonth)
812
Martin Pantereb995702016-07-28 01:11:04 +0000813 def test_programmatic_function_type_with_start(self):
Ethan Furmand9925a12014-09-16 20:35:55 -0700814 SummerMonth = Enum('SummerMonth', 'june july august', type=int, start=30)
815 lst = list(SummerMonth)
816 self.assertEqual(len(lst), len(SummerMonth))
817 self.assertEqual(len(SummerMonth), 3, SummerMonth)
818 self.assertEqual(
819 [SummerMonth.june, SummerMonth.july, SummerMonth.august],
820 lst,
821 )
822 for i, month in enumerate('june july august'.split(), 30):
823 e = SummerMonth(i)
824 self.assertEqual(e, i)
825 self.assertEqual(e.name, month)
826 self.assertIn(e, SummerMonth)
827 self.assertIs(type(e), SummerMonth)
828
Martin Pantereb995702016-07-28 01:11:04 +0000829 def test_programmatic_function_type_from_subclass(self):
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700830 SummerMonth = IntEnum('SummerMonth', 'june july august')
831 lst = list(SummerMonth)
832 self.assertEqual(len(lst), len(SummerMonth))
833 self.assertEqual(len(SummerMonth), 3, SummerMonth)
834 self.assertEqual(
835 [SummerMonth.june, SummerMonth.july, SummerMonth.august],
836 lst,
837 )
838 for i, month in enumerate('june july august'.split(), 1):
839 e = SummerMonth(i)
840 self.assertEqual(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_type_from_subclass_with_start(self):
Ethan Furmand9925a12014-09-16 20:35:55 -0700846 SummerMonth = IntEnum('SummerMonth', 'june july august', start=40)
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(), 40):
855 e = SummerMonth(i)
856 self.assertEqual(e, i)
857 self.assertEqual(e.name, month)
858 self.assertIn(e, SummerMonth)
859 self.assertIs(type(e), SummerMonth)
860
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700861 def test_subclassing(self):
862 if isinstance(Name, Exception):
863 raise Name
864 self.assertEqual(Name.BDFL, 'Guido van Rossum')
865 self.assertTrue(Name.BDFL, Name('Guido van Rossum'))
866 self.assertIs(Name.BDFL, getattr(Name, 'BDFL'))
Ethan Furman2ddb39a2014-02-06 17:28:50 -0800867 test_pickle_dump_load(self.assertIs, Name.BDFL)
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700868
869 def test_extending(self):
870 class Color(Enum):
871 red = 1
872 green = 2
873 blue = 3
874 with self.assertRaises(TypeError):
875 class MoreColor(Color):
876 cyan = 4
877 magenta = 5
878 yellow = 6
879
880 def test_exclude_methods(self):
881 class whatever(Enum):
882 this = 'that'
883 these = 'those'
884 def really(self):
885 return 'no, not %s' % self.value
886 self.assertIsNot(type(whatever.really), whatever)
887 self.assertEqual(whatever.this.really(), 'no, not that')
888
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700889 def test_wrong_inheritance_order(self):
890 with self.assertRaises(TypeError):
891 class Wrong(Enum, str):
892 NotHere = 'error before this point'
893
894 def test_intenum_transitivity(self):
895 class number(IntEnum):
896 one = 1
897 two = 2
898 three = 3
899 class numero(IntEnum):
900 uno = 1
901 dos = 2
902 tres = 3
903 self.assertEqual(number.one, numero.uno)
904 self.assertEqual(number.two, numero.dos)
905 self.assertEqual(number.three, numero.tres)
906
907 def test_wrong_enum_in_call(self):
908 class Monochrome(Enum):
909 black = 0
910 white = 1
911 class Gender(Enum):
912 male = 0
913 female = 1
914 self.assertRaises(ValueError, Monochrome, Gender.male)
915
916 def test_wrong_enum_in_mixed_call(self):
917 class Monochrome(IntEnum):
918 black = 0
919 white = 1
920 class Gender(Enum):
921 male = 0
922 female = 1
923 self.assertRaises(ValueError, Monochrome, Gender.male)
924
925 def test_mixed_enum_in_call_1(self):
926 class Monochrome(IntEnum):
927 black = 0
928 white = 1
929 class Gender(IntEnum):
930 male = 0
931 female = 1
932 self.assertIs(Monochrome(Gender.female), Monochrome.white)
933
934 def test_mixed_enum_in_call_2(self):
935 class Monochrome(Enum):
936 black = 0
937 white = 1
938 class Gender(IntEnum):
939 male = 0
940 female = 1
941 self.assertIs(Monochrome(Gender.male), Monochrome.black)
942
943 def test_flufl_enum(self):
944 class Fluflnum(Enum):
945 def __int__(self):
946 return int(self.value)
947 class MailManOptions(Fluflnum):
948 option1 = 1
949 option2 = 2
950 option3 = 3
951 self.assertEqual(int(MailManOptions.option1), 1)
952
Ethan Furman5e5a8232013-08-04 08:42:23 -0700953 def test_introspection(self):
954 class Number(IntEnum):
955 one = 100
956 two = 200
957 self.assertIs(Number.one._member_type_, int)
958 self.assertIs(Number._member_type_, int)
959 class String(str, Enum):
960 yarn = 'soft'
961 rope = 'rough'
962 wire = 'hard'
963 self.assertIs(String.yarn._member_type_, str)
964 self.assertIs(String._member_type_, str)
965 class Plain(Enum):
966 vanilla = 'white'
967 one = 1
968 self.assertIs(Plain.vanilla._member_type_, object)
969 self.assertIs(Plain._member_type_, object)
970
Ethan Furman6b3d64a2013-06-14 16:55:46 -0700971 def test_no_such_enum_member(self):
972 class Color(Enum):
973 red = 1
974 green = 2
975 blue = 3
976 with self.assertRaises(ValueError):
977 Color(4)
978 with self.assertRaises(KeyError):
979 Color['chartreuse']
980
981 def test_new_repr(self):
982 class Color(Enum):
983 red = 1
984 green = 2
985 blue = 3
986 def __repr__(self):
987 return "don't you just love shades of %s?" % self.name
988 self.assertEqual(
989 repr(Color.blue),
990 "don't you just love shades of blue?",
991 )
992
993 def test_inherited_repr(self):
994 class MyEnum(Enum):
995 def __repr__(self):
996 return "My name is %s." % self.name
997 class MyIntEnum(int, MyEnum):
998 this = 1
999 that = 2
1000 theother = 3
1001 self.assertEqual(repr(MyIntEnum.that), "My name is that.")
1002
1003 def test_multiple_mixin_mro(self):
1004 class auto_enum(type(Enum)):
1005 def __new__(metacls, cls, bases, classdict):
1006 temp = type(classdict)()
1007 names = set(classdict._member_names)
1008 i = 0
1009 for k in classdict._member_names:
1010 v = classdict[k]
1011 if v is Ellipsis:
1012 v = i
1013 else:
1014 i = v
1015 i += 1
1016 temp[k] = v
1017 for k, v in classdict.items():
1018 if k not in names:
1019 temp[k] = v
1020 return super(auto_enum, metacls).__new__(
1021 metacls, cls, bases, temp)
1022
1023 class AutoNumberedEnum(Enum, metaclass=auto_enum):
1024 pass
1025
1026 class AutoIntEnum(IntEnum, metaclass=auto_enum):
1027 pass
1028
1029 class TestAutoNumber(AutoNumberedEnum):
1030 a = ...
1031 b = 3
1032 c = ...
1033
1034 class TestAutoInt(AutoIntEnum):
1035 a = ...
1036 b = 3
1037 c = ...
1038
1039 def test_subclasses_with_getnewargs(self):
1040 class NamedInt(int):
Ethan Furman2ddb39a2014-02-06 17:28:50 -08001041 __qualname__ = 'NamedInt' # needed for pickle protocol 4
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001042 def __new__(cls, *args):
1043 _args = args
1044 name, *args = args
1045 if len(args) == 0:
1046 raise TypeError("name and value must be specified")
1047 self = int.__new__(cls, *args)
1048 self._intname = name
1049 self._args = _args
1050 return self
1051 def __getnewargs__(self):
1052 return self._args
1053 @property
1054 def __name__(self):
1055 return self._intname
1056 def __repr__(self):
1057 # repr() is updated to include the name and type info
1058 return "{}({!r}, {})".format(type(self).__name__,
1059 self.__name__,
1060 int.__repr__(self))
1061 def __str__(self):
1062 # str() is unchanged, even if it relies on the repr() fallback
1063 base = int
1064 base_str = base.__str__
1065 if base_str.__objclass__ is object:
1066 return base.__repr__(self)
1067 return base_str(self)
1068 # for simplicity, we only define one operator that
1069 # propagates expressions
1070 def __add__(self, other):
1071 temp = int(self) + int( other)
1072 if isinstance(self, NamedInt) and isinstance(other, NamedInt):
1073 return NamedInt(
1074 '({0} + {1})'.format(self.__name__, other.__name__),
1075 temp )
1076 else:
1077 return temp
1078
1079 class NEI(NamedInt, Enum):
Ethan Furman2ddb39a2014-02-06 17:28:50 -08001080 __qualname__ = 'NEI' # needed for pickle protocol 4
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001081 x = ('the-x', 1)
1082 y = ('the-y', 2)
1083
Ethan Furman2aa27322013-07-19 19:35:56 -07001084
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001085 self.assertIs(NEI.__new__, Enum.__new__)
1086 self.assertEqual(repr(NEI.x + NEI.y), "NamedInt('(the-x + the-y)', 3)")
1087 globals()['NamedInt'] = NamedInt
1088 globals()['NEI'] = NEI
1089 NI5 = NamedInt('test', 5)
1090 self.assertEqual(NI5, 5)
Ethan Furman2ddb39a2014-02-06 17:28:50 -08001091 test_pickle_dump_load(self.assertEqual, NI5, 5)
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001092 self.assertEqual(NEI.y.value, 2)
Ethan Furman2ddb39a2014-02-06 17:28:50 -08001093 test_pickle_dump_load(self.assertIs, NEI.y)
Ethan Furmandc870522014-02-18 12:37:12 -08001094 test_pickle_dump_load(self.assertIs, NEI)
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001095
Ethan Furmanca1b7942014-02-08 11:36:27 -08001096 def test_subclasses_with_getnewargs_ex(self):
1097 class NamedInt(int):
1098 __qualname__ = 'NamedInt' # needed for pickle protocol 4
1099 def __new__(cls, *args):
1100 _args = args
1101 name, *args = args
1102 if len(args) == 0:
1103 raise TypeError("name and value must be specified")
1104 self = int.__new__(cls, *args)
1105 self._intname = name
1106 self._args = _args
1107 return self
1108 def __getnewargs_ex__(self):
1109 return self._args, {}
1110 @property
1111 def __name__(self):
1112 return self._intname
1113 def __repr__(self):
1114 # repr() is updated to include the name and type info
1115 return "{}({!r}, {})".format(type(self).__name__,
1116 self.__name__,
1117 int.__repr__(self))
1118 def __str__(self):
1119 # str() is unchanged, even if it relies on the repr() fallback
1120 base = int
1121 base_str = base.__str__
1122 if base_str.__objclass__ is object:
1123 return base.__repr__(self)
1124 return base_str(self)
1125 # for simplicity, we only define one operator that
1126 # propagates expressions
1127 def __add__(self, other):
1128 temp = int(self) + int( other)
1129 if isinstance(self, NamedInt) and isinstance(other, NamedInt):
1130 return NamedInt(
1131 '({0} + {1})'.format(self.__name__, other.__name__),
1132 temp )
1133 else:
1134 return temp
1135
1136 class NEI(NamedInt, Enum):
1137 __qualname__ = 'NEI' # needed for pickle protocol 4
1138 x = ('the-x', 1)
1139 y = ('the-y', 2)
1140
1141
1142 self.assertIs(NEI.__new__, Enum.__new__)
1143 self.assertEqual(repr(NEI.x + NEI.y), "NamedInt('(the-x + the-y)', 3)")
1144 globals()['NamedInt'] = NamedInt
1145 globals()['NEI'] = NEI
1146 NI5 = NamedInt('test', 5)
1147 self.assertEqual(NI5, 5)
Serhiy Storchakae50e7802015-03-31 16:56:49 +03001148 test_pickle_dump_load(self.assertEqual, NI5, 5)
Ethan Furmanca1b7942014-02-08 11:36:27 -08001149 self.assertEqual(NEI.y.value, 2)
Serhiy Storchakae50e7802015-03-31 16:56:49 +03001150 test_pickle_dump_load(self.assertIs, NEI.y)
Ethan Furmandc870522014-02-18 12:37:12 -08001151 test_pickle_dump_load(self.assertIs, NEI)
Ethan Furmanca1b7942014-02-08 11:36:27 -08001152
1153 def test_subclasses_with_reduce(self):
1154 class NamedInt(int):
1155 __qualname__ = 'NamedInt' # needed for pickle protocol 4
1156 def __new__(cls, *args):
1157 _args = args
1158 name, *args = args
1159 if len(args) == 0:
1160 raise TypeError("name and value must be specified")
1161 self = int.__new__(cls, *args)
1162 self._intname = name
1163 self._args = _args
1164 return self
1165 def __reduce__(self):
1166 return self.__class__, self._args
1167 @property
1168 def __name__(self):
1169 return self._intname
1170 def __repr__(self):
1171 # repr() is updated to include the name and type info
1172 return "{}({!r}, {})".format(type(self).__name__,
1173 self.__name__,
1174 int.__repr__(self))
1175 def __str__(self):
1176 # str() is unchanged, even if it relies on the repr() fallback
1177 base = int
1178 base_str = base.__str__
1179 if base_str.__objclass__ is object:
1180 return base.__repr__(self)
1181 return base_str(self)
1182 # for simplicity, we only define one operator that
1183 # propagates expressions
1184 def __add__(self, other):
1185 temp = int(self) + int( other)
1186 if isinstance(self, NamedInt) and isinstance(other, NamedInt):
1187 return NamedInt(
1188 '({0} + {1})'.format(self.__name__, other.__name__),
1189 temp )
1190 else:
1191 return temp
1192
1193 class NEI(NamedInt, Enum):
1194 __qualname__ = 'NEI' # needed for pickle protocol 4
1195 x = ('the-x', 1)
1196 y = ('the-y', 2)
1197
1198
1199 self.assertIs(NEI.__new__, Enum.__new__)
1200 self.assertEqual(repr(NEI.x + NEI.y), "NamedInt('(the-x + the-y)', 3)")
1201 globals()['NamedInt'] = NamedInt
1202 globals()['NEI'] = NEI
1203 NI5 = NamedInt('test', 5)
1204 self.assertEqual(NI5, 5)
1205 test_pickle_dump_load(self.assertEqual, NI5, 5)
1206 self.assertEqual(NEI.y.value, 2)
1207 test_pickle_dump_load(self.assertIs, NEI.y)
Ethan Furmandc870522014-02-18 12:37:12 -08001208 test_pickle_dump_load(self.assertIs, NEI)
Ethan Furmanca1b7942014-02-08 11:36:27 -08001209
1210 def test_subclasses_with_reduce_ex(self):
1211 class NamedInt(int):
1212 __qualname__ = 'NamedInt' # needed for pickle protocol 4
1213 def __new__(cls, *args):
1214 _args = args
1215 name, *args = args
1216 if len(args) == 0:
1217 raise TypeError("name and value must be specified")
1218 self = int.__new__(cls, *args)
1219 self._intname = name
1220 self._args = _args
1221 return self
1222 def __reduce_ex__(self, proto):
1223 return self.__class__, self._args
1224 @property
1225 def __name__(self):
1226 return self._intname
1227 def __repr__(self):
1228 # repr() is updated to include the name and type info
1229 return "{}({!r}, {})".format(type(self).__name__,
1230 self.__name__,
1231 int.__repr__(self))
1232 def __str__(self):
1233 # str() is unchanged, even if it relies on the repr() fallback
1234 base = int
1235 base_str = base.__str__
1236 if base_str.__objclass__ is object:
1237 return base.__repr__(self)
1238 return base_str(self)
1239 # for simplicity, we only define one operator that
1240 # propagates expressions
1241 def __add__(self, other):
1242 temp = int(self) + int( other)
1243 if isinstance(self, NamedInt) and isinstance(other, NamedInt):
1244 return NamedInt(
1245 '({0} + {1})'.format(self.__name__, other.__name__),
1246 temp )
1247 else:
1248 return temp
1249
1250 class NEI(NamedInt, Enum):
1251 __qualname__ = 'NEI' # needed for pickle protocol 4
1252 x = ('the-x', 1)
1253 y = ('the-y', 2)
1254
1255
1256 self.assertIs(NEI.__new__, Enum.__new__)
1257 self.assertEqual(repr(NEI.x + NEI.y), "NamedInt('(the-x + the-y)', 3)")
1258 globals()['NamedInt'] = NamedInt
1259 globals()['NEI'] = NEI
1260 NI5 = NamedInt('test', 5)
1261 self.assertEqual(NI5, 5)
1262 test_pickle_dump_load(self.assertEqual, NI5, 5)
1263 self.assertEqual(NEI.y.value, 2)
1264 test_pickle_dump_load(self.assertIs, NEI.y)
Ethan Furmandc870522014-02-18 12:37:12 -08001265 test_pickle_dump_load(self.assertIs, NEI)
Ethan Furmanca1b7942014-02-08 11:36:27 -08001266
Ethan Furmandc870522014-02-18 12:37:12 -08001267 def test_subclasses_without_direct_pickle_support(self):
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001268 class NamedInt(int):
Ethan Furman2ddb39a2014-02-06 17:28:50 -08001269 __qualname__ = 'NamedInt'
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001270 def __new__(cls, *args):
1271 _args = args
1272 name, *args = args
1273 if len(args) == 0:
1274 raise TypeError("name and value must be specified")
1275 self = int.__new__(cls, *args)
1276 self._intname = name
1277 self._args = _args
1278 return self
1279 @property
1280 def __name__(self):
1281 return self._intname
1282 def __repr__(self):
1283 # repr() is updated to include the name and type info
1284 return "{}({!r}, {})".format(type(self).__name__,
1285 self.__name__,
1286 int.__repr__(self))
1287 def __str__(self):
1288 # str() is unchanged, even if it relies on the repr() fallback
1289 base = int
1290 base_str = base.__str__
1291 if base_str.__objclass__ is object:
1292 return base.__repr__(self)
1293 return base_str(self)
1294 # for simplicity, we only define one operator that
1295 # propagates expressions
1296 def __add__(self, other):
1297 temp = int(self) + int( other)
1298 if isinstance(self, NamedInt) and isinstance(other, NamedInt):
1299 return NamedInt(
1300 '({0} + {1})'.format(self.__name__, other.__name__),
1301 temp )
1302 else:
1303 return temp
1304
1305 class NEI(NamedInt, Enum):
Ethan Furman2ddb39a2014-02-06 17:28:50 -08001306 __qualname__ = 'NEI'
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001307 x = ('the-x', 1)
1308 y = ('the-y', 2)
1309
1310 self.assertIs(NEI.__new__, Enum.__new__)
1311 self.assertEqual(repr(NEI.x + NEI.y), "NamedInt('(the-x + the-y)', 3)")
1312 globals()['NamedInt'] = NamedInt
1313 globals()['NEI'] = NEI
1314 NI5 = NamedInt('test', 5)
1315 self.assertEqual(NI5, 5)
1316 self.assertEqual(NEI.y.value, 2)
Ethan Furman2ddb39a2014-02-06 17:28:50 -08001317 test_pickle_exception(self.assertRaises, TypeError, NEI.x)
1318 test_pickle_exception(self.assertRaises, PicklingError, NEI)
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001319
Ethan Furmandc870522014-02-18 12:37:12 -08001320 def test_subclasses_without_direct_pickle_support_using_name(self):
1321 class NamedInt(int):
1322 __qualname__ = 'NamedInt'
1323 def __new__(cls, *args):
1324 _args = args
1325 name, *args = args
1326 if len(args) == 0:
1327 raise TypeError("name and value must be specified")
1328 self = int.__new__(cls, *args)
1329 self._intname = name
1330 self._args = _args
1331 return self
1332 @property
1333 def __name__(self):
1334 return self._intname
1335 def __repr__(self):
1336 # repr() is updated to include the name and type info
1337 return "{}({!r}, {})".format(type(self).__name__,
1338 self.__name__,
1339 int.__repr__(self))
1340 def __str__(self):
1341 # str() is unchanged, even if it relies on the repr() fallback
1342 base = int
1343 base_str = base.__str__
1344 if base_str.__objclass__ is object:
1345 return base.__repr__(self)
1346 return base_str(self)
1347 # for simplicity, we only define one operator that
1348 # propagates expressions
1349 def __add__(self, other):
1350 temp = int(self) + int( other)
1351 if isinstance(self, NamedInt) and isinstance(other, NamedInt):
1352 return NamedInt(
1353 '({0} + {1})'.format(self.__name__, other.__name__),
1354 temp )
1355 else:
1356 return temp
1357
1358 class NEI(NamedInt, Enum):
1359 __qualname__ = 'NEI'
1360 x = ('the-x', 1)
1361 y = ('the-y', 2)
1362 def __reduce_ex__(self, proto):
1363 return getattr, (self.__class__, self._name_)
1364
1365 self.assertIs(NEI.__new__, Enum.__new__)
1366 self.assertEqual(repr(NEI.x + NEI.y), "NamedInt('(the-x + the-y)', 3)")
1367 globals()['NamedInt'] = NamedInt
1368 globals()['NEI'] = NEI
1369 NI5 = NamedInt('test', 5)
1370 self.assertEqual(NI5, 5)
1371 self.assertEqual(NEI.y.value, 2)
1372 test_pickle_dump_load(self.assertIs, NEI.y)
1373 test_pickle_dump_load(self.assertIs, NEI)
1374
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001375 def test_tuple_subclass(self):
1376 class SomeTuple(tuple, Enum):
Ethan Furman2ddb39a2014-02-06 17:28:50 -08001377 __qualname__ = 'SomeTuple' # needed for pickle protocol 4
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001378 first = (1, 'for the money')
1379 second = (2, 'for the show')
1380 third = (3, 'for the music')
1381 self.assertIs(type(SomeTuple.first), SomeTuple)
1382 self.assertIsInstance(SomeTuple.second, tuple)
1383 self.assertEqual(SomeTuple.third, (3, 'for the music'))
1384 globals()['SomeTuple'] = SomeTuple
Ethan Furman2ddb39a2014-02-06 17:28:50 -08001385 test_pickle_dump_load(self.assertIs, SomeTuple.first)
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001386
1387 def test_duplicate_values_give_unique_enum_items(self):
1388 class AutoNumber(Enum):
1389 first = ()
1390 second = ()
1391 third = ()
1392 def __new__(cls):
1393 value = len(cls.__members__) + 1
1394 obj = object.__new__(cls)
Ethan Furman520ad572013-07-19 19:47:21 -07001395 obj._value_ = value
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001396 return obj
1397 def __int__(self):
Ethan Furman520ad572013-07-19 19:47:21 -07001398 return int(self._value_)
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001399 self.assertEqual(
1400 list(AutoNumber),
1401 [AutoNumber.first, AutoNumber.second, AutoNumber.third],
1402 )
1403 self.assertEqual(int(AutoNumber.second), 2)
Ethan Furman2aa27322013-07-19 19:35:56 -07001404 self.assertEqual(AutoNumber.third.value, 3)
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001405 self.assertIs(AutoNumber(1), AutoNumber.first)
1406
1407 def test_inherited_new_from_enhanced_enum(self):
1408 class AutoNumber(Enum):
1409 def __new__(cls):
1410 value = len(cls.__members__) + 1
1411 obj = object.__new__(cls)
Ethan Furman520ad572013-07-19 19:47:21 -07001412 obj._value_ = value
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001413 return obj
1414 def __int__(self):
Ethan Furman520ad572013-07-19 19:47:21 -07001415 return int(self._value_)
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001416 class Color(AutoNumber):
1417 red = ()
1418 green = ()
1419 blue = ()
1420 self.assertEqual(list(Color), [Color.red, Color.green, Color.blue])
1421 self.assertEqual(list(map(int, Color)), [1, 2, 3])
1422
1423 def test_inherited_new_from_mixed_enum(self):
1424 class AutoNumber(IntEnum):
1425 def __new__(cls):
1426 value = len(cls.__members__) + 1
1427 obj = int.__new__(cls, value)
Ethan Furman520ad572013-07-19 19:47:21 -07001428 obj._value_ = value
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001429 return obj
1430 class Color(AutoNumber):
1431 red = ()
1432 green = ()
1433 blue = ()
1434 self.assertEqual(list(Color), [Color.red, Color.green, Color.blue])
1435 self.assertEqual(list(map(int, Color)), [1, 2, 3])
1436
Ethan Furmanbe3c2fe2013-11-13 14:25:45 -08001437 def test_equality(self):
1438 class AlwaysEqual:
1439 def __eq__(self, other):
1440 return True
1441 class OrdinaryEnum(Enum):
1442 a = 1
1443 self.assertEqual(AlwaysEqual(), OrdinaryEnum.a)
1444 self.assertEqual(OrdinaryEnum.a, AlwaysEqual())
1445
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001446 def test_ordered_mixin(self):
1447 class OrderedEnum(Enum):
1448 def __ge__(self, other):
1449 if self.__class__ is other.__class__:
Ethan Furman520ad572013-07-19 19:47:21 -07001450 return self._value_ >= other._value_
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001451 return NotImplemented
1452 def __gt__(self, other):
1453 if self.__class__ is other.__class__:
Ethan Furman520ad572013-07-19 19:47:21 -07001454 return self._value_ > other._value_
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001455 return NotImplemented
1456 def __le__(self, other):
1457 if self.__class__ is other.__class__:
Ethan Furman520ad572013-07-19 19:47:21 -07001458 return self._value_ <= other._value_
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001459 return NotImplemented
1460 def __lt__(self, other):
1461 if self.__class__ is other.__class__:
Ethan Furman520ad572013-07-19 19:47:21 -07001462 return self._value_ < other._value_
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001463 return NotImplemented
1464 class Grade(OrderedEnum):
1465 A = 5
1466 B = 4
1467 C = 3
1468 D = 2
1469 F = 1
1470 self.assertGreater(Grade.A, Grade.B)
1471 self.assertLessEqual(Grade.F, Grade.C)
1472 self.assertLess(Grade.D, Grade.A)
1473 self.assertGreaterEqual(Grade.B, Grade.B)
Ethan Furmanbe3c2fe2013-11-13 14:25:45 -08001474 self.assertEqual(Grade.B, Grade.B)
1475 self.assertNotEqual(Grade.C, Grade.D)
Ethan Furman520ad572013-07-19 19:47:21 -07001476
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001477 def test_extending2(self):
1478 class Shade(Enum):
1479 def shade(self):
1480 print(self.name)
1481 class Color(Shade):
1482 red = 1
1483 green = 2
1484 blue = 3
1485 with self.assertRaises(TypeError):
1486 class MoreColor(Color):
1487 cyan = 4
1488 magenta = 5
1489 yellow = 6
1490
1491 def test_extending3(self):
1492 class Shade(Enum):
1493 def shade(self):
1494 return self.name
1495 class Color(Shade):
1496 def hex(self):
1497 return '%s hexlified!' % self.value
1498 class MoreColor(Color):
1499 cyan = 4
1500 magenta = 5
1501 yellow = 6
1502 self.assertEqual(MoreColor.magenta.hex(), '5 hexlified!')
1503
1504
1505 def test_no_duplicates(self):
1506 class UniqueEnum(Enum):
1507 def __init__(self, *args):
1508 cls = self.__class__
1509 if any(self.value == e.value for e in cls):
1510 a = self.name
1511 e = cls(self.value).name
1512 raise ValueError(
1513 "aliases not allowed in UniqueEnum: %r --> %r"
1514 % (a, e)
1515 )
1516 class Color(UniqueEnum):
1517 red = 1
1518 green = 2
1519 blue = 3
1520 with self.assertRaises(ValueError):
1521 class Color(UniqueEnum):
1522 red = 1
1523 green = 2
1524 blue = 3
1525 grene = 2
1526
1527 def test_init(self):
1528 class Planet(Enum):
1529 MERCURY = (3.303e+23, 2.4397e6)
1530 VENUS = (4.869e+24, 6.0518e6)
1531 EARTH = (5.976e+24, 6.37814e6)
1532 MARS = (6.421e+23, 3.3972e6)
1533 JUPITER = (1.9e+27, 7.1492e7)
1534 SATURN = (5.688e+26, 6.0268e7)
1535 URANUS = (8.686e+25, 2.5559e7)
1536 NEPTUNE = (1.024e+26, 2.4746e7)
1537 def __init__(self, mass, radius):
1538 self.mass = mass # in kilograms
1539 self.radius = radius # in meters
1540 @property
1541 def surface_gravity(self):
1542 # universal gravitational constant (m3 kg-1 s-2)
1543 G = 6.67300E-11
1544 return G * self.mass / (self.radius * self.radius)
1545 self.assertEqual(round(Planet.EARTH.surface_gravity, 2), 9.80)
1546 self.assertEqual(Planet.EARTH.value, (5.976e+24, 6.37814e6))
1547
Ethan Furman2aa27322013-07-19 19:35:56 -07001548 def test_nonhash_value(self):
1549 class AutoNumberInAList(Enum):
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 Furman2aa27322013-07-19 19:35:56 -07001554 return obj
1555 class ColorInAList(AutoNumberInAList):
1556 red = ()
1557 green = ()
1558 blue = ()
1559 self.assertEqual(list(ColorInAList), [ColorInAList.red, ColorInAList.green, ColorInAList.blue])
Ethan Furman1a162882013-10-16 19:09:31 -07001560 for enum, value in zip(ColorInAList, range(3)):
1561 value += 1
1562 self.assertEqual(enum.value, [value])
1563 self.assertIs(ColorInAList([value]), enum)
Ethan Furman2aa27322013-07-19 19:35:56 -07001564
Ethan Furmanb41803e2013-07-25 13:50:45 -07001565 def test_conflicting_types_resolved_in_new(self):
1566 class LabelledIntEnum(int, Enum):
1567 def __new__(cls, *args):
1568 value, label = args
1569 obj = int.__new__(cls, value)
1570 obj.label = label
1571 obj._value_ = value
1572 return obj
1573
1574 class LabelledList(LabelledIntEnum):
1575 unprocessed = (1, "Unprocessed")
1576 payment_complete = (2, "Payment Complete")
1577
1578 self.assertEqual(list(LabelledList), [LabelledList.unprocessed, LabelledList.payment_complete])
1579 self.assertEqual(LabelledList.unprocessed, 1)
1580 self.assertEqual(LabelledList(1), LabelledList.unprocessed)
Ethan Furman2aa27322013-07-19 19:35:56 -07001581
Ethan Furmanc16595e2016-09-10 23:36:59 -07001582 def test_auto_number(self):
1583 class Color(Enum):
1584 red = auto()
1585 blue = auto()
1586 green = auto()
1587
1588 self.assertEqual(list(Color), [Color.red, Color.blue, Color.green])
1589 self.assertEqual(Color.red.value, 1)
1590 self.assertEqual(Color.blue.value, 2)
1591 self.assertEqual(Color.green.value, 3)
1592
1593 def test_auto_name(self):
1594 class Color(Enum):
1595 def _generate_next_value_(name, start, count, last):
1596 return name
1597 red = auto()
1598 blue = auto()
1599 green = auto()
1600
1601 self.assertEqual(list(Color), [Color.red, Color.blue, Color.green])
1602 self.assertEqual(Color.red.value, 'red')
1603 self.assertEqual(Color.blue.value, 'blue')
1604 self.assertEqual(Color.green.value, 'green')
1605
1606 def test_auto_name_inherit(self):
1607 class AutoNameEnum(Enum):
1608 def _generate_next_value_(name, start, count, last):
1609 return name
1610 class Color(AutoNameEnum):
1611 red = auto()
1612 blue = auto()
1613 green = auto()
1614
1615 self.assertEqual(list(Color), [Color.red, Color.blue, Color.green])
1616 self.assertEqual(Color.red.value, 'red')
1617 self.assertEqual(Color.blue.value, 'blue')
1618 self.assertEqual(Color.green.value, 'green')
1619
1620 def test_auto_garbage(self):
1621 class Color(Enum):
1622 red = 'red'
1623 blue = auto()
1624 self.assertEqual(Color.blue.value, 1)
1625
1626 def test_auto_garbage_corrected(self):
1627 class Color(Enum):
1628 red = 'red'
1629 blue = 2
1630 green = auto()
1631
1632 self.assertEqual(list(Color), [Color.red, Color.blue, Color.green])
1633 self.assertEqual(Color.red.value, 'red')
1634 self.assertEqual(Color.blue.value, 2)
1635 self.assertEqual(Color.green.value, 3)
1636
Ethan Furman6b3d64a2013-06-14 16:55:46 -07001637
Ethan Furmane8e61272016-08-20 07:19:31 -07001638class TestOrder(unittest.TestCase):
1639
1640 def test_same_members(self):
1641 class Color(Enum):
1642 _order_ = 'red green blue'
1643 red = 1
1644 green = 2
1645 blue = 3
1646
1647 def test_same_members_with_aliases(self):
1648 class Color(Enum):
1649 _order_ = 'red green blue'
1650 red = 1
1651 green = 2
1652 blue = 3
1653 verde = green
1654
1655 def test_same_members_wrong_order(self):
1656 with self.assertRaisesRegex(TypeError, 'member order does not match _order_'):
1657 class Color(Enum):
1658 _order_ = 'red green blue'
1659 red = 1
1660 blue = 3
1661 green = 2
1662
1663 def test_order_has_extra_members(self):
1664 with self.assertRaisesRegex(TypeError, 'member order does not match _order_'):
1665 class Color(Enum):
1666 _order_ = 'red green blue purple'
1667 red = 1
1668 green = 2
1669 blue = 3
1670
1671 def test_order_has_extra_members_with_aliases(self):
1672 with self.assertRaisesRegex(TypeError, 'member order does not match _order_'):
1673 class Color(Enum):
1674 _order_ = 'red green blue purple'
1675 red = 1
1676 green = 2
1677 blue = 3
1678 verde = green
1679
1680 def test_enum_has_extra_members(self):
1681 with self.assertRaisesRegex(TypeError, 'member order does not match _order_'):
1682 class Color(Enum):
1683 _order_ = 'red green blue'
1684 red = 1
1685 green = 2
1686 blue = 3
1687 purple = 4
1688
1689 def test_enum_has_extra_members_with_aliases(self):
1690 with self.assertRaisesRegex(TypeError, 'member order does not match _order_'):
1691 class Color(Enum):
1692 _order_ = 'red green blue'
1693 red = 1
1694 green = 2
1695 blue = 3
1696 purple = 4
1697 verde = green
1698
1699
Ethan Furman65a5a472016-09-01 23:55:19 -07001700class TestFlag(unittest.TestCase):
Ethan Furmanee47e5c2016-08-31 00:12:15 -07001701 """Tests of the Flags."""
1702
Ethan Furman65a5a472016-09-01 23:55:19 -07001703 class Perm(Flag):
Ethan Furmanee47e5c2016-08-31 00:12:15 -07001704 R, W, X = 4, 2, 1
1705
Ethan Furman65a5a472016-09-01 23:55:19 -07001706 class Open(Flag):
Ethan Furmanee47e5c2016-08-31 00:12:15 -07001707 RO = 0
1708 WO = 1
1709 RW = 2
1710 AC = 3
1711 CE = 1<<19
1712
1713 def test_str(self):
1714 Perm = self.Perm
1715 self.assertEqual(str(Perm.R), 'Perm.R')
1716 self.assertEqual(str(Perm.W), 'Perm.W')
1717 self.assertEqual(str(Perm.X), 'Perm.X')
1718 self.assertEqual(str(Perm.R | Perm.W), 'Perm.R|W')
1719 self.assertEqual(str(Perm.R | Perm.W | Perm.X), 'Perm.R|W|X')
1720 self.assertEqual(str(Perm(0)), 'Perm.0')
1721 self.assertEqual(str(~Perm.R), 'Perm.W|X')
1722 self.assertEqual(str(~Perm.W), 'Perm.R|X')
1723 self.assertEqual(str(~Perm.X), 'Perm.R|W')
1724 self.assertEqual(str(~(Perm.R | Perm.W)), 'Perm.X')
1725 self.assertEqual(str(~(Perm.R | Perm.W | Perm.X)), 'Perm.0')
1726 self.assertEqual(str(Perm(~0)), 'Perm.R|W|X')
1727
1728 Open = self.Open
1729 self.assertEqual(str(Open.RO), 'Open.RO')
1730 self.assertEqual(str(Open.WO), 'Open.WO')
1731 self.assertEqual(str(Open.AC), 'Open.AC')
1732 self.assertEqual(str(Open.RO | Open.CE), 'Open.CE')
1733 self.assertEqual(str(Open.WO | Open.CE), 'Open.CE|WO')
1734 self.assertEqual(str(~Open.RO), 'Open.CE|AC')
1735 self.assertEqual(str(~Open.WO), 'Open.CE|RW')
1736 self.assertEqual(str(~Open.AC), 'Open.CE')
1737 self.assertEqual(str(~(Open.RO | Open.CE)), 'Open.AC')
1738 self.assertEqual(str(~(Open.WO | Open.CE)), 'Open.RW')
1739
1740 def test_repr(self):
1741 Perm = self.Perm
1742 self.assertEqual(repr(Perm.R), '<Perm.R: 4>')
1743 self.assertEqual(repr(Perm.W), '<Perm.W: 2>')
1744 self.assertEqual(repr(Perm.X), '<Perm.X: 1>')
1745 self.assertEqual(repr(Perm.R | Perm.W), '<Perm.R|W: 6>')
1746 self.assertEqual(repr(Perm.R | Perm.W | Perm.X), '<Perm.R|W|X: 7>')
Ethan Furman27682d22016-09-04 11:39:01 -07001747 self.assertEqual(repr(Perm(0)), '<Perm.0: 0>')
Ethan Furmanee47e5c2016-08-31 00:12:15 -07001748 self.assertEqual(repr(~Perm.R), '<Perm.W|X: 3>')
1749 self.assertEqual(repr(~Perm.W), '<Perm.R|X: 5>')
1750 self.assertEqual(repr(~Perm.X), '<Perm.R|W: 6>')
1751 self.assertEqual(repr(~(Perm.R | Perm.W)), '<Perm.X: 1>')
Ethan Furman27682d22016-09-04 11:39:01 -07001752 self.assertEqual(repr(~(Perm.R | Perm.W | Perm.X)), '<Perm.0: 0>')
Ethan Furmanee47e5c2016-08-31 00:12:15 -07001753 self.assertEqual(repr(Perm(~0)), '<Perm.R|W|X: 7>')
1754
1755 Open = self.Open
1756 self.assertEqual(repr(Open.RO), '<Open.RO: 0>')
1757 self.assertEqual(repr(Open.WO), '<Open.WO: 1>')
1758 self.assertEqual(repr(Open.AC), '<Open.AC: 3>')
1759 self.assertEqual(repr(Open.RO | Open.CE), '<Open.CE: 524288>')
1760 self.assertEqual(repr(Open.WO | Open.CE), '<Open.CE|WO: 524289>')
1761 self.assertEqual(repr(~Open.RO), '<Open.CE|AC: 524291>')
1762 self.assertEqual(repr(~Open.WO), '<Open.CE|RW: 524290>')
1763 self.assertEqual(repr(~Open.AC), '<Open.CE: 524288>')
1764 self.assertEqual(repr(~(Open.RO | Open.CE)), '<Open.AC: 3>')
1765 self.assertEqual(repr(~(Open.WO | Open.CE)), '<Open.RW: 2>')
1766
1767 def test_or(self):
1768 Perm = self.Perm
1769 for i in Perm:
1770 for j in Perm:
1771 self.assertEqual((i | j), Perm(i.value | j.value))
1772 self.assertEqual((i | j).value, i.value | j.value)
1773 self.assertIs(type(i | j), Perm)
1774 for i in Perm:
1775 self.assertIs(i | i, i)
1776 Open = self.Open
1777 self.assertIs(Open.RO | Open.CE, Open.CE)
1778
1779 def test_and(self):
1780 Perm = self.Perm
1781 RW = Perm.R | Perm.W
1782 RX = Perm.R | Perm.X
1783 WX = Perm.W | Perm.X
1784 RWX = Perm.R | Perm.W | Perm.X
1785 values = list(Perm) + [RW, RX, WX, RWX, Perm(0)]
1786 for i in values:
1787 for j in values:
1788 self.assertEqual((i & j).value, i.value & j.value)
1789 self.assertIs(type(i & j), Perm)
1790 for i in Perm:
1791 self.assertIs(i & i, i)
1792 self.assertIs(i & RWX, i)
1793 self.assertIs(RWX & i, i)
1794 Open = self.Open
1795 self.assertIs(Open.RO & Open.CE, Open.RO)
1796
1797 def test_xor(self):
1798 Perm = self.Perm
1799 for i in Perm:
1800 for j in Perm:
1801 self.assertEqual((i ^ j).value, i.value ^ j.value)
1802 self.assertIs(type(i ^ j), Perm)
1803 for i in Perm:
1804 self.assertIs(i ^ Perm(0), i)
1805 self.assertIs(Perm(0) ^ i, i)
1806 Open = self.Open
1807 self.assertIs(Open.RO ^ Open.CE, Open.CE)
1808 self.assertIs(Open.CE ^ Open.CE, Open.RO)
1809
1810 def test_invert(self):
1811 Perm = self.Perm
1812 RW = Perm.R | Perm.W
1813 RX = Perm.R | Perm.X
1814 WX = Perm.W | Perm.X
1815 RWX = Perm.R | Perm.W | Perm.X
1816 values = list(Perm) + [RW, RX, WX, RWX, Perm(0)]
1817 for i in values:
1818 self.assertIs(type(~i), Perm)
1819 self.assertEqual(~~i, i)
1820 for i in Perm:
1821 self.assertIs(~~i, i)
1822 Open = self.Open
1823 self.assertIs(Open.WO & ~Open.WO, Open.RO)
1824 self.assertIs((Open.WO|Open.CE) & ~Open.WO, Open.CE)
1825
Ethan Furman25d94bb2016-09-02 16:32:32 -07001826 def test_bool(self):
1827 Perm = self.Perm
1828 for f in Perm:
1829 self.assertTrue(f)
1830 Open = self.Open
1831 for f in Open:
1832 self.assertEqual(bool(f.value), bool(f))
1833
Ethan Furmanee47e5c2016-08-31 00:12:15 -07001834 def test_programatic_function_string(self):
Ethan Furman65a5a472016-09-01 23:55:19 -07001835 Perm = Flag('Perm', 'R W X')
Ethan Furmanee47e5c2016-08-31 00:12:15 -07001836 lst = list(Perm)
1837 self.assertEqual(len(lst), len(Perm))
1838 self.assertEqual(len(Perm), 3, Perm)
1839 self.assertEqual(lst, [Perm.R, Perm.W, Perm.X])
1840 for i, n in enumerate('R W X'.split()):
1841 v = 1<<i
1842 e = Perm(v)
1843 self.assertEqual(e.value, v)
1844 self.assertEqual(type(e.value), int)
1845 self.assertEqual(e.name, n)
1846 self.assertIn(e, Perm)
1847 self.assertIs(type(e), Perm)
1848
1849 def test_programatic_function_string_with_start(self):
Ethan Furman65a5a472016-09-01 23:55:19 -07001850 Perm = Flag('Perm', 'R W X', start=8)
Ethan Furmanee47e5c2016-08-31 00:12:15 -07001851 lst = list(Perm)
1852 self.assertEqual(len(lst), len(Perm))
1853 self.assertEqual(len(Perm), 3, Perm)
1854 self.assertEqual(lst, [Perm.R, Perm.W, Perm.X])
1855 for i, n in enumerate('R W X'.split()):
1856 v = 8<<i
1857 e = Perm(v)
1858 self.assertEqual(e.value, v)
1859 self.assertEqual(type(e.value), int)
1860 self.assertEqual(e.name, n)
1861 self.assertIn(e, Perm)
1862 self.assertIs(type(e), Perm)
1863
1864 def test_programatic_function_string_list(self):
Ethan Furman65a5a472016-09-01 23:55:19 -07001865 Perm = Flag('Perm', ['R', 'W', 'X'])
Ethan Furmanee47e5c2016-08-31 00:12:15 -07001866 lst = list(Perm)
1867 self.assertEqual(len(lst), len(Perm))
1868 self.assertEqual(len(Perm), 3, Perm)
1869 self.assertEqual(lst, [Perm.R, Perm.W, Perm.X])
1870 for i, n in enumerate('R W X'.split()):
1871 v = 1<<i
1872 e = Perm(v)
1873 self.assertEqual(e.value, v)
1874 self.assertEqual(type(e.value), int)
1875 self.assertEqual(e.name, n)
1876 self.assertIn(e, Perm)
1877 self.assertIs(type(e), Perm)
1878
1879 def test_programatic_function_iterable(self):
Ethan Furman65a5a472016-09-01 23:55:19 -07001880 Perm = Flag('Perm', (('R', 2), ('W', 8), ('X', 32)))
Ethan Furmanee47e5c2016-08-31 00:12:15 -07001881 lst = list(Perm)
1882 self.assertEqual(len(lst), len(Perm))
1883 self.assertEqual(len(Perm), 3, Perm)
1884 self.assertEqual(lst, [Perm.R, Perm.W, Perm.X])
1885 for i, n in enumerate('R W X'.split()):
1886 v = 1<<(2*i+1)
1887 e = Perm(v)
1888 self.assertEqual(e.value, v)
1889 self.assertEqual(type(e.value), int)
1890 self.assertEqual(e.name, n)
1891 self.assertIn(e, Perm)
1892 self.assertIs(type(e), Perm)
1893
1894 def test_programatic_function_from_dict(self):
Ethan Furman65a5a472016-09-01 23:55:19 -07001895 Perm = Flag('Perm', OrderedDict((('R', 2), ('W', 8), ('X', 32))))
Ethan Furmanee47e5c2016-08-31 00:12:15 -07001896 lst = list(Perm)
1897 self.assertEqual(len(lst), len(Perm))
1898 self.assertEqual(len(Perm), 3, Perm)
1899 self.assertEqual(lst, [Perm.R, Perm.W, Perm.X])
1900 for i, n in enumerate('R W X'.split()):
1901 v = 1<<(2*i+1)
1902 e = Perm(v)
1903 self.assertEqual(e.value, v)
1904 self.assertEqual(type(e.value), int)
1905 self.assertEqual(e.name, n)
1906 self.assertIn(e, Perm)
1907 self.assertIs(type(e), Perm)
1908
Ethan Furman65a5a472016-09-01 23:55:19 -07001909 def test_pickle(self):
1910 if isinstance(FlagStooges, Exception):
1911 raise FlagStooges
1912 test_pickle_dump_load(self.assertIs, FlagStooges.CURLY|FlagStooges.MOE)
1913 test_pickle_dump_load(self.assertIs, FlagStooges)
Ethan Furmanee47e5c2016-08-31 00:12:15 -07001914
Ethan Furman65a5a472016-09-01 23:55:19 -07001915 def test_containment(self):
1916 Perm = self.Perm
1917 R, W, X = Perm
1918 RW = R | W
1919 RX = R | X
1920 WX = W | X
1921 RWX = R | W | X
1922 self.assertTrue(R in RW)
1923 self.assertTrue(R in RX)
1924 self.assertTrue(R in RWX)
1925 self.assertTrue(W in RW)
1926 self.assertTrue(W in WX)
1927 self.assertTrue(W in RWX)
1928 self.assertTrue(X in RX)
1929 self.assertTrue(X in WX)
1930 self.assertTrue(X in RWX)
1931 self.assertFalse(R in WX)
1932 self.assertFalse(W in RX)
1933 self.assertFalse(X in RW)
1934
Ethan Furmanc16595e2016-09-10 23:36:59 -07001935 def test_auto_number(self):
1936 class Color(Flag):
1937 red = auto()
1938 blue = auto()
1939 green = auto()
1940
1941 self.assertEqual(list(Color), [Color.red, Color.blue, Color.green])
1942 self.assertEqual(Color.red.value, 1)
1943 self.assertEqual(Color.blue.value, 2)
1944 self.assertEqual(Color.green.value, 4)
1945
1946 def test_auto_number_garbage(self):
1947 with self.assertRaisesRegex(TypeError, 'Invalid Flag value: .not an int.'):
1948 class Color(Flag):
1949 red = 'not an int'
1950 blue = auto()
1951
1952
Ethan Furman65a5a472016-09-01 23:55:19 -07001953class TestIntFlag(unittest.TestCase):
Ethan Furmanee47e5c2016-08-31 00:12:15 -07001954 """Tests of the IntFlags."""
1955
Ethan Furman65a5a472016-09-01 23:55:19 -07001956 class Perm(IntFlag):
Ethan Furmanee47e5c2016-08-31 00:12:15 -07001957 X = 1 << 0
1958 W = 1 << 1
1959 R = 1 << 2
1960
Ethan Furman65a5a472016-09-01 23:55:19 -07001961 class Open(IntFlag):
Ethan Furmanee47e5c2016-08-31 00:12:15 -07001962 RO = 0
1963 WO = 1
1964 RW = 2
1965 AC = 3
1966 CE = 1<<19
1967
1968 def test_str(self):
1969 Perm = self.Perm
1970 self.assertEqual(str(Perm.R), 'Perm.R')
1971 self.assertEqual(str(Perm.W), 'Perm.W')
1972 self.assertEqual(str(Perm.X), 'Perm.X')
1973 self.assertEqual(str(Perm.R | Perm.W), 'Perm.R|W')
1974 self.assertEqual(str(Perm.R | Perm.W | Perm.X), 'Perm.R|W|X')
1975 self.assertEqual(str(Perm.R | 8), 'Perm.8|R')
1976 self.assertEqual(str(Perm(0)), 'Perm.0')
1977 self.assertEqual(str(Perm(8)), 'Perm.8')
1978 self.assertEqual(str(~Perm.R), 'Perm.W|X|-8')
1979 self.assertEqual(str(~Perm.W), 'Perm.R|X|-8')
1980 self.assertEqual(str(~Perm.X), 'Perm.R|W|-8')
1981 self.assertEqual(str(~(Perm.R | Perm.W)), 'Perm.X|-8')
1982 self.assertEqual(str(~(Perm.R | Perm.W | Perm.X)), 'Perm.-8')
1983 self.assertEqual(str(~(Perm.R | 8)), 'Perm.W|X|-16')
1984 self.assertEqual(str(Perm(~0)), 'Perm.R|W|X|-8')
1985 self.assertEqual(str(Perm(~8)), 'Perm.R|W|X|-16')
1986
1987 Open = self.Open
1988 self.assertEqual(str(Open.RO), 'Open.RO')
1989 self.assertEqual(str(Open.WO), 'Open.WO')
1990 self.assertEqual(str(Open.AC), 'Open.AC')
1991 self.assertEqual(str(Open.RO | Open.CE), 'Open.CE')
1992 self.assertEqual(str(Open.WO | Open.CE), 'Open.CE|WO')
1993 self.assertEqual(str(Open(4)), 'Open.4')
1994 self.assertEqual(str(~Open.RO), 'Open.CE|AC|-524292')
1995 self.assertEqual(str(~Open.WO), 'Open.CE|RW|-524292')
1996 self.assertEqual(str(~Open.AC), 'Open.CE|-524292')
1997 self.assertEqual(str(~(Open.RO | Open.CE)), 'Open.AC|-524292')
1998 self.assertEqual(str(~(Open.WO | Open.CE)), 'Open.RW|-524292')
1999 self.assertEqual(str(Open(~4)), 'Open.CE|AC|-524296')
2000
2001 def test_repr(self):
2002 Perm = self.Perm
2003 self.assertEqual(repr(Perm.R), '<Perm.R: 4>')
2004 self.assertEqual(repr(Perm.W), '<Perm.W: 2>')
2005 self.assertEqual(repr(Perm.X), '<Perm.X: 1>')
2006 self.assertEqual(repr(Perm.R | Perm.W), '<Perm.R|W: 6>')
2007 self.assertEqual(repr(Perm.R | Perm.W | Perm.X), '<Perm.R|W|X: 7>')
2008 self.assertEqual(repr(Perm.R | 8), '<Perm.8|R: 12>')
Ethan Furman27682d22016-09-04 11:39:01 -07002009 self.assertEqual(repr(Perm(0)), '<Perm.0: 0>')
2010 self.assertEqual(repr(Perm(8)), '<Perm.8: 8>')
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002011 self.assertEqual(repr(~Perm.R), '<Perm.W|X|-8: -5>')
2012 self.assertEqual(repr(~Perm.W), '<Perm.R|X|-8: -3>')
2013 self.assertEqual(repr(~Perm.X), '<Perm.R|W|-8: -2>')
2014 self.assertEqual(repr(~(Perm.R | Perm.W)), '<Perm.X|-8: -7>')
Ethan Furman27682d22016-09-04 11:39:01 -07002015 self.assertEqual(repr(~(Perm.R | Perm.W | Perm.X)), '<Perm.-8: -8>')
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002016 self.assertEqual(repr(~(Perm.R | 8)), '<Perm.W|X|-16: -13>')
2017 self.assertEqual(repr(Perm(~0)), '<Perm.R|W|X|-8: -1>')
2018 self.assertEqual(repr(Perm(~8)), '<Perm.R|W|X|-16: -9>')
2019
2020 Open = self.Open
2021 self.assertEqual(repr(Open.RO), '<Open.RO: 0>')
2022 self.assertEqual(repr(Open.WO), '<Open.WO: 1>')
2023 self.assertEqual(repr(Open.AC), '<Open.AC: 3>')
2024 self.assertEqual(repr(Open.RO | Open.CE), '<Open.CE: 524288>')
2025 self.assertEqual(repr(Open.WO | Open.CE), '<Open.CE|WO: 524289>')
Ethan Furman27682d22016-09-04 11:39:01 -07002026 self.assertEqual(repr(Open(4)), '<Open.4: 4>')
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002027 self.assertEqual(repr(~Open.RO), '<Open.CE|AC|-524292: -1>')
2028 self.assertEqual(repr(~Open.WO), '<Open.CE|RW|-524292: -2>')
2029 self.assertEqual(repr(~Open.AC), '<Open.CE|-524292: -4>')
2030 self.assertEqual(repr(~(Open.RO | Open.CE)), '<Open.AC|-524292: -524289>')
2031 self.assertEqual(repr(~(Open.WO | Open.CE)), '<Open.RW|-524292: -524290>')
2032 self.assertEqual(repr(Open(~4)), '<Open.CE|AC|-524296: -5>')
2033
2034 def test_or(self):
2035 Perm = self.Perm
2036 for i in Perm:
2037 for j in Perm:
2038 self.assertEqual(i | j, i.value | j.value)
2039 self.assertEqual((i | j).value, i.value | j.value)
2040 self.assertIs(type(i | j), Perm)
2041 for j in range(8):
2042 self.assertEqual(i | j, i.value | j)
2043 self.assertEqual((i | j).value, i.value | j)
2044 self.assertIs(type(i | j), Perm)
2045 self.assertEqual(j | i, j | i.value)
2046 self.assertEqual((j | i).value, j | i.value)
2047 self.assertIs(type(j | i), Perm)
2048 for i in Perm:
2049 self.assertIs(i | i, i)
2050 self.assertIs(i | 0, i)
2051 self.assertIs(0 | i, i)
2052 Open = self.Open
2053 self.assertIs(Open.RO | Open.CE, Open.CE)
2054
2055 def test_and(self):
2056 Perm = self.Perm
2057 RW = Perm.R | Perm.W
2058 RX = Perm.R | Perm.X
2059 WX = Perm.W | Perm.X
2060 RWX = Perm.R | Perm.W | Perm.X
2061 values = list(Perm) + [RW, RX, WX, RWX, Perm(0)]
2062 for i in values:
2063 for j in values:
2064 self.assertEqual(i & j, i.value & j.value, 'i is %r, j is %r' % (i, j))
2065 self.assertEqual((i & j).value, i.value & j.value, 'i is %r, j is %r' % (i, j))
2066 self.assertIs(type(i & j), Perm, 'i is %r, j is %r' % (i, j))
2067 for j in range(8):
2068 self.assertEqual(i & j, i.value & j)
2069 self.assertEqual((i & j).value, i.value & j)
2070 self.assertIs(type(i & j), Perm)
2071 self.assertEqual(j & i, j & i.value)
2072 self.assertEqual((j & i).value, j & i.value)
2073 self.assertIs(type(j & i), Perm)
2074 for i in Perm:
2075 self.assertIs(i & i, i)
2076 self.assertIs(i & 7, i)
2077 self.assertIs(7 & i, i)
2078 Open = self.Open
2079 self.assertIs(Open.RO & Open.CE, Open.RO)
2080
2081 def test_xor(self):
2082 Perm = self.Perm
2083 for i in Perm:
2084 for j in Perm:
2085 self.assertEqual(i ^ j, i.value ^ j.value)
2086 self.assertEqual((i ^ j).value, i.value ^ j.value)
2087 self.assertIs(type(i ^ j), Perm)
2088 for j in range(8):
2089 self.assertEqual(i ^ j, i.value ^ j)
2090 self.assertEqual((i ^ j).value, i.value ^ j)
2091 self.assertIs(type(i ^ j), Perm)
2092 self.assertEqual(j ^ i, j ^ i.value)
2093 self.assertEqual((j ^ i).value, j ^ i.value)
2094 self.assertIs(type(j ^ i), Perm)
2095 for i in Perm:
2096 self.assertIs(i ^ 0, i)
2097 self.assertIs(0 ^ i, i)
2098 Open = self.Open
2099 self.assertIs(Open.RO ^ Open.CE, Open.CE)
2100 self.assertIs(Open.CE ^ Open.CE, Open.RO)
2101
2102 def test_invert(self):
2103 Perm = self.Perm
2104 RW = Perm.R | Perm.W
2105 RX = Perm.R | Perm.X
2106 WX = Perm.W | Perm.X
2107 RWX = Perm.R | Perm.W | Perm.X
2108 values = list(Perm) + [RW, RX, WX, RWX, Perm(0)]
2109 for i in values:
2110 self.assertEqual(~i, ~i.value)
2111 self.assertEqual((~i).value, ~i.value)
2112 self.assertIs(type(~i), Perm)
2113 self.assertEqual(~~i, i)
2114 for i in Perm:
2115 self.assertIs(~~i, i)
2116 Open = self.Open
2117 self.assertIs(Open.WO & ~Open.WO, Open.RO)
2118 self.assertIs((Open.WO|Open.CE) & ~Open.WO, Open.CE)
2119
2120 def test_programatic_function_string(self):
Ethan Furman65a5a472016-09-01 23:55:19 -07002121 Perm = IntFlag('Perm', 'R W X')
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002122 lst = list(Perm)
2123 self.assertEqual(len(lst), len(Perm))
2124 self.assertEqual(len(Perm), 3, Perm)
2125 self.assertEqual(lst, [Perm.R, Perm.W, Perm.X])
2126 for i, n in enumerate('R W X'.split()):
2127 v = 1<<i
2128 e = Perm(v)
2129 self.assertEqual(e.value, v)
2130 self.assertEqual(type(e.value), int)
2131 self.assertEqual(e, v)
2132 self.assertEqual(e.name, n)
2133 self.assertIn(e, Perm)
2134 self.assertIs(type(e), Perm)
2135
2136 def test_programatic_function_string_with_start(self):
Ethan Furman65a5a472016-09-01 23:55:19 -07002137 Perm = IntFlag('Perm', 'R W X', start=8)
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002138 lst = list(Perm)
2139 self.assertEqual(len(lst), len(Perm))
2140 self.assertEqual(len(Perm), 3, Perm)
2141 self.assertEqual(lst, [Perm.R, Perm.W, Perm.X])
2142 for i, n in enumerate('R W X'.split()):
2143 v = 8<<i
2144 e = Perm(v)
2145 self.assertEqual(e.value, v)
2146 self.assertEqual(type(e.value), int)
2147 self.assertEqual(e, v)
2148 self.assertEqual(e.name, n)
2149 self.assertIn(e, Perm)
2150 self.assertIs(type(e), Perm)
2151
2152 def test_programatic_function_string_list(self):
Ethan Furman65a5a472016-09-01 23:55:19 -07002153 Perm = IntFlag('Perm', ['R', 'W', 'X'])
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002154 lst = list(Perm)
2155 self.assertEqual(len(lst), len(Perm))
2156 self.assertEqual(len(Perm), 3, Perm)
2157 self.assertEqual(lst, [Perm.R, Perm.W, Perm.X])
2158 for i, n in enumerate('R W X'.split()):
2159 v = 1<<i
2160 e = Perm(v)
2161 self.assertEqual(e.value, v)
2162 self.assertEqual(type(e.value), int)
2163 self.assertEqual(e, v)
2164 self.assertEqual(e.name, n)
2165 self.assertIn(e, Perm)
2166 self.assertIs(type(e), Perm)
2167
2168 def test_programatic_function_iterable(self):
Ethan Furman65a5a472016-09-01 23:55:19 -07002169 Perm = IntFlag('Perm', (('R', 2), ('W', 8), ('X', 32)))
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002170 lst = list(Perm)
2171 self.assertEqual(len(lst), len(Perm))
2172 self.assertEqual(len(Perm), 3, Perm)
2173 self.assertEqual(lst, [Perm.R, Perm.W, Perm.X])
2174 for i, n in enumerate('R W X'.split()):
2175 v = 1<<(2*i+1)
2176 e = Perm(v)
2177 self.assertEqual(e.value, v)
2178 self.assertEqual(type(e.value), int)
2179 self.assertEqual(e, v)
2180 self.assertEqual(e.name, n)
2181 self.assertIn(e, Perm)
2182 self.assertIs(type(e), Perm)
2183
2184 def test_programatic_function_from_dict(self):
Ethan Furman65a5a472016-09-01 23:55:19 -07002185 Perm = IntFlag('Perm', OrderedDict((('R', 2), ('W', 8), ('X', 32))))
Ethan Furmanee47e5c2016-08-31 00:12:15 -07002186 lst = list(Perm)
2187 self.assertEqual(len(lst), len(Perm))
2188 self.assertEqual(len(Perm), 3, Perm)
2189 self.assertEqual(lst, [Perm.R, Perm.W, Perm.X])
2190 for i, n in enumerate('R W X'.split()):
2191 v = 1<<(2*i+1)
2192 e = Perm(v)
2193 self.assertEqual(e.value, v)
2194 self.assertEqual(type(e.value), int)
2195 self.assertEqual(e, v)
2196 self.assertEqual(e.name, n)
2197 self.assertIn(e, Perm)
2198 self.assertIs(type(e), Perm)
2199
2200
Ethan Furman65a5a472016-09-01 23:55:19 -07002201 def test_containment(self):
2202 Perm = self.Perm
2203 R, W, X = Perm
2204 RW = R | W
2205 RX = R | X
2206 WX = W | X
2207 RWX = R | W | X
2208 self.assertTrue(R in RW)
2209 self.assertTrue(R in RX)
2210 self.assertTrue(R in RWX)
2211 self.assertTrue(W in RW)
2212 self.assertTrue(W in WX)
2213 self.assertTrue(W in RWX)
2214 self.assertTrue(X in RX)
2215 self.assertTrue(X in WX)
2216 self.assertTrue(X in RWX)
2217 self.assertFalse(R in WX)
2218 self.assertFalse(W in RX)
2219 self.assertFalse(X in RW)
2220
Ethan Furman25d94bb2016-09-02 16:32:32 -07002221 def test_bool(self):
2222 Perm = self.Perm
2223 for f in Perm:
2224 self.assertTrue(f)
2225 Open = self.Open
2226 for f in Open:
2227 self.assertEqual(bool(f.value), bool(f))
2228
Ethan Furmanf24bb352013-07-18 17:05:39 -07002229class TestUnique(unittest.TestCase):
2230
2231 def test_unique_clean(self):
2232 @unique
2233 class Clean(Enum):
2234 one = 1
2235 two = 'dos'
2236 tres = 4.0
2237 @unique
2238 class Cleaner(IntEnum):
2239 single = 1
2240 double = 2
2241 triple = 3
2242
2243 def test_unique_dirty(self):
2244 with self.assertRaisesRegex(ValueError, 'tres.*one'):
2245 @unique
2246 class Dirty(Enum):
2247 one = 1
2248 two = 'dos'
2249 tres = 1
2250 with self.assertRaisesRegex(
2251 ValueError,
2252 'double.*single.*turkey.*triple',
2253 ):
2254 @unique
2255 class Dirtier(IntEnum):
2256 single = 1
2257 double = 1
2258 triple = 3
2259 turkey = 3
2260
Ethan Furman3803ad42016-05-01 10:03:53 -07002261 def test_unique_with_name(self):
2262 @unique
2263 class Silly(Enum):
2264 one = 1
2265 two = 'dos'
2266 name = 3
2267 @unique
2268 class Sillier(IntEnum):
2269 single = 1
2270 name = 2
2271 triple = 3
2272 value = 4
2273
Ethan Furmanf24bb352013-07-18 17:05:39 -07002274
Ethan Furman3323da92015-04-11 09:39:59 -07002275expected_help_output_with_docs = """\
Ethan Furman5875d742013-10-21 20:45:55 -07002276Help on class Color in module %s:
2277
2278class Color(enum.Enum)
Ethan Furman48a724f2015-04-11 23:23:06 -07002279 | An enumeration.
Serhiy Storchakab599ca82015-04-04 12:48:04 +03002280 |\x20\x20
Ethan Furman5875d742013-10-21 20:45:55 -07002281 | Method resolution order:
2282 | Color
2283 | enum.Enum
2284 | builtins.object
2285 |\x20\x20
2286 | Data and other attributes defined here:
2287 |\x20\x20
2288 | blue = <Color.blue: 3>
2289 |\x20\x20
2290 | green = <Color.green: 2>
2291 |\x20\x20
2292 | red = <Color.red: 1>
2293 |\x20\x20
2294 | ----------------------------------------------------------------------
2295 | Data descriptors inherited from enum.Enum:
2296 |\x20\x20
2297 | name
2298 | The name of the Enum member.
2299 |\x20\x20
2300 | value
2301 | The value of the Enum member.
2302 |\x20\x20
2303 | ----------------------------------------------------------------------
2304 | Data descriptors inherited from enum.EnumMeta:
2305 |\x20\x20
2306 | __members__
2307 | Returns a mapping of member name->value.
2308 |\x20\x20\x20\x20\x20\x20
2309 | This mapping lists all enum members, including aliases. Note that this
Ethan Furman3323da92015-04-11 09:39:59 -07002310 | is a read-only view of the internal mapping."""
2311
2312expected_help_output_without_docs = """\
2313Help on class Color in module %s:
2314
2315class Color(enum.Enum)
2316 | Method resolution order:
2317 | Color
2318 | enum.Enum
2319 | builtins.object
2320 |\x20\x20
2321 | Data and other attributes defined here:
2322 |\x20\x20
2323 | blue = <Color.blue: 3>
2324 |\x20\x20
2325 | green = <Color.green: 2>
2326 |\x20\x20
2327 | red = <Color.red: 1>
2328 |\x20\x20
2329 | ----------------------------------------------------------------------
2330 | Data descriptors inherited from enum.Enum:
2331 |\x20\x20
2332 | name
2333 |\x20\x20
2334 | value
2335 |\x20\x20
2336 | ----------------------------------------------------------------------
2337 | Data descriptors inherited from enum.EnumMeta:
2338 |\x20\x20
2339 | __members__"""
Ethan Furman5875d742013-10-21 20:45:55 -07002340
2341class TestStdLib(unittest.TestCase):
2342
Ethan Furman48a724f2015-04-11 23:23:06 -07002343 maxDiff = None
2344
Ethan Furman5875d742013-10-21 20:45:55 -07002345 class Color(Enum):
2346 red = 1
2347 green = 2
2348 blue = 3
2349
2350 def test_pydoc(self):
2351 # indirectly test __objclass__
Ethan Furman3323da92015-04-11 09:39:59 -07002352 if StrEnum.__doc__ is None:
2353 expected_text = expected_help_output_without_docs % __name__
2354 else:
2355 expected_text = expected_help_output_with_docs % __name__
Ethan Furman5875d742013-10-21 20:45:55 -07002356 output = StringIO()
2357 helper = pydoc.Helper(output=output)
2358 helper(self.Color)
2359 result = output.getvalue().strip()
Victor Stinner4b0432d2014-06-16 22:48:43 +02002360 self.assertEqual(result, expected_text)
Ethan Furman5875d742013-10-21 20:45:55 -07002361
2362 def test_inspect_getmembers(self):
2363 values = dict((
2364 ('__class__', EnumMeta),
Ethan Furman48a724f2015-04-11 23:23:06 -07002365 ('__doc__', 'An enumeration.'),
Ethan Furman5875d742013-10-21 20:45:55 -07002366 ('__members__', self.Color.__members__),
2367 ('__module__', __name__),
2368 ('blue', self.Color.blue),
2369 ('green', self.Color.green),
2370 ('name', Enum.__dict__['name']),
2371 ('red', self.Color.red),
2372 ('value', Enum.__dict__['value']),
2373 ))
2374 result = dict(inspect.getmembers(self.Color))
2375 self.assertEqual(values.keys(), result.keys())
2376 failed = False
2377 for k in values.keys():
2378 if result[k] != values[k]:
2379 print()
2380 print('\n%s\n key: %s\n result: %s\nexpected: %s\n%s\n' %
2381 ('=' * 75, k, result[k], values[k], '=' * 75), sep='')
2382 failed = True
2383 if failed:
2384 self.fail("result does not equal expected, see print above")
2385
2386 def test_inspect_classify_class_attrs(self):
2387 # indirectly test __objclass__
2388 from inspect import Attribute
2389 values = [
2390 Attribute(name='__class__', kind='data',
2391 defining_class=object, object=EnumMeta),
2392 Attribute(name='__doc__', kind='data',
Ethan Furman48a724f2015-04-11 23:23:06 -07002393 defining_class=self.Color, object='An enumeration.'),
Ethan Furman5875d742013-10-21 20:45:55 -07002394 Attribute(name='__members__', kind='property',
2395 defining_class=EnumMeta, object=EnumMeta.__members__),
2396 Attribute(name='__module__', kind='data',
2397 defining_class=self.Color, object=__name__),
2398 Attribute(name='blue', kind='data',
2399 defining_class=self.Color, object=self.Color.blue),
2400 Attribute(name='green', kind='data',
2401 defining_class=self.Color, object=self.Color.green),
2402 Attribute(name='red', kind='data',
2403 defining_class=self.Color, object=self.Color.red),
2404 Attribute(name='name', kind='data',
2405 defining_class=Enum, object=Enum.__dict__['name']),
2406 Attribute(name='value', kind='data',
2407 defining_class=Enum, object=Enum.__dict__['value']),
2408 ]
2409 values.sort(key=lambda item: item.name)
2410 result = list(inspect.classify_class_attrs(self.Color))
2411 result.sort(key=lambda item: item.name)
2412 failed = False
2413 for v, r in zip(values, result):
2414 if r != v:
2415 print('\n%s\n%s\n%s\n%s\n' % ('=' * 75, r, v, '=' * 75), sep='')
2416 failed = True
2417 if failed:
2418 self.fail("result does not equal expected, see print above")
2419
Martin Panter19e69c52015-11-14 12:46:42 +00002420
2421class MiscTestCase(unittest.TestCase):
2422 def test__all__(self):
2423 support.check__all__(self, enum)
2424
2425
Gregory P. Smith ext:(%20%5BGoogle%20Inc.%5D)6f20bd62016-06-03 19:14:52 +00002426# These are unordered here on purpose to ensure that declaration order
2427# makes no difference.
2428CONVERT_TEST_NAME_D = 5
2429CONVERT_TEST_NAME_C = 5
2430CONVERT_TEST_NAME_B = 5
2431CONVERT_TEST_NAME_A = 5 # This one should sort first.
2432CONVERT_TEST_NAME_E = 5
2433CONVERT_TEST_NAME_F = 5
2434
2435class TestIntEnumConvert(unittest.TestCase):
2436 def test_convert_value_lookup_priority(self):
2437 test_type = enum.IntEnum._convert(
2438 'UnittestConvert', 'test.test_enum',
2439 filter=lambda x: x.startswith('CONVERT_TEST_'))
2440 # We don't want the reverse lookup value to vary when there are
2441 # multiple possible names for a given value. It should always
2442 # report the first lexigraphical name in that case.
2443 self.assertEqual(test_type(5).name, 'CONVERT_TEST_NAME_A')
2444
2445 def test_convert(self):
2446 test_type = enum.IntEnum._convert(
2447 'UnittestConvert', 'test.test_enum',
2448 filter=lambda x: x.startswith('CONVERT_TEST_'))
2449 # Ensure that test_type has all of the desired names and values.
2450 self.assertEqual(test_type.CONVERT_TEST_NAME_F,
2451 test_type.CONVERT_TEST_NAME_A)
2452 self.assertEqual(test_type.CONVERT_TEST_NAME_B, 5)
2453 self.assertEqual(test_type.CONVERT_TEST_NAME_C, 5)
2454 self.assertEqual(test_type.CONVERT_TEST_NAME_D, 5)
2455 self.assertEqual(test_type.CONVERT_TEST_NAME_E, 5)
2456 # Ensure that test_type only picked up names matching the filter.
2457 self.assertEqual([name for name in dir(test_type)
2458 if name[0:2] not in ('CO', '__')],
2459 [], msg='Names other than CONVERT_TEST_* found.')
2460
2461
Ethan Furman6b3d64a2013-06-14 16:55:46 -07002462if __name__ == '__main__':
2463 unittest.main()