blob: cabf715dcbdcf9c86c7864bc9ad1ba8e5da0389c [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
95def __cmp__(self, *args):
96 return 0
Guido van Rossum47b9ff62006-08-24 00:41:19 +000097
Thomas Woutersed03b412007-08-28 21:37:11 +000098@trackCall
99def __eq__(self, *args):
100 return True
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000101
Thomas Woutersed03b412007-08-28 21:37:11 +0000102@trackCall
103def __ne__(self, *args):
104 return False
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000105
Thomas Woutersed03b412007-08-28 21:37:11 +0000106@trackCall
107def __lt__(self, *args):
108 return False
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000109
Thomas Woutersed03b412007-08-28 21:37:11 +0000110@trackCall
111def __le__(self, *args):
112 return True
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000113
Thomas Woutersed03b412007-08-28 21:37:11 +0000114@trackCall
115def __gt__(self, *args):
116 return False
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000117
Thomas Woutersed03b412007-08-28 21:37:11 +0000118@trackCall
119def __ge__(self, *args):
120 return True
121"""
Barry Warsaw07d8d642001-08-20 20:29:07 +0000122
Thomas Woutersed03b412007-08-28 21:37:11 +0000123# Synthesize all the other AllTests methods from the names in testmeths.
Tim Peters01705212001-12-11 19:28:47 +0000124
125method_template = """\
Thomas Woutersed03b412007-08-28 21:37:11 +0000126@trackCall
127def __%s__(self, *args):
128 pass
Tim Peters01705212001-12-11 19:28:47 +0000129"""
130
Thomas Wouters4cdada92006-04-15 09:19:16 +0000131d = {}
Thomas Woutersed03b412007-08-28 21:37:11 +0000132exec(statictests, globals(), d)
Thomas Wouters1d75a792000-08-17 22:37:32 +0000133for method in testmeths:
Thomas Woutersed03b412007-08-28 21:37:11 +0000134 exec(method_template % method, globals(), d)
135AllTests = type("AllTests", (object,), d)
136del d, statictests, method, method_template
Thomas Wouters1d75a792000-08-17 22:37:32 +0000137
Thomas Woutersed03b412007-08-28 21:37:11 +0000138class ClassTests(unittest.TestCase):
139 def setUp(self):
140 callLst[:] = []
Thomas Wouters1d75a792000-08-17 22:37:32 +0000141
Thomas Woutersed03b412007-08-28 21:37:11 +0000142 def assertCallStack(self, expected_calls):
143 actualCallList = callLst[:] # need to copy because the comparison below will add
144 # additional calls to callLst
145 if expected_calls != actualCallList:
146 self.fail("Expected call list:\n %s\ndoes not match actual call list\n %s" %
147 (expected_calls, actualCallList))
Thomas Wouters1d75a792000-08-17 22:37:32 +0000148
Thomas Woutersed03b412007-08-28 21:37:11 +0000149 def testInit(self):
150 foo = AllTests()
151 self.assertCallStack([("__init__", (foo,))])
Thomas Wouters1d75a792000-08-17 22:37:32 +0000152
Thomas Woutersed03b412007-08-28 21:37:11 +0000153 def testBinaryOps(self):
154 testme = AllTests()
155 # Binary operations
Thomas Wouters1d75a792000-08-17 22:37:32 +0000156
Thomas Woutersed03b412007-08-28 21:37:11 +0000157 callLst[:] = []
158 testme + 1
159 self.assertCallStack([("__add__", (testme, 1))])
Thomas Wouters1d75a792000-08-17 22:37:32 +0000160
Thomas Woutersed03b412007-08-28 21:37:11 +0000161 callLst[:] = []
162 1 + testme
163 self.assertCallStack([("__radd__", (testme, 1))])
Thomas Wouters1d75a792000-08-17 22:37:32 +0000164
Thomas Woutersed03b412007-08-28 21:37:11 +0000165 callLst[:] = []
166 testme - 1
167 self.assertCallStack([("__sub__", (testme, 1))])
Thomas Wouters1d75a792000-08-17 22:37:32 +0000168
Thomas Woutersed03b412007-08-28 21:37:11 +0000169 callLst[:] = []
170 1 - testme
171 self.assertCallStack([("__rsub__", (testme, 1))])
Thomas Wouters1d75a792000-08-17 22:37:32 +0000172
Thomas Woutersed03b412007-08-28 21:37:11 +0000173 callLst[:] = []
174 testme * 1
175 self.assertCallStack([("__mul__", (testme, 1))])
Thomas Wouters1d75a792000-08-17 22:37:32 +0000176
Thomas Woutersed03b412007-08-28 21:37:11 +0000177 callLst[:] = []
178 1 * testme
179 self.assertCallStack([("__rmul__", (testme, 1))])
Thomas Wouters1d75a792000-08-17 22:37:32 +0000180
Thomas Woutersed03b412007-08-28 21:37:11 +0000181 if 1/2 == 0:
182 callLst[:] = []
183 testme / 1
184 self.assertCallStack([("__div__", (testme, 1))])
Thomas Wouters1d75a792000-08-17 22:37:32 +0000185
186
Thomas Woutersed03b412007-08-28 21:37:11 +0000187 callLst[:] = []
188 1 / testme
189 self.assertCallStack([("__rdiv__", (testme, 1))])
Thomas Wouters1d75a792000-08-17 22:37:32 +0000190
Thomas Woutersed03b412007-08-28 21:37:11 +0000191 callLst[:] = []
192 testme % 1
193 self.assertCallStack([("__mod__", (testme, 1))])
Thomas Wouters89f507f2006-12-13 04:49:30 +0000194
Thomas Woutersed03b412007-08-28 21:37:11 +0000195 callLst[:] = []
196 1 % testme
197 self.assertCallStack([("__rmod__", (testme, 1))])
Thomas Wouters1d75a792000-08-17 22:37:32 +0000198
199
Thomas Woutersed03b412007-08-28 21:37:11 +0000200 callLst[:] = []
201 divmod(testme,1)
202 self.assertCallStack([("__divmod__", (testme, 1))])
Thomas Wouters1d75a792000-08-17 22:37:32 +0000203
Thomas Woutersed03b412007-08-28 21:37:11 +0000204 callLst[:] = []
205 divmod(1, testme)
206 self.assertCallStack([("__rdivmod__", (testme, 1))])
Thomas Wouters1d75a792000-08-17 22:37:32 +0000207
Thomas Woutersed03b412007-08-28 21:37:11 +0000208 callLst[:] = []
209 testme ** 1
210 self.assertCallStack([("__pow__", (testme, 1))])
Thomas Wouters1d75a792000-08-17 22:37:32 +0000211
Thomas Woutersed03b412007-08-28 21:37:11 +0000212 callLst[:] = []
213 1 ** testme
214 self.assertCallStack([("__rpow__", (testme, 1))])
Thomas Wouters1d75a792000-08-17 22:37:32 +0000215
Thomas Woutersed03b412007-08-28 21:37:11 +0000216 callLst[:] = []
217 testme >> 1
218 self.assertCallStack([("__rshift__", (testme, 1))])
Thomas Wouters1d75a792000-08-17 22:37:32 +0000219
Thomas Woutersed03b412007-08-28 21:37:11 +0000220 callLst[:] = []
221 1 >> testme
222 self.assertCallStack([("__rrshift__", (testme, 1))])
Thomas Wouters1d75a792000-08-17 22:37:32 +0000223
Thomas Woutersed03b412007-08-28 21:37:11 +0000224 callLst[:] = []
225 testme << 1
226 self.assertCallStack([("__lshift__", (testme, 1))])
Thomas Wouters1d75a792000-08-17 22:37:32 +0000227
Thomas Woutersed03b412007-08-28 21:37:11 +0000228 callLst[:] = []
229 1 << testme
230 self.assertCallStack([("__rlshift__", (testme, 1))])
Thomas Wouters1d75a792000-08-17 22:37:32 +0000231
Thomas Woutersed03b412007-08-28 21:37:11 +0000232 callLst[:] = []
233 testme & 1
234 self.assertCallStack([("__and__", (testme, 1))])
Thomas Wouters1d75a792000-08-17 22:37:32 +0000235
Thomas Woutersed03b412007-08-28 21:37:11 +0000236 callLst[:] = []
237 1 & testme
238 self.assertCallStack([("__rand__", (testme, 1))])
Thomas Wouters1d75a792000-08-17 22:37:32 +0000239
Thomas Woutersed03b412007-08-28 21:37:11 +0000240 callLst[:] = []
241 testme | 1
242 self.assertCallStack([("__or__", (testme, 1))])
Thomas Wouters1d75a792000-08-17 22:37:32 +0000243
Thomas Woutersed03b412007-08-28 21:37:11 +0000244 callLst[:] = []
245 1 | testme
246 self.assertCallStack([("__ror__", (testme, 1))])
Thomas Wouters1d75a792000-08-17 22:37:32 +0000247
Thomas Woutersed03b412007-08-28 21:37:11 +0000248 callLst[:] = []
249 testme ^ 1
250 self.assertCallStack([("__xor__", (testme, 1))])
Thomas Wouters1d75a792000-08-17 22:37:32 +0000251
Thomas Woutersed03b412007-08-28 21:37:11 +0000252 callLst[:] = []
253 1 ^ testme
254 self.assertCallStack([("__rxor__", (testme, 1))])
Thomas Wouters1d75a792000-08-17 22:37:32 +0000255
Thomas Woutersed03b412007-08-28 21:37:11 +0000256 def testListAndDictOps(self):
257 testme = AllTests()
258
259 # List/dict operations
260
261 class Empty: pass
262
263 try:
264 1 in Empty()
265 self.fail('failed, should have raised TypeError')
266 except TypeError:
267 pass
268
269 callLst[:] = []
270 1 in testme
271 self.assertCallStack([('__contains__', (testme, 1))])
272
273 callLst[:] = []
274 testme[1]
275 self.assertCallStack([('__getitem__', (testme, 1))])
276
277 callLst[:] = []
278 testme[1] = 1
279 self.assertCallStack([('__setitem__', (testme, 1, 1))])
280
281 callLst[:] = []
282 del testme[1]
283 self.assertCallStack([('__delitem__', (testme, 1))])
284
285 callLst[:] = []
286 testme[:42]
Thomas Woutersd2cf20e2007-08-30 22:57:53 +0000287 self.assertCallStack([('__getitem__', (testme, slice(None, 42)))])
Thomas Woutersed03b412007-08-28 21:37:11 +0000288
289 callLst[:] = []
290 testme[:42] = "The Answer"
Thomas Woutersd2cf20e2007-08-30 22:57:53 +0000291 self.assertCallStack([('__setitem__', (testme, slice(None, 42),
292 "The Answer"))])
Thomas Woutersed03b412007-08-28 21:37:11 +0000293
294 callLst[:] = []
295 del testme[:42]
Thomas Woutersd2cf20e2007-08-30 22:57:53 +0000296 self.assertCallStack([('__delitem__', (testme, slice(None, 42)))])
Thomas Woutersed03b412007-08-28 21:37:11 +0000297
298 callLst[:] = []
299 testme[2:1024:10]
300 self.assertCallStack([('__getitem__', (testme, slice(2, 1024, 10)))])
301
302 callLst[:] = []
303 testme[2:1024:10] = "A lot"
304 self.assertCallStack([('__setitem__', (testme, slice(2, 1024, 10),
305 "A lot"))])
306 callLst[:] = []
307 del testme[2:1024:10]
308 self.assertCallStack([('__delitem__', (testme, slice(2, 1024, 10)))])
309
310 callLst[:] = []
311 testme[:42, ..., :24:, 24, 100]
312 self.assertCallStack([('__getitem__', (testme, (slice(None, 42, None),
313 Ellipsis,
314 slice(None, 24, None),
315 24, 100)))])
316 callLst[:] = []
317 testme[:42, ..., :24:, 24, 100] = "Strange"
318 self.assertCallStack([('__setitem__', (testme, (slice(None, 42, None),
319 Ellipsis,
320 slice(None, 24, None),
321 24, 100), "Strange"))])
322 callLst[:] = []
323 del testme[:42, ..., :24:, 24, 100]
324 self.assertCallStack([('__delitem__', (testme, (slice(None, 42, None),
325 Ellipsis,
326 slice(None, 24, None),
327 24, 100)))])
328
Thomas Woutersed03b412007-08-28 21:37:11 +0000329 def testUnaryOps(self):
330 testme = AllTests()
Neil Schemenauer3a313e32004-07-19 16:29:17 +0000331
Thomas Woutersed03b412007-08-28 21:37:11 +0000332 callLst[:] = []
333 -testme
334 self.assertCallStack([('__neg__', (testme,))])
335 callLst[:] = []
336 +testme
337 self.assertCallStack([('__pos__', (testme,))])
338 callLst[:] = []
339 abs(testme)
340 self.assertCallStack([('__abs__', (testme,))])
341 callLst[:] = []
342 int(testme)
343 self.assertCallStack([('__int__', (testme,))])
344 callLst[:] = []
345 float(testme)
346 self.assertCallStack([('__float__', (testme,))])
347 callLst[:] = []
348 oct(testme)
349 self.assertCallStack([('__index__', (testme,))])
350 callLst[:] = []
351 hex(testme)
352 self.assertCallStack([('__index__', (testme,))])
Guido van Rossum2c9590f2002-10-29 19:08:29 +0000353
354
Thomas Woutersed03b412007-08-28 21:37:11 +0000355 def testMisc(self):
356 testme = AllTests()
Guido van Rossum2c9590f2002-10-29 19:08:29 +0000357
Thomas Woutersed03b412007-08-28 21:37:11 +0000358 callLst[:] = []
359 hash(testme)
360 self.assertCallStack([('__hash__', (testme,))])
Guido van Rossum2c9590f2002-10-29 19:08:29 +0000361
Thomas Woutersed03b412007-08-28 21:37:11 +0000362 callLst[:] = []
363 repr(testme)
364 self.assertCallStack([('__repr__', (testme,))])
Guido van Rossum2c9590f2002-10-29 19:08:29 +0000365
Thomas Woutersed03b412007-08-28 21:37:11 +0000366 callLst[:] = []
367 str(testme)
368 self.assertCallStack([('__str__', (testme,))])
Guido van Rossum2c9590f2002-10-29 19:08:29 +0000369
Thomas Woutersed03b412007-08-28 21:37:11 +0000370 callLst[:] = []
371 testme == 1
372 self.assertCallStack([('__eq__', (testme, 1))])
373
374 callLst[:] = []
375 testme < 1
376 self.assertCallStack([('__lt__', (testme, 1))])
377
378 callLst[:] = []
379 testme > 1
380 self.assertCallStack([('__gt__', (testme, 1))])
381
382 callLst[:] = []
383 testme != 1
384 self.assertCallStack([('__ne__', (testme, 1))])
385
386 callLst[:] = []
387 1 == testme
388 self.assertCallStack([('__eq__', (1, testme))])
389
390 callLst[:] = []
391 1 < testme
392 self.assertCallStack([('__gt__', (1, testme))])
393
394 callLst[:] = []
395 1 > testme
396 self.assertCallStack([('__lt__', (1, testme))])
397
398 callLst[:] = []
399 1 != testme
400 self.assertCallStack([('__ne__', (1, testme))])
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000401
402
Thomas Woutersed03b412007-08-28 21:37:11 +0000403 def testGetSetAndDel(self):
404 # Interfering tests
405 class ExtraTests(AllTests):
406 @trackCall
407 def __getattr__(self, *args):
408 return "SomeVal"
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000409
Thomas Woutersed03b412007-08-28 21:37:11 +0000410 @trackCall
411 def __setattr__(self, *args):
412 pass
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000413
Thomas Woutersed03b412007-08-28 21:37:11 +0000414 @trackCall
415 def __delattr__(self, *args):
416 pass
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000417
Thomas Woutersed03b412007-08-28 21:37:11 +0000418 testme = ExtraTests()
419
420 callLst[:] = []
421 testme.spam
422 self.assertCallStack([('__getattr__', (testme, "spam"))])
423
424 callLst[:] = []
425 testme.eggs = "spam, spam, spam and ham"
426 self.assertCallStack([('__setattr__', (testme, "eggs",
427 "spam, spam, spam and ham"))])
428
429 callLst[:] = []
430 del testme.cardinal
431 self.assertCallStack([('__delattr__', (testme, "cardinal"))])
432
433 def testDel(self):
434 x = []
435
436 class DelTest:
437 def __del__(self):
438 x.append("crab people, crab people")
439 testme = DelTest()
440 del testme
441 import gc
442 gc.collect()
443 self.assertEquals(["crab people, crab people"], x)
444
445 def testBadTypeReturned(self):
446 # return values of some method are type-checked
447 class BadTypeClass:
448 def __int__(self):
449 return None
450 __float__ = __int__
451 __str__ = __int__
452 __repr__ = __int__
453 __oct__ = __int__
454 __hex__ = __int__
455
456 for f in [int, float, str, repr, oct, hex]:
457 self.assertRaises(TypeError, f, BadTypeClass())
458
459 def testHashStuff(self):
460 # Test correct errors from hash() on objects with comparisons but
461 # no __hash__
462
463 class C0:
464 pass
465
466 hash(C0()) # This should work; the next two should raise TypeError
467
468 class C1:
469 def __cmp__(self, other): return 0
470
471 self.assertRaises(TypeError, hash, C1())
472
473 class C2:
474 def __eq__(self, other): return 1
475
476 self.assertRaises(TypeError, hash, C2())
477
478
479 def testSFBug532646(self):
480 # Test for SF bug 532646
481
482 class A:
483 pass
484 A.__call__ = A()
485 a = A()
486
487 try:
488 a() # This should not segfault
489 except RuntimeError:
490 pass
491 else:
492 self.fail("Failed to raise RuntimeError")
493
494 def testForExceptionsRaisedInInstanceGetattr2(self):
495 # Tests for exceptions raised in instance_getattr2().
496
497 def booh(self):
498 raise AttributeError("booh")
499
500 class A:
501 a = property(booh)
502 try:
503 A().a # Raised AttributeError: A instance has no attribute 'a'
504 except AttributeError as x:
505 if str(x) != "booh":
506 self.fail("attribute error for A().a got masked: %s" % x)
507
508 class E:
509 __eq__ = property(booh)
510 E() == E() # In debug mode, caused a C-level assert() to fail
511
512 class I:
513 __init__ = property(booh)
514 try:
515 # In debug mode, printed XXX undetected error and
516 # raises AttributeError
517 I()
518 except AttributeError as x:
519 pass
520 else:
521 self.fail("attribute error for I.__init__ got masked")
522
523 def testHashComparisonOfMethods(self):
524 # Test comparison and hash of methods
525 class A:
526 def __init__(self, x):
527 self.x = x
528 def f(self):
529 pass
530 def g(self):
531 pass
532 def __eq__(self, other):
533 return self.x == other.x
534 def __hash__(self):
535 return self.x
536 class B(A):
537 pass
538
539 a1 = A(1)
540 a2 = A(2)
541 self.assertEquals(a1.f, a1.f)
542 self.assertNotEquals(a1.f, a2.f)
543 self.assertNotEquals(a1.f, a1.g)
544 self.assertEquals(a1.f, A(1).f)
545 self.assertEquals(hash(a1.f), hash(a1.f))
546 self.assertEquals(hash(a1.f), hash(A(1).f))
547
548 self.assertNotEquals(A.f, a1.f)
549 self.assertNotEquals(A.f, A.g)
550 self.assertEquals(B.f, A.f)
551 self.assertEquals(hash(B.f), hash(A.f))
552
553 # the following triggers a SystemError in 2.4
Christian Heimes4a22b5d2007-11-25 09:39:14 +0000554 a = A(hash(A.f)^(-1))
Thomas Woutersed03b412007-08-28 21:37:11 +0000555 hash(a.f)
556
557def test_main():
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000558 support.run_unittest(ClassTests)
Thomas Woutersed03b412007-08-28 21:37:11 +0000559
560if __name__=='__main__':
561 test_main()