Author: Armin Rigo <ar...@tunes.org>
Branch: py3.5-corowrapper
Changeset: r87209:53965720c0f3
Date: 2016-09-18 21:56 +0200
http://bitbucket.org/pypy/pypy/changeset/53965720c0f3/

Log:    Test and fix: must reset w_yielded_from to None when running

diff --git a/pypy/interpreter/generator.py b/pypy/interpreter/generator.py
--- a/pypy/interpreter/generator.py
+++ b/pypy/interpreter/generator.py
@@ -158,9 +158,11 @@
         # Called from execute_frame() just before resuming the bytecode
         # interpretation.
         space = self.space
-        if self.w_yielded_from is not None:
+        w_yf = self.w_yielded_from
+        if w_yf is not None:
+            self.w_yielded_from = None
             try:
-                self.next_yield_from(frame, w_arg_or_err)
+                self.next_yield_from(frame, w_yf, w_arg_or_err)
             except OperationError as operr:
                 ec = space.getexecutioncontext()
                 return frame.handle_operation_error(ec, operr)
@@ -184,13 +186,12 @@
             frame.pushvalue(w_arg_or_err)
         return r_uint(last_instr + 1)
 
-    def next_yield_from(self, frame, w_inputvalue_or_err):
+    def next_yield_from(self, frame, w_yf, w_inputvalue_or_err):
         """Fetch the next item of the current 'yield from', push it on
         the frame stack, and raises Yield.  If there isn't one, push
         w_stopiteration_value and returns.  May also just raise.
         """
         space = self.space
-        w_yf = self.w_yielded_from
         try:
             if isinstance(w_yf, GeneratorOrCoroutine):
                 w_retval = w_yf.send_ex(w_inputvalue_or_err)
@@ -199,7 +200,6 @@
             else:
                 w_retval = delegate_to_nongen(space, w_yf, w_inputvalue_or_err)
         except OperationError as e:
-            self.w_yielded_from = None
             if not e.match(space, space.w_StopIteration):
                 raise
             e.normalize_exception(space)
@@ -214,6 +214,7 @@
             return
         else:
             frame.pushvalue(w_retval)
+            self.w_yielded_from = w_yf
             raise Yield
 
     def _leak_stopiteration(self, e):
@@ -256,6 +257,7 @@
         operr = OperationError(w_type, w_val, tb)
         operr.normalize_exception(space)
 
+        # note: w_yielded_from is always None if 'self.running'
         w_yf = self.w_yielded_from
         if (w_yf is not None and
                     operr.match(space, space.w_GeneratorExit)):
@@ -278,6 +280,7 @@
             return     # nothing to do in this case
         space = self.space
         operr = get_generator_exit(space)
+        # note: w_yielded_from is always None if 'self.running'
         w_yf = self.w_yielded_from
         if w_yf is not None:
             self.w_yielded_from = None
diff --git a/pypy/interpreter/pyopcode.py b/pypy/interpreter/pyopcode.py
--- a/pypy/interpreter/pyopcode.py
+++ b/pypy/interpreter/pyopcode.py
@@ -1035,11 +1035,10 @@
         from pypy.interpreter.generator import Coroutine
         in_generator = self.get_generator()
         assert in_generator is not None
-        w_inputvalue = self.popvalue()    # that's always None, actually
+        w_inputvalue = self.popvalue()    # that's always w_None, actually
         w_gen = self.popvalue()
         #
-        in_generator.w_yielded_from = w_gen
-        in_generator.next_yield_from(self, w_inputvalue)
+        in_generator.next_yield_from(self, w_gen, w_inputvalue)
         # Common case: the call above raises Yield.
         # If instead the iterable is empty, next_yield_from() pushed the
         # final result and returns.  In that case, we can just continue
diff --git a/pypy/interpreter/test/test_generator.py 
b/pypy/interpreter/test/test_generator.py
--- a/pypy/interpreter/test/test_generator.py
+++ b/pypy/interpreter/test/test_generator.py
@@ -397,10 +397,15 @@
 
     def test_gi_yieldfrom(self): """
         def g(x):
+            assert gen.gi_yieldfrom is None
             yield x
+            assert gen.gi_yieldfrom is None
         def f(x):
+            assert gen.gi_yieldfrom is None
             yield from g(x)
+            assert gen.gi_yieldfrom is None
             yield 42
+            assert gen.gi_yieldfrom is None
         gen = f(5)
         assert gen.gi_yieldfrom is None
         assert next(gen) == 5
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to