[pypy-commit] pypy default: Support PY_SSIZE_T_CLEAN, part 1
arigo
noreply at buildbot.pypy.org
Mon Nov 11 10:46:27 CET 2013
Author: Armin Rigo <arigo at tunes.org>
Branch:
Changeset: r67948:b41903344f4c
Date: 2013-11-11 10:03 +0100
http://bitbucket.org/pypy/pypy/changeset/b41903344f4c/
Log: Support PY_SSIZE_T_CLEAN, part 1
diff --git a/pypy/module/cpyext/api.py b/pypy/module/cpyext/api.py
--- a/pypy/module/cpyext/api.py
+++ b/pypy/module/cpyext/api.py
@@ -386,12 +386,14 @@
'PyString_FromFormat', 'PyString_FromFormatV',
'PyModule_AddObject', 'PyModule_AddIntConstant', 'PyModule_AddStringConstant',
'Py_BuildValue', 'Py_VaBuildValue', 'PyTuple_Pack',
+ '_Py_BuildValue_SizeT', '_Py_VaBuildValue_SizeT',
'PyErr_Format', 'PyErr_NewException', 'PyErr_NewExceptionWithDoc',
'PySys_WriteStdout', 'PySys_WriteStderr',
'PyEval_CallFunction', 'PyEval_CallMethod', 'PyObject_CallFunction',
'PyObject_CallMethod', 'PyObject_CallFunctionObjArgs', 'PyObject_CallMethodObjArgs',
+ '_PyObject_CallFunction_SizeT', '_PyObject_CallMethod_SizeT',
'PyBuffer_FromMemory', 'PyBuffer_FromReadWriteMemory', 'PyBuffer_FromObject',
'PyBuffer_FromReadWriteObject', 'PyBuffer_New', 'PyBuffer_Type', 'init_bufferobject',
diff --git a/pypy/module/cpyext/include/eval.h b/pypy/module/cpyext/include/eval.h
--- a/pypy/module/cpyext/include/eval.h
+++ b/pypy/module/cpyext/include/eval.h
@@ -9,6 +9,11 @@
#include "Python.h"
+#ifdef PY_SSIZE_T_CLEAN
+#define PyPyObject_CallFunction _PyPyObject_CallFunction_SizeT
+#define PyPyObject_CallMethod _PyPyObject_CallMethod_SizeT
+#endif
+
#define PyEval_CallObject(func,arg) \
PyEval_CallObjectWithKeywords(func, arg, (PyObject *)NULL)
@@ -16,6 +21,8 @@
PyObject * PyEval_CallMethod(PyObject *obj, const char *name, const char *format, ...);
PyObject * PyObject_CallFunction(PyObject *obj, const char *format, ...);
PyObject * PyObject_CallMethod(PyObject *obj, const char *name, const char *format, ...);
+PyObject * _PyObject_CallFunction_SizeT(PyObject *obj, const char *format, ...);
+PyObject * _PyObject_CallMethod_SizeT(PyObject *obj, const char *name, const char *format, ...);
PyObject * PyObject_CallFunctionObjArgs(PyObject *callable, ...);
PyObject * PyObject_CallMethodObjArgs(PyObject *callable, PyObject *name, ...);
diff --git a/pypy/module/cpyext/include/modsupport.h b/pypy/module/cpyext/include/modsupport.h
--- a/pypy/module/cpyext/include/modsupport.h
+++ b/pypy/module/cpyext/include/modsupport.h
@@ -7,6 +7,14 @@
extern "C" {
#endif
+/* If PY_SSIZE_T_CLEAN is defined, each functions treats #-specifier
+ to mean Py_ssize_t */
+#ifdef PY_SSIZE_T_CLEAN
+#define PyPy_BuildValue _PyPy_BuildValue_SizeT
+#define PyPy_VaBuildValue _PyPy_VaBuildValue_SizeT
+ /*XXX more*/
+#endif
+
#define PYTHON_API_VERSION 1013
#define PYTHON_API_STRING "1013"
diff --git a/pypy/module/cpyext/src/abstract.c b/pypy/module/cpyext/src/abstract.c
--- a/pypy/module/cpyext/src/abstract.c
+++ b/pypy/module/cpyext/src/abstract.c
@@ -150,6 +150,26 @@
}
PyObject *
+_PyObject_CallFunction_SizeT(PyObject *callable, const char *format, ...)
+{
+ va_list va;
+ PyObject *args;
+
+ if (callable == NULL)
+ return null_error();
+
+ if (format && *format) {
+ va_start(va, format);
+ args = _Py_VaBuildValue_SizeT(format, va);
+ va_end(va);
+ }
+ else
+ args = PyTuple_New(0);
+
+ return call_function_tail(callable, args);
+}
+
+PyObject *
PyObject_CallMethod(PyObject *o, const char *name, const char *format, ...)
{
va_list va;
@@ -188,6 +208,45 @@
return retval;
}
+PyObject *
+_PyObject_CallMethod_SizeT(PyObject *o, const char *name, const char *format, ...)
+{
+ va_list va;
+ PyObject *args;
+ PyObject *func = NULL;
+ PyObject *retval = NULL;
+
+ if (o == NULL || name == NULL)
+ return null_error();
+
+ func = PyObject_GetAttrString(o, name);
+ if (func == NULL) {
+ PyErr_SetString(PyExc_AttributeError, name);
+ return 0;
+ }
+
+ if (!PyCallable_Check(func)) {
+ type_error("attribute of type '%.200s' is not callable", func);
+ goto exit;
+ }
+
+ if (format && *format) {
+ va_start(va, format);
+ args = _Py_VaBuildValue_SizeT(format, va);
+ va_end(va);
+ }
+ else
+ args = PyTuple_New(0);
+
+ retval = call_function_tail(func, args);
+
+ exit:
+ /* args gets consumed in call_function_tail */
+ Py_XDECREF(func);
+
+ return retval;
+}
+
static PyObject *
objargs_mktuple(va_list va)
{
diff --git a/pypy/module/cpyext/test/test_cpyext.py b/pypy/module/cpyext/test/test_cpyext.py
--- a/pypy/module/cpyext/test/test_cpyext.py
+++ b/pypy/module/cpyext/test/test_cpyext.py
@@ -229,9 +229,11 @@
return space.wrap(pydname)
@unwrap_spec(name=str, init='str_or_None', body=str,
- load_it=bool, filename='str_or_None')
+ load_it=bool, filename='str_or_None',
+ PY_SSIZE_T_CLEAN=bool)
def import_module(space, name, init=None, body='',
- load_it=True, filename=None):
+ load_it=True, filename=None,
+ PY_SSIZE_T_CLEAN=False):
"""
init specifies the overall template of the module.
@@ -243,15 +245,19 @@
"""
if init is not None:
code = """
+ %(PY_SSIZE_T_CLEAN)s
#include <Python.h>
%(body)s
void init%(name)s(void) {
%(init)s
}
- """ % dict(name=name, init=init, body=body)
+ """ % dict(name=name, init=init, body=body,
+ PY_SSIZE_T_CLEAN='#define PY_SSIZE_T_CLEAN'
+ if PY_SSIZE_T_CLEAN else '')
kwds = dict(separate_module_sources=[code])
else:
+ assert not PY_SSIZE_T_CLEAN
if filename is None:
filename = name
filename = py.path.local(pypydir) / 'module' \
@@ -276,8 +282,9 @@
space.sys.get('modules'),
space.wrap(name))
- @unwrap_spec(modname=str, prologue=str)
- def import_extension(space, modname, w_functions, prologue=""):
+ @unwrap_spec(modname=str, prologue=str, PY_SSIZE_T_CLEAN=bool)
+ def import_extension(space, modname, w_functions, prologue="",
+ PY_SSIZE_T_CLEAN=False):
functions = space.unwrap(w_functions)
methods_table = []
codes = []
@@ -300,7 +307,8 @@
};
""" % ('\n'.join(methods_table),)
init = """Py_InitModule("%s", methods);""" % (modname,)
- return import_module(space, name=modname, init=init, body=body)
+ return import_module(space, name=modname, init=init, body=body,
+ PY_SSIZE_T_CLEAN=PY_SSIZE_T_CLEAN)
@unwrap_spec(name=str)
def record_imported_module(name):
diff --git a/pypy/module/cpyext/test/test_eval.py b/pypy/module/cpyext/test/test_eval.py
--- a/pypy/module/cpyext/test/test_eval.py
+++ b/pypy/module/cpyext/test/test_eval.py
@@ -212,7 +212,7 @@
("call_func", "METH_VARARGS",
"""
return PyObject_CallFunction(PyTuple_GetItem(args, 0),
- "siO", "text", 42, Py_None);
+ "siiiiO", "text", 42, -41, 40, -39, Py_None);
"""),
("call_method", "METH_VARARGS",
"""
@@ -222,9 +222,28 @@
])
def f(*args):
return args
- assert module.call_func(f) == ("text", 42, None)
+ assert module.call_func(f) == ("text", 42, -41, 40, -39, None)
assert module.call_method("text") == 2
+ def test_CallFunction_PY_SSIZE_T_CLEAN(self):
+ module = self.import_extension('foo', [
+ ("call_func", "METH_VARARGS",
+ """
+ return PyObject_CallFunction(PyTuple_GetItem(args, 0),
+ "s#s#", "text", (Py_ssize_t)3, "othertext", (Py_ssize_t)6);
+ """),
+ ("call_method", "METH_VARARGS",
+ """
+ return PyObject_CallMethod(PyTuple_GetItem(args, 0),
+ "find", "s#", "substring", (Py_ssize_t)6);
+ """),
+ ], PY_SSIZE_T_CLEAN=True)
+ def f(*args):
+ return args
+ assert module.call_func(f) == ("tex", "othert")
+ assert module.call_method("<<subst>>") == -1
+ assert module.call_method("<<substr>>") == 2
+
def test_CallFunctionObjArgs(self):
module = self.import_extension('foo', [
("call_func", "METH_VARARGS",
More information about the pypy-commit
mailing list