[pypy-commit] pypy default: Fix PyLong_FromVoidPtr to return int/long like CPython.
arigo
pypy.commits at gmail.com
Sun Sep 18 13:11:48 EDT 2016
Author: Armin Rigo <arigo at tunes.org>
Branch:
Changeset: r87204:8bbafbedd0b2
Date: 2016-09-18 19:11 +0200
http://bitbucket.org/pypy/pypy/changeset/8bbafbedd0b2/
Log: Fix PyLong_FromVoidPtr to return int/long like CPython. Hopefully
fix a translation failure on 32-bit too.
diff --git a/pypy/module/cpyext/longobject.py b/pypy/module/cpyext/longobject.py
--- a/pypy/module/cpyext/longobject.py
+++ b/pypy/module/cpyext/longobject.py
@@ -6,7 +6,6 @@
from pypy.interpreter.error import OperationError
from pypy.module.cpyext.intobject import PyInt_AsUnsignedLongMask
from rpython.rlib.rbigint import rbigint
-from rpython.rlib.rarithmetic import widen
PyLong_Check, PyLong_CheckExact = build_type_checkers("Long")
@@ -28,25 +27,25 @@
"""Return a new PyLongObject object from a C size_t, or NULL on
failure.
"""
- return space.wrap(val)
+ return space.newlong_from_rarith_int(val)
@cpython_api([rffi.LONGLONG], PyObject)
def PyLong_FromLongLong(space, val):
"""Return a new PyLongObject object from a C long long, or NULL
on failure."""
- return space.newlong(val)
+ return space.newlong_from_rarith_int(val)
@cpython_api([rffi.ULONG], PyObject)
def PyLong_FromUnsignedLong(space, val):
"""Return a new PyLongObject object from a C unsigned long, or
NULL on failure."""
- return space.wrap(val)
+ return space.newlong_from_rarith_int(val)
@cpython_api([rffi.ULONGLONG], PyObject)
def PyLong_FromUnsignedLongLong(space, val):
"""Return a new PyLongObject object from a C unsigned long long,
or NULL on failure."""
- return space.wrap(val)
+ return space.newlong_from_rarith_int(val)
@cpython_api([PyObject], rffi.ULONG, error=-1)
def PyLong_AsUnsignedLong(space, w_long):
@@ -203,7 +202,10 @@
can be retrieved from the resulting value using PyLong_AsVoidPtr().
If the integer is larger than LONG_MAX, a positive long integer is returned."""
- return space.newlong(rffi.cast(ADDR, p))
+ value = rffi.cast(ADDR, p) # signed integer
+ if value < 0:
+ return space.newlong_from_rarith_int(rffi.cast(lltype.Unsigned, p))
+ return space.wrap(value)
@cpython_api([PyObject], rffi.VOIDP, error=lltype.nullptr(rffi.VOIDP.TO))
def PyLong_AsVoidPtr(space, w_long):
diff --git a/pypy/module/cpyext/test/test_longobject.py b/pypy/module/cpyext/test/test_longobject.py
--- a/pypy/module/cpyext/test/test_longobject.py
+++ b/pypy/module/cpyext/test/test_longobject.py
@@ -1,5 +1,6 @@
import sys, py
from rpython.rtyper.lltypesystem import rffi, lltype
+from rpython.rlib.rarithmetic import maxint
from pypy.objspace.std.intobject import W_IntObject
from pypy.objspace.std.longobject import W_LongObject
from pypy.module.cpyext.test.test_api import BaseApiTest
@@ -108,10 +109,26 @@
lltype.free(overflow, flavor='raw')
def test_as_voidptr(self, space, api):
+ # CPython returns an int (not a long) depending on the value
+ # passed to PyLong_FromVoidPtr(). In all cases, NULL becomes
+ # the int 0.
w_l = api.PyLong_FromVoidPtr(lltype.nullptr(rffi.VOIDP.TO))
- assert isinstance(w_l, W_LongObject)
- assert space.unwrap(w_l) == 0L
+ assert space.is_w(space.type(w_l), space.w_int)
+ assert space.unwrap(w_l) == 0
assert api.PyLong_AsVoidPtr(w_l) == lltype.nullptr(rffi.VOIDP.TO)
+ # Positive values also return an int (assuming, like always in
+ # PyPy, that an int is big enough to store any pointer).
+ p = rffi.cast(rffi.VOIDP, maxint)
+ w_l = api.PyLong_FromVoidPtr(p)
+ assert space.is_w(space.type(w_l), space.w_int)
+ assert space.unwrap(w_l) == maxint
+ assert api.PyLong_AsVoidPtr(w_l) == p
+ # Negative values always return a long.
+ p = rffi.cast(rffi.VOIDP, -maxint-1)
+ w_l = api.PyLong_FromVoidPtr(p)
+ assert space.is_w(space.type(w_l), space.w_long)
+ assert space.unwrap(w_l) == maxint+1
+ assert api.PyLong_AsVoidPtr(w_l) == p
def test_sign_and_bits(self, space, api):
if space.is_true(space.lt(space.sys.get('version_info'),
diff --git a/pypy/objspace/std/objspace.py b/pypy/objspace/std/objspace.py
--- a/pypy/objspace/std/objspace.py
+++ b/pypy/objspace/std/objspace.py
@@ -270,6 +270,9 @@
return W_SmallLongObject.fromint(val)
return W_LongObject.fromint(self, val)
+ def newlong_from_rarith_int(self, val): # val is an rarithmetic type
+ return W_LongObject.fromrarith_int(val)
+
def newlong_from_rbigint(self, val):
return newlong(self, val)
diff --git a/pypy/objspace/std/test/test_longobject.py b/pypy/objspace/std/test/test_longobject.py
--- a/pypy/objspace/std/test/test_longobject.py
+++ b/pypy/objspace/std/test/test_longobject.py
@@ -25,7 +25,6 @@
space.raises_w(space.w_OverflowError, space.float_w, w_big)
def test_rint_variants(self):
- py.test.skip("XXX broken!")
from rpython.rtyper.tool.rfficache import platform
space = self.space
for r in platform.numbertype_to_rclass.values():
@@ -36,8 +35,8 @@
for x in values:
if not r.SIGNED:
x &= r.MASK
- w_obj = space.wrap(r(x))
- assert space.bigint_w(w_obj).eq(rbigint.fromint(x))
+ w_obj = space.newlong_from_rarith_int(r(x))
+ assert space.bigint_w(w_obj).eq(rbigint.fromlong(x))
class AppTestLong:
More information about the pypy-commit
mailing list