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