Commit b24811ed authored by Matti Picus's avatar Matti Picus
Browse files

test, fix partial implementation of PyNumber_AsSsize_t (issue 3456)

parent 94a59bb6a291
Pipeline #21559 passed with stage
in 7 minutes and 46 seconds
......@@ -136,6 +136,7 @@ METH_NOARGS METH_VARARGS METH_KEYWORDS METH_O Py_TPFLAGS_HAVE_INPLACEOPS
Py_TPFLAGS_HEAPTYPE Py_TPFLAGS_HAVE_CLASS Py_TPFLAGS_HAVE_NEWBUFFER
Py_LT Py_LE Py_EQ Py_NE Py_GT Py_GE Py_TPFLAGS_CHECKTYPES Py_MAX_NDIMS
PyBUF_FORMAT PyBUF_ND PyBUF_STRIDES PyBUF_WRITABLE PyBUF_READ PyBUF_WRITE
PY_SSIZE_T_MAX PY_SSIZE_T_MIN
""".split()
for name in ('INT', 'LONG', 'LIST', 'TUPLE', 'UNICODE', 'DICT', 'BASE_EXC',
......
from pypy.interpreter.error import OperationError, oefmt
from pypy.module.cpyext.api import cpython_api, CANNOT_FAIL, Py_ssize_t
from pypy.module.cpyext.api import (
cpython_api, CANNOT_FAIL, Py_ssize_t, PyVarObject, PY_SSIZE_T_MAX,
PY_SSIZE_T_MIN)
from pypy.module.cpyext.pyobject import PyObject, PyObjectP, from_ref, make_ref
from rpython.rtyper.lltypesystem import rffi, lltype
from rpython.rlib.rarithmetic import widen
......@@ -40,7 +42,22 @@ def PyNumber_AsSsize_t(space, w_obj, w_exc):
exception is cleared and the value is clipped to PY_SSIZE_T_MIN for a negative
integer or PY_SSIZE_T_MAX for a positive integer.
"""
return space.int_w(w_obj) #XXX: this is wrong on win64
try:
return space.int_w(w_obj) #XXX: this is wrong on win64
  • I believe the win64 comment is no longer needed as it refers to the old assumption of sizeof(Signed) == sizeof(long). space.int_w converts to Signed which now matches ssize_t/Py_ssize_t on all supported platforms.

Please register or sign in to reply
except OperationError as e:
if e.match(space, space.w_OverflowError):
if not w_exc:
# CPython does _PyLong_Sign(value) < 0 which is equivalent to
# Py_SIZE(value) < 0 which is value->ob_size
pyobj = make_ref(space, w_obj)
if rffi.cast(PyVarObject, pyobj).c_ob_size < 0:
return PY_SSIZE_T_MIN
else:
return PY_SSIZE_T_MAX
else:
raise oefmt(w_exc, "cannot fit '%T' into an index-sized integer", w_obj)
else:
raise
@cpython_api([PyObject], PyObject)
def PyNumber_Int(space, w_obj):
......
......@@ -211,3 +211,32 @@ class AppTestCNumber(AppTestCpythonExtensionBase):
pass
else:
assert False, 'expected TypeError'
def test_number_to_ssize_t(self):
import sys
mod = self.import_extension('foo', [
("to_ssize_t", "METH_VARARGS",
"""
PyObject *obj;
PyObject *exc = NULL;
long long value;
if (!PyArg_ParseTuple(args, "O|O:to_ssize_t",
&obj, &exc)) {
return NULL;
}
if (exc == NULL) {
printf("got no exc\\n");
} else {
printf("got exc\\n");
}
value = PyNumber_AsSsize_t(obj, exc);
if (PyErr_Occurred()) {
return NULL;
}
return PyLong_FromLongLong(value);
""")])
assert mod.to_ssize_t(2 ** 68) == sys.maxsize
assert mod.to_ssize_t(12) == 12
raises(TypeError, mod.to_ssize_t, 2 ** 68, TypeError)
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment