1. Pypy
  2. Untitled project
  3. pypy

Commits

Amaury Forgeot d'Arc  committed f009c07

Progress with the new API for extension modules.
test_cpyext passes entirely.

  • Participants
  • Parent commits aa8d1f8
  • Branches py3k

Comments (0)

Files changed (10)

File pypy/module/cpyext/api.py

View file
  • Ignore whitespace
         state.check_and_raise_exception()
     finally:
         state.package_context = old_context
-    state.fixup_extension(name, path)
+    state.fixup_extension(w_mod, name, path)
 
 @specialize.ll()
 def generic_cpy_call(space, func, *args):

File pypy/module/cpyext/import_.py

View file
  • Ignore whitespace
     not already present."""
     from pypy.module.imp.importing import check_sys_modules_w
     modulename = rffi.charp2str(name)
+    w_modulename = space.wrap(modulename)
     w_mod = check_sys_modules_w(space, modulename)
     if not w_mod or space.is_w(w_mod, space.w_None):
-        w_mod = Module(space, space.wrap(modulename))
+        w_mod = Module(space, w_modulename)
+    space.setitem(space.sys.get('modules'), w_modulename, w_mod)
     return borrow_from(None, w_mod)
 
 @cpython_api([], PyObject)

File pypy/module/cpyext/modsupport.py

View file
  • Ignore whitespace
      ], 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
-    may be of the form package.module. First check the modules dictionary if
-    there's one there, and if not, create a new one and insert it in the modules
-    dictionary.
-
-    This function does not load or import the module; if the module wasn't already
-    loaded, you will get an empty module object. Use PyImport_ImportModule()
-    or one of its variants to import a module.  Package structures implied by a
-    dotted name for name are not created if not already present."""
-    w_name = space.wrap(name)
-    w_modules = space.sys.get('modules')
-
-    w_mod = space.finditem_str(w_modules, name)
-    if w_mod is None:
-        w_mod = space.wrap(Module(space, w_name))
-        space.setitem(w_modules, w_name, w_mod)
-
-    return w_mod
-
 @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
     modname = rffi.charp2str(module.c_m_name)
     if module.c_m_doc:
         doc = rffi.charp2str(module.c_m_doc)
+    else:
+        doc = None
     methods = module.c_m_methods
 
     state = space.fromcache(State)
     f_name, f_path = state.package_context
     if f_name is not None:
         modname = f_name
-    w_mod = PyImport_AddModule(space, modname)
+    w_mod = space.wrap(Module(space, space.wrap(modname)))
     state.package_context = None, None
 
     if f_path is not None:

File pypy/module/cpyext/state.py

View file
  • Ignore whitespace
             self.version = rffi.str2charp(version)
             lltype.render_immortal(self.version)
         return self.version
+        foo = self.import_module(name='foo', init=init)
 
     def find_extension(self, name, path):
-        from pypy.module.cpyext.modsupport import PyImport_AddModule
+        from pypy.module.cpyext.import_ import PyImport_AddModule
         from pypy.interpreter.module import Module
         try:
             w_dict = self.extensions[path]
         except KeyError:
             return None
-        w_mod = PyImport_AddModule(self.space, name)
+        with rffi.scoped_str2charp(name) as ll_name:
+            w_mod = PyImport_AddModule(self.space, ll_name)
         assert isinstance(w_mod, Module)
         w_mdict = w_mod.getdict(self.space)
         self.space.call_method(w_mdict, 'update', w_dict)
         return w_mod
 
-    def fixup_extension(self, name, path):
+    def fixup_extension(self, w_mod, name, path):
         from pypy.interpreter.module import Module
         space = self.space
         w_modules = space.sys.get('modules')
-        w_mod = space.finditem_str(w_modules, name)
-        if not isinstance(w_mod, Module):
-            msg = "fixup_extension: module '%s' not loaded" % name
-            raise OperationError(space.w_SystemError,
-                                 space.wrap(msg))
+        space.setitem_str(w_modules, name, w_mod)
         w_dict = w_mod.getdict(space)
         w_copy = space.call_method(w_dict, 'copy')
         self.extensions[path] = w_copy

File pypy/module/cpyext/test/banana.c

View file
  • Ignore whitespace
     {NULL, NULL}
 };
 
-void initbanana(void)
+static struct PyModuleDef moduledef = {
+    PyModuleDef_HEAD_INIT,
+    "banana",
+    "Module Doc",
+    -1,
+    &banana_functions
+};
+
+PyObject *PyInit_banana(void)
 {
-    Py_InitModule("banana", banana_functions);
+    return PyModule_Create(&moduledef);
 }

File pypy/module/cpyext/test/date.c

View file
  • Ignore whitespace
     {NULL, NULL}
 };
 
-void initdate(void)
+static struct PyModuleDef moduledef = {
+    PyModuleDef_HEAD_INIT,
+    "date",
+    "Module Doc",
+    -1,
+    &date_functions
+};
+
+PyObject *PyInit_date(void)
 {
-    PyObject *module;
-    Py_InitModule("date", date_functions);
-    module = PyImport_ImportModule("apple.banana");
-    Py_DECREF(module);
+    PyObject *module, *othermodule;
+    module = PyModule_Create(&moduledef);
+    othermodule = PyImport_ImportModule("apple.banana");
+    Py_DECREF(othermodule);
+    return module;
 }

File pypy/module/cpyext/test/dotted.c

View file
  • Ignore whitespace
     {NULL, NULL}
 };
 
-void initdotted(void)
+static struct PyModuleDef moduledef = {
+    PyModuleDef_HEAD_INIT,
+    "pypy.module.cpyext.test.dotted",
+    "Module Doc",
+    -1,
+    &dotted_functions
+};
+
+PyObject *PyInit_dotted(void)
 {
-    Py_InitModule("pypy.module.cpyext.test.dotted", dotted_functions);
+    return PyModule_Create(&moduledef);
 }

File pypy/module/cpyext/test/modinit.c

View file
  • Ignore whitespace
     { NULL }
 };
 
+static struct PyModuleDef moduledef = {
+    PyModuleDef_HEAD_INIT,
+    "modinit",
+    "",
+    -1,
+    &methods
+};
+
 PyMODINIT_FUNC
-initmodinit(void) {
-    Py_InitModule3("modinit", methods, "");
+PyInit_modinit(void) {
+    return PyModule_Create(&moduledef);
 }
 

File pypy/module/cpyext/test/test_cpyext.py

View file
  • Ignore whitespace
     """
     modname = modname.split('.')[-1]
     eci = ExternalCompilationInfo(
-        export_symbols=['init%s' % (modname,)],
+        export_symbols=['PyInit_%s' % (modname,)],
         include_dirs=api.include_dirs,
         **kwds
         )
     def setup_class(cls):
         from pypy.rlib.clibffi import get_libc_name
         cls.w_libc = cls.space.wrap(get_libc_name())
+        state = cls.space.fromcache(RefcountState)
+        state.non_heaptypes_w[:] = []
 
     def test_load_error(self):
         import cpyext
         filename.
         """
         name = name.encode()
-        if init is not None:
-            init = init.encode()
-        body = body.encode()
-        if init is not None:
+        if body or init:
+            body = body.encode()
+            if init is None:
+                init = "return PyModule_Create(&moduledef);"
+            else:
+                init = init.encode()
             code = """
             #include <Python.h>
             %(body)s
 
-            void init%(name)s(void) {
+            PyObject* PyInit_%(name)s(void) {
             %(init)s
             }
             """ % dict(name=name, init=init, body=body)
             return os.path.dirname(mod)
 
     def reimport_module(self, mod, name):
+        mod = mod.encode('ascii')
+        name = name.encode('ascii')
         api.load_extension_module(self.space, mod, name)
         return self.space.getitem(
             self.space.sys.get('modules'),
 
         body = prologue + "\n".join(codes) + """
         static PyMethodDef methods[] = {
-        %s
+        %(methods)s
         { NULL }
         };
-        """ % ('\n'.join(methods_table),)
-        init = """Py_InitModule("%s", methods);""" % (modname,)
+        static struct PyModuleDef moduledef = {
+            PyModuleDef_HEAD_INIT,
+            "%(modname)s",  /* m_name */
+            NULL,           /* m_doc */
+            -1,             /* m_size */
+            &methods        /* m_methods */
+        };
+        """ % dict(methods='\n'.join(methods_table), modname=modname)
+        init = """PyObject *mod = PyModule_Create(&moduledef);"""
         return self.import_module(name=modname, init=init, body=body)
 
     def record_imported_module(self, name):
     def test_createmodule(self):
         import sys
         init = """
-        if (Py_IsInitialized())
-            Py_InitModule("foo", NULL);
+        if (Py_IsInitialized()) {
+            PyObject *mod = PyImport_AddModule("foo");
+            Py_INCREF(mod);
+            return mod;
+        }
+        PyErr_SetNone(PyExc_RuntimeError);
+        return NULL;
         """
         self.import_module(name='foo', init=init)
         assert 'foo' in sys.modules
 
     def test_export_function(self):
         import sys
-        init = """
-        if (Py_IsInitialized())
-            Py_InitModule("foo", methods);
-        """
         body = """
         PyObject* foo_pi(PyObject* self, PyObject *args)
         {
             { "return_pi", foo_pi, METH_NOARGS },
             { NULL }
         };
+        static struct PyModuleDef moduledef = {
+            PyModuleDef_HEAD_INIT,
+            "%(modname)s",  /* m_name */
+            NULL,           /* m_doc */
+            -1,             /* m_size */
+            &methods        /* m_methods */
+        };
         """
-        module = self.import_module(name='foo', init=init, body=body)
+        module = self.import_module(name='foo', body=body)
         assert 'foo' in sys.modules
         assert 'return_pi' in dir(module)
         assert module.return_pi is not None
 
     def test_export_docstring(self):
         import sys
-        init = """
-        if (Py_IsInitialized())
-            Py_InitModule("foo", methods);
-        """
         body = """
         PyDoc_STRVAR(foo_pi_doc, "Return pi.");
         PyObject* foo_pi(PyObject* self, PyObject *args)
         {
             return PyFloat_FromDouble(3.14);
         }
-        static PyMethodDef methods[] ={
+        static PyMethodDef methods[] = {
             { "return_pi", foo_pi, METH_NOARGS, foo_pi_doc },
             { NULL }
         };
+        static struct PyModuleDef moduledef = {
+            PyModuleDef_HEAD_INIT,
+            "%(modname)s",  /* m_name */
+            NULL,           /* m_doc */
+            -1,             /* m_size */
+            &methods        /* m_methods */
+        };
         """
-        module = self.import_module(name='foo', init=init, body=body)
+        module = self.import_module(name='foo', body=body)
         doc = module.return_pi.__doc__
         assert doc == "Return pi."
 
-
-    def test_InitModule4(self):
-        init = """
-        PyObject *cookie = PyFloat_FromDouble(3.14);
-        Py_InitModule4("foo", methods, "docstring",
-                       cookie, PYTHON_API_VERSION);
-        Py_DECREF(cookie);
-        """
+    def test_load_dynamic(self):
+        import sys
         body = """
-        PyObject* return_cookie(PyObject* self, PyObject *args)
-        {
-            if (self)
-            {
-                Py_INCREF(self);
-                return self;
-            }
-            else
-                Py_RETURN_FALSE;
-        }
-        static PyMethodDef methods[] = {
-            { "return_cookie", return_cookie, METH_NOARGS },
-            { NULL }
+        static struct PyModuleDef moduledef = {
+            PyModuleDef_HEAD_INIT,
+            "%(modname)s",  /* m_name */
+            NULL,           /* m_doc */
+            -1,             /* m_size */
+            NULL,           /* m_methods */
         };
         """
-        module = self.import_module(name='foo', init=init, body=body)
-        assert module.__doc__ == "docstring"
-        assert module.return_cookie() == 3.14
-
-    def test_load_dynamic(self):
-        import sys
-        init = """
-        if (Py_IsInitialized())
-            Py_InitModule("foo", NULL);
-        """
-        foo = self.import_module(name='foo', init=init)
+        foo = self.import_module(name='foo', body=body)
         assert 'foo' in sys.modules
         del sys.modules['foo']
         import imp
 
     def test_export_function2(self):
         import sys
-        init = """
-        if (Py_IsInitialized())
-            Py_InitModule("foo", methods);
-        """
         body = """
         static PyObject* my_objects[1];
         static PyObject* foo_cached_pi(PyObject* self, PyObject *args)
             { "return_invalid_pointer", foo_retinvalid, METH_NOARGS },
             { NULL }
         };
+        static struct PyModuleDef moduledef = {
+            PyModuleDef_HEAD_INIT,
+            "%(modname)s",  /* m_name */
+            NULL,           /* m_doc */
+            -1,             /* m_size */
+            &methods        /* m_methods */
+        };
         """
-        module = self.import_module(name='foo', init=init, body=body)
+        module = self.import_module(name='foo', body=body)
         assert module.return_pi() == 3.14
         module.drop_pi()
         module.drop_pi()
 
     def test_argument(self):
         import sys
-        init = """
-        if (Py_IsInitialized())
-            Py_InitModule("foo", methods);
-        """
         body = """
         PyObject* foo_test(PyObject* self, PyObject *args)
         {
             { "test", foo_test, METH_VARARGS },
             { NULL }
         };
+        static struct PyModuleDef moduledef = {
+            PyModuleDef_HEAD_INIT,
+            "%(modname)s",  /* m_name */
+            NULL,           /* m_doc */
+            -1,             /* m_size */
+            &methods        /* m_methods */
+        };
         """
-        module = self.import_module(name='foo', init=init, body=body)
+        module = self.import_module(name='foo', body=body)
         assert module.test(True, True) == True
 
     def test_exception(self):
         import sys
-        init = """
-        if (Py_IsInitialized())
-            Py_InitModule("foo", methods);
-        """
         body = """
         static PyObject* foo_pi(PyObject* self, PyObject *args)
         {
             { "raise_exception", foo_pi, METH_NOARGS },
             { NULL }
         };
+        static struct PyModuleDef moduledef = {
+            PyModuleDef_HEAD_INIT,
+            "%(modname)s",  /* m_name */
+            NULL,           /* m_doc */
+            -1,             /* m_size */
+            &methods        /* m_methods */
+        };
         """
-        module = self.import_module(name='foo', init=init, body=body)
+        module = self.import_module(name='foo', body=body)
         exc = raises(Exception, module.raise_exception)
         if type(exc.value) is not Exception:
             raise exc.value
 
     def test_refcount(self):
         import sys
-        init = """
-        if (Py_IsInitialized())
-            Py_InitModule("foo", methods);
-        """
         body = """
         static PyObject* foo_pi(PyObject* self, PyObject *args)
         {
             { "test_refcount2", foo_bar, METH_NOARGS },
             { NULL }
         };
+        static struct PyModuleDef moduledef = {
+            PyModuleDef_HEAD_INIT,
+            "%(modname)s",  /* m_name */
+            NULL,           /* m_doc */
+            -1,             /* m_size */
+            &methods        /* m_methods */
+        };
         """
-        module = self.import_module(name='foo', init=init, body=body)
+        module = self.import_module(name='foo', body=body)
         assert module.test_refcount()
         assert module.test_refcount2()
 
         import sys
         init = """
             PyErr_SetString(PyExc_Exception, "moo!");
+            return NULL;
         """
-        exc = raises(Exception, "self.import_module(name='foo', init=init)")
+        exc = raises(Exception, self.import_module, name='foo', init=init)
         if type(exc.value) is not Exception:
             raise exc.value
 
 
     def test_internal_exceptions(self):
         import sys
-        init = """
-        if (Py_IsInitialized())
-            Py_InitModule("foo", methods);
-        """
         body = """
         PyAPI_FUNC(PyObject*) PyPy_Crash1(void);
         PyAPI_FUNC(long) PyPy_Crash2(void);
             { "clear",  foo_clear, METH_NOARGS },
             { NULL }
         };
+        static struct PyModuleDef moduledef = {
+            PyModuleDef_HEAD_INIT,
+            "%(modname)s",  /* m_name */
+            NULL,           /* m_doc */
+            -1,             /* m_size */
+            &methods        /* m_methods */
+        };
         """
-        module = self.import_module(name='foo', init=init, body=body)
+        module = self.import_module(name='foo', body=body)
         # uncaught interplevel exceptions are turned into SystemError
         raises(SystemError, module.crash1)
         raises(SystemError, module.crash2)
     def test_no_double_imports(self):
         import sys, os
         try:
+            body = """
+            static struct PyModuleDef moduledef = {
+                PyModuleDef_HEAD_INIT,
+                "%(modname)s",  /* m_name */
+                NULL,           /* m_doc */
+                -1,             /* m_size */
+                NULL            /* m_methods */
+            };
+            """
             init = """
             static int _imported_already = 0;
             FILE *f = fopen("_imported_already", "w");
             fprintf(f, "imported_already: %d\\n", _imported_already);
             fclose(f);
             _imported_already = 1;
-            if (Py_IsInitialized()) {
-                Py_InitModule("foo", NULL);
-            }
+            return PyModule_Create(&moduledef);
             """
-            self.import_module(name='foo', init=init)
+            self.import_module(name='foo', init=init, body=body)
             assert 'foo' in sys.modules
 
             f = open('_imported_already')

File pypy/objspace/std/fake.py

View file
  • Ignore whitespace
 def wrap_exception(space):
     """NOT_RPYTHON"""
     exc, value, tb = sys.exc_info()
-    if exc is OperationError:
+    if issubclass(exc, OperationError):
         raise exc, value, tb   # just re-raise it
     name = exc.__name__
     if hasattr(space, 'w_' + name):