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