1from pickle import dumps, loads, PicklingError, HIGHEST_PROTOCOL 2import sys 3import unittest 4pyver = float('%s.%s' % sys.version_info[:2]) 5if pyver < 2.5: 6 sys.path.insert(0, '.') 7import enum 8from enum import Enum, IntEnum, unique, EnumMeta 9 10if pyver < 2.6: 11 from __builtin__ import enumerate as bltin_enumerate 12 def enumerate(thing, start=0): 13 result = [] 14 for i, item in bltin_enumerate(thing): 15 i = i + start 16 result.append((i, item)) 17 return result 18 19try: 20 any 21except NameError: 22 def any(iterable): 23 for element in iterable: 24 if element: 25 return True 26 return False 27 28try: 29 unicode 30except NameError: 31 unicode = str 32 33try: 34 from collections import OrderedDict 35except ImportError: 36 OrderedDict = None 37 38# for pickle tests 39try: 40 class Stooges(Enum): 41 LARRY = 1 42 CURLY = 2 43 MOE = 3 44except Exception: 45 Stooges = sys.exc_info()[1] 46 47try: 48 class IntStooges(int, Enum): 49 LARRY = 1 50 CURLY = 2 51 MOE = 3 52except Exception: 53 IntStooges = sys.exc_info()[1] 54 55try: 56 class FloatStooges(float, Enum): 57 LARRY = 1.39 58 CURLY = 2.72 59 MOE = 3.142596 60except Exception: 61 FloatStooges = sys.exc_info()[1] 62 63# for pickle test and subclass tests 64try: 65 class StrEnum(str, Enum): 66 'accepts only string values' 67 class Name(StrEnum): 68 BDFL = 'Guido van Rossum' 69 FLUFL = 'Barry Warsaw' 70except Exception: 71 Name = sys.exc_info()[1] 72 73try: 74 Question = Enum('Question', 'who what when where why', module=__name__) 75except Exception: 76 Question = sys.exc_info()[1] 77 78try: 79 Answer = Enum('Answer', 'him this then there because') 80except Exception: 81 Answer = sys.exc_info()[1] 82 83try: 84 Theory = Enum('Theory', 'rule law supposition', qualname='spanish_inquisition') 85except Exception: 86 Theory = sys.exc_info()[1] 87 88# for doctests 89try: 90 class Fruit(Enum): 91 tomato = 1 92 banana = 2 93 cherry = 3 94except Exception: 95 pass 96 97def test_pickle_dump_load(assertion, source, target=None, 98 protocol=(0, HIGHEST_PROTOCOL)): 99 start, stop = protocol 100 failures = [] 101 for protocol in range(start, stop+1): 102 try: 103 if target is None: 104 assertion(loads(dumps(source, protocol=protocol)) is source) 105 else: 106 assertion(loads(dumps(source, protocol=protocol)), target) 107 except Exception: 108 exc, tb = sys.exc_info()[1:] 109 failures.append('%2d: %s' %(protocol, exc)) 110 if failures: 111 raise ValueError('Failed with protocols: %s' % ', '.join(failures)) 112 113def test_pickle_exception(assertion, exception, obj, 114 protocol=(0, HIGHEST_PROTOCOL)): 115 start, stop = protocol 116 failures = [] 117 for protocol in range(start, stop+1): 118 try: 119 assertion(exception, dumps, obj, protocol=protocol) 120 except Exception: 121 exc = sys.exc_info()[1] 122 failures.append('%d: %s %s' % (protocol, exc.__class__.__name__, exc)) 123 if failures: 124 raise ValueError('Failed with protocols: %s' % ', '.join(failures)) 125 126 127class TestHelpers(unittest.TestCase): 128 # _is_descriptor, _is_sunder, _is_dunder 129 130 def test_is_descriptor(self): 131 class foo: 132 pass 133 for attr in ('__get__','__set__','__delete__'): 134 obj = foo() 135 self.assertFalse(enum._is_descriptor(obj)) 136 setattr(obj, attr, 1) 137 self.assertTrue(enum._is_descriptor(obj)) 138 139 def test_is_sunder(self): 140 for s in ('_a_', '_aa_'): 141 self.assertTrue(enum._is_sunder(s)) 142 143 for s in ('a', 'a_', '_a', '__a', 'a__', '__a__', '_a__', '__a_', '_', 144 '__', '___', '____', '_____',): 145 self.assertFalse(enum._is_sunder(s)) 146 147 def test_is_dunder(self): 148 for s in ('__a__', '__aa__'): 149 self.assertTrue(enum._is_dunder(s)) 150 for s in ('a', 'a_', '_a', '__a', 'a__', '_a_', '_a__', '__a_', '_', 151 '__', '___', '____', '_____',): 152 self.assertFalse(enum._is_dunder(s)) 153 154 155class TestEnum(unittest.TestCase): 156 def setUp(self): 157 class Season(Enum): 158 SPRING = 1 159 SUMMER = 2 160 AUTUMN = 3 161 WINTER = 4 162 self.Season = Season 163 164 class Konstants(float, Enum): 165 E = 2.7182818 166 PI = 3.1415926 167 TAU = 2 * PI 168 self.Konstants = Konstants 169 170 class Grades(IntEnum): 171 A = 5 172 B = 4 173 C = 3 174 D = 2 175 F = 0 176 self.Grades = Grades 177 178 class Directional(str, Enum): 179 EAST = 'east' 180 WEST = 'west' 181 NORTH = 'north' 182 SOUTH = 'south' 183 self.Directional = Directional 184 185 from datetime import date 186 class Holiday(date, Enum): 187 NEW_YEAR = 2013, 1, 1 188 IDES_OF_MARCH = 2013, 3, 15 189 self.Holiday = Holiday 190 191 if pyver >= 3.0: # do not specify custom `dir` on previous versions 192 def test_dir_on_class(self): 193 Season = self.Season 194 self.assertEqual( 195 set(dir(Season)), 196 set(['__class__', '__doc__', '__members__', '__module__', 197 'SPRING', 'SUMMER', 'AUTUMN', 'WINTER']), 198 ) 199 200 def test_dir_on_item(self): 201 Season = self.Season 202 self.assertEqual( 203 set(dir(Season.WINTER)), 204 set(['__class__', '__doc__', '__module__', 'name', 'value']), 205 ) 206 207 def test_dir_with_added_behavior(self): 208 class Test(Enum): 209 this = 'that' 210 these = 'those' 211 def wowser(self): 212 return ("Wowser! I'm %s!" % self.name) 213 self.assertEqual( 214 set(dir(Test)), 215 set(['__class__', '__doc__', '__members__', '__module__', 'this', 'these']), 216 ) 217 self.assertEqual( 218 set(dir(Test.this)), 219 set(['__class__', '__doc__', '__module__', 'name', 'value', 'wowser']), 220 ) 221 222 def test_dir_on_sub_with_behavior_on_super(self): 223 # see issue22506 224 class SuperEnum(Enum): 225 def invisible(self): 226 return "did you see me?" 227 class SubEnum(SuperEnum): 228 sample = 5 229 self.assertEqual( 230 set(dir(SubEnum.sample)), 231 set(['__class__', '__doc__', '__module__', 'name', 'value', 'invisible']), 232 ) 233 234 if pyver >= 2.7: # OrderedDict first available here 235 def test_members_is_ordereddict_if_ordered(self): 236 class Ordered(Enum): 237 __order__ = 'first second third' 238 first = 'bippity' 239 second = 'boppity' 240 third = 'boo' 241 self.assertTrue(type(Ordered.__members__) is OrderedDict) 242 243 def test_members_is_ordereddict_if_not_ordered(self): 244 class Unordered(Enum): 245 this = 'that' 246 these = 'those' 247 self.assertTrue(type(Unordered.__members__) is OrderedDict) 248 249 if pyver >= 3.0: # all objects are ordered in Python 2.x 250 def test_members_is_always_ordered(self): 251 class AlwaysOrdered(Enum): 252 first = 1 253 second = 2 254 third = 3 255 self.assertTrue(type(AlwaysOrdered.__members__) is OrderedDict) 256 257 def test_comparisons(self): 258 def bad_compare(): 259 Season.SPRING > 4 260 Season = self.Season 261 self.assertNotEqual(Season.SPRING, 1) 262 self.assertRaises(TypeError, bad_compare) 263 264 class Part(Enum): 265 SPRING = 1 266 CLIP = 2 267 BARREL = 3 268 269 self.assertNotEqual(Season.SPRING, Part.SPRING) 270 def bad_compare(): 271 Season.SPRING < Part.CLIP 272 self.assertRaises(TypeError, bad_compare) 273 274 def test_enum_in_enum_out(self): 275 Season = self.Season 276 self.assertTrue(Season(Season.WINTER) is Season.WINTER) 277 278 def test_enum_value(self): 279 Season = self.Season 280 self.assertEqual(Season.SPRING.value, 1) 281 282 def test_intenum_value(self): 283 self.assertEqual(IntStooges.CURLY.value, 2) 284 285 def test_enum(self): 286 Season = self.Season 287 lst = list(Season) 288 self.assertEqual(len(lst), len(Season)) 289 self.assertEqual(len(Season), 4, Season) 290 self.assertEqual( 291 [Season.SPRING, Season.SUMMER, Season.AUTUMN, Season.WINTER], lst) 292 293 for i, season in enumerate('SPRING SUMMER AUTUMN WINTER'.split()): 294 i += 1 295 e = Season(i) 296 self.assertEqual(e, getattr(Season, season)) 297 self.assertEqual(e.value, i) 298 self.assertNotEqual(e, i) 299 self.assertEqual(e.name, season) 300 self.assertTrue(e in Season) 301 self.assertTrue(type(e) is Season) 302 self.assertTrue(isinstance(e, Season)) 303 self.assertEqual(str(e), 'Season.' + season) 304 self.assertEqual( 305 repr(e), 306 '<Season.%s: %s>' % (season, i), 307 ) 308 309 def test_value_name(self): 310 Season = self.Season 311 self.assertEqual(Season.SPRING.name, 'SPRING') 312 self.assertEqual(Season.SPRING.value, 1) 313 def set_name(obj, new_value): 314 obj.name = new_value 315 def set_value(obj, new_value): 316 obj.value = new_value 317 self.assertRaises(AttributeError, set_name, Season.SPRING, 'invierno', ) 318 self.assertRaises(AttributeError, set_value, Season.SPRING, 2) 319 320 def test_attribute_deletion(self): 321 class Season(Enum): 322 SPRING = 1 323 SUMMER = 2 324 AUTUMN = 3 325 WINTER = 4 326 327 def spam(cls): 328 pass 329 330 self.assertTrue(hasattr(Season, 'spam')) 331 del Season.spam 332 self.assertFalse(hasattr(Season, 'spam')) 333 334 self.assertRaises(AttributeError, delattr, Season, 'SPRING') 335 self.assertRaises(AttributeError, delattr, Season, 'DRY') 336 self.assertRaises(AttributeError, delattr, Season.SPRING, 'name') 337 338 def test_bool_of_class(self): 339 class Empty(Enum): 340 pass 341 self.assertTrue(bool(Empty)) 342 343 def test_bool_of_member(self): 344 class Count(Enum): 345 zero = 0 346 one = 1 347 two = 2 348 for member in Count: 349 self.assertTrue(bool(member)) 350 351 def test_invalid_names(self): 352 def create_bad_class_1(): 353 class Wrong(Enum): 354 mro = 9 355 def create_bad_class_2(): 356 class Wrong(Enum): 357 _reserved_ = 3 358 self.assertRaises(ValueError, create_bad_class_1) 359 self.assertRaises(ValueError, create_bad_class_2) 360 361 def test_contains(self): 362 Season = self.Season 363 self.assertTrue(Season.AUTUMN in Season) 364 self.assertTrue(3 not in Season) 365 366 val = Season(3) 367 self.assertTrue(val in Season) 368 369 class OtherEnum(Enum): 370 one = 1; two = 2 371 self.assertTrue(OtherEnum.two not in Season) 372 373 if pyver >= 2.6: # when `format` came into being 374 375 def test_format_enum(self): 376 Season = self.Season 377 self.assertEqual('{0}'.format(Season.SPRING), 378 '{0}'.format(str(Season.SPRING))) 379 self.assertEqual( '{0:}'.format(Season.SPRING), 380 '{0:}'.format(str(Season.SPRING))) 381 self.assertEqual('{0:20}'.format(Season.SPRING), 382 '{0:20}'.format(str(Season.SPRING))) 383 self.assertEqual('{0:^20}'.format(Season.SPRING), 384 '{0:^20}'.format(str(Season.SPRING))) 385 self.assertEqual('{0:>20}'.format(Season.SPRING), 386 '{0:>20}'.format(str(Season.SPRING))) 387 self.assertEqual('{0:<20}'.format(Season.SPRING), 388 '{0:<20}'.format(str(Season.SPRING))) 389 390 def test_format_enum_custom(self): 391 class TestFloat(float, Enum): 392 one = 1.0 393 two = 2.0 394 def __format__(self, spec): 395 return 'TestFloat success!' 396 self.assertEqual('{0}'.format(TestFloat.one), 'TestFloat success!') 397 398 def assertFormatIsValue(self, spec, member): 399 self.assertEqual(spec.format(member), spec.format(member.value)) 400 401 def test_format_enum_date(self): 402 Holiday = self.Holiday 403 self.assertFormatIsValue('{0}', Holiday.IDES_OF_MARCH) 404 self.assertFormatIsValue('{0:}', Holiday.IDES_OF_MARCH) 405 self.assertFormatIsValue('{0:20}', Holiday.IDES_OF_MARCH) 406 self.assertFormatIsValue('{0:^20}', Holiday.IDES_OF_MARCH) 407 self.assertFormatIsValue('{0:>20}', Holiday.IDES_OF_MARCH) 408 self.assertFormatIsValue('{0:<20}', Holiday.IDES_OF_MARCH) 409 self.assertFormatIsValue('{0:%Y %m}', Holiday.IDES_OF_MARCH) 410 self.assertFormatIsValue('{0:%Y %m %M:00}', Holiday.IDES_OF_MARCH) 411 412 def test_format_enum_float(self): 413 Konstants = self.Konstants 414 self.assertFormatIsValue('{0}', Konstants.TAU) 415 self.assertFormatIsValue('{0:}', Konstants.TAU) 416 self.assertFormatIsValue('{0:20}', Konstants.TAU) 417 self.assertFormatIsValue('{0:^20}', Konstants.TAU) 418 self.assertFormatIsValue('{0:>20}', Konstants.TAU) 419 self.assertFormatIsValue('{0:<20}', Konstants.TAU) 420 self.assertFormatIsValue('{0:n}', Konstants.TAU) 421 self.assertFormatIsValue('{0:5.2}', Konstants.TAU) 422 self.assertFormatIsValue('{0:f}', Konstants.TAU) 423 424 def test_format_enum_int(self): 425 Grades = self.Grades 426 self.assertFormatIsValue('{0}', Grades.C) 427 self.assertFormatIsValue('{0:}', Grades.C) 428 self.assertFormatIsValue('{0:20}', Grades.C) 429 self.assertFormatIsValue('{0:^20}', Grades.C) 430 self.assertFormatIsValue('{0:>20}', Grades.C) 431 self.assertFormatIsValue('{0:<20}', Grades.C) 432 self.assertFormatIsValue('{0:+}', Grades.C) 433 self.assertFormatIsValue('{0:08X}', Grades.C) 434 self.assertFormatIsValue('{0:b}', Grades.C) 435 436 def test_format_enum_str(self): 437 Directional = self.Directional 438 self.assertFormatIsValue('{0}', Directional.WEST) 439 self.assertFormatIsValue('{0:}', Directional.WEST) 440 self.assertFormatIsValue('{0:20}', Directional.WEST) 441 self.assertFormatIsValue('{0:^20}', Directional.WEST) 442 self.assertFormatIsValue('{0:>20}', Directional.WEST) 443 self.assertFormatIsValue('{0:<20}', Directional.WEST) 444 445 def test_hash(self): 446 Season = self.Season 447 dates = {} 448 dates[Season.WINTER] = '1225' 449 dates[Season.SPRING] = '0315' 450 dates[Season.SUMMER] = '0704' 451 dates[Season.AUTUMN] = '1031' 452 self.assertEqual(dates[Season.AUTUMN], '1031') 453 454 def test_enum_duplicates(self): 455 class Season(Enum): 456 _order_ = "SPRING SUMMER AUTUMN WINTER" 457 SPRING = 1 458 SUMMER = 2 459 AUTUMN = FALL = 3 460 WINTER = 4 461 ANOTHER_SPRING = 1 462 lst = list(Season) 463 self.assertEqual( 464 lst, 465 [Season.SPRING, Season.SUMMER, 466 Season.AUTUMN, Season.WINTER, 467 ]) 468 self.assertTrue(Season.FALL is Season.AUTUMN) 469 self.assertEqual(Season.FALL.value, 3) 470 self.assertEqual(Season.AUTUMN.value, 3) 471 self.assertTrue(Season(3) is Season.AUTUMN) 472 self.assertTrue(Season(1) is Season.SPRING) 473 self.assertEqual(Season.FALL.name, 'AUTUMN') 474 self.assertEqual( 475 set([k for k,v in Season.__members__.items() if v.name != k]), 476 set(['FALL', 'ANOTHER_SPRING']), 477 ) 478 479 if pyver >= 3.0: 480 cls = vars() 481 result = {'Enum':Enum} 482 exec("""def test_duplicate_name(self): 483 with self.assertRaises(TypeError): 484 class Color(Enum): 485 red = 1 486 green = 2 487 blue = 3 488 red = 4 489 490 with self.assertRaises(TypeError): 491 class Color(Enum): 492 red = 1 493 green = 2 494 blue = 3 495 def red(self): 496 return 'red' 497 498 with self.assertRaises(TypeError): 499 class Color(Enum): 500 @property 501 502 def red(self): 503 return 'redder' 504 red = 1 505 green = 2 506 blue = 3""", 507 result) 508 cls['test_duplicate_name'] = result['test_duplicate_name'] 509 510 def test_enum_with_value_name(self): 511 class Huh(Enum): 512 name = 1 513 value = 2 514 self.assertEqual( 515 list(Huh), 516 [Huh.name, Huh.value], 517 ) 518 self.assertTrue(type(Huh.name) is Huh) 519 self.assertEqual(Huh.name.name, 'name') 520 self.assertEqual(Huh.name.value, 1) 521 522 def test_intenum_from_scratch(self): 523 class phy(int, Enum): 524 pi = 3 525 tau = 2 * pi 526 self.assertTrue(phy.pi < phy.tau) 527 528 def test_intenum_inherited(self): 529 class IntEnum(int, Enum): 530 pass 531 class phy(IntEnum): 532 pi = 3 533 tau = 2 * pi 534 self.assertTrue(phy.pi < phy.tau) 535 536 def test_floatenum_from_scratch(self): 537 class phy(float, Enum): 538 pi = 3.1415926 539 tau = 2 * pi 540 self.assertTrue(phy.pi < phy.tau) 541 542 def test_floatenum_inherited(self): 543 class FloatEnum(float, Enum): 544 pass 545 class phy(FloatEnum): 546 pi = 3.1415926 547 tau = 2 * pi 548 self.assertTrue(phy.pi < phy.tau) 549 550 def test_strenum_from_scratch(self): 551 class phy(str, Enum): 552 pi = 'Pi' 553 tau = 'Tau' 554 self.assertTrue(phy.pi < phy.tau) 555 556 def test_strenum_inherited(self): 557 class StrEnum(str, Enum): 558 pass 559 class phy(StrEnum): 560 pi = 'Pi' 561 tau = 'Tau' 562 self.assertTrue(phy.pi < phy.tau) 563 564 def test_intenum(self): 565 class WeekDay(IntEnum): 566 SUNDAY = 1 567 MONDAY = 2 568 TUESDAY = 3 569 WEDNESDAY = 4 570 THURSDAY = 5 571 FRIDAY = 6 572 SATURDAY = 7 573 574 self.assertEqual(['a', 'b', 'c'][WeekDay.MONDAY], 'c') 575 self.assertEqual([i for i in range(WeekDay.TUESDAY)], [0, 1, 2]) 576 577 lst = list(WeekDay) 578 self.assertEqual(len(lst), len(WeekDay)) 579 self.assertEqual(len(WeekDay), 7) 580 target = 'SUNDAY MONDAY TUESDAY WEDNESDAY THURSDAY FRIDAY SATURDAY' 581 target = target.split() 582 for i, weekday in enumerate(target): 583 i += 1 584 e = WeekDay(i) 585 self.assertEqual(e, i) 586 self.assertEqual(int(e), i) 587 self.assertEqual(e.name, weekday) 588 self.assertTrue(e in WeekDay) 589 self.assertEqual(lst.index(e)+1, i) 590 self.assertTrue(0 < e < 8) 591 self.assertTrue(type(e) is WeekDay) 592 self.assertTrue(isinstance(e, int)) 593 self.assertTrue(isinstance(e, Enum)) 594 595 def test_intenum_duplicates(self): 596 class WeekDay(IntEnum): 597 __order__ = 'SUNDAY MONDAY TUESDAY WEDNESDAY THURSDAY FRIDAY SATURDAY' 598 SUNDAY = 1 599 MONDAY = 2 600 TUESDAY = TEUSDAY = 3 601 WEDNESDAY = 4 602 THURSDAY = 5 603 FRIDAY = 6 604 SATURDAY = 7 605 self.assertTrue(WeekDay.TEUSDAY is WeekDay.TUESDAY) 606 self.assertEqual(WeekDay(3).name, 'TUESDAY') 607 self.assertEqual([k for k,v in WeekDay.__members__.items() 608 if v.name != k], ['TEUSDAY', ]) 609 610 def test_pickle_enum(self): 611 if isinstance(Stooges, Exception): 612 raise Stooges 613 test_pickle_dump_load(self.assertTrue, Stooges.CURLY) 614 test_pickle_dump_load(self.assertTrue, Stooges) 615 616 def test_pickle_int(self): 617 if isinstance(IntStooges, Exception): 618 raise IntStooges 619 test_pickle_dump_load(self.assertTrue, IntStooges.CURLY) 620 test_pickle_dump_load(self.assertTrue, IntStooges) 621 622 def test_pickle_float(self): 623 if isinstance(FloatStooges, Exception): 624 raise FloatStooges 625 test_pickle_dump_load(self.assertTrue, FloatStooges.CURLY) 626 test_pickle_dump_load(self.assertTrue, FloatStooges) 627 628 def test_pickle_enum_function(self): 629 if isinstance(Answer, Exception): 630 raise Answer 631 test_pickle_dump_load(self.assertTrue, Answer.him) 632 test_pickle_dump_load(self.assertTrue, Answer) 633 634 def test_pickle_enum_function_with_module(self): 635 if isinstance(Question, Exception): 636 raise Question 637 test_pickle_dump_load(self.assertTrue, Question.who) 638 test_pickle_dump_load(self.assertTrue, Question) 639 640 if pyver == 3.4: 641 def test_class_nested_enum_and_pickle_protocol_four(self): 642 # would normally just have this directly in the class namespace 643 class NestedEnum(Enum): 644 twigs = 'common' 645 shiny = 'rare' 646 647 self.__class__.NestedEnum = NestedEnum 648 self.NestedEnum.__qualname__ = '%s.NestedEnum' % self.__class__.__name__ 649 test_pickle_exception( 650 self.assertRaises, PicklingError, self.NestedEnum.twigs, 651 protocol=(0, 3)) 652 test_pickle_dump_load(self.assertTrue, self.NestedEnum.twigs, 653 protocol=(4, HIGHEST_PROTOCOL)) 654 655 elif pyver == 3.5: 656 def test_class_nested_enum_and_pickle_protocol_four(self): 657 # would normally just have this directly in the class namespace 658 class NestedEnum(Enum): 659 twigs = 'common' 660 shiny = 'rare' 661 662 self.__class__.NestedEnum = NestedEnum 663 self.NestedEnum.__qualname__ = '%s.NestedEnum' % self.__class__.__name__ 664 test_pickle_dump_load(self.assertTrue, self.NestedEnum.twigs, 665 protocol=(0, HIGHEST_PROTOCOL)) 666 667 def test_exploding_pickle(self): 668 BadPickle = Enum('BadPickle', 'dill sweet bread_n_butter') 669 enum._make_class_unpicklable(BadPickle) 670 globals()['BadPickle'] = BadPickle 671 test_pickle_exception(self.assertRaises, TypeError, BadPickle.dill) 672 test_pickle_exception(self.assertRaises, PicklingError, BadPickle) 673 674 def test_string_enum(self): 675 class SkillLevel(str, Enum): 676 master = 'what is the sound of one hand clapping?' 677 journeyman = 'why did the chicken cross the road?' 678 apprentice = 'knock, knock!' 679 self.assertEqual(SkillLevel.apprentice, 'knock, knock!') 680 681 def test_getattr_getitem(self): 682 class Period(Enum): 683 morning = 1 684 noon = 2 685 evening = 3 686 night = 4 687 self.assertTrue(Period(2) is Period.noon) 688 self.assertTrue(getattr(Period, 'night') is Period.night) 689 self.assertTrue(Period['morning'] is Period.morning) 690 691 def test_getattr_dunder(self): 692 Season = self.Season 693 self.assertTrue(getattr(Season, '__hash__')) 694 695 def test_iteration_order(self): 696 class Season(Enum): 697 _order_ = 'SUMMER WINTER AUTUMN SPRING' 698 SUMMER = 2 699 WINTER = 4 700 AUTUMN = 3 701 SPRING = 1 702 self.assertEqual( 703 list(Season), 704 [Season.SUMMER, Season.WINTER, Season.AUTUMN, Season.SPRING], 705 ) 706 707 def test_iteration_order_reversed(self): 708 self.assertEqual( 709 list(reversed(self.Season)), 710 [self.Season.WINTER, self.Season.AUTUMN, self.Season.SUMMER, 711 self.Season.SPRING] 712 ) 713 714 def test_iteration_order_with_unorderable_values(self): 715 class Complex(Enum): 716 a = complex(7, 9) 717 b = complex(3.14, 2) 718 c = complex(1, -1) 719 d = complex(-77, 32) 720 self.assertEqual( 721 list(Complex), 722 [Complex.a, Complex.b, Complex.c, Complex.d], 723 ) 724 725 def test_programatic_function_string(self): 726 SummerMonth = Enum('SummerMonth', 'june july august') 727 lst = list(SummerMonth) 728 self.assertEqual(len(lst), len(SummerMonth)) 729 self.assertEqual(len(SummerMonth), 3, SummerMonth) 730 self.assertEqual( 731 [SummerMonth.june, SummerMonth.july, SummerMonth.august], 732 lst, 733 ) 734 for i, month in enumerate('june july august'.split()): 735 i += 1 736 e = SummerMonth(i) 737 self.assertEqual(int(e.value), i) 738 self.assertNotEqual(e, i) 739 self.assertEqual(e.name, month) 740 self.assertTrue(e in SummerMonth) 741 self.assertTrue(type(e) is SummerMonth) 742 743 def test_programatic_function_string_with_start(self): 744 SummerMonth = Enum('SummerMonth', 'june july august', start=10) 745 lst = list(SummerMonth) 746 self.assertEqual(len(lst), len(SummerMonth)) 747 self.assertEqual(len(SummerMonth), 3, SummerMonth) 748 self.assertEqual( 749 [SummerMonth.june, SummerMonth.july, SummerMonth.august], 750 lst, 751 ) 752 for i, month in enumerate('june july august'.split(), 10): 753 e = SummerMonth(i) 754 self.assertEqual(int(e.value), i) 755 self.assertNotEqual(e, i) 756 self.assertEqual(e.name, month) 757 self.assertTrue(e in SummerMonth) 758 self.assertTrue(type(e) is SummerMonth) 759 760 def test_programatic_function_string_list(self): 761 SummerMonth = Enum('SummerMonth', ['june', 'july', 'august']) 762 lst = list(SummerMonth) 763 self.assertEqual(len(lst), len(SummerMonth)) 764 self.assertEqual(len(SummerMonth), 3, SummerMonth) 765 self.assertEqual( 766 [SummerMonth.june, SummerMonth.july, SummerMonth.august], 767 lst, 768 ) 769 for i, month in enumerate('june july august'.split()): 770 i += 1 771 e = SummerMonth(i) 772 self.assertEqual(int(e.value), i) 773 self.assertNotEqual(e, i) 774 self.assertEqual(e.name, month) 775 self.assertTrue(e in SummerMonth) 776 self.assertTrue(type(e) is SummerMonth) 777 778 def test_programatic_function_string_list_with_start(self): 779 SummerMonth = Enum('SummerMonth', ['june', 'july', 'august'], start=20) 780 lst = list(SummerMonth) 781 self.assertEqual(len(lst), len(SummerMonth)) 782 self.assertEqual(len(SummerMonth), 3, SummerMonth) 783 self.assertEqual( 784 [SummerMonth.june, SummerMonth.july, SummerMonth.august], 785 lst, 786 ) 787 for i, month in enumerate('june july august'.split(), 20): 788 e = SummerMonth(i) 789 self.assertEqual(int(e.value), i) 790 self.assertNotEqual(e, i) 791 self.assertEqual(e.name, month) 792 self.assertTrue(e in SummerMonth) 793 self.assertTrue(type(e) is SummerMonth) 794 795 def test_programatic_function_iterable(self): 796 SummerMonth = Enum( 797 'SummerMonth', 798 (('june', 1), ('july', 2), ('august', 3)) 799 ) 800 lst = list(SummerMonth) 801 self.assertEqual(len(lst), len(SummerMonth)) 802 self.assertEqual(len(SummerMonth), 3, SummerMonth) 803 self.assertEqual( 804 [SummerMonth.june, SummerMonth.july, SummerMonth.august], 805 lst, 806 ) 807 for i, month in enumerate('june july august'.split()): 808 i += 1 809 e = SummerMonth(i) 810 self.assertEqual(int(e.value), i) 811 self.assertNotEqual(e, i) 812 self.assertEqual(e.name, month) 813 self.assertTrue(e in SummerMonth) 814 self.assertTrue(type(e) is SummerMonth) 815 816 def test_programatic_function_iterable_with_weird_names(self): 817 SummerMonth = Enum( 818 'SummerMonth', 819 (('june', 1), ('july', 2), ('august', 3), ('fabulous september', 4)) 820 ) 821 lst = list(SummerMonth) 822 self.assertEqual(len(lst), len(SummerMonth)) 823 self.assertEqual(len(SummerMonth), 4, SummerMonth) 824 self.assertEqual( 825 [SummerMonth.june, SummerMonth.july, SummerMonth.august, SummerMonth['fabulous september']], 826 lst, 827 ) 828 for i, month in enumerate('june july august'.split() + ['fabulous september']): 829 i += 1 830 e = SummerMonth(i) 831 self.assertEqual(int(e.value), i) 832 self.assertNotEqual(e, i) 833 self.assertEqual(e.name, month) 834 self.assertTrue(e in SummerMonth) 835 self.assertTrue(type(e) is SummerMonth) 836 837 def test_programatic_function_from_dict(self): 838 SummerMonth = Enum( 839 'SummerMonth', 840 dict((('june', 1), ('july', 2), ('august', 3))) 841 ) 842 lst = list(SummerMonth) 843 self.assertEqual(len(lst), len(SummerMonth)) 844 self.assertEqual(len(SummerMonth), 3, SummerMonth) 845 if pyver < 3.0: 846 self.assertEqual( 847 [SummerMonth.june, SummerMonth.july, SummerMonth.august], 848 lst, 849 ) 850 for i, month in enumerate('june july august'.split()): 851 i += 1 852 e = SummerMonth(i) 853 self.assertEqual(int(e.value), i) 854 self.assertNotEqual(e, i) 855 self.assertEqual(e.name, month) 856 self.assertTrue(e in SummerMonth) 857 self.assertTrue(type(e) is SummerMonth) 858 859 def test_programatic_function_type(self): 860 SummerMonth = Enum('SummerMonth', 'june july august', type=int) 861 lst = list(SummerMonth) 862 self.assertEqual(len(lst), len(SummerMonth)) 863 self.assertEqual(len(SummerMonth), 3, SummerMonth) 864 self.assertEqual( 865 [SummerMonth.june, SummerMonth.july, SummerMonth.august], 866 lst, 867 ) 868 for i, month in enumerate('june july august'.split()): 869 i += 1 870 e = SummerMonth(i) 871 self.assertEqual(e, i) 872 self.assertEqual(e.name, month) 873 self.assertTrue(e in SummerMonth) 874 self.assertTrue(type(e) is SummerMonth) 875 876 def test_programatic_function_type_with_start(self): 877 SummerMonth = Enum('SummerMonth', 'june july august', type=int, start=30) 878 lst = list(SummerMonth) 879 self.assertEqual(len(lst), len(SummerMonth)) 880 self.assertEqual(len(SummerMonth), 3, SummerMonth) 881 self.assertEqual( 882 [SummerMonth.june, SummerMonth.july, SummerMonth.august], 883 lst, 884 ) 885 for i, month in enumerate('june july august'.split(), 30): 886 e = SummerMonth(i) 887 self.assertEqual(e, i) 888 self.assertEqual(e.name, month) 889 self.assertTrue(e in SummerMonth) 890 self.assertTrue(type(e) is SummerMonth) 891 892 def test_programatic_function_type_from_subclass(self): 893 SummerMonth = IntEnum('SummerMonth', 'june july august') 894 lst = list(SummerMonth) 895 self.assertEqual(len(lst), len(SummerMonth)) 896 self.assertEqual(len(SummerMonth), 3, SummerMonth) 897 self.assertEqual( 898 [SummerMonth.june, SummerMonth.july, SummerMonth.august], 899 lst, 900 ) 901 for i, month in enumerate('june july august'.split()): 902 i += 1 903 e = SummerMonth(i) 904 self.assertEqual(e, i) 905 self.assertEqual(e.name, month) 906 self.assertTrue(e in SummerMonth) 907 self.assertTrue(type(e) is SummerMonth) 908 909 def test_programatic_function_type_from_subclass_with_start(self): 910 SummerMonth = IntEnum('SummerMonth', 'june july august', start=40) 911 lst = list(SummerMonth) 912 self.assertEqual(len(lst), len(SummerMonth)) 913 self.assertEqual(len(SummerMonth), 3, SummerMonth) 914 self.assertEqual( 915 [SummerMonth.june, SummerMonth.july, SummerMonth.august], 916 lst, 917 ) 918 for i, month in enumerate('june july august'.split(), 40): 919 e = SummerMonth(i) 920 self.assertEqual(e, i) 921 self.assertEqual(e.name, month) 922 self.assertTrue(e in SummerMonth) 923 self.assertTrue(type(e) is SummerMonth) 924 925 def test_programatic_function_unicode(self): 926 SummerMonth = Enum('SummerMonth', unicode('june july august')) 927 lst = list(SummerMonth) 928 self.assertEqual(len(lst), len(SummerMonth)) 929 self.assertEqual(len(SummerMonth), 3, SummerMonth) 930 self.assertEqual( 931 [SummerMonth.june, SummerMonth.july, SummerMonth.august], 932 lst, 933 ) 934 for i, month in enumerate(unicode('june july august').split()): 935 i += 1 936 e = SummerMonth(i) 937 self.assertEqual(int(e.value), i) 938 self.assertNotEqual(e, i) 939 self.assertEqual(e.name, month) 940 self.assertTrue(e in SummerMonth) 941 self.assertTrue(type(e) is SummerMonth) 942 943 def test_programatic_function_unicode_list(self): 944 SummerMonth = Enum('SummerMonth', [unicode('june'), unicode('july'), unicode('august')]) 945 lst = list(SummerMonth) 946 self.assertEqual(len(lst), len(SummerMonth)) 947 self.assertEqual(len(SummerMonth), 3, SummerMonth) 948 self.assertEqual( 949 [SummerMonth.june, SummerMonth.july, SummerMonth.august], 950 lst, 951 ) 952 for i, month in enumerate(unicode('june july august').split()): 953 i += 1 954 e = SummerMonth(i) 955 self.assertEqual(int(e.value), i) 956 self.assertNotEqual(e, i) 957 self.assertEqual(e.name, month) 958 self.assertTrue(e in SummerMonth) 959 self.assertTrue(type(e) is SummerMonth) 960 961 def test_programatic_function_unicode_iterable(self): 962 SummerMonth = Enum( 963 'SummerMonth', 964 ((unicode('june'), 1), (unicode('july'), 2), (unicode('august'), 3)) 965 ) 966 lst = list(SummerMonth) 967 self.assertEqual(len(lst), len(SummerMonth)) 968 self.assertEqual(len(SummerMonth), 3, SummerMonth) 969 self.assertEqual( 970 [SummerMonth.june, SummerMonth.july, SummerMonth.august], 971 lst, 972 ) 973 for i, month in enumerate(unicode('june july august').split()): 974 i += 1 975 e = SummerMonth(i) 976 self.assertEqual(int(e.value), i) 977 self.assertNotEqual(e, i) 978 self.assertEqual(e.name, month) 979 self.assertTrue(e in SummerMonth) 980 self.assertTrue(type(e) is SummerMonth) 981 982 def test_programatic_function_from_unicode_dict(self): 983 SummerMonth = Enum( 984 'SummerMonth', 985 dict(((unicode('june'), 1), (unicode('july'), 2), (unicode('august'), 3))) 986 ) 987 lst = list(SummerMonth) 988 self.assertEqual(len(lst), len(SummerMonth)) 989 self.assertEqual(len(SummerMonth), 3, SummerMonth) 990 if pyver < 3.0: 991 self.assertEqual( 992 [SummerMonth.june, SummerMonth.july, SummerMonth.august], 993 lst, 994 ) 995 for i, month in enumerate(unicode('june july august').split()): 996 i += 1 997 e = SummerMonth(i) 998 self.assertEqual(int(e.value), i) 999 self.assertNotEqual(e, i) 1000 self.assertEqual(e.name, month) 1001 self.assertTrue(e in SummerMonth) 1002 self.assertTrue(type(e) is SummerMonth) 1003 1004 def test_programatic_function_unicode_type(self): 1005 SummerMonth = Enum('SummerMonth', unicode('june july august'), type=int) 1006 lst = list(SummerMonth) 1007 self.assertEqual(len(lst), len(SummerMonth)) 1008 self.assertEqual(len(SummerMonth), 3, SummerMonth) 1009 self.assertEqual( 1010 [SummerMonth.june, SummerMonth.july, SummerMonth.august], 1011 lst, 1012 ) 1013 for i, month in enumerate(unicode('june july august').split()): 1014 i += 1 1015 e = SummerMonth(i) 1016 self.assertEqual(e, i) 1017 self.assertEqual(e.name, month) 1018 self.assertTrue(e in SummerMonth) 1019 self.assertTrue(type(e) is SummerMonth) 1020 1021 def test_programatic_function_unicode_type_from_subclass(self): 1022 SummerMonth = IntEnum('SummerMonth', unicode('june july august')) 1023 lst = list(SummerMonth) 1024 self.assertEqual(len(lst), len(SummerMonth)) 1025 self.assertEqual(len(SummerMonth), 3, SummerMonth) 1026 self.assertEqual( 1027 [SummerMonth.june, SummerMonth.july, SummerMonth.august], 1028 lst, 1029 ) 1030 for i, month in enumerate(unicode('june july august').split()): 1031 i += 1 1032 e = SummerMonth(i) 1033 self.assertEqual(e, i) 1034 self.assertEqual(e.name, month) 1035 self.assertTrue(e in SummerMonth) 1036 self.assertTrue(type(e) is SummerMonth) 1037 1038 def test_programmatic_function_unicode_class(self): 1039 if pyver < 3.0: 1040 class_names = unicode('SummerMonth'), 'S\xfcmm\xe9rM\xf6nth'.decode('latin1') 1041 else: 1042 class_names = 'SummerMonth', 'S\xfcmm\xe9rM\xf6nth' 1043 for i, class_name in enumerate(class_names): 1044 if pyver < 3.0 and i == 1: 1045 self.assertRaises(TypeError, Enum, class_name, unicode('june july august')) 1046 else: 1047 SummerMonth = Enum(class_name, unicode('june july august')) 1048 lst = list(SummerMonth) 1049 self.assertEqual(len(lst), len(SummerMonth)) 1050 self.assertEqual(len(SummerMonth), 3, SummerMonth) 1051 self.assertEqual( 1052 [SummerMonth.june, SummerMonth.july, SummerMonth.august], 1053 lst, 1054 ) 1055 for i, month in enumerate(unicode('june july august').split()): 1056 i += 1 1057 e = SummerMonth(i) 1058 self.assertEqual(e.value, i) 1059 self.assertEqual(e.name, month) 1060 self.assertTrue(e in SummerMonth) 1061 self.assertTrue(type(e) is SummerMonth) 1062 1063 def test_subclassing(self): 1064 if isinstance(Name, Exception): 1065 raise Name 1066 self.assertEqual(Name.BDFL, 'Guido van Rossum') 1067 self.assertTrue(Name.BDFL, Name('Guido van Rossum')) 1068 self.assertTrue(Name.BDFL is getattr(Name, 'BDFL')) 1069 test_pickle_dump_load(self.assertTrue, Name.BDFL) 1070 1071 def test_extending(self): 1072 def bad_extension(): 1073 class Color(Enum): 1074 red = 1 1075 green = 2 1076 blue = 3 1077 class MoreColor(Color): 1078 cyan = 4 1079 magenta = 5 1080 yellow = 6 1081 self.assertRaises(TypeError, bad_extension) 1082 1083 def test_exclude_methods(self): 1084 class whatever(Enum): 1085 this = 'that' 1086 these = 'those' 1087 def really(self): 1088 return 'no, not %s' % self.value 1089 self.assertFalse(type(whatever.really) is whatever) 1090 self.assertEqual(whatever.this.really(), 'no, not that') 1091 1092 def test_wrong_inheritance_order(self): 1093 def wrong_inherit(): 1094 class Wrong(Enum, str): 1095 NotHere = 'error before this point' 1096 self.assertRaises(TypeError, wrong_inherit) 1097 1098 def test_intenum_transitivity(self): 1099 class number(IntEnum): 1100 one = 1 1101 two = 2 1102 three = 3 1103 class numero(IntEnum): 1104 uno = 1 1105 dos = 2 1106 tres = 3 1107 self.assertEqual(number.one, numero.uno) 1108 self.assertEqual(number.two, numero.dos) 1109 self.assertEqual(number.three, numero.tres) 1110 1111 def test_introspection(self): 1112 class Number(IntEnum): 1113 one = 100 1114 two = 200 1115 self.assertTrue(Number.one._member_type_ is int) 1116 self.assertTrue(Number._member_type_ is int) 1117 class String(str, Enum): 1118 yarn = 'soft' 1119 rope = 'rough' 1120 wire = 'hard' 1121 self.assertTrue(String.yarn._member_type_ is str) 1122 self.assertTrue(String._member_type_ is str) 1123 class Plain(Enum): 1124 vanilla = 'white' 1125 one = 1 1126 self.assertTrue(Plain.vanilla._member_type_ is object) 1127 self.assertTrue(Plain._member_type_ is object) 1128 1129 def test_wrong_enum_in_call(self): 1130 class Monochrome(Enum): 1131 black = 0 1132 white = 1 1133 class Gender(Enum): 1134 male = 0 1135 female = 1 1136 self.assertRaises(ValueError, Monochrome, Gender.male) 1137 1138 def test_wrong_enum_in_mixed_call(self): 1139 class Monochrome(IntEnum): 1140 black = 0 1141 white = 1 1142 class Gender(Enum): 1143 male = 0 1144 female = 1 1145 self.assertRaises(ValueError, Monochrome, Gender.male) 1146 1147 def test_mixed_enum_in_call_1(self): 1148 class Monochrome(IntEnum): 1149 black = 0 1150 white = 1 1151 class Gender(IntEnum): 1152 male = 0 1153 female = 1 1154 self.assertTrue(Monochrome(Gender.female) is Monochrome.white) 1155 1156 def test_mixed_enum_in_call_2(self): 1157 class Monochrome(Enum): 1158 black = 0 1159 white = 1 1160 class Gender(IntEnum): 1161 male = 0 1162 female = 1 1163 self.assertTrue(Monochrome(Gender.male) is Monochrome.black) 1164 1165 def test_flufl_enum(self): 1166 class Fluflnum(Enum): 1167 def __int__(self): 1168 return int(self.value) 1169 class MailManOptions(Fluflnum): 1170 option1 = 1 1171 option2 = 2 1172 option3 = 3 1173 self.assertEqual(int(MailManOptions.option1), 1) 1174 1175 def test_no_such_enum_member(self): 1176 class Color(Enum): 1177 red = 1 1178 green = 2 1179 blue = 3 1180 self.assertRaises(ValueError, Color, 4) 1181 self.assertRaises(KeyError, Color.__getitem__, 'chartreuse') 1182 1183 def test_new_repr(self): 1184 class Color(Enum): 1185 red = 1 1186 green = 2 1187 blue = 3 1188 def __repr__(self): 1189 return "don't you just love shades of %s?" % self.name 1190 self.assertEqual( 1191 repr(Color.blue), 1192 "don't you just love shades of blue?", 1193 ) 1194 1195 def test_inherited_repr(self): 1196 class MyEnum(Enum): 1197 def __repr__(self): 1198 return "My name is %s." % self.name 1199 class MyIntEnum(int, MyEnum): 1200 this = 1 1201 that = 2 1202 theother = 3 1203 self.assertEqual(repr(MyIntEnum.that), "My name is that.") 1204 1205 def test_multiple_mixin_mro(self): 1206 class auto_enum(EnumMeta): 1207 def __new__(metacls, cls, bases, classdict): 1208 original_dict = classdict 1209 classdict = enum._EnumDict() 1210 for k, v in original_dict.items(): 1211 classdict[k] = v 1212 temp = type(classdict)() 1213 names = set(classdict._member_names) 1214 i = 0 1215 for k in classdict._member_names: 1216 v = classdict[k] 1217 if v == (): 1218 v = i 1219 else: 1220 i = v 1221 i += 1 1222 temp[k] = v 1223 for k, v in classdict.items(): 1224 if k not in names: 1225 temp[k] = v 1226 return super(auto_enum, metacls).__new__( 1227 metacls, cls, bases, temp) 1228 1229 AutoNumberedEnum = auto_enum('AutoNumberedEnum', (Enum,), {}) 1230 1231 AutoIntEnum = auto_enum('AutoIntEnum', (IntEnum,), {}) 1232 1233 class TestAutoNumber(AutoNumberedEnum): 1234 a = () 1235 b = 3 1236 c = () 1237 1238 class TestAutoInt(AutoIntEnum): 1239 a = () 1240 b = 3 1241 c = () 1242 1243 def test_subclasses_with_getnewargs(self): 1244 class NamedInt(int): 1245 __qualname__ = 'NamedInt' # needed for pickle protocol 4 1246 def __new__(cls, *args): 1247 _args = args 1248 if len(args) < 1: 1249 raise TypeError("name and value must be specified") 1250 name, args = args[0], args[1:] 1251 self = int.__new__(cls, *args) 1252 self._intname = name 1253 self._args = _args 1254 return self 1255 def __getnewargs__(self): 1256 return self._args 1257 @property 1258 def __name__(self): 1259 return self._intname 1260 def __repr__(self): 1261 # repr() is updated to include the name and type info 1262 return "%s(%r, %s)" % (type(self).__name__, 1263 self.__name__, 1264 int.__repr__(self)) 1265 def __str__(self): 1266 # str() is unchanged, even if it relies on the repr() fallback 1267 base = int 1268 base_str = base.__str__ 1269 if base_str.__objclass__ is object: 1270 return base.__repr__(self) 1271 return base_str(self) 1272 # for simplicity, we only define one operator that 1273 # propagates expressions 1274 def __add__(self, other): 1275 temp = int(self) + int( other) 1276 if isinstance(self, NamedInt) and isinstance(other, NamedInt): 1277 return NamedInt( 1278 '(%s + %s)' % (self.__name__, other.__name__), 1279 temp ) 1280 else: 1281 return temp 1282 1283 class NEI(NamedInt, Enum): 1284 __qualname__ = 'NEI' # needed for pickle protocol 4 1285 x = ('the-x', 1) 1286 y = ('the-y', 2) 1287 1288 self.assertTrue(NEI.__new__ is Enum.__new__) 1289 self.assertEqual(repr(NEI.x + NEI.y), "NamedInt('(the-x + the-y)', 3)") 1290 globals()['NamedInt'] = NamedInt 1291 globals()['NEI'] = NEI 1292 NI5 = NamedInt('test', 5) 1293 self.assertEqual(NI5, 5) 1294 test_pickle_dump_load(self.assertTrue, NI5, 5) 1295 self.assertEqual(NEI.y.value, 2) 1296 test_pickle_dump_load(self.assertTrue, NEI.y) 1297 1298 if pyver >= 3.4: 1299 def test_subclasses_with_getnewargs_ex(self): 1300 class NamedInt(int): 1301 __qualname__ = 'NamedInt' # needed for pickle protocol 4 1302 def __new__(cls, *args): 1303 _args = args 1304 if len(args) < 2: 1305 raise TypeError("name and value must be specified") 1306 name, args = args[0], args[1:] 1307 self = int.__new__(cls, *args) 1308 self._intname = name 1309 self._args = _args 1310 return self 1311 def __getnewargs_ex__(self): 1312 return self._args, {} 1313 @property 1314 def __name__(self): 1315 return self._intname 1316 def __repr__(self): 1317 # repr() is updated to include the name and type info 1318 return "{}({!r}, {})".format(type(self).__name__, 1319 self.__name__, 1320 int.__repr__(self)) 1321 def __str__(self): 1322 # str() is unchanged, even if it relies on the repr() fallback 1323 base = int 1324 base_str = base.__str__ 1325 if base_str.__objclass__ is object: 1326 return base.__repr__(self) 1327 return base_str(self) 1328 # for simplicity, we only define one operator that 1329 # propagates expressions 1330 def __add__(self, other): 1331 temp = int(self) + int( other) 1332 if isinstance(self, NamedInt) and isinstance(other, NamedInt): 1333 return NamedInt( 1334 '({0} + {1})'.format(self.__name__, other.__name__), 1335 temp ) 1336 else: 1337 return temp 1338 1339 class NEI(NamedInt, Enum): 1340 __qualname__ = 'NEI' # needed for pickle protocol 4 1341 x = ('the-x', 1) 1342 y = ('the-y', 2) 1343 1344 1345 self.assertIs(NEI.__new__, Enum.__new__) 1346 self.assertEqual(repr(NEI.x + NEI.y), "NamedInt('(the-x + the-y)', 3)") 1347 globals()['NamedInt'] = NamedInt 1348 globals()['NEI'] = NEI 1349 NI5 = NamedInt('test', 5) 1350 self.assertEqual(NI5, 5) 1351 test_pickle_dump_load(self.assertEqual, NI5, 5, protocol=(4, HIGHEST_PROTOCOL)) 1352 self.assertEqual(NEI.y.value, 2) 1353 test_pickle_dump_load(self.assertTrue, NEI.y, protocol=(4, HIGHEST_PROTOCOL)) 1354 1355 def test_subclasses_with_reduce(self): 1356 class NamedInt(int): 1357 __qualname__ = 'NamedInt' # needed for pickle protocol 4 1358 def __new__(cls, *args): 1359 _args = args 1360 if len(args) < 1: 1361 raise TypeError("name and value must be specified") 1362 name, args = args[0], args[1:] 1363 self = int.__new__(cls, *args) 1364 self._intname = name 1365 self._args = _args 1366 return self 1367 def __reduce__(self): 1368 return self.__class__, self._args 1369 @property 1370 def __name__(self): 1371 return self._intname 1372 def __repr__(self): 1373 # repr() is updated to include the name and type info 1374 return "%s(%r, %s)" % (type(self).__name__, 1375 self.__name__, 1376 int.__repr__(self)) 1377 def __str__(self): 1378 # str() is unchanged, even if it relies on the repr() fallback 1379 base = int 1380 base_str = base.__str__ 1381 if base_str.__objclass__ is object: 1382 return base.__repr__(self) 1383 return base_str(self) 1384 # for simplicity, we only define one operator that 1385 # propagates expressions 1386 def __add__(self, other): 1387 temp = int(self) + int( other) 1388 if isinstance(self, NamedInt) and isinstance(other, NamedInt): 1389 return NamedInt( 1390 '(%s + %s)' % (self.__name__, other.__name__), 1391 temp ) 1392 else: 1393 return temp 1394 1395 class NEI(NamedInt, Enum): 1396 __qualname__ = 'NEI' # needed for pickle protocol 4 1397 x = ('the-x', 1) 1398 y = ('the-y', 2) 1399 1400 1401 self.assertTrue(NEI.__new__ is Enum.__new__) 1402 self.assertEqual(repr(NEI.x + NEI.y), "NamedInt('(the-x + the-y)', 3)") 1403 globals()['NamedInt'] = NamedInt 1404 globals()['NEI'] = NEI 1405 NI5 = NamedInt('test', 5) 1406 self.assertEqual(NI5, 5) 1407 test_pickle_dump_load(self.assertEqual, NI5, 5) 1408 self.assertEqual(NEI.y.value, 2) 1409 test_pickle_dump_load(self.assertTrue, NEI.y) 1410 1411 def test_subclasses_with_reduce_ex(self): 1412 class NamedInt(int): 1413 __qualname__ = 'NamedInt' # needed for pickle protocol 4 1414 def __new__(cls, *args): 1415 _args = args 1416 if len(args) < 1: 1417 raise TypeError("name and value must be specified") 1418 name, args = args[0], args[1:] 1419 self = int.__new__(cls, *args) 1420 self._intname = name 1421 self._args = _args 1422 return self 1423 def __reduce_ex__(self, proto): 1424 return self.__class__, self._args 1425 @property 1426 def __name__(self): 1427 return self._intname 1428 def __repr__(self): 1429 # repr() is updated to include the name and type info 1430 return "%s(%r, %s)" % (type(self).__name__, 1431 self.__name__, 1432 int.__repr__(self)) 1433 def __str__(self): 1434 # str() is unchanged, even if it relies on the repr() fallback 1435 base = int 1436 base_str = base.__str__ 1437 if base_str.__objclass__ is object: 1438 return base.__repr__(self) 1439 return base_str(self) 1440 # for simplicity, we only define one operator that 1441 # propagates expressions 1442 def __add__(self, other): 1443 temp = int(self) + int( other) 1444 if isinstance(self, NamedInt) and isinstance(other, NamedInt): 1445 return NamedInt( 1446 '(%s + %s)' % (self.__name__, other.__name__), 1447 temp ) 1448 else: 1449 return temp 1450 1451 class NEI(NamedInt, Enum): 1452 __qualname__ = 'NEI' # needed for pickle protocol 4 1453 x = ('the-x', 1) 1454 y = ('the-y', 2) 1455 1456 1457 self.assertTrue(NEI.__new__ is Enum.__new__) 1458 self.assertEqual(repr(NEI.x + NEI.y), "NamedInt('(the-x + the-y)', 3)") 1459 globals()['NamedInt'] = NamedInt 1460 globals()['NEI'] = NEI 1461 NI5 = NamedInt('test', 5) 1462 self.assertEqual(NI5, 5) 1463 test_pickle_dump_load(self.assertEqual, NI5, 5) 1464 self.assertEqual(NEI.y.value, 2) 1465 test_pickle_dump_load(self.assertTrue, NEI.y) 1466 1467 def test_subclasses_without_direct_pickle_support(self): 1468 class NamedInt(int): 1469 __qualname__ = 'NamedInt' 1470 def __new__(cls, *args): 1471 _args = args 1472 name, args = args[0], args[1:] 1473 if len(args) == 0: 1474 raise TypeError("name and value must be specified") 1475 self = int.__new__(cls, *args) 1476 self._intname = name 1477 self._args = _args 1478 return self 1479 @property 1480 def __name__(self): 1481 return self._intname 1482 def __repr__(self): 1483 # repr() is updated to include the name and type info 1484 return "%s(%r, %s)" % (type(self).__name__, 1485 self.__name__, 1486 int.__repr__(self)) 1487 def __str__(self): 1488 # str() is unchanged, even if it relies on the repr() fallback 1489 base = int 1490 base_str = base.__str__ 1491 if base_str.__objclass__ is object: 1492 return base.__repr__(self) 1493 return base_str(self) 1494 # for simplicity, we only define one operator that 1495 # propagates expressions 1496 def __add__(self, other): 1497 temp = int(self) + int( other) 1498 if isinstance(self, NamedInt) and isinstance(other, NamedInt): 1499 return NamedInt( 1500 '(%s + %s)' % (self.__name__, other.__name__), 1501 temp ) 1502 else: 1503 return temp 1504 1505 class NEI(NamedInt, Enum): 1506 __qualname__ = 'NEI' 1507 x = ('the-x', 1) 1508 y = ('the-y', 2) 1509 1510 self.assertTrue(NEI.__new__ is Enum.__new__) 1511 self.assertEqual(repr(NEI.x + NEI.y), "NamedInt('(the-x + the-y)', 3)") 1512 globals()['NamedInt'] = NamedInt 1513 globals()['NEI'] = NEI 1514 NI5 = NamedInt('test', 5) 1515 self.assertEqual(NI5, 5) 1516 self.assertEqual(NEI.y.value, 2) 1517 test_pickle_exception(self.assertRaises, TypeError, NEI.x) 1518 test_pickle_exception(self.assertRaises, PicklingError, NEI) 1519 1520 def test_subclasses_without_direct_pickle_support_using_name(self): 1521 class NamedInt(int): 1522 __qualname__ = 'NamedInt' 1523 def __new__(cls, *args): 1524 _args = args 1525 name, args = args[0], args[1:] 1526 if len(args) == 0: 1527 raise TypeError("name and value must be specified") 1528 self = int.__new__(cls, *args) 1529 self._intname = name 1530 self._args = _args 1531 return self 1532 @property 1533 def __name__(self): 1534 return self._intname 1535 def __repr__(self): 1536 # repr() is updated to include the name and type info 1537 return "%s(%r, %s)" % (type(self).__name__, 1538 self.__name__, 1539 int.__repr__(self)) 1540 def __str__(self): 1541 # str() is unchanged, even if it relies on the repr() fallback 1542 base = int 1543 base_str = base.__str__ 1544 if base_str.__objclass__ is object: 1545 return base.__repr__(self) 1546 return base_str(self) 1547 # for simplicity, we only define one operator that 1548 # propagates expressions 1549 def __add__(self, other): 1550 temp = int(self) + int( other) 1551 if isinstance(self, NamedInt) and isinstance(other, NamedInt): 1552 return NamedInt( 1553 '(%s + %s)' % (self.__name__, other.__name__), 1554 temp ) 1555 else: 1556 return temp 1557 1558 class NEI(NamedInt, Enum): 1559 __qualname__ = 'NEI' 1560 x = ('the-x', 1) 1561 y = ('the-y', 2) 1562 def __reduce_ex__(self, proto): 1563 return getattr, (self.__class__, self._name_) 1564 1565 self.assertTrue(NEI.__new__ is Enum.__new__) 1566 self.assertEqual(repr(NEI.x + NEI.y), "NamedInt('(the-x + the-y)', 3)") 1567 globals()['NamedInt'] = NamedInt 1568 globals()['NEI'] = NEI 1569 NI5 = NamedInt('test', 5) 1570 self.assertEqual(NI5, 5) 1571 self.assertEqual(NEI.y.value, 2) 1572 test_pickle_dump_load(self.assertTrue, NEI.y) 1573 test_pickle_dump_load(self.assertTrue, NEI) 1574 1575 def test_tuple_subclass(self): 1576 class SomeTuple(tuple, Enum): 1577 __qualname__ = 'SomeTuple' 1578 first = (1, 'for the money') 1579 second = (2, 'for the show') 1580 third = (3, 'for the music') 1581 self.assertTrue(type(SomeTuple.first) is SomeTuple) 1582 self.assertTrue(isinstance(SomeTuple.second, tuple)) 1583 self.assertEqual(SomeTuple.third, (3, 'for the music')) 1584 globals()['SomeTuple'] = SomeTuple 1585 test_pickle_dump_load(self.assertTrue, SomeTuple.first) 1586 1587 def test_duplicate_values_give_unique_enum_items(self): 1588 class AutoNumber(Enum): 1589 __order__ = 'enum_m enum_d enum_y' 1590 enum_m = () 1591 enum_d = () 1592 enum_y = () 1593 def __new__(cls): 1594 value = len(cls.__members__) + 1 1595 obj = object.__new__(cls) 1596 obj._value_ = value 1597 return obj 1598 def __int__(self): 1599 return int(self._value_) 1600 self.assertEqual(int(AutoNumber.enum_d), 2) 1601 self.assertEqual(AutoNumber.enum_y.value, 3) 1602 self.assertTrue(AutoNumber(1) is AutoNumber.enum_m) 1603 self.assertEqual( 1604 list(AutoNumber), 1605 [AutoNumber.enum_m, AutoNumber.enum_d, AutoNumber.enum_y], 1606 ) 1607 1608 def test_inherited_new_from_enhanced_enum(self): 1609 class AutoNumber2(Enum): 1610 def __new__(cls): 1611 value = len(cls.__members__) + 1 1612 obj = object.__new__(cls) 1613 obj._value_ = value 1614 return obj 1615 def __int__(self): 1616 return int(self._value_) 1617 class Color(AutoNumber2): 1618 _order_ = 'red green blue' 1619 red = () 1620 green = () 1621 blue = () 1622 self.assertEqual(len(Color), 3, "wrong number of elements: %d (should be %d)" % (len(Color), 3)) 1623 self.assertEqual(list(Color), [Color.red, Color.green, Color.blue]) 1624 if pyver >= 3.0: 1625 self.assertEqual(list(map(int, Color)), [1, 2, 3]) 1626 1627 def test_inherited_new_from_mixed_enum(self): 1628 class AutoNumber3(IntEnum): 1629 def __new__(cls): 1630 value = len(cls.__members__) + 1 1631 obj = int.__new__(cls, value) 1632 obj._value_ = value 1633 return obj 1634 class Color(AutoNumber3): 1635 red = () 1636 green = () 1637 blue = () 1638 self.assertEqual(len(Color), 3, "wrong number of elements: %d (should be %d)" % (len(Color), 3)) 1639 Color.red 1640 Color.green 1641 Color.blue 1642 1643 def test_equality(self): 1644 class AlwaysEqual: 1645 def __eq__(self, other): 1646 return True 1647 class OrdinaryEnum(Enum): 1648 a = 1 1649 self.assertEqual(AlwaysEqual(), OrdinaryEnum.a) 1650 self.assertEqual(OrdinaryEnum.a, AlwaysEqual()) 1651 1652 def test_ordered_mixin(self): 1653 class OrderedEnum(Enum): 1654 def __ge__(self, other): 1655 if self.__class__ is other.__class__: 1656 return self._value_ >= other._value_ 1657 return NotImplemented 1658 def __gt__(self, other): 1659 if self.__class__ is other.__class__: 1660 return self._value_ > other._value_ 1661 return NotImplemented 1662 def __le__(self, other): 1663 if self.__class__ is other.__class__: 1664 return self._value_ <= other._value_ 1665 return NotImplemented 1666 def __lt__(self, other): 1667 if self.__class__ is other.__class__: 1668 return self._value_ < other._value_ 1669 return NotImplemented 1670 class Grade(OrderedEnum): 1671 __order__ = 'A B C D F' 1672 A = 5 1673 B = 4 1674 C = 3 1675 D = 2 1676 F = 1 1677 self.assertEqual(list(Grade), [Grade.A, Grade.B, Grade.C, Grade.D, Grade.F]) 1678 self.assertTrue(Grade.A > Grade.B) 1679 self.assertTrue(Grade.F <= Grade.C) 1680 self.assertTrue(Grade.D < Grade.A) 1681 self.assertTrue(Grade.B >= Grade.B) 1682 1683 def test_extending2(self): 1684 def bad_extension(): 1685 class Shade(Enum): 1686 def shade(self): 1687 print(self.name) 1688 class Color(Shade): 1689 red = 1 1690 green = 2 1691 blue = 3 1692 class MoreColor(Color): 1693 cyan = 4 1694 magenta = 5 1695 yellow = 6 1696 self.assertRaises(TypeError, bad_extension) 1697 1698 def test_extending3(self): 1699 class Shade(Enum): 1700 def shade(self): 1701 return self.name 1702 class Color(Shade): 1703 def hex(self): 1704 return '%s hexlified!' % self.value 1705 class MoreColor(Color): 1706 cyan = 4 1707 magenta = 5 1708 yellow = 6 1709 self.assertEqual(MoreColor.magenta.hex(), '5 hexlified!') 1710 1711 def test_no_duplicates(self): 1712 def bad_duplicates(): 1713 class UniqueEnum(Enum): 1714 def __init__(self, *args): 1715 cls = self.__class__ 1716 if any(self.value == e.value for e in cls): 1717 a = self.name 1718 e = cls(self.value).name 1719 raise ValueError( 1720 "aliases not allowed in UniqueEnum: %r --> %r" 1721 % (a, e) 1722 ) 1723 class Color(UniqueEnum): 1724 red = 1 1725 green = 2 1726 blue = 3 1727 class Color(UniqueEnum): 1728 red = 1 1729 green = 2 1730 blue = 3 1731 grene = 2 1732 self.assertRaises(ValueError, bad_duplicates) 1733 1734 def test_init(self): 1735 class Planet(Enum): 1736 MERCURY = (3.303e+23, 2.4397e6) 1737 VENUS = (4.869e+24, 6.0518e6) 1738 EARTH = (5.976e+24, 6.37814e6) 1739 MARS = (6.421e+23, 3.3972e6) 1740 JUPITER = (1.9e+27, 7.1492e7) 1741 SATURN = (5.688e+26, 6.0268e7) 1742 URANUS = (8.686e+25, 2.5559e7) 1743 NEPTUNE = (1.024e+26, 2.4746e7) 1744 def __init__(self, mass, radius): 1745 self.mass = mass # in kilograms 1746 self.radius = radius # in meters 1747 @property 1748 def surface_gravity(self): 1749 # universal gravitational constant (m3 kg-1 s-2) 1750 G = 6.67300E-11 1751 return G * self.mass / (self.radius * self.radius) 1752 self.assertEqual(round(Planet.EARTH.surface_gravity, 2), 9.80) 1753 self.assertEqual(Planet.EARTH.value, (5.976e+24, 6.37814e6)) 1754 1755 def test_nonhash_value(self): 1756 class AutoNumberInAList(Enum): 1757 def __new__(cls): 1758 value = [len(cls.__members__) + 1] 1759 obj = object.__new__(cls) 1760 obj._value_ = value 1761 return obj 1762 class ColorInAList(AutoNumberInAList): 1763 _order_ = 'red green blue' 1764 red = () 1765 green = () 1766 blue = () 1767 self.assertEqual(list(ColorInAList), [ColorInAList.red, ColorInAList.green, ColorInAList.blue]) 1768 self.assertEqual(ColorInAList.red.value, [1]) 1769 self.assertEqual(ColorInAList([1]), ColorInAList.red) 1770 1771 def test_conflicting_types_resolved_in_new(self): 1772 class LabelledIntEnum(int, Enum): 1773 def __new__(cls, *args): 1774 value, label = args 1775 obj = int.__new__(cls, value) 1776 obj.label = label 1777 obj._value_ = value 1778 return obj 1779 1780 class LabelledList(LabelledIntEnum): 1781 unprocessed = (1, "Unprocessed") 1782 payment_complete = (2, "Payment Complete") 1783 1784 self.assertEqual(list(LabelledList), [LabelledList.unprocessed, LabelledList.payment_complete]) 1785 self.assertEqual(LabelledList.unprocessed, 1) 1786 self.assertEqual(LabelledList(1), LabelledList.unprocessed) 1787 1788 def test_empty_with_functional_api(self): 1789 empty = enum.IntEnum('Foo', {}) 1790 self.assertEqual(len(empty), 0) 1791 1792 1793class TestUnique(unittest.TestCase): 1794 """2.4 doesn't allow class decorators, use function syntax.""" 1795 1796 def test_unique_clean(self): 1797 class Clean(Enum): 1798 one = 1 1799 two = 'dos' 1800 tres = 4.0 1801 unique(Clean) 1802 class Cleaner(IntEnum): 1803 single = 1 1804 double = 2 1805 triple = 3 1806 unique(Cleaner) 1807 1808 def test_unique_dirty(self): 1809 try: 1810 class Dirty(Enum): 1811 __order__ = 'one two tres' 1812 one = 1 1813 two = 'dos' 1814 tres = 1 1815 unique(Dirty) 1816 except ValueError: 1817 exc = sys.exc_info()[1] 1818 message = exc.args[0] 1819 self.assertTrue('tres -> one' in message) 1820 1821 try: 1822 class Dirtier(IntEnum): 1823 _order_ = 'single double triple turkey' 1824 single = 1 1825 double = 1 1826 triple = 3 1827 turkey = 3 1828 unique(Dirtier) 1829 except ValueError: 1830 exc = sys.exc_info()[1] 1831 message = exc.args[0] 1832 self.assertTrue('double -> single' in message) 1833 self.assertTrue('turkey -> triple' in message) 1834 1835 1836class TestMe(unittest.TestCase): 1837 1838 pass 1839 1840if __name__ == '__main__': 1841 unittest.main() 1842