1 "Test the functionality of Python classes implementing operators."
5 from test
import test_support
35 # List/dict operations
53 # These need to return something other than None
64 # These are separate because they can influence the test of other methods.
71 def track(*args
, **kwargs
):
72 callLst
.append((f
.__name
__, args
))
73 return f(*args
, **kwargs
)
80 def __coerce__(self
, *args
):
84 def __hash__(self
, *args
):
88 def __str__(self
, *args
):
92 def __repr__(self
, *args
):
96 def __int__(self
, *args
):
100 def __float__(self
, *args
):
104 def __long__(self
, *args
):
108 def __oct__(self
, *args
):
112 def __hex__(self
, *args
):
116 def __cmp__(self
, *args
):
119 # Synthesize all the other AllTests methods from the names in testmeths.
121 method_template
= """\
123 def __%(method)s__(self, *args):
127 for method
in testmeths
:
128 exec method_template
% locals() in AllTests
.__dict
__
130 del method
, method_template
132 class ClassTests(unittest
.TestCase
):
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
))
145 self
.assertCallStack([("__init__", (foo
,))])
147 def testBinaryOps(self
):
153 self
.assertCallStack([("__coerce__", (testme
, 1)), ("__add__", (testme
, 1))])
157 self
.assertCallStack([("__coerce__", (testme
, 1)), ("__radd__", (testme
, 1))])
161 self
.assertCallStack([("__coerce__", (testme
, 1)), ("__sub__", (testme
, 1))])
165 self
.assertCallStack([("__coerce__", (testme
, 1)), ("__rsub__", (testme
, 1))])
169 self
.assertCallStack([("__coerce__", (testme
, 1)), ("__mul__", (testme
, 1))])
173 self
.assertCallStack([("__coerce__", (testme
, 1)), ("__rmul__", (testme
, 1))])
178 self
.assertCallStack([("__coerce__", (testme
, 1)), ("__div__", (testme
, 1))])
183 self
.assertCallStack([("__coerce__", (testme
, 1)), ("__rdiv__", (testme
, 1))])
187 self
.assertCallStack([("__coerce__", (testme
, 1)), ("__mod__", (testme
, 1))])
191 self
.assertCallStack([("__coerce__", (testme
, 1)), ("__rmod__", (testme
, 1))])
196 self
.assertCallStack([("__coerce__", (testme
, 1)), ("__divmod__", (testme
, 1))])
200 self
.assertCallStack([("__coerce__", (testme
, 1)), ("__rdivmod__", (testme
, 1))])
204 self
.assertCallStack([("__coerce__", (testme
, 1)), ("__pow__", (testme
, 1))])
208 self
.assertCallStack([("__coerce__", (testme
, 1)), ("__rpow__", (testme
, 1))])
212 self
.assertCallStack([("__coerce__", (testme
, 1)), ("__rshift__", (testme
, 1))])
216 self
.assertCallStack([("__coerce__", (testme
, 1)), ("__rrshift__", (testme
, 1))])
220 self
.assertCallStack([("__coerce__", (testme
, 1)), ("__lshift__", (testme
, 1))])
224 self
.assertCallStack([("__coerce__", (testme
, 1)), ("__rlshift__", (testme
, 1))])
228 self
.assertCallStack([("__coerce__", (testme
, 1)), ("__and__", (testme
, 1))])
232 self
.assertCallStack([("__coerce__", (testme
, 1)), ("__rand__", (testme
, 1))])
236 self
.assertCallStack([("__coerce__", (testme
, 1)), ("__or__", (testme
, 1))])
240 self
.assertCallStack([("__coerce__", (testme
, 1)), ("__ror__", (testme
, 1))])
244 self
.assertCallStack([("__coerce__", (testme
, 1)), ("__xor__", (testme
, 1))])
248 self
.assertCallStack([("__coerce__", (testme
, 1)), ("__rxor__", (testme
, 1))])
250 def testListAndDictOps(self
):
253 # List/dict operations
259 self
.fail('failed, should have raised TypeError')
265 self
.assertCallStack([('__contains__', (testme
, 1))])
269 self
.assertCallStack([('__getitem__', (testme
, 1))])
273 self
.assertCallStack([('__setitem__', (testme
, 1, 1))])
277 self
.assertCallStack([('__delitem__', (testme
, 1))])
281 self
.assertCallStack([('__getslice__', (testme
, 0, 42))])
284 testme
[:42] = "The Answer"
285 self
.assertCallStack([('__setslice__', (testme
, 0, 42, "The Answer"))])
289 self
.assertCallStack([('__delslice__', (testme
, 0, 42))])
293 self
.assertCallStack([('__getitem__', (testme
, slice(2, 1024, 10)))])
296 testme
[2:1024:10] = "A lot"
297 self
.assertCallStack([('__setitem__', (testme
, slice(2, 1024, 10),
300 del testme
[2:1024:10]
301 self
.assertCallStack([('__delitem__', (testme
, slice(2, 1024, 10)))])
304 testme
[:42, ..., :24:, 24, 100]
305 self
.assertCallStack([('__getitem__', (testme
, (slice(None, 42, None),
307 slice(None, 24, None),
310 testme
[:42, ..., :24:, 24, 100] = "Strange"
311 self
.assertCallStack([('__setitem__', (testme
, (slice(None, 42, None),
313 slice(None, 24, None),
314 24, 100), "Strange"))])
316 del testme
[:42, ..., :24:, 24, 100]
317 self
.assertCallStack([('__delitem__', (testme
, (slice(None, 42, None),
319 slice(None, 24, None),
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.
337 self
.assertCallStack([('__getitem__', (testme
, slice(0, 42, None)))])
340 testme
[:42] = "The Answer"
341 self
.assertCallStack([('__setitem__', (testme
, slice(0, 42, None),
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
):
358 self
.assertCallStack([('__neg__', (testme
,))])
361 self
.assertCallStack([('__pos__', (testme
,))])
364 self
.assertCallStack([('__abs__', (testme
,))])
367 self
.assertCallStack([('__int__', (testme
,))])
370 self
.assertCallStack([('__long__', (testme
,))])
373 self
.assertCallStack([('__float__', (testme
,))])
376 self
.assertCallStack([('__oct__', (testme
,))])
379 self
.assertCallStack([('__hex__', (testme
,))])
387 self
.assertCallStack([('__hash__', (testme
,))])
391 self
.assertCallStack([('__repr__', (testme
,))])
395 self
.assertCallStack([('__str__', (testme
,))])
399 self
.assertCallStack([("__coerce__", (testme
, 1)), ('__cmp__', (testme
, 1))])
403 self
.assertCallStack([("__coerce__", (testme
, 1)), ('__cmp__', (testme
, 1))])
407 self
.assertCallStack([("__coerce__", (testme
, 1)), ('__cmp__', (testme
, 1))])
410 eval('testme <> 1') # XXX kill this in py3k
411 self
.assertCallStack([("__coerce__", (testme
, 1)), ('__cmp__', (testme
, 1))])
415 self
.assertCallStack([("__coerce__", (testme
, 1)), ('__cmp__', (testme
, 1))])
419 self
.assertCallStack([("__coerce__", (testme
, 1)), ('__cmp__', (1, testme
))])
423 self
.assertCallStack([("__coerce__", (testme
, 1)), ('__cmp__', (1, testme
))])
427 self
.assertCallStack([("__coerce__", (testme
, 1)), ('__cmp__', (1, testme
))])
431 self
.assertCallStack([("__coerce__", (testme
, 1)), ('__cmp__', (1, testme
))])
435 self
.assertCallStack([("__coerce__", (testme
, 1)), ('__cmp__', (1, testme
))])
438 def testGetSetAndDel(self
):
440 class ExtraTests(AllTests
):
442 def __getattr__(self
, *args
):
446 def __setattr__(self
, *args
):
450 def __delattr__(self
, *args
):
453 testme
= ExtraTests()
457 self
.assertCallStack([('__getattr__', (testme
, "spam"))])
460 testme
.eggs
= "spam, spam, spam and ham"
461 self
.assertCallStack([('__setattr__', (testme
, "eggs",
462 "spam, spam, spam and ham"))])
466 self
.assertCallStack([('__delattr__', (testme
, "cardinal"))])
473 x
.append("crab people, crab people")
478 self
.assertEquals(["crab people, crab people"], x
)
480 def testBadTypeReturned(self
):
481 # return values of some method are type-checked
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
:
506 mixIntAndLong
= IntLongMixClass()
509 as_int
= int(mixIntAndLong
)
510 self
.assertEquals(type(as_int
), long)
511 self
.assertEquals(as_int
, 42L)
512 self
.assertCallStack([('__int__', (mixIntAndLong
,))])
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
527 hash(C0()) # This should work; the next two should raise TypeError
530 def __cmp__(self
, other
): return 0
532 self
.assertRaises(TypeError, hash, C1())
535 def __eq__(self
, other
): return 1
537 self
.assertRaises(TypeError, hash, C2())
540 def testSFBug532646(self
):
541 # Test for SF bug 532646
549 a() # This should not segfault
553 self
.fail("Failed to raise RuntimeError")
555 def testForExceptionsRaisedInInstanceGetattr2(self
):
556 # Tests for exceptions raised in instance_getattr2().
559 raise AttributeError("booh")
564 A().a
# Raised AttributeError: A instance has no attribute 'a'
565 except AttributeError, x
:
567 self
.fail("attribute error for A().a got masked: %s" % x
)
570 __eq__
= property(booh
)
571 E() == E() # In debug mode, caused a C-level assert() to fail
574 __init__
= property(booh
)
576 # In debug mode, printed XXX undetected error and
577 # raises AttributeError
579 except AttributeError, x
:
582 self
.fail("attribute error for I.__init__ got masked")
584 def testHashComparisonOfMethods(self
):
585 # Test comparison and hash of methods
587 def __init__(self
, x
):
593 def __eq__(self
, other
):
594 return self
.x
== other
.x
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))
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__':