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