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