Author: Armin Rigo <ar...@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: _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit