move sections
[python/dscho.git] / Lib / test / test_class.py
blob914ea73c40d3f0f06cc5d5da9cb7bdcbe476f65b
1 "Test the functionality of Python classes implementing operators."
3 import unittest
5 from test import test_support
7 testmeths = [
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",
35 # List/dict operations
36 "contains",
37 "getitem",
38 "getslice",
39 "setitem",
40 "setslice",
41 "delitem",
42 "delslice",
44 # Unary operations
45 "neg",
46 "pos",
47 "abs",
49 # generic operations
50 "init",
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",
64 # These are separate because they can influence the test of other methods.
65 # "getattr",
66 # "setattr",
67 # "delattr",
69 callLst = []
70 def trackCall(f):
71 def track(*args, **kwargs):
72 callLst.append((f.__name__, args))
73 return f(*args, **kwargs)
74 return track
76 class AllTests:
77 trackCall = trackCall
79 @trackCall
80 def __coerce__(self, *args):
81 return (self,) + args
83 @trackCall
84 def __hash__(self, *args):
85 return hash(id(self))
87 @trackCall
88 def __str__(self, *args):
89 return "AllTests"
91 @trackCall
92 def __repr__(self, *args):
93 return "AllTests"
95 @trackCall
96 def __int__(self, *args):
97 return 1
99 @trackCall
100 def __float__(self, *args):
101 return 1.0
103 @trackCall
104 def __long__(self, *args):
105 return 1L
107 @trackCall
108 def __oct__(self, *args):
109 return '01'
111 @trackCall
112 def __hex__(self, *args):
113 return '0x1'
115 @trackCall
116 def __cmp__(self, *args):
117 return 0
119 # Synthesize all the other AllTests methods from the names in testmeths.
121 method_template = """\
122 @trackCall
123 def __%(method)s__(self, *args):
124 pass
127 for method in testmeths:
128 exec method_template % locals() in AllTests.__dict__
130 del method, method_template
132 class ClassTests(unittest.TestCase):
133 def setUp(self):
134 callLst[:] = []
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))
143 def testInit(self):
144 foo = AllTests()
145 self.assertCallStack([("__init__", (foo,))])
147 def testBinaryOps(self):
148 testme = AllTests()
149 # Binary operations
151 callLst[:] = []
152 testme + 1
153 self.assertCallStack([("__coerce__", (testme, 1)), ("__add__", (testme, 1))])
155 callLst[:] = []
156 1 + testme
157 self.assertCallStack([("__coerce__", (testme, 1)), ("__radd__", (testme, 1))])
159 callLst[:] = []
160 testme - 1
161 self.assertCallStack([("__coerce__", (testme, 1)), ("__sub__", (testme, 1))])
163 callLst[:] = []
164 1 - testme
165 self.assertCallStack([("__coerce__", (testme, 1)), ("__rsub__", (testme, 1))])
167 callLst[:] = []
168 testme * 1
169 self.assertCallStack([("__coerce__", (testme, 1)), ("__mul__", (testme, 1))])
171 callLst[:] = []
172 1 * testme
173 self.assertCallStack([("__coerce__", (testme, 1)), ("__rmul__", (testme, 1))])
175 if 1/2 == 0:
176 callLst[:] = []
177 testme / 1
178 self.assertCallStack([("__coerce__", (testme, 1)), ("__div__", (testme, 1))])
181 callLst[:] = []
182 1 / testme
183 self.assertCallStack([("__coerce__", (testme, 1)), ("__rdiv__", (testme, 1))])
185 callLst[:] = []
186 testme % 1
187 self.assertCallStack([("__coerce__", (testme, 1)), ("__mod__", (testme, 1))])
189 callLst[:] = []
190 1 % testme
191 self.assertCallStack([("__coerce__", (testme, 1)), ("__rmod__", (testme, 1))])
194 callLst[:] = []
195 divmod(testme,1)
196 self.assertCallStack([("__coerce__", (testme, 1)), ("__divmod__", (testme, 1))])
198 callLst[:] = []
199 divmod(1, testme)
200 self.assertCallStack([("__coerce__", (testme, 1)), ("__rdivmod__", (testme, 1))])
202 callLst[:] = []
203 testme ** 1
204 self.assertCallStack([("__coerce__", (testme, 1)), ("__pow__", (testme, 1))])
206 callLst[:] = []
207 1 ** testme
208 self.assertCallStack([("__coerce__", (testme, 1)), ("__rpow__", (testme, 1))])
210 callLst[:] = []
211 testme >> 1
212 self.assertCallStack([("__coerce__", (testme, 1)), ("__rshift__", (testme, 1))])
214 callLst[:] = []
215 1 >> testme
216 self.assertCallStack([("__coerce__", (testme, 1)), ("__rrshift__", (testme, 1))])
218 callLst[:] = []
219 testme << 1
220 self.assertCallStack([("__coerce__", (testme, 1)), ("__lshift__", (testme, 1))])
222 callLst[:] = []
223 1 << testme
224 self.assertCallStack([("__coerce__", (testme, 1)), ("__rlshift__", (testme, 1))])
226 callLst[:] = []
227 testme & 1
228 self.assertCallStack([("__coerce__", (testme, 1)), ("__and__", (testme, 1))])
230 callLst[:] = []
231 1 & testme
232 self.assertCallStack([("__coerce__", (testme, 1)), ("__rand__", (testme, 1))])
234 callLst[:] = []
235 testme | 1
236 self.assertCallStack([("__coerce__", (testme, 1)), ("__or__", (testme, 1))])
238 callLst[:] = []
239 1 | testme
240 self.assertCallStack([("__coerce__", (testme, 1)), ("__ror__", (testme, 1))])
242 callLst[:] = []
243 testme ^ 1
244 self.assertCallStack([("__coerce__", (testme, 1)), ("__xor__", (testme, 1))])
246 callLst[:] = []
247 1 ^ testme
248 self.assertCallStack([("__coerce__", (testme, 1)), ("__rxor__", (testme, 1))])
250 def testListAndDictOps(self):
251 testme = AllTests()
253 # List/dict operations
255 class Empty: pass
257 try:
258 1 in Empty()
259 self.fail('failed, should have raised TypeError')
260 except TypeError:
261 pass
263 callLst[:] = []
264 1 in testme
265 self.assertCallStack([('__contains__', (testme, 1))])
267 callLst[:] = []
268 testme[1]
269 self.assertCallStack([('__getitem__', (testme, 1))])
271 callLst[:] = []
272 testme[1] = 1
273 self.assertCallStack([('__setitem__', (testme, 1, 1))])
275 callLst[:] = []
276 del testme[1]
277 self.assertCallStack([('__delitem__', (testme, 1))])
279 callLst[:] = []
280 testme[:42]
281 self.assertCallStack([('__getslice__', (testme, 0, 42))])
283 callLst[:] = []
284 testme[:42] = "The Answer"
285 self.assertCallStack([('__setslice__', (testme, 0, 42, "The Answer"))])
287 callLst[:] = []
288 del testme[:42]
289 self.assertCallStack([('__delslice__', (testme, 0, 42))])
291 callLst[:] = []
292 testme[2:1024:10]
293 self.assertCallStack([('__getitem__', (testme, slice(2, 1024, 10)))])
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)))])
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)))])
322 # Now remove the slice hooks to see if converting normal slices to
323 # slice object works.
325 getslice = AllTests.__getslice__
326 del AllTests.__getslice__
327 setslice = AllTests.__setslice__
328 del AllTests.__setslice__
329 delslice = AllTests.__delslice__
330 del AllTests.__delslice__
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)))])
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)))])
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
353 def testUnaryOps(self):
354 testme = AllTests()
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,))])
382 def testMisc(self):
383 testme = AllTests()
385 callLst[:] = []
386 hash(testme)
387 self.assertCallStack([('__hash__', (testme,))])
389 callLst[:] = []
390 repr(testme)
391 self.assertCallStack([('__repr__', (testme,))])
393 callLst[:] = []
394 str(testme)
395 self.assertCallStack([('__str__', (testme,))])
397 callLst[:] = []
398 testme == 1
399 self.assertCallStack([("__coerce__", (testme, 1)), ('__cmp__', (testme, 1))])
401 callLst[:] = []
402 testme < 1
403 self.assertCallStack([("__coerce__", (testme, 1)), ('__cmp__', (testme, 1))])
405 callLst[:] = []
406 testme > 1
407 self.assertCallStack([("__coerce__", (testme, 1)), ('__cmp__', (testme, 1))])
409 callLst[:] = []
410 eval('testme <> 1') # XXX kill this in py3k
411 self.assertCallStack([("__coerce__", (testme, 1)), ('__cmp__', (testme, 1))])
413 callLst[:] = []
414 testme != 1
415 self.assertCallStack([("__coerce__", (testme, 1)), ('__cmp__', (testme, 1))])
417 callLst[:] = []
418 1 == testme
419 self.assertCallStack([("__coerce__", (testme, 1)), ('__cmp__', (1, testme))])
421 callLst[:] = []
422 1 < testme
423 self.assertCallStack([("__coerce__", (testme, 1)), ('__cmp__', (1, testme))])
425 callLst[:] = []
426 1 > testme
427 self.assertCallStack([("__coerce__", (testme, 1)), ('__cmp__', (1, testme))])
429 callLst[:] = []
430 eval('1 <> testme')
431 self.assertCallStack([("__coerce__", (testme, 1)), ('__cmp__', (1, testme))])
433 callLst[:] = []
434 1 != testme
435 self.assertCallStack([("__coerce__", (testme, 1)), ('__cmp__', (1, testme))])
438 def testGetSetAndDel(self):
439 # Interfering tests
440 class ExtraTests(AllTests):
441 @trackCall
442 def __getattr__(self, *args):
443 return "SomeVal"
445 @trackCall
446 def __setattr__(self, *args):
447 pass
449 @trackCall
450 def __delattr__(self, *args):
451 pass
453 testme = ExtraTests()
455 callLst[:] = []
456 testme.spam
457 self.assertCallStack([('__getattr__', (testme, "spam"))])
459 callLst[:] = []
460 testme.eggs = "spam, spam, spam and ham"
461 self.assertCallStack([('__setattr__', (testme, "eggs",
462 "spam, spam, spam and ham"))])
464 callLst[:] = []
465 del testme.cardinal
466 self.assertCallStack([('__delattr__', (testme, "cardinal"))])
468 def testDel(self):
469 x = []
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.assertEquals(["crab people, crab people"], x)
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__
492 for f in [int, float, long, str, repr, oct, hex]:
493 self.assertRaises(TypeError, f, BadTypeClass())
495 def testMixIntsAndLongs(self):
496 # mixing up ints and longs is okay
497 class IntLongMixClass:
498 @trackCall
499 def __int__(self):
500 return 42L
502 @trackCall
503 def __long__(self):
504 return 64
506 mixIntAndLong = IntLongMixClass()
508 callLst[:] = []
509 as_int = int(mixIntAndLong)
510 self.assertEquals(type(as_int), long)
511 self.assertEquals(as_int, 42L)
512 self.assertCallStack([('__int__', (mixIntAndLong,))])
514 callLst[:] = []
515 as_long = long(mixIntAndLong)
516 self.assertEquals(type(as_long), int)
517 self.assertEquals(as_long, 64)
518 self.assertCallStack([('__long__', (mixIntAndLong,))])
520 def testHashStuff(self):
521 # Test correct errors from hash() on objects with comparisons but
522 # no __hash__
524 class C0:
525 pass
527 hash(C0()) # This should work; the next two should raise TypeError
529 class C1:
530 def __cmp__(self, other): return 0
532 self.assertRaises(TypeError, hash, C1())
534 class C2:
535 def __eq__(self, other): return 1
537 self.assertRaises(TypeError, hash, C2())
540 def testSFBug532646(self):
541 # Test for SF bug 532646
543 class A:
544 pass
545 A.__call__ = A()
546 a = A()
548 try:
549 a() # This should not segfault
550 except RuntimeError:
551 pass
552 else:
553 self.fail("Failed to raise RuntimeError")
555 def testForExceptionsRaisedInInstanceGetattr2(self):
556 # Tests for exceptions raised in instance_getattr2().
558 def booh(self):
559 raise AttributeError("booh")
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)
569 class E:
570 __eq__ = property(booh)
571 E() == E() # In debug mode, caused a C-level assert() to fail
573 class I:
574 __init__ = property(booh)
575 try:
576 # In debug mode, printed XXX undetected error and
577 # raises AttributeError
579 except AttributeError, x:
580 pass
581 else:
582 self.fail("attribute error for I.__init__ got masked")
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
600 a1 = A(1)
601 a2 = A(2)
602 self.assertEquals(a1.f, a1.f)
603 self.assertNotEquals(a1.f, a2.f)
604 self.assertNotEquals(a1.f, a1.g)
605 self.assertEquals(a1.f, A(1).f)
606 self.assertEquals(hash(a1.f), hash(a1.f))
607 self.assertEquals(hash(a1.f), hash(A(1).f))
609 self.assertNotEquals(A.f, a1.f)
610 self.assertNotEquals(A.f, A.g)
611 self.assertEquals(B.f, A.f)
612 self.assertEquals(hash(B.f), hash(A.f))
614 # the following triggers a SystemError in 2.4
615 a = A(hash(A.f.im_func)^(-1))
616 hash(a.f)
618 def 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)
625 if __name__=='__main__':
626 test_main()