1# -*- coding: utf-8 -*- 2 3from __future__ import division, print_function 4import sys 5pyver = float('%s.%s' % sys.version_info[:2]) 6import aenum 7import doctest 8import os 9import shutil 10import tempfile 11import unittest 12import warnings 13from aenum import EnumMeta, Enum, IntEnum, AutoNumberEnum, MultiValueEnum, OrderedEnum, UniqueEnum, Flag, IntFlag 14from aenum import NamedTuple, TupleSize, NamedConstant, constant, NoAlias, AutoNumber, AutoValue, Unique 15from aenum import _reduce_ex_by_name, unique, skip, extend_enum, auto, enum, MultiValue, member, nonmember, no_arg 16from collections import OrderedDict 17from datetime import timedelta 18from pickle import dumps, loads, PicklingError, HIGHEST_PROTOCOL 19from operator import or_ as _or_, and_ as _and_, xor as _xor_, inv as _inv_ 20from operator import abs as _abs_, add as _add_, floordiv as _floordiv_ 21from operator import lshift as _lshift_, rshift as _rshift_, mod as _mod_ 22from operator import mul as _mul_, neg as _neg_, pos as _pos_, pow as _pow_ 23from operator import truediv as _truediv_, sub as _sub_ 24if pyver < 3: 25 from operator import div as _div_ 26try: 27 import threading 28except ImportError: 29 threading = None 30 31try: 32 basestring 33except NameError: 34 # In Python 2 basestring is the ancestor of both str and unicode 35 # in Python 3 it's just str, but was missing in 3.1 36 basestring = str 37 38try: 39 any 40except NameError: 41 def any(iterable): 42 for element in iterable: 43 if element: 44 return True 45 return False 46 47try: 48 unicode 49except NameError: 50 unicode = str 51 52try: 53 from enum import EnumMeta as StdlibEnumMeta, Enum as StdlibEnum 54 import enum as enum_module 55 if hasattr(enum_module, 'version'): 56 StdlibEnumMeta = StdlibEnum = None 57 del enum_module 58except ImportError: 59 StdlibEnumMeta = StdlibEnum = None 60 61def load_tests(loader, tests, ignore): 62 tests.addTests(doctest.DocTestSuite(aenum)) 63 tests.addTests(doctest.DocFileSuite( 64 'doc/aenum.rst', 65 package=aenum, 66 optionflags=doctest.ELLIPSIS|doctest.NORMALIZE_WHITESPACE, 67 )) 68 return tests 69 70class TestCase(unittest.TestCase): 71 72 def __init__(self, *args, **kwds): 73 regex = getattr(self, 'assertRaisesRegex', None) 74 if regex is None: 75 self.assertRaisesRegex = getattr(self, 'assertRaisesRegexp') 76 super(TestCase, self).__init__(*args, **kwds) 77 78 @classmethod 79 def setUpClass(cls, *args, **kwds): 80 super(TestCase, cls).setUpClass(*args, **kwds) 81 # filter warnings 82 warnings.filterwarnings( 83 'ignore', 84 'inspect\.getargspec\(\) is deprecated', 85 DeprecationWarning, 86 'aenum', 87 0, 88 ) 89 90# for pickle tests 91try: 92 class Stooges(Enum): 93 LARRY = 1 94 CURLY = 2 95 MOE = 3 96except Exception: 97 Stooges = sys.exc_info()[1] 98 99try: 100 class IntStooges(int, Enum): 101 LARRY = 1 102 CURLY = 2 103 MOE = 3 104except Exception: 105 IntStooges = sys.exc_info()[1] 106 107try: 108 class FloatStooges(float, Enum): 109 LARRY = 1.39 110 CURLY = 2.72 111 MOE = 3.142596 112except Exception: 113 FloatStooges = sys.exc_info()[1] 114 115try: 116 class FlagStooges(Flag): 117 LARRY = 1 118 CURLY = 2 119 MOE = 3 120except Exception as exc: 121 FlagStooges = exc 122 123try: 124 LifeForm = NamedTuple('LifeForm', 'branch genus species', module=__name__) 125except Exception: 126 LifeForm = sys.exc_info()[1] 127 128try: 129 class DeathForm(NamedTuple): 130 color = 0 131 rigidity = 1 132 odor = 2 133except Exception: 134 DeathForm = sys.exc_info()[1] 135 136# for pickle test and subclass tests 137try: 138 class StrEnum(str, Enum): 139 'members become strings' 140 class Name(StrEnum): 141 BDFL = 'Guido van Rossum' 142 FLUFL = 'Barry Warsaw' 143except Exception: 144 Name = sys.exc_info()[1] 145 146try: 147 Question = Enum('Question', 'who what when where why', module=__name__) 148except Exception: 149 Question = sys.exc_info()[1] 150 151try: 152 Answer = Enum('Answer', 'him this then there because') 153except Exception: 154 Answer = sys.exc_info()[1] 155 156try: 157 Theory = Enum('Theory', 'rule law supposition', qualname='spanish_inquisition') 158except Exception: 159 Theory = sys.exc_info()[1] 160 161try: 162 class WhatsIt(NamedTuple): 163 def what(self): 164 return self[0] 165 class ThatsIt(WhatsIt): 166 blah = 0 167 bleh = 1 168except Exception: 169 ThatsIt = sys.exc_info()[1] 170 171# for doctests 172try: 173 class Fruit(Enum): 174 tomato = 1 175 banana = 2 176 cherry = 3 177except Exception: 178 pass 179 180def test_pickle_dump_load(assertion, source, target=None, protocol=(0, HIGHEST_PROTOCOL)): 181 start, stop = protocol 182 failures = [] 183 for protocol in range(start, stop+1): 184 try: 185 if target is None: 186 # if isinstance(source, Enum): 187 # print('tpdl 1') 188 # assertion(loads(dumps(source, protocol=protocol)) is source) 189 # else: 190 # print('tpdl 2') 191 assertion(loads(dumps(source, protocol=protocol)), source) 192 else: 193 # print('tpdl 3') 194 assertion(loads(dumps(source, protocol=protocol)), target) 195 except Exception: 196 exc, tb = sys.exc_info()[1:] 197 failures.append('%2d: %s' %(protocol, exc)) 198 if failures: 199 raise ValueError('Failed with protocols: %s' % ', '.join(failures)) 200 201def test_pickle_exception(assertion, exception, obj, 202 protocol=(0, HIGHEST_PROTOCOL)): 203 start, stop = protocol 204 failures = [] 205 for protocol in range(start, stop+1): 206 try: 207 assertion(exception, dumps, obj, protocol=protocol) 208 except Exception: 209 exc = sys.exc_info()[1] 210 failures.append('%d: %s %s' % (protocol, exc.__class__.__name__, exc)) 211 if failures: 212 raise ValueError('Failed with protocols: %s' % ', '.join(failures)) 213 214if pyver >= 3.0: 215 from aenum.test_v3 import TestEnumV3, TestOrderV3, TestNamedTupleV3 216 from aenum import test_v3 217 test_v3.pyver = pyver 218 test_v3.IntStooges = IntStooges 219 test_v3.test_pickle_exception = test_pickle_exception 220 test_v3.test_pickle_dump_load = test_pickle_dump_load 221 222# for subclassing tests 223 224class classproperty(object): 225 226 def __init__(self, fget=None, fset=None, fdel=None, doc=None): 227 self.fget = fget 228 self.fset = fset 229 self.fdel = fdel 230 if doc is None and fget is not None: 231 doc = fget.__doc__ 232 self.__doc__ = doc 233 234 def __get__(self, instance, ownerclass): 235 return self.fget(ownerclass) 236 237 238# tests 239class TestHelpers(TestCase): 240 # _is_descriptor, _is_sunder, _is_dunder 241 242 def test_is_descriptor(self): 243 class foo: 244 pass 245 for attr in ('__get__','__set__','__delete__'): 246 obj = foo() 247 self.assertFalse(aenum._is_descriptor(obj)) 248 setattr(obj, attr, 1) 249 self.assertTrue(aenum._is_descriptor(obj)) 250 251 def test_is_sunder(self): 252 for s in ('_a_', '_aa_'): 253 self.assertTrue(aenum._is_sunder(s)) 254 255 for s in ('a', 'a_', '_a', '__a', 'a__', '__a__', '_a__', '__a_', '_', 256 '__', '___', '____', '_____',): 257 self.assertFalse(aenum._is_sunder(s)) 258 259 def test_is_dunder(self): 260 for s in ('__a__', '__aa__'): 261 self.assertTrue(aenum._is_dunder(s)) 262 for s in ('a', 'a_', '_a', '__a', 'a__', '_a_', '_a__', '__a_', '_', 263 '__', '___', '____', '_____',): 264 self.assertFalse(aenum._is_dunder(s)) 265 266 def test_auto(self): 267 def tester(first, op, final, second=None): 268 if second is None: 269 left = auto() 270 value = op(left) 271 left.value = first 272 self.assertEqual(value.value, final, 273 "%s %r -> %r != %r" % (op.__name__, first, value, final)) 274 else: 275 left = first 276 right = auto() 277 value = op(left, right) 278 right.value = second 279 self.assertEqual(value.value, final, 280 "forward: %r %s %r -> %r != %r" % (first, op.__name__, second, value.value, final)) 281 left = auto() 282 right = second 283 value = op(left, right) 284 left.value = first 285 self.assertEqual(value.value, final, 286 "reversed: %r %s %r -> %r != %r" % (second, op.__name__, first, value.value, final)) 287 for args in ( 288 (1, _abs_, abs(1)), 289 (-3, _abs_, abs(-3)), 290 (1, _add_, 1+2, 2), 291 (25, _floordiv_, 25 // 5, 5), 292 (49, _truediv_, 49 / 9, 9), 293 (6, _mod_, 6 % 9, 9), 294 (5, _lshift_, 5 << 2, 2), 295 (5, _rshift_, 5 >> 2, 2), 296 (3, _mul_, 3 * 6, 6), 297 (5, _neg_, -5), 298 (-4, _pos_, +(-4)), 299 (2, _pow_, 2**5, 5), 300 (7, _sub_, 7 - 10, 10), 301 (1, _or_, 1 | 2, 2), 302 (3, _xor_, 3 ^ 6, 6), 303 (3, _and_, 3 & 6, 6), 304 (7, _inv_, ~7), 305 ('a', _add_, 'a'+'b', 'b'), 306 ('a', _mul_, 'a' * 3, 3), 307 ): 308 tester(*args) 309 # operator.div is gone in 3 310 if pyver < 3: 311 tester(12, _div_, 12 // 5, 5) 312 # strings are a pain 313 left = auto() 314 right = 'eggs' 315 value = _mod_(left, right) 316 left.value = 'I see 17 %s!' 317 self.assertEqual(value.value, 'I see 17 %s!' % 'eggs') 318 319 def test_constant(self): 320 errors = [] 321 def tester(first, op, final, second=None): 322 if second is None: 323 primary = constant(first) 324 secondary = constant(op(primary)) 325 if secondary.value != final: 326 errors.append( 327 "%s %r -> %r != %r" % (op.__name__, first, secondary.value, final), 328 ) 329 else: 330 left = constant(first) 331 right = second 332 value = op(left, right) 333 if value != final: 334 errors.append( 335 "forward: %r %s %r -> %r != %r" % (first, op.__name__, second, value, final), 336 ) 337 left = first 338 right = constant(second) 339 value = op(left, right) 340 if value != final: 341 errors.append( 342 "reversed: %r %s %r -> %r != %r" % (second, op.__name__, first, value, final), 343 ) 344 for args in ( 345 (1, _abs_, abs(1)), 346 (-3, _abs_, abs(-3)), 347 (1, _add_, 1+2, 2), 348 (25, _floordiv_, 25 // 5, 5), 349 (49, _truediv_, 49 / 9, 9), 350 (6, _mod_, 6 % 9, 9), 351 (5, _lshift_, 5 << 2, 2), 352 (5, _rshift_, 5 >> 2, 2), 353 (3, _mul_, 3 * 6, 6), 354 (5, _neg_, -5), 355 (-4, _pos_, +(-4)), 356 (2, _pow_, 2**5, 5), 357 (7, _sub_, 7 - 10, 10), 358 (1, _or_, 1 | 2, 2), 359 (3, _xor_, 3 ^ 6, 6), 360 (3, _and_, 3 & 6, 6), 361 (7, _inv_, ~7), 362 ('a', _add_, 'a'+'b', 'b'), 363 ('a', _mul_, 'a' * 3, 3), 364 ): 365 tester(*args) 366 # operator.div is gone in 3 367 if pyver < 3: 368 tester(12, _div_, 12 // 5, 5) 369 # strings are a pain 370 left = constant('I see 17 %s!') 371 right = 'eggs' 372 value = _mod_(left, right) 373 if value != 'I see 17 %s!' % 'eggs': 374 errors.append("'I see 17 eggs!' != %r" % value) 375 if errors: 376 print() 377 for error in errors: 378 print(error) 379 self.assertTrue(False) 380 381 382class TestEnum(TestCase): 383 384 def setUp(self): 385 class Season(Enum): 386 SPRING = 1 387 SUMMER = 2 388 AUTUMN = 3 389 WINTER = 4 390 self.Season = Season 391 392 class Konstants(float, Enum): 393 E = 2.7182818 394 PI = 3.1415926 395 TAU = 2 * PI 396 self.Konstants = Konstants 397 398 class Grades(IntEnum): 399 A = 5 400 B = 4 401 C = 3 402 D = 2 403 F = 0 404 self.Grades = Grades 405 406 class Directional(str, Enum): 407 EAST = 'east' 408 WEST = 'west' 409 NORTH = 'north' 410 SOUTH = 'south' 411 self.Directional = Directional 412 413 from datetime import date 414 class Holiday(date, Enum): 415 NEW_YEAR = 2013, 1, 1 416 IDES_OF_MARCH = 2013, 3, 15 417 self.Holiday = Holiday 418 419 def test_members_is_ordereddict_if_ordered(self): 420 class Ordered(Enum): 421 __order__ = 'first second third' 422 first = 'bippity' 423 second = 'boppity' 424 third = 'boo' 425 self.assertTrue(type(Ordered.__members__) is OrderedDict) 426 427 def test_members_is_ordereddict_if_not_ordered(self): 428 class Unordered(Enum): 429 this = 'that' 430 these = 'those' 431 self.assertTrue(type(Unordered.__members__) is OrderedDict) 432 433 def test_enum_in_enum_out(self): 434 Season = self.Season 435 self.assertTrue(Season(Season.WINTER) is Season.WINTER) 436 437 def test_enum_value(self): 438 Season = self.Season 439 self.assertEqual(Season.SPRING.value, 1) 440 441 def test_intenum_value(self): 442 self.assertEqual(IntStooges.CURLY.value, 2) 443 444 def test_enum(self): 445 Season = self.Season 446 lst = list(Season) 447 self.assertEqual(len(lst), len(Season)) 448 self.assertEqual(len(Season), 4, Season) 449 self.assertEqual( 450 [Season.SPRING, Season.SUMMER, Season.AUTUMN, Season.WINTER], lst) 451 452 for i, season in enumerate('SPRING SUMMER AUTUMN WINTER'.split()): 453 i += 1 454 e = Season(i) 455 self.assertEqual(e, getattr(Season, season)) 456 self.assertEqual(e.value, i) 457 self.assertNotEqual(e, i) 458 self.assertEqual(e.name, season) 459 self.assertTrue(e in Season) 460 self.assertTrue(type(e) is Season) 461 self.assertTrue(isinstance(e, Season)) 462 self.assertEqual(str(e), 'Season.' + season) 463 self.assertEqual( 464 repr(e), 465 '<Season.%s: %s>' % (season, i), 466 ) 467 def test_enum_helper(self): 468 e1 = enum(1, 2, three=9) 469 e2 = enum(1, 2, three=9) 470 e3 = enum(1, 2, 9) 471 self.assertTrue(e1 is not e2) 472 self.assertEqual(e1, e2) 473 self.assertNotEqual(e1, e3) 474 self.assertNotEqual(e2, e3) 475 476 def test_enum_in_enum(self): 477 # 478 class Level(Enum): 479 _order_ = 'DATA_CHECK DESIGN_CHECK ALERT' 480 # 481 def __new__(cls, *args, **kwds): 482 member = object.__new__(cls) 483 member._value_ = len(cls) + 1 # members are 1-based 484 return member 485 # 486 def __init__(self, prereq=None, dependent=None): 487 # create priority level lists 488 self.lower_priority_levels = list(self.__class__._member_map_.values()) 489 self.greater_priority_levels = [] 490 # update previous members' greater priority list 491 for member in self.lower_priority_levels: 492 member.greater_priority_levels.append(self) 493 # and save prereq and dependent 494 self.prerequisite = prereq and self.__class__[prereq.name] or None 495 self.dependent = dependent and self.__class__[dependent.name] or None 496 # 497 DATA_CHECK = enum() 498 DESIGN_CHECK = enum(DATA_CHECK) 499 ALERT = enum(None, DATA_CHECK) 500 # 501 self.assertEqual(Level.DATA_CHECK.value, 1) 502 self.assertEqual(Level.DATA_CHECK.prerequisite, None) 503 self.assertEqual(Level.DATA_CHECK.dependent, None) 504 self.assertEqual(Level.DESIGN_CHECK.prerequisite, Level.DATA_CHECK) 505 self.assertEqual(Level.DESIGN_CHECK.dependent, None) 506 self.assertEqual(Level.ALERT.prerequisite, None) 507 self.assertEqual(Level.ALERT.dependent, Level.DATA_CHECK) 508 509 def test_value_name(self): 510 Season = self.Season 511 self.assertEqual(Season.SPRING.name, 'SPRING') 512 self.assertEqual(Season.SPRING.value, 1) 513 def set_name(obj, new_value): 514 obj.name = new_value 515 def set_value(obj, new_value): 516 obj.value = new_value 517 self.assertRaises(AttributeError, set_name, Season.SPRING, 'invierno', ) 518 self.assertRaises(AttributeError, set_value, Season.SPRING, 2) 519 520 def test_attribute_deletion(self): 521 class Season(Enum): 522 SPRING = 1 523 SUMMER = 2 524 AUTUMN = 3 525 WINTER = 4 526 527 def spam(cls): 528 pass 529 530 self.assertTrue(hasattr(Season, 'spam')) 531 del Season.spam 532 self.assertFalse(hasattr(Season, 'spam')) 533 534 self.assertRaises(AttributeError, delattr, Season, 'SPRING') 535 self.assertRaises(AttributeError, delattr, Season, 'DRY') 536 self.assertRaises(AttributeError, delattr, Season.SPRING, 'name') 537 538 def test_bool_of_class(self): 539 class Empty(Enum): 540 pass 541 self.assertTrue(bool(Empty)) 542 543 def test_bool_of_member(self): 544 class Count(Enum): 545 zero = 0 546 one = 1 547 two = 2 548 for member in Count: 549 self.assertTrue(bool(member)) 550 551 def test_invalid_names(self): 552 def create_bad_class_1(): 553 class Wrong(Enum): 554 mro = 9 555 def create_bad_class_2(): 556 class Wrong(Enum): 557 _reserved_ = 3 558 self.assertRaises(ValueError, create_bad_class_1) 559 self.assertRaises(ValueError, create_bad_class_2) 560 561 def test_bool(self): 562 class Logic(Enum): 563 true = True 564 false = False 565 def __bool__(self): 566 return bool(self.value) 567 __nonzero__ = __bool__ 568 self.assertTrue(Logic.true) 569 self.assertFalse(Logic.false) 570 571 def test_contains(self): 572 Season = self.Season 573 self.assertRaises(TypeError, lambda: 'AUTUMN' in Season) 574 self.assertTrue(Season.AUTUMN in Season) 575 self.assertRaises(TypeError, lambda: 3 not in Season) 576 val = Season(3) 577 self.assertTrue(val in Season) 578 # 579 class OtherEnum(Enum): 580 one = 1; two = 2 581 self.assertTrue(OtherEnum.two not in Season) 582 # 583 class Wierd(Enum): 584 this = [1, 2, 3] 585 that = (1, 2, 3) 586 those = {1: 1, 2: 2, 3: 3} 587 self.assertTrue(Wierd.this in Wierd) 588 self.assertRaises(TypeError, lambda: [1, 2, 3] in Wierd) 589 self.assertRaises(TypeError, lambda: {1: 1, 2: 2, 3: 3} in Wierd) 590 591 def test_member_contains(self): 592 self.assertRaises(TypeError, lambda: 'test' in self.Season.AUTUMN) 593 594 if pyver >= 2.6: # when `format` came into being 595 596 def test_format_enum(self): 597 Season = self.Season 598 self.assertEqual('{0}'.format(Season.SPRING), 599 '{0}'.format(str(Season.SPRING))) 600 self.assertEqual( '{0:}'.format(Season.SPRING), 601 '{0:}'.format(str(Season.SPRING))) 602 self.assertEqual('{0:20}'.format(Season.SPRING), 603 '{0:20}'.format(str(Season.SPRING))) 604 self.assertEqual('{0:^20}'.format(Season.SPRING), 605 '{0:^20}'.format(str(Season.SPRING))) 606 self.assertEqual('{0:>20}'.format(Season.SPRING), 607 '{0:>20}'.format(str(Season.SPRING))) 608 self.assertEqual('{0:<20}'.format(Season.SPRING), 609 '{0:<20}'.format(str(Season.SPRING))) 610 611 def test_custom_format(self): 612 class TestFloat(float, Enum): 613 one = 1.0 614 two = 2.0 615 def __format__(self, spec): 616 return 'TestFloat success!' 617 self.assertEqual(str(TestFloat.one), 'TestFloat.one') 618 self.assertEqual('{0}'.format(TestFloat.one), 'TestFloat success!') 619 620 def test_format_with_custom_str(self): 621 class TestInt(int, Enum): 622 one = 1 623 two = 2 624 def __str__(self): 625 return self.name * 3 626 self.assertEqual(str(TestInt.two), 'twotwotwo') 627 self.assertEqual('{0}'.format(TestInt.two), 'twotwotwo') 628 629 def assertFormatIsValue(self, spec, member): 630 self.assertEqual(spec.format(member), spec.format(member.value)) 631 632 def test_format_enum_date(self): 633 Holiday = self.Holiday 634 self.assertFormatIsValue('{0}', Holiday.IDES_OF_MARCH) 635 self.assertFormatIsValue('{0:}', Holiday.IDES_OF_MARCH) 636 self.assertFormatIsValue('{0:20}', Holiday.IDES_OF_MARCH) 637 self.assertFormatIsValue('{0:^20}', Holiday.IDES_OF_MARCH) 638 self.assertFormatIsValue('{0:>20}', Holiday.IDES_OF_MARCH) 639 self.assertFormatIsValue('{0:<20}', Holiday.IDES_OF_MARCH) 640 self.assertFormatIsValue('{0:%Y %m}', Holiday.IDES_OF_MARCH) 641 self.assertFormatIsValue('{0:%Y %m %M:00}', Holiday.IDES_OF_MARCH) 642 643 def test_format_enum_float(self): 644 Konstants = self.Konstants 645 self.assertFormatIsValue('{0}', Konstants.TAU) 646 self.assertFormatIsValue('{0:}', Konstants.TAU) 647 self.assertFormatIsValue('{0:20}', Konstants.TAU) 648 self.assertFormatIsValue('{0:^20}', Konstants.TAU) 649 self.assertFormatIsValue('{0:>20}', Konstants.TAU) 650 self.assertFormatIsValue('{0:<20}', Konstants.TAU) 651 self.assertFormatIsValue('{0:n}', Konstants.TAU) 652 self.assertFormatIsValue('{0:5.2}', Konstants.TAU) 653 self.assertFormatIsValue('{0:f}', Konstants.TAU) 654 655 def test_format_enum_int(self): 656 Grades = self.Grades 657 self.assertFormatIsValue('{0}', Grades.C) 658 self.assertFormatIsValue('{0:}', Grades.C) 659 self.assertFormatIsValue('{0:20}', Grades.C) 660 self.assertFormatIsValue('{0:^20}', Grades.C) 661 self.assertFormatIsValue('{0:>20}', Grades.C) 662 self.assertFormatIsValue('{0:<20}', Grades.C) 663 self.assertFormatIsValue('{0:+}', Grades.C) 664 self.assertFormatIsValue('{0:08X}', Grades.C) 665 self.assertFormatIsValue('{0:b}', Grades.C) 666 667 def test_format_enum_str(self): 668 Directional = self.Directional 669 self.assertFormatIsValue('{0}', Directional.WEST) 670 self.assertFormatIsValue('{0:}', Directional.WEST) 671 self.assertFormatIsValue('{0:20}', Directional.WEST) 672 self.assertFormatIsValue('{0:^20}', Directional.WEST) 673 self.assertFormatIsValue('{0:>20}', Directional.WEST) 674 self.assertFormatIsValue('{0:<20}', Directional.WEST) 675 676 def test_hash(self): 677 Season = self.Season 678 dates = {} 679 dates[Season.WINTER] = '1225' 680 dates[Season.SPRING] = '0315' 681 dates[Season.SUMMER] = '0704' 682 dates[Season.AUTUMN] = '1031' 683 self.assertEqual(dates[Season.AUTUMN], '1031') 684 685 def test_enum_duplicates(self): 686 class Season(Enum): 687 __order__ = "SPRING SUMMER AUTUMN WINTER" 688 SPRING = 1 689 SUMMER = 2 690 AUTUMN = FALL = 3 691 WINTER = 4 692 ANOTHER_SPRING = 1 693 lst = list(Season) 694 self.assertEqual( 695 lst, 696 [Season.SPRING, Season.SUMMER, 697 Season.AUTUMN, Season.WINTER, 698 ]) 699 self.assertTrue(Season.FALL is Season.AUTUMN) 700 self.assertEqual(Season.FALL.value, 3) 701 self.assertEqual(Season.AUTUMN.value, 3) 702 self.assertTrue(Season(3) is Season.AUTUMN) 703 self.assertTrue(Season(1) is Season.SPRING) 704 self.assertEqual(Season.FALL.name, 'AUTUMN') 705 self.assertEqual( 706 set([k for k,v in Season.__members__.items() if v.name != k]), 707 set(['FALL', 'ANOTHER_SPRING']), 708 ) 709 710 def test_enum_with_value_name(self): 711 class Huh(Enum): 712 _order_ = 'name value' 713 name = 1 714 value = 2 715 self.assertEqual( 716 list(Huh), 717 [Huh.name, Huh.value], 718 ) 719 self.assertTrue(type(Huh.name) is Huh) 720 self.assertEqual(Huh.name.name, 'name') 721 self.assertEqual(Huh.name.value, 1) 722 723 def test_intenum_from_scratch(self): 724 class phy(int, Enum): 725 pi = 3 726 tau = 2 * pi 727 self.assertTrue(phy.pi < phy.tau) 728 729 def test_intenum_inherited(self): 730 class IntEnum(int, Enum): 731 pass 732 class phy(IntEnum): 733 pi = 3 734 tau = 2 * pi 735 self.assertTrue(phy.pi < phy.tau) 736 737 def test_floatenum_from_scratch(self): 738 class phy(float, Enum): 739 pi = 3.1415926 740 tau = 2 * pi 741 self.assertTrue(phy.pi < phy.tau) 742 743 def test_floatenum_inherited(self): 744 class FloatEnum(float, Enum): 745 pass 746 class phy(FloatEnum): 747 pi = 3.1415926 748 tau = 2 * pi 749 self.assertTrue(phy.pi < phy.tau) 750 751 def test_strenum_from_scratch(self): 752 class phy(str, Enum): 753 pi = 'Pi' 754 tau = 'Tau' 755 self.assertTrue(phy.pi < phy.tau) 756 757 def test_strenum_inherited(self): 758 class StrEnum(str, Enum): 759 pass 760 class phy(StrEnum): 761 pi = 'Pi' 762 tau = 'Tau' 763 self.assertTrue(phy.pi < phy.tau) 764 765 def test_intenum(self): 766 class WeekDay(IntEnum): 767 SUNDAY = 1 768 MONDAY = 2 769 TUESDAY = 3 770 WEDNESDAY = 4 771 THURSDAY = 5 772 FRIDAY = 6 773 SATURDAY = 7 774 775 self.assertEqual(['a', 'b', 'c'][WeekDay.MONDAY], 'c') 776 self.assertEqual([i for i in range(WeekDay.TUESDAY)], [0, 1, 2]) 777 778 lst = list(WeekDay) 779 self.assertEqual(len(lst), len(WeekDay)) 780 self.assertEqual(len(WeekDay), 7) 781 target = 'SUNDAY MONDAY TUESDAY WEDNESDAY THURSDAY FRIDAY SATURDAY' 782 target = target.split() 783 for i, weekday in enumerate(target): 784 i += 1 785 e = WeekDay(i) 786 self.assertEqual(e, i) 787 self.assertEqual(int(e), i) 788 self.assertEqual(e.name, weekday) 789 self.assertTrue(e in WeekDay) 790 self.assertEqual(lst.index(e)+1, i) 791 self.assertTrue(0 < e < 8) 792 self.assertTrue(type(e) is WeekDay) 793 self.assertTrue(isinstance(e, int)) 794 self.assertTrue(isinstance(e, Enum)) 795 796 def test_intenum_duplicates(self): 797 class WeekDay(IntEnum): 798 __order__ = 'SUNDAY MONDAY TUESDAY WEDNESDAY THURSDAY FRIDAY SATURDAY' 799 SUNDAY = 1 800 MONDAY = 2 801 TUESDAY = TEUSDAY = 3 802 WEDNESDAY = 4 803 THURSDAY = 5 804 FRIDAY = 6 805 SATURDAY = 7 806 self.assertTrue(WeekDay.TEUSDAY is WeekDay.TUESDAY) 807 self.assertEqual(WeekDay(3).name, 'TUESDAY') 808 self.assertEqual([k for k,v in WeekDay.__members__.items() 809 if v.name != k], ['TEUSDAY', ]) 810 811 def test_floatenum_fromhex(self): 812 h = float.hex(FloatStooges.MOE.value) 813 self.assertIs(FloatStooges.fromhex(h), FloatStooges.MOE) 814 h = float.hex(FloatStooges.MOE.value + 0.01) 815 with self.assertRaises(ValueError): 816 FloatStooges.fromhex(h) 817 818 def test_pickle_enum(self): 819 if isinstance(Stooges, Exception): 820 raise Stooges 821 test_pickle_dump_load(self.assertTrue, Stooges.CURLY) 822 test_pickle_dump_load(self.assertTrue, Stooges) 823 824 def test_pickle_int(self): 825 if isinstance(IntStooges, Exception): 826 raise IntStooges 827 test_pickle_dump_load(self.assertTrue, IntStooges.CURLY) 828 test_pickle_dump_load(self.assertTrue, IntStooges) 829 830 def test_pickle_float(self): 831 if isinstance(FloatStooges, Exception): 832 raise FloatStooges 833 test_pickle_dump_load(self.assertTrue, FloatStooges.CURLY) 834 test_pickle_dump_load(self.assertTrue, FloatStooges) 835 836 def test_pickle_enum_function(self): 837 if isinstance(Answer, Exception): 838 raise Answer 839 test_pickle_dump_load(self.assertTrue, Answer.him) 840 test_pickle_dump_load(self.assertTrue, Answer) 841 842 def test_pickle_enum_function_with_module(self): 843 if isinstance(Question, Exception): 844 raise Question 845 test_pickle_dump_load(self.assertTrue, Question.who) 846 test_pickle_dump_load(self.assertTrue, Question) 847 848 def test_pickle_by_name(self): 849 class ReplaceGlobalInt(IntEnum): 850 ONE = 1 851 TWO = 2 852 ReplaceGlobalInt.__reduce_ex__ = _reduce_ex_by_name 853 for proto in range(HIGHEST_PROTOCOL): 854 self.assertEqual(ReplaceGlobalInt.TWO.__reduce_ex__(proto), 'TWO') 855 856 def test_exploding_pickle(self): 857 BadPickle = Enum('BadPickle', 'dill sweet bread-n-butter') 858 aenum._make_class_unpicklable(BadPickle) 859 globals()['BadPickle'] = BadPickle 860 test_pickle_exception(self.assertRaises, TypeError, BadPickle.dill) 861 test_pickle_exception(self.assertRaises, PicklingError, BadPickle) 862 863 def test_string_enum(self): 864 class SkillLevel(str, Enum): 865 master = 'what is the sound of one hand clapping?' 866 journeyman = 'why did the chicken cross the road?' 867 apprentice = 'knock, knock!' 868 self.assertEqual(SkillLevel.apprentice, 'knock, knock!') 869 870 def test_getattr_getitem(self): 871 class Period(Enum): 872 morning = 1 873 noon = 2 874 evening = 3 875 night = 4 876 self.assertTrue(Period(2) is Period.noon) 877 self.assertTrue(getattr(Period, 'night') is Period.night) 878 self.assertTrue(Period['morning'] is Period.morning) 879 880 def test_getattr_dunder(self): 881 Season = self.Season 882 self.assertTrue(getattr(Season, '__hash__')) 883 884 def test_iteration_order(self): 885 class Season(Enum): 886 __order__ = 'SUMMER WINTER AUTUMN SPRING' 887 SUMMER = 2 888 WINTER = 4 889 AUTUMN = 3 890 SPRING = 1 891 self.assertEqual( 892 list(Season), 893 [Season.SUMMER, Season.WINTER, Season.AUTUMN, Season.SPRING], 894 ) 895 896 def test_iteration_order_reversed(self): 897 self.assertEqual( 898 list(reversed(self.Season)), 899 [self.Season.WINTER, self.Season.AUTUMN, self.Season.SUMMER, 900 self.Season.SPRING] 901 ) 902 903 def test_iteration_order_with_unorderable_values(self): 904 class Complex(Enum): 905 a = complex(7, 9) 906 b = complex(3.14, 2) 907 c = complex(1, -1) 908 d = complex(-77, 32) 909 self.assertEqual( 910 list(Complex), 911 [Complex.a, Complex.b, Complex.c, Complex.d], 912 ) 913 914 def test_programatic_function_string(self): 915 SummerMonth = Enum('SummerMonth', 'june july august') 916 lst = list(SummerMonth) 917 self.assertEqual(len(lst), len(SummerMonth)) 918 self.assertEqual(len(SummerMonth), 3, SummerMonth) 919 self.assertEqual( 920 [SummerMonth.june, SummerMonth.july, SummerMonth.august], 921 lst, 922 ) 923 for i, month in enumerate('june july august'.split()): 924 i += 1 925 e = SummerMonth(i) 926 self.assertEqual(int(e.value), i) 927 self.assertNotEqual(e, i) 928 self.assertEqual(e.name, month) 929 self.assertTrue(e in SummerMonth) 930 self.assertTrue(type(e) is SummerMonth) 931 932 def test_programatic_function_string_with_start(self): 933 SummerMonth = Enum('SummerMonth', 'june july august', start=10) 934 lst = list(SummerMonth) 935 self.assertEqual(len(lst), len(SummerMonth)) 936 self.assertEqual(len(SummerMonth), 3, SummerMonth) 937 self.assertEqual( 938 [SummerMonth.june, SummerMonth.july, SummerMonth.august], 939 lst, 940 ) 941 for i, month in enumerate('june july august'.split(), 10): 942 e = SummerMonth(i) 943 self.assertEqual(int(e.value), i) 944 self.assertNotEqual(e, i) 945 self.assertEqual(e.name, month) 946 self.assertTrue(e in SummerMonth) 947 self.assertTrue(type(e) is SummerMonth) 948 949 def test_programatic_function_string_list(self): 950 SummerMonth = Enum('SummerMonth', ['june', 'july', 'august']) 951 lst = list(SummerMonth) 952 self.assertEqual(len(lst), len(SummerMonth)) 953 self.assertEqual(len(SummerMonth), 3, SummerMonth) 954 self.assertEqual( 955 [SummerMonth.june, SummerMonth.july, SummerMonth.august], 956 lst, 957 ) 958 for i, month in enumerate('june july august'.split()): 959 i += 1 960 e = SummerMonth(i) 961 self.assertEqual(int(e.value), i) 962 self.assertNotEqual(e, i) 963 self.assertEqual(e.name, month) 964 self.assertTrue(e in SummerMonth) 965 self.assertTrue(type(e) is SummerMonth) 966 967 def test_programatic_function_string_list_with_start(self): 968 SummerMonth = Enum('SummerMonth', ['june', 'july', 'august'], start=20) 969 lst = list(SummerMonth) 970 self.assertEqual(len(lst), len(SummerMonth)) 971 self.assertEqual(len(SummerMonth), 3, SummerMonth) 972 self.assertEqual( 973 [SummerMonth.june, SummerMonth.july, SummerMonth.august], 974 lst, 975 ) 976 for i, month in enumerate('june july august'.split(), 20): 977 e = SummerMonth(i) 978 self.assertEqual(int(e.value), i) 979 self.assertNotEqual(e, i) 980 self.assertEqual(e.name, month) 981 self.assertTrue(e in SummerMonth) 982 self.assertTrue(type(e) is SummerMonth) 983 984 def test_programatic_function_iterable(self): 985 SummerMonth = Enum( 986 'SummerMonth', 987 (('june', 1), ('july', 2), ('august', 3)) 988 ) 989 lst = list(SummerMonth) 990 self.assertEqual(len(lst), len(SummerMonth)) 991 self.assertEqual(len(SummerMonth), 3, SummerMonth) 992 self.assertEqual( 993 [SummerMonth.june, SummerMonth.july, SummerMonth.august], 994 lst, 995 ) 996 for i, month in enumerate('june july august'.split()): 997 i += 1 998 e = SummerMonth(i) 999 self.assertEqual(int(e.value), i) 1000 self.assertNotEqual(e, i) 1001 self.assertEqual(e.name, month) 1002 self.assertTrue(e in SummerMonth) 1003 self.assertTrue(type(e) is SummerMonth) 1004 1005 def test_programatic_function_from_dict(self): 1006 SummerMonth = Enum( 1007 'SummerMonth', 1008 dict((('june', 1), ('july', 2), ('august', 3))) 1009 ) 1010 lst = list(SummerMonth) 1011 self.assertEqual(len(lst), len(SummerMonth)) 1012 self.assertEqual(len(SummerMonth), 3, SummerMonth) 1013 if pyver < 3.0: 1014 self.assertEqual( 1015 [SummerMonth.june, SummerMonth.july, SummerMonth.august], 1016 lst, 1017 ) 1018 for i, month in enumerate('june july august'.split()): 1019 i += 1 1020 e = SummerMonth(i) 1021 self.assertEqual(int(e.value), i) 1022 self.assertNotEqual(e, i) 1023 self.assertEqual(e.name, month) 1024 self.assertTrue(e in SummerMonth) 1025 self.assertTrue(type(e) is SummerMonth) 1026 1027 def test_programatic_function_type(self): 1028 SummerMonth = Enum('SummerMonth', 'june july august', type=int) 1029 lst = list(SummerMonth) 1030 self.assertEqual(len(lst), len(SummerMonth)) 1031 self.assertEqual(len(SummerMonth), 3, SummerMonth) 1032 self.assertEqual( 1033 [SummerMonth.june, SummerMonth.july, SummerMonth.august], 1034 lst, 1035 ) 1036 for i, month in enumerate('june july august'.split()): 1037 i += 1 1038 e = SummerMonth(i) 1039 self.assertEqual(e, i) 1040 self.assertEqual(e.name, month) 1041 self.assertTrue(e in SummerMonth) 1042 self.assertTrue(type(e) is SummerMonth) 1043 1044 def test_programatic_function_type_with_start(self): 1045 SummerMonth = Enum('SummerMonth', 'june july august', type=int, start=30) 1046 lst = list(SummerMonth) 1047 self.assertEqual(len(lst), len(SummerMonth)) 1048 self.assertEqual(len(SummerMonth), 3, SummerMonth) 1049 self.assertEqual( 1050 [SummerMonth.june, SummerMonth.july, SummerMonth.august], 1051 lst, 1052 ) 1053 for i, month in enumerate('june july august'.split(), 30): 1054 e = SummerMonth(i) 1055 self.assertEqual(e, i) 1056 self.assertEqual(e.name, month) 1057 self.assertTrue(e in SummerMonth) 1058 self.assertTrue(type(e) is SummerMonth) 1059 1060 def test_programatic_function_type_from_subclass(self): 1061 SummerMonth = IntEnum('SummerMonth', 'june july august') 1062 lst = list(SummerMonth) 1063 self.assertEqual(len(lst), len(SummerMonth)) 1064 self.assertEqual(len(SummerMonth), 3, SummerMonth) 1065 self.assertEqual( 1066 [SummerMonth.june, SummerMonth.july, SummerMonth.august], 1067 lst, 1068 ) 1069 for i, month in enumerate('june july august'.split()): 1070 i += 1 1071 e = SummerMonth(i) 1072 self.assertEqual(e, i) 1073 self.assertEqual(e.name, month) 1074 self.assertTrue(e in SummerMonth) 1075 self.assertTrue(type(e) is SummerMonth) 1076 1077 def test_programatic_function_type_from_subclass_with_start(self): 1078 SummerMonth = IntEnum('SummerMonth', 'june july august', start=40) 1079 lst = list(SummerMonth) 1080 self.assertEqual(len(lst), len(SummerMonth)) 1081 self.assertEqual(len(SummerMonth), 3, SummerMonth) 1082 self.assertEqual( 1083 [SummerMonth.june, SummerMonth.july, SummerMonth.august], 1084 lst, 1085 ) 1086 for i, month in enumerate('june july august'.split(), 40): 1087 e = SummerMonth(i) 1088 self.assertEqual(e, i) 1089 self.assertEqual(e.name, month) 1090 self.assertTrue(e in SummerMonth) 1091 self.assertTrue(type(e) is SummerMonth) 1092 1093 def test_programatic_function_unicode(self): 1094 SummerMonth = Enum('SummerMonth', unicode('june july august')) 1095 lst = list(SummerMonth) 1096 self.assertEqual(len(lst), len(SummerMonth)) 1097 self.assertEqual(len(SummerMonth), 3, SummerMonth) 1098 self.assertEqual( 1099 [SummerMonth.june, SummerMonth.july, SummerMonth.august], 1100 lst, 1101 ) 1102 for i, month in enumerate(unicode('june july august').split()): 1103 i += 1 1104 e = SummerMonth(i) 1105 self.assertEqual(int(e.value), i) 1106 self.assertNotEqual(e, i) 1107 self.assertEqual(e.name, month) 1108 self.assertTrue(e in SummerMonth) 1109 self.assertTrue(type(e) is SummerMonth) 1110 1111 def test_programatic_function_unicode_list(self): 1112 SummerMonth = Enum('SummerMonth', [unicode('june'), unicode('july'), unicode('august')]) 1113 lst = list(SummerMonth) 1114 self.assertEqual(len(lst), len(SummerMonth)) 1115 self.assertEqual(len(SummerMonth), 3, SummerMonth) 1116 self.assertEqual( 1117 [SummerMonth.june, SummerMonth.july, SummerMonth.august], 1118 lst, 1119 ) 1120 for i, month in enumerate(unicode('june july august').split()): 1121 i += 1 1122 e = SummerMonth(i) 1123 self.assertEqual(int(e.value), i) 1124 self.assertNotEqual(e, i) 1125 self.assertEqual(e.name, month) 1126 self.assertTrue(e in SummerMonth) 1127 self.assertTrue(type(e) is SummerMonth) 1128 1129 def test_programatic_function_unicode_iterable(self): 1130 SummerMonth = Enum( 1131 'SummerMonth', 1132 ((unicode('june'), 1), (unicode('july'), 2), (unicode('august'), 3)) 1133 ) 1134 lst = list(SummerMonth) 1135 self.assertEqual(len(lst), len(SummerMonth)) 1136 self.assertEqual(len(SummerMonth), 3, SummerMonth) 1137 self.assertEqual( 1138 [SummerMonth.june, SummerMonth.july, SummerMonth.august], 1139 lst, 1140 ) 1141 for i, month in enumerate(unicode('june july august').split()): 1142 i += 1 1143 e = SummerMonth(i) 1144 self.assertEqual(int(e.value), i) 1145 self.assertNotEqual(e, i) 1146 self.assertEqual(e.name, month) 1147 self.assertTrue(e in SummerMonth) 1148 self.assertTrue(type(e) is SummerMonth) 1149 1150 def test_programatic_function_from_unicode_dict(self): 1151 SummerMonth = Enum( 1152 'SummerMonth', 1153 dict(((unicode('june'), 1), (unicode('july'), 2), (unicode('august'), 3))) 1154 ) 1155 lst = list(SummerMonth) 1156 self.assertEqual(len(lst), len(SummerMonth)) 1157 self.assertEqual(len(SummerMonth), 3, SummerMonth) 1158 if pyver < 3.0: 1159 self.assertEqual( 1160 [SummerMonth.june, SummerMonth.july, SummerMonth.august], 1161 lst, 1162 ) 1163 for i, month in enumerate(unicode('june july august').split()): 1164 i += 1 1165 e = SummerMonth(i) 1166 self.assertEqual(int(e.value), i) 1167 self.assertNotEqual(e, i) 1168 self.assertEqual(e.name, month) 1169 self.assertTrue(e in SummerMonth) 1170 self.assertTrue(type(e) is SummerMonth) 1171 1172 def test_programatic_function_unicode_type(self): 1173 SummerMonth = Enum('SummerMonth', unicode('june july august'), type=int) 1174 lst = list(SummerMonth) 1175 self.assertEqual(len(lst), len(SummerMonth)) 1176 self.assertEqual(len(SummerMonth), 3, SummerMonth) 1177 self.assertEqual( 1178 [SummerMonth.june, SummerMonth.july, SummerMonth.august], 1179 lst, 1180 ) 1181 for i, month in enumerate(unicode('june july august').split()): 1182 i += 1 1183 e = SummerMonth(i) 1184 self.assertEqual(e, i) 1185 self.assertEqual(e.name, month) 1186 self.assertTrue(e in SummerMonth) 1187 self.assertTrue(type(e) is SummerMonth) 1188 1189 def test_programatic_function_unicode_type_from_subclass(self): 1190 SummerMonth = IntEnum('SummerMonth', unicode('june july august')) 1191 lst = list(SummerMonth) 1192 self.assertEqual(len(lst), len(SummerMonth)) 1193 self.assertEqual(len(SummerMonth), 3, SummerMonth) 1194 self.assertEqual( 1195 [SummerMonth.june, SummerMonth.july, SummerMonth.august], 1196 lst, 1197 ) 1198 for i, month in enumerate(unicode('june july august').split()): 1199 i += 1 1200 e = SummerMonth(i) 1201 self.assertEqual(e, i) 1202 self.assertEqual(e.name, month) 1203 self.assertTrue(e in SummerMonth) 1204 self.assertTrue(type(e) is SummerMonth) 1205 1206 def test_programmatic_function_unicode_class(self): 1207 if pyver < 3.0: 1208 class_names = unicode('SummerMonth'), 'S\xfcmm\xe9rM\xf6nth'.decode('latin1') 1209 else: 1210 class_names = 'SummerMonth', 'S\xfcmm\xe9rM\xf6nth' 1211 for i, class_name in enumerate(class_names): 1212 if pyver < 3.0 and i == 1: 1213 self.assertRaises(TypeError, Enum, class_name, unicode('june july august')) 1214 else: 1215 SummerMonth = Enum(class_name, unicode('june july august')) 1216 lst = list(SummerMonth) 1217 self.assertEqual(len(lst), len(SummerMonth)) 1218 self.assertEqual(len(SummerMonth), 3, SummerMonth) 1219 self.assertEqual( 1220 [SummerMonth.june, SummerMonth.july, SummerMonth.august], 1221 lst, 1222 ) 1223 for i, month in enumerate(unicode('june july august').split()): 1224 i += 1 1225 e = SummerMonth(i) 1226 self.assertEqual(e.value, i) 1227 self.assertEqual(e.name, month) 1228 self.assertTrue(e in SummerMonth) 1229 self.assertTrue(type(e) is SummerMonth) 1230 1231 def test_subclassing(self): 1232 if isinstance(Name, Exception): 1233 raise Name 1234 self.assertEqual(Name.BDFL, 'Guido van Rossum') 1235 self.assertTrue(Name.BDFL, Name('Guido van Rossum')) 1236 self.assertTrue(Name.BDFL is getattr(Name, 'BDFL')) 1237 test_pickle_dump_load(self.assertTrue, Name.BDFL) 1238 1239 def test_extending(self): 1240 def bad_extension(): 1241 class Color(Enum): 1242 red = 1 1243 green = 2 1244 blue = 3 1245 class MoreColor(Color): 1246 cyan = 4 1247 magenta = 5 1248 yellow = 6 1249 self.assertRaises(TypeError, bad_extension) 1250 1251 def test_exclude_methods(self): 1252 class whatever(Enum): 1253 this = 'that' 1254 these = 'those' 1255 def really(self): 1256 return 'no, not %s' % self.value 1257 self.assertFalse(type(whatever.really) is whatever) 1258 self.assertEqual(whatever.this.really(), 'no, not that') 1259 1260 def test_wrong_inheritance_order(self): 1261 def wrong_inherit(): 1262 class Wrong(Enum, str): 1263 NotHere = 'error before this point' 1264 self.assertRaises(TypeError, wrong_inherit) 1265 1266 def test_intenum_transitivity(self): 1267 class number(IntEnum): 1268 one = 1 1269 two = 2 1270 three = 3 1271 class numero(IntEnum): 1272 uno = 1 1273 dos = 2 1274 tres = 3 1275 self.assertEqual(number.one, numero.uno) 1276 self.assertEqual(number.two, numero.dos) 1277 self.assertEqual(number.three, numero.tres) 1278 1279 def test_introspection(self): 1280 class Number(IntEnum): 1281 one = 100 1282 two = 200 1283 self.assertTrue(Number.one._member_type_ is int) 1284 self.assertTrue(Number._member_type_ is int) 1285 class String(str, Enum): 1286 yarn = 'soft' 1287 rope = 'rough' 1288 wire = 'hard' 1289 self.assertTrue(String.yarn._member_type_ is str) 1290 self.assertTrue(String._member_type_ is str) 1291 class Plain(Enum): 1292 vanilla = 'white' 1293 one = 1 1294 self.assertTrue(Plain.vanilla._member_type_ is object) 1295 self.assertTrue(Plain._member_type_ is object) 1296 1297 def test_wrong_enum_in_call(self): 1298 class Monochrome(Enum): 1299 black = 0 1300 white = 1 1301 class Gender(Enum): 1302 male = 0 1303 female = 1 1304 self.assertRaises(ValueError, Monochrome, Gender.male) 1305 1306 def test_wrong_enum_in_mixed_call(self): 1307 class Monochrome(IntEnum): 1308 black = 0 1309 white = 1 1310 class Gender(Enum): 1311 male = 0 1312 female = 1 1313 self.assertRaises(ValueError, Monochrome, Gender.male) 1314 1315 def test_mixed_enum_in_call_1(self): 1316 class Monochrome(IntEnum): 1317 black = 0 1318 white = 1 1319 class Gender(IntEnum): 1320 male = 0 1321 female = 1 1322 self.assertTrue(Monochrome(Gender.female) is Monochrome.white) 1323 1324 def test_mixed_enum_in_call_2(self): 1325 class Monochrome(Enum): 1326 black = 0 1327 white = 1 1328 class Gender(IntEnum): 1329 male = 0 1330 female = 1 1331 self.assertTrue(Monochrome(Gender.male) is Monochrome.black) 1332 1333 def test_flufl_enum(self): 1334 class Fluflnum(Enum): 1335 def __int__(self): 1336 return int(self.value) 1337 class MailManOptions(Fluflnum): 1338 option1 = 1 1339 option2 = 2 1340 option3 = 3 1341 self.assertEqual(int(MailManOptions.option1), 1) 1342 1343 def test_no_such_enum_member(self): 1344 class Color(Enum): 1345 red = 1 1346 green = 2 1347 blue = 3 1348 self.assertRaises(ValueError, Color, 4) 1349 self.assertRaises(KeyError, Color.__getitem__, 'chartreuse') 1350 1351 def test_new_repr(self): 1352 class Color(Enum): 1353 red = 1 1354 green = 2 1355 blue = 3 1356 def __repr__(self): 1357 return "don't you just love shades of %s?" % self.name 1358 self.assertEqual( 1359 repr(Color.blue), 1360 "don't you just love shades of blue?", 1361 ) 1362 1363 def test_inherited_repr(self): 1364 class MyEnum(Enum): 1365 def __repr__(self): 1366 return "My name is %s." % self.name 1367 class MyIntEnum(int, MyEnum): 1368 this = 1 1369 that = 2 1370 theother = 3 1371 self.assertEqual(repr(MyIntEnum.that), "My name is that.") 1372 1373 def test_multiple_mixin_mro(self): 1374 class auto_enum(EnumMeta): 1375 def __new__(metacls, cls, bases, classdict): 1376 original_dict = classdict 1377 temp_dict = metacls.__prepare__(cls, bases, {}) 1378 if hasattr(original_dict, '_member_names'): 1379 for k in original_dict._member_names: 1380 temp_dict[k] = original_dict[k] 1381 sunders = [k for k in original_dict.keys() if aenum._is_sunder(k)] 1382 else: 1383 sunders = [] 1384 for k, v in original_dict.items(): 1385 if aenum._is_sunder(k): 1386 sunders.append(k) 1387 temp_dict[k] = v 1388 classdict = metacls.__prepare__(cls, bases, {}) 1389 i = 0 1390 for k in sunders: 1391 classdict[k] = original_dict[k] 1392 for k in temp_dict._member_names: 1393 v = original_dict[k] 1394 if v == (): 1395 v = i 1396 else: 1397 i = v 1398 i += 1 1399 classdict[k] = v 1400 for k, v in original_dict.items(): 1401 if k not in temp_dict._member_names and k not in sunders: 1402 classdict[k] = v 1403 return super(auto_enum, metacls).__new__( 1404 metacls, cls, bases, classdict) 1405 1406 AutoNumberedEnum = auto_enum('AutoNumberedEnum', (Enum,), {}) 1407 1408 AutoIntEnum = auto_enum('AutoIntEnum', (IntEnum,), {}) 1409 1410 class TestAutoNumber(AutoNumberedEnum): 1411 a = () 1412 b = 3 1413 c = () 1414 self.assertEqual(TestAutoNumber.b.value, 3) 1415 1416 if pyver >= 3.0: 1417 self.assertEqual( 1418 [TestAutoNumber.a.value, TestAutoNumber.b.value, TestAutoNumber.c.value], 1419 [0, 3, 4], 1420 ) 1421 1422 class TestAutoInt(AutoIntEnum): 1423 a = () 1424 b = 3 1425 c = () 1426 self.assertEqual(TestAutoInt.b, 3) 1427 1428 if pyver >= 3.0: 1429 self.assertEqual( 1430 [TestAutoInt.a.value, TestAutoInt.b.value, TestAutoInt.c.value], 1431 [0, 3, 4], 1432 ) 1433 1434 def test_meta_reconfigure(self): 1435 1436 def identity(*args): 1437 if len(args) == 1: 1438 return args[0] 1439 return args 1440 1441 JSONEnum = None 1442 1443 class JSONEnumMeta(EnumMeta): 1444 1445 @classmethod 1446 def __prepare__(metacls, cls, bases, init=None, start=None, settings=()): 1447 return {} 1448 1449 def __init__(cls, *args , **kwds): 1450 super(JSONEnumMeta, cls).__init__(*args) 1451 1452 def __new__(metacls, cls, bases, clsdict, init=None, start=None, settings=()): 1453 import json 1454 members = [] 1455 if JSONEnum is not None: 1456 if '_file' not in clsdict: 1457 raise TypeError('_file is required') 1458 if '_name' not in clsdict: 1459 raise TypeError('_name is required') 1460 if '_value' not in clsdict: 1461 raise TypeError('_value is required') 1462 name_spec = clsdict.pop('_name') 1463 if not isinstance(name_spec, (tuple, list)): 1464 name_spec = (name_spec, ) 1465 value_spec = clsdict.pop('_value') 1466 file = clsdict.pop('_file') 1467 with open(file) as f: 1468 json_data = json.load(f) 1469 for data in json_data: 1470 values = [] 1471 name = data[name_spec[0]] 1472 for piece in name_spec[1:]: 1473 name = name[piece] 1474 for order, (value_path, func) in sorted(value_spec.items()): 1475 if not isinstance(value_path, (list, tuple)): 1476 value_path = (value_path, ) 1477 value = data[value_path[0]] 1478 for piece in value_path[1:]: 1479 value = value[piece] 1480 if func is not None: 1481 value = func(value) 1482 values.append(value) 1483 values = tuple(values) 1484 members.append( 1485 (name, identity(*values)) 1486 ) 1487 # get the real EnumDict 1488 enum_dict = super(JSONEnumMeta, metacls).__prepare__(cls, bases, init, start, settings) 1489 # transfer the original dict content, _items first 1490 items = list(clsdict.items()) 1491 items.sort(key=lambda p: (0 if p[0][0] == '_' else 1, p)) 1492 for name, value in items: 1493 enum_dict[name] = value 1494 # add the members 1495 for name, value in members: 1496 enum_dict[name] = value 1497 return super(JSONEnumMeta, metacls).__new__(metacls, cls, bases, enum_dict, init, start, settings) 1498 1499 # for use with both Python 2/3 1500 JSONEnum = JSONEnumMeta('JsonEnum', (Enum, ), {}) 1501 1502 test_file = os.path.join(tempdir, 'test_json.json') 1503 with open(test_file, 'w') as f: 1504 f.write( 1505 '[{"name":"Afghanistan","alpha-2":"AF","country-code":"004","notes":{"description":"pretty"}},' 1506 '{"name":"Åland Islands","alpha-2":"AX","country-code":"248","notes":{"description":"serene"}},' 1507 '{"name":"Albania","alpha-2":"AL","country-code":"008","notes":{"description":"exciting"}},' 1508 '{"name":"Algeria","alpha-2":"DZ","country-code":"012","notes":{"description":"scarce"}}]') 1509 1510 class Country(JSONEnum): 1511 _init_ = 'abbr code country_name description' 1512 _file = test_file 1513 _name = 'alpha-2' 1514 _value = { 1515 1: ('alpha-2', None), 1516 2: ('country-code', lambda c: int(c)), 1517 3: ('name', None), 1518 4: (('notes','description'), lambda s: s.title()), 1519 } 1520 1521 self.assertEqual([Country.AF, Country.AX, Country.AL, Country.DZ], list(Country)) 1522 self.assertEqual(Country.AF.abbr, 'AF') 1523 self.assertEqual(Country.AX.code, 248) 1524 self.assertEqual(Country.AL.country_name, 'Albania') 1525 self.assertEqual(Country.DZ.description, 'Scarce') 1526 1527 1528 def test_subclasses_with_getnewargs(self): 1529 class NamedInt(int): 1530 __qualname__ = 'NamedInt' # needed for pickle protocol 4 1531 def __new__(cls, *args): 1532 _args = args 1533 if len(args) < 1: 1534 raise TypeError("name and value must be specified") 1535 name, args = args[0], args[1:] 1536 self = int.__new__(cls, *args) 1537 self._intname = name 1538 self._args = _args 1539 return self 1540 def __getnewargs__(self): 1541 return self._args 1542 @property 1543 def __name__(self): 1544 return self._intname 1545 def __repr__(self): 1546 # repr() is updated to include the name and type info 1547 return "%s(%r, %s)" % (type(self).__name__, 1548 self.__name__, 1549 int.__repr__(self)) 1550 def __str__(self): 1551 # str() is unchanged, even if it relies on the repr() fallback 1552 base = int 1553 base_str = base.__str__ 1554 if base_str.__objclass__ is object: 1555 return base.__repr__(self) 1556 return base_str(self) 1557 # for simplicity, we only define one operator that 1558 # propagates expressions 1559 def __add__(self, other): 1560 temp = int(self) + int( other) 1561 if isinstance(self, NamedInt) and isinstance(other, NamedInt): 1562 return NamedInt( 1563 '(%s + %s)' % (self.__name__, other.__name__), 1564 temp ) 1565 else: 1566 return temp 1567 1568 class NEI(NamedInt, Enum): 1569 __qualname__ = 'NEI' # needed for pickle protocol 4 1570 x = ('the-x', 1) 1571 y = ('the-y', 2) 1572 1573 self.assertTrue(NEI.__new__ is Enum.__new__) 1574 self.assertEqual(repr(NEI.x + NEI.y), "NamedInt('(the-x + the-y)', 3)") 1575 globals()['NamedInt'] = NamedInt 1576 globals()['NEI'] = NEI 1577 NI5 = NamedInt('test', 5) 1578 self.assertEqual(NI5, 5) 1579 test_pickle_dump_load(self.assertTrue, NI5, 5) 1580 self.assertEqual(NEI.y.value, 2) 1581 test_pickle_dump_load(self.assertTrue, NEI.y) 1582 1583 def test_subclasses_with_reduce(self): 1584 class NamedInt(int): 1585 __qualname__ = 'NamedInt' # needed for pickle protocol 4 1586 def __new__(cls, *args): 1587 _args = args 1588 if len(args) < 1: 1589 raise TypeError("name and value must be specified") 1590 name, args = args[0], args[1:] 1591 self = int.__new__(cls, *args) 1592 self._intname = name 1593 self._args = _args 1594 return self 1595 def __reduce__(self): 1596 return self.__class__, self._args 1597 @property 1598 def __name__(self): 1599 return self._intname 1600 def __repr__(self): 1601 # repr() is updated to include the name and type info 1602 return "%s(%r, %s)" % (type(self).__name__, 1603 self.__name__, 1604 int.__repr__(self)) 1605 def __str__(self): 1606 # str() is unchanged, even if it relies on the repr() fallback 1607 base = int 1608 base_str = base.__str__ 1609 if base_str.__objclass__ is object: 1610 return base.__repr__(self) 1611 return base_str(self) 1612 # for simplicity, we only define one operator that 1613 # propagates expressions 1614 def __add__(self, other): 1615 temp = int(self) + int( other) 1616 if isinstance(self, NamedInt) and isinstance(other, NamedInt): 1617 return NamedInt( 1618 '(%s + %s)' % (self.__name__, other.__name__), 1619 temp ) 1620 else: 1621 return temp 1622 1623 class NEI(NamedInt, Enum): 1624 __qualname__ = 'NEI' # needed for pickle protocol 4 1625 x = ('the-x', 1) 1626 y = ('the-y', 2) 1627 1628 1629 self.assertTrue(NEI.__new__ is Enum.__new__) 1630 self.assertEqual(repr(NEI.x + NEI.y), "NamedInt('(the-x + the-y)', 3)") 1631 globals()['NamedInt'] = NamedInt 1632 globals()['NEI'] = NEI 1633 NI5 = NamedInt('test', 5) 1634 self.assertEqual(NI5, 5) 1635 test_pickle_dump_load(self.assertEqual, NI5, 5) 1636 self.assertEqual(NEI.y.value, 2) 1637 test_pickle_dump_load(self.assertTrue, NEI.y) 1638 1639 def test_subclasses_with_reduce_ex(self): 1640 class NamedInt(int): 1641 __qualname__ = 'NamedInt' # needed for pickle protocol 4 1642 def __new__(cls, *args): 1643 _args = args 1644 if len(args) < 1: 1645 raise TypeError("name and value must be specified") 1646 name, args = args[0], args[1:] 1647 self = int.__new__(cls, *args) 1648 self._intname = name 1649 self._args = _args 1650 return self 1651 def __reduce_ex__(self, proto): 1652 return self.__class__, self._args 1653 @property 1654 def __name__(self): 1655 return self._intname 1656 def __repr__(self): 1657 # repr() is updated to include the name and type info 1658 return "%s(%r, %s)" % (type(self).__name__, 1659 self.__name__, 1660 int.__repr__(self)) 1661 def __str__(self): 1662 # str() is unchanged, even if it relies on the repr() fallback 1663 base = int 1664 base_str = base.__str__ 1665 if base_str.__objclass__ is object: 1666 return base.__repr__(self) 1667 return base_str(self) 1668 # for simplicity, we only define one operator that 1669 # propagates expressions 1670 def __add__(self, other): 1671 temp = int(self) + int( other) 1672 if isinstance(self, NamedInt) and isinstance(other, NamedInt): 1673 return NamedInt( 1674 '(%s + %s)' % (self.__name__, other.__name__), 1675 temp ) 1676 else: 1677 return temp 1678 1679 class NEI(NamedInt, Enum): 1680 __qualname__ = 'NEI' # needed for pickle protocol 4 1681 x = ('the-x', 1) 1682 y = ('the-y', 2) 1683 1684 1685 self.assertTrue(NEI.__new__ is Enum.__new__) 1686 self.assertEqual(repr(NEI.x + NEI.y), "NamedInt('(the-x + the-y)', 3)") 1687 globals()['NamedInt'] = NamedInt 1688 globals()['NEI'] = NEI 1689 NI5 = NamedInt('test', 5) 1690 self.assertEqual(NI5, 5) 1691 test_pickle_dump_load(self.assertEqual, NI5, 5) 1692 self.assertEqual(NEI.y.value, 2) 1693 test_pickle_dump_load(self.assertTrue, NEI.y) 1694 1695 def test_subclasses_without_direct_pickle_support(self): 1696 class NamedInt(int): 1697 __qualname__ = 'NamedInt' 1698 def __new__(cls, *args): 1699 _args = args 1700 name, args = args[0], args[1:] 1701 if len(args) == 0: 1702 raise TypeError("name and value must be specified") 1703 self = int.__new__(cls, *args) 1704 self._intname = name 1705 self._args = _args 1706 return self 1707 @property 1708 def __name__(self): 1709 return self._intname 1710 def __repr__(self): 1711 # repr() is updated to include the name and type info 1712 return "%s(%r, %s)" % (type(self).__name__, 1713 self.__name__, 1714 int.__repr__(self)) 1715 def __str__(self): 1716 # str() is unchanged, even if it relies on the repr() fallback 1717 base = int 1718 base_str = base.__str__ 1719 if base_str.__objclass__ is object: 1720 return base.__repr__(self) 1721 return base_str(self) 1722 # for simplicity, we only define one operator that 1723 # propagates expressions 1724 def __add__(self, other): 1725 temp = int(self) + int( other) 1726 if isinstance(self, NamedInt) and isinstance(other, NamedInt): 1727 return NamedInt( 1728 '(%s + %s)' % (self.__name__, other.__name__), 1729 temp ) 1730 else: 1731 return temp 1732 1733 class NEI(NamedInt, Enum): 1734 __qualname__ = 'NEI' 1735 x = ('the-x', 1) 1736 y = ('the-y', 2) 1737 1738 self.assertTrue(NEI.__new__ is Enum.__new__) 1739 self.assertEqual(repr(NEI.x + NEI.y), "NamedInt('(the-x + the-y)', 3)") 1740 globals()['NamedInt'] = NamedInt 1741 globals()['NEI'] = NEI 1742 NI5 = NamedInt('test', 5) 1743 self.assertEqual(NI5, 5) 1744 self.assertEqual(NEI.y.value, 2) 1745 test_pickle_exception(self.assertRaises, TypeError, NEI.x) 1746 test_pickle_exception(self.assertRaises, PicklingError, NEI) 1747 1748 def test_subclasses_without_direct_pickle_support_using_name(self): 1749 class NamedInt(int): 1750 __qualname__ = 'NamedInt' 1751 def __new__(cls, *args): 1752 _args = args 1753 name, args = args[0], args[1:] 1754 if len(args) == 0: 1755 raise TypeError("name and value must be specified") 1756 self = int.__new__(cls, *args) 1757 self._intname = name 1758 self._args = _args 1759 return self 1760 @property 1761 def __name__(self): 1762 return self._intname 1763 def __repr__(self): 1764 # repr() is updated to include the name and type info 1765 return "%s(%r, %s)" % (type(self).__name__, 1766 self.__name__, 1767 int.__repr__(self)) 1768 def __str__(self): 1769 # str() is unchanged, even if it relies on the repr() fallback 1770 base = int 1771 base_str = base.__str__ 1772 if base_str.__objclass__ is object: 1773 return base.__repr__(self) 1774 return base_str(self) 1775 # for simplicity, we only define one operator that 1776 # propagates expressions 1777 def __add__(self, other): 1778 temp = int(self) + int( other) 1779 if isinstance(self, NamedInt) and isinstance(other, NamedInt): 1780 return NamedInt( 1781 '(%s + %s)' % (self.__name__, other.__name__), 1782 temp ) 1783 else: 1784 return temp 1785 1786 class NEI(NamedInt, Enum): 1787 __qualname__ = 'NEI' 1788 x = ('the-x', 1) 1789 y = ('the-y', 2) 1790 def __reduce_ex__(self, proto): 1791 return getattr, (self.__class__, self._name_) 1792 1793 self.assertTrue(NEI.__new__ is Enum.__new__) 1794 self.assertEqual(repr(NEI.x + NEI.y), "NamedInt('(the-x + the-y)', 3)") 1795 globals()['NamedInt'] = NamedInt 1796 globals()['NEI'] = NEI 1797 NI5 = NamedInt('test', 5) 1798 self.assertEqual(NI5, 5) 1799 self.assertEqual(NEI.y.value, 2) 1800 test_pickle_dump_load(self.assertTrue, NEI.y) 1801 test_pickle_dump_load(self.assertTrue, NEI) 1802 1803 def test_tuple_subclass(self): 1804 class SomeTuple(tuple, Enum): 1805 __qualname__ = 'SomeTuple' 1806 first = (1, 'for the money') 1807 second = (2, 'for the show') 1808 third = (3, 'for the music') 1809 self.assertTrue(type(SomeTuple.first) is SomeTuple) 1810 self.assertTrue(isinstance(SomeTuple.second, tuple)) 1811 self.assertEqual(SomeTuple.third, (3, 'for the music')) 1812 globals()['SomeTuple'] = SomeTuple 1813 test_pickle_dump_load(self.assertTrue, SomeTuple.first) 1814 1815 def test_duplicate_values_give_unique_enum_items(self): 1816 class NumericEnum(AutoNumberEnum): 1817 __order__ = 'enum_m enum_d enum_y' 1818 enum_m = () 1819 enum_d = () 1820 enum_y = () 1821 def __int__(self): 1822 return int(self._value_) 1823 self.assertEqual(int(NumericEnum.enum_d), 2) 1824 self.assertEqual(NumericEnum.enum_y.value, 3) 1825 self.assertTrue(NumericEnum(1) is NumericEnum.enum_m) 1826 self.assertEqual( 1827 list(NumericEnum), 1828 [NumericEnum.enum_m, NumericEnum.enum_d, NumericEnum.enum_y], 1829 ) 1830 1831 def test_inherited_new_from_enhanced_enum(self): 1832 class AutoNumber2(Enum): 1833 def __new__(cls): 1834 value = len(cls.__members__) + 1 1835 obj = object.__new__(cls) 1836 obj._value_ = value 1837 return obj 1838 def __int__(self): 1839 return int(self._value_) 1840 class Color(AutoNumber2): 1841 __order__ = 'red green blue' 1842 red = () 1843 green = () 1844 blue = () 1845 self.assertEqual(len(Color), 3, "wrong number of elements: %d (should be %d)" % (len(Color), 3)) 1846 self.assertEqual(list(Color), [Color.red, Color.green, Color.blue]) 1847 if pyver >= 3.0: 1848 self.assertEqual(list(map(int, Color)), [1, 2, 3]) 1849 1850 def test_inherited_new_from_mixed_enum(self): 1851 class AutoNumber3(IntEnum): 1852 def __new__(cls): 1853 value = len(cls.__members__) + 11 1854 obj = int.__new__(cls, value) 1855 obj._value_ = value 1856 return obj 1857 class Color(AutoNumber3): 1858 __order__ = 'red green blue' 1859 red = () 1860 green = () 1861 blue = () 1862 self.assertEqual(len(Color), 3, "wrong number of elements: %d (should be %d)" % (len(Color), 3)) 1863 Color.red 1864 Color.green 1865 Color.blue 1866 self.assertEqual(Color.blue, 13) 1867 1868 def test_equality(self): 1869 class AlwaysEqual: 1870 def __eq__(self, other): 1871 return True 1872 class OrdinaryEnum(Enum): 1873 a = 1 1874 self.assertEqual(AlwaysEqual(), OrdinaryEnum.a) 1875 self.assertEqual(OrdinaryEnum.a, AlwaysEqual()) 1876 1877 def test_ordered_mixin(self): 1878 class Grade(OrderedEnum): 1879 __order__ = 'A B C D F' 1880 A = 5 1881 B = 4 1882 C = 3 1883 D = 2 1884 F = 1 1885 self.assertEqual(list(Grade), [Grade.A, Grade.B, Grade.C, Grade.D, Grade.F]) 1886 self.assertTrue(Grade.A > Grade.B) 1887 self.assertTrue(Grade.F <= Grade.C) 1888 self.assertTrue(Grade.D < Grade.A) 1889 self.assertTrue(Grade.B >= Grade.B) 1890 1891 def test_missing_deprecated(self): 1892 class Label(Enum): 1893 AnyApple = 0 1894 RedApple = 1 1895 GreenApple = 2 1896 @classmethod 1897 def _missing_(cls, name): 1898 return cls.AnyApple 1899 1900 self.assertEqual(Label.AnyApple, Label(4)) 1901 with self.assertRaises(AttributeError): 1902 Label.redapple 1903 with self.assertRaises(KeyError): 1904 Label['redapple'] 1905 1906 def test_missing(self): 1907 class Label(Enum): 1908 AnyApple = 0 1909 RedApple = 1 1910 GreenApple = 2 1911 @classmethod 1912 def _missing_value_(cls, value): 1913 return cls.AnyApple 1914 1915 self.assertEqual(Label.AnyApple, Label(4)) 1916 with self.assertRaises(AttributeError): 1917 Label.redapple 1918 with self.assertRaises(KeyError): 1919 Label['redapple'] 1920 1921 def test_missing_name(self): 1922 class Label(Enum): 1923 RedApple = 1 1924 GreenApple = 2 1925 @classmethod 1926 def _missing_name_(cls, name): 1927 for member in cls: 1928 if member.name.lower() == name.lower(): 1929 return member 1930 1931 Label['redapple'] 1932 with self.assertRaises(AttributeError): 1933 Label.redapple 1934 with self.assertRaises(ValueError): 1935 Label('redapple') 1936 1937 def test_missing_value_bad_input(self): 1938 class Label(Enum): 1939 AnyApple = 0 1940 RedApple = 1 1941 GreenApple = 2 1942 @classmethod 1943 def _missing_value_(cls, value): 1944 return cls.AnyApple 1945 1946 self.assertEqual(Label.AnyApple, Label(4)) 1947 with self.assertRaises(KeyError): 1948 Label[True] 1949 1950 def test_missing_name_bad_return(self): 1951 class Label(Enum): 1952 RedApple = 1 1953 GreenApple = 2 1954 @classmethod 1955 def _missing_name_(cls, name): 1956 return None 1957 1958 with self.assertRaises(AttributeError): 1959 Label.redapple 1960 with self.assertRaises(ValueError): 1961 Label('redapple') 1962 with self.assertRaises(KeyError): 1963 Label['redapple'] 1964 1965 def test_extending2(self): 1966 def bad_extension(): 1967 class Shade(Enum): 1968 def shade(self): 1969 print(self.name) 1970 class Color(Shade): 1971 red = 1 1972 green = 2 1973 blue = 3 1974 class MoreColor(Color): 1975 cyan = 4 1976 magenta = 5 1977 yellow = 6 1978 self.assertRaises(TypeError, bad_extension) 1979 1980 def test_extending3(self): 1981 class Shade(Enum): 1982 def shade(self): 1983 return self.name 1984 class Color(Shade): 1985 def hex(self): 1986 return '%s hexlified!' % self.value 1987 class MoreColor(Color): 1988 cyan = 4 1989 magenta = 5 1990 yellow = 6 1991 self.assertEqual(MoreColor.magenta.hex(), '5 hexlified!') 1992 1993 def test_extending4(self): 1994 class hohum(object): 1995 def cyan(self): 1996 "cyanize a color" 1997 return self.value * 7 1998 class Color(hohum, Enum): 1999 red = 1 2000 green = 2 2001 blue = 3 2002 cyan = 4 2003 self.assertEqual(list(Color), [Color.red, Color.green, Color.blue, Color.cyan]) 2004 self.assertEqual(Color.red.cyan(), 7) 2005 self.assertEqual(Color.green.cyan(), 14) 2006 self.assertEqual(Color.blue.cyan(), 21) 2007 self.assertEqual(Color.cyan.cyan(), 28) 2008 2009 2010 def test_extending5(self): 2011 class Color(Enum): 2012 _order_ = 'red green blue value' 2013 red = 1 2014 green = 2 2015 blue = 3 2016 value = 4 2017 self.assertEqual(list(Color), [Color.red, Color.green, Color.blue, Color.value]) 2018 self.assertEqual(Color.value.name, 'value') 2019 self.assertEqual(Color.value.value, 4) 2020 self.assertTrue(Color.value in Color) 2021 self.assertEqual(Color(4), Color.value) 2022 self.assertEqual(Color['value'], Color.value) 2023 self.assertEqual(Color.red.value, 1) 2024 2025 if StdlibEnum is not None: 2026 2027 def test_extend_enum_stdlib(self): 2028 class Color(StdlibEnum): 2029 red = 1 2030 green = 2 2031 blue = 3 2032 self.assertEqual(getattr(Color.red, '_values_', None), None) 2033 extend_enum(Color, 'brown', 4) 2034 self.assertEqual(Color.brown.name, 'brown') 2035 self.assertEqual(Color.brown.value, 4) 2036 self.assertTrue(Color.brown in Color) 2037 self.assertEqual(Color(4), Color.brown) 2038 self.assertEqual(Color['brown'], Color.brown) 2039 self.assertEqual(len(Color), 4) 2040 2041 def test_extend_enum_plain(self): 2042 class Color(UniqueEnum): 2043 red = 1 2044 green = 2 2045 blue = 3 2046 extend_enum(Color, 'brown', 4) 2047 self.assertEqual(Color.brown.name, 'brown') 2048 self.assertEqual(Color.brown.value, 4) 2049 self.assertTrue(Color.brown in Color) 2050 self.assertEqual(Color(4), Color.brown) 2051 self.assertEqual(Color['brown'], Color.brown) 2052 self.assertEqual(len(Color), 4) 2053 2054 def test_extend_enum_alias(self): 2055 class Color(Enum): 2056 red = 1 2057 green = 2 2058 blue = 3 2059 extend_enum(Color, 'rojo', 1) 2060 self.assertEqual(Color.rojo.name, 'red') 2061 self.assertEqual(Color.rojo.value, 1) 2062 self.assertTrue(Color.rojo in Color) 2063 self.assertEqual(Color(1), Color.rojo) 2064 self.assertEqual(Color['rojo'], Color.red) 2065 self.assertEqual(len(Color), 3) 2066 2067 def test_extend_enum_no_alias(self): 2068 class Color(UniqueEnum): 2069 red = 1 2070 green = 2 2071 blue = 3 2072 self.assertRaisesRegex(ValueError, 'rojo is a duplicate of red', extend_enum, Color, 'rojo', 1) 2073 self.assertEqual(Color.red.name, 'red') 2074 self.assertEqual(Color.red.value, 1) 2075 self.assertTrue(Color.red in Color) 2076 self.assertEqual(Color(1), Color.red) 2077 self.assertEqual(Color['red'], Color.red) 2078 self.assertEqual(Color.green.name, 'green') 2079 self.assertEqual(Color.green.value, 2) 2080 self.assertTrue(Color.green in Color) 2081 self.assertEqual(Color(2), Color.green) 2082 self.assertEqual(Color['blue'], Color.blue) 2083 self.assertEqual(Color.blue.name, 'blue') 2084 self.assertEqual(Color.blue.value, 3) 2085 self.assertTrue(Color.blue in Color) 2086 self.assertEqual(Color(3), Color.blue) 2087 self.assertEqual(len(Color), 3) 2088 2089 def test_extend_enum_shadow(self): 2090 class Color(UniqueEnum): 2091 red = 1 2092 green = 2 2093 blue = 3 2094 extend_enum(Color, 'value', 4) 2095 self.assertEqual(Color.value.name, 'value') 2096 self.assertEqual(Color.value.value, 4) 2097 self.assertTrue(Color.value in Color) 2098 self.assertEqual(Color(4), Color.value) 2099 self.assertEqual(Color['value'], Color.value) 2100 self.assertEqual(len(Color), 4) 2101 self.assertEqual(Color.red.value, 1) 2102 2103 def test_extend_enum_shadow_base(self): 2104 class hohum(object): 2105 def cyan(self): 2106 "cyanize a color" 2107 return self.value 2108 class Color(hohum, UniqueEnum): 2109 red = 1 2110 green = 2 2111 blue = 3 2112 with self.assertRaises(TypeError): 2113 extend_enum(Color, 'cyan', 4) 2114 self.assertEqual(len(Color), 3) 2115 self.assertEqual(list(Color), [Color.red, Color.green, Color.blue]) 2116 2117 def test_extend_enum_multivalue(self): 2118 class Color(MultiValueEnum): 2119 red = 1, 4, 7 2120 green = 2, 5, 8 2121 blue = 3, 6, 9 2122 extend_enum(Color, 'brown', 10, 20) 2123 self.assertEqual(Color.brown.name, 'brown') 2124 self.assertEqual(Color.brown.value, 10) 2125 self.assertTrue(Color.brown in Color) 2126 self.assertEqual(Color(10), Color.brown) 2127 self.assertEqual(Color(20), Color.brown) 2128 self.assertEqual(Color['brown'], Color.brown) 2129 self.assertEqual(len(Color), 4) 2130 2131 def test_extend_enum_multivalue_alias(self): 2132 class Color(MultiValueEnum): 2133 red = 1, 4, 7 2134 green = 2, 5, 8 2135 blue = 3, 6, 9 2136 self.assertRaisesRegex(ValueError, 'rojo is a duplicate of red', extend_enum, Color, 'rojo', 7) 2137 self.assertEqual(Color.red.name, 'red') 2138 self.assertEqual(Color.red.value, 1) 2139 self.assertTrue(Color.red in Color) 2140 self.assertEqual(Color(1), Color.red) 2141 self.assertEqual(Color(4), Color.red) 2142 self.assertEqual(Color(7), Color.red) 2143 self.assertEqual(Color['red'], Color.red) 2144 self.assertEqual(Color.green.name, 'green') 2145 self.assertEqual(Color.green.value, 2) 2146 self.assertTrue(Color.green in Color) 2147 self.assertEqual(Color(2), Color.green) 2148 self.assertEqual(Color(5), Color.green) 2149 self.assertEqual(Color(8), Color.green) 2150 self.assertEqual(Color['blue'], Color.blue) 2151 self.assertEqual(Color.blue.name, 'blue') 2152 self.assertEqual(Color.blue.value, 3) 2153 self.assertTrue(Color.blue in Color) 2154 self.assertEqual(Color(3), Color.blue) 2155 self.assertEqual(Color(6), Color.blue) 2156 self.assertEqual(Color(9), Color.blue) 2157 self.assertEqual(len(Color), 3) 2158 2159 def test_extend_intenum(self): 2160 class Index(IntEnum): 2161 DeviceType = 0x1000 2162 ErrorRegister = 0x1001 2163 2164 for name, value in ( 2165 ('ControlWord', 0x6040), 2166 ('StatusWord', 0x6041), 2167 ('OperationMode', 0x6060), 2168 ): 2169 extend_enum(Index, name, value) 2170 2171 self.assertEqual(len(Index), 5) 2172 self.assertEqual(list(Index), [Index.DeviceType, Index.ErrorRegister, Index.ControlWord, Index.StatusWord, Index.OperationMode]) 2173 self.assertEqual(Index.DeviceType.value, 0x1000) 2174 self.assertEqual(Index.StatusWord.value, 0x6041) 2175 2176 def test_extend_multi_init(self): 2177 try: 2178 from http import HTTPStatus 2179 length = len(HTTPStatus) 2180 except ImportError: 2181 class HTTPStatus(IntEnum): 2182 def __new__(cls, value, phrase, description): 2183 obj = int.__new__(cls, value) 2184 obj._value_ = value 2185 2186 obj.phrase = phrase 2187 obj.description = description 2188 return obj 2189 CONTINUE = 100, 'Continue', 'Request received, please continue' 2190 SWITCHING_PROTOCOLS = 101, 'Switching Protocols', 'Switching to new protocol; obey Upgrade header' 2191 PROCESSING = 102, 'Processing', '' 2192 length = 3 2193 extend_enum(HTTPStatus, 'BAD_SPAM', 513, 'Too greasy', 'for a train') 2194 extend_enum(HTTPStatus, 'BAD_EGGS', 514, 'Too green', '') 2195 self.assertEqual(len(HTTPStatus), length+2) 2196 self.assertEqual( 2197 list(HTTPStatus)[-2:], 2198 [HTTPStatus.BAD_SPAM, HTTPStatus.BAD_EGGS], 2199 ) 2200 self.assertEqual(HTTPStatus.BAD_SPAM.value, 513) 2201 self.assertEqual(HTTPStatus.BAD_SPAM.name, 'BAD_SPAM') 2202 self.assertEqual(HTTPStatus.BAD_SPAM.phrase, 'Too greasy') 2203 self.assertEqual(HTTPStatus.BAD_SPAM.description, 'for a train') 2204 self.assertEqual(HTTPStatus.BAD_EGGS.value, 514) 2205 self.assertEqual(HTTPStatus.BAD_EGGS.name, 'BAD_EGGS') 2206 self.assertEqual(HTTPStatus.BAD_EGGS.phrase, 'Too green') 2207 self.assertEqual(HTTPStatus.BAD_EGGS.description, '') 2208 2209 # informational 2210 CONTINUE = 100, 'Continue', 'Request received, please continue' 2211 SWITCHING_PROTOCOLS = (101, 'Switching Protocols', 2212 'Switching to new protocol; obey Upgrade header') 2213 PROCESSING = 102, 'Processing' 2214 2215 def test_no_duplicates(self): 2216 def bad_duplicates(): 2217 class Color1(UniqueEnum): 2218 red = 1 2219 green = 2 2220 blue = 3 2221 class Color2(UniqueEnum): 2222 red = 1 2223 green = 2 2224 blue = 3 2225 grene = 2 2226 self.assertRaises(ValueError, bad_duplicates) 2227 2228 def test_no_duplicates_kinda(self): 2229 class Silly(UniqueEnum): 2230 one = 1 2231 two = 'dos' 2232 name = 3 2233 class Sillier(IntEnum, UniqueEnum): 2234 single = 1 2235 name = 2 2236 triple = 3 2237 value = 4 2238 2239 def test_init(self): 2240 class Planet(Enum): 2241 MERCURY = (3.303e+23, 2.4397e6) 2242 VENUS = (4.869e+24, 6.0518e6) 2243 EARTH = (5.976e+24, 6.37814e6) 2244 MARS = (6.421e+23, 3.3972e6) 2245 JUPITER = (1.9e+27, 7.1492e7) 2246 SATURN = (5.688e+26, 6.0268e7) 2247 URANUS = (8.686e+25, 2.5559e7) 2248 NEPTUNE = (1.024e+26, 2.4746e7) 2249 def __init__(self, mass, radius): 2250 self.mass = mass # in kilograms 2251 self.radius = radius # in meters 2252 @property 2253 def surface_gravity(self): 2254 # universal gravitational constant (m3 kg-1 s-2) 2255 G = 6.67300E-11 2256 return G * self.mass / (self.radius * self.radius) 2257 self.assertEqual(round(Planet.EARTH.surface_gravity, 2), 9.80) 2258 self.assertEqual(Planet.EARTH.value, (5.976e+24, 6.37814e6)) 2259 2260 @unittest.skip 2261 def test_init_and_autonumber(self): 2262 pass 2263 2264 @unittest.skip 2265 def test_init_and_autonumber_and_value(self): 2266 pass 2267 2268 def test_no_init_and_autonumber(self): 2269 class DocEnum(str, Enum): 2270 """ 2271 compares equal to all cased versions of its name 2272 accepts a docstring for each member 2273 """ 2274 _settings_ = AutoNumber 2275 def __init__(self, value, doc=None): 2276 # first, fix _value_ 2277 self._value_ = self._name_.lower() 2278 self.__doc__ = doc 2279 def __eq__(self, other): 2280 if isinstance(other, basestring): 2281 return self._value_ == other.lower() 2282 elif isinstance(other, self.__class__): 2283 return self is other 2284 else: 2285 return False 2286 def __ne__(self, other): 2287 return not self == other 2288 REQUIRED = "required value" 2289 OPTION = "single value per name" 2290 MULTI = "multiple values per name (list form, no whitespace)" 2291 FLAG = "boolean/trivalent value per name" 2292 KEYWORD = 'unknown options' 2293 self.assertEqual(DocEnum.REQUIRED, 'required') 2294 self.assertEqual(DocEnum.REQUIRED, 'Required') 2295 self.assertEqual(DocEnum.REQUIRED, 'REQUIRED') 2296 2297 def test_nonhash_value(self): 2298 class AutoNumberInAList(Enum): 2299 def __new__(cls): 2300 value = [len(cls.__members__) + 1] 2301 obj = object.__new__(cls) 2302 obj._value_ = value 2303 return obj 2304 class ColorInAList(AutoNumberInAList): 2305 __order__ = 'red green blue' 2306 red = () 2307 green = () 2308 blue = () 2309 self.assertEqual(list(ColorInAList), [ColorInAList.red, ColorInAList.green, ColorInAList.blue]) 2310 self.assertEqual(ColorInAList.red.value, [1]) 2311 self.assertEqual(ColorInAList([1]), ColorInAList.red) 2312 2313 def test_conflicting_types_resolved_in_new(self): 2314 class LabelledIntEnum(int, Enum): 2315 def __new__(cls, *args): 2316 value, label = args 2317 obj = int.__new__(cls, value) 2318 obj.label = label 2319 obj._value_ = value 2320 return obj 2321 2322 class LabelledList(LabelledIntEnum): 2323 unprocessed = (1, "Unprocessed") 2324 payment_complete = (2, "Payment Complete") 2325 2326 self.assertEqual(LabelledList.unprocessed, 1) 2327 self.assertEqual(LabelledList(1), LabelledList.unprocessed) 2328 self.assertEqual(list(LabelledList), [LabelledList.unprocessed, LabelledList.payment_complete]) 2329 2330 def test_auto_number(self): 2331 class Color(Enum): 2332 _order_ = 'red blue green' 2333 red = auto() 2334 blue = auto() 2335 green = auto() 2336 2337 self.assertEqual(list(Color), [Color.red, Color.blue, Color.green]) 2338 self.assertEqual(Color.red.value, 1) 2339 self.assertEqual(Color.blue.value, 2) 2340 self.assertEqual(Color.green.value, 3) 2341 2342 def test_auto_name(self): 2343 class Color(Enum): 2344 _order_ = 'red blue green' 2345 def _generate_next_value_(name, start, count, last): 2346 return name 2347 red = auto() 2348 blue = auto() 2349 green = auto() 2350 2351 self.assertEqual(list(Color), [Color.red, Color.blue, Color.green]) 2352 self.assertEqual(Color.red.value, 'red') 2353 self.assertEqual(Color.blue.value, 'blue') 2354 self.assertEqual(Color.green.value, 'green') 2355 2356 def test_auto_name_inherit(self): 2357 class AutoNameEnum(Enum): 2358 def _generate_next_value_(name, start, count, last): 2359 return name 2360 class Color(AutoNameEnum): 2361 _order_ = 'red blue green' 2362 red = auto() 2363 blue = auto() 2364 green = auto() 2365 2366 self.assertEqual(list(Color), [Color.red, Color.blue, Color.green]) 2367 self.assertEqual(Color.red.value, 'red') 2368 self.assertEqual(Color.blue.value, 'blue') 2369 self.assertEqual(Color.green.value, 'green') 2370 2371 def test_auto_garbage(self): 2372 class Color(Enum): 2373 _order_ = 'red blue' 2374 red = 'red' 2375 blue = auto() 2376 self.assertEqual(Color.blue.value, 1) 2377 2378 def test_auto_garbage_corrected(self): 2379 class Color(Enum): 2380 _order_ = 'red blue green' 2381 red = 'red' 2382 blue = 2 2383 green = auto() 2384 2385 self.assertEqual(list(Color), [Color.red, Color.blue, Color.green]) 2386 self.assertEqual(Color.red.value, 'red') 2387 self.assertEqual(Color.blue.value, 2) 2388 self.assertEqual(Color.green.value, 3) 2389 2390 def test_duplicate_auto(self): 2391 class Dupes(Enum): 2392 _order_ = 'first second third' 2393 first = primero = auto() 2394 second = auto() 2395 third = auto() 2396 self.assertEqual([Dupes.first, Dupes.second, Dupes.third], list(Dupes)) 2397 2398 def test_auto_value_with_auto(self): 2399 2400 class SelectionEnum(Enum): 2401 _init_ = 'db user' 2402 def __new__(cls, *args, **kwds): 2403 count = len(cls.__members__) 2404 obj = object.__new__(cls) 2405 obj._count = count 2406 obj._value_ = args 2407 obj.db, obj.user = args 2408 return obj 2409 @staticmethod 2410 def _generate_next_value_(name, start, count, values, *args, **kwds): 2411 return (name, ) + args 2412 2413 class Test(SelectionEnum): 2414 _order_ = 'this that' 2415 this = auto('these') 2416 that = auto('those') 2417 2418 self.assertEqual(list(Test), [Test.this, Test.that]) 2419 self.assertEqual(Test.this.name, 'this') 2420 self.assertEqual(Test.this.value, ('this', 'these')) 2421 self.assertEqual(Test.this.db, 'this') 2422 self.assertEqual(Test.this.user, 'these') 2423 self.assertEqual(Test.that.name, 'that') 2424 self.assertEqual(Test.that.value, ('that', 'those')) 2425 self.assertEqual(Test.that.db, 'that') 2426 self.assertEqual(Test.that.user, 'those') 2427 2428 def test_auto_value_with_autovalue(self): 2429 2430 class SelectionEnum(Enum): 2431 _init_ = 'db user' 2432 _settings_ = AutoValue 2433 def __new__(cls, *args, **kwds): 2434 count = len(cls.__members__) 2435 obj = object.__new__(cls) 2436 obj._count = count 2437 obj._value_ = args 2438 return obj 2439 @staticmethod 2440 def _generate_next_value_(name, start, count, values, *args, **kwds): 2441 return (name, ) + args 2442 2443 class Test(SelectionEnum): 2444 _order_ = 'this that' 2445 this = 'these' 2446 that = 'those' 2447 2448 self.assertEqual(list(Test), [Test.this, Test.that]) 2449 self.assertEqual(Test.this.name, 'this') 2450 self.assertEqual(Test.this.value, ('this', 'these')) 2451 self.assertEqual(Test.this.db, 'this') 2452 self.assertEqual(Test.this.user, 'these') 2453 self.assertEqual(Test.that.name, 'that') 2454 self.assertEqual(Test.that.value, ('that', 'those')) 2455 self.assertEqual(Test.that.db, 'that') 2456 self.assertEqual(Test.that.user, 'those') 2457 2458 def test_empty_with_functional_api(self): 2459 empty = aenum.IntEnum('Foo', {}) 2460 self.assertEqual(len(empty), 0) 2461 2462 def test_auto_init(self): 2463 class Planet(Enum): 2464 _init_ = 'mass radius' 2465 MERCURY = (3.303e+23, 2.4397e6) 2466 VENUS = (4.869e+24, 6.0518e6) 2467 EARTH = (5.976e+24, 6.37814e6) 2468 MARS = (6.421e+23, 3.3972e6) 2469 JUPITER = (1.9e+27, 7.1492e7) 2470 SATURN = (5.688e+26, 6.0268e7) 2471 URANUS = (8.686e+25, 2.5559e7) 2472 NEPTUNE = (1.024e+26, 2.4746e7) 2473 @property 2474 def surface_gravity(self): 2475 # universal gravitational constant (m3 kg-1 s-2) 2476 G = 6.67300E-11 2477 return G * self.mass / (self.radius * self.radius) 2478 self.assertEqual(round(Planet.EARTH.surface_gravity, 2), 9.80) 2479 self.assertEqual(Planet.EARTH.value, (5.976e+24, 6.37814e6)) 2480 2481 def test_auto_init_with_value(self): 2482 class Color(Enum): 2483 _init_='value, rgb' 2484 RED = 1, (1, 0, 0) 2485 BLUE = 2, (0, 1, 0) 2486 GREEN = 3, (0, 0, 1) 2487 self.assertEqual(Color.RED.value, 1) 2488 self.assertEqual(Color.BLUE.value, 2) 2489 self.assertEqual(Color.GREEN.value, 3) 2490 self.assertEqual(Color.RED.rgb, (1, 0, 0)) 2491 self.assertEqual(Color.BLUE.rgb, (0, 1, 0)) 2492 self.assertEqual(Color.GREEN.rgb, (0, 0, 1)) 2493 2494 def test_noalias(self): 2495 class Settings(Enum): 2496 _settings_ = NoAlias 2497 red = 1 2498 rojo = 1 2499 self.assertFalse(Settings.red is Settings.rojo) 2500 self.assertRaises(TypeError, Settings, 1) 2501 2502 def test_auto_and_init(self): 2503 class Field(IntEnum): 2504 _order_ = 'TYPE START' 2505 _init_ = '__doc__' 2506 _settings_ = AutoNumber 2507 TYPE = "Char, Date, Logical, etc." 2508 START = "Field offset in record" 2509 self.assertEqual(Field.TYPE, 1) 2510 self.assertEqual(Field.START, 2) 2511 self.assertEqual(Field.TYPE.__doc__, 'Char, Date, Logical, etc.') 2512 self.assertEqual(Field.START.__doc__, 'Field offset in record') 2513 2514 def test_auto_and_start(self): 2515 class Field(IntEnum): 2516 _order_ = 'TYPE START' 2517 _start_ = 0 2518 _init_ = '__doc__' 2519 TYPE = "Char, Date, Logical, etc." 2520 START = "Field offset in record" 2521 self.assertEqual(Field.TYPE, 0) 2522 self.assertEqual(Field.START, 1) 2523 self.assertEqual(Field.TYPE.__doc__, 'Char, Date, Logical, etc.') 2524 self.assertEqual(Field.START.__doc__, 'Field offset in record') 2525 2526 def test_auto_and_init_and_some_values(self): 2527 class Field(IntEnum): 2528 _order_ = 'TYPE START BLAH BELCH' 2529 _init_ = '__doc__' 2530 _settings_ = AutoNumber 2531 TYPE = "Char, Date, Logical, etc." 2532 START = "Field offset in record" 2533 BLAH = 5, "test blah" 2534 BELCH = 'test belch' 2535 self.assertEqual(Field.TYPE, 1) 2536 self.assertEqual(Field.START, 2) 2537 self.assertEqual(Field.BLAH, 5) 2538 self.assertEqual(Field.BELCH, 6) 2539 self.assertEqual(Field.TYPE.__doc__, 'Char, Date, Logical, etc.') 2540 self.assertEqual(Field.START.__doc__, 'Field offset in record') 2541 self.assertEqual(Field.BLAH.__doc__, 'test blah') 2542 self.assertEqual(Field.BELCH.__doc__, 'test belch') 2543 2544 def test_auto_and_init_w_value_and_some_values(self): 2545 class Field(IntEnum): 2546 _order_ = 'TYPE START BLAH BELCH' 2547 _init_ = 'value __doc__' 2548 _settings_ = AutoNumber 2549 TYPE = 1, "Char, Date, Logical, etc." 2550 START = 2, "Field offset in record" 2551 BLAH = 5, "test blah" 2552 BELCH = 7, 'test belch' 2553 self.assertEqual(Field.TYPE, 1) 2554 self.assertEqual(Field.START, 2) 2555 self.assertEqual(Field.BLAH, 5) 2556 self.assertEqual(Field.BELCH, 7) 2557 self.assertEqual(Field.TYPE.__doc__, 'Char, Date, Logical, etc.') 2558 self.assertEqual(Field.START.__doc__, 'Field offset in record') 2559 self.assertEqual(Field.BLAH.__doc__, 'test blah') 2560 self.assertEqual(Field.BELCH.__doc__, 'test belch') 2561 2562 def test_auto_and_init_w_value_and_too_many_values(self): 2563 with self.assertRaisesRegex(TypeError, 'BLAH: number of fields provided do not match init'): 2564 class Field(IntEnum): 2565 _order_ = 'TYPE START BLAH BELCH' 2566 _init_ = 'value __doc__' 2567 _settings_ = AutoNumber 2568 TYPE = 1, "Char, Date, Logical, etc." 2569 START = 2, "Field offset in record" 2570 BLAH = 5, 6, "test blah" 2571 BELCH = 7, 'test belch' 2572 2573 def test_auto_and_init_and_some_complex_values(self): 2574 class Field(IntEnum): 2575 _order_ = 'TYPE START BLAH BELCH' 2576 _init_ = '__doc__ help' 2577 _settings_ = AutoNumber 2578 TYPE = "Char, Date, Logical, etc.", "fields composed of character data" 2579 START = "Field offset in record", "where the data starts in the record" 2580 BLAH = 5, "test blah", "some help" 2581 BELCH = 'test belch', "some more help" 2582 self.assertEqual(Field.TYPE, 1) 2583 self.assertEqual(Field.START, 2) 2584 self.assertEqual(Field.BLAH, 5) 2585 self.assertEqual(Field.BELCH, 6) 2586 self.assertEqual(Field.TYPE.__doc__, 'Char, Date, Logical, etc.') 2587 self.assertEqual(Field.START.__doc__, 'Field offset in record') 2588 self.assertEqual(Field.BLAH.__doc__, 'test blah') 2589 self.assertEqual(Field.BELCH.__doc__, 'test belch') 2590 self.assertEqual(Field.TYPE.help, "fields composed of character data") 2591 self.assertEqual(Field.START.help, "where the data starts in the record") 2592 self.assertEqual(Field.BLAH.help, "some help") 2593 self.assertEqual(Field.BELCH.help, "some more help") 2594 2595 def test_auto_and_init_inherited(self): 2596 class AutoEnum(IntEnum): 2597 _start_ = 0 2598 _init_ = '__doc__' 2599 class Field(AutoEnum): 2600 _order_ = 'TYPE START BLAH BELCH' 2601 TYPE = "Char, Date, Logical, etc." 2602 START = "Field offset in record" 2603 BLAH = 5, "test blah" 2604 BELCH = 'test belch' 2605 self.assertEqual(Field.TYPE, 0) 2606 self.assertEqual(Field.START, 1) 2607 self.assertEqual(Field.BLAH, 5) 2608 self.assertEqual(Field.BELCH, 6) 2609 self.assertEqual(Field.TYPE.__doc__, 'Char, Date, Logical, etc.') 2610 self.assertEqual(Field.START.__doc__, 'Field offset in record') 2611 self.assertEqual(Field.BLAH.__doc__, 'test blah') 2612 self.assertEqual(Field.BELCH.__doc__, 'test belch') 2613 2614 def test_auto_and_enum(self): 2615 class Foo(aenum.Flag): 2616 _order_ = 'a b' 2617 a = aenum.auto() 2618 b = a | aenum.auto() 2619 2620 self.assertEqual([Foo.a, Foo.b], list(Foo)) 2621 self.assertEqual(Foo.a.value, 1) 2622 self.assertEqual(Foo.b.value, 3) 2623 2624 def test_AutoNumberEnum_and_property(self): 2625 class Color(aenum.AutoNumberEnum): 2626 red = () 2627 green = () 2628 blue = () 2629 @property 2630 def cap_name(self): 2631 return self.name.title() 2632 self.assertEqual(Color.blue.cap_name, 'Blue') 2633 2634 def test_AutoNumberEnum(self): 2635 class Color(aenum.AutoNumberEnum): 2636 _order_ = 'red green blue' 2637 red = () 2638 green = () 2639 blue = () 2640 self.assertEqual(list(Color), [Color.red, Color.green, Color.blue]) 2641 self.assertEqual(Color.red.value, 1) 2642 self.assertEqual(Color.green.value, 2) 2643 self.assertEqual(Color.blue.value, 3) 2644 2645 def test_MultiValue_with_init_wo_value(self): 2646 class Color(Enum): 2647 _init_ = 'color r g b' 2648 _order_ = 'red green blue' 2649 _settings_ = MultiValue 2650 red = 'red', 1, 2, 3 2651 green = 'green', 4, 5, 6 2652 blue = 'blue', 7, 8, 9 2653 self.assertEqual(Color.red.value, 'red') 2654 self.assertEqual(Color.red.color, 'red') 2655 self.assertEqual(Color.red.r, 1) 2656 self.assertEqual(Color.red.g, 2) 2657 self.assertEqual(Color.red.b, 3) 2658 self.assertEqual(Color.green.value, 'green') 2659 self.assertEqual(Color.green.color, 'green') 2660 self.assertEqual(Color.green.r, 4) 2661 self.assertEqual(Color.green.g, 5) 2662 self.assertEqual(Color.green.b, 6) 2663 self.assertEqual(Color.blue.value, 'blue') 2664 self.assertEqual(Color.blue.color, 'blue') 2665 self.assertEqual(Color.blue.r, 7) 2666 self.assertEqual(Color.blue.g, 8) 2667 self.assertEqual(Color.blue.b, 9) 2668 self.assertIs(Color('red'), Color.red) 2669 self.assertIs(Color(1), Color.red) 2670 self.assertIs(Color(2), Color.red) 2671 self.assertIs(Color(3), Color.red) 2672 self.assertIs(Color('green'), Color.green) 2673 self.assertIs(Color(4), Color.green) 2674 self.assertIs(Color(5), Color.green) 2675 self.assertIs(Color(6), Color.green) 2676 self.assertIs(Color('blue'), Color.blue) 2677 self.assertIs(Color(7), Color.blue) 2678 self.assertIs(Color(8), Color.blue) 2679 self.assertIs(Color(9), Color.blue) 2680 2681 def test_MultiValue_with_init_w_value(self): 2682 class Color(Enum): 2683 _init_ = 'value r g b' 2684 _order_ = 'red green blue' 2685 _settings_ = MultiValue 2686 red = 'red', 1, 2, 3 2687 green = 'green', 4, 5, 6 2688 blue = 'blue', 7, 8, 9 2689 self.assertEqual(Color.red.value, 'red') 2690 self.assertEqual(Color.red.r, 1) 2691 self.assertEqual(Color.red.g, 2) 2692 self.assertEqual(Color.red.b, 3) 2693 self.assertEqual(Color.green.value, 'green') 2694 self.assertEqual(Color.green.r, 4) 2695 self.assertEqual(Color.green.g, 5) 2696 self.assertEqual(Color.green.b, 6) 2697 self.assertEqual(Color.blue.value, 'blue') 2698 self.assertEqual(Color.blue.r, 7) 2699 self.assertEqual(Color.blue.g, 8) 2700 self.assertEqual(Color.blue.b, 9) 2701 self.assertIs(Color('red'), Color.red) 2702 self.assertIs(Color(1), Color.red) 2703 self.assertIs(Color(2), Color.red) 2704 self.assertIs(Color(3), Color.red) 2705 self.assertIs(Color('green'), Color.green) 2706 self.assertIs(Color(4), Color.green) 2707 self.assertIs(Color(5), Color.green) 2708 self.assertIs(Color(6), Color.green) 2709 self.assertIs(Color('blue'), Color.blue) 2710 self.assertIs(Color(7), Color.blue) 2711 self.assertIs(Color(8), Color.blue) 2712 self.assertIs(Color(9), Color.blue) 2713 2714 def test_MultiValue_with_init_wo_value_w_autonumber(self): 2715 class Color(Enum): 2716 _init_ = 'color r g b' 2717 _order_ = 'red green blue' 2718 _settings_ = MultiValue, AutoNumber 2719 red = 'red', 10, 20, 30 2720 green = 'green', 40, 50, 60 2721 blue = 'blue', 70, 80, 90 2722 self.assertEqual(Color.red.value, 1) 2723 self.assertEqual(Color.red.color, 'red') 2724 self.assertEqual(Color.red.r, 10) 2725 self.assertEqual(Color.red.g, 20) 2726 self.assertEqual(Color.red.b, 30) 2727 self.assertEqual(Color.green.value, 2) 2728 self.assertEqual(Color.green.color, 'green') 2729 self.assertEqual(Color.green.r, 40) 2730 self.assertEqual(Color.green.g, 50) 2731 self.assertEqual(Color.green.b, 60) 2732 self.assertEqual(Color.blue.value, 3) 2733 self.assertEqual(Color.blue.color, 'blue') 2734 self.assertEqual(Color.blue.r, 70) 2735 self.assertEqual(Color.blue.g, 80) 2736 self.assertEqual(Color.blue.b, 90) 2737 self.assertIs(Color(1), Color.red) 2738 self.assertIs(Color('red'), Color.red) 2739 self.assertIs(Color(10), Color.red) 2740 self.assertIs(Color(20), Color.red) 2741 self.assertIs(Color(30), Color.red) 2742 self.assertIs(Color(2), Color.green) 2743 self.assertIs(Color('green'), Color.green) 2744 self.assertIs(Color(40), Color.green) 2745 self.assertIs(Color(50), Color.green) 2746 self.assertIs(Color(60), Color.green) 2747 self.assertIs(Color(3), Color.blue) 2748 self.assertIs(Color('blue'), Color.blue) 2749 self.assertIs(Color(70), Color.blue) 2750 self.assertIs(Color(80), Color.blue) 2751 self.assertIs(Color(90), Color.blue) 2752 2753 def test_MultiValue_with_init_wo_value_w_autonumber_and_value(self): 2754 class Color(Enum): 2755 _init_ = 'color r g b' 2756 _order_ = 'red green blue chartruese' 2757 _settings_ = MultiValue, AutoNumber 2758 red = 'red', 10, 20, 30 2759 green = 'green', 40, 50, 60 2760 blue = 5, 'blue', 70, 80, 90 2761 chartruese = 'chartruese', 100, 110, 120 2762 self.assertEqual(Color.red.value, 1) 2763 self.assertEqual(Color.red.color, 'red') 2764 self.assertEqual(Color.red.r, 10) 2765 self.assertEqual(Color.red.g, 20) 2766 self.assertEqual(Color.red.b, 30) 2767 self.assertEqual(Color.green.value, 2) 2768 self.assertEqual(Color.green.color, 'green') 2769 self.assertEqual(Color.green.r, 40) 2770 self.assertEqual(Color.green.g, 50) 2771 self.assertEqual(Color.green.b, 60) 2772 self.assertEqual(Color.blue.value, 5) 2773 self.assertEqual(Color.blue.color, 'blue') 2774 self.assertEqual(Color.blue.r, 70) 2775 self.assertEqual(Color.blue.g, 80) 2776 self.assertEqual(Color.blue.b, 90) 2777 self.assertEqual(Color.chartruese.value, 6) 2778 self.assertEqual(Color.chartruese.color, 'chartruese') 2779 self.assertEqual(Color.chartruese.r, 100) 2780 self.assertEqual(Color.chartruese.g, 110) 2781 self.assertEqual(Color.chartruese.b, 120) 2782 self.assertIs(Color(1), Color.red) 2783 self.assertIs(Color('red'), Color.red) 2784 self.assertIs(Color(10), Color.red) 2785 self.assertIs(Color(20), Color.red) 2786 self.assertIs(Color(30), Color.red) 2787 self.assertIs(Color(2), Color.green) 2788 self.assertIs(Color('green'), Color.green) 2789 self.assertIs(Color(40), Color.green) 2790 self.assertIs(Color(50), Color.green) 2791 self.assertIs(Color(60), Color.green) 2792 self.assertIs(Color(5), Color.blue) 2793 self.assertIs(Color('blue'), Color.blue) 2794 self.assertIs(Color(70), Color.blue) 2795 self.assertIs(Color(80), Color.blue) 2796 self.assertIs(Color(90), Color.blue) 2797 self.assertIs(Color(6), Color.chartruese) 2798 self.assertIs(Color('chartruese'), Color.chartruese) 2799 self.assertIs(Color(100), Color.chartruese) 2800 self.assertIs(Color(110), Color.chartruese) 2801 self.assertIs(Color(120), Color.chartruese) 2802 2803 def test_multivalue_and_autonumber_wo_init_wo_value(self): 2804 class Day(Enum): 2805 _settings_ = MultiValue, AutoNumber 2806 _order_ = 'one two three' 2807 _start_ = 1 2808 one = "21", "one" 2809 two = "22", "two" 2810 three = "23", "three" 2811 self.assertEqual(Day.one.value, 1) 2812 self.assertEqual(Day.two.value, 2) 2813 self.assertEqual(Day.three.value, 3) 2814 self.assertEqual(Day('one'), Day.one) 2815 2816 def test_multivalue_and_autonumber_wo_init_w_some_value(self): 2817 class Color(Enum): 2818 _settings_ = AutoNumber, MultiValue, Unique 2819 _order_ = 'BLACK RED BLUE YELLOW GREEN MAGENTA' 2820 _init_ = "value description" 2821 BLACK = -1, "Text0" 2822 RED = -50, "Text1" 2823 BLUE = auto(), "Text2" 2824 YELLOW = auto(), "Text3" 2825 GREEN = -70, "Text4" 2826 MAGENTA = auto(), "Text5" 2827 self.assertEqual(Color.BLACK.value, -1) 2828 self.assertEqual(Color.RED.value, -50) 2829 self.assertEqual(Color.BLUE.value, -49) 2830 self.assertEqual(Color.YELLOW.value, -48) 2831 self.assertEqual(Color.GREEN.value, -70) 2832 self.assertEqual(Color.MAGENTA.value, -69) 2833 self.assertEqual(Color(-1), Color.BLACK) 2834 self.assertEqual(Color('Text2'), Color.BLUE) 2835 2836 def test_combine_new_settings_with_old_settings(self): 2837 class Auto(Enum): 2838 _settings_ = Unique 2839 with self.assertRaises(ValueError): 2840 class AutoUnique(Auto): 2841 _settings_ = AutoNumber 2842 BLAH = () 2843 BLUH = () 2844 ICK = 1 2845 2846 def test_timedelta(self): 2847 class Period(timedelta, Enum): 2848 ''' 2849 different lengths of time 2850 ''' 2851 _init_ = 'value period' 2852 _settings_ = NoAlias 2853 _ignore_ = 'Period i' 2854 Period = vars() 2855 for i in range(31): 2856 Period['day_%d' % i] = i, 'day' 2857 for i in range(15): 2858 Period['week_%d' % i] = i*7, 'week' 2859 for i in range(12): 2860 Period['month_%d' % i] = i*30, 'month' 2861 OneDay = day_1 2862 OneWeek = week_1 2863 self.assertFalse(hasattr(Period, '_ignore_')) 2864 self.assertFalse(hasattr(Period, 'Period')) 2865 self.assertFalse(hasattr(Period, 'i')) 2866 self.assertTrue(isinstance(Period.day_1, timedelta)) 2867 2868 def test_skip(self): 2869 class enumA(Enum): 2870 @skip 2871 class enumB(Enum): 2872 elementA = 'a' 2873 elementB = 'b' 2874 @skip 2875 class enumC(Enum): 2876 elementC = 'c' 2877 elementD = 'd' 2878 self.assertIs(enumA.enumB, enumA.__dict__['enumB']) 2879 2880 def test_nonmember(self): 2881 class enumA(Enum): 2882 @nonmember 2883 class enumB(Enum): 2884 elementA = 'a' 2885 elementB = 'b' 2886 @nonmember 2887 class enumC(Enum): 2888 elementC = 'c' 2889 elementD = 'd' 2890 self.assertIs(enumA.enumB, enumA.__dict__['enumB']) 2891 2892 def test_member_with_external_functions(self): 2893 class Func(Enum): 2894 _order_ = 'an_int a_str' 2895 an_int = member(int) 2896 a_str = member(str) 2897 @classproperty 2898 def types(cls): 2899 return [m.value for m in list(cls)] 2900 def __repr__(self): 2901 return "<%s.%s>" % (self.__class__.__name__, self.name, ) 2902 def __call__(self, *args, **kwds): 2903 return self.value(*args, **kwds) 2904 # 2905 self.assertEqual([Func.an_int, Func.a_str], list(Func)) 2906 self.assertEqual([int, str], Func.types) 2907 self.assertEqual(Func.an_int(7), 7) 2908 self.assertEqual(Func.a_str('BlahBlah'), 'BlahBlah') 2909 2910 def test_member_with_internal_functions(self): 2911 class Func(Enum): 2912 _order_ = 'haha hehe' 2913 @member 2914 def haha(): 2915 return 'haha' 2916 @member 2917 def hehe(name): 2918 return 'hehe -- what a name! %s!' % name 2919 @classproperty 2920 def types(cls): 2921 return [m.value for m in list(cls)] 2922 def __repr__(self): 2923 return "<%s.%s>" % (self.__class__.__name__, self.name, ) 2924 def __call__(self, *args, **kwds): 2925 return self.value(*args, **kwds) 2926 # 2927 self.assertEqual([Func.haha, Func.hehe], list(Func)) 2928 self.assertEqual([Func.haha.value, Func.hehe.value], Func.types) 2929 self.assertEqual(Func.haha(), 'haha') 2930 self.assertEqual(Func.hehe('BlahBlah'), 'hehe -- what a name! BlahBlah!') 2931 2932 def test_constantness_of_constants(self): 2933 class Universe(Enum): 2934 PI = constant(3.141596) 2935 G = constant(6.67300E-11) 2936 self.assertEqual(Universe.PI, 3.141596) 2937 self.assertRaisesRegex(AttributeError, 'cannot rebind constant', setattr, Universe, 'PI', 9) 2938 self.assertRaisesRegex(AttributeError, 'cannot delete constant', delattr, Universe, 'PI') 2939 2940 def test_math_and_stuff_with_constants(self): 2941 class Universe(Enum): 2942 PI = constant(3.141596) 2943 TAU = constant(2 * PI) 2944 self.assertEqual(Universe.PI, 3.141596) 2945 self.assertEqual(Universe.TAU, 2 * Universe.PI) 2946 2947 def test_constant_with_auto_is_updated(self): 2948 class Fruit(Flag): 2949 _order_ = 'apple banana lemon orange' 2950 apple = auto() 2951 banana = auto() 2952 lemon = auto() 2953 orange = auto() 2954 CitrusTypes = constant(lemon | orange) 2955 self.assertEqual(list(Fruit), [Fruit.apple, Fruit.banana, Fruit.lemon, Fruit.orange]) 2956 self.assertEqual(list(Fruit.CitrusTypes), [Fruit.orange, Fruit.lemon]) 2957 self.assertTrue(Fruit.orange in Fruit.CitrusTypes) 2958 2959 def test_constant_with_enum_is_updated(self): 2960 class Fruit(Flag): 2961 _order_ = 'apple banana lemon orange' 2962 apple = auto() 2963 banana = auto() 2964 lemon = auto() 2965 orange = auto() 2966 CitrusTypes = constant(lemon | orange) 2967 self.assertEqual(list(Fruit), [Fruit.apple, Fruit.banana, Fruit.lemon, Fruit.orange]) 2968 self.assertEqual(list(Fruit.CitrusTypes), [Fruit.orange, Fruit.lemon]) 2969 self.assertTrue(Fruit.orange in Fruit.CitrusTypes) 2970 2971 def test_order_as_function(self): 2972 # first with _init_ 2973 class TestSequence(Enum): 2974 _init_ = 'value, sequence' 2975 _order_ = lambda member: member.sequence 2976 item_id = 'An$(1,6)', 0 # Item Code 2977 company_id = 'An$(7,2)', 1 # Company Code 2978 warehouse_no = 'An$(9,4)', 2 # Warehouse Number 2979 company = 'Hn$(13,6)', 3 # 4 SPACES + COMPANY 2980 key_type = 'Cn$(19,3)', 4 # Key Type = '1**' 2981 available = 'Zn$(1,1)', 5 # Available? 2982 contract_item = 'Bn(2,1)', 6 # Contract Item? 2983 sales_category = 'Fn', 7 # Sales Category 2984 gl_category = 'Rn$(5,1)', 8 # G/L Category 2985 warehouse_category = 'Sn$(6,1)', 9 # Warehouse Category 2986 inv_units = 'Qn$(7,2)', 10 # Inv Units 2987 for i, member in enumerate(TestSequence): 2988 self.assertEqual(i, member.sequence) 2989 ts = TestSequence 2990 self.assertEqual(ts.item_id.name, 'item_id') 2991 self.assertEqual(ts.item_id.value, 'An$(1,6)') 2992 self.assertEqual(ts.item_id.sequence, 0) 2993 self.assertEqual(ts.company_id.name, 'company_id') 2994 self.assertEqual(ts.company_id.value, 'An$(7,2)') 2995 self.assertEqual(ts.company_id.sequence, 1) 2996 self.assertEqual(ts.warehouse_no.name, 'warehouse_no') 2997 self.assertEqual(ts.warehouse_no.value, 'An$(9,4)') 2998 self.assertEqual(ts.warehouse_no.sequence, 2) 2999 self.assertEqual(ts.company.name, 'company') 3000 self.assertEqual(ts.company.value, 'Hn$(13,6)') 3001 self.assertEqual(ts.company.sequence, 3) 3002 self.assertEqual(ts.key_type.name, 'key_type') 3003 self.assertEqual(ts.key_type.value, 'Cn$(19,3)') 3004 self.assertEqual(ts.key_type.sequence, 4) 3005 self.assertEqual(ts.available.name, 'available') 3006 self.assertEqual(ts.available.value, 'Zn$(1,1)') 3007 self.assertEqual(ts.available.sequence, 5) 3008 self.assertEqual(ts.contract_item.name, 'contract_item') 3009 self.assertEqual(ts.contract_item.value, 'Bn(2,1)') 3010 self.assertEqual(ts.contract_item.sequence, 6) 3011 self.assertEqual(ts.sales_category.name, 'sales_category') 3012 self.assertEqual(ts.sales_category.value, 'Fn') 3013 self.assertEqual(ts.sales_category.sequence, 7) 3014 self.assertEqual(ts.gl_category.name, 'gl_category') 3015 self.assertEqual(ts.gl_category.value, 'Rn$(5,1)') 3016 self.assertEqual(ts.gl_category.sequence, 8) 3017 self.assertEqual(ts.warehouse_category.name, 'warehouse_category') 3018 self.assertEqual(ts.warehouse_category.value, 'Sn$(6,1)') 3019 self.assertEqual(ts.warehouse_category.sequence, 9) 3020 self.assertEqual(ts.inv_units.name, 'inv_units') 3021 self.assertEqual(ts.inv_units.value, 'Qn$(7,2)') 3022 self.assertEqual(ts.inv_units.sequence, 10) 3023 # and then without 3024 class TestSequence(Enum): 3025 _order_ = lambda member: member.value[1] 3026 item_id = 'An$(1,6)', 0 # Item Code 3027 company_id = 'An$(7,2)', 1 # Company Code 3028 warehouse_no = 'An$(9,4)', 2 # Warehouse Number 3029 company = 'Hn$(13,6)', 3 # 4 SPACES + COMPANY 3030 key_type = 'Cn$(19,3)', 4 # Key Type = '1**' 3031 available = 'Zn$(1,1)', 5 # Available? 3032 contract_item = 'Bn(2,1)', 6 # Contract Item? 3033 sales_category = 'Fn', 7 # Sales Category 3034 gl_category = 'Rn$(5,1)', 8 # G/L Category 3035 warehouse_category = 'Sn$(6,1)', 9 # Warehouse Category 3036 inv_units = 'Qn$(7,2)', 10 # Inv Units 3037 for i, member in enumerate(TestSequence): 3038 self.assertEqual(i, member.value[1]) 3039 ts = TestSequence 3040 self.assertEqual(ts.item_id.name, 'item_id') 3041 self.assertEqual(ts.item_id.value, ('An$(1,6)', 0)) 3042 self.assertEqual(ts.company_id.name, 'company_id') 3043 self.assertEqual(ts.company_id.value, ('An$(7,2)', 1)) 3044 self.assertEqual(ts.warehouse_no.name, 'warehouse_no') 3045 self.assertEqual(ts.warehouse_no.value, ('An$(9,4)', 2)) 3046 self.assertEqual(ts.company.name, 'company') 3047 self.assertEqual(ts.company.value, ('Hn$(13,6)', 3)) 3048 self.assertEqual(ts.key_type.name, 'key_type') 3049 self.assertEqual(ts.key_type.value, ('Cn$(19,3)', 4)) 3050 self.assertEqual(ts.available.name, 'available') 3051 self.assertEqual(ts.available.value, ('Zn$(1,1)', 5)) 3052 self.assertEqual(ts.contract_item.name, 'contract_item') 3053 self.assertEqual(ts.contract_item.value, ('Bn(2,1)', 6)) 3054 self.assertEqual(ts.sales_category.name, 'sales_category') 3055 self.assertEqual(ts.sales_category.value, ('Fn', 7)) 3056 self.assertEqual(ts.gl_category.name, 'gl_category') 3057 self.assertEqual(ts.gl_category.value, ('Rn$(5,1)', 8)) 3058 self.assertEqual(ts.warehouse_category.name, 'warehouse_category') 3059 self.assertEqual(ts.warehouse_category.value, ('Sn$(6,1)', 9)) 3060 self.assertEqual(ts.inv_units.name, 'inv_units') 3061 self.assertEqual(ts.inv_units.value, ('Qn$(7,2)', 10)) 3062 # then with _init_ but without value 3063 with self.assertRaises(TypeError): 3064 class TestSequence(Enum): 3065 _init_ = 'sequence' 3066 _order_ = lambda member: member.sequence 3067 item_id = 'An$(1,6)', 0 # Item Code 3068 company_id = 'An$(7,2)', 1 # Company Code 3069 warehouse_no = 'An$(9,4)', 2 # Warehouse Number 3070 company = 'Hn$(13,6)', 3 # 4 SPACES + COMPANY 3071 key_type = 'Cn$(19,3)', 4 # Key Type = '1**' 3072 available = 'Zn$(1,1)', 5 # Available? 3073 contract_item = 'Bn(2,1)', 6 # Contract Item? 3074 sales_category = 'Fn', 7 # Sales Category 3075 gl_category = 'Rn$(5,1)', 8 # G/L Category 3076 warehouse_category = 'Sn$(6,1)', 9 # Warehouse Category 3077 inv_units = 'Qn$(7,2)', 10 # Inv Units 3078 # finally, out of order so Python 3 barfs 3079 with self.assertRaises(TypeError): 3080 class TestSequence(Enum): 3081 _init_ = 'sequence' 3082 _order_ = lambda member: member.sequence 3083 item_id = 'An$(1,6)', 0 # Item Code 3084 warehouse_no = 'An$(9,4)', 2 # Warehouse Number 3085 company = 'Hn$(13,6)', 3 # 4 SPACES + COMPANY 3086 company_id = 'An$(7,2)', 1 # Company Code 3087 inv_units = 'Qn$(7,2)', 10 # Inv Units 3088 available = 'Zn$(1,1)', 5 # Available? 3089 contract_item = 'Bn(2,1)', 6 # Contract Item? 3090 sales_category = 'Fn', 7 # Sales Category 3091 key_type = 'Cn$(19,3)', 4 # Key Type = '1**' 3092 gl_category = 'Rn$(5,1)', 8 # G/L Category 3093 warehouse_category = 'Sn$(6,1)', 9 # Warehouse Category 3094 3095 def test_order_as_function_in_subclass(self): 3096 # 3097 class Parent(Enum): 3098 _init_ = 'value sequence' 3099 _order_ = lambda m: m.sequence 3100 # 3101 class Child(Parent): 3102 item_id = 'An$(1,6)', 0 # Item Code 3103 company_id = 'An$(7,2)', 1 # Company Code 3104 warehouse_no = 'An$(9,4)', 2 # Warehouse Number 3105 company = 'Hn$(13,6)', 3 # 4 SPACES + COMPANY 3106 key_type = 'Cn$(19,3)', 4 # Key Type = '1**' 3107 available = 'Zn$(1,1)', 5 # Available? 3108 contract_item = 'Bn(2,1)', 6 # Contract Item? 3109 sales_category = 'Fn', 7 # Sales Category 3110 gl_category = 'Rn$(5,1)', 8 # G/L Category 3111 warehouse_category = 'Sn$(6,1)', 9 # Warehouse Category 3112 inv_units = 'Qn$(7,2)', 10 # Inv Units 3113 # 3114 for i, member in enumerate(Child): 3115 self.assertEqual(i, member.sequence) 3116 # 3117 ts = Child 3118 self.assertEqual(ts.item_id.name, 'item_id') 3119 self.assertEqual(ts.item_id.value, 'An$(1,6)') 3120 self.assertEqual(ts.item_id.sequence, 0) 3121 self.assertEqual(ts.company_id.name, 'company_id') 3122 self.assertEqual(ts.company_id.value, 'An$(7,2)') 3123 self.assertEqual(ts.company_id.sequence, 1) 3124 self.assertEqual(ts.warehouse_no.name, 'warehouse_no') 3125 self.assertEqual(ts.warehouse_no.value, 'An$(9,4)') 3126 self.assertEqual(ts.warehouse_no.sequence, 2) 3127 self.assertEqual(ts.company.name, 'company') 3128 self.assertEqual(ts.company.value, 'Hn$(13,6)') 3129 self.assertEqual(ts.company.sequence, 3) 3130 self.assertEqual(ts.key_type.name, 'key_type') 3131 self.assertEqual(ts.key_type.value, 'Cn$(19,3)') 3132 self.assertEqual(ts.key_type.sequence, 4) 3133 self.assertEqual(ts.available.name, 'available') 3134 self.assertEqual(ts.available.value, 'Zn$(1,1)') 3135 self.assertEqual(ts.available.sequence, 5) 3136 self.assertEqual(ts.contract_item.name, 'contract_item') 3137 self.assertEqual(ts.contract_item.value, 'Bn(2,1)') 3138 self.assertEqual(ts.contract_item.sequence, 6) 3139 self.assertEqual(ts.sales_category.name, 'sales_category') 3140 self.assertEqual(ts.sales_category.value, 'Fn') 3141 self.assertEqual(ts.sales_category.sequence, 7) 3142 self.assertEqual(ts.gl_category.name, 'gl_category') 3143 self.assertEqual(ts.gl_category.value, 'Rn$(5,1)') 3144 self.assertEqual(ts.gl_category.sequence, 8) 3145 self.assertEqual(ts.warehouse_category.name, 'warehouse_category') 3146 self.assertEqual(ts.warehouse_category.value, 'Sn$(6,1)') 3147 self.assertEqual(ts.warehouse_category.sequence, 9) 3148 self.assertEqual(ts.inv_units.name, 'inv_units') 3149 self.assertEqual(ts.inv_units.value, 'Qn$(7,2)') 3150 self.assertEqual(ts.inv_units.sequence, 10) 3151 3152 pass 3153 3154 if StdlibEnumMeta is not None: 3155 def test_stdlib_inheritence(self): 3156 self.assertTrue(isinstance(self.Season, StdlibEnumMeta)) 3157 self.assertTrue(issubclass(self.Season, StdlibEnum)) 3158 3159 def test_multiple_mixin(self): 3160 class MaxMixin(object): 3161 @classproperty 3162 def MAX(cls): 3163 max = len(cls) 3164 cls.MAX = max 3165 return max 3166 class StrMixin(object): 3167 def __str__(self): 3168 return self._name_.lower() 3169 class SomeEnum(Enum): 3170 def behavior(self): 3171 return 'booyah' 3172 class AnotherEnum(Enum): 3173 def behavior(self): 3174 return 'nuhuh!' 3175 def social(self): 3176 return "what's up?" 3177 class Color(MaxMixin, Enum): 3178 _order_ = 'RED GREEN BLUE' 3179 RED = auto() 3180 GREEN = auto() 3181 BLUE = auto() 3182 self.assertEqual(Color.RED.value, 1) 3183 self.assertEqual(Color.GREEN.value, 2) 3184 self.assertEqual(Color.BLUE.value, 3) 3185 self.assertEqual(Color.MAX, 3) 3186 self.assertEqual(str(Color.BLUE), 'Color.BLUE') 3187 class Color(MaxMixin, StrMixin, Enum): 3188 _order_ = 'RED GREEN BLUE' 3189 RED = auto() 3190 GREEN = auto() 3191 BLUE = auto() 3192 # print('-' * 15) 3193 # print(list(Color)) 3194 # print(Color.__mro__) 3195 # print('-' * 15) 3196 self.assertEqual(Color.RED.value, 1) 3197 self.assertEqual(Color.GREEN.value, 2) 3198 self.assertEqual(Color.BLUE.value, 3) 3199 self.assertEqual(Color.MAX, 3) 3200 self.assertEqual(str(Color.BLUE), 'blue', '%r is not %r' % (str(Color.BLUE), 'blue')) 3201 class Color(StrMixin, MaxMixin, Enum): 3202 _order_ = 'RED GREEN BLUE' 3203 RED = auto() 3204 GREEN = auto() 3205 BLUE = auto() 3206 self.assertEqual(Color.RED.value, 1) 3207 self.assertEqual(Color.GREEN.value, 2) 3208 self.assertEqual(Color.BLUE.value, 3) 3209 self.assertEqual(Color.MAX, 3) 3210 self.assertEqual(str(Color.BLUE), 'blue', '%r is not %r' % (str(Color.BLUE), 'blue')) 3211 class CoolColor(StrMixin, SomeEnum, Enum): 3212 _order_ = 'RED GREEN BLUE' 3213 RED = auto() 3214 GREEN = auto() 3215 BLUE = auto() 3216 self.assertEqual(CoolColor.RED.value, 1) 3217 self.assertEqual(CoolColor.GREEN.value, 2) 3218 self.assertEqual(CoolColor.BLUE.value, 3) 3219 self.assertEqual(str(CoolColor.BLUE), 'blue', '%r is not %r' % (str(Color.BLUE), 'blue')) 3220 self.assertEqual(CoolColor.RED.behavior(), 'booyah') 3221 class CoolerColor(StrMixin, AnotherEnum, Enum): 3222 _order_ = 'RED GREEN BLUE' 3223 RED = auto() 3224 GREEN = auto() 3225 BLUE = auto() 3226 self.assertEqual(CoolerColor.RED.value, 1) 3227 self.assertEqual(CoolerColor.GREEN.value, 2) 3228 self.assertEqual(CoolerColor.BLUE.value, 3) 3229 self.assertEqual(str(CoolerColor.BLUE), 'blue', '%r is not %r' % (str(Color.BLUE), 'blue')) 3230 self.assertEqual(CoolerColor.RED.behavior(), 'nuhuh!') 3231 self.assertEqual(CoolerColor.RED.social(), "what's up?") 3232 class CoolestColor(StrMixin, SomeEnum, AnotherEnum): 3233 _order_ = 'RED GREEN BLUE' 3234 RED = auto() 3235 GREEN = auto() 3236 BLUE = auto() 3237 self.assertEqual(CoolestColor.RED.value, 1) 3238 self.assertEqual(CoolestColor.GREEN.value, 2) 3239 self.assertEqual(CoolestColor.BLUE.value, 3) 3240 self.assertEqual(str(CoolestColor.BLUE), 'blue', '%r is not %r' % (str(Color.BLUE), 'blue')) 3241 self.assertEqual(CoolestColor.RED.behavior(), 'booyah') 3242 self.assertEqual(CoolestColor.RED.social(), "what's up?") 3243 class ConfusedColor(StrMixin, AnotherEnum, SomeEnum): 3244 _order_ = 'RED GREEN BLUE' 3245 RED = auto() 3246 GREEN = auto() 3247 BLUE = auto() 3248 self.assertEqual(ConfusedColor.RED.value, 1) 3249 self.assertEqual(ConfusedColor.GREEN.value, 2) 3250 self.assertEqual(ConfusedColor.BLUE.value, 3) 3251 self.assertEqual(str(ConfusedColor.BLUE), 'blue', '%r is not %r' % (str(Color.BLUE), 'blue')) 3252 self.assertEqual(ConfusedColor.RED.behavior(), 'nuhuh!') 3253 self.assertEqual(ConfusedColor.RED.social(), "what's up?") 3254 class ReformedColor(StrMixin, IntEnum, SomeEnum, AnotherEnum): 3255 _order_ = 'RED GREEN BLUE' 3256 RED = auto() 3257 GREEN = auto() 3258 BLUE = auto() 3259 self.assertEqual(ReformedColor.RED.value, 1) 3260 self.assertEqual(ReformedColor.GREEN.value, 2) 3261 self.assertEqual(ReformedColor.BLUE.value, 3) 3262 self.assertEqual(str(ReformedColor.BLUE), 'blue', '%r is not %r' % (str(Color.BLUE), 'blue')) 3263 self.assertEqual(ReformedColor.RED.behavior(), 'booyah') 3264 self.assertEqual(ConfusedColor.RED.social(), "what's up?") 3265 self.assertTrue(issubclass(ReformedColor, int)) 3266 3267 def test_multiple_inherited_mixin(self): 3268 class StrEnum(str, Enum): 3269 def __new__(cls, *args, **kwargs): 3270 for a in args: 3271 if not isinstance(a, str): 3272 raise TypeError("Enumeration '%s' (%s) is not" 3273 " a string" % (a, type(a).__name__)) 3274 return str.__new__(cls, *args, **kwargs) 3275 @unique 3276 class Decision1(StrEnum): 3277 REVERT = "REVERT" 3278 REVERT_ALL = "REVERT_ALL" 3279 RETRY = "RETRY" 3280 class MyEnum(StrEnum): 3281 pass 3282 @unique 3283 class Decision2(MyEnum): 3284 REVERT = "REVERT" 3285 REVERT_ALL = "REVERT_ALL" 3286 RETRY = "RETRY" 3287 3288 3289 def test_enum_of_types(self): 3290 """Support using Enum to refer to types deliberately.""" 3291 class MyTypes(Enum): 3292 i = int 3293 f = float 3294 s = str 3295 self.assertEqual(MyTypes.i.value, int) 3296 self.assertEqual(MyTypes.f.value, float) 3297 self.assertEqual(MyTypes.s.value, str) 3298 class Foo: 3299 pass 3300 class Bar: 3301 pass 3302 class MyTypes2(Enum): 3303 a = Foo 3304 b = Bar 3305 self.assertEqual(MyTypes2.a.value, Foo) 3306 self.assertEqual(MyTypes2.b.value, Bar) 3307 class SpamEnumNotInner: 3308 pass 3309 class SpamEnum(Enum): 3310 spam = SpamEnumNotInner 3311 self.assertEqual(SpamEnum.spam.value, SpamEnumNotInner) 3312 3313 if pyver < 3.0: 3314 def test_nested_classes_in_enum_do_become_members(self): 3315 # manually set __qualname__ to remove testing framework noise 3316 class Outer(Enum): 3317 _order_ = 'a b Inner' 3318 __qualname__ = "Outer" 3319 a = 1 3320 b = 2 3321 class Inner(Enum): 3322 __qualname__ = "Outer.Inner" 3323 foo = 10 3324 bar = 11 3325 self.assertTrue(isinstance(Outer.Inner, Outer)) 3326 self.assertEqual(Outer.a.value, 1) 3327 self.assertEqual(Outer.Inner.value.foo.value, 10) 3328 self.assertEqual( 3329 list(Outer.Inner.value), 3330 [Outer.Inner.value.foo, Outer.Inner.value.bar], 3331 ) 3332 self.assertEqual( 3333 list(Outer), 3334 [Outer.a, Outer.b, Outer.Inner], 3335 ) 3336 3337 def test_really_nested_classes_in_enum_do_become_members(self): 3338 class Outer(Enum): 3339 _order_ = 'a b Inner' 3340 a = 1 3341 b = 2 3342 class Inner(Enum): 3343 foo = 10 3344 bar = 11 3345 self.assertTrue(isinstance(Outer.Inner, Outer)) 3346 self.assertEqual(Outer.a.value, 1) 3347 self.assertEqual(Outer.Inner.value.foo.value, 10) 3348 self.assertEqual( 3349 list(Outer.Inner.value), 3350 [Outer.Inner.value.foo, Outer.Inner.value.bar], 3351 ) 3352 self.assertEqual( 3353 list(Outer), 3354 [Outer.a, Outer.b, Outer.Inner], 3355 ) 3356 3357 def test_nested_classes_in_enum_are_skipped_with_skip(self): 3358 """Support locally-defined nested classes using @skip""" 3359 # manually set __qualname__ to remove testing framework noise 3360 class Outer(Enum): 3361 __qualname__ = "Outer" 3362 a = 1 3363 b = 2 3364 @skip 3365 class Inner(Enum): 3366 __qualname__ = "Outer.Inner" 3367 foo = 10 3368 bar = 11 3369 self.assertTrue(isinstance(Outer.Inner, type)) 3370 self.assertEqual(Outer.a.value, 1) 3371 self.assertEqual(Outer.Inner.foo.value, 10) 3372 self.assertEqual( 3373 list(Outer.Inner), 3374 [Outer.Inner.foo, Outer.Inner.bar], 3375 ) 3376 self.assertEqual( 3377 list(Outer), 3378 [Outer.a, Outer.b], 3379 ) 3380 3381 def test_really_nested_classes_in_enum_are_skipped_with_skip(self): 3382 """Support locally-defined nested classes using @skip""" 3383 class Outer(Enum): 3384 a = 1 3385 b = 2 3386 @skip 3387 class Inner(Enum): 3388 foo = 10 3389 bar = 11 3390 self.assertTrue(isinstance(Outer.Inner, type)) 3391 self.assertEqual(Outer.a.value, 1) 3392 self.assertEqual(Outer.Inner.foo.value, 10) 3393 self.assertEqual( 3394 list(Outer.Inner), 3395 [Outer.Inner.foo, Outer.Inner.bar], 3396 ) 3397 self.assertEqual( 3398 list(Outer), 3399 [Outer.a, Outer.b], 3400 ) 3401 3402 def test_enum_call_without_arg(self): 3403 class Color(Enum): 3404 black = 0 3405 red = 1 3406 green = 2 3407 blue = 3 3408 # 3409 @classmethod 3410 def _missing_value_(cls, value): 3411 if value is no_arg: 3412 return cls.black 3413 self.assertTrue(Color.red is Color(1)) 3414 self.assertTrue(Color.black is Color()) 3415 3416 def test_strict_strenum(self): 3417 from aenum import StrEnum, LowerStrEnum, UpperStrEnum 3418 with self.assertRaisesRegex(TypeError, 'only a single string value may be specified'): 3419 class Huh(StrEnum): 3420 huh = 'this', 'is', 'too', 'many' 3421 3422 for uhoh in (object, object(), [], Enum, 9): 3423 with self.assertRaisesRegex(TypeError, 'values for StrEnum must be strings, not '): 3424 class Huh(StrEnum): 3425 huh = uhoh 3426 3427 class Either(StrEnum): 3428 _order_ = 'this that Those lower upper' 3429 this = auto() 3430 that = 'That' 3431 Those = auto() 3432 lower = 'lower' 3433 upper = 'UPPER' 3434 3435 self.assertEqual([m.value for m in Either], ['this', 'That', 'Those', 'lower', 'UPPER']) 3436 3437 with self.assertRaisesRegex(ValueError, ' is not lower-case'): 3438 class Huh(LowerStrEnum): 3439 huh = 'What' 3440 3441 class Lower(LowerStrEnum): 3442 _order_ = 'this that Those lower upper' 3443 this = auto() 3444 that = 'that' 3445 Those = auto() 3446 lower = 'lower' 3447 upper = 'upper' 3448 3449 self.assertEqual([m.value for m in Lower], ['this', 'that', 'those', 'lower', 'upper']) 3450 3451 with self.assertRaisesRegex(ValueError, ' is not upper-case'): 3452 class Huh(UpperStrEnum): 3453 huh = 'What' 3454 3455 class Upper(UpperStrEnum): 3456 _order_ = 'this that Those lower upper' 3457 this = auto() 3458 that = 'THAT' 3459 Those = auto() 3460 lower = 'LOWER' 3461 upper = 'UPPER' 3462 3463 self.assertEqual([m.value for m in Upper], ['THIS', 'THAT', 'THOSE', 'LOWER', 'UPPER']) 3464 3465 def test_enum_property(self): 3466 class SomeClass(object): 3467 # 3468 an_attr = 97 3469 _attr_x = None 3470 # 3471 def a_method(self, some_number): 3472 return self.an_attr - some_number 3473 # 3474 @property 3475 def attr(self): 3476 return self._attr_x 3477 @attr.setter 3478 def attr(self, value): 3479 self._attr_x = value 3480 # 3481 @classmethod 3482 def a_class_method(cls, another_number, a_string=None): 3483 return a_string * (9 - another_number) 3484 # 3485 @staticmethod 3486 def a_static_method(a, b): 3487 return a * b 3488 # 3489 class SomeEnum(SomeClass, Enum): 3490 _order_ = 'an_attr a_method attr a_class_method a_static_method' 3491 an_attr = 1 3492 a_method = 2 3493 attr = 3 3494 a_class_method = 4 3495 a_static_method = 5 3496 # 3497 SE = SomeEnum 3498 self.assertEqual( 3499 list(SomeEnum), 3500 [SE.an_attr, SE.a_method, SE.attr, SE.a_class_method, SE.a_static_method], 3501 ) 3502 self.assertEqual(SE.an_attr.a_static_method(2, 3), 6) 3503 self.assertEqual(SE.a_method.an_attr, 97) 3504 self.assertEqual(SE.attr.a_class_method(6, 'x'), 'xxx') 3505 self.assertEqual(SE.a_class_method.attr, None) 3506 SE.a_class_method.attr = 99 3507 self.assertEqual(SE.a_class_method.attr, 99) 3508 self.assertEqual(SE.a_method.attr, None) 3509 self.assertEqual(SE.a_static_method.a_method(90), 7) 3510 3511 3512class TestFlag(TestCase): 3513 """Tests of the Flags.""" 3514 3515 class Perm(Flag): 3516 R, W, X = 4, 2, 1 3517 3518 class Color(Flag): 3519 BLACK = 0 3520 RED = 1 3521 GREEN = 2 3522 BLUE = 4 3523 PURPLE = RED|BLUE 3524 3525 class TermColor(str, Flag): 3526 _settings_ = AutoValue 3527 3528 def __new__(cls, value, code): 3529 str_value = '\x1b[%sm' % code 3530 obj = str.__new__(cls, str_value) 3531 obj._value_ = value 3532 obj.code = code 3533 return obj 3534 3535 @classmethod 3536 def _create_pseudo_member_values_(cls, members, *values): 3537 code = ';'.join(m.code for m in members) 3538 return values + (code, ) 3539 3540 AllReset = '0' # ESC [ 0 m # reset all (colors and brightness) 3541 Bright = '1' # ESC [ 1 m # bright 3542 Dim = '2' # ESC [ 2 m # dim (looks same as normal brightness) 3543 Underline = '4' 3544 Normal = '22' # ESC [ 22 m # normal brightness 3545 # 3546 # # FOREGROUND - 30s BACKGROUND - 40s: 3547 FG_Black = '30' # ESC [ 30 m # black 3548 FG_Red = '31' # ESC [ 31 m # red 3549 FG_Green = '32' # ESC [ 32 m # green 3550 FG_Yellow = '33' # ESC [ 33 m # yellow 3551 FG_Blue = '34' # ESC [ 34 m # blue 3552 FG_Magenta = '35' # ESC [ 35 m # magenta 3553 FG_Cyan = '36' # ESC [ 36 m # cyan 3554 FG_White = '37' # ESC [ 37 m # white 3555 FG_Reset = '39' # ESC [ 39 m # reset 3556 # 3557 BG_Black = '40' # ESC [ 30 m # black 3558 BG_Red = '41' # ESC [ 31 m # red 3559 BG_Green = '42' # ESC [ 32 m # green 3560 BG_Yellow = '43' # ESC [ 33 m # yellow 3561 BG_Blue = '44' # ESC [ 34 m # blue 3562 BG_Magenta = '45' # ESC [ 35 m # magenta 3563 BG_Cyan = '46' # ESC [ 36 m # cyan 3564 BG_White = '47' # ESC [ 37 m # white 3565 BG_Reset = '49' # ESC [ 39 m # reset 3566 3567 __str__ = str.__str__ 3568 3569 def __repr__(self): 3570 if self._name_ is not None: 3571 return '<%s.%s>' % (self.__class__.__name__, self._name_) 3572 else: 3573 return '<%s: %s>' % (self.__class__.__name__, '|'.join([m.name for m in Flag.__iter__(self)])) 3574 3575 def __enter__(self): 3576 print(self.AllReset, end='', verbose=0) 3577 return self 3578 3579 def __exit__(self, *args): 3580 print(self.AllReset, end='', verbose=0) 3581 3582 3583 class Open(Flag): 3584 RO = 0 3585 WO = 1 3586 RW = 2 3587 AC = 3 3588 CE = 1<<19 3589 3590 def test_str_is_str_str(self): 3591 red, white = self.TermColor.FG_Red, self.TermColor.BG_White 3592 barber = red | white 3593 self.assertEqual(barber, '\x1b[47;31m') 3594 self.assertEqual(barber.value, red.value | white.value) 3595 self.assertEqual(barber.code, ';'.join([white.code, red.code])) 3596 self.assertEqual(repr(barber), '<TermColor: BG_White|FG_Red>') 3597 self.assertEqual(str(barber), '\x1b[47;31m') 3598 3599 def test_membership(self): 3600 Color = self.Color 3601 Open = self.Open 3602 self.assertRaises(TypeError, lambda: 'BLACK' in Color) 3603 self.assertRaises(TypeError, lambda: 'RO' in Open) 3604 self.assertTrue(Color.BLACK in Color) 3605 self.assertTrue(Open.RO in Open) 3606 self.assertFalse(Color.BLACK in Open) 3607 self.assertFalse(Open.RO in Color) 3608 self.assertRaises(TypeError, lambda: 0 in Color) 3609 self.assertRaises(TypeError, lambda: 0 in Open) 3610 3611 def test_member_contains(self): 3612 Color = self.Color 3613 self.assertRaises(TypeError, lambda: 'test' in Color.BLUE) 3614 self.assertRaises(TypeError, lambda: 2 in Color.BLUE) 3615 self.assertTrue(Color.BLUE in Color.BLUE) 3616 self.assertTrue(Color.BLUE in Color['RED|GREEN|BLUE']) 3617 3618 def test_str(self): 3619 Perm = self.Perm 3620 self.assertEqual(str(Perm.R), 'Perm.R') 3621 self.assertEqual(str(Perm.W), 'Perm.W') 3622 self.assertEqual(str(Perm.X), 'Perm.X') 3623 self.assertEqual(str(Perm.R | Perm.W), 'Perm.R|W') 3624 self.assertEqual(str(Perm.R | Perm.W | Perm.X), 'Perm.R|W|X') 3625 self.assertEqual(str(Perm(0)), 'Perm.0') 3626 self.assertEqual(str(~Perm.R), 'Perm.W|X') 3627 self.assertEqual(str(~Perm.W), 'Perm.R|X') 3628 self.assertEqual(str(~Perm.X), 'Perm.R|W') 3629 self.assertEqual(str(~(Perm.R | Perm.W)), 'Perm.X') 3630 self.assertEqual(str(~(Perm.R | Perm.W | Perm.X)), 'Perm.0') 3631 self.assertEqual(str(Perm(~0)), 'Perm.R|W|X') 3632 3633 Open = self.Open 3634 self.assertEqual(str(Open.RO), 'Open.RO') 3635 self.assertEqual(str(Open.WO), 'Open.WO') 3636 self.assertEqual(str(Open.AC), 'Open.AC') 3637 self.assertEqual(str(Open.RO | Open.CE), 'Open.CE') 3638 self.assertEqual(str(Open.WO | Open.CE), 'Open.CE|WO') 3639 self.assertEqual(str(~Open.RO), 'Open.CE|AC|RW|WO') 3640 self.assertEqual(str(~Open.WO), 'Open.CE|RW') 3641 self.assertEqual(str(~Open.AC), 'Open.CE') 3642 self.assertEqual(str(~(Open.RO | Open.CE)), 'Open.AC') 3643 self.assertEqual(str(~(Open.WO | Open.CE)), 'Open.RW') 3644 3645 def test_repr(self): 3646 Perm = self.Perm 3647 self.assertEqual(repr(Perm.R), '<Perm.R: 4>') 3648 self.assertEqual(repr(Perm.W), '<Perm.W: 2>') 3649 self.assertEqual(repr(Perm.X), '<Perm.X: 1>') 3650 self.assertEqual(repr(Perm.R | Perm.W), '<Perm.R|W: 6>') 3651 self.assertEqual(repr(Perm.R | Perm.W | Perm.X), '<Perm.R|W|X: 7>') 3652 self.assertEqual(repr(Perm(0)), '<Perm.0: 0>') 3653 self.assertEqual(repr(~Perm.R), '<Perm.W|X: 3>') 3654 self.assertEqual(repr(~Perm.W), '<Perm.R|X: 5>') 3655 self.assertEqual(repr(~Perm.X), '<Perm.R|W: 6>') 3656 self.assertEqual(repr(~(Perm.R | Perm.W)), '<Perm.X: 1>') 3657 self.assertEqual(repr(~(Perm.R | Perm.W | Perm.X)), '<Perm.0: 0>') 3658 self.assertEqual(repr(Perm(~0)), '<Perm.R|W|X: 7>') 3659 3660 Open = self.Open 3661 self.assertEqual(repr(Open.RO), '<Open.RO: 0>') 3662 self.assertEqual(repr(Open.WO), '<Open.WO: 1>') 3663 self.assertEqual(repr(Open.AC), '<Open.AC: 3>') 3664 self.assertEqual(repr(Open.RO | Open.CE), '<Open.CE: 524288>') 3665 self.assertEqual(repr(Open.WO | Open.CE), '<Open.CE|WO: 524289>') 3666 self.assertEqual(repr(~Open.RO), '<Open.CE|AC|RW|WO: 524291>') 3667 self.assertEqual(repr(~Open.WO), '<Open.CE|RW: 524290>') 3668 self.assertEqual(repr(~Open.AC), '<Open.CE: 524288>') 3669 self.assertEqual(repr(~(Open.RO | Open.CE)), '<Open.AC: 3>') 3670 self.assertEqual(repr(~(Open.WO | Open.CE)), '<Open.RW: 2>') 3671 3672 def test_name_lookup(self): 3673 Color = self.Color 3674 self.assertTrue(Color.RED is Color['RED']) 3675 self.assertTrue(Color.RED|Color.GREEN is Color['RED|GREEN']) 3676 self.assertTrue(Color.PURPLE is Color['RED|BLUE']) 3677 3678 def test_or(self): 3679 Perm = self.Perm 3680 for i in Perm: 3681 for j in Perm: 3682 self.assertEqual((i | j), Perm(i.value | j.value)) 3683 self.assertEqual((i | j).value, i.value | j.value) 3684 self.assertIs(type(i | j), Perm) 3685 for i in Perm: 3686 self.assertIs(i | i, i) 3687 Open = self.Open 3688 self.assertIs(Open.RO | Open.CE, Open.CE) 3689 3690 def test_and(self): 3691 Perm = self.Perm 3692 RW = Perm.R | Perm.W 3693 RX = Perm.R | Perm.X 3694 WX = Perm.W | Perm.X 3695 RWX = Perm.R | Perm.W | Perm.X 3696 values = list(Perm) + [RW, RX, WX, RWX, Perm(0)] 3697 for i in values: 3698 for j in values: 3699 self.assertEqual((i & j).value, i.value & j.value) 3700 self.assertIs(type(i & j), Perm) 3701 for i in Perm: 3702 self.assertIs(i & i, i) 3703 self.assertIs(i & RWX, i) 3704 self.assertIs(RWX & i, i) 3705 Open = self.Open 3706 self.assertIs(Open.RO & Open.CE, Open.RO) 3707 3708 def test_xor(self): 3709 Perm = self.Perm 3710 for i in Perm: 3711 for j in Perm: 3712 self.assertEqual((i ^ j).value, i.value ^ j.value) 3713 self.assertIs(type(i ^ j), Perm) 3714 for i in Perm: 3715 self.assertIs(i ^ Perm(0), i) 3716 self.assertIs(Perm(0) ^ i, i) 3717 Open = self.Open 3718 self.assertIs(Open.RO ^ Open.CE, Open.CE) 3719 self.assertIs(Open.CE ^ Open.CE, Open.RO) 3720 3721 def test_invert(self): 3722 Perm = self.Perm 3723 RW = Perm.R | Perm.W 3724 RX = Perm.R | Perm.X 3725 WX = Perm.W | Perm.X 3726 RWX = Perm.R | Perm.W | Perm.X 3727 values = list(Perm) + [RW, RX, WX, RWX, Perm(0)] 3728 for i in values: 3729 self.assertIs(type(~i), Perm) 3730 self.assertEqual(~~i, i) 3731 for i in Perm: 3732 self.assertIs(~~i, i) 3733 Open = self.Open 3734 self.assertIs(Open.WO & ~Open.WO, Open.RO) 3735 self.assertIs((Open.WO|Open.CE) & ~Open.WO, Open.CE) 3736 3737 def test_bool(self): 3738 Perm = self.Perm 3739 for f in Perm: 3740 self.assertTrue(f) 3741 Open = self.Open 3742 for f in Open: 3743 self.assertEqual(bool(f.value), bool(f)) 3744 3745 def test_iteration(self): 3746 C = self.Color 3747 self.assertEqual(list(C), [C.BLACK, C.RED, C.GREEN, C.BLUE, C.PURPLE]) 3748 3749 def test_member_iteration(self): 3750 C = self.Color 3751 self.assertEqual(list(C.BLACK), []) 3752 self.assertEqual(list(C.RED), [C.RED]) 3753 self.assertEqual(list(C.PURPLE), [C.BLUE, C.RED]) 3754 3755 def test_programatic_function_string(self): 3756 Perm = Flag('Perm', 'R W X') 3757 lst = list(Perm) 3758 self.assertEqual(len(lst), len(Perm)) 3759 self.assertEqual(len(Perm), 3, Perm) 3760 self.assertEqual(lst, [Perm.R, Perm.W, Perm.X]) 3761 for i, n in enumerate('R W X'.split()): 3762 v = 1<<i 3763 e = Perm(v) 3764 self.assertEqual(e.value, v) 3765 self.assertEqual(type(e.value), int) 3766 self.assertEqual(e.name, n) 3767 self.assertIn(e, Perm) 3768 self.assertIs(type(e), Perm) 3769 3770 def test_programatic_function_string_with_start(self): 3771 Perm = Flag('Perm', 'R W X', start=8) 3772 lst = list(Perm) 3773 self.assertEqual(len(lst), len(Perm)) 3774 self.assertEqual(len(Perm), 3, Perm) 3775 self.assertEqual(lst, [Perm.R, Perm.W, Perm.X]) 3776 for i, n in enumerate('R W X'.split()): 3777 v = 8<<i 3778 e = Perm(v) 3779 self.assertEqual(e.value, v) 3780 self.assertEqual(type(e.value), int) 3781 self.assertEqual(e.name, n) 3782 self.assertIn(e, Perm) 3783 self.assertIs(type(e), Perm) 3784 3785 def test_programatic_function_string_list(self): 3786 Perm = Flag('Perm', ['R', 'W', 'X']) 3787 lst = list(Perm) 3788 self.assertEqual(len(lst), len(Perm)) 3789 self.assertEqual(len(Perm), 3, Perm) 3790 self.assertEqual(lst, [Perm.R, Perm.W, Perm.X]) 3791 for i, n in enumerate('R W X'.split()): 3792 v = 1<<i 3793 e = Perm(v) 3794 self.assertEqual(e.value, v) 3795 self.assertEqual(type(e.value), int) 3796 self.assertEqual(e.name, n) 3797 self.assertIn(e, Perm) 3798 self.assertIs(type(e), Perm) 3799 3800 def test_programatic_function_iterable(self): 3801 Perm = Flag('Perm', (('R', 2), ('W', 8), ('X', 32))) 3802 lst = list(Perm) 3803 self.assertEqual(len(lst), len(Perm)) 3804 self.assertEqual(len(Perm), 3, Perm) 3805 self.assertEqual(lst, [Perm.R, Perm.W, Perm.X]) 3806 for i, n in enumerate('R W X'.split()): 3807 v = 1<<(2*i+1) 3808 e = Perm(v) 3809 self.assertEqual(e.value, v) 3810 self.assertEqual(type(e.value), int) 3811 self.assertEqual(e.name, n) 3812 self.assertIn(e, Perm) 3813 self.assertIs(type(e), Perm) 3814 3815 def test_programatic_function_from_dict(self): 3816 Perm = Flag('Perm', OrderedDict((('R', 2), ('W', 8), ('X', 32)))) 3817 lst = list(Perm) 3818 self.assertEqual(len(lst), len(Perm)) 3819 self.assertEqual(len(Perm), 3, Perm) 3820 self.assertEqual(lst, [Perm.R, Perm.W, Perm.X]) 3821 for i, n in enumerate('R W X'.split()): 3822 v = 1<<(2*i+1) 3823 e = Perm(v) 3824 self.assertEqual(e.value, v) 3825 self.assertEqual(type(e.value), int) 3826 self.assertEqual(e.name, n) 3827 self.assertIn(e, Perm) 3828 self.assertIs(type(e), Perm) 3829 3830 def test_programatic_function_empty_list(self): 3831 Perm = IntFlag('Perm', []) 3832 self.assertEqual(len(list(Perm)), len(Perm)) 3833 self.assertEqual(len(Perm), 0) 3834 Thing = Enum('Thing', []) 3835 self.assertEqual(len(list(Thing)), len(Thing)) 3836 self.assertEqual(len(Thing), 0) 3837 3838 def test_programatic_function_empty_tuple(self): 3839 Perm = IntFlag('Perm', ()) 3840 self.assertEqual(len(list(Perm)), len(Perm)) 3841 self.assertEqual(len(Perm), 0) 3842 Thing = Enum('Thing', ()) 3843 self.assertEqual(len(list(Thing)), len(Thing)) 3844 self.assertEqual(len(Thing), 0) 3845 3846 def test_pickle(self): 3847 if isinstance(FlagStooges, Exception): 3848 raise FlagStooges 3849 test_pickle_dump_load(self.assertIs, FlagStooges.CURLY|FlagStooges.MOE) 3850 test_pickle_dump_load(self.assertIs, FlagStooges) 3851 3852 def test_containment(self): 3853 Perm = self.Perm 3854 R, W, X = Perm 3855 RW = R | W 3856 RX = R | X 3857 WX = W | X 3858 RWX = R | W | X 3859 self.assertTrue(R in RW) 3860 self.assertTrue(R in RX) 3861 self.assertTrue(R in RWX) 3862 self.assertTrue(W in RW) 3863 self.assertTrue(W in WX) 3864 self.assertTrue(W in RWX) 3865 self.assertTrue(X in RX) 3866 self.assertTrue(X in WX) 3867 self.assertTrue(X in RWX) 3868 self.assertFalse(R in WX) 3869 self.assertFalse(W in RX) 3870 self.assertFalse(X in RW) 3871 3872 def test_auto_number(self): 3873 class Color(Flag): 3874 _order_ = 'red blue green' 3875 red = auto() 3876 blue = auto() 3877 green = auto() 3878 3879 self.assertEqual(list(Color), [Color.red, Color.blue, Color.green]) 3880 self.assertEqual(Color.red.value, 1) 3881 self.assertEqual(Color.blue.value, 2) 3882 self.assertEqual(Color.green.value, 4) 3883 3884 def test_auto_number_garbage(self): 3885 with self.assertRaisesRegex(TypeError, 'invalid Flag value: .not an int.'): 3886 class Color(Flag): 3887 _order_ = 'red blue' 3888 red = 'not an int' 3889 blue = auto() 3890 3891 def test_auto_w_pending(self): 3892 class Required(Flag): 3893 _order_ = 'NONE TO_S FROM_S BOTH' 3894 NONE = 0 3895 TO_S = auto() 3896 FROM_S = auto() 3897 BOTH = TO_S | FROM_S 3898 self.assertEqual(Required.TO_S.value, 1) 3899 self.assertEqual(Required.FROM_S.value, 2) 3900 self.assertEqual(Required.BOTH.value, 3) 3901 3902 def test_cascading_failure(self): 3903 class Bizarre(Flag): 3904 c = 3 3905 d = 4 3906 f = 6 3907 # Bizarre.c | Bizarre.d 3908 self.assertRaisesRegex(ValueError, "5 is not a valid Bizarre", Bizarre, 5) 3909 self.assertRaisesRegex(ValueError, "5 is not a valid Bizarre", Bizarre, 5) 3910 self.assertRaisesRegex(ValueError, "2 is not a valid Bizarre", Bizarre, 2) 3911 self.assertRaisesRegex(ValueError, "2 is not a valid Bizarre", Bizarre, 2) 3912 self.assertRaisesRegex(ValueError, "1 is not a valid Bizarre", Bizarre, 1) 3913 self.assertRaisesRegex(ValueError, "1 is not a valid Bizarre", Bizarre, 1) 3914 3915 def test_duplicate_auto(self): 3916 class Dupes(Enum): 3917 _order_ = 'first second third' 3918 first = primero = auto() 3919 second = auto() 3920 third = auto() 3921 self.assertEqual([Dupes.first, Dupes.second, Dupes.third], list(Dupes)) 3922 3923 def test_bizarre(self): 3924 class Bizarre(Flag): 3925 b = 3 3926 c = 4 3927 d = 6 3928 self.assertEqual(repr(Bizarre(7)), '<Bizarre.d|c|b: 7>') 3929 3930 def test_multiple_mixin(self): 3931 class AllMixin(object): 3932 @classproperty 3933 def ALL(cls): 3934 members = list(cls) 3935 all_value = None 3936 if members: 3937 all_value = members[0] 3938 for member in members[1:]: 3939 all_value |= member 3940 cls.ALL = all_value 3941 return all_value 3942 class StrMixin(object): 3943 def __str__(self): 3944 return self._name_.lower() 3945 class Color(AllMixin, Flag): 3946 _order_ = 'RED GREEN BLUE' 3947 RED = auto() 3948 GREEN = auto() 3949 BLUE = auto() 3950 self.assertEqual(Color.RED.value, 1) 3951 self.assertEqual(Color.GREEN.value, 2) 3952 self.assertEqual(Color.BLUE.value, 4) 3953 self.assertEqual(Color.ALL.value, 7) 3954 self.assertEqual(str(Color.BLUE), 'Color.BLUE') 3955 class Color(AllMixin, StrMixin, Flag): 3956 _order_ = 'RED GREEN BLUE' 3957 RED = auto() 3958 GREEN = auto() 3959 BLUE = auto() 3960 self.assertEqual(Color.RED.value, 1) 3961 self.assertEqual(Color.GREEN.value, 2) 3962 self.assertEqual(Color.BLUE.value, 4) 3963 self.assertEqual(Color.ALL.value, 7) 3964 self.assertEqual(str(Color.BLUE), 'blue') 3965 class Color(StrMixin, AllMixin, Flag): 3966 _order_ = 'RED GREEN BLUE' 3967 RED = auto() 3968 GREEN = auto() 3969 BLUE = auto() 3970 self.assertEqual(Color.RED.value, 1) 3971 self.assertEqual(Color.GREEN.value, 2) 3972 self.assertEqual(Color.BLUE.value, 4) 3973 self.assertEqual(Color.ALL.value, 7) 3974 self.assertEqual(str(Color.BLUE), 'blue') 3975 3976 @unittest.skipUnless(threading, 'Threading required for this test.') 3977 def test_unique_composite(self): 3978 # override __eq__ to be identity only 3979 class TestFlag(Flag): 3980 _order_ = 'one two three four five six seven eight' 3981 one = auto() 3982 two = auto() 3983 three = auto() 3984 four = auto() 3985 five = auto() 3986 six = auto() 3987 seven = auto() 3988 eight = auto() 3989 def __eq__(self, other): 3990 return self is other 3991 def __hash__(self): 3992 return hash(self._value_) 3993 # have multiple threads competing to complete the composite members 3994 seen = set() 3995 failed = [False] 3996 def cycle_enum(): 3997 # nonlocal failed 3998 try: 3999 for i in range(256): 4000 seen.add(TestFlag(i)) 4001 except Exception: 4002 failed[0] = True 4003 threads = [ 4004 threading.Thread(target=cycle_enum) 4005 for _ in range(8) 4006 ] 4007 for t in threads: 4008 t.start() 4009 for t in threads: 4010 t.join() 4011 # check that only 248 members were created (8 were created originally) 4012 self.assertFalse( 4013 failed[0], 4014 'at least one thread failed while creating composite members') 4015 self.assertEqual(256, len(seen), 'too many composite members created') 4016 4017 def test_init_with_autovalue_and_generate_next_value(self): 4018 class Color(Flag): 4019 _settings_ = AutoValue 4020 _init_ = 'value code' 4021 def _generate_next_value_(name, start, count, last_values, *args, **kwds): 4022 if not count: 4023 return ((1, start)[start is not None], ) + args 4024 error = False 4025 for last_value_pair in reversed(last_values): 4026 last_value, last_code = last_value_pair 4027 try: 4028 high_bit = aenum._high_bit(last_value) 4029 break 4030 except Exception: 4031 error = True 4032 break 4033 if error: 4034 raise TypeError('Invalid Flag value: %r' % (last_value, )) 4035 return (2 ** (high_bit+1), ) + args 4036 # TODO: actually test _create_pseudo_member 4037 @classmethod 4038 def _create_pseudo_member_(cls, value): 4039 pseudo_member = cls._value2member_map_.get(value, None) 4040 if pseudo_member is None: 4041 members, _ = aenum._decompose(cls, value) 4042 pseudo_member = super(Color, cls)._create_pseudo_member_(value) 4043 pseudo_member.code = ';'.join(m.code for m in members) 4044 return pseudo_member 4045 AllReset = '0' # ESC [ 0 m # reset all (colors and brightness) 4046 Bright = '1' # ESC [ 1 m # bright 4047 Dim = '2' # ESC [ 2 m # dim (looks same as normal brightness) 4048 Underline = '4' 4049 Normal = '22' # ESC [ 22 m # normal brightness 4050 # if we got here, we're good 4051 4052 def test_autovalue_and_generate_next_value(self): 4053 class Color(str, Flag): 4054 _order_ = 'FG_Black FG_Red FG_Green FG_Blue BG_Yellow BG_Magenta BG_Cyan BG_White' 4055 _settings_ = AutoValue 4056 def __new__(cls, value, code): 4057 str_value = '\x1b[%sm' % code 4058 obj = str.__new__(cls, str_value) 4059 obj._value_ = value 4060 obj.code = code 4061 return obj 4062 @staticmethod 4063 def _generate_next_value_(name, start, count, values, *args, **kwds): 4064 return (2 ** count, ) + args 4065 # TODO: actually test _create_pseudo_member 4066 @classmethod 4067 def _create_pseudo_member_(cls, value): 4068 pseudo_member = cls._value2member_map_.get(value, None) 4069 if pseudo_member is None: 4070 # calculate the code 4071 members, _ = aenum._decompose(cls, value) 4072 code = ';'.join(m.code for m in members) 4073 pseudo_member = super(Color, cls)._create_pseudo_member_(value, code) 4074 return pseudo_member 4075 # 4076 # # FOREGROUND - 30s BACKGROUND - 40s: 4077 FG_Black = '30' # ESC [ 30 m # black 4078 FG_Red = '31' # ESC [ 31 m # red 4079 FG_Green = '32' # ESC [ 32 m # green 4080 FG_Blue = '34' # ESC [ 34 m # blue 4081 # 4082 BG_Yellow = '43' # ESC [ 33 m # yellow 4083 BG_Magenta = '45' # ESC [ 35 m # magenta 4084 BG_Cyan = '46' # ESC [ 36 m # cyan 4085 BG_White = '47' # ESC [ 37 m # white 4086 # if we got here, we're good 4087 4088 def test_subclass(self): 4089 class Color(str, Flag): 4090 _order_ = 'FG_Black FG_Red FG_Green FG_Blue BG_Yellow BG_Magenta BG_Cyan BG_White' 4091 _settings_ = AutoValue 4092 def __new__(cls, value, code): 4093 str_value = '\x1b[%sm' % code 4094 obj = str.__new__(cls, str_value) 4095 obj._value_ = value 4096 obj.code = code 4097 return obj 4098 @staticmethod 4099 def _generate_next_value_(name, start, count, values, *args, **kwds): 4100 return (2 ** count, ) + args 4101 @classmethod 4102 def _create_pseudo_member_(cls, value): 4103 pseudo_member = cls._value2member_map_.get(value, None) 4104 if pseudo_member is None: 4105 # calculate the code 4106 members, _ = aenum._decompose(cls, value) 4107 code = ';'.join(m.code for m in members) 4108 pseudo_member = super(Color, cls)._create_pseudo_member_(value, code) 4109 return pseudo_member 4110 # 4111 # # FOREGROUND - 30s BACKGROUND - 40s: 4112 FG_Black = '30' # ESC [ 30 m # black 4113 FG_Red = '31' # ESC [ 31 m # red 4114 FG_Green = '32' # ESC [ 32 m # green 4115 FG_Blue = '34' # ESC [ 34 m # blue 4116 # 4117 BG_Yellow = '43' # ESC [ 33 m # yellow 4118 BG_Magenta = '45' # ESC [ 35 m # magenta 4119 BG_Cyan = '46' # ESC [ 36 m # cyan 4120 BG_White = '47' # ESC [ 37 m # white 4121 self.assertTrue(isinstance(Color.FG_Black, Color)) 4122 self.assertTrue(isinstance(Color.FG_Black, str)) 4123 self.assertEqual(Color.FG_Black, '\x1b[30m') 4124 self.assertEqual(Color.FG_Black.code, '30') 4125 4126 def test_sub_subclass_1(self): 4127 class StrFlag(str, Flag): 4128 _settings_ = AutoValue 4129 def __new__(cls, value, code): 4130 str_value = '\x1b[%sm' % code 4131 obj = str.__new__(cls, str_value) 4132 obj._value_ = value 4133 obj.code = code 4134 return obj 4135 @classmethod 4136 def _create_pseudo_member_(cls, value): 4137 pseudo_member = cls._value2member_map_.get(value, None) 4138 if pseudo_member is None: 4139 # calculate the code 4140 members, _ = aenum._decompose(cls, value) 4141 code = ';'.join(m.code for m in members) 4142 pseudo_member = super(Color, cls)._create_pseudo_member_(value, code) 4143 return pseudo_member 4144 # 4145 class Color(StrFlag): 4146 _order_ = 'FG_Black FG_Red FG_Green FG_Blue BG_Yellow BG_Magenta BG_Cyan BG_White' 4147 # # FOREGROUND - 30s BACKGROUND - 40s: 4148 FG_Black = '30' # ESC [ 30 m # black 4149 FG_Red = '31' # ESC [ 31 m # red 4150 FG_Green = '32' # ESC [ 32 m # green 4151 FG_Blue = '34' # ESC [ 34 m # blue 4152 # 4153 BG_Yellow = '43' # ESC [ 33 m # yellow 4154 BG_Magenta = '45' # ESC [ 35 m # magenta 4155 BG_Cyan = '46' # ESC [ 36 m # cyan 4156 BG_White = '47' # ESC [ 37 m # white 4157 self.assertTrue(isinstance(Color.FG_Black, Color)) 4158 self.assertTrue(isinstance(Color.FG_Black, str)) 4159 self.assertEqual(Color.FG_Black, '\x1b[30m') 4160 self.assertEqual(Color.FG_Black.code, '30') 4161 4162 def test_sub_subclass_2(self): 4163 class StrFlag(str, Flag): 4164 _settings_ = AutoValue 4165 @staticmethod 4166 def _generate_next_value_(name, start, count, values, *args, **kwds): 4167 return (2 ** count, ) + args 4168 @classmethod 4169 def _create_pseudo_member_(cls, value): 4170 pseudo_member = cls._value2member_map_.get(value, None) 4171 if pseudo_member is None: 4172 # calculate the code 4173 members, _ = aenum._decompose(cls, value) 4174 code = ';'.join(m.code for m in members) 4175 pseudo_member = super(Color, cls)._create_pseudo_member_(value, code) 4176 return pseudo_member 4177 # 4178 class Color(StrFlag): 4179 _order_ = 'FG_Black FG_Red FG_Green FG_Blue BG_Yellow BG_Magenta BG_Cyan BG_White' 4180 def __new__(cls, value, code): 4181 str_value = '\x1b[%sm' % code 4182 obj = str.__new__(cls, str_value) 4183 obj._value_ = value 4184 obj.code = code 4185 return obj 4186 # # FOREGROUND - 30s BACKGROUND - 40s: 4187 FG_Black = '30' # ESC [ 30 m # black 4188 FG_Red = '31' # ESC [ 31 m # red 4189 FG_Green = '32' # ESC [ 32 m # green 4190 FG_Blue = '34' # ESC [ 34 m # blue 4191 # 4192 BG_Yellow = '43' # ESC [ 33 m # yellow 4193 BG_Magenta = '45' # ESC [ 35 m # magenta 4194 BG_Cyan = '46' # ESC [ 36 m # cyan 4195 BG_White = '47' # ESC [ 37 m # white 4196 self.assertTrue(isinstance(Color.FG_Black, Color)) 4197 self.assertTrue(isinstance(Color.FG_Black, str)) 4198 self.assertEqual(Color.FG_Black, '\x1b[30m') 4199 self.assertEqual(Color.FG_Black.code, '30') 4200 4201 def test_sub_subclass_3(self): 4202 class StrFlag(str, Flag): 4203 def __new__(cls, value, code): 4204 str_value = '\x1b[%sm' % code 4205 obj = str.__new__(cls, str_value) 4206 obj._value_ = value 4207 obj.code = code 4208 return obj 4209 @classmethod 4210 def _create_pseudo_member_(cls, value): 4211 pseudo_member = cls._value2member_map_.get(value, None) 4212 if pseudo_member is None: 4213 # calculate the code 4214 members, _ = aenum._decompose(cls, value) 4215 code = ';'.join(m.code for m in members) 4216 pseudo_member = super(Color, cls)._create_pseudo_member_(value, code) 4217 return pseudo_member 4218 # 4219 class Color(StrFlag): 4220 _settings_ = AutoValue 4221 _order_ = 'FG_Black FG_Red FG_Green FG_Blue BG_Yellow BG_Magenta BG_Cyan BG_White' 4222 # # FOREGROUND - 30s BACKGROUND - 40s: 4223 FG_Black = '30' # ESC [ 30 m # black 4224 FG_Red = '31' # ESC [ 31 m # red 4225 FG_Green = '32' # ESC [ 32 m # green 4226 FG_Blue = '34' # ESC [ 34 m # blue 4227 # 4228 BG_Yellow = '43' # ESC [ 33 m # yellow 4229 BG_Magenta = '45' # ESC [ 35 m # magenta 4230 BG_Cyan = '46' # ESC [ 36 m # cyan 4231 BG_White = '47' # ESC [ 37 m # white 4232 self.assertTrue(isinstance(Color.FG_Black, Color)) 4233 self.assertTrue(isinstance(Color.FG_Black, str)) 4234 self.assertEqual(Color.FG_Black, '\x1b[30m') 4235 self.assertEqual(Color.FG_Black.code, '30') 4236 4237 def test_sub_subclass_4(self): 4238 class StrFlag(str, Flag): 4239 def __new__(cls, value, code): 4240 str_value = '\x1b[%sm' % code 4241 obj = str.__new__(cls, str_value) 4242 obj._value_ = value 4243 obj.code = code 4244 return obj 4245 @classmethod 4246 def _create_pseudo_member_values_(cls, members, *values): 4247 code = ';'.join(m.code for m in members) 4248 return values + (code, ) 4249 # 4250 class Color(StrFlag): 4251 _settings_ = AutoValue 4252 _order_ = 'FG_Black FG_Red FG_Green FG_Blue BG_Yellow BG_Magenta BG_Cyan BG_White' 4253 # # FOREGROUND - 30s BACKGROUND - 40s: 4254 FG_Black = '30' # ESC [ 30 m # black 4255 FG_Red = '31' # ESC [ 31 m # red 4256 FG_Green = '32' # ESC [ 32 m # green 4257 FG_Blue = '34' # ESC [ 34 m # blue 4258 # 4259 BG_Yellow = '43' # ESC [ 33 m # yellow 4260 BG_Magenta = '45' # ESC [ 35 m # magenta 4261 BG_Cyan = '46' # ESC [ 36 m # cyan 4262 BG_White = '47' # ESC [ 37 m # white 4263 # 4264 def __repr__(self): 4265 if self._name_ is not None: 4266 return '<%s.%s>' % (self.__class__.__name__, self._name_) 4267 else: 4268 return '<%s: %s>' % (self.__class__.__name__, '|'.join([m.name for m in Flag.__iter__(self)])) 4269 self.assertTrue(isinstance(Color.FG_Black, Color)) 4270 self.assertTrue(isinstance(Color.FG_Black, str)) 4271 self.assertEqual(Color.FG_Black, '\x1b[30m') 4272 self.assertEqual(Color.FG_Black.code, '30') 4273 colors = Color.BG_Magenta | Color.FG_Black 4274 self.assertTrue(isinstance(colors, Color)) 4275 self.assertTrue(isinstance(colors, str)) 4276 self.assertEqual(colors, '\x1b[45;30m') 4277 self.assertEqual(colors.code, '45;30') 4278 self.assertEqual(repr(colors), '<Color: BG_Magenta|FG_Black>') 4279 4280 def test_sub_subclass_with_new_new(self): 4281 class StrFlag(str, Flag): 4282 def __new__(cls, value, code): 4283 str_value = '\x1b[%sm' % code 4284 obj = str.__new__(cls, str_value) 4285 obj._value_ = value 4286 obj.code = code 4287 return obj 4288 @classmethod 4289 def _create_pseudo_member_(cls, value): 4290 pseudo_member = cls._value2member_map_.get(value, None) 4291 if pseudo_member is None: 4292 # calculate the code 4293 members, _ = aenum._decompose(cls, value) 4294 code = ';'.join(m.code for m in members) 4295 pseudo_member = super(Color, cls)._create_pseudo_member_(value, code) 4296 return pseudo_member 4297 # 4298 class Color(StrFlag): 4299 _settings_ = AutoValue 4300 _order_ = 'FG_Black FG_Red FG_Green FG_Blue BG_Yellow BG_Magenta BG_Cyan BG_White' 4301 def __new__(cls, value, string, abbr): 4302 str_value = abbr.title() 4303 obj = str.__new__(cls, str_value) 4304 obj._value_ = value 4305 obj.code = string 4306 obj.abbr = abbr 4307 return obj 4308 # # FOREGROUND - 30s BACKGROUND - 40s: 4309 FG_Black = '30', 'blk' # ESC [ 30 m # black 4310 FG_Red = '31', 'red' # ESC [ 31 m # red 4311 FG_Green = '32', 'grn' # ESC [ 32 m # green 4312 FG_Blue = '34', 'blu' # ESC [ 34 m # blue 4313 # 4314 BG_Yellow = '43', 'ylw' # ESC [ 33 m # yellow 4315 BG_Magenta = '45', 'mag' # ESC [ 35 m # magenta 4316 BG_Cyan = '46', 'cyn' # ESC [ 36 m # cyan 4317 BG_White = '47', 'wht' # ESC [ 37 m # white 4318 # 4319 def __repr__(self): 4320 if self._name_ is not None: 4321 return '<%s.%s>' % (self.__class__.__name__, self._name_) 4322 else: 4323 return '<%s: %s>' % (self.__class__.__name__, '|'.join([m.name for m in self])) 4324 self.assertTrue(isinstance(Color.FG_Black, Color)) 4325 self.assertTrue(isinstance(Color.FG_Black, str)) 4326 self.assertEqual(Color.FG_Black, 'Blk', str.__repr__(Color.FG_Black)) 4327 self.assertEqual(Color.FG_Black.abbr, 'blk') 4328 4329 def test_subclass_with_default_new(self): 4330 class MyFlag(str, Flag): 4331 _settings_ = AutoValue 4332 _order_ = 'this these theother' 4333 this = 'that' 4334 these = 'those' 4335 theother = 'thingimibobs' 4336 self.assertEqual(MyFlag.this, 'that') 4337 self.assertEqual(MyFlag.this.value, 1) 4338 self.assertEqual(MyFlag.these, 'those') 4339 self.assertEqual(MyFlag.these.value, 2) 4340 self.assertEqual(MyFlag.theother, 'thingimibobs') 4341 self.assertEqual(MyFlag.theother.value, 4) 4342 4343 def test_extend_flag(self): 4344 class Color(Flag): 4345 BLACK = 0 4346 RED = 1 4347 GREEN = 2 4348 BLUE = 4 4349 extend_enum(Color, 'MAGENTA') 4350 self.assertTrue(Color(8) is Color.MAGENTA) 4351 self.assertTrue(isinstance(Color.MAGENTA, Color)) 4352 self.assertEqual(Color.MAGENTA.value, 8) 4353 extend_enum(Color, 'PURPLE', 11) 4354 self.assertTrue(Color(11) is Color.PURPLE) 4355 self.assertTrue(isinstance(Color.PURPLE, Color)) 4356 self.assertEqual(Color.PURPLE.value, 11) 4357 self.assertTrue(issubclass(Color, Flag)) 4358 4359 def test_extend_flag_subclass(self): 4360 class Color(str, Flag): 4361 _order_ = 'FG_Black FG_Red FG_Green FG_Blue BG_Yellow BG_Magenta BG_Cyan BG_White' 4362 _settings_ = AutoValue 4363 def __new__(cls, value, code=None): 4364 str_value = '\x1b[%sm' % code 4365 obj = str.__new__(cls, str_value) 4366 obj._value_ = value 4367 obj.code = code 4368 return obj 4369 @staticmethod 4370 def _generate_next_value_(name, start, count, values, *args, **kwds): 4371 return (2 ** count, ) + args 4372 @classmethod 4373 def _create_pseudo_member_(cls, value): 4374 pseudo_member = cls._value2member_map_.get(value, None) 4375 if pseudo_member is None: 4376 # calculate the code 4377 members, _ = aenum._decompose(cls, value) 4378 code = ';'.join(m.code for m in members) 4379 pseudo_member = super(Color, cls)._create_pseudo_member_(value, code) 4380 return pseudo_member 4381 # 4382 # # FOREGROUND - 30s BACKGROUND - 40s: 4383 FG_Black = '30' # ESC [ 30 m # black 4384 FG_Red = '31' # ESC [ 31 m # red 4385 FG_Green = '32' # ESC [ 32 m # green 4386 FG_Blue = '34' # ESC [ 34 m # blue 4387 # 4388 BG_Yellow = '43' # ESC [ 33 m # yellow 4389 BG_Magenta = '45' # ESC [ 35 m # magenta 4390 BG_Cyan = '46' # ESC [ 36 m # cyan 4391 BG_White = '47' # ESC [ 37 m # white 4392 # 4393 def __repr__(self): 4394 if self._name_ is not None: 4395 return '<%s.%s>' % (self.__class__.__name__, self._name_) 4396 else: 4397 return '<%s: %s>' % (self.__class__.__name__, '|'.join([m.name for m in self])) 4398 # 4399 Purple = Color.BG_Magenta | Color.FG_Blue 4400 self.assertTrue(isinstance(Purple, Color)) 4401 self.assertTrue(isinstance(Purple, str)) 4402 self.assertIs(Purple, Color.BG_Magenta | Color.FG_Blue) 4403 self.assertEqual(Purple, '\x1b[45;34m') 4404 self.assertEqual(Purple.code, '45;34') 4405 self.assertIs(Purple.name, None) 4406 4407 4408class TestIntFlag(TestCase): 4409 """Tests of the IntFlags.""" 4410 4411 class Perm(IntFlag): 4412 X = 1 << 0 4413 W = 1 << 1 4414 R = 1 << 2 4415 4416 class Color(IntFlag): 4417 BLACK = 0 4418 RED = 1 4419 GREEN = 2 4420 BLUE = 4 4421 PURPLE = RED|BLUE 4422 4423 class Open(IntFlag): 4424 "not a good flag candidate" 4425 RO = 0 4426 WO = 1 4427 RW = 2 4428 AC = 3 4429 CE = 1<<19 4430 4431 def test_membership(self): 4432 Color = self.Color 4433 Open = self.Open 4434 self.assertRaises(TypeError, lambda: 'GREEN' in Color) 4435 self.assertRaises(TypeError, lambda: 'RW' in Open) 4436 self.assertTrue(Color.GREEN in Color) 4437 self.assertTrue(Open.RW in Open) 4438 self.assertFalse(Color.GREEN in Open) 4439 self.assertFalse(Open.RW in Color) 4440 self.assertRaises(TypeError, lambda: 2 in Color) 4441 self.assertRaises(TypeError, lambda: 2 in Open) 4442 4443 def test_member_contains(self): 4444 Color = self.Color 4445 self.assertRaises(TypeError, lambda: 'test' in Color.RED) 4446 self.assertRaises(TypeError, lambda: 1 in Color.RED) 4447 self.assertTrue(Color.RED in Color.RED) 4448 self.assertTrue(Color.RED in Color.PURPLE) 4449 4450 def test_name_lookup(self): 4451 Color = self.Color 4452 self.assertTrue(Color.RED is Color['RED']) 4453 self.assertTrue(Color.RED|Color.GREEN is Color['RED|GREEN']) 4454 self.assertTrue(Color.PURPLE is Color['RED|BLUE']) 4455 4456 def test_type(self): 4457 Perm = self.Perm 4458 Open = self.Open 4459 for f in Perm: 4460 self.assertTrue(isinstance(f, Perm)) 4461 self.assertEqual(f, f.value) 4462 self.assertTrue(isinstance(Perm.W | Perm.X, Perm)) 4463 self.assertEqual(Perm.W | Perm.X, 3) 4464 for f in Open: 4465 self.assertTrue(isinstance(f, Open)) 4466 self.assertEqual(f, f.value) 4467 self.assertTrue(isinstance(Open.WO | Open.RW, Open)) 4468 self.assertEqual(Open.WO | Open.RW, 3) 4469 4470 4471 def test_str(self): 4472 Perm = self.Perm 4473 self.assertEqual(str(Perm.R), 'Perm.R') 4474 self.assertEqual(str(Perm.W), 'Perm.W') 4475 self.assertEqual(str(Perm.X), 'Perm.X') 4476 self.assertEqual(str(Perm.R | Perm.W), 'Perm.R|W') 4477 self.assertEqual(str(Perm.R | Perm.W | Perm.X), 'Perm.R|W|X') 4478 self.assertEqual(str(Perm.R | 8), 'Perm.8|R') 4479 self.assertEqual(str(Perm(0)), 'Perm.0') 4480 self.assertEqual(str(Perm(8)), 'Perm.8') 4481 self.assertEqual(str(~Perm.R), 'Perm.W|X') 4482 self.assertEqual(str(~Perm.W), 'Perm.R|X') 4483 self.assertEqual(str(~Perm.X), 'Perm.R|W') 4484 self.assertEqual(str(~(Perm.R | Perm.W)), 'Perm.X') 4485 self.assertEqual(str(~(Perm.R | Perm.W | Perm.X)), 'Perm.-8') 4486 self.assertEqual(str(~(Perm.R | 8)), 'Perm.W|X') 4487 self.assertEqual(str(Perm(~0)), 'Perm.R|W|X') 4488 self.assertEqual(str(Perm(~8)), 'Perm.R|W|X') 4489 4490 Open = self.Open 4491 self.assertEqual(str(Open.RO), 'Open.RO') 4492 self.assertEqual(str(Open.WO), 'Open.WO') 4493 self.assertEqual(str(Open.AC), 'Open.AC') 4494 self.assertEqual(str(Open.RO | Open.CE), 'Open.CE') 4495 self.assertEqual(str(Open.WO | Open.CE), 'Open.CE|WO') 4496 self.assertEqual(str(Open(4)), 'Open.4') 4497 self.assertEqual(str(~Open.RO), 'Open.CE|AC|RW|WO') 4498 self.assertEqual(str(~Open.WO), 'Open.CE|RW') 4499 self.assertEqual(str(~Open.AC), 'Open.CE') 4500 self.assertEqual(str(~(Open.RO | Open.CE)), 'Open.AC|RW|WO') 4501 self.assertEqual(str(~(Open.WO | Open.CE)), 'Open.RW') 4502 self.assertEqual(str(Open(~4)), 'Open.CE|AC|RW|WO') 4503 4504 def test_repr(self): 4505 Perm = self.Perm 4506 self.assertEqual(repr(Perm.R), '<Perm.R: 4>') 4507 self.assertEqual(repr(Perm.W), '<Perm.W: 2>') 4508 self.assertEqual(repr(Perm.X), '<Perm.X: 1>') 4509 self.assertEqual(repr(Perm.R | Perm.W), '<Perm.R|W: 6>') 4510 self.assertEqual(repr(Perm.R | Perm.W | Perm.X), '<Perm.R|W|X: 7>') 4511 self.assertEqual(repr(Perm.R | 8), '<Perm.8|R: 12>') 4512 self.assertEqual(repr(Perm(0)), '<Perm.0: 0>') 4513 self.assertEqual(repr(Perm(8)), '<Perm.8: 8>') 4514 self.assertEqual(repr(~Perm.R), '<Perm.W|X: -5>') 4515 self.assertEqual(repr(~Perm.W), '<Perm.R|X: -3>') 4516 self.assertEqual(repr(~Perm.X), '<Perm.R|W: -2>') 4517 self.assertEqual(repr(~(Perm.R | Perm.W)), '<Perm.X: -7>') 4518 self.assertEqual(repr(~(Perm.R | Perm.W | Perm.X)), '<Perm.-8: -8>') 4519 self.assertEqual(repr(~(Perm.R | 8)), '<Perm.W|X: -13>') 4520 self.assertEqual(repr(Perm(~0)), '<Perm.R|W|X: -1>') 4521 self.assertEqual(repr(Perm(~8)), '<Perm.R|W|X: -9>') 4522 4523 Open = self.Open 4524 self.assertEqual(repr(Open.RO), '<Open.RO: 0>') 4525 self.assertEqual(repr(Open.WO), '<Open.WO: 1>') 4526 self.assertEqual(repr(Open.AC), '<Open.AC: 3>') 4527 self.assertEqual(repr(Open.RO | Open.CE), '<Open.CE: 524288>') 4528 self.assertEqual(repr(Open.WO | Open.CE), '<Open.CE|WO: 524289>') 4529 self.assertEqual(repr(Open(4)), '<Open.4: 4>') 4530 self.assertEqual(repr(~Open.RO), '<Open.CE|AC|RW|WO: -1>') 4531 self.assertEqual(repr(~Open.WO), '<Open.CE|RW: -2>') 4532 self.assertEqual(repr(~Open.AC), '<Open.CE: -4>') 4533 self.assertEqual(repr(~(Open.RO | Open.CE)), '<Open.AC|RW|WO: -524289>') 4534 self.assertEqual(repr(~(Open.WO | Open.CE)), '<Open.RW: -524290>') 4535 self.assertEqual(repr(Open(~4)), '<Open.CE|AC|RW|WO: -5>') 4536 4537 def test_or(self): 4538 Perm = self.Perm 4539 for i in Perm: 4540 for j in Perm: 4541 self.assertEqual(i | j, i.value | j.value) 4542 self.assertEqual((i | j).value, i.value | j.value) 4543 self.assertIs(type(i | j), Perm) 4544 for j in range(8): 4545 self.assertEqual(i | j, i.value | j) 4546 self.assertEqual((i | j).value, i.value | j) 4547 self.assertIs(type(i | j), Perm) 4548 self.assertEqual(j | i, j | i.value) 4549 self.assertEqual((j | i).value, j | i.value) 4550 self.assertIs(type(j | i), Perm) 4551 for i in Perm: 4552 self.assertIs(i | i, i) 4553 self.assertIs(i | 0, i) 4554 self.assertIs(0 | i, i) 4555 Open = self.Open 4556 self.assertIs(Open.RO | Open.CE, Open.CE) 4557 4558 def test_and(self): 4559 Perm = self.Perm 4560 RW = Perm.R | Perm.W 4561 RX = Perm.R | Perm.X 4562 WX = Perm.W | Perm.X 4563 RWX = Perm.R | Perm.W | Perm.X 4564 values = list(Perm) + [RW, RX, WX, RWX, Perm(0)] 4565 for i in values: 4566 for j in values: 4567 self.assertEqual(i & j, i.value & j.value, 'i is %r, j is %r' % (i, j)) 4568 self.assertEqual((i & j).value, i.value & j.value, 'i is %r, j is %r' % (i, j)) 4569 self.assertIs(type(i & j), Perm, 'i is %r, j is %r' % (i, j)) 4570 for j in range(8): 4571 self.assertEqual(i & j, i.value & j) 4572 self.assertEqual((i & j).value, i.value & j) 4573 self.assertIs(type(i & j), Perm) 4574 self.assertEqual(j & i, j & i.value) 4575 self.assertEqual((j & i).value, j & i.value) 4576 self.assertIs(type(j & i), Perm) 4577 for i in Perm: 4578 self.assertIs(i & i, i) 4579 self.assertIs(i & 7, i) 4580 self.assertIs(7 & i, i) 4581 Open = self.Open 4582 self.assertIs(Open.RO & Open.CE, Open.RO) 4583 4584 def test_xor(self): 4585 Perm = self.Perm 4586 for i in Perm: 4587 for j in Perm: 4588 self.assertEqual(i ^ j, i.value ^ j.value) 4589 self.assertEqual((i ^ j).value, i.value ^ j.value) 4590 self.assertIs(type(i ^ j), Perm) 4591 for j in range(8): 4592 self.assertEqual(i ^ j, i.value ^ j) 4593 self.assertEqual((i ^ j).value, i.value ^ j) 4594 self.assertIs(type(i ^ j), Perm) 4595 self.assertEqual(j ^ i, j ^ i.value) 4596 self.assertEqual((j ^ i).value, j ^ i.value) 4597 self.assertIs(type(j ^ i), Perm) 4598 for i in Perm: 4599 self.assertIs(i ^ 0, i) 4600 self.assertIs(0 ^ i, i) 4601 Open = self.Open 4602 self.assertIs(Open.RO ^ Open.CE, Open.CE) 4603 self.assertIs(Open.CE ^ Open.CE, Open.RO) 4604 4605 def test_invert(self): 4606 Perm = self.Perm 4607 RW = Perm.R | Perm.W 4608 RX = Perm.R | Perm.X 4609 WX = Perm.W | Perm.X 4610 RWX = Perm.R | Perm.W | Perm.X 4611 values = list(Perm) + [RW, RX, WX, RWX, Perm(0)] 4612 for i in values: 4613 self.assertEqual(~i, ~i.value) 4614 self.assertEqual((~i).value, ~i.value) 4615 self.assertIs(type(~i), Perm) 4616 self.assertEqual(~~i, i) 4617 for i in Perm: 4618 self.assertIs(~~i, i) 4619 Open = self.Open 4620 self.assertIs(Open.WO & ~Open.WO, Open.RO) 4621 self.assertIs((Open.WO|Open.CE) & ~Open.WO, Open.CE) 4622 4623 def test_iter(self): 4624 Perm = self.Perm 4625 NoPerm = Perm.R ^ Perm.R 4626 RWX = Perm.R | Perm.W | Perm.X 4627 self.assertEqual(list(NoPerm), []) 4628 self.assertEqual(list(Perm.R), [Perm.R]) 4629 self.assertEqual(list(RWX), [Perm.R, Perm.W, Perm.X]) 4630 4631 def test_programatic_function_string(self): 4632 Perm = IntFlag('Perm', 'R W X') 4633 lst = list(Perm) 4634 self.assertEqual(len(lst), len(Perm)) 4635 self.assertEqual(len(Perm), 3, Perm) 4636 self.assertEqual(lst, [Perm.R, Perm.W, Perm.X]) 4637 for i, n in enumerate('R W X'.split()): 4638 v = 1<<i 4639 e = Perm(v) 4640 self.assertEqual(e.value, v) 4641 self.assertEqual(type(e.value), int) 4642 self.assertEqual(e, v) 4643 self.assertEqual(e.name, n) 4644 self.assertIn(e, Perm) 4645 self.assertIs(type(e), Perm) 4646 4647 def test_programatic_function_string_with_start(self): 4648 Perm = IntFlag('Perm', 'R W X', start=8) 4649 lst = list(Perm) 4650 self.assertEqual(len(lst), len(Perm)) 4651 self.assertEqual(len(Perm), 3, Perm) 4652 self.assertEqual(lst, [Perm.R, Perm.W, Perm.X]) 4653 for i, n in enumerate('R W X'.split()): 4654 v = 8<<i 4655 e = Perm(v) 4656 self.assertEqual(e.value, v) 4657 self.assertEqual(type(e.value), int) 4658 self.assertEqual(e, v) 4659 self.assertEqual(e.name, n) 4660 self.assertIn(e, Perm) 4661 self.assertIs(type(e), Perm) 4662 4663 def test_programatic_function_string_list(self): 4664 Perm = IntFlag('Perm', ['R', 'W', 'X']) 4665 lst = list(Perm) 4666 self.assertEqual(len(lst), len(Perm)) 4667 self.assertEqual(len(Perm), 3, Perm) 4668 self.assertEqual(lst, [Perm.R, Perm.W, Perm.X]) 4669 for i, n in enumerate('R W X'.split()): 4670 v = 1<<i 4671 e = Perm(v) 4672 self.assertEqual(e.value, v) 4673 self.assertEqual(type(e.value), int) 4674 self.assertEqual(e, v) 4675 self.assertEqual(e.name, n) 4676 self.assertIn(e, Perm) 4677 self.assertIs(type(e), Perm) 4678 4679 def test_programatic_function_iterable(self): 4680 Perm = IntFlag('Perm', (('R', 2), ('W', 8), ('X', 32))) 4681 lst = list(Perm) 4682 self.assertEqual(len(lst), len(Perm)) 4683 self.assertEqual(len(Perm), 3, Perm) 4684 self.assertEqual(lst, [Perm.R, Perm.W, Perm.X]) 4685 for i, n in enumerate('R W X'.split()): 4686 v = 1<<(2*i+1) 4687 e = Perm(v) 4688 self.assertEqual(e.value, v) 4689 self.assertEqual(type(e.value), int) 4690 self.assertEqual(e, v) 4691 self.assertEqual(e.name, n) 4692 self.assertIn(e, Perm) 4693 self.assertIs(type(e), Perm) 4694 4695 def test_programatic_function_from_dict(self): 4696 Perm = IntFlag('Perm', OrderedDict((('R', 2), ('W', 8), ('X', 32)))) 4697 lst = list(Perm) 4698 self.assertEqual(len(lst), len(Perm)) 4699 self.assertEqual(len(Perm), 3, Perm) 4700 self.assertEqual(lst, [Perm.R, Perm.W, Perm.X]) 4701 for i, n in enumerate('R W X'.split()): 4702 v = 1<<(2*i+1) 4703 e = Perm(v) 4704 self.assertEqual(e.value, v) 4705 self.assertEqual(type(e.value), int) 4706 self.assertEqual(e, v) 4707 self.assertEqual(e.name, n) 4708 self.assertIn(e, Perm) 4709 self.assertIs(type(e), Perm) 4710 4711 def test_containment(self): 4712 Perm = self.Perm 4713 R, W, X = Perm 4714 RW = R | W 4715 RX = R | X 4716 WX = W | X 4717 RWX = R | W | X 4718 self.assertTrue(R in RW) 4719 self.assertTrue(R in RX) 4720 self.assertTrue(R in RWX) 4721 self.assertTrue(W in RW) 4722 self.assertTrue(W in WX) 4723 self.assertTrue(W in RWX) 4724 self.assertTrue(X in RX) 4725 self.assertTrue(X in WX) 4726 self.assertTrue(X in RWX) 4727 self.assertFalse(R in WX) 4728 self.assertFalse(W in RX) 4729 self.assertFalse(X in RW) 4730 4731 def test_bool(self): 4732 Perm = self.Perm 4733 for f in Perm: 4734 self.assertTrue(f) 4735 Open = self.Open 4736 for f in Open: 4737 self.assertEqual(bool(f.value), bool(f)) 4738 4739 def test_multiple_mixin(self): 4740 class AllMixin(object): 4741 @classproperty 4742 def ALL(cls): 4743 members = list(cls) 4744 all_value = None 4745 if members: 4746 all_value = members[0] 4747 for member in members[1:]: 4748 all_value |= member 4749 cls.ALL = all_value 4750 return all_value 4751 class StrMixin(object): 4752 def __str__(self): 4753 return self._name_.lower() 4754 class Color(AllMixin, IntFlag): 4755 _order_ = 'RED GREEN BLUE' 4756 RED = auto() 4757 GREEN = auto() 4758 BLUE = auto() 4759 self.assertEqual(Color.RED.value, 1) 4760 self.assertEqual(Color.GREEN.value, 2) 4761 self.assertEqual(Color.BLUE.value, 4) 4762 self.assertEqual(Color.ALL.value, 7) 4763 self.assertEqual(str(Color.BLUE), 'Color.BLUE') 4764 class Color(AllMixin, StrMixin, IntFlag): 4765 _order_ = 'RED GREEN BLUE' 4766 RED = auto() 4767 GREEN = auto() 4768 BLUE = auto() 4769 self.assertEqual(Color.RED.value, 1) 4770 self.assertEqual(Color.GREEN.value, 2) 4771 self.assertEqual(Color.BLUE.value, 4) 4772 self.assertEqual(Color.ALL.value, 7) 4773 self.assertEqual(str(Color.BLUE), 'blue') 4774 class Color(StrMixin, AllMixin, IntFlag): 4775 _order_ = 'RED GREEN BLUE' 4776 RED = auto() 4777 GREEN = auto() 4778 BLUE = auto() 4779 self.assertEqual(Color.RED.value, 1) 4780 self.assertEqual(Color.GREEN.value, 2) 4781 self.assertEqual(Color.BLUE.value, 4) 4782 self.assertEqual(Color.ALL.value, 7) 4783 self.assertEqual(str(Color.BLUE), 'blue') 4784 4785 @unittest.skipUnless(threading, 'Threading required for this test.') 4786 def test_unique_composite(self): 4787 # override __eq__ to be identity only 4788 class TestFlag(IntFlag): 4789 _order_ = 'one two three four five six seven eight' 4790 one = auto() 4791 two = auto() 4792 three = auto() 4793 four = auto() 4794 five = auto() 4795 six = auto() 4796 seven = auto() 4797 eight = auto() 4798 def __eq__(self, other): 4799 return self is other 4800 def __hash__(self): 4801 return hash(self._value_) 4802 # have multiple threads competing to complete the composite members 4803 seen = set() 4804 failed = [False] 4805 def cycle_enum(): 4806 # nonlocal failed 4807 try: 4808 for i in range(256): 4809 seen.add(TestFlag(i)) 4810 except Exception: 4811 failed[0] = True 4812 threads = [ 4813 threading.Thread(target=cycle_enum) 4814 for _ in range(8) 4815 ] 4816 for t in threads: 4817 t.start() 4818 for t in threads: 4819 t.join() 4820 # check that only 248 members were created (8 were created originally) 4821 self.assertFalse( 4822 failed[0], 4823 'at least one thread failed while creating composite members') 4824 self.assertEqual(256, len(seen), 'too many composite members created') 4825 4826 4827class TestEmptyAndNonLatinStrings(unittest.TestCase): 4828 4829 def test_empty_string(self): 4830 with self.assertRaises(ValueError): 4831 empty_abc = Enum('empty_abc', ('', 'B', 'C')) 4832 4833 def test_non_latin_character_string(self): 4834 greek_abc = Enum('greek_abc', ('\u03B1', 'B', 'C')) 4835 item = getattr(greek_abc, '\u03B1') 4836 self.assertEqual(item.value, 1) 4837 4838 def test_non_latin_number_string(self): 4839 hebrew_123 = Enum('hebrew_123', ('\u05D0', '2', '3')) 4840 item = getattr(hebrew_123, '\u05D0') 4841 self.assertEqual(item.value, 1) 4842 4843 4844class TestUnique(TestCase): 4845 """2.4 doesn't allow class decorators, use function syntax.""" 4846 4847 def test_unique_clean(self): 4848 class Clean(Enum): 4849 one = 1 4850 two = 'dos' 4851 tres = 4.0 4852 unique(Clean) 4853 class Cleaner(IntEnum): 4854 single = 1 4855 double = 2 4856 triple = 3 4857 unique(Cleaner) 4858 4859 def test_unique_dirty(self): 4860 try: 4861 class Dirty(Enum): 4862 __order__ = 'one two' 4863 one = 1 4864 two = 'dos' 4865 tres = 1 4866 unique(Dirty) 4867 except ValueError: 4868 exc = sys.exc_info()[1] 4869 message = exc.args[0] 4870 self.assertTrue('tres -> one' in message) 4871 4872 try: 4873 class Dirtier(IntEnum): 4874 __order__ = 'single triple' 4875 single = 1 4876 double = 1 4877 triple = 3 4878 turkey = 3 4879 unique(Dirtier) 4880 except ValueError: 4881 exc = sys.exc_info()[1] 4882 message = exc.args[0] 4883 self.assertTrue('double -> single' in message) 4884 self.assertTrue('turkey -> triple' in message) 4885 4886 def test_unique_with_name(self): 4887 @unique 4888 class Silly(Enum): 4889 one = 1 4890 two = 'dos' 4891 name = 3 4892 @unique 4893 class Sillier(IntEnum): 4894 single = 1 4895 name = 2 4896 triple = 3 4897 value = 4 4898 4899 4900class TestNamedTuple(TestCase): 4901 4902 def test_explicit_indexing(self): 4903 class Person(NamedTuple): 4904 age = 0 4905 first = 1 4906 last = 2 4907 p1 = Person(17, 'John', 'Doe') 4908 p2 = Person(21, 'Jane', 'Doe') 4909 self.assertEqual(p1[0], 17) 4910 self.assertEqual(p1[1], 'John') 4911 self.assertEqual(p1[2], 'Doe') 4912 self.assertEqual(p2[0], 21) 4913 self.assertEqual(p2[1], 'Jane') 4914 self.assertEqual(p2[2], 'Doe') 4915 self.assertEqual(p1.age, 17) 4916 self.assertEqual(p1.first, 'John') 4917 self.assertEqual(p1.last, 'Doe') 4918 self.assertEqual(p2.age, 21) 4919 self.assertEqual(p2.first, 'Jane') 4920 self.assertEqual(p2.last, 'Doe') 4921 4922 def test_implicit_indexing(self): 4923 class Person(NamedTuple): 4924 __order__ = "age first last" 4925 age = "person's age" 4926 first = "person's first name" 4927 last = "person's last name" 4928 p1 = Person(17, 'John', 'Doe') 4929 p2 = Person(21, 'Jane', 'Doe') 4930 self.assertEqual(p1[0], 17) 4931 self.assertEqual(p1[1], 'John') 4932 self.assertEqual(p1[2], 'Doe') 4933 self.assertEqual(p2[0], 21) 4934 self.assertEqual(p2[1], 'Jane') 4935 self.assertEqual(p2[2], 'Doe') 4936 self.assertEqual(p1.age, 17) 4937 self.assertEqual(p1.first, 'John') 4938 self.assertEqual(p1.last, 'Doe') 4939 self.assertEqual(p2.age, 21) 4940 self.assertEqual(p2.first, 'Jane') 4941 self.assertEqual(p2.last, 'Doe') 4942 4943 def test_mixed_indexing(self): 4944 class Person(NamedTuple): 4945 __order__ = "age last cars" 4946 age = "person's age" 4947 last = 2, "person's last name" 4948 cars = "person's cars" 4949 p1 = Person(17, 'John', 'Doe', 3) 4950 p2 = Person(21, 'Jane', 'Doe', 9) 4951 self.assertEqual(p1[0], 17) 4952 self.assertEqual(p1[1], 'John') 4953 self.assertEqual(p1[2], 'Doe') 4954 self.assertEqual(p1[3], 3) 4955 self.assertEqual(p2[0], 21) 4956 self.assertEqual(p2[1], 'Jane') 4957 self.assertEqual(p2[2], 'Doe') 4958 self.assertEqual(p2[3], 9) 4959 self.assertEqual(p1.age, 17) 4960 self.assertEqual(p1.last, 'Doe') 4961 self.assertEqual(p1.cars, 3) 4962 self.assertEqual(p2.age, 21) 4963 self.assertEqual(p2.last, 'Doe') 4964 self.assertEqual(p2.cars, 9) 4965 4966 def test_issubclass(self): 4967 class Person(NamedTuple): 4968 age = 0 4969 first = 1 4970 last = 2 4971 self.assertTrue(issubclass(Person, NamedTuple)) 4972 self.assertTrue(issubclass(Person, tuple)) 4973 4974 def test_isinstance(self): 4975 class Person(NamedTuple): 4976 age = 0 4977 first = 1 4978 last = 2 4979 p1 = Person(17, 'John', 'Doe') 4980 self.assertTrue(isinstance(p1, Person)) 4981 self.assertTrue(isinstance(p1, NamedTuple)) 4982 self.assertTrue(isinstance(p1, tuple)) 4983 4984 def test_explicit_indexing_after_functional_api(self): 4985 Person = NamedTuple('Person', (('age', 0), ('first', 1), ('last', 2))) 4986 p1 = Person(17, 'John', 'Doe') 4987 p2 = Person(21, 'Jane', 'Doe') 4988 self.assertEqual(p1[0], 17) 4989 self.assertEqual(p1[1], 'John') 4990 self.assertEqual(p1[2], 'Doe') 4991 self.assertEqual(p2[0], 21) 4992 self.assertEqual(p2[1], 'Jane') 4993 self.assertEqual(p2[2], 'Doe') 4994 self.assertEqual(p1.age, 17) 4995 self.assertEqual(p1.first, 'John') 4996 self.assertEqual(p1.last, 'Doe') 4997 self.assertEqual(p2.age, 21) 4998 self.assertEqual(p2.first, 'Jane') 4999 self.assertEqual(p2.last, 'Doe') 5000 5001 def test_implicit_indexing_after_functional_api(self): 5002 Person = NamedTuple('Person', 'age first last') 5003 p1 = Person(17, 'John', 'Doe') 5004 p2 = Person(21, 'Jane', 'Doe') 5005 self.assertEqual(p1[0], 17) 5006 self.assertEqual(p1[1], 'John') 5007 self.assertEqual(p1[2], 'Doe') 5008 self.assertEqual(p2[0], 21) 5009 self.assertEqual(p2[1], 'Jane') 5010 self.assertEqual(p2[2], 'Doe') 5011 self.assertEqual(p1.age, 17) 5012 self.assertEqual(p1.first, 'John') 5013 self.assertEqual(p1.last, 'Doe') 5014 self.assertEqual(p2.age, 21) 5015 self.assertEqual(p2.first, 'Jane') 5016 self.assertEqual(p2.last, 'Doe') 5017 5018 def test_mixed_indexing_after_functional_api(self): 5019 Person = NamedTuple('Person', (('age', 0), ('last', 2), ('cars', 3))) 5020 p1 = Person(17, 'John', 'Doe', 3) 5021 p2 = Person(21, 'Jane', 'Doe', 9) 5022 self.assertEqual(p1[0], 17) 5023 self.assertEqual(p1[1], 'John') 5024 self.assertEqual(p1[2], 'Doe') 5025 self.assertEqual(p1[3], 3) 5026 self.assertEqual(p2[0], 21) 5027 self.assertEqual(p2[1], 'Jane') 5028 self.assertEqual(p2[2], 'Doe') 5029 self.assertEqual(p2[3], 9) 5030 self.assertEqual(p1.age, 17) 5031 self.assertEqual(p1.last, 'Doe') 5032 self.assertEqual(p1.cars, 3) 5033 self.assertEqual(p2.age, 21) 5034 self.assertEqual(p2.last, 'Doe') 5035 self.assertEqual(p2.cars, 9) 5036 5037 def test_issubclass_after_functional_api(self): 5038 Person = NamedTuple('Person', 'age first last') 5039 self.assertTrue(issubclass(Person, NamedTuple)) 5040 self.assertTrue(issubclass(Person, tuple)) 5041 5042 def test_isinstance_after_functional_api(self): 5043 Person = NamedTuple('Person', 'age first last') 5044 p1 = Person(17, 'John', 'Doe') 5045 self.assertTrue(isinstance(p1, Person)) 5046 self.assertTrue(isinstance(p1, NamedTuple)) 5047 self.assertTrue(isinstance(p1, tuple)) 5048 5049 def test_creation_with_all_keywords(self): 5050 Person = NamedTuple('Person', 'age first last') 5051 p1 = Person(age=17, first='John', last='Doe') 5052 self.assertEqual(p1[0], 17) 5053 self.assertEqual(p1[1], 'John') 5054 self.assertEqual(p1[2], 'Doe') 5055 self.assertEqual(p1.age, 17) 5056 self.assertEqual(p1.first, 'John') 5057 self.assertEqual(p1.last, 'Doe') 5058 5059 def test_creation_with_some_keywords(self): 5060 Person = NamedTuple('Person', 'age first last') 5061 p1 = Person(17, first='John', last='Doe') 5062 self.assertEqual(p1[0], 17) 5063 self.assertEqual(p1[1], 'John') 5064 self.assertEqual(p1[2], 'Doe') 5065 self.assertEqual(p1.age, 17) 5066 self.assertEqual(p1.first, 'John') 5067 self.assertEqual(p1.last, 'Doe') 5068 p1 = Person(17, last='Doe', first='John') 5069 self.assertEqual(p1[0], 17) 5070 self.assertEqual(p1[1], 'John') 5071 self.assertEqual(p1[2], 'Doe') 5072 self.assertEqual(p1.age, 17) 5073 self.assertEqual(p1.first, 'John') 5074 self.assertEqual(p1.last, 'Doe') 5075 5076 def test_custom_new(self): 5077 class Book(NamedTuple): 5078 title = 0 5079 author = 1 5080 genre = 2 5081 def __new__(cls, string): 5082 args = [s.strip() for s in string.split(';')] 5083 return super(Book, cls).__new__(cls, *tuple(args)) 5084 b1 = Book('The Last Mohican; John Doe; Historical') 5085 self.assertEqual(b1.title, 'The Last Mohican') 5086 self.assertEqual(b1.author, 'John Doe') 5087 self.assertEqual(b1.genre, 'Historical') 5088 5089 def test_defaults_in_class(self): 5090 class Character(NamedTuple): 5091 name = 0 5092 gender = 1, None, 'male' 5093 klass = 2, None, 'fighter' 5094 for char in ( 5095 {'name':'John Doe'}, 5096 {'name':'William Pickney', 'klass':'scholar'}, 5097 {'name':'Sarah Doughtery', 'gender':'female'}, 5098 {'name':'Sissy Moonbeam', 'gender':'female', 'klass':'sorceress'}, 5099 ): 5100 c = Character(**char) 5101 for name, value in (('name', None), ('gender','male'), ('klass','fighter')): 5102 if name in char: 5103 value = char[name] 5104 self.assertEqual(getattr(c, name), value) 5105 5106 def test_defaults_in_class_that_are_falsey(self): 5107 class Point(NamedTuple): 5108 x = 0, 'horizondal coordinate', 0 5109 y = 1, 'vertical coordinate', 0 5110 p = Point() 5111 self.assertEqual(p.x, 0) 5112 self.assertEqual(p.y, 0) 5113 5114 def test_pickle_namedtuple_with_module(self): 5115 if isinstance(LifeForm, Exception): 5116 raise LifeForm 5117 lf = LifeForm('this', 'that', 'theother') 5118 test_pickle_dump_load(self.assertEqual, lf) 5119 5120 def test_pickle_namedtuple_without_module(self): 5121 if isinstance(DeathForm, Exception): 5122 raise DeathForm 5123 df = DeathForm('sickly green', '2x4', 'foul') 5124 test_pickle_dump_load(self.assertEqual, df) 5125 5126 def test_subclassing(self): 5127 if isinstance(ThatsIt, Exception): 5128 raise ThatsIt 5129 ti = ThatsIt('Henry', 'Weinhardt') 5130 self.assertEqual(ti.blah, 'Henry') 5131 self.assertTrue(ti.what(), 'Henry') 5132 test_pickle_dump_load(self.assertEqual, ti) 5133 5134 def test_contains(self): 5135 Book = NamedTuple('Book', 'title author genre') 5136 b = Book('Teckla', 'Steven Brust', 'fantasy') 5137 self.assertTrue('Teckla' in b) 5138 self.assertTrue('Steven Brust' in b) 5139 self.assertTrue('fantasy' in b) 5140 5141 def test_fixed_size(self): 5142 class Book(NamedTuple): 5143 _size_ = TupleSize.fixed 5144 title = 0 5145 author = 1 5146 genre = 2 5147 b = Book('Teckla', 'Steven Brust', 'fantasy') 5148 self.assertTrue('Teckla' in b) 5149 self.assertTrue('Steven Brust' in b) 5150 self.assertTrue('fantasy' in b) 5151 self.assertEqual(b.title, 'Teckla') 5152 self.assertEqual(b.author, 'Steven Brust') 5153 self.assertRaises(TypeError, Book, 'Teckla', 'Steven Brust') 5154 self.assertRaises(TypeError, Book, 'Teckla') 5155 5156 def test_minimum_size(self): 5157 class Book(NamedTuple): 5158 _size_ = TupleSize.minimum 5159 title = 0 5160 author = 1 5161 b = Book('Teckla', 'Steven Brust', 'fantasy') 5162 self.assertTrue('Teckla' in b) 5163 self.assertTrue('Steven Brust' in b) 5164 self.assertTrue('fantasy' in b) 5165 self.assertEqual(b.title, 'Teckla') 5166 self.assertEqual(b.author, 'Steven Brust') 5167 b = Book('Teckla', 'Steven Brust') 5168 self.assertTrue('Teckla' in b) 5169 self.assertTrue('Steven Brust' in b) 5170 self.assertEqual(b.title, 'Teckla') 5171 self.assertEqual(b.author, 'Steven Brust') 5172 self.assertRaises(TypeError, Book, 'Teckla') 5173 5174 def test_variable_size(self): 5175 class Book(NamedTuple): 5176 _size_ = TupleSize.variable 5177 title = 0 5178 author = 1 5179 genre = 2 5180 b = Book('Teckla', 'Steven Brust', 'fantasy') 5181 self.assertTrue('Teckla' in b) 5182 self.assertTrue('Steven Brust' in b) 5183 self.assertTrue('fantasy' in b) 5184 self.assertEqual(b.title, 'Teckla') 5185 self.assertEqual(b.author, 'Steven Brust') 5186 self.assertEqual(b.genre, 'fantasy') 5187 b = Book('Teckla', 'Steven Brust') 5188 self.assertTrue('Teckla' in b) 5189 self.assertTrue('Steven Brust' in b) 5190 self.assertEqual(b.title, 'Teckla') 5191 self.assertEqual(b.author, 'Steven Brust') 5192 self.assertRaises(AttributeError, getattr, b, 'genre') 5193 self.assertRaises(TypeError, Book, title='Teckla', genre='fantasy') 5194 self.assertRaises(TypeError, Book, author='Steven Brust') 5195 5196 def test_combining_namedtuples(self): 5197 class Point(NamedTuple): 5198 x = 0, 'horizontal coordinate', 1 5199 y = 1, 'vertical coordinate', -1 5200 class Color(NamedTuple): 5201 r = 0, 'red component', 11 5202 g = 1, 'green component', 29 5203 b = 2, 'blue component', 37 5204 Pixel1 = NamedTuple('Pixel', Point+Color, module=__name__) 5205 class Pixel2(Point, Color): 5206 "a colored dot" 5207 class Pixel3(Point): 5208 r = 2, 'red component', 11 5209 g = 3, 'green component', 29 5210 b = 4, 'blue component', 37 5211 self.assertEqual(Pixel1._fields_, 'x y r g b'.split()) 5212 self.assertEqual(Pixel1.x.__doc__, 'horizontal coordinate') 5213 self.assertEqual(Pixel1.x.default, 1) 5214 self.assertEqual(Pixel1.y.__doc__, 'vertical coordinate') 5215 self.assertEqual(Pixel1.y.default, -1) 5216 self.assertEqual(Pixel1.r.__doc__, 'red component') 5217 self.assertEqual(Pixel1.r.default, 11) 5218 self.assertEqual(Pixel1.g.__doc__, 'green component') 5219 self.assertEqual(Pixel1.g.default, 29) 5220 self.assertEqual(Pixel1.b.__doc__, 'blue component') 5221 self.assertEqual(Pixel1.b.default, 37) 5222 self.assertEqual(Pixel2._fields_, 'x y r g b'.split()) 5223 self.assertEqual(Pixel2.x.__doc__, 'horizontal coordinate') 5224 self.assertEqual(Pixel2.x.default, 1) 5225 self.assertEqual(Pixel2.y.__doc__, 'vertical coordinate') 5226 self.assertEqual(Pixel2.y.default, -1) 5227 self.assertEqual(Pixel2.r.__doc__, 'red component') 5228 self.assertEqual(Pixel2.r.default, 11) 5229 self.assertEqual(Pixel2.g.__doc__, 'green component') 5230 self.assertEqual(Pixel2.g.default, 29) 5231 self.assertEqual(Pixel2.b.__doc__, 'blue component') 5232 self.assertEqual(Pixel2.b.default, 37) 5233 self.assertEqual(Pixel3._fields_, 'x y r g b'.split()) 5234 self.assertEqual(Pixel3.x.__doc__, 'horizontal coordinate') 5235 self.assertEqual(Pixel3.x.default, 1) 5236 self.assertEqual(Pixel3.y.__doc__, 'vertical coordinate') 5237 self.assertEqual(Pixel3.y.default, -1) 5238 self.assertEqual(Pixel3.r.__doc__, 'red component') 5239 self.assertEqual(Pixel3.r.default, 11) 5240 self.assertEqual(Pixel3.g.__doc__, 'green component') 5241 self.assertEqual(Pixel3.g.default, 29) 5242 self.assertEqual(Pixel3.b.__doc__, 'blue component') 5243 self.assertEqual(Pixel3.b.default, 37) 5244 5245 def test_function_api_type(self): 5246 class Tester(NamedTuple): 5247 def howdy(self): 5248 return 'backwards', list(reversed(self)) 5249 Testee = NamedTuple('Testee', 'a c e', type=Tester) 5250 t = Testee(1, 2, 3) 5251 self.assertEqual(t.howdy(), ('backwards', [3, 2, 1])) 5252 5253 def test_asdict(self): 5254 class Point(NamedTuple): 5255 x = 0, 'horizontal coordinate', 1 5256 y = 1, 'vertical coordinate', -1 5257 class Color(NamedTuple): 5258 r = 0, 'red component', 11 5259 g = 1, 'green component', 29 5260 b = 2, 'blue component', 37 5261 Pixel = NamedTuple('Pixel', Point+Color, module=__name__) 5262 pixel = Pixel(99, -101, 255, 128, 0) 5263 self.assertEqual(pixel._asdict(), {'x':99, 'y':-101, 'r':255, 'g':128, 'b':0}) 5264 5265 def test_make(self): 5266 class Point(NamedTuple): 5267 x = 0, 'horizontal coordinate', 1 5268 y = 1, 'vertical coordinate', -1 5269 self.assertEqual(Point(4, 5), (4, 5)) 5270 self.assertEqual(Point._make((4, 5)), (4, 5)) 5271 5272 def test_replace(self): 5273 class Color(NamedTuple): 5274 r = 0, 'red component', 11 5275 g = 1, 'green component', 29 5276 b = 2, 'blue component', 37 5277 purple = Color(127, 0, 127) 5278 mid_gray = purple._replace(g=127) 5279 self.assertEqual(mid_gray, (127, 127, 127)) 5280 5281 5282class TestNamedConstant(TestCase): 5283 5284 def test_constantness(self): 5285 class K(NamedConstant): 5286 PI = 3.141596 5287 TAU = 2 * PI 5288 self.assertEqual(K.PI, 3.141596) 5289 self.assertEqual(K.TAU, 2 * K.PI) 5290 with self.assertRaisesRegex(AttributeError, 'cannot rebind constant'): 5291 K.PI = 9 5292 with self.assertRaisesRegex(AttributeError, 'cannot delete constant'): 5293 del K.PI 5294 with self.assertRaisesRegex(AttributeError, 'cannot rebind constant'): 5295 K('PI', 3) 5296 5297 def test_duplicates(self): 5298 class CardNumber(NamedConstant): 5299 ACE = 11 5300 TWO = 2 5301 THREE = 3 5302 FOUR = 4 5303 FIVE = 5 5304 SIX = 6 5305 SEVEN = 7 5306 EIGHT = 8 5307 NINE = 9 5308 TEN = 10 5309 JACK = 10 5310 QUEEN = 10 5311 KING = 10 5312 self.assertFalse(CardNumber.TEN is CardNumber.JACK) 5313 self.assertEqual(CardNumber.TEN, CardNumber.JACK) 5314 self.assertEqual(CardNumber.TEN, 10) 5315 5316 def test_extend_constants(self): 5317 class CardSuit(NamedConstant): 5318 HEARTS = 1 5319 SPADES = 2 5320 DIAMONTS = 3 5321 CLUBS = 4 5322 self.assertEqual(CardSuit.HEARTS, 1) 5323 stars = CardSuit('STARS', 5) 5324 self.assertIs(stars, CardSuit.STARS) 5325 self.assertEqual(CardSuit.STARS, 5) 5326 5327 def test_constant_with_docstring(self): 5328 class Stuff(NamedConstant): 5329 Artifact = constant(7, "lucky number!") 5330 Bowling = 11 5331 HillWomp = constant(29, 'blah blah') 5332 self.assertEqual(Stuff.Artifact, 7) 5333 self.assertEqual(Stuff.Artifact.__doc__, 'lucky number!') 5334 self.assertEqual(Stuff.Bowling, 11) 5335 self.assertEqual(Stuff.Bowling.__doc__, None) 5336 self.assertEqual(Stuff.HillWomp, 29) 5337 self.assertEqual(Stuff.HillWomp.__doc__, 'blah blah') 5338 5339 def test_deep_copy(self): 5340 import copy 5341 class APITypes(aenum.Constant): 5342 STRING = "string" 5343 INT = "int" 5344 APITypes('string') 5345 d = {"first": APITypes.STRING} 5346 copy.deepcopy(d) 5347 self.assertTrue(d['first'] is APITypes.STRING) 5348 5349 def test_subclass_w_same_value(self): 5350 class Foo(aenum.Constant): 5351 BLA = 'bla1' 5352 ABA = 'aba1' 5353 class Bar(aenum.Constant): 5354 BLA = Foo.BLA 5355 ABA = 'aba2' 5356 self.assertEqual(Foo.BLA, Bar.BLA) 5357 self.assertFalse(Foo.BLA is Bar.BLA) 5358 5359# These are unordered here on purpose to ensure that declaration order 5360# makes no difference. 5361CONVERT_TEST_NAME_D = 5 5362CONVERT_TEST_NAME_C = 5 5363CONVERT_TEST_NAME_B = 5 5364CONVERT_TEST_NAME_A = 5 # This one should sort first. 5365CONVERT_TEST_NAME_E = 5 5366CONVERT_TEST_NAME_F = 5 5367CONVERT_TEST_SIGABRT = 4 # and this one 5368CONVERT_TEST_SIGIOT = 4 5369CONVERT_TEST_EIO = 7 5370CONVERT_TEST_EBUS = 7 # and this one 5371 5372class TestIntEnumConvert(TestCase): 5373 def test_convert_value_lookup_priority(self): 5374 test_type = IntEnum._convert( 5375 'UnittestConvert', 5376 '__main__', 5377 filter=lambda x: x.startswith('CONVERT_TEST_')) 5378 # We don't want the reverse lookup value to vary when there are 5379 # multiple possible names for a given value. It should always 5380 # report the first lexigraphical name in that case. 5381 self.assertEqual(test_type(5).name, 'CONVERT_TEST_NAME_A') 5382 self.assertEqual(test_type(4).name, 'CONVERT_TEST_SIGABRT') 5383 self.assertEqual(test_type(7).name, 'CONVERT_TEST_EBUS') 5384 self.assertEqual( 5385 list(test_type), 5386 [ 5387 test_type.CONVERT_TEST_SIGABRT, 5388 test_type.CONVERT_TEST_NAME_A, 5389 test_type.CONVERT_TEST_EBUS, 5390 ], 5391 ) 5392 5393 def test_convert(self): 5394 test_type = IntEnum._convert( 5395 'UnittestConvert', 5396 '__main__', 5397 filter=lambda x: x.startswith('CONVERT_TEST_')) 5398 # Ensure that test_type has all of the desired names and values. 5399 self.assertEqual(test_type.CONVERT_TEST_NAME_F, 5400 test_type.CONVERT_TEST_NAME_A) 5401 self.assertEqual(test_type.CONVERT_TEST_NAME_B, 5) 5402 self.assertEqual(test_type.CONVERT_TEST_NAME_C, 5) 5403 self.assertEqual(test_type.CONVERT_TEST_NAME_D, 5) 5404 self.assertEqual(test_type.CONVERT_TEST_NAME_E, 5) 5405 # Ensure that test_type only picked up names matching the filter. 5406 self.assertEqual([name for name in dir(test_type) 5407 if name[0:2] not in ('CO', '__')], 5408 [], msg='Names other than CONVERT_TEST_* found.') 5409 5410 5411class TestStarImport(TestCase): 5412 5413 def test_all_exports_names(self): 5414 scope = {} 5415 exec('from aenum import *', scope, scope) 5416 self.assertIn('Enum', scope) 5417 5418 5419if __name__ == '__main__': 5420 tempdir = tempfile.mkdtemp() 5421 try: 5422 unittest.main() 5423 finally: 5424 shutil.rmtree(tempdir, True) 5425 5426