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