[pypy-commit] pypy py3.3: "yield from": Correctly wrap/uwrap the returned value in the StopIteration exception.

amauryfa noreply at buildbot.pypy.org
Tue Mar 24 23:40:13 CET 2015


Author: Amaury Forgeot d'Arc <amauryfa at gmail.com>
Branch: py3.3
Changeset: r76553:deae634f291c
Date: 2015-03-24 15:14 +0100
http://bitbucket.org/pypy/pypy/changeset/deae634f291c/

Log:	"yield from": Correctly wrap/uwrap the returned value in the
	StopIteration exception. It's important when the value is a tuple.

diff --git a/pypy/interpreter/generator.py b/pypy/interpreter/generator.py
--- a/pypy/interpreter/generator.py
+++ b/pypy/interpreter/generator.py
@@ -99,7 +99,12 @@
             # if the frame is now marked as finished, it was RETURNed from
             if frame.frame_finished_execution:
                 self.frame = None
-                raise OperationError(space.w_StopIteration, w_result)
+                if space.is_none(w_result):
+                    # Delay exception instantiation if we can
+                    raise OperationError(space.w_StopIteration, space.w_None)
+                else:
+                    raise OperationError(space.w_StopIteration,
+                                         space.newtuple([w_result]))
             else:
                 return w_result     # YIELDed
         finally:
@@ -170,7 +175,9 @@
                 # Termination repetition of YIELD_FROM
                 self.frame.last_instr += 1
                 if operr.match(space, space.w_StopIteration):
-                    w_val = operr.get_w_value(space)
+                    operr.normalize_exception(space)
+                    w_val = space.getattr(operr.get_w_value(space),
+                                          space.wrap("value"))
                     return self.send_ex(w_val)
                 else:
                     return self.send_ex(space.w_None, operr)
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
@@ -348,6 +348,24 @@
             assert False, 'Expected StopIteration'
             """
 
+    def test_yield_from_return_tuple(self):
+        """
+        def f1():
+            result = yield from f2()
+            return result
+        def f2():
+            yield 1
+            return (1, 2)
+        g = f1()
+        assert next(g) == 1
+        try:
+            next(g)
+        except StopIteration as e:
+            assert e.value == (1, 2)
+        else:
+            assert False, 'Expected StopIteration'
+            """
+
 
 def test_should_not_inline(space):
     from pypy.interpreter.generator import should_not_inline


More information about the pypy-commit mailing list