1"Test the functionality of Python classes implementing operators." 2 3import unittest 4 5 6testmeths = [ 7 8# Binary operations 9 "add", 10 "radd", 11 "sub", 12 "rsub", 13 "mul", 14 "rmul", 15 "matmul", 16 "rmatmul", 17 "truediv", 18 "rtruediv", 19 "floordiv", 20 "rfloordiv", 21 "mod", 22 "rmod", 23 "divmod", 24 "rdivmod", 25 "pow", 26 "rpow", 27 "rshift", 28 "rrshift", 29 "lshift", 30 "rlshift", 31 "and", 32 "rand", 33 "or", 34 "ror", 35 "xor", 36 "rxor", 37 38# List/dict operations 39 "contains", 40 "getitem", 41 "setitem", 42 "delitem", 43 44# Unary operations 45 "neg", 46 "pos", 47 "abs", 48 49# generic operations 50 "init", 51 ] 52 53# These need to return something other than None 54# "hash", 55# "str", 56# "repr", 57# "int", 58# "float", 59 60# These are separate because they can influence the test of other methods. 61# "getattr", 62# "setattr", 63# "delattr", 64 65callLst = [] 66def trackCall(f): 67 def track(*args, **kwargs): 68 callLst.append((f.__name__, args)) 69 return f(*args, **kwargs) 70 return track 71 72statictests = """ 73@trackCall 74def __hash__(self, *args): 75 return hash(id(self)) 76 77@trackCall 78def __str__(self, *args): 79 return "AllTests" 80 81@trackCall 82def __repr__(self, *args): 83 return "AllTests" 84 85@trackCall 86def __int__(self, *args): 87 return 1 88 89@trackCall 90def __index__(self, *args): 91 return 1 92 93@trackCall 94def __float__(self, *args): 95 return 1.0 96 97@trackCall 98def __eq__(self, *args): 99 return True 100 101@trackCall 102def __ne__(self, *args): 103 return False 104 105@trackCall 106def __lt__(self, *args): 107 return False 108 109@trackCall 110def __le__(self, *args): 111 return True 112 113@trackCall 114def __gt__(self, *args): 115 return False 116 117@trackCall 118def __ge__(self, *args): 119 return True 120""" 121 122# Synthesize all the other AllTests methods from the names in testmeths. 123 124method_template = """\ 125@trackCall 126def __%s__(self, *args): 127 pass 128""" 129 130d = {} 131exec(statictests, globals(), d) 132for method in testmeths: 133 exec(method_template % method, globals(), d) 134AllTests = type("AllTests", (object,), d) 135del d, statictests, method, method_template 136 137class ClassTests(unittest.TestCase): 138 def setUp(self): 139 callLst[:] = [] 140 141 def assertCallStack(self, expected_calls): 142 actualCallList = callLst[:] # need to copy because the comparison below will add 143 # additional calls to callLst 144 if expected_calls != actualCallList: 145 self.fail("Expected call list:\n %s\ndoes not match actual call list\n %s" % 146 (expected_calls, actualCallList)) 147 148 def testInit(self): 149 foo = AllTests() 150 self.assertCallStack([("__init__", (foo,))]) 151 152 def testBinaryOps(self): 153 testme = AllTests() 154 # Binary operations 155 156 callLst[:] = [] 157 testme + 1 158 self.assertCallStack([("__add__", (testme, 1))]) 159 160 callLst[:] = [] 161 1 + testme 162 self.assertCallStack([("__radd__", (testme, 1))]) 163 164 callLst[:] = [] 165 testme - 1 166 self.assertCallStack([("__sub__", (testme, 1))]) 167 168 callLst[:] = [] 169 1 - testme 170 self.assertCallStack([("__rsub__", (testme, 1))]) 171 172 callLst[:] = [] 173 testme * 1 174 self.assertCallStack([("__mul__", (testme, 1))]) 175 176 callLst[:] = [] 177 1 * testme 178 self.assertCallStack([("__rmul__", (testme, 1))]) 179 180 callLst[:] = [] 181 testme @ 1 182 self.assertCallStack([("__matmul__", (testme, 1))]) 183 184 callLst[:] = [] 185 1 @ testme 186 self.assertCallStack([("__rmatmul__", (testme, 1))]) 187 188 callLst[:] = [] 189 testme / 1 190 self.assertCallStack([("__truediv__", (testme, 1))]) 191 192 193 callLst[:] = [] 194 1 / testme 195 self.assertCallStack([("__rtruediv__", (testme, 1))]) 196 197 callLst[:] = [] 198 testme // 1 199 self.assertCallStack([("__floordiv__", (testme, 1))]) 200 201 202 callLst[:] = [] 203 1 // testme 204 self.assertCallStack([("__rfloordiv__", (testme, 1))]) 205 206 callLst[:] = [] 207 testme % 1 208 self.assertCallStack([("__mod__", (testme, 1))]) 209 210 callLst[:] = [] 211 1 % testme 212 self.assertCallStack([("__rmod__", (testme, 1))]) 213 214 215 callLst[:] = [] 216 divmod(testme,1) 217 self.assertCallStack([("__divmod__", (testme, 1))]) 218 219 callLst[:] = [] 220 divmod(1, testme) 221 self.assertCallStack([("__rdivmod__", (testme, 1))]) 222 223 callLst[:] = [] 224 testme ** 1 225 self.assertCallStack([("__pow__", (testme, 1))]) 226 227 callLst[:] = [] 228 1 ** testme 229 self.assertCallStack([("__rpow__", (testme, 1))]) 230 231 callLst[:] = [] 232 testme >> 1 233 self.assertCallStack([("__rshift__", (testme, 1))]) 234 235 callLst[:] = [] 236 1 >> testme 237 self.assertCallStack([("__rrshift__", (testme, 1))]) 238 239 callLst[:] = [] 240 testme << 1 241 self.assertCallStack([("__lshift__", (testme, 1))]) 242 243 callLst[:] = [] 244 1 << testme 245 self.assertCallStack([("__rlshift__", (testme, 1))]) 246 247 callLst[:] = [] 248 testme & 1 249 self.assertCallStack([("__and__", (testme, 1))]) 250 251 callLst[:] = [] 252 1 & testme 253 self.assertCallStack([("__rand__", (testme, 1))]) 254 255 callLst[:] = [] 256 testme | 1 257 self.assertCallStack([("__or__", (testme, 1))]) 258 259 callLst[:] = [] 260 1 | testme 261 self.assertCallStack([("__ror__", (testme, 1))]) 262 263 callLst[:] = [] 264 testme ^ 1 265 self.assertCallStack([("__xor__", (testme, 1))]) 266 267 callLst[:] = [] 268 1 ^ testme 269 self.assertCallStack([("__rxor__", (testme, 1))]) 270 271 def testListAndDictOps(self): 272 testme = AllTests() 273 274 # List/dict operations 275 276 class Empty: pass 277 278 try: 279 1 in Empty() 280 self.fail('failed, should have raised TypeError') 281 except TypeError: 282 pass 283 284 callLst[:] = [] 285 1 in testme 286 self.assertCallStack([('__contains__', (testme, 1))]) 287 288 callLst[:] = [] 289 testme[1] 290 self.assertCallStack([('__getitem__', (testme, 1))]) 291 292 callLst[:] = [] 293 testme[1] = 1 294 self.assertCallStack([('__setitem__', (testme, 1, 1))]) 295 296 callLst[:] = [] 297 del testme[1] 298 self.assertCallStack([('__delitem__', (testme, 1))]) 299 300 callLst[:] = [] 301 testme[:42] 302 self.assertCallStack([('__getitem__', (testme, slice(None, 42)))]) 303 304 callLst[:] = [] 305 testme[:42] = "The Answer" 306 self.assertCallStack([('__setitem__', (testme, slice(None, 42), 307 "The Answer"))]) 308 309 callLst[:] = [] 310 del testme[:42] 311 self.assertCallStack([('__delitem__', (testme, slice(None, 42)))]) 312 313 callLst[:] = [] 314 testme[2:1024:10] 315 self.assertCallStack([('__getitem__', (testme, slice(2, 1024, 10)))]) 316 317 callLst[:] = [] 318 testme[2:1024:10] = "A lot" 319 self.assertCallStack([('__setitem__', (testme, slice(2, 1024, 10), 320 "A lot"))]) 321 callLst[:] = [] 322 del testme[2:1024:10] 323 self.assertCallStack([('__delitem__', (testme, slice(2, 1024, 10)))]) 324 325 callLst[:] = [] 326 testme[:42, ..., :24:, 24, 100] 327 self.assertCallStack([('__getitem__', (testme, (slice(None, 42, None), 328 Ellipsis, 329 slice(None, 24, None), 330 24, 100)))]) 331 callLst[:] = [] 332 testme[:42, ..., :24:, 24, 100] = "Strange" 333 self.assertCallStack([('__setitem__', (testme, (slice(None, 42, None), 334 Ellipsis, 335 slice(None, 24, None), 336 24, 100), "Strange"))]) 337 callLst[:] = [] 338 del testme[:42, ..., :24:, 24, 100] 339 self.assertCallStack([('__delitem__', (testme, (slice(None, 42, None), 340 Ellipsis, 341 slice(None, 24, None), 342 24, 100)))]) 343 344 def testUnaryOps(self): 345 testme = AllTests() 346 347 callLst[:] = [] 348 -testme 349 self.assertCallStack([('__neg__', (testme,))]) 350 callLst[:] = [] 351 +testme 352 self.assertCallStack([('__pos__', (testme,))]) 353 callLst[:] = [] 354 abs(testme) 355 self.assertCallStack([('__abs__', (testme,))]) 356 callLst[:] = [] 357 int(testme) 358 self.assertCallStack([('__int__', (testme,))]) 359 callLst[:] = [] 360 float(testme) 361 self.assertCallStack([('__float__', (testme,))]) 362 callLst[:] = [] 363 oct(testme) 364 self.assertCallStack([('__index__', (testme,))]) 365 callLst[:] = [] 366 hex(testme) 367 self.assertCallStack([('__index__', (testme,))]) 368 369 370 def testMisc(self): 371 testme = AllTests() 372 373 callLst[:] = [] 374 hash(testme) 375 self.assertCallStack([('__hash__', (testme,))]) 376 377 callLst[:] = [] 378 repr(testme) 379 self.assertCallStack([('__repr__', (testme,))]) 380 381 callLst[:] = [] 382 str(testme) 383 self.assertCallStack([('__str__', (testme,))]) 384 385 callLst[:] = [] 386 testme == 1 387 self.assertCallStack([('__eq__', (testme, 1))]) 388 389 callLst[:] = [] 390 testme < 1 391 self.assertCallStack([('__lt__', (testme, 1))]) 392 393 callLst[:] = [] 394 testme > 1 395 self.assertCallStack([('__gt__', (testme, 1))]) 396 397 callLst[:] = [] 398 testme != 1 399 self.assertCallStack([('__ne__', (testme, 1))]) 400 401 callLst[:] = [] 402 1 == testme 403 self.assertCallStack([('__eq__', (1, testme))]) 404 405 callLst[:] = [] 406 1 < testme 407 self.assertCallStack([('__gt__', (1, testme))]) 408 409 callLst[:] = [] 410 1 > testme 411 self.assertCallStack([('__lt__', (1, testme))]) 412 413 callLst[:] = [] 414 1 != testme 415 self.assertCallStack([('__ne__', (1, testme))]) 416 417 418 def testGetSetAndDel(self): 419 # Interfering tests 420 class ExtraTests(AllTests): 421 @trackCall 422 def __getattr__(self, *args): 423 return "SomeVal" 424 425 @trackCall 426 def __setattr__(self, *args): 427 pass 428 429 @trackCall 430 def __delattr__(self, *args): 431 pass 432 433 testme = ExtraTests() 434 435 callLst[:] = [] 436 testme.spam 437 self.assertCallStack([('__getattr__', (testme, "spam"))]) 438 439 callLst[:] = [] 440 testme.eggs = "spam, spam, spam and ham" 441 self.assertCallStack([('__setattr__', (testme, "eggs", 442 "spam, spam, spam and ham"))]) 443 444 callLst[:] = [] 445 del testme.cardinal 446 self.assertCallStack([('__delattr__', (testme, "cardinal"))]) 447 448 def testDel(self): 449 x = [] 450 451 class DelTest: 452 def __del__(self): 453 x.append("crab people, crab people") 454 testme = DelTest() 455 del testme 456 import gc 457 gc.collect() 458 self.assertEqual(["crab people, crab people"], x) 459 460 def testBadTypeReturned(self): 461 # return values of some method are type-checked 462 class BadTypeClass: 463 def __int__(self): 464 return None 465 __float__ = __int__ 466 __complex__ = __int__ 467 __str__ = __int__ 468 __repr__ = __int__ 469 __bytes__ = __int__ 470 __bool__ = __int__ 471 __index__ = __int__ 472 def index(x): 473 return [][x] 474 475 for f in [float, complex, str, repr, bytes, bin, oct, hex, bool, index]: 476 self.assertRaises(TypeError, f, BadTypeClass()) 477 478 def testHashStuff(self): 479 # Test correct errors from hash() on objects with comparisons but 480 # no __hash__ 481 482 class C0: 483 pass 484 485 hash(C0()) # This should work; the next two should raise TypeError 486 487 class C2: 488 def __eq__(self, other): return 1 489 490 self.assertRaises(TypeError, hash, C2()) 491 492 493 def testSFBug532646(self): 494 # Test for SF bug 532646 495 496 class A: 497 pass 498 A.__call__ = A() 499 a = A() 500 501 try: 502 a() # This should not segfault 503 except RecursionError: 504 pass 505 else: 506 self.fail("Failed to raise RecursionError") 507 508 def testForExceptionsRaisedInInstanceGetattr2(self): 509 # Tests for exceptions raised in instance_getattr2(). 510 511 def booh(self): 512 raise AttributeError("booh") 513 514 class A: 515 a = property(booh) 516 try: 517 A().a # Raised AttributeError: A instance has no attribute 'a' 518 except AttributeError as x: 519 if str(x) != "booh": 520 self.fail("attribute error for A().a got masked: %s" % x) 521 522 class E: 523 __eq__ = property(booh) 524 E() == E() # In debug mode, caused a C-level assert() to fail 525 526 class I: 527 __init__ = property(booh) 528 try: 529 # In debug mode, printed XXX undetected error and 530 # raises AttributeError 531 I() 532 except AttributeError: 533 pass 534 else: 535 self.fail("attribute error for I.__init__ got masked") 536 537 def assertNotOrderable(self, a, b): 538 with self.assertRaises(TypeError): 539 a < b 540 with self.assertRaises(TypeError): 541 a > b 542 with self.assertRaises(TypeError): 543 a <= b 544 with self.assertRaises(TypeError): 545 a >= b 546 547 def testHashComparisonOfMethods(self): 548 # Test comparison and hash of methods 549 class A: 550 def __init__(self, x): 551 self.x = x 552 def f(self): 553 pass 554 def g(self): 555 pass 556 def __eq__(self, other): 557 return True 558 def __hash__(self): 559 raise TypeError 560 class B(A): 561 pass 562 563 a1 = A(1) 564 a2 = A(1) 565 self.assertTrue(a1.f == a1.f) 566 self.assertFalse(a1.f != a1.f) 567 self.assertFalse(a1.f == a2.f) 568 self.assertTrue(a1.f != a2.f) 569 self.assertFalse(a1.f == a1.g) 570 self.assertTrue(a1.f != a1.g) 571 self.assertNotOrderable(a1.f, a1.f) 572 self.assertEqual(hash(a1.f), hash(a1.f)) 573 574 self.assertFalse(A.f == a1.f) 575 self.assertTrue(A.f != a1.f) 576 self.assertFalse(A.f == A.g) 577 self.assertTrue(A.f != A.g) 578 self.assertTrue(B.f == A.f) 579 self.assertFalse(B.f != A.f) 580 self.assertNotOrderable(A.f, A.f) 581 self.assertEqual(hash(B.f), hash(A.f)) 582 583 # the following triggers a SystemError in 2.4 584 a = A(hash(A.f)^(-1)) 585 hash(a.f) 586 587 def testSetattrWrapperNameIntern(self): 588 # Issue #25794: __setattr__ should intern the attribute name 589 class A: 590 pass 591 592 def add(self, other): 593 return 'summa' 594 595 name = str(b'__add__', 'ascii') # shouldn't be optimized 596 self.assertIsNot(name, '__add__') # not interned 597 type.__setattr__(A, name, add) 598 self.assertEqual(A() + 1, 'summa') 599 600 name2 = str(b'__add__', 'ascii') 601 self.assertIsNot(name2, '__add__') 602 self.assertIsNot(name2, name) 603 type.__delattr__(A, name2) 604 with self.assertRaises(TypeError): 605 A() + 1 606 607 def testSetattrNonStringName(self): 608 class A: 609 pass 610 611 with self.assertRaises(TypeError): 612 type.__setattr__(A, b'x', None) 613 614 def testConstructorErrorMessages(self): 615 # bpo-31506: Improves the error message logic for object_new & object_init 616 617 # Class without any method overrides 618 class C: 619 pass 620 621 error_msg = r'C.__init__\(\) takes exactly one argument \(the instance to initialize\)' 622 623 with self.assertRaisesRegex(TypeError, r'C\(\) takes no arguments'): 624 C(42) 625 626 with self.assertRaisesRegex(TypeError, r'C\(\) takes no arguments'): 627 C.__new__(C, 42) 628 629 with self.assertRaisesRegex(TypeError, error_msg): 630 C().__init__(42) 631 632 with self.assertRaisesRegex(TypeError, r'C\(\) takes no arguments'): 633 object.__new__(C, 42) 634 635 with self.assertRaisesRegex(TypeError, error_msg): 636 object.__init__(C(), 42) 637 638 # Class with both `__init__` & `__new__` method overridden 639 class D: 640 def __new__(cls, *args, **kwargs): 641 super().__new__(cls, *args, **kwargs) 642 def __init__(self, *args, **kwargs): 643 super().__init__(*args, **kwargs) 644 645 error_msg = r'object.__new__\(\) takes exactly one argument \(the type to instantiate\)' 646 647 with self.assertRaisesRegex(TypeError, error_msg): 648 D(42) 649 650 with self.assertRaisesRegex(TypeError, error_msg): 651 D.__new__(D, 42) 652 653 with self.assertRaisesRegex(TypeError, error_msg): 654 object.__new__(D, 42) 655 656 # Class that only overrides __init__ 657 class E: 658 def __init__(self, *args, **kwargs): 659 super().__init__(*args, **kwargs) 660 661 error_msg = r'object.__init__\(\) takes exactly one argument \(the instance to initialize\)' 662 663 with self.assertRaisesRegex(TypeError, error_msg): 664 E().__init__(42) 665 666 with self.assertRaisesRegex(TypeError, error_msg): 667 object.__init__(E(), 42) 668 669if __name__ == '__main__': 670 unittest.main() 671