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

Reply via email to