Author: Armin Rigo <ar...@tunes.org> Branch: rpython-error-to-systemerror Changeset: r88159:b0bd408d0a1e Date: 2016-11-06 19:22 +0100 http://bitbucket.org/pypy/pypy/changeset/b0bd408d0a1e/
Log: First draft diff --git a/pypy/interpreter/baseobjspace.py b/pypy/interpreter/baseobjspace.py --- a/pypy/interpreter/baseobjspace.py +++ b/pypy/interpreter/baseobjspace.py @@ -1836,6 +1836,29 @@ finally: self.sys.track_resources = flag + def _convert_unexpected_exception_extra(self, e): + "NOT_RPYTHON" + if e.__class__.__name__ in ( + 'Skipped', # list of exception class names that are ok + ): # to get during ==untranslated tests== only + raise + # include the RPython-level traceback + exc = sys.exc_info() + import traceback, cStringIO + f = cStringIO.StringIO() + print >> f, "\nTraceback (interpreter-level):" + traceback.print_tb(exc[2], file=f) + return f.getvalue() + + def _convert_unexpected_exception(self, e): + if we_are_translated(): + extra = '' + else: + extra = self._convert_unexpected_exception_extra(e) + raise OperationError(self.w_SystemError, self.wrap( + "unexpected internal exception (please report a bug): %r%s" % + (e, extra))) + class AppExecCache(SpaceCache): def build(cache, source): diff --git a/pypy/interpreter/error.py b/pypy/interpreter/error.py --- a/pypy/interpreter/error.py +++ b/pypy/interpreter/error.py @@ -58,10 +58,14 @@ def __str__(self): "NOT_RPYTHON: Convenience for tracebacks." s = self._w_value - if self.__class__ is not OperationError and s is None: - space = getattr(self.w_type, 'space') - if space is not None: + space = getattr(self.w_type, 'space', None) + if space is not None: + if self.__class__ is not OperationError and s is None: s = self._compute_value(space) + try: + s = space.str_w(s) + except Exception: + pass return '[%s: %s]' % (self.w_type, s) def errorstr(self, space, use_repr=False): diff --git a/pypy/interpreter/gateway.py b/pypy/interpreter/gateway.py --- a/pypy/interpreter/gateway.py +++ b/pypy/interpreter/gateway.py @@ -712,6 +712,8 @@ if not we_are_translated(): raise raise e + except OperationError: + raise except KeyboardInterrupt: raise OperationError(space.w_KeyboardInterrupt, space.w_None) except MemoryError: @@ -722,6 +724,8 @@ "maximum recursion depth exceeded") except RuntimeError: # not on top of py.py raise OperationError(space.w_RuntimeError, space.w_None) + except Exception as e: # general fall-back + raise space._convert_unexpected_exception(e) # (verbose) performance hack below diff --git a/pypy/interpreter/pyopcode.py b/pypy/interpreter/pyopcode.py --- a/pypy/interpreter/pyopcode.py +++ b/pypy/interpreter/pyopcode.py @@ -70,6 +70,8 @@ next_instr = self.dispatch_bytecode(co_code, next_instr, ec) except OperationError as operr: next_instr = self.handle_operation_error(ec, operr) + except ExitFrame: + raise except RaiseWithExplicitTraceback as e: next_instr = self.handle_operation_error(ec, e.operr, attach_tb=False) @@ -85,6 +87,8 @@ next_instr = self.handle_asynchronous_error(ec, self.space.w_RuntimeError, self.space.wrap("maximum recursion depth exceeded")) + except Exception as e: # general fall-back + raise self.space._convert_unexpected_exception(e) return next_instr def handle_asynchronous_error(self, ec, w_type, w_value=None): diff --git a/pypy/interpreter/test/test_executioncontext.py b/pypy/interpreter/test/test_executioncontext.py --- a/pypy/interpreter/test/test_executioncontext.py +++ b/pypy/interpreter/test/test_executioncontext.py @@ -1,8 +1,10 @@ import py from pypy.interpreter import executioncontext +from pypy.interpreter.error import OperationError -class Finished(Exception): - pass +class Finished(OperationError): + def __init__(self): + OperationError.__init__(self, "exception_class", "exception_value") class TestExecutionContext: diff --git a/pypy/interpreter/test/test_gateway.py b/pypy/interpreter/test/test_gateway.py --- a/pypy/interpreter/test/test_gateway.py +++ b/pypy/interpreter/test/test_gateway.py @@ -4,6 +4,7 @@ from pypy.interpreter import gateway, argument from pypy.interpreter.gateway import ObjSpace, W_Root, WrappedDefault from pypy.interpreter.signature import Signature +from pypy.interpreter.error import OperationError import py import sys @@ -771,6 +772,21 @@ w_g = space.wrap(gateway.interp2app_temp(g, doc='bar')) assert space.unwrap(space.getattr(w_g, space.wrap('__doc__'))) == 'bar' + def test_system_error(self): + class UnexpectedException(Exception): + pass + space = self.space + def g(space): + raise UnexpectedException + w_g = space.wrap(gateway.interp2app_temp(g)) + e = py.test.raises(OperationError, space.appexec, [w_g], """(my_g): + my_g() + """) + err = str(e.value) + assert 'SystemError' in err + assert ('unexpected internal exception (please ' + 'report a bug): UnexpectedException') in err + class AppTestPyTestMark: @py.test.mark.unlikely_to_exist _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit