[pypy-commit] pypy default: merge the int_w-refactor branch: in a lot of places CPython allows objects with __int__ and __float__ instead of actual ints and floats, while until now pypy disallowed them. We fix it by making space.{int_w, float_w, etc.} accepting those objects by default, and disallowing conversions only when explicitly needed
antocuni
noreply at buildbot.pypy.org
Fri Feb 28 16:27:16 CET 2014
Author: Antonio Cuni <anto.cuni at gmail.com>
Branch:
Changeset: r69551:ccdc7e797e3b
Date: 2014-02-28 16:26 +0100
http://bitbucket.org/pypy/pypy/changeset/ccdc7e797e3b/
Log: merge the int_w-refactor branch: in a lot of places CPython allows
objects with __int__ and __float__ instead of actual ints and
floats, while until now pypy disallowed them. We fix it by making
space.{int_w,float_w,etc.} accepting those objects by default, and
disallowing conversions only when explicitly needed
diff --git a/lib-python/2.7/ctypes/test/test_numbers.py b/lib-python/2.7/ctypes/test/test_numbers.py
--- a/lib-python/2.7/ctypes/test/test_numbers.py
+++ b/lib-python/2.7/ctypes/test/test_numbers.py
@@ -105,7 +105,6 @@
self.assertEqual(ArgType, type(parm))
- @xfail
def test_floats(self):
# c_float and c_double can be created from
# Python int, long and float
diff --git a/pypy/interpreter/baseobjspace.py b/pypy/interpreter/baseobjspace.py
--- a/pypy/interpreter/baseobjspace.py
+++ b/pypy/interpreter/baseobjspace.py
@@ -92,7 +92,7 @@
i = 2 * HUGEVAL_BYTES
addrstring = [' '] * i
while True:
- n = space.int_w(space.and_(w_id, w_0x0F))
+ n = space.int_w(space.and_(w_id, w_0x0F), allow_conversion=False)
n += ord('0')
if n > ord('9'):
n += (ord('a') - ord('9') - 1)
@@ -201,16 +201,38 @@
def unicode_w(self, space):
self._typed_unwrap_error(space, "unicode")
- def int_w(self, space):
+ def int_w(self, space, allow_conversion=True):
+ # note that W_IntObject.int_w has a fast path and W_FloatObject.int_w
+ # raises w_TypeError
+ w_obj = self
+ if allow_conversion:
+ w_obj = space.int(self)
+ return w_obj._int_w(space)
+
+ def _int_w(self, space):
self._typed_unwrap_error(space, "integer")
- def float_w(self, space):
+ def float_w(self, space, allow_conversion=True):
+ w_obj = self
+ if allow_conversion:
+ w_obj = space.float(self)
+ return w_obj._float_w(space)
+
+ def _float_w(self, space):
self._typed_unwrap_error(space, "float")
def uint_w(self, space):
self._typed_unwrap_error(space, "integer")
- def bigint_w(self, space):
+ def bigint_w(self, space, allow_conversion=True):
+ # note that W_IntObject and W_LongObject have fast paths,
+ # W_FloatObject.rbigint_w raises w_TypeError raises
+ w_obj = self
+ if allow_conversion:
+ w_obj = space.long(self)
+ return w_obj._bigint_w(space)
+
+ def _bigint_w(self, space):
self._typed_unwrap_error(space, "integer")
def _typed_unwrap_error(self, space, expected):
@@ -220,8 +242,7 @@
def int(self, space):
w_impl = space.lookup(self, '__int__')
if w_impl is None:
- raise oefmt(space.w_TypeError,
- "unsupported operand type for int(): '%T'", self)
+ self._typed_unwrap_error(space, "integer")
w_result = space.get_and_call_function(w_impl, self)
if (space.isinstance_w(w_result, space.w_int) or
@@ -1210,7 +1231,7 @@
assert isinstance(w_index_or_slice, W_SliceObject)
start, stop, step = w_index_or_slice.indices3(self, seqlength)
else:
- start = self.int_w(w_index_or_slice)
+ start = self.int_w(w_index_or_slice, allow_conversion=False)
if start < 0:
start += seqlength
if not (0 <= start < seqlength):
@@ -1231,7 +1252,7 @@
start, stop, step, length = w_index_or_slice.indices4(self,
seqlength)
else:
- start = self.int_w(w_index_or_slice)
+ start = self.int_w(w_index_or_slice, allow_conversion=False)
if start < 0:
start += seqlength
if not (0 <= start < seqlength):
@@ -1255,7 +1276,10 @@
raise oefmt(self.w_TypeError, "%s must be an integer, not %T",
objdescr, w_obj)
try:
- index = self.int_w(w_index)
+ # allow_conversion=False it's not really necessary because the
+ # return type of __index__ is already checked by space.index(),
+ # but there is no reason to allow conversions anyway
+ index = self.int_w(w_index, allow_conversion=False)
except OperationError, err:
if not err.match(self, self.w_OverflowError):
raise
@@ -1272,16 +1296,16 @@
else:
return index
- def r_longlong_w(self, w_obj):
- bigint = self.bigint_w(w_obj)
+ def r_longlong_w(self, w_obj, allow_conversion=True):
+ bigint = self.bigint_w(w_obj, allow_conversion)
try:
return bigint.tolonglong()
except OverflowError:
raise OperationError(self.w_OverflowError,
self.wrap('integer too large'))
- def r_ulonglong_w(self, w_obj):
- bigint = self.bigint_w(w_obj)
+ def r_ulonglong_w(self, w_obj, allow_conversion=True):
+ bigint = self.bigint_w(w_obj, allow_conversion)
try:
return bigint.toulonglong()
except OverflowError:
@@ -1348,8 +1372,19 @@
'argument must be a string without NUL characters'))
return rstring.assert_str0(result)
- def int_w(self, w_obj):
- return w_obj.int_w(self)
+ def int_w(self, w_obj, allow_conversion=True):
+ """
+ Unwrap an app-level int object into an interpret-level int.
+
+ If allow_conversion==True, w_obj might be of any type which implements
+ __int__, *except* floats which are explicitly rejected. This is the
+ same logic as CPython's PyArg_ParseTuple. If you want to also allow
+ floats, you can call space.int_w(space.int(w_obj)).
+
+ If allow_conversion=False, w_obj needs to be an app-level int or a
+ subclass.
+ """
+ return w_obj.int_w(self, allow_conversion)
def int(self, w_obj):
return w_obj.int(self)
@@ -1357,11 +1392,19 @@
def uint_w(self, w_obj):
return w_obj.uint_w(self)
- def bigint_w(self, w_obj):
- return w_obj.bigint_w(self)
+ def bigint_w(self, w_obj, allow_conversion=True):
+ """
+ Like int_w, but return a rlib.rbigint object and call __long__ if
+ allow_conversion is True.
+ """
+ return w_obj.bigint_w(self, allow_conversion)
- def float_w(self, w_obj):
- return w_obj.float_w(self)
+ def float_w(self, w_obj, allow_conversion=True):
+ """
+ Like int_w, but return an interp-level float and call __float__ if
+ allow_conversion is True.
+ """
+ return w_obj.float_w(self, allow_conversion)
def realstr_w(self, w_obj):
# Like str_w, but only works if w_obj is really of type 'str'.
@@ -1399,20 +1442,10 @@
return w_obj.ord(self)
# This is all interface for gateway.py.
- def gateway_int_w(self, w_obj):
- if self.isinstance_w(w_obj, self.w_float):
- raise OperationError(self.w_TypeError,
- self.wrap("integer argument expected, got float"))
- return self.int_w(self.int(w_obj))
-
- def gateway_float_w(self, w_obj):
- return self.float_w(self.float(w_obj))
-
- def gateway_r_longlong_w(self, w_obj):
- if self.isinstance_w(w_obj, self.w_float):
- raise OperationError(self.w_TypeError,
- self.wrap("integer argument expected, got float"))
- return self.r_longlong_w(self.int(w_obj))
+ gateway_int_w = int_w
+ gateway_float_w = float_w
+ gateway_r_longlong_w = r_longlong_w
+ gateway_r_ulonglong_w = r_ulonglong_w
def gateway_r_uint_w(self, w_obj):
if self.isinstance_w(w_obj, self.w_float):
@@ -1420,12 +1453,6 @@
self.wrap("integer argument expected, got float"))
return self.uint_w(self.int(w_obj))
- def gateway_r_ulonglong_w(self, w_obj):
- if self.isinstance_w(w_obj, self.w_float):
- raise OperationError(self.w_TypeError,
- self.wrap("integer argument expected, got float"))
- return self.r_ulonglong_w(self.int(w_obj))
-
def gateway_nonnegint_w(self, w_obj):
# Like space.gateway_int_w(), but raises an app-level ValueError if
# the integer is negative. Here for gateway.py.
@@ -1447,7 +1474,7 @@
def c_uint_w(self, w_obj):
# Like space.gateway_uint_w(), but raises an app-level OverflowError if
# the integer does not fit in 32 bits. Here for gateway.py.
- value = self.gateway_r_uint_w(w_obj)
+ value = self.uint_w(w_obj)
if value > UINT_MAX_32_BITS:
raise OperationError(self.w_OverflowError,
self.wrap("expected an unsigned 32-bit integer"))
@@ -1457,7 +1484,7 @@
# Like space.gateway_int_w(), but raises an app-level ValueError if
# the integer is negative or does not fit in 32 bits. Here
# for gateway.py.
- value = self.gateway_int_w(w_obj)
+ value = self.int_w(w_obj)
if value < 0:
raise OperationError(self.w_ValueError,
self.wrap("expected a non-negative integer"))
@@ -1466,22 +1493,22 @@
self.wrap("expected a 32-bit integer"))
return value
- def truncatedint_w(self, w_obj):
+ def truncatedint_w(self, w_obj, allow_conversion=True):
# Like space.gateway_int_w(), but return the integer truncated
# instead of raising OverflowError. For obscure cases only.
try:
- return self.int_w(w_obj)
+ return self.int_w(w_obj, allow_conversion)
except OperationError, e:
if not e.match(self, self.w_OverflowError):
raise
from rpython.rlib.rarithmetic import intmask
return intmask(self.bigint_w(w_obj).uintmask())
- def truncatedlonglong_w(self, w_obj):
+ def truncatedlonglong_w(self, w_obj, allow_conversion=True):
# Like space.gateway_r_longlong_w(), but return the integer truncated
# instead of raising OverflowError.
try:
- return self.r_longlong_w(w_obj)
+ return self.r_longlong_w(w_obj, allow_conversion)
except OperationError, e:
if not e.match(self, self.w_OverflowError):
raise
diff --git a/pypy/interpreter/main.py b/pypy/interpreter/main.py
--- a/pypy/interpreter/main.py
+++ b/pypy/interpreter/main.py
@@ -134,7 +134,7 @@
exitcode = 0
else:
try:
- exitcode = space.int_w(w_exitcode)
+ exitcode = space.int_w(w_exitcode, allow_conversion=False)
except OperationError:
# not an integer: print it to stderr
msg = space.str_w(space.str(w_exitcode))
diff --git a/pypy/interpreter/test/test_argument.py b/pypy/interpreter/test/test_argument.py
--- a/pypy/interpreter/test/test_argument.py
+++ b/pypy/interpreter/test/test_argument.py
@@ -106,7 +106,7 @@
def len(self, x):
return len(x)
- def int_w(self, x):
+ def int_w(self, x, allow_conversion=True):
return x
def eq_w(self, x, y):
diff --git a/pypy/interpreter/test/test_gateway.py b/pypy/interpreter/test/test_gateway.py
--- a/pypy/interpreter/test/test_gateway.py
+++ b/pypy/interpreter/test/test_gateway.py
@@ -457,6 +457,8 @@
space.mul(space.wrap(sys.maxint), space.wrap(-7)))
def test_interp2app_unwrap_spec_typechecks(self):
+ from rpython.rlib.rarithmetic import r_longlong
+
space = self.space
w = space.wrap
def g3_id(space, x):
@@ -491,6 +493,12 @@
raises(gateway.OperationError,space.call_function,w_app_g3_f,w(None))
raises(gateway.OperationError,space.call_function,w_app_g3_f,w("foo"))
+ app_g3_r = gateway.interp2app_temp(g3_id,
+ unwrap_spec=[gateway.ObjSpace,
+ r_longlong])
+ w_app_g3_r = space.wrap(app_g3_r)
+ raises(gateway.OperationError,space.call_function,w_app_g3_r,w(1.0))
+
def test_interp2app_unwrap_spec_unicode(self):
space = self.space
w = space.wrap
diff --git a/pypy/interpreter/test/test_objspace.py b/pypy/interpreter/test/test_objspace.py
--- a/pypy/interpreter/test/test_objspace.py
+++ b/pypy/interpreter/test/test_objspace.py
@@ -167,6 +167,40 @@
self.space.setattr(w_oldstyle, self.space.wrap("__call__"), w_func)
assert is_callable(w_oldstyle)
+ def test_int_w(self):
+ space = self.space
+ w_x = space.wrap(42)
+ assert space.int_w(w_x) == 42
+ assert space.int_w(w_x, allow_conversion=False) == 42
+ #
+ w_x = space.wrap(44.0)
+ space.raises_w(space.w_TypeError, space.int_w, w_x)
+ space.raises_w(space.w_TypeError, space.int_w, w_x, allow_conversion=False)
+ #
+ w_instance = self.space.appexec([], """():
+ class MyInt(object):
+ def __int__(self):
+ return 43
+ return MyInt()
+ """)
+ assert space.int_w(w_instance) == 43
+ space.raises_w(space.w_TypeError, space.int_w, w_instance, allow_conversion=False)
+ #
+ w_instance = self.space.appexec([], """():
+ class MyInt(object):
+ def __int__(self):
+ return 43
+
+ class AnotherInt(object):
+ def __int__(self):
+ return MyInt()
+
+ return AnotherInt()
+ """)
+ space.raises_w(space.w_TypeError, space.int_w, w_instance)
+ space.raises_w(space.w_TypeError, space.int_w, w_instance, allow_conversion=False)
+
+
def test_interp_w(self):
w = self.space.wrap
w_bltinfunction = self.space.builtin.get('len')
diff --git a/pypy/module/__builtin__/test/test_buffer.py b/pypy/module/__builtin__/test/test_buffer.py
--- a/pypy/module/__builtin__/test/test_buffer.py
+++ b/pypy/module/__builtin__/test/test_buffer.py
@@ -170,6 +170,19 @@
for step in indices[1:]:
assert b[start:stop:step] == s[start:stop:step]
+ def test_getitem_only_ints(self):
+ class MyInt(object):
+ def __init__(self, x):
+ self.x = x
+
+ def __int__(self):
+ return self.x
+
+ buf = buffer('hello world')
+ raises(TypeError, "buf[MyInt(0)]")
+ raises(TypeError, "buf[MyInt(0):MyInt(5)]")
+
+
class AppTestMemoryView:
def test_basic(self):
v = memoryview("abc")
diff --git a/pypy/module/_cffi_backend/misc.py b/pypy/module/_cffi_backend/misc.py
--- a/pypy/module/_cffi_backend/misc.py
+++ b/pypy/module/_cffi_backend/misc.py
@@ -131,13 +131,13 @@
if space.is_w(space.type(w_ob), space.w_int): # shortcut
return space.int_w(w_ob)
try:
- bigint = space.bigint_w(w_ob)
+ bigint = space.bigint_w(w_ob, allow_conversion=False)
except OperationError, e:
if not e.match(space, space.w_TypeError):
raise
if _is_a_float(space, w_ob):
raise
- bigint = space.bigint_w(space.int(w_ob))
+ bigint = space.bigint_w(space.int(w_ob), allow_conversion=False)
try:
return bigint.tolonglong()
except OverflowError:
@@ -148,13 +148,13 @@
if space.is_w(space.type(w_ob), space.w_int): # shortcut
return space.int_w(w_ob)
try:
- bigint = space.bigint_w(w_ob)
+ bigint = space.bigint_w(w_ob, allow_conversion=False)
except OperationError, e:
if not e.match(space, space.w_TypeError):
raise
if _is_a_float(space, w_ob):
raise
- bigint = space.bigint_w(space.int(w_ob))
+ bigint = space.bigint_w(space.int(w_ob), allow_conversion=False)
try:
return bigint.toint()
except OverflowError:
@@ -171,13 +171,13 @@
raise OperationError(space.w_OverflowError, space.wrap(neg_msg))
return r_ulonglong(value)
try:
- bigint = space.bigint_w(w_ob)
+ bigint = space.bigint_w(w_ob, allow_conversion=False)
except OperationError, e:
if not e.match(space, space.w_TypeError):
raise
if strict and _is_a_float(space, w_ob):
raise
- bigint = space.bigint_w(space.int(w_ob))
+ bigint = space.bigint_w(space.int(w_ob), allow_conversion=False)
if strict:
try:
return bigint.toulonglong()
@@ -196,13 +196,13 @@
raise OperationError(space.w_OverflowError, space.wrap(neg_msg))
return r_uint(value)
try:
- bigint = space.bigint_w(w_ob)
+ bigint = space.bigint_w(w_ob, allow_conversion=False)
except OperationError, e:
if not e.match(space, space.w_TypeError):
raise
if strict and _is_a_float(space, w_ob):
raise
- bigint = space.bigint_w(space.int(w_ob))
+ bigint = space.bigint_w(space.int(w_ob), allow_conversion=False)
if strict:
try:
return bigint.touint()
diff --git a/pypy/module/_cffi_backend/test/_backend_test_c.py b/pypy/module/_cffi_backend/test/_backend_test_c.py
--- a/pypy/module/_cffi_backend/test/_backend_test_c.py
+++ b/pypy/module/_cffi_backend/test/_backend_test_c.py
@@ -1418,8 +1418,10 @@
p = newp(BStructPtr, [12])
assert p.a1 == 12
e = py.test.raises(TypeError, newp, BStructPtr, [None])
- assert ("an integer is required" in str(e.value) or
- "unsupported operand type for int(): 'NoneType'" in str(e.value)) #PyPy
+ msg = str(e.value)
+ assert ("an integer is required" in msg or # CPython
+ "unsupported operand type for int(): 'NoneType'" in msg or # old PyPys
+ "expected integer, got NoneType object" in msg) # newer PyPys
py.test.raises(TypeError, 'p.a1 = "def"')
if sys.version_info < (3,):
BEnum2 = new_enum_type(unicode("foo"), (unicode('abc'),), (5,), BInt)
diff --git a/pypy/module/_rawffi/alt/test/test_funcptr.py b/pypy/module/_rawffi/alt/test/test_funcptr.py
--- a/pypy/module/_rawffi/alt/test/test_funcptr.py
+++ b/pypy/module/_rawffi/alt/test/test_funcptr.py
@@ -185,6 +185,10 @@
set_val_to_ptr(ptr2, 123)
assert get_dummy() == 123
set_val_to_ptr(ptr2, 0)
+ #
+ class OldStyle:
+ pass
+ raises(TypeError, "set_val_to_ptr(OldStyle(), 0)")
def test_convert_strings_to_char_p(self):
"""
diff --git a/pypy/module/_rawffi/alt/type_converter.py b/pypy/module/_rawffi/alt/type_converter.py
--- a/pypy/module/_rawffi/alt/type_converter.py
+++ b/pypy/module/_rawffi/alt/type_converter.py
@@ -25,7 +25,7 @@
assert libffi.IS_32_BIT
self._longlong(w_ffitype, w_obj)
elif w_ffitype.is_signed():
- intval = space.truncatedint_w(w_obj)
+ intval = space.truncatedint_w(w_obj, allow_conversion=False)
self.handle_signed(w_ffitype, w_obj, intval)
elif self.maybe_handle_char_or_unichar_p(w_ffitype, w_obj):
# the object was already handled from within
@@ -33,16 +33,16 @@
pass
elif w_ffitype.is_pointer():
w_obj = self.convert_pointer_arg_maybe(w_obj, w_ffitype)
- intval = space.truncatedint_w(w_obj)
+ intval = space.truncatedint_w(w_obj, allow_conversion=False)
self.handle_pointer(w_ffitype, w_obj, intval)
elif w_ffitype.is_unsigned():
- uintval = r_uint(space.truncatedint_w(w_obj))
+ uintval = r_uint(space.truncatedint_w(w_obj, allow_conversion=False))
self.handle_unsigned(w_ffitype, w_obj, uintval)
elif w_ffitype.is_char():
- intval = space.int_w(space.ord(w_obj))
+ intval = space.int_w(space.ord(w_obj), allow_conversion=False)
self.handle_char(w_ffitype, w_obj, intval)
elif w_ffitype.is_unichar():
- intval = space.int_w(space.ord(w_obj))
+ intval = space.int_w(space.ord(w_obj), allow_conversion=False)
self.handle_unichar(w_ffitype, w_obj, intval)
elif w_ffitype.is_double():
self._float(w_ffitype, w_obj)
@@ -60,20 +60,20 @@
def _longlong(self, w_ffitype, w_obj):
# a separate function, which can be seen by the jit or not,
# depending on whether longlongs are supported
- longlongval = self.space.truncatedlonglong_w(w_obj)
+ longlongval = self.space.truncatedlonglong_w(w_obj, allow_conversion=False)
self.handle_longlong(w_ffitype, w_obj, longlongval)
def _float(self, w_ffitype, w_obj):
# a separate function, which can be seen by the jit or not,
# depending on whether floats are supported
- floatval = self.space.float_w(w_obj)
+ floatval = self.space.float_w(w_obj, allow_conversion=False)
self.handle_float(w_ffitype, w_obj, floatval)
def _singlefloat(self, w_ffitype, w_obj):
# a separate function, which can be seen by the jit or not,
# depending on whether singlefloats are supported
from rpython.rlib.rarithmetic import r_singlefloat
- floatval = self.space.float_w(w_obj)
+ floatval = self.space.float_w(w_obj, allow_conversion=False)
singlefloatval = r_singlefloat(floatval)
self.handle_singlefloat(w_ffitype, w_obj, singlefloatval)
diff --git a/pypy/module/array/test/test_array.py b/pypy/module/array/test/test_array.py
--- a/pypy/module/array/test/test_array.py
+++ b/pypy/module/array/test/test_array.py
@@ -1034,6 +1034,18 @@
assert len(b) == 13
assert str(b[12]) == "-0.0"
+ def test_getitem_only_ints(self):
+ class MyInt(object):
+ def __init__(self, x):
+ self.x = x
+
+ def __int__(self):
+ return self.x
+
+ a = self.array('i', [1, 2, 3, 4, 5, 6])
+ raises(TypeError, "a[MyInt(0)]")
+ raises(TypeError, "a[MyInt(0):MyInt(5)]")
+
class AppTestArrayBuiltinShortcut(AppTestArray):
spaceconfig = AppTestArray.spaceconfig.copy()
diff --git a/pypy/module/cppyy/test/test_zjit.py b/pypy/module/cppyy/test/test_zjit.py
--- a/pypy/module/cppyy/test/test_zjit.py
+++ b/pypy/module/cppyy/test/test_zjit.py
@@ -120,7 +120,7 @@
return FakeInt(int(obj))
assert 0
- def float_w(self, w_obj):
+ def float_w(self, w_obj, allow_conversion=True):
assert isinstance(w_obj, FakeFloat)
return w_obj.val
@@ -141,7 +141,7 @@
def is_w(self, w_one, w_two):
return w_one is w_two
- def int_w(self, w_obj):
+ def int_w(self, w_obj, allow_conversion=True):
assert isinstance(w_obj, FakeInt)
return w_obj.val
diff --git a/pypy/module/micronumpy/boxes.py b/pypy/module/micronumpy/boxes.py
--- a/pypy/module/micronumpy/boxes.py
+++ b/pypy/module/micronumpy/boxes.py
@@ -375,7 +375,7 @@
pass
class W_IntegerBox(W_NumberBox):
- def int_w(self, space):
+ def _int_w(self, space):
return space.int_w(self.descr_int(space))
class W_SignedIntegerBox(W_IntegerBox):
diff --git a/pypy/module/micronumpy/compile.py b/pypy/module/micronumpy/compile.py
--- a/pypy/module/micronumpy/compile.py
+++ b/pypy/module/micronumpy/compile.py
@@ -151,11 +151,11 @@
assert isinstance(w_obj, boxes.W_GenericBox)
return self.float(w_obj.descr_float(self))
- def float_w(self, w_obj):
+ def float_w(self, w_obj, allow_conversion=True):
assert isinstance(w_obj, FloatObject)
return w_obj.floatval
- def int_w(self, w_obj):
+ def int_w(self, w_obj, allow_conversion=True):
if isinstance(w_obj, IntObject):
return w_obj.intval
elif isinstance(w_obj, FloatObject):
diff --git a/pypy/module/posix/interp_posix.py b/pypy/module/posix/interp_posix.py
--- a/pypy/module/posix/interp_posix.py
+++ b/pypy/module/posix/interp_posix.py
@@ -868,8 +868,8 @@
args_w = space.fixedview(w_tuple)
if len(args_w) != 2:
raise OperationError(space.w_TypeError, space.wrap(msg))
- actime = space.float_w(args_w[0])
- modtime = space.float_w(args_w[1])
+ actime = space.float_w(args_w[0], allow_conversion=False)
+ modtime = space.float_w(args_w[1], allow_conversion=False)
dispatch_filename(rposix.utime, 2)(space, w_path, (actime, modtime))
except OSError, e:
raise wrap_oserror2(space, e, w_path)
diff --git a/pypy/module/struct/test/test_struct.py b/pypy/module/struct/test/test_struct.py
--- a/pypy/module/struct/test/test_struct.py
+++ b/pypy/module/struct/test/test_struct.py
@@ -7,7 +7,7 @@
class AppTestStruct(object):
- spaceconfig = dict(usemodules=['struct'])
+ spaceconfig = dict(usemodules=['struct', 'micronumpy'])
def setup_class(cls):
"""
@@ -19,7 +19,7 @@
return struct
""")
cls.w_native_is_bigendian = cls.space.wrap(native_is_bigendian)
-
+ cls.w_runappdirect = cls.space.wrap(cls.runappdirect)
def test_error(self):
"""
@@ -384,6 +384,19 @@
assert self.struct.unpack("ii", b) == (62, 12)
raises(self.struct.error, self.struct.unpack, "i", b)
+ def test___float__(self):
+ class MyFloat(object):
+ def __init__(self, x):
+ self.x = x
+ def __float__(self):
+ return self.x
+
+ obj = MyFloat(42.3)
+ data = self.struct.pack('d', obj)
+ obj2, = self.struct.unpack('d', data)
+ assert type(obj2) is float
+ assert obj2 == 42.3
+
class AppTestStructBuffer(object):
spaceconfig = dict(usemodules=['struct', '__pypy__'])
diff --git a/pypy/objspace/fake/objspace.py b/pypy/objspace/fake/objspace.py
--- a/pypy/objspace/fake/objspace.py
+++ b/pypy/objspace/fake/objspace.py
@@ -45,13 +45,13 @@
def unicode_w(self, space):
return NonConstant(u"foobar")
- def int_w(self, space):
+ def int_w(self, space, allow_conversion=True):
return NonConstant(-42)
def uint_w(self, space):
return r_uint(NonConstant(42))
- def bigint_w(self, space):
+ def bigint_w(self, space, allow_conversion=True):
from rpython.rlib.rbigint import rbigint
return rbigint.fromint(NonConstant(42))
@@ -117,7 +117,7 @@
def _freeze_(self):
return True
- def float_w(self, w_obj):
+ def float_w(self, w_obj, allow_conversion=True):
is_root(w_obj)
return NonConstant(42.5)
diff --git a/pypy/objspace/std/floatobject.py b/pypy/objspace/std/floatobject.py
--- a/pypy/objspace/std/floatobject.py
+++ b/pypy/objspace/std/floatobject.py
@@ -34,7 +34,16 @@
def unwrap(self, space):
return self.floatval
- def float_w(self, space):
+ def int_w(self, space, allow_conversion=True):
+ self._typed_unwrap_error(space, "integer")
+
+ def bigint_w(self, space, allow_conversion=True):
+ self._typed_unwrap_error(space, "integer")
+
+ def float_w(self, space, allow_conversion=True):
+ return self.floatval
+
+ def _float_w(self, space):
return self.floatval
def int(self, space):
diff --git a/pypy/objspace/std/intobject.py b/pypy/objspace/std/intobject.py
--- a/pypy/objspace/std/intobject.py
+++ b/pypy/objspace/std/intobject.py
@@ -42,7 +42,8 @@
return False
if self.user_overridden_class or w_other.user_overridden_class:
return self is w_other
- return space.int_w(self) == space.int_w(w_other)
+ return (space.int_w(self, allow_conversion=False) ==
+ space.int_w(w_other, allow_conversion=False))
def immutable_unique_id(self, space):
if self.user_overridden_class:
@@ -309,9 +310,13 @@
"""representation for debugging purposes"""
return "%s(%d)" % (self.__class__.__name__, self.intval)
- def int_w(self, space):
+ def int_w(self, space, allow_conversion=True):
return int(self.intval)
- unwrap = int_w
+
+ def _int_w(self, space):
+ return int(self.intval)
+
+ unwrap = _int_w
def uint_w(self, space):
intval = self.intval
@@ -320,12 +325,18 @@
"cannot convert negative integer to unsigned")
return r_uint(intval)
- def bigint_w(self, space):
+ def bigint_w(self, space, allow_conversion=True):
return rbigint.fromint(self.intval)
- def float_w(self, space):
+ def _bigint_w(self, space):
+ return rbigint.fromint(self.intval)
+
+ def float_w(self, space, allow_conversion=True):
return float(self.intval)
+ # note that we do NOT implement _float_w, because __float__ cannot return
+ # an int
+
def int(self, space):
if type(self) is W_IntObject:
return self
@@ -665,7 +676,7 @@
# int_w is effectively what we want in this case,
# we cannot construct a subclass of int instance with an
# an overflowing long
- value = space.int_w(w_obj)
+ value = space.int_w(w_obj, allow_conversion=False)
elif space.isinstance_w(w_value, space.w_str):
value, w_longval = _string_to_int_or_long(space, w_value,
space.str_w(w_value))
diff --git a/pypy/objspace/std/longobject.py b/pypy/objspace/std/longobject.py
--- a/pypy/objspace/std/longobject.py
+++ b/pypy/objspace/std/longobject.py
@@ -244,7 +244,7 @@
def fromrarith_int(i):
return W_LongObject(rbigint.fromrarith_int(i))
- def int_w(self, space):
+ def _int_w(self, space):
try:
return self.num.toint()
except OverflowError:
@@ -261,10 +261,16 @@
raise oefmt(space.w_OverflowError,
"long int too large to convert to unsigned int")
- def bigint_w(self, space):
+ def bigint_w(self, space, allow_conversion=True):
return self.num
- def float_w(self, space):
+ def _bigint_w(self, space):
+ return self.num
+
+ def float_w(self, space, allow_conversion=True):
+ return self.tofloat(space)
+
+ def _float_w(self, space):
return self.tofloat(space)
def int(self, space):
diff --git a/pypy/objspace/std/smalllongobject.py b/pypy/objspace/std/smalllongobject.py
--- a/pypy/objspace/std/smalllongobject.py
+++ b/pypy/objspace/std/smalllongobject.py
@@ -44,7 +44,7 @@
def __repr__(self):
return '<W_SmallLongObject(%d)>' % self.longlong
- def int_w(self, space):
+ def _int_w(self, space):
a = self.longlong
b = intmask(a)
if b == a:
@@ -63,10 +63,13 @@
raise oefmt(space.w_OverflowError,
"long int too large to convert to unsigned int")
- def bigint_w(self, space):
+ def bigint_w(self, space, allow_conversion=True):
return self.asbigint()
- def float_w(self, space):
+ def _bigint_w(self, space):
+ return self.asbigint()
+
+ def _float_w(self, space):
return float(self.longlong)
def int(self, space):
diff --git a/pypy/objspace/std/test/test_dictmultiobject.py b/pypy/objspace/std/test/test_dictmultiobject.py
--- a/pypy/objspace/std/test/test_dictmultiobject.py
+++ b/pypy/objspace/std/test/test_dictmultiobject.py
@@ -1046,7 +1046,7 @@
assert isinstance(string, str)
return string
- def int_w(self, integer):
+ def int_w(self, integer, allow_conversion=True):
assert isinstance(integer, int)
return integer
diff --git a/pypy/objspace/std/test/test_intobject.py b/pypy/objspace/std/test/test_intobject.py
--- a/pypy/objspace/std/test/test_intobject.py
+++ b/pypy/objspace/std/test/test_intobject.py
@@ -553,6 +553,15 @@
assert 3 .__coerce__(4) == (3, 4)
assert 3 .__coerce__(4L) == NotImplemented
+ def test_fake_int_as_base(self):
+ class MyInt(object):
+ def __init__(self, x):
+ self.x = x
+ def __int__(self):
+ return self.x
+
+ base = MyInt(24)
+ assert int('10', base) == 24
class AppTestIntShortcut(AppTestInt):
spaceconfig = {"objspace.std.intshortcut": True}
diff --git a/pypy/objspace/std/test/test_listobject.py b/pypy/objspace/std/test/test_listobject.py
--- a/pypy/objspace/std/test/test_listobject.py
+++ b/pypy/objspace/std/test/test_listobject.py
@@ -842,6 +842,26 @@
except TypeError:
pass
+ def test_mul___index__(self):
+ class MyInt(object):
+ def __init__(self, x):
+ self.x = x
+
+ def __int__(self):
+ return self.x
+
+ class MyIndex(object):
+ def __init__(self, x):
+ self.x = x
+
+ def __index__(self):
+ return self.x
+
+ assert [0] * MyIndex(3) == [0, 0, 0]
+ raises(TypeError, "[0]*MyInt(3)")
+ raises(TypeError, "[0]*MyIndex(MyInt(3))")
+
+
def test_index(self):
c = range(10)
assert c.index(0) == 0
diff --git a/pypy/objspace/std/test/test_stringformat.py b/pypy/objspace/std/test/test_stringformat.py
--- a/pypy/objspace/std/test/test_stringformat.py
+++ b/pypy/objspace/std/test/test_stringformat.py
@@ -186,6 +186,22 @@
def test_broken_unicode(self):
raises(UnicodeDecodeError, 'Názov: %s'.__mod__, u'Jerry')
+ def test___int__(self):
+ class MyInt(object):
+ def __init__(self, x):
+ self.x = x
+ def __int__(self):
+ return self.x
+ #
+ x = MyInt(65)
+ assert '%c' % x == 'A'
+
+
+class Foo(object):
+ def __cmp__(self, other):
+ return MyInt(0)
+
+
class AppTestWidthPrec:
def test_width(self):
a = 'a'
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
@@ -721,8 +721,19 @@
return CannotConvertToBool()
x = X()
raises(MyError, "'foo' in x")
-
-
+
+ def test___cmp___fake_int(self):
+ class MyInt(object):
+ def __init__(self, x):
+ self.x = x
+ def __int__(self):
+ return self.x
+ class X(object):
+ def __cmp__(self, other):
+ return MyInt(0)
+
+ assert X() == 'hello'
+
class AppTestWithBuiltinShortcut(AppTest_Descroperation):
spaceconfig = {'objspace.std.builtinshortcut': True}
More information about the pypy-commit
mailing list