Author: Amaury Forgeot d'Arc <[email protected]>
Branch: py3k
Changeset: r59097:f009c071884f
Date: 2012-11-27 22:53 +0100
http://bitbucket.org/pypy/pypy/changeset/f009c071884f/
Log: Progress with the new API for extension modules. test_cpyext passes
entirely.
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
@@ -1056,7 +1056,7 @@
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):
diff --git a/pypy/module/cpyext/import_.py b/pypy/module/cpyext/import_.py
--- a/pypy/module/cpyext/import_.py
+++ b/pypy/module/cpyext/import_.py
@@ -70,9 +70,11 @@
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)
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
@@ -23,27 +23,6 @@
], 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
@@ -56,13 +35,15 @@
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:
diff --git a/pypy/module/cpyext/state.py b/pypy/module/cpyext/state.py
--- a/pypy/module/cpyext/state.py
+++ b/pypy/module/cpyext/state.py
@@ -111,29 +111,27 @@
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
diff --git a/pypy/module/cpyext/test/banana.c b/pypy/module/cpyext/test/banana.c
--- a/pypy/module/cpyext/test/banana.c
+++ b/pypy/module/cpyext/test/banana.c
@@ -4,7 +4,15 @@
{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);
}
diff --git a/pypy/module/cpyext/test/date.c b/pypy/module/cpyext/test/date.c
--- a/pypy/module/cpyext/test/date.c
+++ b/pypy/module/cpyext/test/date.c
@@ -4,10 +4,19 @@
{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;
}
diff --git a/pypy/module/cpyext/test/dotted.c b/pypy/module/cpyext/test/dotted.c
--- a/pypy/module/cpyext/test/dotted.c
+++ b/pypy/module/cpyext/test/dotted.c
@@ -4,7 +4,15 @@
{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);
}
diff --git a/pypy/module/cpyext/test/modinit.c
b/pypy/module/cpyext/test/modinit.c
--- a/pypy/module/cpyext/test/modinit.c
+++ b/pypy/module/cpyext/test/modinit.c
@@ -9,8 +9,16 @@
{ 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);
}
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
@@ -45,7 +45,7 @@
"""
modname = modname.split('.')[-1]
eci = ExternalCompilationInfo(
- export_symbols=['init%s' % (modname,)],
+ export_symbols=['PyInit_%s' % (modname,)],
include_dirs=api.include_dirs,
**kwds
)
@@ -147,6 +147,8 @@
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
@@ -201,15 +203,17 @@
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)
@@ -233,6 +237,8 @@
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'),
@@ -255,11 +261,18 @@
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):
@@ -317,18 +330,19 @@
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)
{
@@ -338,8 +352,15 @@
{ "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
@@ -349,60 +370,40 @@
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
@@ -471,10 +472,6 @@
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)
@@ -504,8 +501,15 @@
{ "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()
@@ -517,10 +521,6 @@
def test_argument(self):
import sys
- init = """
- if (Py_IsInitialized())
- Py_InitModule("foo", methods);
- """
body = """
PyObject* foo_test(PyObject* self, PyObject *args)
{
@@ -532,16 +532,19 @@
{ "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)
{
@@ -552,8 +555,15 @@
{ "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
@@ -562,10 +572,6 @@
def test_refcount(self):
import sys
- init = """
- if (Py_IsInitialized())
- Py_InitModule("foo", methods);
- """
body = """
static PyObject* foo_pi(PyObject* self, PyObject *args)
{
@@ -603,8 +609,15 @@
{ "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()
@@ -613,8 +626,9 @@
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
@@ -623,10 +637,6 @@
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);
@@ -666,8 +676,15 @@
{ "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)
@@ -759,17 +776,24 @@
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')
diff --git a/pypy/objspace/std/fake.py b/pypy/objspace/std/fake.py
--- a/pypy/objspace/std/fake.py
+++ b/pypy/objspace/std/fake.py
@@ -32,7 +32,7 @@
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):
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit