source: python/trunk/Lib/test/test_class.py

Last change on this file was 391, checked in by dmik, 11 years ago

python: Merge vendor 2.7.6 to trunk.

  • Property svn:eol-style set to native
File size: 17.9 KB
Line 
1"Test the functionality of Python classes implementing operators."
2
3import unittest
4
5from test import test_support
6
7testmeths = [
8
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",
34
35# List/dict operations
36 "contains",
37 "getitem",
38 "getslice",
39 "setitem",
40 "setslice",
41 "delitem",
42 "delslice",
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# "coerce",
55# "hash",
56# "str",
57# "repr",
58# "int",
59# "long",
60# "float",
61# "oct",
62# "hex",
63
64# These are separate because they can influence the test of other methods.
65# "getattr",
66# "setattr",
67# "delattr",
68
69callLst = []
70def trackCall(f):
71 def track(*args, **kwargs):
72 callLst.append((f.__name__, args))
73 return f(*args, **kwargs)
74 return track
75
76class AllTests:
77 trackCall = trackCall
78
79 @trackCall
80 def __coerce__(self, *args):
81 return (self,) + args
82
83 @trackCall
84 def __hash__(self, *args):
85 return hash(id(self))
86
87 @trackCall
88 def __str__(self, *args):
89 return "AllTests"
90
91 @trackCall
92 def __repr__(self, *args):
93 return "AllTests"
94
95 @trackCall
96 def __int__(self, *args):
97 return 1
98
99 @trackCall
100 def __float__(self, *args):
101 return 1.0
102
103 @trackCall
104 def __long__(self, *args):
105 return 1L
106
107 @trackCall
108 def __oct__(self, *args):
109 return '01'
110
111 @trackCall
112 def __hex__(self, *args):
113 return '0x1'
114
115 @trackCall
116 def __cmp__(self, *args):
117 return 0
118
119# Synthesize all the other AllTests methods from the names in testmeths.
120
121method_template = """\
122@trackCall
123def __%(method)s__(self, *args):
124 pass
125"""
126
127for method in testmeths:
128 exec method_template % locals() in AllTests.__dict__
129
130del method, method_template
131
132class ClassTests(unittest.TestCase):
133 def setUp(self):
134 callLst[:] = []
135
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))
142
143 def testInit(self):
144 foo = AllTests()
145 self.assertCallStack([("__init__", (foo,))])
146
147 def testBinaryOps(self):
148 testme = AllTests()
149 # Binary operations
150
151 callLst[:] = []
152 testme + 1
153 self.assertCallStack([("__coerce__", (testme, 1)), ("__add__", (testme, 1))])
154
155 callLst[:] = []
156 1 + testme
157 self.assertCallStack([("__coerce__", (testme, 1)), ("__radd__", (testme, 1))])
158
159 callLst[:] = []
160 testme - 1
161 self.assertCallStack([("__coerce__", (testme, 1)), ("__sub__", (testme, 1))])
162
163 callLst[:] = []
164 1 - testme
165 self.assertCallStack([("__coerce__", (testme, 1)), ("__rsub__", (testme, 1))])
166
167 callLst[:] = []
168 testme * 1
169 self.assertCallStack([("__coerce__", (testme, 1)), ("__mul__", (testme, 1))])
170
171 callLst[:] = []
172 1 * testme
173 self.assertCallStack([("__coerce__", (testme, 1)), ("__rmul__", (testme, 1))])
174
175 if 1/2 == 0:
176 callLst[:] = []
177 testme / 1
178 self.assertCallStack([("__coerce__", (testme, 1)), ("__div__", (testme, 1))])
179
180
181 callLst[:] = []
182 1 / testme
183 self.assertCallStack([("__coerce__", (testme, 1)), ("__rdiv__", (testme, 1))])
184
185 callLst[:] = []
186 testme % 1
187 self.assertCallStack([("__coerce__", (testme, 1)), ("__mod__", (testme, 1))])
188
189 callLst[:] = []
190 1 % testme
191 self.assertCallStack([("__coerce__", (testme, 1)), ("__rmod__", (testme, 1))])
192
193
194 callLst[:] = []
195 divmod(testme,1)
196 self.assertCallStack([("__coerce__", (testme, 1)), ("__divmod__", (testme, 1))])
197
198 callLst[:] = []
199 divmod(1, testme)
200 self.assertCallStack([("__coerce__", (testme, 1)), ("__rdivmod__", (testme, 1))])
201
202 callLst[:] = []
203 testme ** 1
204 self.assertCallStack([("__coerce__", (testme, 1)), ("__pow__", (testme, 1))])
205
206 callLst[:] = []
207 1 ** testme
208 self.assertCallStack([("__coerce__", (testme, 1)), ("__rpow__", (testme, 1))])
209
210 callLst[:] = []
211 testme >> 1
212 self.assertCallStack([("__coerce__", (testme, 1)), ("__rshift__", (testme, 1))])
213
214 callLst[:] = []
215 1 >> testme
216 self.assertCallStack([("__coerce__", (testme, 1)), ("__rrshift__", (testme, 1))])
217
218 callLst[:] = []
219 testme << 1
220 self.assertCallStack([("__coerce__", (testme, 1)), ("__lshift__", (testme, 1))])
221
222 callLst[:] = []
223 1 << testme
224 self.assertCallStack([("__coerce__", (testme, 1)), ("__rlshift__", (testme, 1))])
225
226 callLst[:] = []
227 testme & 1
228 self.assertCallStack([("__coerce__", (testme, 1)), ("__and__", (testme, 1))])
229
230 callLst[:] = []
231 1 & testme
232 self.assertCallStack([("__coerce__", (testme, 1)), ("__rand__", (testme, 1))])
233
234 callLst[:] = []
235 testme | 1
236 self.assertCallStack([("__coerce__", (testme, 1)), ("__or__", (testme, 1))])
237
238 callLst[:] = []
239 1 | testme
240 self.assertCallStack([("__coerce__", (testme, 1)), ("__ror__", (testme, 1))])
241
242 callLst[:] = []
243 testme ^ 1
244 self.assertCallStack([("__coerce__", (testme, 1)), ("__xor__", (testme, 1))])
245
246 callLst[:] = []
247 1 ^ testme
248 self.assertCallStack([("__coerce__", (testme, 1)), ("__rxor__", (testme, 1))])
249
250 def testListAndDictOps(self):
251 testme = AllTests()
252
253 # List/dict operations
254
255 class Empty: pass
256
257 try:
258 1 in Empty()
259 self.fail('failed, should have raised TypeError')
260 except TypeError:
261 pass
262
263 callLst[:] = []
264 1 in testme
265 self.assertCallStack([('__contains__', (testme, 1))])
266
267 callLst[:] = []
268 testme[1]
269 self.assertCallStack([('__getitem__', (testme, 1))])
270
271 callLst[:] = []
272 testme[1] = 1
273 self.assertCallStack([('__setitem__', (testme, 1, 1))])
274
275 callLst[:] = []
276 del testme[1]
277 self.assertCallStack([('__delitem__', (testme, 1))])
278
279 callLst[:] = []
280 testme[:42]
281 self.assertCallStack([('__getslice__', (testme, 0, 42))])
282
283 callLst[:] = []
284 testme[:42] = "The Answer"
285 self.assertCallStack([('__setslice__', (testme, 0, 42, "The Answer"))])
286
287 callLst[:] = []
288 del testme[:42]
289 self.assertCallStack([('__delslice__', (testme, 0, 42))])
290
291 callLst[:] = []
292 testme[2:1024:10]
293 self.assertCallStack([('__getitem__', (testme, slice(2, 1024, 10)))])
294
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)))])
302
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)))])
321
322 # Now remove the slice hooks to see if converting normal slices to
323 # slice object works.
324
325 getslice = AllTests.__getslice__
326 del AllTests.__getslice__
327 setslice = AllTests.__setslice__
328 del AllTests.__setslice__
329 delslice = AllTests.__delslice__
330 del AllTests.__delslice__
331
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)))])
338
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)))])
346
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
351
352
353 @test_support.cpython_only
354 def testDelItem(self):
355 class A:
356 ok = False
357 def __delitem__(self, key):
358 self.ok = True
359 a = A()
360 # Subtle: we need to call PySequence_SetItem, not PyMapping_SetItem.
361 from _testcapi import sequence_delitem
362 sequence_delitem(a, 2)
363 self.assertTrue(a.ok)
364
365
366 def testUnaryOps(self):
367 testme = AllTests()
368
369 callLst[:] = []
370 -testme
371 self.assertCallStack([('__neg__', (testme,))])
372 callLst[:] = []
373 +testme
374 self.assertCallStack([('__pos__', (testme,))])
375 callLst[:] = []
376 abs(testme)
377 self.assertCallStack([('__abs__', (testme,))])
378 callLst[:] = []
379 int(testme)
380 self.assertCallStack([('__int__', (testme,))])
381 callLst[:] = []
382 long(testme)
383 self.assertCallStack([('__long__', (testme,))])
384 callLst[:] = []
385 float(testme)
386 self.assertCallStack([('__float__', (testme,))])
387 callLst[:] = []
388 oct(testme)
389 self.assertCallStack([('__oct__', (testme,))])
390 callLst[:] = []
391 hex(testme)
392 self.assertCallStack([('__hex__', (testme,))])
393
394
395 def testMisc(self):
396 testme = AllTests()
397
398 callLst[:] = []
399 hash(testme)
400 self.assertCallStack([('__hash__', (testme,))])
401
402 callLst[:] = []
403 repr(testme)
404 self.assertCallStack([('__repr__', (testme,))])
405
406 callLst[:] = []
407 str(testme)
408 self.assertCallStack([('__str__', (testme,))])
409
410 callLst[:] = []
411 testme == 1
412 self.assertCallStack([("__coerce__", (testme, 1)), ('__cmp__', (testme, 1))])
413
414 callLst[:] = []
415 testme < 1
416 self.assertCallStack([("__coerce__", (testme, 1)), ('__cmp__', (testme, 1))])
417
418 callLst[:] = []
419 testme > 1
420 self.assertCallStack([("__coerce__", (testme, 1)), ('__cmp__', (testme, 1))])
421
422 callLst[:] = []
423 eval('testme <> 1') # XXX kill this in py3k
424 self.assertCallStack([("__coerce__", (testme, 1)), ('__cmp__', (testme, 1))])
425
426 callLst[:] = []
427 testme != 1
428 self.assertCallStack([("__coerce__", (testme, 1)), ('__cmp__', (testme, 1))])
429
430 callLst[:] = []
431 1 == testme
432 self.assertCallStack([("__coerce__", (testme, 1)), ('__cmp__', (1, testme))])
433
434 callLst[:] = []
435 1 < testme
436 self.assertCallStack([("__coerce__", (testme, 1)), ('__cmp__', (1, testme))])
437
438 callLst[:] = []
439 1 > testme
440 self.assertCallStack([("__coerce__", (testme, 1)), ('__cmp__', (1, testme))])
441
442 callLst[:] = []
443 eval('1 <> testme')
444 self.assertCallStack([("__coerce__", (testme, 1)), ('__cmp__', (1, testme))])
445
446 callLst[:] = []
447 1 != testme
448 self.assertCallStack([("__coerce__", (testme, 1)), ('__cmp__', (1, testme))])
449
450
451 def testGetSetAndDel(self):
452 # Interfering tests
453 class ExtraTests(AllTests):
454 @trackCall
455 def __getattr__(self, *args):
456 return "SomeVal"
457
458 @trackCall
459 def __setattr__(self, *args):
460 pass
461
462 @trackCall
463 def __delattr__(self, *args):
464 pass
465
466 testme = ExtraTests()
467
468 callLst[:] = []
469 testme.spam
470 self.assertCallStack([('__getattr__', (testme, "spam"))])
471
472 callLst[:] = []
473 testme.eggs = "spam, spam, spam and ham"
474 self.assertCallStack([('__setattr__', (testme, "eggs",
475 "spam, spam, spam and ham"))])
476
477 callLst[:] = []
478 del testme.cardinal
479 self.assertCallStack([('__delattr__', (testme, "cardinal"))])
480
481 def testDel(self):
482 x = []
483
484 class DelTest:
485 def __del__(self):
486 x.append("crab people, crab people")
487 testme = DelTest()
488 del testme
489 import gc
490 gc.collect()
491 self.assertEqual(["crab people, crab people"], x)
492
493 def testBadTypeReturned(self):
494 # return values of some method are type-checked
495 class BadTypeClass:
496 def __int__(self):
497 return None
498 __float__ = __int__
499 __long__ = __int__
500 __str__ = __int__
501 __repr__ = __int__
502 __oct__ = __int__
503 __hex__ = __int__
504
505 for f in [int, float, long, str, repr, oct, hex]:
506 self.assertRaises(TypeError, f, BadTypeClass())
507
508 def testMixIntsAndLongs(self):
509 # mixing up ints and longs is okay
510 class IntLongMixClass:
511 @trackCall
512 def __int__(self):
513 return 42L
514
515 @trackCall
516 def __long__(self):
517 return 64
518
519 mixIntAndLong = IntLongMixClass()
520
521 callLst[:] = []
522 as_int = int(mixIntAndLong)
523 self.assertEqual(type(as_int), long)
524 self.assertEqual(as_int, 42L)
525 self.assertCallStack([('__int__', (mixIntAndLong,))])
526
527 callLst[:] = []
528 as_long = long(mixIntAndLong)
529 self.assertEqual(type(as_long), long)
530 self.assertEqual(as_long, 64)
531 self.assertCallStack([('__long__', (mixIntAndLong,))])
532
533 def testHashStuff(self):
534 # Test correct errors from hash() on objects with comparisons but
535 # no __hash__
536
537 class C0:
538 pass
539
540 hash(C0()) # This should work; the next two should raise TypeError
541
542 class C1:
543 def __cmp__(self, other): return 0
544
545 self.assertRaises(TypeError, hash, C1())
546
547 class C2:
548 def __eq__(self, other): return 1
549
550 self.assertRaises(TypeError, hash, C2())
551
552
553 def testSFBug532646(self):
554 # Test for SF bug 532646
555
556 class A:
557 pass
558 A.__call__ = A()
559 a = A()
560
561 try:
562 a() # This should not segfault
563 except RuntimeError:
564 pass
565 else:
566 self.fail("Failed to raise RuntimeError")
567
568 def testForExceptionsRaisedInInstanceGetattr2(self):
569 # Tests for exceptions raised in instance_getattr2().
570
571 def booh(self):
572 raise AttributeError("booh")
573
574 class A:
575 a = property(booh)
576 try:
577 A().a # Raised AttributeError: A instance has no attribute 'a'
578 except AttributeError, x:
579 if str(x) != "booh":
580 self.fail("attribute error for A().a got masked: %s" % x)
581
582 class E:
583 __eq__ = property(booh)
584 E() == E() # In debug mode, caused a C-level assert() to fail
585
586 class I:
587 __init__ = property(booh)
588 try:
589 # In debug mode, printed XXX undetected error and
590 # raises AttributeError
591 I()
592 except AttributeError, x:
593 pass
594 else:
595 self.fail("attribute error for I.__init__ got masked")
596
597 def testHashComparisonOfMethods(self):
598 # Test comparison and hash of methods
599 class A:
600 def __init__(self, x):
601 self.x = x
602 def f(self):
603 pass
604 def g(self):
605 pass
606 def __eq__(self, other):
607 return self.x == other.x
608 def __hash__(self):
609 return self.x
610 class B(A):
611 pass
612
613 a1 = A(1)
614 a2 = A(2)
615 self.assertEqual(a1.f, a1.f)
616 self.assertNotEqual(a1.f, a2.f)
617 self.assertNotEqual(a1.f, a1.g)
618 self.assertEqual(a1.f, A(1).f)
619 self.assertEqual(hash(a1.f), hash(a1.f))
620 self.assertEqual(hash(a1.f), hash(A(1).f))
621
622 self.assertNotEqual(A.f, a1.f)
623 self.assertNotEqual(A.f, A.g)
624 self.assertEqual(B.f, A.f)
625 self.assertEqual(hash(B.f), hash(A.f))
626
627 # the following triggers a SystemError in 2.4
628 a = A(hash(A.f.im_func)^(-1))
629 hash(a.f)
630
631 def testAttrSlots(self):
632 class C:
633 pass
634 for c in C, C():
635 self.assertRaises(TypeError, type(c).__getattribute__, c, [])
636 self.assertRaises(TypeError, type(c).__setattr__, c, [], [])
637
638def test_main():
639 with test_support.check_py3k_warnings(
640 (".+__(get|set|del)slice__ has been removed", DeprecationWarning),
641 ("classic int division", DeprecationWarning),
642 ("<> not supported", DeprecationWarning)):
643 test_support.run_unittest(ClassTests)
644
645if __name__=='__main__':
646 test_main()
Note: See TracBrowser for help on using the repository browser.