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 as x: 533 pass 534 else: 535 self.fail("attribute error for I.__init__ got masked") 536 537 def testHashComparisonOfMethods(self): 538 # Test comparison and hash of methods 539 class A: 540 def __init__(self, x): 541 self.x = x 542 def f(self): 543 pass 544 def g(self): 545 pass 546 def __eq__(self, other): 547 return self.x == other.x 548 def __hash__(self): 549 return self.x 550 class B(A): 551 pass 552 553 a1 = A(1) 554 a2 = A(2) 555 self.assertEqual(a1.f, a1.f) 556 self.assertNotEqual(a1.f, a2.f) 557 self.assertNotEqual(a1.f, a1.g) 558 self.assertEqual(a1.f, A(1).f) 559 self.assertEqual(hash(a1.f), hash(a1.f)) 560 self.assertEqual(hash(a1.f), hash(A(1).f)) 561 562 self.assertNotEqual(A.f, a1.f) 563 self.assertNotEqual(A.f, A.g) 564 self.assertEqual(B.f, A.f) 565 self.assertEqual(hash(B.f), hash(A.f)) 566 567 # the following triggers a SystemError in 2.4 568 a = A(hash(A.f)^(-1)) 569 hash(a.f) 570 571if __name__ == '__main__': 572 unittest.main() 573