[pypy-svn] pypy default: Extend test_trace_generator_finalisation to check for the correct

arigo commits-noreply at bitbucket.org
Mon Feb 7 15:10:58 CET 2011


Author: Armin Rigo <arigo at tunes.org>
Branch: 
Changeset: r41668:9dc525f2d8e4
Date: 2011-02-07 15:10 +0100
http://bitbucket.org/pypy/pypy/changeset/9dc525f2d8e4/

Log:	Extend test_trace_generator_finalisation to check for the correct
	order of the events: generator.throw() used to get the tracing
	events "exception" followed by "call", whereas on CPython it is the
	opposite order. Fix it.

diff --git a/pypy/interpreter/generator.py b/pypy/interpreter/generator.py
--- a/pypy/interpreter/generator.py
+++ b/pypy/interpreter/generator.py
@@ -55,7 +55,7 @@
         frame = self.frame
         if frame is None:
             # xxx a bit ad-hoc, but we don't want to go inside
-            # execute_generator_frame() if the frame is actually finished
+            # execute_frame() if the frame is actually finished
             if operr is None:
                 operr = OperationError(space.w_StopIteration, space.w_None)
             raise operr
@@ -72,7 +72,7 @@
         self.running = True
         try:
             try:
-                w_result = frame.execute_generator_frame(w_arg, operr)
+                w_result = frame.execute_frame(w_arg, operr)
             except OperationError:
                 # errors finish a frame
                 self.frame = None

diff --git a/pypy/interpreter/test/test_pyframe.py b/pypy/interpreter/test/test_pyframe.py
--- a/pypy/interpreter/test/test_pyframe.py
+++ b/pypy/interpreter/test/test_pyframe.py
@@ -279,12 +279,13 @@
         
 
     def test_trace_generator_finalisation(self):
-        # XXX expand to check more aspects
         import sys
         l = []
+        got_exc = []
         def trace(frame, event, arg):
+            l.append((frame.f_lineno, event))
             if event == 'exception':
-                l.append(arg)
+                got_exc.append(arg)
             return trace
 
         d = {}
@@ -308,8 +309,22 @@
         sys.settrace(trace)
         f()
         sys.settrace(None)
-        assert len(l) == 1
-        assert issubclass(l[0][0], GeneratorExit)
+        assert len(got_exc) == 1
+        assert issubclass(got_exc[0][0], GeneratorExit)
+        assert l == [(8, 'call'),
+                     (9, 'line'),
+                     (10, 'line'),
+                     (11, 'line'),
+                     (2, 'call'),
+                     (3, 'line'),
+                     (4, 'line'),
+                     (4, 'return'),
+                     (12, 'line'),
+                     (4, 'call'),
+                     (4, 'exception'),
+                     (6, 'line'),
+                     (6, 'return'),
+                     (12, 'return')]
 
     def test_dont_trace_on_reraise(self):
         import sys

diff --git a/pypy/interpreter/pyframe.py b/pypy/interpreter/pyframe.py
--- a/pypy/interpreter/pyframe.py
+++ b/pypy/interpreter/pyframe.py
@@ -125,17 +125,12 @@
         else:
             return self.execute_frame()
 
-    def execute_generator_frame(self, w_inputvalue, operr=None):
-        if operr is not None:
-            ec = self.space.getexecutioncontext()
-            next_instr = self.handle_operation_error(ec, operr)
-            self.last_instr = intmask(next_instr - 1)
-        elif self.last_instr != -1:
-            self.pushvalue(w_inputvalue)
-        return self.execute_frame()
-
-    def execute_frame(self):
-        """Execute this frame.  Main entry point to the interpreter."""
+    def execute_frame(self, w_inputvalue=None, operr=None):
+        """Execute this frame.  Main entry point to the interpreter.
+        The optional arguments are there to handle a generator's frame:
+        w_inputvalue is for generator.send()) and operr is for
+        generator.throw()).
+        """
         # the following 'assert' is an annotation hint: it hides from
         # the annotator all methods that are defined in PyFrame but
         # overridden in the {,Host}FrameClass subclasses of PyFrame.
@@ -145,10 +140,19 @@
         executioncontext.enter(self)
         try:
             executioncontext.call_trace(self)
-            # Execution starts just after the last_instr.  Initially,
-            # last_instr is -1.  After a generator suspends it points to
-            # the YIELD_VALUE instruction.
-            next_instr = self.last_instr + 1
+            #
+            if operr is not None:
+                ec = self.space.getexecutioncontext()
+                next_instr = self.handle_operation_error(ec, operr)
+                self.last_instr = intmask(next_instr - 1)
+            else:
+                # Execution starts just after the last_instr.  Initially,
+                # last_instr is -1.  After a generator suspends it points to
+                # the YIELD_VALUE instruction.
+                next_instr = self.last_instr + 1
+                if next_instr != 0:
+                    self.pushvalue(w_inputvalue)
+            #
             try:
                 w_exitvalue = self.dispatch(self.pycode, next_instr,
                                             executioncontext)


More information about the Pypy-commit mailing list