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 _order_ = "SPRING SUMMER AUTUMN WINTER" 456 class Season(Enum): 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_from_dict(self): 817 SummerMonth = Enum( 818 'SummerMonth', 819 dict((('june', 1), ('july', 2), ('august', 3))) 820 ) 821 lst = list(SummerMonth) 822 self.assertEqual(len(lst), len(SummerMonth)) 823 self.assertEqual(len(SummerMonth), 3, SummerMonth) 824 if pyver < 3.0: 825 self.assertEqual( 826 [SummerMonth.june, SummerMonth.july, SummerMonth.august], 827 lst, 828 ) 829 for i, month in enumerate('june july august'.split()): 830 i += 1 831 e = SummerMonth(i) 832 self.assertEqual(int(e.value), i) 833 self.assertNotEqual(e, i) 834 self.assertEqual(e.name, month) 835 self.assertTrue(e in SummerMonth) 836 self.assertTrue(type(e) is SummerMonth) 837 838 def test_programatic_function_type(self): 839 SummerMonth = Enum('SummerMonth', 'june july august', type=int) 840 lst = list(SummerMonth) 841 self.assertEqual(len(lst), len(SummerMonth)) 842 self.assertEqual(len(SummerMonth), 3, SummerMonth) 843 self.assertEqual( 844 [SummerMonth.june, SummerMonth.july, SummerMonth.august], 845 lst, 846 ) 847 for i, month in enumerate('june july august'.split()): 848 i += 1 849 e = SummerMonth(i) 850 self.assertEqual(e, i) 851 self.assertEqual(e.name, month) 852 self.assertTrue(e in SummerMonth) 853 self.assertTrue(type(e) is SummerMonth) 854 855 def test_programatic_function_type_with_start(self): 856 SummerMonth = Enum('SummerMonth', 'june july august', type=int, start=30) 857 lst = list(SummerMonth) 858 self.assertEqual(len(lst), len(SummerMonth)) 859 self.assertEqual(len(SummerMonth), 3, SummerMonth) 860 self.assertEqual( 861 [SummerMonth.june, SummerMonth.july, SummerMonth.august], 862 lst, 863 ) 864 for i, month in enumerate('june july august'.split(), 30): 865 e = SummerMonth(i) 866 self.assertEqual(e, i) 867 self.assertEqual(e.name, month) 868 self.assertTrue(e in SummerMonth) 869 self.assertTrue(type(e) is SummerMonth) 870 871 def test_programatic_function_type_from_subclass(self): 872 SummerMonth = IntEnum('SummerMonth', 'june july august') 873 lst = list(SummerMonth) 874 self.assertEqual(len(lst), len(SummerMonth)) 875 self.assertEqual(len(SummerMonth), 3, SummerMonth) 876 self.assertEqual( 877 [SummerMonth.june, SummerMonth.july, SummerMonth.august], 878 lst, 879 ) 880 for i, month in enumerate('june july august'.split()): 881 i += 1 882 e = SummerMonth(i) 883 self.assertEqual(e, i) 884 self.assertEqual(e.name, month) 885 self.assertTrue(e in SummerMonth) 886 self.assertTrue(type(e) is SummerMonth) 887 888 def test_programatic_function_type_from_subclass_with_start(self): 889 SummerMonth = IntEnum('SummerMonth', 'june july august', start=40) 890 lst = list(SummerMonth) 891 self.assertEqual(len(lst), len(SummerMonth)) 892 self.assertEqual(len(SummerMonth), 3, SummerMonth) 893 self.assertEqual( 894 [SummerMonth.june, SummerMonth.july, SummerMonth.august], 895 lst, 896 ) 897 for i, month in enumerate('june july august'.split(), 40): 898 e = SummerMonth(i) 899 self.assertEqual(e, i) 900 self.assertEqual(e.name, month) 901 self.assertTrue(e in SummerMonth) 902 self.assertTrue(type(e) is SummerMonth) 903 904 def test_programatic_function_unicode(self): 905 SummerMonth = Enum('SummerMonth', unicode('june july august')) 906 lst = list(SummerMonth) 907 self.assertEqual(len(lst), len(SummerMonth)) 908 self.assertEqual(len(SummerMonth), 3, SummerMonth) 909 self.assertEqual( 910 [SummerMonth.june, SummerMonth.july, SummerMonth.august], 911 lst, 912 ) 913 for i, month in enumerate(unicode('june july august').split()): 914 i += 1 915 e = SummerMonth(i) 916 self.assertEqual(int(e.value), i) 917 self.assertNotEqual(e, i) 918 self.assertEqual(e.name, month) 919 self.assertTrue(e in SummerMonth) 920 self.assertTrue(type(e) is SummerMonth) 921 922 def test_programatic_function_unicode_list(self): 923 SummerMonth = Enum('SummerMonth', [unicode('june'), unicode('july'), unicode('august')]) 924 lst = list(SummerMonth) 925 self.assertEqual(len(lst), len(SummerMonth)) 926 self.assertEqual(len(SummerMonth), 3, SummerMonth) 927 self.assertEqual( 928 [SummerMonth.june, SummerMonth.july, SummerMonth.august], 929 lst, 930 ) 931 for i, month in enumerate(unicode('june july august').split()): 932 i += 1 933 e = SummerMonth(i) 934 self.assertEqual(int(e.value), i) 935 self.assertNotEqual(e, i) 936 self.assertEqual(e.name, month) 937 self.assertTrue(e in SummerMonth) 938 self.assertTrue(type(e) is SummerMonth) 939 940 def test_programatic_function_unicode_iterable(self): 941 SummerMonth = Enum( 942 'SummerMonth', 943 ((unicode('june'), 1), (unicode('july'), 2), (unicode('august'), 3)) 944 ) 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_from_unicode_dict(self): 962 SummerMonth = Enum( 963 'SummerMonth', 964 dict(((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 if pyver < 3.0: 970 self.assertEqual( 971 [SummerMonth.june, SummerMonth.july, SummerMonth.august], 972 lst, 973 ) 974 for i, month in enumerate(unicode('june july august').split()): 975 i += 1 976 e = SummerMonth(i) 977 self.assertEqual(int(e.value), i) 978 self.assertNotEqual(e, i) 979 self.assertEqual(e.name, month) 980 self.assertTrue(e in SummerMonth) 981 self.assertTrue(type(e) is SummerMonth) 982 983 def test_programatic_function_unicode_type(self): 984 SummerMonth = Enum('SummerMonth', unicode('june july august'), type=int) 985 lst = list(SummerMonth) 986 self.assertEqual(len(lst), len(SummerMonth)) 987 self.assertEqual(len(SummerMonth), 3, SummerMonth) 988 self.assertEqual( 989 [SummerMonth.june, SummerMonth.july, SummerMonth.august], 990 lst, 991 ) 992 for i, month in enumerate(unicode('june july august').split()): 993 i += 1 994 e = SummerMonth(i) 995 self.assertEqual(e, i) 996 self.assertEqual(e.name, month) 997 self.assertTrue(e in SummerMonth) 998 self.assertTrue(type(e) is SummerMonth) 999 1000 def test_programatic_function_unicode_type_from_subclass(self): 1001 SummerMonth = IntEnum('SummerMonth', unicode('june july august')) 1002 lst = list(SummerMonth) 1003 self.assertEqual(len(lst), len(SummerMonth)) 1004 self.assertEqual(len(SummerMonth), 3, SummerMonth) 1005 self.assertEqual( 1006 [SummerMonth.june, SummerMonth.july, SummerMonth.august], 1007 lst, 1008 ) 1009 for i, month in enumerate(unicode('june july august').split()): 1010 i += 1 1011 e = SummerMonth(i) 1012 self.assertEqual(e, i) 1013 self.assertEqual(e.name, month) 1014 self.assertTrue(e in SummerMonth) 1015 self.assertTrue(type(e) is SummerMonth) 1016 1017 def test_programmatic_function_unicode_class(self): 1018 if pyver < 3.0: 1019 class_names = unicode('SummerMonth'), 'S\xfcmm\xe9rM\xf6nth'.decode('latin1') 1020 else: 1021 class_names = 'SummerMonth', 'S\xfcmm\xe9rM\xf6nth' 1022 for i, class_name in enumerate(class_names): 1023 if pyver < 3.0 and i == 1: 1024 self.assertRaises(TypeError, Enum, class_name, unicode('june july august')) 1025 else: 1026 SummerMonth = Enum(class_name, unicode('june july august')) 1027 lst = list(SummerMonth) 1028 self.assertEqual(len(lst), len(SummerMonth)) 1029 self.assertEqual(len(SummerMonth), 3, SummerMonth) 1030 self.assertEqual( 1031 [SummerMonth.june, SummerMonth.july, SummerMonth.august], 1032 lst, 1033 ) 1034 for i, month in enumerate(unicode('june july august').split()): 1035 i += 1 1036 e = SummerMonth(i) 1037 self.assertEqual(e.value, i) 1038 self.assertEqual(e.name, month) 1039 self.assertTrue(e in SummerMonth) 1040 self.assertTrue(type(e) is SummerMonth) 1041 1042 def test_subclassing(self): 1043 if isinstance(Name, Exception): 1044 raise Name 1045 self.assertEqual(Name.BDFL, 'Guido van Rossum') 1046 self.assertTrue(Name.BDFL, Name('Guido van Rossum')) 1047 self.assertTrue(Name.BDFL is getattr(Name, 'BDFL')) 1048 test_pickle_dump_load(self.assertTrue, Name.BDFL) 1049 1050 def test_extending(self): 1051 def bad_extension(): 1052 class Color(Enum): 1053 red = 1 1054 green = 2 1055 blue = 3 1056 class MoreColor(Color): 1057 cyan = 4 1058 magenta = 5 1059 yellow = 6 1060 self.assertRaises(TypeError, bad_extension) 1061 1062 def test_exclude_methods(self): 1063 class whatever(Enum): 1064 this = 'that' 1065 these = 'those' 1066 def really(self): 1067 return 'no, not %s' % self.value 1068 self.assertFalse(type(whatever.really) is whatever) 1069 self.assertEqual(whatever.this.really(), 'no, not that') 1070 1071 def test_wrong_inheritance_order(self): 1072 def wrong_inherit(): 1073 class Wrong(Enum, str): 1074 NotHere = 'error before this point' 1075 self.assertRaises(TypeError, wrong_inherit) 1076 1077 def test_intenum_transitivity(self): 1078 class number(IntEnum): 1079 one = 1 1080 two = 2 1081 three = 3 1082 class numero(IntEnum): 1083 uno = 1 1084 dos = 2 1085 tres = 3 1086 self.assertEqual(number.one, numero.uno) 1087 self.assertEqual(number.two, numero.dos) 1088 self.assertEqual(number.three, numero.tres) 1089 1090 def test_introspection(self): 1091 class Number(IntEnum): 1092 one = 100 1093 two = 200 1094 self.assertTrue(Number.one._member_type_ is int) 1095 self.assertTrue(Number._member_type_ is int) 1096 class String(str, Enum): 1097 yarn = 'soft' 1098 rope = 'rough' 1099 wire = 'hard' 1100 self.assertTrue(String.yarn._member_type_ is str) 1101 self.assertTrue(String._member_type_ is str) 1102 class Plain(Enum): 1103 vanilla = 'white' 1104 one = 1 1105 self.assertTrue(Plain.vanilla._member_type_ is object) 1106 self.assertTrue(Plain._member_type_ is object) 1107 1108 def test_wrong_enum_in_call(self): 1109 class Monochrome(Enum): 1110 black = 0 1111 white = 1 1112 class Gender(Enum): 1113 male = 0 1114 female = 1 1115 self.assertRaises(ValueError, Monochrome, Gender.male) 1116 1117 def test_wrong_enum_in_mixed_call(self): 1118 class Monochrome(IntEnum): 1119 black = 0 1120 white = 1 1121 class Gender(Enum): 1122 male = 0 1123 female = 1 1124 self.assertRaises(ValueError, Monochrome, Gender.male) 1125 1126 def test_mixed_enum_in_call_1(self): 1127 class Monochrome(IntEnum): 1128 black = 0 1129 white = 1 1130 class Gender(IntEnum): 1131 male = 0 1132 female = 1 1133 self.assertTrue(Monochrome(Gender.female) is Monochrome.white) 1134 1135 def test_mixed_enum_in_call_2(self): 1136 class Monochrome(Enum): 1137 black = 0 1138 white = 1 1139 class Gender(IntEnum): 1140 male = 0 1141 female = 1 1142 self.assertTrue(Monochrome(Gender.male) is Monochrome.black) 1143 1144 def test_flufl_enum(self): 1145 class Fluflnum(Enum): 1146 def __int__(self): 1147 return int(self.value) 1148 class MailManOptions(Fluflnum): 1149 option1 = 1 1150 option2 = 2 1151 option3 = 3 1152 self.assertEqual(int(MailManOptions.option1), 1) 1153 1154 def test_no_such_enum_member(self): 1155 class Color(Enum): 1156 red = 1 1157 green = 2 1158 blue = 3 1159 self.assertRaises(ValueError, Color, 4) 1160 self.assertRaises(KeyError, Color.__getitem__, 'chartreuse') 1161 1162 def test_new_repr(self): 1163 class Color(Enum): 1164 red = 1 1165 green = 2 1166 blue = 3 1167 def __repr__(self): 1168 return "don't you just love shades of %s?" % self.name 1169 self.assertEqual( 1170 repr(Color.blue), 1171 "don't you just love shades of blue?", 1172 ) 1173 1174 def test_inherited_repr(self): 1175 class MyEnum(Enum): 1176 def __repr__(self): 1177 return "My name is %s." % self.name 1178 class MyIntEnum(int, MyEnum): 1179 this = 1 1180 that = 2 1181 theother = 3 1182 self.assertEqual(repr(MyIntEnum.that), "My name is that.") 1183 1184 def test_multiple_mixin_mro(self): 1185 class auto_enum(EnumMeta): 1186 def __new__(metacls, cls, bases, classdict): 1187 original_dict = classdict 1188 classdict = enum._EnumDict() 1189 for k, v in original_dict.items(): 1190 classdict[k] = v 1191 temp = type(classdict)() 1192 names = set(classdict._member_names) 1193 i = 0 1194 for k in classdict._member_names: 1195 v = classdict[k] 1196 if v == (): 1197 v = i 1198 else: 1199 i = v 1200 i += 1 1201 temp[k] = v 1202 for k, v in classdict.items(): 1203 if k not in names: 1204 temp[k] = v 1205 return super(auto_enum, metacls).__new__( 1206 metacls, cls, bases, temp) 1207 1208 AutoNumberedEnum = auto_enum('AutoNumberedEnum', (Enum,), {}) 1209 1210 AutoIntEnum = auto_enum('AutoIntEnum', (IntEnum,), {}) 1211 1212 class TestAutoNumber(AutoNumberedEnum): 1213 a = () 1214 b = 3 1215 c = () 1216 1217 class TestAutoInt(AutoIntEnum): 1218 a = () 1219 b = 3 1220 c = () 1221 1222 def test_subclasses_with_getnewargs(self): 1223 class NamedInt(int): 1224 __qualname__ = 'NamedInt' # needed for pickle protocol 4 1225 def __new__(cls, *args): 1226 _args = args 1227 if len(args) < 1: 1228 raise TypeError("name and value must be specified") 1229 name, args = args[0], args[1:] 1230 self = int.__new__(cls, *args) 1231 self._intname = name 1232 self._args = _args 1233 return self 1234 def __getnewargs__(self): 1235 return self._args 1236 @property 1237 def __name__(self): 1238 return self._intname 1239 def __repr__(self): 1240 # repr() is updated to include the name and type info 1241 return "%s(%r, %s)" % (type(self).__name__, 1242 self.__name__, 1243 int.__repr__(self)) 1244 def __str__(self): 1245 # str() is unchanged, even if it relies on the repr() fallback 1246 base = int 1247 base_str = base.__str__ 1248 if base_str.__objclass__ is object: 1249 return base.__repr__(self) 1250 return base_str(self) 1251 # for simplicity, we only define one operator that 1252 # propagates expressions 1253 def __add__(self, other): 1254 temp = int(self) + int( other) 1255 if isinstance(self, NamedInt) and isinstance(other, NamedInt): 1256 return NamedInt( 1257 '(%s + %s)' % (self.__name__, other.__name__), 1258 temp ) 1259 else: 1260 return temp 1261 1262 class NEI(NamedInt, Enum): 1263 __qualname__ = 'NEI' # needed for pickle protocol 4 1264 x = ('the-x', 1) 1265 y = ('the-y', 2) 1266 1267 self.assertTrue(NEI.__new__ is Enum.__new__) 1268 self.assertEqual(repr(NEI.x + NEI.y), "NamedInt('(the-x + the-y)', 3)") 1269 globals()['NamedInt'] = NamedInt 1270 globals()['NEI'] = NEI 1271 NI5 = NamedInt('test', 5) 1272 self.assertEqual(NI5, 5) 1273 test_pickle_dump_load(self.assertTrue, NI5, 5) 1274 self.assertEqual(NEI.y.value, 2) 1275 test_pickle_dump_load(self.assertTrue, NEI.y) 1276 1277 if pyver >= 3.4: 1278 def test_subclasses_with_getnewargs_ex(self): 1279 class NamedInt(int): 1280 __qualname__ = 'NamedInt' # needed for pickle protocol 4 1281 def __new__(cls, *args): 1282 _args = args 1283 if len(args) < 2: 1284 raise TypeError("name and value must be specified") 1285 name, args = args[0], args[1:] 1286 self = int.__new__(cls, *args) 1287 self._intname = name 1288 self._args = _args 1289 return self 1290 def __getnewargs_ex__(self): 1291 return self._args, {} 1292 @property 1293 def __name__(self): 1294 return self._intname 1295 def __repr__(self): 1296 # repr() is updated to include the name and type info 1297 return "{}({!r}, {})".format(type(self).__name__, 1298 self.__name__, 1299 int.__repr__(self)) 1300 def __str__(self): 1301 # str() is unchanged, even if it relies on the repr() fallback 1302 base = int 1303 base_str = base.__str__ 1304 if base_str.__objclass__ is object: 1305 return base.__repr__(self) 1306 return base_str(self) 1307 # for simplicity, we only define one operator that 1308 # propagates expressions 1309 def __add__(self, other): 1310 temp = int(self) + int( other) 1311 if isinstance(self, NamedInt) and isinstance(other, NamedInt): 1312 return NamedInt( 1313 '({0} + {1})'.format(self.__name__, other.__name__), 1314 temp ) 1315 else: 1316 return temp 1317 1318 class NEI(NamedInt, Enum): 1319 __qualname__ = 'NEI' # needed for pickle protocol 4 1320 x = ('the-x', 1) 1321 y = ('the-y', 2) 1322 1323 1324 self.assertIs(NEI.__new__, Enum.__new__) 1325 self.assertEqual(repr(NEI.x + NEI.y), "NamedInt('(the-x + the-y)', 3)") 1326 globals()['NamedInt'] = NamedInt 1327 globals()['NEI'] = NEI 1328 NI5 = NamedInt('test', 5) 1329 self.assertEqual(NI5, 5) 1330 test_pickle_dump_load(self.assertEqual, NI5, 5, protocol=(4, HIGHEST_PROTOCOL)) 1331 self.assertEqual(NEI.y.value, 2) 1332 test_pickle_dump_load(self.assertTrue, NEI.y, protocol=(4, HIGHEST_PROTOCOL)) 1333 1334 def test_subclasses_with_reduce(self): 1335 class NamedInt(int): 1336 __qualname__ = 'NamedInt' # needed for pickle protocol 4 1337 def __new__(cls, *args): 1338 _args = args 1339 if len(args) < 1: 1340 raise TypeError("name and value must be specified") 1341 name, args = args[0], args[1:] 1342 self = int.__new__(cls, *args) 1343 self._intname = name 1344 self._args = _args 1345 return self 1346 def __reduce__(self): 1347 return self.__class__, self._args 1348 @property 1349 def __name__(self): 1350 return self._intname 1351 def __repr__(self): 1352 # repr() is updated to include the name and type info 1353 return "%s(%r, %s)" % (type(self).__name__, 1354 self.__name__, 1355 int.__repr__(self)) 1356 def __str__(self): 1357 # str() is unchanged, even if it relies on the repr() fallback 1358 base = int 1359 base_str = base.__str__ 1360 if base_str.__objclass__ is object: 1361 return base.__repr__(self) 1362 return base_str(self) 1363 # for simplicity, we only define one operator that 1364 # propagates expressions 1365 def __add__(self, other): 1366 temp = int(self) + int( other) 1367 if isinstance(self, NamedInt) and isinstance(other, NamedInt): 1368 return NamedInt( 1369 '(%s + %s)' % (self.__name__, other.__name__), 1370 temp ) 1371 else: 1372 return temp 1373 1374 class NEI(NamedInt, Enum): 1375 __qualname__ = 'NEI' # needed for pickle protocol 4 1376 x = ('the-x', 1) 1377 y = ('the-y', 2) 1378 1379 1380 self.assertTrue(NEI.__new__ is Enum.__new__) 1381 self.assertEqual(repr(NEI.x + NEI.y), "NamedInt('(the-x + the-y)', 3)") 1382 globals()['NamedInt'] = NamedInt 1383 globals()['NEI'] = NEI 1384 NI5 = NamedInt('test', 5) 1385 self.assertEqual(NI5, 5) 1386 test_pickle_dump_load(self.assertEqual, NI5, 5) 1387 self.assertEqual(NEI.y.value, 2) 1388 test_pickle_dump_load(self.assertTrue, NEI.y) 1389 1390 def test_subclasses_with_reduce_ex(self): 1391 class NamedInt(int): 1392 __qualname__ = 'NamedInt' # needed for pickle protocol 4 1393 def __new__(cls, *args): 1394 _args = args 1395 if len(args) < 1: 1396 raise TypeError("name and value must be specified") 1397 name, args = args[0], args[1:] 1398 self = int.__new__(cls, *args) 1399 self._intname = name 1400 self._args = _args 1401 return self 1402 def __reduce_ex__(self, proto): 1403 return self.__class__, self._args 1404 @property 1405 def __name__(self): 1406 return self._intname 1407 def __repr__(self): 1408 # repr() is updated to include the name and type info 1409 return "%s(%r, %s)" % (type(self).__name__, 1410 self.__name__, 1411 int.__repr__(self)) 1412 def __str__(self): 1413 # str() is unchanged, even if it relies on the repr() fallback 1414 base = int 1415 base_str = base.__str__ 1416 if base_str.__objclass__ is object: 1417 return base.__repr__(self) 1418 return base_str(self) 1419 # for simplicity, we only define one operator that 1420 # propagates expressions 1421 def __add__(self, other): 1422 temp = int(self) + int( other) 1423 if isinstance(self, NamedInt) and isinstance(other, NamedInt): 1424 return NamedInt( 1425 '(%s + %s)' % (self.__name__, other.__name__), 1426 temp ) 1427 else: 1428 return temp 1429 1430 class NEI(NamedInt, Enum): 1431 __qualname__ = 'NEI' # needed for pickle protocol 4 1432 x = ('the-x', 1) 1433 y = ('the-y', 2) 1434 1435 1436 self.assertTrue(NEI.__new__ is Enum.__new__) 1437 self.assertEqual(repr(NEI.x + NEI.y), "NamedInt('(the-x + the-y)', 3)") 1438 globals()['NamedInt'] = NamedInt 1439 globals()['NEI'] = NEI 1440 NI5 = NamedInt('test', 5) 1441 self.assertEqual(NI5, 5) 1442 test_pickle_dump_load(self.assertEqual, NI5, 5) 1443 self.assertEqual(NEI.y.value, 2) 1444 test_pickle_dump_load(self.assertTrue, NEI.y) 1445 1446 def test_subclasses_without_direct_pickle_support(self): 1447 class NamedInt(int): 1448 __qualname__ = 'NamedInt' 1449 def __new__(cls, *args): 1450 _args = args 1451 name, args = args[0], args[1:] 1452 if len(args) == 0: 1453 raise TypeError("name and value must be specified") 1454 self = int.__new__(cls, *args) 1455 self._intname = name 1456 self._args = _args 1457 return self 1458 @property 1459 def __name__(self): 1460 return self._intname 1461 def __repr__(self): 1462 # repr() is updated to include the name and type info 1463 return "%s(%r, %s)" % (type(self).__name__, 1464 self.__name__, 1465 int.__repr__(self)) 1466 def __str__(self): 1467 # str() is unchanged, even if it relies on the repr() fallback 1468 base = int 1469 base_str = base.__str__ 1470 if base_str.__objclass__ is object: 1471 return base.__repr__(self) 1472 return base_str(self) 1473 # for simplicity, we only define one operator that 1474 # propagates expressions 1475 def __add__(self, other): 1476 temp = int(self) + int( other) 1477 if isinstance(self, NamedInt) and isinstance(other, NamedInt): 1478 return NamedInt( 1479 '(%s + %s)' % (self.__name__, other.__name__), 1480 temp ) 1481 else: 1482 return temp 1483 1484 class NEI(NamedInt, Enum): 1485 __qualname__ = 'NEI' 1486 x = ('the-x', 1) 1487 y = ('the-y', 2) 1488 1489 self.assertTrue(NEI.__new__ is Enum.__new__) 1490 self.assertEqual(repr(NEI.x + NEI.y), "NamedInt('(the-x + the-y)', 3)") 1491 globals()['NamedInt'] = NamedInt 1492 globals()['NEI'] = NEI 1493 NI5 = NamedInt('test', 5) 1494 self.assertEqual(NI5, 5) 1495 self.assertEqual(NEI.y.value, 2) 1496 test_pickle_exception(self.assertRaises, TypeError, NEI.x) 1497 test_pickle_exception(self.assertRaises, PicklingError, NEI) 1498 1499 def test_subclasses_without_direct_pickle_support_using_name(self): 1500 class NamedInt(int): 1501 __qualname__ = 'NamedInt' 1502 def __new__(cls, *args): 1503 _args = args 1504 name, args = args[0], args[1:] 1505 if len(args) == 0: 1506 raise TypeError("name and value must be specified") 1507 self = int.__new__(cls, *args) 1508 self._intname = name 1509 self._args = _args 1510 return self 1511 @property 1512 def __name__(self): 1513 return self._intname 1514 def __repr__(self): 1515 # repr() is updated to include the name and type info 1516 return "%s(%r, %s)" % (type(self).__name__, 1517 self.__name__, 1518 int.__repr__(self)) 1519 def __str__(self): 1520 # str() is unchanged, even if it relies on the repr() fallback 1521 base = int 1522 base_str = base.__str__ 1523 if base_str.__objclass__ is object: 1524 return base.__repr__(self) 1525 return base_str(self) 1526 # for simplicity, we only define one operator that 1527 # propagates expressions 1528 def __add__(self, other): 1529 temp = int(self) + int( other) 1530 if isinstance(self, NamedInt) and isinstance(other, NamedInt): 1531 return NamedInt( 1532 '(%s + %s)' % (self.__name__, other.__name__), 1533 temp ) 1534 else: 1535 return temp 1536 1537 class NEI(NamedInt, Enum): 1538 __qualname__ = 'NEI' 1539 x = ('the-x', 1) 1540 y = ('the-y', 2) 1541 def __reduce_ex__(self, proto): 1542 return getattr, (self.__class__, self._name_) 1543 1544 self.assertTrue(NEI.__new__ is Enum.__new__) 1545 self.assertEqual(repr(NEI.x + NEI.y), "NamedInt('(the-x + the-y)', 3)") 1546 globals()['NamedInt'] = NamedInt 1547 globals()['NEI'] = NEI 1548 NI5 = NamedInt('test', 5) 1549 self.assertEqual(NI5, 5) 1550 self.assertEqual(NEI.y.value, 2) 1551 test_pickle_dump_load(self.assertTrue, NEI.y) 1552 test_pickle_dump_load(self.assertTrue, NEI) 1553 1554 def test_tuple_subclass(self): 1555 class SomeTuple(tuple, Enum): 1556 __qualname__ = 'SomeTuple' 1557 first = (1, 'for the money') 1558 second = (2, 'for the show') 1559 third = (3, 'for the music') 1560 self.assertTrue(type(SomeTuple.first) is SomeTuple) 1561 self.assertTrue(isinstance(SomeTuple.second, tuple)) 1562 self.assertEqual(SomeTuple.third, (3, 'for the music')) 1563 globals()['SomeTuple'] = SomeTuple 1564 test_pickle_dump_load(self.assertTrue, SomeTuple.first) 1565 1566 def test_duplicate_values_give_unique_enum_items(self): 1567 class AutoNumber(Enum): 1568 __order__ = 'enum_m enum_d enum_y' 1569 enum_m = () 1570 enum_d = () 1571 enum_y = () 1572 def __new__(cls): 1573 value = len(cls.__members__) + 1 1574 obj = object.__new__(cls) 1575 obj._value_ = value 1576 return obj 1577 def __int__(self): 1578 return int(self._value_) 1579 self.assertEqual(int(AutoNumber.enum_d), 2) 1580 self.assertEqual(AutoNumber.enum_y.value, 3) 1581 self.assertTrue(AutoNumber(1) is AutoNumber.enum_m) 1582 self.assertEqual( 1583 list(AutoNumber), 1584 [AutoNumber.enum_m, AutoNumber.enum_d, AutoNumber.enum_y], 1585 ) 1586 1587 def test_inherited_new_from_enhanced_enum(self): 1588 class AutoNumber2(Enum): 1589 def __new__(cls): 1590 value = len(cls.__members__) + 1 1591 obj = object.__new__(cls) 1592 obj._value_ = value 1593 return obj 1594 def __int__(self): 1595 return int(self._value_) 1596 class Color(AutoNumber2): 1597 _order_ = 'red green blue' 1598 red = () 1599 green = () 1600 blue = () 1601 self.assertEqual(len(Color), 3, "wrong number of elements: %d (should be %d)" % (len(Color), 3)) 1602 self.assertEqual(list(Color), [Color.red, Color.green, Color.blue]) 1603 if pyver >= 3.0: 1604 self.assertEqual(list(map(int, Color)), [1, 2, 3]) 1605 1606 def test_inherited_new_from_mixed_enum(self): 1607 class AutoNumber3(IntEnum): 1608 def __new__(cls): 1609 value = len(cls.__members__) + 1 1610 obj = int.__new__(cls, value) 1611 obj._value_ = value 1612 return obj 1613 class Color(AutoNumber3): 1614 red = () 1615 green = () 1616 blue = () 1617 self.assertEqual(len(Color), 3, "wrong number of elements: %d (should be %d)" % (len(Color), 3)) 1618 Color.red 1619 Color.green 1620 Color.blue 1621 1622 def test_equality(self): 1623 class AlwaysEqual: 1624 def __eq__(self, other): 1625 return True 1626 class OrdinaryEnum(Enum): 1627 a = 1 1628 self.assertEqual(AlwaysEqual(), OrdinaryEnum.a) 1629 self.assertEqual(OrdinaryEnum.a, AlwaysEqual()) 1630 1631 def test_ordered_mixin(self): 1632 class OrderedEnum(Enum): 1633 def __ge__(self, other): 1634 if self.__class__ is other.__class__: 1635 return self._value_ >= other._value_ 1636 return NotImplemented 1637 def __gt__(self, other): 1638 if self.__class__ is other.__class__: 1639 return self._value_ > other._value_ 1640 return NotImplemented 1641 def __le__(self, other): 1642 if self.__class__ is other.__class__: 1643 return self._value_ <= other._value_ 1644 return NotImplemented 1645 def __lt__(self, other): 1646 if self.__class__ is other.__class__: 1647 return self._value_ < other._value_ 1648 return NotImplemented 1649 class Grade(OrderedEnum): 1650 __order__ = 'A B C D F' 1651 A = 5 1652 B = 4 1653 C = 3 1654 D = 2 1655 F = 1 1656 self.assertEqual(list(Grade), [Grade.A, Grade.B, Grade.C, Grade.D, Grade.F]) 1657 self.assertTrue(Grade.A > Grade.B) 1658 self.assertTrue(Grade.F <= Grade.C) 1659 self.assertTrue(Grade.D < Grade.A) 1660 self.assertTrue(Grade.B >= Grade.B) 1661 1662 def test_extending2(self): 1663 def bad_extension(): 1664 class Shade(Enum): 1665 def shade(self): 1666 print(self.name) 1667 class Color(Shade): 1668 red = 1 1669 green = 2 1670 blue = 3 1671 class MoreColor(Color): 1672 cyan = 4 1673 magenta = 5 1674 yellow = 6 1675 self.assertRaises(TypeError, bad_extension) 1676 1677 def test_extending3(self): 1678 class Shade(Enum): 1679 def shade(self): 1680 return self.name 1681 class Color(Shade): 1682 def hex(self): 1683 return '%s hexlified!' % self.value 1684 class MoreColor(Color): 1685 cyan = 4 1686 magenta = 5 1687 yellow = 6 1688 self.assertEqual(MoreColor.magenta.hex(), '5 hexlified!') 1689 1690 def test_no_duplicates(self): 1691 def bad_duplicates(): 1692 class UniqueEnum(Enum): 1693 def __init__(self, *args): 1694 cls = self.__class__ 1695 if any(self.value == e.value for e in cls): 1696 a = self.name 1697 e = cls(self.value).name 1698 raise ValueError( 1699 "aliases not allowed in UniqueEnum: %r --> %r" 1700 % (a, e) 1701 ) 1702 class Color(UniqueEnum): 1703 red = 1 1704 green = 2 1705 blue = 3 1706 class Color(UniqueEnum): 1707 red = 1 1708 green = 2 1709 blue = 3 1710 grene = 2 1711 self.assertRaises(ValueError, bad_duplicates) 1712 1713 def test_init(self): 1714 class Planet(Enum): 1715 MERCURY = (3.303e+23, 2.4397e6) 1716 VENUS = (4.869e+24, 6.0518e6) 1717 EARTH = (5.976e+24, 6.37814e6) 1718 MARS = (6.421e+23, 3.3972e6) 1719 JUPITER = (1.9e+27, 7.1492e7) 1720 SATURN = (5.688e+26, 6.0268e7) 1721 URANUS = (8.686e+25, 2.5559e7) 1722 NEPTUNE = (1.024e+26, 2.4746e7) 1723 def __init__(self, mass, radius): 1724 self.mass = mass # in kilograms 1725 self.radius = radius # in meters 1726 @property 1727 def surface_gravity(self): 1728 # universal gravitational constant (m3 kg-1 s-2) 1729 G = 6.67300E-11 1730 return G * self.mass / (self.radius * self.radius) 1731 self.assertEqual(round(Planet.EARTH.surface_gravity, 2), 9.80) 1732 self.assertEqual(Planet.EARTH.value, (5.976e+24, 6.37814e6)) 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 _order_ = 'red green blue' 1743 red = () 1744 green = () 1745 blue = () 1746 self.assertEqual(list(ColorInAList), [ColorInAList.red, ColorInAList.green, ColorInAList.blue]) 1747 self.assertEqual(ColorInAList.red.value, [1]) 1748 self.assertEqual(ColorInAList([1]), ColorInAList.red) 1749 1750 def test_conflicting_types_resolved_in_new(self): 1751 class LabelledIntEnum(int, Enum): 1752 def __new__(cls, *args): 1753 value, label = args 1754 obj = int.__new__(cls, value) 1755 obj.label = label 1756 obj._value_ = value 1757 return obj 1758 1759 class LabelledList(LabelledIntEnum): 1760 unprocessed = (1, "Unprocessed") 1761 payment_complete = (2, "Payment Complete") 1762 1763 self.assertEqual(list(LabelledList), [LabelledList.unprocessed, LabelledList.payment_complete]) 1764 self.assertEqual(LabelledList.unprocessed, 1) 1765 self.assertEqual(LabelledList(1), LabelledList.unprocessed) 1766 1767 def test_empty_with_functional_api(self): 1768 empty = enum.IntEnum('Foo', {}) 1769 self.assertEqual(len(empty), 0) 1770 1771 1772class TestUnique(unittest.TestCase): 1773 """2.4 doesn't allow class decorators, use function syntax.""" 1774 1775 def test_unique_clean(self): 1776 class Clean(Enum): 1777 one = 1 1778 two = 'dos' 1779 tres = 4.0 1780 unique(Clean) 1781 class Cleaner(IntEnum): 1782 single = 1 1783 double = 2 1784 triple = 3 1785 unique(Cleaner) 1786 1787 def test_unique_dirty(self): 1788 try: 1789 class Dirty(Enum): 1790 __order__ = 'one two tres' 1791 one = 1 1792 two = 'dos' 1793 tres = 1 1794 unique(Dirty) 1795 except ValueError: 1796 exc = sys.exc_info()[1] 1797 message = exc.args[0] 1798 self.assertTrue('tres -> one' in message) 1799 1800 try: 1801 class Dirtier(IntEnum): 1802 _order_ = 'single double triple turkey' 1803 single = 1 1804 double = 1 1805 triple = 3 1806 turkey = 3 1807 unique(Dirtier) 1808 except ValueError: 1809 exc = sys.exc_info()[1] 1810 message = exc.args[0] 1811 self.assertTrue('double -> single' in message) 1812 self.assertTrue('turkey -> triple' in message) 1813 1814 1815class TestMe(unittest.TestCase): 1816 1817 pass 1818 1819if __name__ == '__main__': 1820 unittest.main() 1821