[pypy-commit] pypy multiphase: Check the result of module init functions more carefully; improve tests for this
rlamy
pypy.commits at gmail.com
Fri Aug 11 11:44:39 EDT 2017
Author: Ronan Lamy <ronan.lamy at gmail.com>
Branch: multiphase
Changeset: r92124:fe04b833579b
Date: 2017-08-11 17:41 +0200
http://bitbucket.org/pypy/pypy/changeset/fe04b833579b/
Log: Check the result of module init functions more carefully; improve
tests for this
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
@@ -1545,7 +1545,17 @@
try:
initfunc = rffi.cast(initfunctype, initptr)
initret = generic_cpy_call_dont_convert_result(space, initfunc)
- state.check_and_raise_exception()
+ if not initret:
+ if state.operror:
+ state.check_and_raise_exception()
+ raise oefmt(space.w_SystemError,
+ "initialization of %s failed without raising an exception",
+ name)
+ else:
+ if state.clear_exception():
+ raise oefmt(space.w_SystemError,
+ "initialization of %s raised unreported exception",
+ name)
if not initret.c_ob_type:
raise oefmt(space.w_SystemError,
"init function of %s returned uninitialized object",
@@ -1588,7 +1598,7 @@
@specialize.ll()
def generic_cpy_call_dont_convert_result(space, func, *args):
FT = lltype.typeOf(func).TO
- return make_generic_cpy_call(FT, False, False)(space, func, *args)
+ return make_generic_cpy_call(FT, True, False)(space, func, *args)
@specialize.memo()
def make_generic_cpy_call(FT, expect_null, convert_result):
diff --git a/pypy/module/cpyext/test/test_module.py b/pypy/module/cpyext/test/test_module.py
--- a/pypy/module/cpyext/test/test_module.py
+++ b/pypy/module/cpyext/test/test_module.py
@@ -135,25 +135,28 @@
raises(SystemError, self.import_module, name='multiphase', body=body,
init=init)
+class AppTestMultiPhase2(AppTestCpythonExtensionBase):
+ def setup_class(cls):
+ cls.w_name = cls.space.wrap('multiphase2')
+ AppTestCpythonExtensionBase.setup_class.im_func(cls)
+
def test_multiphase2(self):
import sys
from importlib import machinery, util
- NAME = 'multiphase2'
- module = self.import_module(name=NAME)
+ module = self.import_module(name=self.name)
finder = machinery.FileFinder(None)
- spec = util.find_spec(NAME)
+ spec = util.find_spec(self.name)
assert spec
- assert module.__name__ == NAME
+ assert module.__name__ == self.name
#assert module.__file__ == spec.origin
assert module.__package__ == ''
raises(AttributeError, 'module.__path__')
- assert module is sys.modules[NAME]
+ assert module is sys.modules[self.name]
assert isinstance(module.__loader__, machinery.ExtensionFileLoader)
def test_functionality(self):
import types
- NAME = 'multiphase2'
- module = self.import_module(name=NAME)
+ module = self.import_module(name=self.name)
assert isinstance(module, types.ModuleType)
ex = module.Example()
assert ex.demo('abcd') == 'abcd'
@@ -170,14 +173,19 @@
def test_reload(self):
import importlib
- NAME = 'multiphase2'
- module = self.import_module(name=NAME)
+ module = self.import_module(name=self.name)
ex_class = module.Example
importlib.reload(module)
assert ex_class is module.Example
- def w_load_from_spec(self, loader, spec):
- from importlib import util
+ def w_load_from_name(self, name, origin=None):
+ from importlib import machinery, util
+ if not origin:
+ module = self.import_module(name=self.name)
+ origin = module.__loader__.path
+ name = '_testmultiphase_' + name
+ loader = machinery.ExtensionFileLoader(name, origin)
+ spec = util.spec_from_loader(name, loader)
module = util.module_from_spec(spec)
loader.exec_module(module)
return module
@@ -185,19 +193,13 @@
def test_bad_modules(self):
# XXX: not a very good test, since most internal issues in cpyext
# cause SystemErrors.
- from importlib import machinery, util
- NAME = 'multiphase2'
- module = self.import_module(name=NAME)
+ module = self.import_module(name=self.name)
origin = module.__loader__.path
- for name_base in [
+ for name in [
'bad_slot_large',
'bad_slot_negative',
'create_int_with_state',
'negative_size',
- 'export_null',
- 'export_uninitialized',
- 'export_raise',
- 'export_unreported_exception',
'create_null',
'create_raise',
'create_unreported_exception',
@@ -206,7 +208,23 @@
'exec_raise',
'exec_unreported_exception',
]:
- name = '_testmultiphase_' + name_base
- loader = machinery.ExtensionFileLoader(name, origin)
- spec = util.spec_from_loader(name, loader)
- raises(SystemError, self.load_from_spec, loader, spec)
+ raises(SystemError, self.load_from_name, name, origin)
+
+ def test_export_null(self):
+ excinfo = raises(SystemError, self.load_from_name, 'export_null')
+ assert "initialization" in excinfo.value.args[0]
+ assert "without raising" in excinfo.value.args[0]
+
+ def test_export_uninit(self):
+ excinfo = raises(SystemError, self.load_from_name, 'export_uninitialized')
+ assert "init function" in excinfo.value.args[0]
+ assert "uninitialized object" in excinfo.value.args[0]
+
+ def test_export_raise(self):
+ excinfo = raises(SystemError, self.load_from_name, 'export_raise')
+ assert "bad export function" == excinfo.value.args[0]
+
+ def test_export_unreported(self):
+ excinfo = raises(SystemError, self.load_from_name, 'export_unreported_exception')
+ assert "initialization" in excinfo.value.args[0]
+ assert "unreported exception" in excinfo.value.args[0]
More information about the pypy-commit
mailing list