Author: Amaury Forgeot d'Arc <[email protected]>
Branch: py3.3
Changeset: r74204:cbd6c0accf8c
Date: 2014-10-25 11:29 +0200
http://bitbucket.org/pypy/pypy/changeset/cbd6c0accf8c/
Log: yield from: More tests, and fixes
diff --git a/pypy/interpreter/generator.py b/pypy/interpreter/generator.py
--- a/pypy/interpreter/generator.py
+++ b/pypy/interpreter/generator.py
@@ -117,16 +117,14 @@
# Probably a hack (but CPython has the same):
# If the current frame is stopped in a "yield from",
# return the paused generator.
- from pypy.interpreter.pyopcode import bytecode_spec
if not self.frame:
return None
co_code = self.frame.pycode.co_code
opcode = ord(co_code[self.frame.last_instr + 1])
- if opcode == opcodedesc.YIELD_FROM.index:
+ if opcode == YIELD_FROM:
return self.frame.peekvalue()
def throw(self, w_type, w_val, w_tb):
- from pypy.interpreter.pytraceback import check_traceback
space = self.space
w_yf = self._get_yield_from()
@@ -144,27 +142,33 @@
space.call_function(w_close)
except OperationError as operr:
self.running = False
- self.send_ex(space.w_None, operr)
- return
+ return self.send_ex(space.w_None, operr)
finally:
self.running = False
return self._throw_here(space, w_type, w_val, w_tb)
else:
try:
- space.call_method(w_yf, "throw", w_type, w_val, w_tb)
+ w_throw = space.getattr(w_yf, space.wrap("throw"))
+ except OperationError as e:
+ if not e.match(space, space.w_AttributeError):
+ raise
+ return self._throw_here(space, w_type, w_val, w_tb)
+ self.running = True
+ try:
+ space.call_function(w_throw, w_type, w_val, w_tb)
except OperationError as operr:
self.running = False
- self.send_ex(space.w_None, operr)
- return
+ # XXX Should pop subiterator from stack?
+ return self.send_ex(space.w_None, operr)
finally:
self.running = False
-
- return self.forward_throw_to_yield_from(yf)
# Not paused in a "yield from", quit this generator
return self._throw_here(space, w_type, w_val, w_tb)
def _throw_here(self, space, w_type, w_val, w_tb):
+ from pypy.interpreter.pytraceback import check_traceback
+
msg = "throw() third argument must be a traceback object"
if space.is_none(w_tb):
tb = None
@@ -286,6 +290,7 @@
from pypy.tool.stdlib_opcode import HAVE_ARGUMENT, opmap
YIELD_VALUE = opmap['YIELD_VALUE']
+YIELD_FROM = opmap['YIELD_FROM']
@jit.elidable_promote()
def should_not_inline(pycode):
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
@@ -485,6 +485,37 @@
"Finishing g1",
]
+ def test_delegating_throw_to_non_generator(self):
+ """
+ Test delegating 'throw' to non-generator
+ """
+ trace = []
+ d = dict(trace=trace)
+ exec('''if 1:
+ def g():
+ try:
+ trace.append("Starting g")
+ yield from range(10)
+ finally:
+ trace.append("Finishing g")
+ ''', d)
+ g = d['g']
+ gi = g()
+ for i in range(5):
+ x = next(gi)
+ trace.append("Yielded %s" % (x,))
+ exc = raises(ValueError, gi.throw, ValueError("tomato ejected"))
+ assert exc.value.args[0] == "tomato ejected"
+ assert trace == [
+ "Starting g",
+ "Yielded 0",
+ "Yielded 1",
+ "Yielded 2",
+ "Yielded 3",
+ "Yielded 4",
+ "Finishing g",
+ ]
+
def test_broken_getattr_handling(self):
"""
Test subiterator with a broken getattr implementation
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit