blob: ab44a4cb3cd3e827b36acf54621e641af2db7e5b [file] [log] [blame]
Thomas Wouters1d75a792000-08-17 22:37:32 +00001"Test the functionality of Python classes implementing operators."
2
Thomas Woutersed03b412007-08-28 21:37:11 +00003import unittest
4import sys
5
6from test import test_support
Thomas Wouters1d75a792000-08-17 22:37:32 +00007
8testmeths = [
9
10# Binary operations
11 "add",
12 "radd",
13 "sub",
14 "rsub",
15 "mul",
16 "rmul",
Neal Norwitzbcc0db82006-03-24 08:14:36 +000017 "truediv",
18 "rtruediv",
Thomas Wouters1d75a792000-08-17 22:37:32 +000019 "mod",
20 "rmod",
21 "divmod",
22 "rdivmod",
23 "pow",
24 "rpow",
25 "rshift",
26 "rrshift",
27 "lshift",
28 "rlshift",
29 "and",
30 "rand",
31 "or",
32 "ror",
33 "xor",
34 "rxor",
35
36# List/dict operations
37 "contains",
38 "getitem",
Thomas Wouters1d75a792000-08-17 22:37:32 +000039 "setitem",
Thomas Wouters1d75a792000-08-17 22:37:32 +000040 "delitem",
Thomas Wouters1d75a792000-08-17 22:37:32 +000041
42# Unary operations
43 "neg",
44 "pos",
45 "abs",
Thomas Wouters1d75a792000-08-17 22:37:32 +000046
47# generic operations
48 "init",
Thomas Wouters1d75a792000-08-17 22:37:32 +000049 ]
50
51# These need to return something other than None
Thomas Wouters1d75a792000-08-17 22:37:32 +000052# "hash",
53# "str",
54# "repr",
Neil Schemenauer3a313e32004-07-19 16:29:17 +000055# "int",
Neil Schemenauer3a313e32004-07-19 16:29:17 +000056# "float",
Thomas Wouters1d75a792000-08-17 22:37:32 +000057
58# These are separate because they can influence the test of other methods.
59# "getattr",
60# "setattr",
61# "delattr",
62
Thomas Woutersed03b412007-08-28 21:37:11 +000063callLst = []
64def trackCall(f):
65 def track(*args, **kwargs):
66 callLst.append((f.__name__, args))
67 return f(*args, **kwargs)
68 return track
Thomas Wouters1d75a792000-08-17 22:37:32 +000069
Thomas Woutersed03b412007-08-28 21:37:11 +000070statictests = """
71@trackCall
72def __hash__(self, *args):
73 return hash(id(self))
Thomas Wouters1d75a792000-08-17 22:37:32 +000074
Thomas Woutersed03b412007-08-28 21:37:11 +000075@trackCall
76def __str__(self, *args):
77 return "AllTests"
Thomas Wouters1d75a792000-08-17 22:37:32 +000078
Thomas Woutersed03b412007-08-28 21:37:11 +000079@trackCall
80def __repr__(self, *args):
81 return "AllTests"
Neil Schemenauer3a313e32004-07-19 16:29:17 +000082
Thomas Woutersed03b412007-08-28 21:37:11 +000083@trackCall
84def __int__(self, *args):
85 return 1
Guido van Rossumcd16bf62007-06-13 18:07:49 +000086
Thomas Woutersed03b412007-08-28 21:37:11 +000087@trackCall
88def __index__(self, *args):
89 return 1
Neil Schemenauer3a313e32004-07-19 16:29:17 +000090
Thomas Woutersed03b412007-08-28 21:37:11 +000091@trackCall
92def __float__(self, *args):
93 return 1.0
Thomas Wouters1d75a792000-08-17 22:37:32 +000094
Thomas Woutersed03b412007-08-28 21:37:11 +000095@trackCall
96def __cmp__(self, *args):
97 return 0
Guido van Rossum47b9ff62006-08-24 00:41:19 +000098
Thomas Woutersed03b412007-08-28 21:37:11 +000099@trackCall
100def __eq__(self, *args):
101 return True
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000102
Thomas Woutersed03b412007-08-28 21:37:11 +0000103@trackCall
104def __ne__(self, *args):
105 return False
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000106
Thomas Woutersed03b412007-08-28 21:37:11 +0000107@trackCall
108def __lt__(self, *args):
109 return False
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000110
Thomas Woutersed03b412007-08-28 21:37:11 +0000111@trackCall
112def __le__(self, *args):
113 return True
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000114
Thomas Woutersed03b412007-08-28 21:37:11 +0000115@trackCall
116def __gt__(self, *args):
117 return False
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000118
Thomas Woutersed03b412007-08-28 21:37:11 +0000119@trackCall
120def __ge__(self, *args):
121 return True
122"""
Barry Warsaw07d8d642001-08-20 20:29:07 +0000123
Thomas Woutersed03b412007-08-28 21:37:11 +0000124# Synthesize all the other AllTests methods from the names in testmeths.
Tim Peters01705212001-12-11 19:28:47 +0000125
126method_template = """\
Thomas Woutersed03b412007-08-28 21:37:11 +0000127@trackCall
128def __%s__(self, *args):
129 pass
Tim Peters01705212001-12-11 19:28:47 +0000130"""
131
Thomas Wouters4cdada92006-04-15 09:19:16 +0000132d = {}
Thomas Woutersed03b412007-08-28 21:37:11 +0000133exec(statictests, globals(), d)
Thomas Wouters1d75a792000-08-17 22:37:32 +0000134for method in testmeths:
Thomas Woutersed03b412007-08-28 21:37:11 +0000135 exec(method_template % method, globals(), d)
136AllTests = type("AllTests", (object,), d)
137del d, statictests, method, method_template
Thomas Wouters1d75a792000-08-17 22:37:32 +0000138
Thomas Woutersed03b412007-08-28 21:37:11 +0000139class ClassTests(unittest.TestCase):
140 def setUp(self):
141 callLst[:] = []
Thomas Wouters1d75a792000-08-17 22:37:32 +0000142
Thomas Woutersed03b412007-08-28 21:37:11 +0000143 def assertCallStack(self, expected_calls):
144 actualCallList = callLst[:] # need to copy because the comparison below will add
145 # additional calls to callLst
146 if expected_calls != actualCallList:
147 self.fail("Expected call list:\n %s\ndoes not match actual call list\n %s" %
148 (expected_calls, actualCallList))
Thomas Wouters1d75a792000-08-17 22:37:32 +0000149
Thomas Woutersed03b412007-08-28 21:37:11 +0000150 def testInit(self):
151 foo = AllTests()
152 self.assertCallStack([("__init__", (foo,))])
Thomas Wouters1d75a792000-08-17 22:37:32 +0000153
Thomas Woutersed03b412007-08-28 21:37:11 +0000154 def testBinaryOps(self):
155 testme = AllTests()
156 # Binary operations
Thomas Wouters1d75a792000-08-17 22:37:32 +0000157
Thomas Woutersed03b412007-08-28 21:37:11 +0000158 callLst[:] = []
159 testme + 1
160 self.assertCallStack([("__add__", (testme, 1))])
Thomas Wouters1d75a792000-08-17 22:37:32 +0000161
Thomas Woutersed03b412007-08-28 21:37:11 +0000162 callLst[:] = []
163 1 + testme
164 self.assertCallStack([("__radd__", (testme, 1))])
Thomas Wouters1d75a792000-08-17 22:37:32 +0000165
Thomas Woutersed03b412007-08-28 21:37:11 +0000166 callLst[:] = []
167 testme - 1
168 self.assertCallStack([("__sub__", (testme, 1))])
Thomas Wouters1d75a792000-08-17 22:37:32 +0000169
Thomas Woutersed03b412007-08-28 21:37:11 +0000170 callLst[:] = []
171 1 - testme
172 self.assertCallStack([("__rsub__", (testme, 1))])
Thomas Wouters1d75a792000-08-17 22:37:32 +0000173
Thomas Woutersed03b412007-08-28 21:37:11 +0000174 callLst[:] = []
175 testme * 1
176 self.assertCallStack([("__mul__", (testme, 1))])
Thomas Wouters1d75a792000-08-17 22:37:32 +0000177
Thomas Woutersed03b412007-08-28 21:37:11 +0000178 callLst[:] = []
179 1 * testme
180 self.assertCallStack([("__rmul__", (testme, 1))])
Thomas Wouters1d75a792000-08-17 22:37:32 +0000181
Thomas Woutersed03b412007-08-28 21:37:11 +0000182 if 1/2 == 0:
183 callLst[:] = []
184 testme / 1
185 self.assertCallStack([("__div__", (testme, 1))])
Thomas Wouters1d75a792000-08-17 22:37:32 +0000186
187
Thomas Woutersed03b412007-08-28 21:37:11 +0000188 callLst[:] = []
189 1 / testme
190 self.assertCallStack([("__rdiv__", (testme, 1))])
Thomas Wouters1d75a792000-08-17 22:37:32 +0000191
Thomas Woutersed03b412007-08-28 21:37:11 +0000192 callLst[:] = []
193 testme % 1
194 self.assertCallStack([("__mod__", (testme, 1))])
Thomas Wouters89f507f2006-12-13 04:49:30 +0000195
Thomas Woutersed03b412007-08-28 21:37:11 +0000196 callLst[:] = []
197 1 % testme
198 self.assertCallStack([("__rmod__", (testme, 1))])
Thomas Wouters1d75a792000-08-17 22:37:32 +0000199
200
Thomas Woutersed03b412007-08-28 21:37:11 +0000201 callLst[:] = []
202 divmod(testme,1)
203 self.assertCallStack([("__divmod__", (testme, 1))])
Thomas Wouters1d75a792000-08-17 22:37:32 +0000204
Thomas Woutersed03b412007-08-28 21:37:11 +0000205 callLst[:] = []
206 divmod(1, testme)
207 self.assertCallStack([("__rdivmod__", (testme, 1))])
Thomas Wouters1d75a792000-08-17 22:37:32 +0000208
Thomas Woutersed03b412007-08-28 21:37:11 +0000209 callLst[:] = []
210 testme ** 1
211 self.assertCallStack([("__pow__", (testme, 1))])
Thomas Wouters1d75a792000-08-17 22:37:32 +0000212
Thomas Woutersed03b412007-08-28 21:37:11 +0000213 callLst[:] = []
214 1 ** testme
215 self.assertCallStack([("__rpow__", (testme, 1))])
Thomas Wouters1d75a792000-08-17 22:37:32 +0000216
Thomas Woutersed03b412007-08-28 21:37:11 +0000217 callLst[:] = []
218 testme >> 1
219 self.assertCallStack([("__rshift__", (testme, 1))])
Thomas Wouters1d75a792000-08-17 22:37:32 +0000220
Thomas Woutersed03b412007-08-28 21:37:11 +0000221 callLst[:] = []
222 1 >> testme
223 self.assertCallStack([("__rrshift__", (testme, 1))])
Thomas Wouters1d75a792000-08-17 22:37:32 +0000224
Thomas Woutersed03b412007-08-28 21:37:11 +0000225 callLst[:] = []
226 testme << 1
227 self.assertCallStack([("__lshift__", (testme, 1))])
Thomas Wouters1d75a792000-08-17 22:37:32 +0000228
Thomas Woutersed03b412007-08-28 21:37:11 +0000229 callLst[:] = []
230 1 << testme
231 self.assertCallStack([("__rlshift__", (testme, 1))])
Thomas Wouters1d75a792000-08-17 22:37:32 +0000232
Thomas Woutersed03b412007-08-28 21:37:11 +0000233 callLst[:] = []
234 testme & 1
235 self.assertCallStack([("__and__", (testme, 1))])
Thomas Wouters1d75a792000-08-17 22:37:32 +0000236
Thomas Woutersed03b412007-08-28 21:37:11 +0000237 callLst[:] = []
238 1 & testme
239 self.assertCallStack([("__rand__", (testme, 1))])
Thomas Wouters1d75a792000-08-17 22:37:32 +0000240
Thomas Woutersed03b412007-08-28 21:37:11 +0000241 callLst[:] = []
242 testme | 1
243 self.assertCallStack([("__or__", (testme, 1))])
Thomas Wouters1d75a792000-08-17 22:37:32 +0000244
Thomas Woutersed03b412007-08-28 21:37:11 +0000245 callLst[:] = []
246 1 | testme
247 self.assertCallStack([("__ror__", (testme, 1))])
Thomas Wouters1d75a792000-08-17 22:37:32 +0000248
Thomas Woutersed03b412007-08-28 21:37:11 +0000249 callLst[:] = []
250 testme ^ 1
251 self.assertCallStack([("__xor__", (testme, 1))])
Thomas Wouters1d75a792000-08-17 22:37:32 +0000252
Thomas Woutersed03b412007-08-28 21:37:11 +0000253 callLst[:] = []
254 1 ^ testme
255 self.assertCallStack([("__rxor__", (testme, 1))])
Thomas Wouters1d75a792000-08-17 22:37:32 +0000256
Thomas Woutersed03b412007-08-28 21:37:11 +0000257 def testListAndDictOps(self):
258 testme = AllTests()
259
260 # List/dict operations
261
262 class Empty: pass
263
264 try:
265 1 in Empty()
266 self.fail('failed, should have raised TypeError')
267 except TypeError:
268 pass
269
270 callLst[:] = []
271 1 in testme
272 self.assertCallStack([('__contains__', (testme, 1))])
273
274 callLst[:] = []
275 testme[1]
276 self.assertCallStack([('__getitem__', (testme, 1))])
277
278 callLst[:] = []
279 testme[1] = 1
280 self.assertCallStack([('__setitem__', (testme, 1, 1))])
281
282 callLst[:] = []
283 del testme[1]
284 self.assertCallStack([('__delitem__', (testme, 1))])
285
286 callLst[:] = []
287 testme[:42]
Thomas Woutersd2cf20e2007-08-30 22:57:53 +0000288 self.assertCallStack([('__getitem__', (testme, slice(None, 42)))])
Thomas Woutersed03b412007-08-28 21:37:11 +0000289
290 callLst[:] = []
291 testme[:42] = "The Answer"
Thomas Woutersd2cf20e2007-08-30 22:57:53 +0000292 self.assertCallStack([('__setitem__', (testme, slice(None, 42),
293 "The Answer"))])
Thomas Woutersed03b412007-08-28 21:37:11 +0000294
295 callLst[:] = []
296 del testme[:42]
Thomas Woutersd2cf20e2007-08-30 22:57:53 +0000297 self.assertCallStack([('__delitem__', (testme, slice(None, 42)))])
Thomas Woutersed03b412007-08-28 21:37:11 +0000298
299 callLst[:] = []
300 testme[2:1024:10]
301 self.assertCallStack([('__getitem__', (testme, slice(2, 1024, 10)))])
302
303 callLst[:] = []
304 testme[2:1024:10] = "A lot"
305 self.assertCallStack([('__setitem__', (testme, slice(2, 1024, 10),
306 "A lot"))])
307 callLst[:] = []
308 del testme[2:1024:10]
309 self.assertCallStack([('__delitem__', (testme, slice(2, 1024, 10)))])
310
311 callLst[:] = []
312 testme[:42, ..., :24:, 24, 100]
313 self.assertCallStack([('__getitem__', (testme, (slice(None, 42, None),
314 Ellipsis,
315 slice(None, 24, None),
316 24, 100)))])
317 callLst[:] = []
318 testme[:42, ..., :24:, 24, 100] = "Strange"
319 self.assertCallStack([('__setitem__', (testme, (slice(None, 42, None),
320 Ellipsis,
321 slice(None, 24, None),
322 24, 100), "Strange"))])
323 callLst[:] = []
324 del testme[:42, ..., :24:, 24, 100]
325 self.assertCallStack([('__delitem__', (testme, (slice(None, 42, None),
326 Ellipsis,
327 slice(None, 24, None),
328 24, 100)))])
329
Thomas Woutersed03b412007-08-28 21:37:11 +0000330 def testUnaryOps(self):
331 testme = AllTests()
Neil Schemenauer3a313e32004-07-19 16:29:17 +0000332
Thomas Woutersed03b412007-08-28 21:37:11 +0000333 callLst[:] = []
334 -testme
335 self.assertCallStack([('__neg__', (testme,))])
336 callLst[:] = []
337 +testme
338 self.assertCallStack([('__pos__', (testme,))])
339 callLst[:] = []
340 abs(testme)
341 self.assertCallStack([('__abs__', (testme,))])
342 callLst[:] = []
343 int(testme)
344 self.assertCallStack([('__int__', (testme,))])
345 callLst[:] = []
346 float(testme)
347 self.assertCallStack([('__float__', (testme,))])
348 callLst[:] = []
349 oct(testme)
350 self.assertCallStack([('__index__', (testme,))])
351 callLst[:] = []
352 hex(testme)
353 self.assertCallStack([('__index__', (testme,))])
Guido van Rossum2c9590f2002-10-29 19:08:29 +0000354
355
Thomas Woutersed03b412007-08-28 21:37:11 +0000356 def testMisc(self):
357 testme = AllTests()
Guido van Rossum2c9590f2002-10-29 19:08:29 +0000358
Thomas Woutersed03b412007-08-28 21:37:11 +0000359 callLst[:] = []
360 hash(testme)
361 self.assertCallStack([('__hash__', (testme,))])
Guido van Rossum2c9590f2002-10-29 19:08:29 +0000362
Thomas Woutersed03b412007-08-28 21:37:11 +0000363 callLst[:] = []
364 repr(testme)
365 self.assertCallStack([('__repr__', (testme,))])
Guido van Rossum2c9590f2002-10-29 19:08:29 +0000366
Thomas Woutersed03b412007-08-28 21:37:11 +0000367 callLst[:] = []
368 str(testme)
369 self.assertCallStack([('__str__', (testme,))])
Guido van Rossum2c9590f2002-10-29 19:08:29 +0000370
Thomas Woutersed03b412007-08-28 21:37:11 +0000371 callLst[:] = []
372 testme == 1
373 self.assertCallStack([('__eq__', (testme, 1))])
374
375 callLst[:] = []
376 testme < 1
377 self.assertCallStack([('__lt__', (testme, 1))])
378
379 callLst[:] = []
380 testme > 1
381 self.assertCallStack([('__gt__', (testme, 1))])
382
383 callLst[:] = []
384 testme != 1
385 self.assertCallStack([('__ne__', (testme, 1))])
386
387 callLst[:] = []
388 1 == testme
389 self.assertCallStack([('__eq__', (1, testme))])
390
391 callLst[:] = []
392 1 < testme
393 self.assertCallStack([('__gt__', (1, testme))])
394
395 callLst[:] = []
396 1 > testme
397 self.assertCallStack([('__lt__', (1, testme))])
398
399 callLst[:] = []
400 1 != testme
401 self.assertCallStack([('__ne__', (1, testme))])
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000402
403
Thomas Woutersed03b412007-08-28 21:37:11 +0000404 def testGetSetAndDel(self):
405 # Interfering tests
406 class ExtraTests(AllTests):
407 @trackCall
408 def __getattr__(self, *args):
409 return "SomeVal"
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000410
Thomas Woutersed03b412007-08-28 21:37:11 +0000411 @trackCall
412 def __setattr__(self, *args):
413 pass
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000414
Thomas Woutersed03b412007-08-28 21:37:11 +0000415 @trackCall
416 def __delattr__(self, *args):
417 pass
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000418
Thomas Woutersed03b412007-08-28 21:37:11 +0000419 testme = ExtraTests()
420
421 callLst[:] = []
422 testme.spam
423 self.assertCallStack([('__getattr__', (testme, "spam"))])
424
425 callLst[:] = []
426 testme.eggs = "spam, spam, spam and ham"
427 self.assertCallStack([('__setattr__', (testme, "eggs",
428 "spam, spam, spam and ham"))])
429
430 callLst[:] = []
431 del testme.cardinal
432 self.assertCallStack([('__delattr__', (testme, "cardinal"))])
433
434 def testDel(self):
435 x = []
436
437 class DelTest:
438 def __del__(self):
439 x.append("crab people, crab people")
440 testme = DelTest()
441 del testme
442 import gc
443 gc.collect()
444 self.assertEquals(["crab people, crab people"], x)
445
446 def testBadTypeReturned(self):
447 # return values of some method are type-checked
448 class BadTypeClass:
449 def __int__(self):
450 return None
451 __float__ = __int__
452 __str__ = __int__
453 __repr__ = __int__
454 __oct__ = __int__
455 __hex__ = __int__
456
457 for f in [int, float, str, repr, oct, hex]:
458 self.assertRaises(TypeError, f, BadTypeClass())
459
460 def testHashStuff(self):
461 # Test correct errors from hash() on objects with comparisons but
462 # no __hash__
463
464 class C0:
465 pass
466
467 hash(C0()) # This should work; the next two should raise TypeError
468
469 class C1:
470 def __cmp__(self, other): return 0
471
472 self.assertRaises(TypeError, hash, C1())
473
474 class C2:
475 def __eq__(self, other): return 1
476
477 self.assertRaises(TypeError, hash, C2())
478
479
480 def testSFBug532646(self):
481 # Test for SF bug 532646
482
483 class A:
484 pass
485 A.__call__ = A()
486 a = A()
487
488 try:
489 a() # This should not segfault
490 except RuntimeError:
491 pass
492 else:
493 self.fail("Failed to raise RuntimeError")
494
495 def testForExceptionsRaisedInInstanceGetattr2(self):
496 # Tests for exceptions raised in instance_getattr2().
497
498 def booh(self):
499 raise AttributeError("booh")
500
501 class A:
502 a = property(booh)
503 try:
504 A().a # Raised AttributeError: A instance has no attribute 'a'
505 except AttributeError as x:
506 if str(x) != "booh":
507 self.fail("attribute error for A().a got masked: %s" % x)
508
509 class E:
510 __eq__ = property(booh)
511 E() == E() # In debug mode, caused a C-level assert() to fail
512
513 class I:
514 __init__ = property(booh)
515 try:
516 # In debug mode, printed XXX undetected error and
517 # raises AttributeError
518 I()
519 except AttributeError as x:
520 pass
521 else:
522 self.fail("attribute error for I.__init__ got masked")
523
524 def testHashComparisonOfMethods(self):
525 # Test comparison and hash of methods
526 class A:
527 def __init__(self, x):
528 self.x = x
529 def f(self):
530 pass
531 def g(self):
532 pass
533 def __eq__(self, other):
534 return self.x == other.x
535 def __hash__(self):
536 return self.x
537 class B(A):
538 pass
539
540 a1 = A(1)
541 a2 = A(2)
542 self.assertEquals(a1.f, a1.f)
543 self.assertNotEquals(a1.f, a2.f)
544 self.assertNotEquals(a1.f, a1.g)
545 self.assertEquals(a1.f, A(1).f)
546 self.assertEquals(hash(a1.f), hash(a1.f))
547 self.assertEquals(hash(a1.f), hash(A(1).f))
548
549 self.assertNotEquals(A.f, a1.f)
550 self.assertNotEquals(A.f, A.g)
551 self.assertEquals(B.f, A.f)
552 self.assertEquals(hash(B.f), hash(A.f))
553
554 # the following triggers a SystemError in 2.4
Christian Heimes4a22b5d2007-11-25 09:39:14 +0000555 a = A(hash(A.f)^(-1))
Thomas Woutersed03b412007-08-28 21:37:11 +0000556 hash(a.f)
557
558def test_main():
559 test_support.run_unittest(ClassTests)
560
561if __name__=='__main__':
562 test_main()