blob: c7003fbe608b53ef5e5464754691342c14e5dddd [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
Thomas Woutersed03b412007-08-28 21:37:11 +00004
Benjamin Petersonee8712c2008-05-20 21:35:26 +00005from test import support
Thomas Wouters1d75a792000-08-17 22:37:32 +00006
7testmeths = [
8
9# Binary operations
10 "add",
11 "radd",
12 "sub",
13 "rsub",
14 "mul",
15 "rmul",
Neal Norwitzbcc0db82006-03-24 08:14:36 +000016 "truediv",
17 "rtruediv",
Thomas Wouters1d75a792000-08-17 22:37:32 +000018 "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",
Thomas Wouters1d75a792000-08-17 22:37:32 +000038 "setitem",
Thomas Wouters1d75a792000-08-17 22:37:32 +000039 "delitem",
Thomas Wouters1d75a792000-08-17 22:37:32 +000040
41# Unary operations
42 "neg",
43 "pos",
44 "abs",
Thomas Wouters1d75a792000-08-17 22:37:32 +000045
46# generic operations
47 "init",
Thomas Wouters1d75a792000-08-17 22:37:32 +000048 ]
49
50# These need to return something other than None
Thomas Wouters1d75a792000-08-17 22:37:32 +000051# "hash",
52# "str",
53# "repr",
Neil Schemenauer3a313e32004-07-19 16:29:17 +000054# "int",
Neil Schemenauer3a313e32004-07-19 16:29:17 +000055# "float",
Thomas Wouters1d75a792000-08-17 22:37:32 +000056
57# These are separate because they can influence the test of other methods.
58# "getattr",
59# "setattr",
60# "delattr",
61
Thomas Woutersed03b412007-08-28 21:37:11 +000062callLst = []
63def trackCall(f):
64 def track(*args, **kwargs):
65 callLst.append((f.__name__, args))
66 return f(*args, **kwargs)
67 return track
Thomas Wouters1d75a792000-08-17 22:37:32 +000068
Thomas Woutersed03b412007-08-28 21:37:11 +000069statictests = """
70@trackCall
71def __hash__(self, *args):
72 return hash(id(self))
Thomas Wouters1d75a792000-08-17 22:37:32 +000073
Thomas Woutersed03b412007-08-28 21:37:11 +000074@trackCall
75def __str__(self, *args):
76 return "AllTests"
Thomas Wouters1d75a792000-08-17 22:37:32 +000077
Thomas Woutersed03b412007-08-28 21:37:11 +000078@trackCall
79def __repr__(self, *args):
80 return "AllTests"
Neil Schemenauer3a313e32004-07-19 16:29:17 +000081
Thomas Woutersed03b412007-08-28 21:37:11 +000082@trackCall
83def __int__(self, *args):
84 return 1
Guido van Rossumcd16bf62007-06-13 18:07:49 +000085
Thomas Woutersed03b412007-08-28 21:37:11 +000086@trackCall
87def __index__(self, *args):
88 return 1
Neil Schemenauer3a313e32004-07-19 16:29:17 +000089
Thomas Woutersed03b412007-08-28 21:37:11 +000090@trackCall
91def __float__(self, *args):
92 return 1.0
Thomas Wouters1d75a792000-08-17 22:37:32 +000093
Thomas Woutersed03b412007-08-28 21:37:11 +000094@trackCall
Thomas Woutersed03b412007-08-28 21:37:11 +000095def __eq__(self, *args):
96 return True
Guido van Rossum47b9ff62006-08-24 00:41:19 +000097
Thomas Woutersed03b412007-08-28 21:37:11 +000098@trackCall
99def __ne__(self, *args):
100 return False
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000101
Thomas Woutersed03b412007-08-28 21:37:11 +0000102@trackCall
103def __lt__(self, *args):
104 return False
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000105
Thomas Woutersed03b412007-08-28 21:37:11 +0000106@trackCall
107def __le__(self, *args):
108 return True
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000109
Thomas Woutersed03b412007-08-28 21:37:11 +0000110@trackCall
111def __gt__(self, *args):
112 return False
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000113
Thomas Woutersed03b412007-08-28 21:37:11 +0000114@trackCall
115def __ge__(self, *args):
116 return True
117"""
Barry Warsaw07d8d642001-08-20 20:29:07 +0000118
Thomas Woutersed03b412007-08-28 21:37:11 +0000119# Synthesize all the other AllTests methods from the names in testmeths.
Tim Peters01705212001-12-11 19:28:47 +0000120
121method_template = """\
Thomas Woutersed03b412007-08-28 21:37:11 +0000122@trackCall
123def __%s__(self, *args):
124 pass
Tim Peters01705212001-12-11 19:28:47 +0000125"""
126
Thomas Wouters4cdada92006-04-15 09:19:16 +0000127d = {}
Thomas Woutersed03b412007-08-28 21:37:11 +0000128exec(statictests, globals(), d)
Thomas Wouters1d75a792000-08-17 22:37:32 +0000129for method in testmeths:
Thomas Woutersed03b412007-08-28 21:37:11 +0000130 exec(method_template % method, globals(), d)
131AllTests = type("AllTests", (object,), d)
132del d, statictests, method, method_template
Thomas Wouters1d75a792000-08-17 22:37:32 +0000133
Thomas Woutersed03b412007-08-28 21:37:11 +0000134class ClassTests(unittest.TestCase):
135 def setUp(self):
136 callLst[:] = []
Thomas Wouters1d75a792000-08-17 22:37:32 +0000137
Thomas Woutersed03b412007-08-28 21:37:11 +0000138 def assertCallStack(self, expected_calls):
139 actualCallList = callLst[:] # need to copy because the comparison below will add
140 # additional calls to callLst
141 if expected_calls != actualCallList:
142 self.fail("Expected call list:\n %s\ndoes not match actual call list\n %s" %
143 (expected_calls, actualCallList))
Thomas Wouters1d75a792000-08-17 22:37:32 +0000144
Thomas Woutersed03b412007-08-28 21:37:11 +0000145 def testInit(self):
146 foo = AllTests()
147 self.assertCallStack([("__init__", (foo,))])
Thomas Wouters1d75a792000-08-17 22:37:32 +0000148
Thomas Woutersed03b412007-08-28 21:37:11 +0000149 def testBinaryOps(self):
150 testme = AllTests()
151 # Binary operations
Thomas Wouters1d75a792000-08-17 22:37:32 +0000152
Thomas Woutersed03b412007-08-28 21:37:11 +0000153 callLst[:] = []
154 testme + 1
155 self.assertCallStack([("__add__", (testme, 1))])
Thomas Wouters1d75a792000-08-17 22:37:32 +0000156
Thomas Woutersed03b412007-08-28 21:37:11 +0000157 callLst[:] = []
158 1 + testme
159 self.assertCallStack([("__radd__", (testme, 1))])
Thomas Wouters1d75a792000-08-17 22:37:32 +0000160
Thomas Woutersed03b412007-08-28 21:37:11 +0000161 callLst[:] = []
162 testme - 1
163 self.assertCallStack([("__sub__", (testme, 1))])
Thomas Wouters1d75a792000-08-17 22:37:32 +0000164
Thomas Woutersed03b412007-08-28 21:37:11 +0000165 callLst[:] = []
166 1 - testme
167 self.assertCallStack([("__rsub__", (testme, 1))])
Thomas Wouters1d75a792000-08-17 22:37:32 +0000168
Thomas Woutersed03b412007-08-28 21:37:11 +0000169 callLst[:] = []
170 testme * 1
171 self.assertCallStack([("__mul__", (testme, 1))])
Thomas Wouters1d75a792000-08-17 22:37:32 +0000172
Thomas Woutersed03b412007-08-28 21:37:11 +0000173 callLst[:] = []
174 1 * testme
175 self.assertCallStack([("__rmul__", (testme, 1))])
Thomas Wouters1d75a792000-08-17 22:37:32 +0000176
Thomas Woutersed03b412007-08-28 21:37:11 +0000177 if 1/2 == 0:
178 callLst[:] = []
179 testme / 1
180 self.assertCallStack([("__div__", (testme, 1))])
Thomas Wouters1d75a792000-08-17 22:37:32 +0000181
182
Thomas Woutersed03b412007-08-28 21:37:11 +0000183 callLst[:] = []
184 1 / testme
185 self.assertCallStack([("__rdiv__", (testme, 1))])
Thomas Wouters1d75a792000-08-17 22:37:32 +0000186
Thomas Woutersed03b412007-08-28 21:37:11 +0000187 callLst[:] = []
188 testme % 1
189 self.assertCallStack([("__mod__", (testme, 1))])
Thomas Wouters89f507f2006-12-13 04:49:30 +0000190
Thomas Woutersed03b412007-08-28 21:37:11 +0000191 callLst[:] = []
192 1 % testme
193 self.assertCallStack([("__rmod__", (testme, 1))])
Thomas Wouters1d75a792000-08-17 22:37:32 +0000194
195
Thomas Woutersed03b412007-08-28 21:37:11 +0000196 callLst[:] = []
197 divmod(testme,1)
198 self.assertCallStack([("__divmod__", (testme, 1))])
Thomas Wouters1d75a792000-08-17 22:37:32 +0000199
Thomas Woutersed03b412007-08-28 21:37:11 +0000200 callLst[:] = []
201 divmod(1, testme)
202 self.assertCallStack([("__rdivmod__", (testme, 1))])
Thomas Wouters1d75a792000-08-17 22:37:32 +0000203
Thomas Woutersed03b412007-08-28 21:37:11 +0000204 callLst[:] = []
205 testme ** 1
206 self.assertCallStack([("__pow__", (testme, 1))])
Thomas Wouters1d75a792000-08-17 22:37:32 +0000207
Thomas Woutersed03b412007-08-28 21:37:11 +0000208 callLst[:] = []
209 1 ** testme
210 self.assertCallStack([("__rpow__", (testme, 1))])
Thomas Wouters1d75a792000-08-17 22:37:32 +0000211
Thomas Woutersed03b412007-08-28 21:37:11 +0000212 callLst[:] = []
213 testme >> 1
214 self.assertCallStack([("__rshift__", (testme, 1))])
Thomas Wouters1d75a792000-08-17 22:37:32 +0000215
Thomas Woutersed03b412007-08-28 21:37:11 +0000216 callLst[:] = []
217 1 >> testme
218 self.assertCallStack([("__rrshift__", (testme, 1))])
Thomas Wouters1d75a792000-08-17 22:37:32 +0000219
Thomas Woutersed03b412007-08-28 21:37:11 +0000220 callLst[:] = []
221 testme << 1
222 self.assertCallStack([("__lshift__", (testme, 1))])
Thomas Wouters1d75a792000-08-17 22:37:32 +0000223
Thomas Woutersed03b412007-08-28 21:37:11 +0000224 callLst[:] = []
225 1 << testme
226 self.assertCallStack([("__rlshift__", (testme, 1))])
Thomas Wouters1d75a792000-08-17 22:37:32 +0000227
Thomas Woutersed03b412007-08-28 21:37:11 +0000228 callLst[:] = []
229 testme & 1
230 self.assertCallStack([("__and__", (testme, 1))])
Thomas Wouters1d75a792000-08-17 22:37:32 +0000231
Thomas Woutersed03b412007-08-28 21:37:11 +0000232 callLst[:] = []
233 1 & testme
234 self.assertCallStack([("__rand__", (testme, 1))])
Thomas Wouters1d75a792000-08-17 22:37:32 +0000235
Thomas Woutersed03b412007-08-28 21:37:11 +0000236 callLst[:] = []
237 testme | 1
238 self.assertCallStack([("__or__", (testme, 1))])
Thomas Wouters1d75a792000-08-17 22:37:32 +0000239
Thomas Woutersed03b412007-08-28 21:37:11 +0000240 callLst[:] = []
241 1 | testme
242 self.assertCallStack([("__ror__", (testme, 1))])
Thomas Wouters1d75a792000-08-17 22:37:32 +0000243
Thomas Woutersed03b412007-08-28 21:37:11 +0000244 callLst[:] = []
245 testme ^ 1
246 self.assertCallStack([("__xor__", (testme, 1))])
Thomas Wouters1d75a792000-08-17 22:37:32 +0000247
Thomas Woutersed03b412007-08-28 21:37:11 +0000248 callLst[:] = []
249 1 ^ testme
250 self.assertCallStack([("__rxor__", (testme, 1))])
Thomas Wouters1d75a792000-08-17 22:37:32 +0000251
Thomas Woutersed03b412007-08-28 21:37:11 +0000252 def testListAndDictOps(self):
253 testme = AllTests()
254
255 # List/dict operations
256
257 class Empty: pass
258
259 try:
260 1 in Empty()
261 self.fail('failed, should have raised TypeError')
262 except TypeError:
263 pass
264
265 callLst[:] = []
266 1 in testme
267 self.assertCallStack([('__contains__', (testme, 1))])
268
269 callLst[:] = []
270 testme[1]
271 self.assertCallStack([('__getitem__', (testme, 1))])
272
273 callLst[:] = []
274 testme[1] = 1
275 self.assertCallStack([('__setitem__', (testme, 1, 1))])
276
277 callLst[:] = []
278 del testme[1]
279 self.assertCallStack([('__delitem__', (testme, 1))])
280
281 callLst[:] = []
282 testme[:42]
Thomas Woutersd2cf20e2007-08-30 22:57:53 +0000283 self.assertCallStack([('__getitem__', (testme, slice(None, 42)))])
Thomas Woutersed03b412007-08-28 21:37:11 +0000284
285 callLst[:] = []
286 testme[:42] = "The Answer"
Thomas Woutersd2cf20e2007-08-30 22:57:53 +0000287 self.assertCallStack([('__setitem__', (testme, slice(None, 42),
288 "The Answer"))])
Thomas Woutersed03b412007-08-28 21:37:11 +0000289
290 callLst[:] = []
291 del testme[:42]
Thomas Woutersd2cf20e2007-08-30 22:57:53 +0000292 self.assertCallStack([('__delitem__', (testme, slice(None, 42)))])
Thomas Woutersed03b412007-08-28 21:37:11 +0000293
294 callLst[:] = []
295 testme[2:1024:10]
296 self.assertCallStack([('__getitem__', (testme, slice(2, 1024, 10)))])
297
298 callLst[:] = []
299 testme[2:1024:10] = "A lot"
300 self.assertCallStack([('__setitem__', (testme, slice(2, 1024, 10),
301 "A lot"))])
302 callLst[:] = []
303 del testme[2:1024:10]
304 self.assertCallStack([('__delitem__', (testme, slice(2, 1024, 10)))])
305
306 callLst[:] = []
307 testme[:42, ..., :24:, 24, 100]
308 self.assertCallStack([('__getitem__', (testme, (slice(None, 42, None),
309 Ellipsis,
310 slice(None, 24, None),
311 24, 100)))])
312 callLst[:] = []
313 testme[:42, ..., :24:, 24, 100] = "Strange"
314 self.assertCallStack([('__setitem__', (testme, (slice(None, 42, None),
315 Ellipsis,
316 slice(None, 24, None),
317 24, 100), "Strange"))])
318 callLst[:] = []
319 del testme[:42, ..., :24:, 24, 100]
320 self.assertCallStack([('__delitem__', (testme, (slice(None, 42, None),
321 Ellipsis,
322 slice(None, 24, None),
323 24, 100)))])
324
Thomas Woutersed03b412007-08-28 21:37:11 +0000325 def testUnaryOps(self):
326 testme = AllTests()
Neil Schemenauer3a313e32004-07-19 16:29:17 +0000327
Thomas Woutersed03b412007-08-28 21:37:11 +0000328 callLst[:] = []
329 -testme
330 self.assertCallStack([('__neg__', (testme,))])
331 callLst[:] = []
332 +testme
333 self.assertCallStack([('__pos__', (testme,))])
334 callLst[:] = []
335 abs(testme)
336 self.assertCallStack([('__abs__', (testme,))])
337 callLst[:] = []
338 int(testme)
339 self.assertCallStack([('__int__', (testme,))])
340 callLst[:] = []
341 float(testme)
342 self.assertCallStack([('__float__', (testme,))])
343 callLst[:] = []
344 oct(testme)
345 self.assertCallStack([('__index__', (testme,))])
346 callLst[:] = []
347 hex(testme)
348 self.assertCallStack([('__index__', (testme,))])
Guido van Rossum2c9590f2002-10-29 19:08:29 +0000349
350
Thomas Woutersed03b412007-08-28 21:37:11 +0000351 def testMisc(self):
352 testme = AllTests()
Guido van Rossum2c9590f2002-10-29 19:08:29 +0000353
Thomas Woutersed03b412007-08-28 21:37:11 +0000354 callLst[:] = []
355 hash(testme)
356 self.assertCallStack([('__hash__', (testme,))])
Guido van Rossum2c9590f2002-10-29 19:08:29 +0000357
Thomas Woutersed03b412007-08-28 21:37:11 +0000358 callLst[:] = []
359 repr(testme)
360 self.assertCallStack([('__repr__', (testme,))])
Guido van Rossum2c9590f2002-10-29 19:08:29 +0000361
Thomas Woutersed03b412007-08-28 21:37:11 +0000362 callLst[:] = []
363 str(testme)
364 self.assertCallStack([('__str__', (testme,))])
Guido van Rossum2c9590f2002-10-29 19:08:29 +0000365
Thomas Woutersed03b412007-08-28 21:37:11 +0000366 callLst[:] = []
367 testme == 1
368 self.assertCallStack([('__eq__', (testme, 1))])
369
370 callLst[:] = []
371 testme < 1
372 self.assertCallStack([('__lt__', (testme, 1))])
373
374 callLst[:] = []
375 testme > 1
376 self.assertCallStack([('__gt__', (testme, 1))])
377
378 callLst[:] = []
379 testme != 1
380 self.assertCallStack([('__ne__', (testme, 1))])
381
382 callLst[:] = []
383 1 == testme
384 self.assertCallStack([('__eq__', (1, testme))])
385
386 callLst[:] = []
387 1 < testme
388 self.assertCallStack([('__gt__', (1, testme))])
389
390 callLst[:] = []
391 1 > testme
392 self.assertCallStack([('__lt__', (1, testme))])
393
394 callLst[:] = []
395 1 != testme
396 self.assertCallStack([('__ne__', (1, testme))])
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000397
398
Thomas Woutersed03b412007-08-28 21:37:11 +0000399 def testGetSetAndDel(self):
400 # Interfering tests
401 class ExtraTests(AllTests):
402 @trackCall
403 def __getattr__(self, *args):
404 return "SomeVal"
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000405
Thomas Woutersed03b412007-08-28 21:37:11 +0000406 @trackCall
407 def __setattr__(self, *args):
408 pass
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000409
Thomas Woutersed03b412007-08-28 21:37:11 +0000410 @trackCall
411 def __delattr__(self, *args):
412 pass
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000413
Thomas Woutersed03b412007-08-28 21:37:11 +0000414 testme = ExtraTests()
415
416 callLst[:] = []
417 testme.spam
418 self.assertCallStack([('__getattr__', (testme, "spam"))])
419
420 callLst[:] = []
421 testme.eggs = "spam, spam, spam and ham"
422 self.assertCallStack([('__setattr__', (testme, "eggs",
423 "spam, spam, spam and ham"))])
424
425 callLst[:] = []
426 del testme.cardinal
427 self.assertCallStack([('__delattr__', (testme, "cardinal"))])
428
429 def testDel(self):
430 x = []
431
432 class DelTest:
433 def __del__(self):
434 x.append("crab people, crab people")
435 testme = DelTest()
436 del testme
437 import gc
438 gc.collect()
Ezio Melottib3aedd42010-11-20 19:04:17 +0000439 self.assertEqual(["crab people, crab people"], x)
Thomas Woutersed03b412007-08-28 21:37:11 +0000440
441 def testBadTypeReturned(self):
442 # return values of some method are type-checked
443 class BadTypeClass:
444 def __int__(self):
445 return None
446 __float__ = __int__
447 __str__ = __int__
448 __repr__ = __int__
449 __oct__ = __int__
450 __hex__ = __int__
451
452 for f in [int, float, str, repr, oct, hex]:
453 self.assertRaises(TypeError, f, BadTypeClass())
454
455 def testHashStuff(self):
456 # Test correct errors from hash() on objects with comparisons but
457 # no __hash__
458
459 class C0:
460 pass
461
462 hash(C0()) # This should work; the next two should raise TypeError
463
Thomas Woutersed03b412007-08-28 21:37:11 +0000464 class C2:
465 def __eq__(self, other): return 1
466
467 self.assertRaises(TypeError, hash, C2())
468
469
470 def testSFBug532646(self):
471 # Test for SF bug 532646
472
473 class A:
474 pass
475 A.__call__ = A()
476 a = A()
477
478 try:
479 a() # This should not segfault
480 except RuntimeError:
481 pass
482 else:
483 self.fail("Failed to raise RuntimeError")
484
485 def testForExceptionsRaisedInInstanceGetattr2(self):
486 # Tests for exceptions raised in instance_getattr2().
487
488 def booh(self):
489 raise AttributeError("booh")
490
491 class A:
492 a = property(booh)
493 try:
494 A().a # Raised AttributeError: A instance has no attribute 'a'
495 except AttributeError as x:
496 if str(x) != "booh":
497 self.fail("attribute error for A().a got masked: %s" % x)
498
499 class E:
500 __eq__ = property(booh)
501 E() == E() # In debug mode, caused a C-level assert() to fail
502
503 class I:
504 __init__ = property(booh)
505 try:
506 # In debug mode, printed XXX undetected error and
507 # raises AttributeError
508 I()
509 except AttributeError as x:
510 pass
511 else:
512 self.fail("attribute error for I.__init__ got masked")
513
514 def testHashComparisonOfMethods(self):
515 # Test comparison and hash of methods
516 class A:
517 def __init__(self, x):
518 self.x = x
519 def f(self):
520 pass
521 def g(self):
522 pass
523 def __eq__(self, other):
524 return self.x == other.x
525 def __hash__(self):
526 return self.x
527 class B(A):
528 pass
529
530 a1 = A(1)
531 a2 = A(2)
Ezio Melottib3aedd42010-11-20 19:04:17 +0000532 self.assertEqual(a1.f, a1.f)
533 self.assertNotEqual(a1.f, a2.f)
534 self.assertNotEqual(a1.f, a1.g)
535 self.assertEqual(a1.f, A(1).f)
536 self.assertEqual(hash(a1.f), hash(a1.f))
537 self.assertEqual(hash(a1.f), hash(A(1).f))
Thomas Woutersed03b412007-08-28 21:37:11 +0000538
Ezio Melottib3aedd42010-11-20 19:04:17 +0000539 self.assertNotEqual(A.f, a1.f)
540 self.assertNotEqual(A.f, A.g)
541 self.assertEqual(B.f, A.f)
542 self.assertEqual(hash(B.f), hash(A.f))
Thomas Woutersed03b412007-08-28 21:37:11 +0000543
544 # the following triggers a SystemError in 2.4
Christian Heimes4a22b5d2007-11-25 09:39:14 +0000545 a = A(hash(A.f)^(-1))
Thomas Woutersed03b412007-08-28 21:37:11 +0000546 hash(a.f)
547
548def test_main():
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000549 support.run_unittest(ClassTests)
Thomas Woutersed03b412007-08-28 21:37:11 +0000550
551if __name__=='__main__':
552 test_main()