cpython: be85914b611c (original) (raw)
new file mode 100644 --- /dev/null +++ b/Lib/test/test_pep380.py @@ -0,0 +1,842 @@ +# -- coding: utf-8 -- + +""" +Test suite for PEP 380 implementation + +adapted from original tests written by Greg Ewing +see http://www.cosc.canterbury.ac.nz/greg.ewing/python/yield-from/YieldFrom-Python3.1.2-rev5.zip +""" + +import unittest +import io +import sys +import traceback +import parser + +from test.support import captured_stderr + +class TestPEP380Operation(unittest.TestCase):
- def test_delegation_of_initial_next_to_subgenerator(self):
"""[](#l1.28)
Test delegation of initial next() call to subgenerator[](#l1.29)
"""[](#l1.30)
trace = [][](#l1.31)
def g1():[](#l1.32)
trace.append("Starting g1")[](#l1.33)
yield from g2()[](#l1.34)
trace.append("Finishing g1")[](#l1.35)
def g2():[](#l1.36)
trace.append("Starting g2")[](#l1.37)
yield 42[](#l1.38)
trace.append("Finishing g2")[](#l1.39)
for x in g1():[](#l1.40)
trace.append("Yielded %s" % (x,))[](#l1.41)
self.assertEqual(trace,[[](#l1.42)
"Starting g1",[](#l1.43)
"Starting g2",[](#l1.44)
"Yielded 42",[](#l1.45)
"Finishing g2",[](#l1.46)
"Finishing g1",[](#l1.47)
])[](#l1.48)
- def test_raising_exception_in_initial_next_call(self):
"""[](#l1.51)
Test raising exception in initial next() call[](#l1.52)
"""[](#l1.53)
trace = [][](#l1.54)
def g1():[](#l1.55)
try:[](#l1.56)
trace.append("Starting g1")[](#l1.57)
yield from g2()[](#l1.58)
finally:[](#l1.59)
trace.append("Finishing g1")[](#l1.60)
def g2():[](#l1.61)
try:[](#l1.62)
trace.append("Starting g2")[](#l1.63)
raise ValueError("spanish inquisition occurred")[](#l1.64)
finally:[](#l1.65)
trace.append("Finishing g2")[](#l1.66)
try:[](#l1.67)
for x in g1():[](#l1.68)
trace.append("Yielded %s" % (x,))[](#l1.69)
except ValueError as e:[](#l1.70)
self.assertEqual(e.args[0], "spanish inquisition occurred")[](#l1.71)
else:[](#l1.72)
self.fail("subgenerator failed to raise ValueError")[](#l1.73)
self.assertEqual(trace,[[](#l1.74)
"Starting g1",[](#l1.75)
"Starting g2",[](#l1.76)
"Finishing g2",[](#l1.77)
"Finishing g1",[](#l1.78)
])[](#l1.79)
- def test_delegation_of_next_call_to_subgenerator(self):
"""[](#l1.82)
Test delegation of next() call to subgenerator[](#l1.83)
"""[](#l1.84)
trace = [][](#l1.85)
def g1():[](#l1.86)
trace.append("Starting g1")[](#l1.87)
yield "g1 ham"[](#l1.88)
yield from g2()[](#l1.89)
yield "g1 eggs"[](#l1.90)
trace.append("Finishing g1")[](#l1.91)
def g2():[](#l1.92)
trace.append("Starting g2")[](#l1.93)
yield "g2 spam"[](#l1.94)
yield "g2 more spam"[](#l1.95)
trace.append("Finishing g2")[](#l1.96)
for x in g1():[](#l1.97)
trace.append("Yielded %s" % (x,))[](#l1.98)
self.assertEqual(trace,[[](#l1.99)
"Starting g1",[](#l1.100)
"Yielded g1 ham",[](#l1.101)
"Starting g2",[](#l1.102)
"Yielded g2 spam",[](#l1.103)
"Yielded g2 more spam",[](#l1.104)
"Finishing g2",[](#l1.105)
"Yielded g1 eggs",[](#l1.106)
"Finishing g1",[](#l1.107)
])[](#l1.108)
- def test_raising_exception_in_delegated_next_call(self):
"""[](#l1.111)
Test raising exception in delegated next() call[](#l1.112)
"""[](#l1.113)
trace = [][](#l1.114)
def g1():[](#l1.115)
try:[](#l1.116)
trace.append("Starting g1")[](#l1.117)
yield "g1 ham"[](#l1.118)
yield from g2()[](#l1.119)
yield "g1 eggs"[](#l1.120)
finally:[](#l1.121)
trace.append("Finishing g1")[](#l1.122)
def g2():[](#l1.123)
try:[](#l1.124)
trace.append("Starting g2")[](#l1.125)
yield "g2 spam"[](#l1.126)
raise ValueError("hovercraft is full of eels")[](#l1.127)
yield "g2 more spam"[](#l1.128)
finally:[](#l1.129)
trace.append("Finishing g2")[](#l1.130)
try:[](#l1.131)
for x in g1():[](#l1.132)
trace.append("Yielded %s" % (x,))[](#l1.133)
except ValueError as e:[](#l1.134)
self.assertEqual(e.args[0], "hovercraft is full of eels")[](#l1.135)
else:[](#l1.136)
self.fail("subgenerator failed to raise ValueError")[](#l1.137)
self.assertEqual(trace,[[](#l1.138)
"Starting g1",[](#l1.139)
"Yielded g1 ham",[](#l1.140)
"Starting g2",[](#l1.141)
"Yielded g2 spam",[](#l1.142)
"Finishing g2",[](#l1.143)
"Finishing g1",[](#l1.144)
])[](#l1.145)
- def test_delegation_of_send(self):
"""[](#l1.148)
Test delegation of send()[](#l1.149)
"""[](#l1.150)
trace = [][](#l1.151)
def g1():[](#l1.152)
trace.append("Starting g1")[](#l1.153)
x = yield "g1 ham"[](#l1.154)
trace.append("g1 received %s" % (x,))[](#l1.155)
yield from g2()[](#l1.156)
x = yield "g1 eggs"[](#l1.157)
trace.append("g1 received %s" % (x,))[](#l1.158)
trace.append("Finishing g1")[](#l1.159)
def g2():[](#l1.160)
trace.append("Starting g2")[](#l1.161)
x = yield "g2 spam"[](#l1.162)
trace.append("g2 received %s" % (x,))[](#l1.163)
x = yield "g2 more spam"[](#l1.164)
trace.append("g2 received %s" % (x,))[](#l1.165)
trace.append("Finishing g2")[](#l1.166)
g = g1()[](#l1.167)
y = next(g)[](#l1.168)
x = 1[](#l1.169)
try:[](#l1.170)
while 1:[](#l1.171)
y = g.send(x)[](#l1.172)
trace.append("Yielded %s" % (y,))[](#l1.173)
x += 1[](#l1.174)
except StopIteration:[](#l1.175)
pass[](#l1.176)
self.assertEqual(trace,[[](#l1.177)
"Starting g1",[](#l1.178)
"g1 received 1",[](#l1.179)
"Starting g2",[](#l1.180)
"Yielded g2 spam",[](#l1.181)
"g2 received 2",[](#l1.182)
"Yielded g2 more spam",[](#l1.183)
"g2 received 3",[](#l1.184)
"Finishing g2",[](#l1.185)
"Yielded g1 eggs",[](#l1.186)
"g1 received 4",[](#l1.187)
"Finishing g1",[](#l1.188)
])[](#l1.189)
- def test_handling_exception_while_delegating_send(self):
"""[](#l1.192)
Test handling exception while delegating 'send'[](#l1.193)
"""[](#l1.194)
trace = [][](#l1.195)
def g1():[](#l1.196)
trace.append("Starting g1")[](#l1.197)
x = yield "g1 ham"[](#l1.198)
trace.append("g1 received %s" % (x,))[](#l1.199)
yield from g2()[](#l1.200)
x = yield "g1 eggs"[](#l1.201)
trace.append("g1 received %s" % (x,))[](#l1.202)
trace.append("Finishing g1")[](#l1.203)
def g2():[](#l1.204)
trace.append("Starting g2")[](#l1.205)
x = yield "g2 spam"[](#l1.206)
trace.append("g2 received %s" % (x,))[](#l1.207)
raise ValueError("hovercraft is full of eels")[](#l1.208)
x = yield "g2 more spam"[](#l1.209)
trace.append("g2 received %s" % (x,))[](#l1.210)
trace.append("Finishing g2")[](#l1.211)
def run():[](#l1.212)
g = g1()[](#l1.213)
y = next(g)[](#l1.214)
x = 1[](#l1.215)
try:[](#l1.216)
while 1:[](#l1.217)
y = g.send(x)[](#l1.218)
trace.append("Yielded %s" % (y,))[](#l1.219)
x += 1[](#l1.220)
except StopIteration:[](#l1.221)
trace.append("StopIteration")[](#l1.222)
self.assertRaises(ValueError,run)[](#l1.223)
self.assertEqual(trace,[[](#l1.224)
"Starting g1",[](#l1.225)
"g1 received 1",[](#l1.226)
"Starting g2",[](#l1.227)
"Yielded g2 spam",[](#l1.228)
"g2 received 2",[](#l1.229)
])[](#l1.230)
- def test_delegating_close(self):
"""[](#l1.233)
Test delegating 'close'[](#l1.234)
"""[](#l1.235)
trace = [][](#l1.236)
def g1():[](#l1.237)
try:[](#l1.238)
trace.append("Starting g1")[](#l1.239)
yield "g1 ham"[](#l1.240)
yield from g2()[](#l1.241)
yield "g1 eggs"[](#l1.242)
finally:[](#l1.243)
trace.append("Finishing g1")[](#l1.244)
def g2():[](#l1.245)
try:[](#l1.246)
trace.append("Starting g2")[](#l1.247)
yield "g2 spam"[](#l1.248)
yield "g2 more spam"[](#l1.249)
finally:[](#l1.250)
trace.append("Finishing g2")[](#l1.251)
g = g1()[](#l1.252)
for i in range(2):[](#l1.253)
x = next(g)[](#l1.254)
trace.append("Yielded %s" % (x,))[](#l1.255)
g.close()[](#l1.256)
self.assertEqual(trace,[[](#l1.257)
"Starting g1",[](#l1.258)
"Yielded g1 ham",[](#l1.259)
"Starting g2",[](#l1.260)
"Yielded g2 spam",[](#l1.261)
"Finishing g2",[](#l1.262)
"Finishing g1"[](#l1.263)
])[](#l1.264)
- def test_handing_exception_while_delegating_close(self):
"""[](#l1.267)
Test handling exception while delegating 'close'[](#l1.268)
"""[](#l1.269)
trace = [][](#l1.270)
def g1():[](#l1.271)
try:[](#l1.272)
trace.append("Starting g1")[](#l1.273)
yield "g1 ham"[](#l1.274)
yield from g2()[](#l1.275)
yield "g1 eggs"[](#l1.276)
finally:[](#l1.277)
trace.append("Finishing g1")[](#l1.278)
def g2():[](#l1.279)
try:[](#l1.280)
trace.append("Starting g2")[](#l1.281)
yield "g2 spam"[](#l1.282)
yield "g2 more spam"[](#l1.283)
finally:[](#l1.284)
trace.append("Finishing g2")[](#l1.285)
raise ValueError("nybbles have exploded with delight")[](#l1.286)
try:[](#l1.287)
g = g1()[](#l1.288)
for i in range(2):[](#l1.289)
x = next(g)[](#l1.290)
trace.append("Yielded %s" % (x,))[](#l1.291)
g.close()[](#l1.292)
except ValueError as e:[](#l1.293)
self.assertEqual(e.args[0], "nybbles have exploded with delight")[](#l1.294)
self.assertIsInstance(e.__context__, GeneratorExit)[](#l1.295)
else:[](#l1.296)
self.fail("subgenerator failed to raise ValueError")[](#l1.297)
self.assertEqual(trace,[[](#l1.298)
"Starting g1",[](#l1.299)
"Yielded g1 ham",[](#l1.300)
"Starting g2",[](#l1.301)
"Yielded g2 spam",[](#l1.302)
"Finishing g2",[](#l1.303)
"Finishing g1",[](#l1.304)
])[](#l1.305)
- def test_delegating_throw(self):
"""[](#l1.308)
Test delegating 'throw'[](#l1.309)
"""[](#l1.310)
trace = [][](#l1.311)
def g1():[](#l1.312)
try:[](#l1.313)
trace.append("Starting g1")[](#l1.314)
yield "g1 ham"[](#l1.315)
yield from g2()[](#l1.316)
yield "g1 eggs"[](#l1.317)
finally:[](#l1.318)
trace.append("Finishing g1")[](#l1.319)
def g2():[](#l1.320)
try:[](#l1.321)
trace.append("Starting g2")[](#l1.322)
yield "g2 spam"[](#l1.323)
yield "g2 more spam"[](#l1.324)
finally:[](#l1.325)
trace.append("Finishing g2")[](#l1.326)
try:[](#l1.327)
g = g1()[](#l1.328)
for i in range(2):[](#l1.329)
x = next(g)[](#l1.330)
trace.append("Yielded %s" % (x,))[](#l1.331)
e = ValueError("tomato ejected")[](#l1.332)
g.throw(e)[](#l1.333)
except ValueError as e:[](#l1.334)
self.assertEqual(e.args[0], "tomato ejected")[](#l1.335)
else:[](#l1.336)
self.fail("subgenerator failed to raise ValueError")[](#l1.337)
self.assertEqual(trace,[[](#l1.338)
"Starting g1",[](#l1.339)
"Yielded g1 ham",[](#l1.340)
"Starting g2",[](#l1.341)
"Yielded g2 spam",[](#l1.342)
"Finishing g2",[](#l1.343)
"Finishing g1",[](#l1.344)
])[](#l1.345)
- def test_value_attribute_of_StopIteration_exception(self):
"""[](#l1.348)
Test 'value' attribute of StopIteration exception[](#l1.349)
"""[](#l1.350)
trace = [][](#l1.351)
def pex(e):[](#l1.352)
trace.append("%s: %s" % (e.__class__.__name__, e))[](#l1.353)
trace.append("value = %s" % (e.value,))[](#l1.354)
e = StopIteration()[](#l1.355)
pex(e)[](#l1.356)
e = StopIteration("spam")[](#l1.357)
pex(e)[](#l1.358)
e.value = "eggs"[](#l1.359)
pex(e)[](#l1.360)
self.assertEqual(trace,[[](#l1.361)
"StopIteration: ",[](#l1.362)
"value = None",[](#l1.363)
"StopIteration: spam",[](#l1.364)
"value = spam",[](#l1.365)
"StopIteration: spam",[](#l1.366)
"value = eggs",[](#l1.367)
])[](#l1.368)
- def test_generator_return_value(self):
"""[](#l1.372)
Test generator return value[](#l1.373)
"""[](#l1.374)
trace = [][](#l1.375)
def g1():[](#l1.376)
trace.append("Starting g1")[](#l1.377)
yield "g1 ham"[](#l1.378)
ret = yield from g2()[](#l1.379)
trace.append("g2 returned %s" % (ret,))[](#l1.380)
ret = yield from g2(42)[](#l1.381)
trace.append("g2 returned %s" % (ret,))[](#l1.382)
yield "g1 eggs"[](#l1.383)
trace.append("Finishing g1")[](#l1.384)
def g2(v = None):[](#l1.385)
trace.append("Starting g2")[](#l1.386)
yield "g2 spam"[](#l1.387)
yield "g2 more spam"[](#l1.388)
trace.append("Finishing g2")[](#l1.389)
if v:[](#l1.390)
return v[](#l1.391)
for x in g1():[](#l1.392)
trace.append("Yielded %s" % (x,))[](#l1.393)
self.assertEqual(trace,[[](#l1.394)
"Starting g1",[](#l1.395)
"Yielded g1 ham",[](#l1.396)
"Starting g2",[](#l1.397)
"Yielded g2 spam",[](#l1.398)
"Yielded g2 more spam",[](#l1.399)
"Finishing g2",[](#l1.400)
"g2 returned None",[](#l1.401)
"Starting g2",[](#l1.402)
"Yielded g2 spam",[](#l1.403)
"Yielded g2 more spam",[](#l1.404)
"Finishing g2",[](#l1.405)
"g2 returned 42",[](#l1.406)
"Yielded g1 eggs",[](#l1.407)
"Finishing g1",[](#l1.408)
])[](#l1.409)
- def test_delegation_of_next_to_non_generator(self):
"""[](#l1.412)
Test delegation of next() to non-generator[](#l1.413)
"""[](#l1.414)
trace = [][](#l1.415)
def g():[](#l1.416)
yield from range(3)[](#l1.417)
for x in g():[](#l1.418)
trace.append("Yielded %s" % (x,))[](#l1.419)
self.assertEqual(trace,[[](#l1.420)
"Yielded 0",[](#l1.421)
"Yielded 1",[](#l1.422)
"Yielded 2",[](#l1.423)
])[](#l1.424)
- def test_conversion_of_sendNone_to_next(self):
"""[](#l1.428)
Test conversion of send(None) to next()[](#l1.429)
"""[](#l1.430)
trace = [][](#l1.431)
def g():[](#l1.432)
yield from range(3)[](#l1.433)
gi = g()[](#l1.434)
for x in range(3):[](#l1.435)
y = gi.send(None)[](#l1.436)
trace.append("Yielded: %s" % (y,))[](#l1.437)
self.assertEqual(trace,[[](#l1.438)
"Yielded: 0",[](#l1.439)
"Yielded: 1",[](#l1.440)
"Yielded: 2",[](#l1.441)
])[](#l1.442)
- def test_delegation_of_close_to_non_generator(self):
"""[](#l1.445)
Test delegation of close() to non-generator[](#l1.446)
"""[](#l1.447)
trace = [][](#l1.448)
def g():[](#l1.449)
try:[](#l1.450)
trace.append("starting g")[](#l1.451)
yield from range(3)[](#l1.452)
trace.append("g should not be here")[](#l1.453)
finally:[](#l1.454)
trace.append("finishing g")[](#l1.455)
gi = g()[](#l1.456)
next(gi)[](#l1.457)
with captured_stderr() as output:[](#l1.458)
gi.close()[](#l1.459)
self.assertEqual(output.getvalue(), '')[](#l1.460)
self.assertEqual(trace,[[](#l1.461)
"starting g",[](#l1.462)
"finishing g",[](#l1.463)
])[](#l1.464)
- def test_delegating_throw_to_non_generator(self):
"""[](#l1.467)
Test delegating 'throw' to non-generator[](#l1.468)
"""[](#l1.469)
trace = [][](#l1.470)
def g():[](#l1.471)
try:[](#l1.472)
trace.append("Starting g")[](#l1.473)
yield from range(10)[](#l1.474)
finally:[](#l1.475)
trace.append("Finishing g")[](#l1.476)
try:[](#l1.477)
gi = g()[](#l1.478)
for i in range(5):[](#l1.479)
x = next(gi)[](#l1.480)
trace.append("Yielded %s" % (x,))[](#l1.481)
e = ValueError("tomato ejected")[](#l1.482)
gi.throw(e)[](#l1.483)
except ValueError as e:[](#l1.484)
self.assertEqual(e.args[0],"tomato ejected")[](#l1.485)
else:[](#l1.486)
self.fail("subgenerator failed to raise ValueError")[](#l1.487)
self.assertEqual(trace,[[](#l1.488)
"Starting g",[](#l1.489)
"Yielded 0",[](#l1.490)
"Yielded 1",[](#l1.491)
"Yielded 2",[](#l1.492)
"Yielded 3",[](#l1.493)
"Yielded 4",[](#l1.494)
"Finishing g",[](#l1.495)
])[](#l1.496)
- def test_attempting_to_send_to_non_generator(self):
"""[](#l1.499)
Test attempting to send to non-generator[](#l1.500)
"""[](#l1.501)
trace = [][](#l1.502)
def g():[](#l1.503)
try:[](#l1.504)
trace.append("starting g")[](#l1.505)
yield from range(3)[](#l1.506)
trace.append("g should not be here")[](#l1.507)
finally:[](#l1.508)
trace.append("finishing g")[](#l1.509)
try:[](#l1.510)
gi = g()[](#l1.511)
next(gi)[](#l1.512)
for x in range(3):[](#l1.513)
y = gi.send(42)[](#l1.514)
trace.append("Should not have yielded:", y)[](#l1.515)
except AttributeError as e:[](#l1.516)
self.assertIn("send", e.args[0])[](#l1.517)
else:[](#l1.518)
self.fail("was able to send into non-generator")[](#l1.519)
self.assertEqual(trace,[[](#l1.520)
"starting g",[](#l1.521)
"finishing g",[](#l1.522)
])[](#l1.523)
- def test_broken_getattr_handling(self):
"""[](#l1.526)
Test subiterator with a broken getattr implementation[](#l1.527)
"""[](#l1.528)
class Broken:[](#l1.529)
def __iter__(self):[](#l1.530)
return self[](#l1.531)
def __next__(self):[](#l1.532)
return 1[](#l1.533)
def __getattr__(self, attr):[](#l1.534)
1/0[](#l1.535)
def g():[](#l1.537)
yield from Broken()[](#l1.538)
with self.assertRaises(ZeroDivisionError):[](#l1.540)
gi = g()[](#l1.541)
self.assertEqual(next(gi), 1)[](#l1.542)
gi.send(1)[](#l1.543)
with self.assertRaises(ZeroDivisionError):[](#l1.545)
gi = g()[](#l1.546)
self.assertEqual(next(gi), 1)[](#l1.547)
gi.throw(AttributeError)[](#l1.548)
with captured_stderr() as output:[](#l1.550)
gi = g()[](#l1.551)
self.assertEqual(next(gi), 1)[](#l1.552)
gi.close()[](#l1.553)
self.assertIn('ZeroDivisionError', output.getvalue())[](#l1.554)
- def test_exception_in_initial_next_call(self):
"""[](#l1.557)
Test exception in initial next() call[](#l1.558)
"""[](#l1.559)
trace = [][](#l1.560)
def g1():[](#l1.561)
trace.append("g1 about to yield from g2")[](#l1.562)
yield from g2()[](#l1.563)
trace.append("g1 should not be here")[](#l1.564)
def g2():[](#l1.565)
yield 1/0[](#l1.566)
def run():[](#l1.567)
gi = g1()[](#l1.568)
next(gi)[](#l1.569)
self.assertRaises(ZeroDivisionError,run)[](#l1.570)
self.assertEqual(trace,[[](#l1.571)
"g1 about to yield from g2"[](#l1.572)
])[](#l1.573)
- def test_attempted_yield_from_loop(self):
"""[](#l1.576)
Test attempted yield-from loop[](#l1.577)
"""[](#l1.578)
trace = [][](#l1.579)
def g1():[](#l1.580)
trace.append("g1: starting")[](#l1.581)
yield "y1"[](#l1.582)
trace.append("g1: about to yield from g2")[](#l1.583)
yield from g2()[](#l1.584)
trace.append("g1 should not be here")[](#l1.585)
def g2():[](#l1.587)
trace.append("g2: starting")[](#l1.588)
yield "y2"[](#l1.589)
trace.append("g2: about to yield from g1")[](#l1.590)
yield from gi[](#l1.591)
trace.append("g2 should not be here")[](#l1.592)
try:[](#l1.593)
gi = g1()[](#l1.594)
for y in gi:[](#l1.595)
trace.append("Yielded: %s" % (y,))[](#l1.596)
except ValueError as e:[](#l1.597)
self.assertEqual(e.args[0],"generator already executing")[](#l1.598)
else:[](#l1.599)
self.fail("subgenerator didn't raise ValueError")[](#l1.600)
self.assertEqual(trace,[[](#l1.601)
"g1: starting",[](#l1.602)
"Yielded: y1",[](#l1.603)
"g1: about to yield from g2",[](#l1.604)
"g2: starting",[](#l1.605)
"Yielded: y2",[](#l1.606)
"g2: about to yield from g1",[](#l1.607)
])[](#l1.608)
- def test_returning_value_from_delegated_throw(self):
"""[](#l1.611)
Test returning value from delegated 'throw'[](#l1.612)
"""[](#l1.613)
trace = [][](#l1.614)
def g1():[](#l1.615)
try:[](#l1.616)
trace.append("Starting g1")[](#l1.617)
yield "g1 ham"[](#l1.618)
yield from g2()[](#l1.619)
yield "g1 eggs"[](#l1.620)
finally:[](#l1.621)
trace.append("Finishing g1")[](#l1.622)
def g2():[](#l1.623)
try:[](#l1.624)
trace.append("Starting g2")[](#l1.625)
yield "g2 spam"[](#l1.626)
yield "g2 more spam"[](#l1.627)
except LunchError:[](#l1.628)
trace.append("Caught LunchError in g2")[](#l1.629)
yield "g2 lunch saved"[](#l1.630)
yield "g2 yet more spam"[](#l1.631)
class LunchError(Exception):[](#l1.632)
pass[](#l1.633)
g = g1()[](#l1.634)
for i in range(2):[](#l1.635)
x = next(g)[](#l1.636)
trace.append("Yielded %s" % (x,))[](#l1.637)
e = LunchError("tomato ejected")[](#l1.638)
g.throw(e)[](#l1.639)
for x in g:[](#l1.640)
trace.append("Yielded %s" % (x,))[](#l1.641)
self.assertEqual(trace,[[](#l1.642)
"Starting g1",[](#l1.643)
"Yielded g1 ham",[](#l1.644)
"Starting g2",[](#l1.645)
"Yielded g2 spam",[](#l1.646)
"Caught LunchError in g2",[](#l1.647)
"Yielded g2 yet more spam",[](#l1.648)
"Yielded g1 eggs",[](#l1.649)
"Finishing g1",[](#l1.650)
])[](#l1.651)
- def test_next_and_return_with_value(self):
"""[](#l1.654)
Test next and return with value[](#l1.655)
"""[](#l1.656)
trace = [][](#l1.657)
def f(r):[](#l1.658)
gi = g(r)[](#l1.659)
next(gi)[](#l1.660)
try:[](#l1.661)
trace.append("f resuming g")[](#l1.662)
next(gi)[](#l1.663)
trace.append("f SHOULD NOT BE HERE")[](#l1.664)
except StopIteration as e:[](#l1.665)
trace.append("f caught %s" % (repr(e),))[](#l1.666)
def g(r):[](#l1.667)
trace.append("g starting")[](#l1.668)
yield[](#l1.669)
trace.append("g returning %s" % (r,))[](#l1.670)
return r[](#l1.671)
f(None)[](#l1.672)
f(42)[](#l1.673)
self.assertEqual(trace,[[](#l1.674)
"g starting",[](#l1.675)
"f resuming g",[](#l1.676)
"g returning None",[](#l1.677)
"f caught StopIteration()",[](#l1.678)
"g starting",[](#l1.679)
"f resuming g",[](#l1.680)
"g returning 42",[](#l1.681)
"f caught StopIteration(42,)",[](#l1.682)
])[](#l1.683)
- def test_send_and_return_with_value(self):
"""[](#l1.686)
Test send and return with value[](#l1.687)
"""[](#l1.688)
trace = [][](#l1.689)
def f(r):[](#l1.690)
gi = g(r)[](#l1.691)
next(gi)[](#l1.692)
try:[](#l1.693)
trace.append("f sending spam to g")[](#l1.694)
gi.send("spam")[](#l1.695)
trace.append("f SHOULD NOT BE HERE")[](#l1.696)
except StopIteration as e:[](#l1.697)
trace.append("f caught %r" % (e,))[](#l1.698)
def g(r):[](#l1.699)
trace.append("g starting")[](#l1.700)
x = yield[](#l1.701)
trace.append("g received %s" % (x,))[](#l1.702)
trace.append("g returning %s" % (r,))[](#l1.703)
return r[](#l1.704)
f(None)[](#l1.705)
f(42)[](#l1.706)
self.assertEqual(trace,[[](#l1.707)
"g starting",[](#l1.708)
"f sending spam to g",[](#l1.709)
"g received spam",[](#l1.710)
"g returning None",[](#l1.711)
"f caught StopIteration()",[](#l1.712)
"g starting",[](#l1.713)
"f sending spam to g",[](#l1.714)
"g received spam",[](#l1.715)
"g returning 42",[](#l1.716)
"f caught StopIteration(42,)",[](#l1.717)
])[](#l1.718)
- def test_catching_exception_from_subgen_and_returning(self):
"""[](#l1.721)
Test catching an exception thrown into a[](#l1.722)
subgenerator and returning a value[](#l1.723)
"""[](#l1.724)
trace = [][](#l1.725)
def inner():[](#l1.726)
try:[](#l1.727)
yield 1[](#l1.728)
except ValueError:[](#l1.729)
trace.append("inner caught ValueError")[](#l1.730)
return 2[](#l1.731)
def outer():[](#l1.733)
v = yield from inner()[](#l1.734)
trace.append("inner returned %r to outer" % v)[](#l1.735)
yield v[](#l1.736)
g = outer()[](#l1.737)
trace.append(next(g))[](#l1.738)
trace.append(g.throw(ValueError))[](#l1.739)
self.assertEqual(trace,[[](#l1.740)
1,[](#l1.741)
"inner caught ValueError",[](#l1.742)
"inner returned 2 to outer",[](#l1.743)
2,[](#l1.744)
])[](#l1.745)
- def test_throwing_GeneratorExit_into_subgen_that_returns(self):
"""[](#l1.748)
Test throwing GeneratorExit into a subgenerator that[](#l1.749)
catches it and returns normally.[](#l1.750)
"""[](#l1.751)
trace = [][](#l1.752)
def f():[](#l1.753)
try:[](#l1.754)
trace.append("Enter f")[](#l1.755)
yield[](#l1.756)
trace.append("Exit f")[](#l1.757)
except GeneratorExit:[](#l1.758)
return[](#l1.759)
def g():[](#l1.760)
trace.append("Enter g")[](#l1.761)
yield from f()[](#l1.762)
trace.append("Exit g")[](#l1.763)
try:[](#l1.764)
gi = g()[](#l1.765)
next(gi)[](#l1.766)
gi.throw(GeneratorExit)[](#l1.767)
except GeneratorExit:[](#l1.768)
pass[](#l1.769)
else:[](#l1.770)
self.fail("subgenerator failed to raise GeneratorExit")[](#l1.771)
self.assertEqual(trace,[[](#l1.772)
"Enter g",[](#l1.773)
"Enter f",[](#l1.774)
])[](#l1.775)
- def test_throwing_GeneratorExit_into_subgenerator_that_yields(self):
"""[](#l1.778)
Test throwing GeneratorExit into a subgenerator that[](#l1.779)
catches it and yields.[](#l1.780)
"""[](#l1.781)
trace = [][](#l1.782)
def f():[](#l1.783)
try:[](#l1.784)
trace.append("Enter f")[](#l1.785)
yield[](#l1.786)
trace.append("Exit f")[](#l1.787)
except GeneratorExit:[](#l1.788)
yield[](#l1.789)
def g():[](#l1.790)
trace.append("Enter g")[](#l1.791)
yield from f()[](#l1.792)
trace.append("Exit g")[](#l1.793)
try:[](#l1.794)
gi = g()[](#l1.795)
next(gi)[](#l1.796)
gi.throw(GeneratorExit)[](#l1.797)
except RuntimeError as e:[](#l1.798)
self.assertEqual(e.args[0], "generator ignored GeneratorExit")[](#l1.799)
else:[](#l1.800)
self.fail("subgenerator failed to raise GeneratorExit")[](#l1.801)
self.assertEqual(trace,[[](#l1.802)
"Enter g",[](#l1.803)
"Enter f",[](#l1.804)
])[](#l1.805)
- def test_throwing_GeneratorExit_into_subgen_that_raises(self):
"""[](#l1.808)
Test throwing GeneratorExit into a subgenerator that[](#l1.809)
catches it and raises a different exception.[](#l1.810)
"""[](#l1.811)
trace = [][](#l1.812)
def f():[](#l1.813)
try:[](#l1.814)
trace.append("Enter f")[](#l1.815)
yield[](#l1.816)
trace.append("Exit f")[](#l1.817)
except GeneratorExit:[](#l1.818)
raise ValueError("Vorpal bunny encountered")[](#l1.819)
def g():[](#l1.820)
trace.append("Enter g")[](#l1.821)
yield from f()[](#l1.822)
trace.append("Exit g")[](#l1.823)
try:[](#l1.824)
gi = g()[](#l1.825)
next(gi)[](#l1.826)
gi.throw(GeneratorExit)[](#l1.827)
except ValueError as e:[](#l1.828)
self.assertEqual(e.args[0], "Vorpal bunny encountered")[](#l1.829)
self.assertIsInstance(e.__context__, GeneratorExit)[](#l1.830)
else:[](#l1.831)
self.fail("subgenerator failed to raise ValueError")[](#l1.832)
self.assertEqual(trace,[[](#l1.833)
"Enter g",[](#l1.834)
"Enter f",[](#l1.835)
])[](#l1.836)