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