1"Test the functionality of Python classes implementing operators." 2 3import unittest 4 5from test import test_support 6 7testmeths = [ 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 69callLst = [] 70def trackCall(f): 71 def track(*args, **kwargs): 72 callLst.append((f.__name__, args)) 73 return f(*args, **kwargs) 74 return track 75 76class 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 121method_template = """\ 122@trackCall 123def __%(method)s__(self, *args): 124 pass 125""" 126 127for method in testmeths: 128 exec method_template % locals() in AllTests.__dict__ 129 130del method, method_template 131 132class 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 def testUnaryOps(self): 354 testme = AllTests() 355 356 callLst[:] = [] 357 -testme 358 self.assertCallStack([('__neg__', (testme,))]) 359 callLst[:] = [] 360 +testme 361 self.assertCallStack([('__pos__', (testme,))]) 362 callLst[:] = [] 363 abs(testme) 364 self.assertCallStack([('__abs__', (testme,))]) 365 callLst[:] = [] 366 int(testme) 367 self.assertCallStack([('__int__', (testme,))]) 368 callLst[:] = [] 369 long(testme) 370 self.assertCallStack([('__long__', (testme,))]) 371 callLst[:] = [] 372 float(testme) 373 self.assertCallStack([('__float__', (testme,))]) 374 callLst[:] = [] 375 oct(testme) 376 self.assertCallStack([('__oct__', (testme,))]) 377 callLst[:] = [] 378 hex(testme) 379 self.assertCallStack([('__hex__', (testme,))]) 380 381 382 def testMisc(self): 383 testme = AllTests() 384 385 callLst[:] = [] 386 hash(testme) 387 self.assertCallStack([('__hash__', (testme,))]) 388 389 callLst[:] = [] 390 repr(testme) 391 self.assertCallStack([('__repr__', (testme,))]) 392 393 callLst[:] = [] 394 str(testme) 395 self.assertCallStack([('__str__', (testme,))]) 396 397 callLst[:] = [] 398 testme == 1 399 self.assertCallStack([("__coerce__", (testme, 1)), ('__cmp__', (testme, 1))]) 400 401 callLst[:] = [] 402 testme < 1 403 self.assertCallStack([("__coerce__", (testme, 1)), ('__cmp__', (testme, 1))]) 404 405 callLst[:] = [] 406 testme > 1 407 self.assertCallStack([("__coerce__", (testme, 1)), ('__cmp__', (testme, 1))]) 408 409 callLst[:] = [] 410 eval('testme <> 1') # XXX kill this in py3k 411 self.assertCallStack([("__coerce__", (testme, 1)), ('__cmp__', (testme, 1))]) 412 413 callLst[:] = [] 414 testme != 1 415 self.assertCallStack([("__coerce__", (testme, 1)), ('__cmp__', (testme, 1))]) 416 417 callLst[:] = [] 418 1 == testme 419 self.assertCallStack([("__coerce__", (testme, 1)), ('__cmp__', (1, testme))]) 420 421 callLst[:] = [] 422 1 < testme 423 self.assertCallStack([("__coerce__", (testme, 1)), ('__cmp__', (1, testme))]) 424 425 callLst[:] = [] 426 1 > testme 427 self.assertCallStack([("__coerce__", (testme, 1)), ('__cmp__', (1, testme))]) 428 429 callLst[:] = [] 430 eval('1 <> testme') 431 self.assertCallStack([("__coerce__", (testme, 1)), ('__cmp__', (1, testme))]) 432 433 callLst[:] = [] 434 1 != testme 435 self.assertCallStack([("__coerce__", (testme, 1)), ('__cmp__', (1, testme))]) 436 437 438 def testGetSetAndDel(self): 439 # Interfering tests 440 class ExtraTests(AllTests): 441 @trackCall 442 def __getattr__(self, *args): 443 return "SomeVal" 444 445 @trackCall 446 def __setattr__(self, *args): 447 pass 448 449 @trackCall 450 def __delattr__(self, *args): 451 pass 452 453 testme = ExtraTests() 454 455 callLst[:] = [] 456 testme.spam 457 self.assertCallStack([('__getattr__', (testme, "spam"))]) 458 459 callLst[:] = [] 460 testme.eggs = "spam, spam, spam and ham" 461 self.assertCallStack([('__setattr__', (testme, "eggs", 462 "spam, spam, spam and ham"))]) 463 464 callLst[:] = [] 465 del testme.cardinal 466 self.assertCallStack([('__delattr__', (testme, "cardinal"))]) 467 468 def testDel(self): 469 x = [] 470 471 class DelTest: 472 def __del__(self): 473 x.append("crab people, crab people") 474 testme = DelTest() 475 del testme 476 import gc 477 gc.collect() 478 self.assertEqual(["crab people, crab people"], x) 479 480 def testBadTypeReturned(self): 481 # return values of some method are type-checked 482 class BadTypeClass: 483 def __int__(self): 484 return None 485 __float__ = __int__ 486 __long__ = __int__ 487 __str__ = __int__ 488 __repr__ = __int__ 489 __oct__ = __int__ 490 __hex__ = __int__ 491 492 for f in [int, float, long, str, repr, oct, hex]: 493 self.assertRaises(TypeError, f, BadTypeClass()) 494 495 def testMixIntsAndLongs(self): 496 # mixing up ints and longs is okay 497 class IntLongMixClass: 498 @trackCall 499 def __int__(self): 500 return 42L 501 502 @trackCall 503 def __long__(self): 504 return 64 505 506 mixIntAndLong = IntLongMixClass() 507 508 callLst[:] = [] 509 as_int = int(mixIntAndLong) 510 self.assertEqual(type(as_int), long) 511 self.assertEqual(as_int, 42L) 512 self.assertCallStack([('__int__', (mixIntAndLong,))]) 513 514 callLst[:] = [] 515 as_long = long(mixIntAndLong) 516 self.assertEqual(type(as_long), long) 517 self.assertEqual(as_long, 64) 518 self.assertCallStack([('__long__', (mixIntAndLong,))]) 519 520 def testHashStuff(self): 521 # Test correct errors from hash() on objects with comparisons but 522 # no __hash__ 523 524 class C0: 525 pass 526 527 hash(C0()) # This should work; the next two should raise TypeError 528 529 class C1: 530 def __cmp__(self, other): return 0 531 532 self.assertRaises(TypeError, hash, C1()) 533 534 class C2: 535 def __eq__(self, other): return 1 536 537 self.assertRaises(TypeError, hash, C2()) 538 539 540 def testSFBug532646(self): 541 # Test for SF bug 532646 542 543 class A: 544 pass 545 A.__call__ = A() 546 a = A() 547 548 try: 549 a() # This should not segfault 550 except RuntimeError: 551 pass 552 else: 553 self.fail("Failed to raise RuntimeError") 554 555 def testForExceptionsRaisedInInstanceGetattr2(self): 556 # Tests for exceptions raised in instance_getattr2(). 557 558 def booh(self): 559 raise AttributeError("booh") 560 561 class A: 562 a = property(booh) 563 try: 564 A().a # Raised AttributeError: A instance has no attribute 'a' 565 except AttributeError, x: 566 if str(x) != "booh": 567 self.fail("attribute error for A().a got masked: %s" % x) 568 569 class E: 570 __eq__ = property(booh) 571 E() == E() # In debug mode, caused a C-level assert() to fail 572 573 class I: 574 __init__ = property(booh) 575 try: 576 # In debug mode, printed XXX undetected error and 577 # raises AttributeError 578 I() 579 except AttributeError, x: 580 pass 581 else: 582 self.fail("attribute error for I.__init__ got masked") 583 584 def testHashComparisonOfMethods(self): 585 # Test comparison and hash of methods 586 class A: 587 def __init__(self, x): 588 self.x = x 589 def f(self): 590 pass 591 def g(self): 592 pass 593 def __eq__(self, other): 594 return self.x == other.x 595 def __hash__(self): 596 return self.x 597 class B(A): 598 pass 599 600 a1 = A(1) 601 a2 = A(2) 602 self.assertEqual(a1.f, a1.f) 603 self.assertNotEqual(a1.f, a2.f) 604 self.assertNotEqual(a1.f, a1.g) 605 self.assertEqual(a1.f, A(1).f) 606 self.assertEqual(hash(a1.f), hash(a1.f)) 607 self.assertEqual(hash(a1.f), hash(A(1).f)) 608 609 self.assertNotEqual(A.f, a1.f) 610 self.assertNotEqual(A.f, A.g) 611 self.assertEqual(B.f, A.f) 612 self.assertEqual(hash(B.f), hash(A.f)) 613 614 # the following triggers a SystemError in 2.4 615 a = A(hash(A.f.im_func)^(-1)) 616 hash(a.f) 617 618def test_main(): 619 with test_support.check_py3k_warnings( 620 (".+__(get|set|del)slice__ has been removed", DeprecationWarning), 621 ("classic int division", DeprecationWarning), 622 ("<> not supported", DeprecationWarning)): 623 test_support.run_unittest(ClassTests) 624 625if __name__=='__main__': 626 test_main() 627