[pypy-svn] r58278 - in pypy/dist/pypy/interpreter: . test

arigo at codespeak.net arigo at codespeak.net
Sat Sep 20 18:54:20 CEST 2008


Author: arigo
Date: Sat Sep 20 18:54:19 2008
New Revision: 58278

Modified:
   pypy/dist/pypy/interpreter/pyopcode.py
   pypy/dist/pypy/interpreter/test/test_raise.py
Log:
(pedronis around, arigo)
Tests and fix for when exceptions should show up in sys.exc_info()
or not.


Modified: pypy/dist/pypy/interpreter/pyopcode.py
==============================================================================
--- pypy/dist/pypy/interpreter/pyopcode.py	(original)
+++ pypy/dist/pypy/interpreter/pyopcode.py	Sat Sep 20 18:54:19 2008
@@ -95,6 +95,9 @@
             operr = self.last_exception
             next_instr = self.handle_operation_error(ec, operr,
                                                      attach_tb=False)
+        except RaiseWithExplicitTraceback, e:
+            next_instr = self.handle_operation_error(ec, e.operr,
+                                                     attach_tb=False)
         except KeyboardInterrupt:
             next_instr = self.handle_asynchronous_error(ec,
                 self.space.w_KeyboardInterrupt)
@@ -122,7 +125,6 @@
         return self.handle_operation_error(ec, operr)
 
     def handle_operation_error(self, ec, operr, attach_tb=True):
-        self.last_exception = operr
         if attach_tb:
             pytraceback.record_application_traceback(
                 self.space, operr, self, self.last_instr)
@@ -533,9 +535,8 @@
                 raise OperationError(space.w_TypeError,
                       space.wrap("raise: arg 3 must be a traceback or None"))
             operror.application_traceback = tb
-            # re-raise, no new traceback obj will be attached
-            f.last_exception = operror
-            raise Reraise
+            # special 3-arguments raise, no new traceback obj will be attached
+            raise RaiseWithExplicitTraceback(operror)
 
     def LOAD_LOCALS(f, *ignored):
         f.pushvalue(f.w_locals)
@@ -979,17 +980,20 @@
 
 ### ____________________________________________________________ ###
 
-class Reraise(Exception):
-    """Signal an application-level OperationError that should not grow
-    a new traceback entry nor trigger the trace hook."""
-
 class ExitFrame(Exception):
     pass
 
 class Return(ExitFrame):
-    """Obscure."""
+    """Raised when exiting a frame via a 'return' statement."""
 class Yield(ExitFrame):
-    """Obscure."""
+    """Raised when exiting a frame via a 'yield' statement."""
+
+class Reraise(Exception):
+    """Raised at interp-level by a bare 'raise' statement."""
+class RaiseWithExplicitTraceback(Exception):
+    """Raised at interp-level by a 3-arguments 'raise' statement."""
+    def __init__(self, operr):
+        self.operr = operr
 
 class BytecodeCorruption(Exception):
     """Detected bytecode corruption.  Never caught; it's an error."""
@@ -1157,6 +1161,7 @@
         frame.pushvalue(frame.space.wrap(unroller))
         frame.pushvalue(operationerr.w_value)
         frame.pushvalue(operationerr.w_type)
+        frame.last_exception = operationerr
         return self.handlerposition   # jump to the handler
 
 

Modified: pypy/dist/pypy/interpreter/test/test_raise.py
==============================================================================
--- pypy/dist/pypy/interpreter/test/test_raise.py	(original)
+++ pypy/dist/pypy/interpreter/test/test_raise.py	Sat Sep 20 18:54:19 2008
@@ -90,6 +90,75 @@
         assert exc_val ==exc_val2
         assert exc_tb ==exc_tb2
 
+    def test_reraise(self):
+        # some collection of funny code
+        import sys
+        raises(ValueError, """
+            import sys
+            try:
+                raise ValueError
+            except:
+                try:
+                    raise IndexError
+                finally:
+                    assert sys.exc_info()[0] is ValueError
+                    raise
+        """)
+        raises(ValueError, """
+            def foo():
+                import sys
+                assert sys.exc_info()[0] is ValueError
+                raise
+            try:
+                raise ValueError
+            except:
+                try:
+                    raise IndexError
+                finally:
+                    foo()
+        """)
+        raises(IndexError, """
+            def spam():
+                import sys
+                try:
+                    raise KeyError
+                except KeyError:
+                    pass
+                assert sys._getframe().f_exc_type is ValueError
+            try:
+                raise ValueError
+            except:
+                try:
+                    raise IndexError
+                finally:
+                    spam()
+        """)
+
+        try:
+            raise ValueError
+        except:
+            try:
+                raise KeyError
+            except:
+                ok = sys.exc_info()[0] is KeyError
+        assert ok
+
+        raises(IndexError, """
+            import sys
+            try:
+                raise ValueError
+            except:
+                some_traceback = sys.exc_info()[2]
+            try:
+                raise KeyError
+            except:
+                try:
+                    raise IndexError, IndexError(), some_traceback
+                finally:
+                    assert sys.exc_info()[0] is KeyError
+                    assert sys.exc_info()[2] is not some_traceback
+        """)
+
     def test_tuple_type(self):
         def f():
             raise ((StopIteration, 123), 456, 789)



More information about the Pypy-commit mailing list