[pypy-commit] pypy default: Tweaks for CPython 2.7 compatibility:
arigo
noreply at buildbot.pypy.org
Wed Aug 15 18:06:21 CEST 2012
Author: Armin Rigo <arigo at tunes.org>
Branch:
Changeset: r56730:3c783b31f9da
Date: 2012-08-15 18:06 +0200
http://bitbucket.org/pypy/pypy/changeset/3c783b31f9da/
Log: Tweaks for CPython 2.7 compatibility:
- __nonzero__ must return a bool or an int, but not a long
- if there is no __nonzero__, fall back to __len__, but then
handle the result in the same way as len() would, e.g. allowing a
long or a custom class with an __int__.
diff --git a/pypy/objspace/descroperation.py b/pypy/objspace/descroperation.py
--- a/pypy/objspace/descroperation.py
+++ b/pypy/objspace/descroperation.py
@@ -229,13 +229,15 @@
return space.get_and_call_function(w_descr, w_obj, w_name)
def is_true(space, w_obj):
- method = "__nonzero__"
- w_descr = space.lookup(w_obj, method)
+ w_descr = space.lookup(w_obj, "__nonzero__")
if w_descr is None:
- method = "__len__"
- w_descr = space.lookup(w_obj, method)
+ w_descr = space.lookup(w_obj, "__len__")
if w_descr is None:
return True
+ # call __len__
+ w_res = space.get_and_call_function(w_descr, w_obj)
+ return space._check_len_result(w_res) != 0
+ # call __nonzero__
w_res = space.get_and_call_function(w_descr, w_obj)
# more shortcuts for common cases
if space.is_w(w_res, space.w_False):
@@ -245,11 +247,10 @@
w_restype = space.type(w_res)
# Note there is no check for bool here because the only possible
# instances of bool are w_False and w_True, which are checked above.
- if (space.is_w(w_restype, space.w_int) or
- space.is_w(w_restype, space.w_long)):
+ if space.is_w(w_restype, space.w_int):
return space.int_w(w_res) != 0
else:
- msg = "%s should return bool or integer" % (method,)
+ msg = "__nonzero__ should return bool or integer"
raise OperationError(space.w_TypeError, space.wrap(msg))
def nonzero(space, w_obj):
diff --git a/pypy/objspace/test/test_descroperation.py b/pypy/objspace/test/test_descroperation.py
--- a/pypy/objspace/test/test_descroperation.py
+++ b/pypy/objspace/test/test_descroperation.py
@@ -658,7 +658,7 @@
class X(object):
def __len__(self): return 1L
__nonzero__ = __len__
- assert X()
+ raises(TypeError, bool, X()) # must return bool or int, not long
del X.__nonzero__
assert X()
@@ -668,6 +668,7 @@
def __len__(self):
return sys.maxsize + 1
raises(OverflowError, len, X())
+ raises(OverflowError, bool, X())
def test_len_underflow(self):
import sys
@@ -675,10 +676,12 @@
def __len__(self):
return -1
raises(ValueError, len, X())
+ raises(ValueError, bool, X())
class Y(object):
def __len__(self):
return -1L
raises(ValueError, len, Y())
+ raises(ValueError, bool, Y())
def test_len_custom__int__(self):
class X(object):
@@ -691,8 +694,12 @@
l = len(X(3.0))
assert l == 3 and type(l) is int
+ assert X(3.0)
+ assert not X(0.0)
l = len(X(X(2)))
assert l == 2 and type(l) is int
+ assert X(X(2))
+ assert not X(X(0))
def test_bool___contains__(self):
class X(object):
More information about the pypy-commit
mailing list