Author: Armin Rigo <[email protected]>
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
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit