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