diff options
author | Armin Rigo <arigo@tunes.org> | 2005-12-29 15:59:19 (GMT) |
---|---|---|
committer | Armin Rigo <arigo@tunes.org> | 2005-12-29 15:59:19 (GMT) |
commit | fd163f92cee2aa8189879bd43670782f4cfd2cf8 (patch) | |
tree | 9bd3785dde016396b17a006059c68b3e4b60023e /Lib/test/test_descr.py | |
parent | c4308d5be64a622ee7be685c5eb05f90782711c1 (diff) | |
download | cpython-fd163f92cee2aa8189879bd43670782f4cfd2cf8.zip cpython-fd163f92cee2aa8189879bd43670782f4cfd2cf8.tar.gz cpython-fd163f92cee2aa8189879bd43670782f4cfd2cf8.tar.bz2 |
SF patch #1390657:
* set sq_repeat and sq_concat to NULL for user-defined new-style
classes, as a way to fix a number of related problems. See
test_descr.notimplemented()). One of these problems was fixed
in r25556 and r25557 but many more existed; this is a general
fix and thus reverts r25556-r25557.
* to avoid having PySequence_Repeat()/PySequence_Concat() failing
on user-defined classes, they now fall back to nb_add/nb_mul if
sq_concat/sq_repeat are not defined and the arguments appear to
be sequences.
* added tests.
Backport candidate.
Diffstat (limited to 'Lib/test/test_descr.py')
-rw-r--r-- | Lib/test/test_descr.py | 72 |
1 files changed, 72 insertions, 0 deletions
diff --git a/Lib/test/test_descr.py b/Lib/test/test_descr.py index f594ca8..2ea8186 100644 --- a/Lib/test/test_descr.py +++ b/Lib/test/test_descr.py @@ -3990,6 +3990,77 @@ def methodwrapper(): verify(l.__add__.__objclass__ is list) vereq(l.__add__.__doc__, list.__add__.__doc__) +def notimplemented(): + # all binary methods should be able to return a NotImplemented + if verbose: + print "Testing NotImplemented..." + + import sys + import types + import operator + + def specialmethod(self, other): + return NotImplemented + + def check(expr, x, y): + try: + exec expr in {'x': x, 'y': y, 'operator': operator} + except TypeError: + pass + else: + raise TestFailed("no TypeError from %r" % (expr,)) + + N1 = sys.maxint + 1L # might trigger OverflowErrors instead of TypeErrors + N2 = sys.maxint # if sizeof(int) < sizeof(long), might trigger + # ValueErrors instead of TypeErrors + for metaclass in [type, types.ClassType]: + for name, expr, iexpr in [ + ('__add__', 'x + y', 'x += y'), + ('__sub__', 'x - y', 'x -= y'), + ('__mul__', 'x * y', 'x *= y'), + ('__truediv__', 'operator.truediv(x, y)', None), + ('__floordiv__', 'operator.floordiv(x, y)', None), + ('__div__', 'x / y', 'x /= y'), + ('__mod__', 'x % y', 'x %= y'), + ('__divmod__', 'divmod(x, y)', None), + ('__pow__', 'x ** y', 'x **= y'), + ('__lshift__', 'x << y', 'x <<= y'), + ('__rshift__', 'x >> y', 'x >>= y'), + ('__and__', 'x & y', 'x &= y'), + ('__or__', 'x | y', 'x |= y'), + ('__xor__', 'x ^ y', 'x ^= y'), + ('__coerce__', 'coerce(x, y)', None)]: + if name == '__coerce__': + rname = name + else: + rname = '__r' + name[2:] + A = metaclass('A', (), {name: specialmethod}) + B = metaclass('B', (), {rname: specialmethod}) + a = A() + b = B() + check(expr, a, a) + check(expr, a, b) + check(expr, b, a) + check(expr, b, b) + check(expr, a, N1) + check(expr, a, N2) + check(expr, N1, b) + check(expr, N2, b) + if iexpr: + check(iexpr, a, a) + check(iexpr, a, b) + check(iexpr, b, a) + check(iexpr, b, b) + check(iexpr, a, N1) + check(iexpr, a, N2) + iname = '__i' + name[2:] + C = metaclass('C', (), {iname: specialmethod}) + c = C() + check(iexpr, c, a) + check(iexpr, c, b) + check(iexpr, c, N1) + check(iexpr, c, N2) + def test_main(): weakref_segfault() # Must be first, somehow do_this_first() @@ -4084,6 +4155,7 @@ def test_main(): vicious_descriptor_nonsense() test_init() methodwrapper() + notimplemented() if verbose: print "All OK" |