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

Reply via email to