Author: Amaury Forgeot d'Arc <[email protected]>
Branch: py3k
Changeset: r59096:aa8d1f836403
Date: 2012-11-23 22:30 +0100
http://bitbucket.org/pypy/pypy/changeset/aa8d1f836403/
Log: cpyext now use the Python3 way to declare builtin modules!
Surprisingly easy change.
Only array.c was ported to the new scheme, it's now an exact copy
from CPython Modules/arraymodule.c. All other test modules need to
be migrated.
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
@@ -1021,7 +1021,7 @@
trunk_include = pypydir.dirpath() / 'include'
copy_header_files(trunk_include)
-initfunctype = lltype.Ptr(lltype.FuncType([], lltype.Void))
+initfunctype = lltype.Ptr(lltype.FuncType([], PyObject))
@unwrap_spec(path=str, name=str)
def load_extension_module(space, path, name):
if os.sep not in path:
@@ -1045,14 +1045,14 @@
"unable to load extension module '%s': %s",
path, e.msg)
try:
- initptr = rdynload.dlsym(dll, 'init%s' % (name.split('.')[-1],))
+ initptr = rdynload.dlsym(dll, 'PyInit_%s' % (name.split('.')[-1],))
except KeyError:
raise operationerrfmt(
space.w_ImportError,
"function init%s not found in library %s",
name, path)
initfunc = rffi.cast(initfunctype, initptr)
- generic_cpy_call(space, initfunc)
+ w_mod = generic_cpy_call(space, initfunc)
state.check_and_raise_exception()
finally:
state.package_context = old_context
diff --git a/pypy/module/cpyext/include/Python.h
b/pypy/module/cpyext/include/Python.h
--- a/pypy/module/cpyext/include/Python.h
+++ b/pypy/module/cpyext/include/Python.h
@@ -100,6 +100,7 @@
#include "methodobject.h"
#include "funcobject.h"
+#include "moduleobject.h"
#include "modsupport.h"
#include "pythonrun.h"
#include "pyerrors.h"
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
@@ -11,6 +11,11 @@
#define PYTHON_API_VERSION 1013
#define PYTHON_API_STRING "1013"
+/* The PYTHON_ABI_VERSION is introduced in PEP 384. For the lifetime of
+ Python 3, it will stay at the value of 3; changes to the limited API
+ must be performed in a strictly backwards-compatible manner. */
+#define PYTHON_ABI_VERSION 3
+#define PYTHON_ABI_STRING "3"
int PyArg_Parse(PyObject *, const char *, ...);
int PyArg_ParseTuple(PyObject *, const char *, ...);
@@ -21,18 +26,15 @@
int PyArg_VaParseTupleAndKeywords(PyObject *, PyObject *,
const char *, char **, va_list);
-/* to make sure that modules compiled with CPython's or PyPy's Python.h
- are not importable on the other interpreter, use a #define to expect a
- different symbol: (this function is implemented in ../modsupport.py) */
-#define Py_InitModule4 _Py_InitPyPyModule
-
-#define Py_InitModule(name, methods) \
- Py_InitModule4(name, methods, (char *)NULL, (PyObject *)NULL, \
- PYTHON_API_VERSION)
-
-#define Py_InitModule3(name, methods, doc) \
- Py_InitModule4(name, methods, doc, (PyObject *)NULL, \
- PYTHON_API_VERSION)
+PyAPI_FUNC(PyObject *) PyModule_Create2(struct PyModuleDef*,
+ int apiver);
+#ifdef Py_LIMITED_API
+#define PyModule_Create(module) \
+ PyModule_Create2(module, PYTHON_ABI_VERSION)
+#else
+#define PyModule_Create(module) \
+ PyModule_Create2(module, PYTHON_API_VERSION)
+#endif
int PyModule_AddObject(PyObject *m, const char *name, PyObject *o);
int PyModule_AddIntConstant(PyObject *m, const char *name, long value);
@@ -53,9 +55,9 @@
* This is from pyport.h. Perhaps it belongs elsewhere.
*/
#ifdef __cplusplus
-#define PyMODINIT_FUNC extern "C" void
+#define PyMODINIT_FUNC extern "C" PyObject*
#else
-#define PyMODINIT_FUNC void
+#define PyMODINIT_FUNC PyObject*
#endif
diff --git a/pypy/module/cpyext/include/moduleobject.h
b/pypy/module/cpyext/include/moduleobject.h
new file mode 100644
--- /dev/null
+++ b/pypy/module/cpyext/include/moduleobject.h
@@ -0,0 +1,38 @@
+/* Module object interface */
+
+#ifndef Py_MODULEOBJECT_H
+#define Py_MODULEOBJECT_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct PyModuleDef_Base {
+ PyObject_HEAD
+ PyObject* (*m_init)(void);
+ Py_ssize_t m_index;
+ PyObject* m_copy;
+} PyModuleDef_Base;
+
+#define PyModuleDef_HEAD_INIT { \
+ PyObject_HEAD_INIT(NULL) \
+ NULL, /* m_init */ \
+ 0, /* m_index */ \
+ NULL, /* m_copy */ \
+ }
+
+typedef struct PyModuleDef{
+ PyModuleDef_Base m_base;
+ const char* m_name;
+ const char* m_doc;
+ Py_ssize_t m_size;
+ PyMethodDef *m_methods;
+ inquiry m_reload;
+ traverseproc m_traverse;
+ inquiry m_clear;
+ freefunc m_free;
+}PyModuleDef;
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* !Py_MODULEOBJECT_H */
diff --git a/pypy/module/cpyext/modsupport.py b/pypy/module/cpyext/modsupport.py
--- a/pypy/module/cpyext/modsupport.py
+++ b/pypy/module/cpyext/modsupport.py
@@ -10,6 +10,19 @@
from pypy.module.cpyext.state import State
from pypy.interpreter.error import OperationError
+PyModuleDef_BaseStruct = cpython_struct(
+ 'PyModuleDef_Base',
+ [])
+
+PyModuleDefStruct = cpython_struct(
+ 'PyModuleDef',
+ [('m_base', PyModuleDef_BaseStruct),
+ ('m_name', rffi.CCHARP),
+ ('m_doc', rffi.CCHARP),
+ ('m_methods', lltype.Ptr(PyMethodDef)),
+ ], level=2)
+PyModuleDef = lltype.Ptr(PyModuleDefStruct)
+
#@cpython_api([rffi.CCHARP], PyObject)
def PyImport_AddModule(space, name):
"""Return the module object corresponding to a module name. The name
argument
@@ -31,27 +44,20 @@
return w_mod
-# This is actually the Py_InitModule4 function,
-# renamed to refuse modules built against CPython headers.
-@cpython_api([CONST_STRING, lltype.Ptr(PyMethodDef), CONST_STRING,
- PyObject, rffi.INT_real], PyObject)
-def _Py_InitPyPyModule(space, name, methods, doc, w_self, apiver):
- """
- Create a new module object based on a name and table of functions,
returning
- the new module object. If doc is non-NULL, it will be used to define the
- docstring for the module. If self is non-NULL, it will passed to the
- functions of the module as their (otherwise NULL) first parameter. (This
was
- added as an experimental feature, and there are no known uses in the
current
- version of Python.) For apiver, the only value which should be passed is
- defined by the constant PYTHON_API_VERSION.
+@cpython_api([PyModuleDef, rffi.INT_real], PyObject)
+def PyModule_Create2(space, module, api_version):
+ """Create a new module object, given the definition in module, assuming the
+ API version module_api_version. If that version does not match the version
+ of the running interpreter, a RuntimeWarning is emitted.
+
+ Most uses of this function should be using PyModule_Create()
+ instead; only use this if you are sure you need it."""
- Note that the name parameter is actually ignored, and the module name is
- taken from the package_context attribute of the cpyext.State in the space
- cache. CPython includes some extra checking here to make sure the module
- being initialized lines up with what's expected, but we don't.
- """
- from pypy.module.cpyext.typeobjectdefs import PyTypeObjectPtr
- modname = rffi.charp2str(name)
+ modname = rffi.charp2str(module.c_m_name)
+ if module.c_m_doc:
+ doc = rffi.charp2str(module.c_m_doc)
+ methods = module.c_m_methods
+
state = space.fromcache(State)
f_name, f_path = state.package_context
if f_name is not None:
@@ -63,13 +69,13 @@
dict_w = {'__file__': space.wrap(f_path)}
else:
dict_w = {}
- convert_method_defs(space, dict_w, methods, None, w_self, modname)
+ convert_method_defs(space, dict_w, methods, None, w_mod, modname)
for key, w_value in dict_w.items():
space.setattr(w_mod, space.wrap(key), w_value)
if doc:
space.setattr(w_mod, space.wrap("__doc__"),
- space.wrap(rffi.charp2str(doc)))
- return borrow_from(None, w_mod)
+ space.wrap(doc))
+ return w_mod
def convert_method_defs(space, dict_w, methods, w_type, w_self=None,
name=None):
diff --git a/pypy/module/cpyext/test/array.c b/pypy/module/cpyext/test/array.c
--- a/pypy/module/cpyext/test/array.c
+++ b/pypy/module/cpyext/test/array.c
@@ -2719,9 +2719,21 @@
{NULL, NULL, 0, NULL} /* Sentinel */
};
+static struct PyModuleDef arraymodule = {
+ PyModuleDef_HEAD_INIT,
+ "array",
+ module_doc,
+ -1,
+ a_methods,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
+
PyMODINIT_FUNC
-initarray(void)
+PyInit_array(void)
{
PyObject *m;
PyObject *typecodes;
@@ -2730,11 +2742,11 @@
struct arraydescr *descr;
if (PyType_Ready(&Arraytype) < 0)
- return;
+ return NULL;
Py_TYPE(&PyArrayIter_Type) = &PyType_Type;
- m = Py_InitModule3("array", a_methods, module_doc);
+ m = PyModule_Create(&arraymodule);
if (m == NULL)
- return;
+ return NULL;
Py_INCREF((PyObject *)&Arraytype);
PyModule_AddObject(m, "ArrayType", (PyObject *)&Arraytype);
@@ -2752,4 +2764,10 @@
}
PyModule_AddObject(m, "typecodes", (PyObject *)typecodes);
+
+ if (PyErr_Occurred()) {
+ Py_DECREF(m);
+ m = NULL;
+ }
+ return m;
}
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit