Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(95853)

Delta Between Two Patch Sets: Lib/test/test_pep380.py

Issue 11682: PEP 380 reference implementation for 3.3
Left Patch Set: Created 8 years, 1 month ago
Right Patch Set: Created 7 years, 7 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
Left: Side by side diff | Download
Right: Side by side diff | Download
LEFTRIGHT
1 # -*- coding: utf-8 -*- 1 # -*- coding: utf-8 -*-
Benjamin Peterson 2011/07/09 18:41:14 This file is really hideous. It should be converte
Nick Coghlan 2011/09/20 13:21:02 Done.
2 2
3 """ 3 """
4 Test suite for PEP 380 implementation 4 Test suite for PEP 380 implementation
5 5
6 adapted from original tests written by Greg Ewing 6 adapted from original tests written by Greg Ewing
7 see <http://www.cosc.canterbury.ac.nz/greg.ewing/python/yield-from/YieldFrom-Pyt hon3.1.2-rev5.zip> 7 see <http://www.cosc.canterbury.ac.nz/greg.ewing/python/yield-from/YieldFrom-Pyt hon3.1.2-rev5.zip>
8 """ 8 """
9 9
10 import unittest 10 import unittest
11 import io 11 import io
12 import sys 12 import sys
13 import traceback 13 import traceback
14 14 import parser
15 # XXX (ncoghlan): The line numbers make many of these tests quite fragile. 15
16 # Ideally the whole lot should be modified to use independent asserts rather 16 from test.support import captured_stderr
17 # than golden output comparisons 17
18 18 class TestPEP380Operation(unittest.TestCase):
19 class PEP380Test(unittest.TestCase):
20 maxDiff = None
21 def setUp(self):
22 self.out = io.StringIO()
23 self.saved_stdout = sys.stdout
24 self.saved_stderr = sys.stderr
25 sys.stdout = sys.stderr = self.out
26
27 def test(self):
28 try:
29 self.case()
30 except:
31 et, ev, tb = sys.exc_info()
32 tb = tb.tb_next
33 traceback.print_exception(et, ev, tb)
34 # Trailing whitespace does not play nicely with checkin hooks
35 self.assertEqual('\n'.join(line.rstrip() for line in self.out.getvalue() .split('\n')),
36 '\n'.join(line.rstrip() for line in self.expected.split ('\n')))
37
38 def tearDown(self):
39 sys.stdout = self.saved_stdout
40 sys.stderr = self.saved_stderr
41 self.out.close()
42
43
44 class Test1(PEP380Test):
Benjamin Peterson 2011/07/09 18:41:14 What is the point of this test? Shouldn't the sema
Nick Coghlan 2011/09/20 13:21:02 Done.
45 """ 19 """
46 Test grammar and code generation 20 Test semantics.
47 """ 21 """
48 22
49 expected = """\ 23 def test_delegation_of_initial_next_to_subgenerator(self):
50 ---------- g1 ---------- 24 """
51 78 0 LOAD_CONST 0 (None) 25 Test delegation of initial next() call to subgenerator
52 3 YIELD_VALUE 26 """
53 4 POP_TOP 27 trace = []
54 28 def g1():
55 79 5 LOAD_CONST 1 (42) 29 trace.append("Starting g1")
56 8 YIELD_VALUE 30 yield from g2()
57 9 POP_TOP 31 trace.append("Finishing g1")
58 10 LOAD_CONST 0 (None) 32 def g2():
59 13 RETURN_VALUE 33 trace.append("Starting g2")
60 ---------- g2 ----------
61 82 0 LOAD_GLOBAL 0 (x)
62 3 YIELD_FROM
63 4 POP_TOP
64 5 LOAD_CONST 0 (None)
65 8 RETURN_VALUE
66 ---------- g3 ----------
67 85 0 LOAD_FAST 0 (x)
68 3 YIELD_FROM
69 4 STORE_FAST 0 (x)
70 7 LOAD_CONST 0 (None)
71 10 RETURN_VALUE
72 """.format(__file__)
73
74 def case(self):
75 import dis
76
77 def g1():
78 yield
79 yield 42 34 yield 42
80 35 trace.append("Finishing g2")
81 def g2():
82 yield from x
83
84 def g3():
85 x = yield from x
86
87 def disgen(g):
88 print("---------- %s ----------" % g.__name__)
89 dis.dis(g)
90
91 disgen(g1)
92 disgen(g2)
93 disgen(g3)
94
95
96 class Test2(PEP380Test):
97 """
98 Test delegation of initial next() call to subgenerator
99 """
100
101 expected = """\
102 Starting g1
103 Starting g2
104 Yielded 42
105 Finishing g2
106 Finishing g1
107 """.format(__file__)
108
109 def case(self):
110 def g1():
111 print("Starting g1")
112 yield from g2()
113 print("Finishing g1")
114
115 def g2():
116 print("Starting g2")
117 yield 42
118 print("Finishing g2")
119
120 for x in g1(): 36 for x in g1():
121 print("Yielded", x) 37 trace.append("Yielded %s" % (x,))
122 38 self.assertEqual(trace,[
123 39 "Starting g1",
124 class Test3(PEP380Test): 40 "Starting g2",
125 """ 41 "Yielded 42",
126 Test raising exception in initial next() call 42 "Finishing g2",
127 """ 43 "Finishing g1",
128 44 ])
129 expected = """\ 45
130 Starting g1 46 def test_raising_exception_in_initial_next_call(self):
131 Starting g2 47 """
132 Finishing g2 48 Test raising exception in initial next() call
133 Finishing g1 49 """
134 Traceback (most recent call last): 50 trace = []
135 File "{0}", line 159, in case 51 def g1():
136 for x in g1(): 52 try:
137 File "{0}", line 148, in g1 53 trace.append("Starting g1")
138 yield from g2()
139 File "{0}", line 155, in g2
140 raise ValueError("spanish inquisition occurred")
141 ValueError: spanish inquisition occurred
142 """.format(__file__)
143
144 def case(self):
145 def g1():
146 try:
147 print("Starting g1")
148 yield from g2() 54 yield from g2()
149 finally: 55 finally:
150 print("Finishing g1") 56 trace.append("Finishing g1")
151 57 def g2():
152 def g2(): 58 try:
153 try: 59 trace.append("Starting g2")
154 print("Starting g2")
155 raise ValueError("spanish inquisition occurred") 60 raise ValueError("spanish inquisition occurred")
156 finally: 61 finally:
157 print("Finishing g2") 62 trace.append("Finishing g2")
158 63 try:
159 for x in g1(): 64 for x in g1():
160 print("Yielded", x) 65 trace.append("Yielded %s" % (x,))
161 66 except ValueError as e:
162 67 self.assertEqual(e.args[0], "spanish inquisition occurred")
163 class Test4(PEP380Test): 68 else:
164 """ 69 self.fail("subgenerator failed to raise ValueError")
165 Test delegation of next() call to subgenerator 70 self.assertEqual(trace,[
166 """ 71 "Starting g1",
167 72 "Starting g2",
168 expected = """\ 73 "Finishing g2",
169 Starting g1 74 "Finishing g1",
170 Yielded g1 ham 75 ])
171 Starting g2 76
172 Yielded g2 spam 77 def test_delegation_of_next_call_to_subgenerator(self):
173 Yielded g2 more spam 78 """
174 Finishing g2 79 Test delegation of next() call to subgenerator
175 Yielded g1 eggs 80 """
176 Finishing g1 81 trace = []
177 """.format(__file__) 82 def g1():
178 83 trace.append("Starting g1")
179 def case(self):
180
181 def g1():
182 print("Starting g1")
183 yield "g1 ham" 84 yield "g1 ham"
184 yield from g2() 85 yield from g2()
185 yield "g1 eggs" 86 yield "g1 eggs"
186 print("Finishing g1") 87 trace.append("Finishing g1")
187 88 def g2():
188 def g2(): 89 trace.append("Starting g2")
189 print("Starting g2")
190 yield "g2 spam" 90 yield "g2 spam"
191 yield "g2 more spam" 91 yield "g2 more spam"
192 print("Finishing g2") 92 trace.append("Finishing g2")
193
194 for x in g1(): 93 for x in g1():
195 print("Yielded", x) 94 trace.append("Yielded %s" % (x,))
196 95 self.assertEqual(trace,[
197 96 "Starting g1",
198 class Test5(PEP380Test): 97 "Yielded g1 ham",
199 """ 98 "Starting g2",
200 Test raising exception in delegated next() call 99 "Yielded g2 spam",
201 """ 100 "Yielded g2 more spam",
202 101 "Finishing g2",
203 expected = """\ 102 "Yielded g1 eggs",
204 Starting g1 103 "Finishing g1",
205 Yielded g1 ham 104 ])
206 Starting g2 105
207 Yielded g2 spam 106 def test_raising_exception_in_delegated_next_call(self):
208 Finishing g2 107 """
209 Finishing g1 108 Test raising exception in delegated next() call
210 Traceback (most recent call last): 109 """
211 File "{0}", line 239, in case 110 trace = []
212 for x in g1(): 111 def g1():
213 File "{0}", line 225, in g1 112 try:
214 yield from g2() 113 trace.append("Starting g1")
215 File "{0}", line 234, in g2
216 raise ValueError("hovercraft is full of eels")
217 ValueError: hovercraft is full of eels
218 """.format(__file__)
219
220 def case(self):
221 def g1():
222 try:
223 print("Starting g1")
224 yield "g1 ham" 114 yield "g1 ham"
225 yield from g2() 115 yield from g2()
226 yield "g1 eggs" 116 yield "g1 eggs"
227 finally: 117 finally:
228 print("Finishing g1") 118 trace.append("Finishing g1")
229 119 def g2():
230 def g2(): 120 try:
231 try: 121 trace.append("Starting g2")
232 print("Starting g2")
233 yield "g2 spam" 122 yield "g2 spam"
234 raise ValueError("hovercraft is full of eels") 123 raise ValueError("hovercraft is full of eels")
235 yield "g2 more spam" 124 yield "g2 more spam"
236 finally: 125 finally:
237 print("Finishing g2") 126 trace.append("Finishing g2")
238 127 try:
239 for x in g1(): 128 for x in g1():
240 print("Yielded", x) 129 trace.append("Yielded %s" % (x,))
241 130 except ValueError as e:
242 131 self.assertEqual(e.args[0], "hovercraft is full of eels")
243 class Test6(PEP380Test): 132 else:
244 """ 133 self.fail("subgenerator failed to raise ValueError")
245 Test delegation of send() 134 self.assertEqual(trace,[
246 """ 135 "Starting g1",
247 136 "Yielded g1 ham",
248 expected = """\ 137 "Starting g2",
249 Starting g1 138 "Yielded g2 spam",
250 g1 received 1 139 "Finishing g2",
251 Starting g2 140 "Finishing g1",
252 Yielded g2 spam 141 ])
253 g2 received 2 142
254 Yielded g2 more spam 143 def test_delegation_of_send(self):
255 g2 received 3 144 """
256 Finishing g2 145 Test delegation of send()
257 Yielded g1 eggs 146 """
258 g1 received 4 147 trace = []
259 Finishing g1 148 def g1():
260 """.format(__file__) 149 trace.append("Starting g1")
261
262 def case(self):
263 def g1():
264 print("Starting g1")
265 x = yield "g1 ham" 150 x = yield "g1 ham"
266 print("g1 received", x) 151 trace.append("g1 received %s" % (x,))
267 yield from g2() 152 yield from g2()
268 x = yield "g1 eggs" 153 x = yield "g1 eggs"
269 print("g1 received", x) 154 trace.append("g1 received %s" % (x,))
270 print("Finishing g1") 155 trace.append("Finishing g1")
271 156 def g2():
272 def g2(): 157 trace.append("Starting g2")
273 print("Starting g2")
274 x = yield "g2 spam" 158 x = yield "g2 spam"
275 print("g2 received", x) 159 trace.append("g2 received %s" % (x,))
276 x = yield "g2 more spam" 160 x = yield "g2 more spam"
277 print("g2 received", x) 161 trace.append("g2 received %s" % (x,))
278 print("Finishing g2") 162 trace.append("Finishing g2")
279
280 g = g1() 163 g = g1()
281 y = next(g) 164 y = next(g)
282 x = 1 165 x = 1
283 try: 166 try:
284 while 1: 167 while 1:
285 y = g.send(x) 168 y = g.send(x)
286 print("Yielded", y) 169 trace.append("Yielded %s" % (y,))
287 x += 1 170 x += 1
288 except StopIteration: 171 except StopIteration:
289 pass 172 pass
290 173 self.assertEqual(trace,[
291 174 "Starting g1",
292 class Test7(PEP380Test): 175 "g1 received 1",
293 """ 176 "Starting g2",
294 Test handling exception while delegating 'send' 177 "Yielded g2 spam",
295 """ 178 "g2 received 2",
296 179 "Yielded g2 more spam",
297 expected = """\ 180 "g2 received 3",
298 Starting g1 181 "Finishing g2",
299 g1 received 1 182 "Yielded g1 eggs",
300 Starting g2 183 "g1 received 4",
301 Yielded g2 spam 184 "Finishing g1",
302 g2 received 2 185 ])
303 Traceback (most recent call last): 186
304 File "{0}", line 337, in case 187 def test_handling_exception_while_delegating_send(self):
305 y = g.send(x) 188 """
306 File "{0}", line 318, in g1 189 Test handling exception while delegating 'send'
307 yield from g2() 190 """
308 File "{0}", line 327, in g2 191 trace = []
309 raise ValueError("hovercraft is full of eels") 192 def g1():
310 ValueError: hovercraft is full of eels 193 trace.append("Starting g1")
311 """.format(__file__)
312
313 def case(self):
314 def g1():
315 print("Starting g1")
316 x = yield "g1 ham" 194 x = yield "g1 ham"
317 print("g1 received", x) 195 trace.append("g1 received %s" % (x,))
318 yield from g2() 196 yield from g2()
319 x = yield "g1 eggs" 197 x = yield "g1 eggs"
320 print("g1 received", x) 198 trace.append("g1 received %s" % (x,))
321 print("Finishing g1") 199 trace.append("Finishing g1")
322 200 def g2():
323 def g2(): 201 trace.append("Starting g2")
324 print("Starting g2")
325 x = yield "g2 spam" 202 x = yield "g2 spam"
326 print("g2 received", x) 203 trace.append("g2 received %s" % (x,))
327 raise ValueError("hovercraft is full of eels") 204 raise ValueError("hovercraft is full of eels")
328 x = yield "g2 more spam" 205 x = yield "g2 more spam"
329 print("g2 received", x) 206 trace.append("g2 received %s" % (x,))
330 print("Finishing g2") 207 trace.append("Finishing g2")
331 208 def run():
332 g = g1() 209 g = g1()
333 y = next(g) 210 y = next(g)
334 x = 1 211 x = 1
335 try: 212 try:
336 while 1: 213 while 1:
337 y = g.send(x) 214 y = g.send(x)
338 print("Yielded", y) 215 trace.append("Yielded %s" % (y,))
339 x += 1 216 x += 1
340 except StopIteration: 217 except StopIteration:
341 print("StopIteration") 218 trace.append("StopIteration")
342 219 self.assertRaises(ValueError,run)
343 220 self.assertEqual(trace,[
344 221 "Starting g1",
345 class Test8(PEP380Test): 222 "g1 received 1",
346 """ 223 "Starting g2",
347 Test delegating 'close' 224 "Yielded g2 spam",
348 """ 225 "g2 received 2",
349 226 ])
350 expected = """\ 227
351 Starting g1 228 def test_delegating_close(self):
352 Yielded g1 ham 229 """
353 Starting g2 230 Test delegating 'close'
354 Yielded g2 spam 231 """
355 Finishing g2 232 trace = []
356 Finishing g1 233 def g1():
357 """.format(__file__) 234 try:
358 235 trace.append("Starting g1")
359 def case(self):
360 def g1():
361 try:
362 print("Starting g1")
363 yield "g1 ham" 236 yield "g1 ham"
364 yield from g2() 237 yield from g2()
365 yield "g1 eggs" 238 yield "g1 eggs"
366 finally: 239 finally:
367 print("Finishing g1") 240 trace.append("Finishing g1")
368 241 def g2():
369 def g2(): 242 try:
370 try: 243 trace.append("Starting g2")
371 print("Starting g2")
372 yield "g2 spam" 244 yield "g2 spam"
373 yield "g2 more spam" 245 yield "g2 more spam"
374 finally: 246 finally:
375 print("Finishing g2") 247 trace.append("Finishing g2")
376
377 g = g1() 248 g = g1()
378 for i in range(2): 249 for i in range(2):
379 x = next(g) 250 x = next(g)
380 print("Yielded", x) 251 trace.append("Yielded %s" % (x,))
381 g.close() 252 g.close()
382 253 self.assertEqual(trace,[
383 254 "Starting g1",
384 class Test9(PEP380Test): 255 "Yielded g1 ham",
385 """ 256 "Starting g2",
386 Test handling exception while delegating 'close' 257 "Yielded g2 spam",
387 """ 258 "Finishing g2",
388 259 "Finishing g1"
389 expected = """\ 260 ])
390 Starting g1 261
391 Yielded g1 ham 262 def test_handing_exception_while_delegating_close(self):
392 Starting g2 263 """
393 Yielded g2 spam 264 Test handling exception while delegating 'close'
394 Finishing g2 265 """
395 Finishing g1 266 trace = []
396 Traceback (most recent call last): 267 def g1():
397 File "{0}", line 426, in g2 268 try:
398 yield "g2 spam" 269 trace.append("Starting g1")
399 GeneratorExit
400
401 During handling of the above exception, another exception occurred:
402
403 Traceback (most recent call last):
404 File "{0}", line 436, in case
405 g.close()
406 File "{0}", line 418, in g1
407 yield from g2()
408 File "{0}", line 430, in g2
409 raise ValueError("nybbles have exploded with delight")
410 ValueError: nybbles have exploded with delight
411 """.format(__file__)
412
413 def case(self):
414 def g1():
415 try:
416 print("Starting g1")
417 yield "g1 ham" 270 yield "g1 ham"
418 yield from g2() 271 yield from g2()
419 yield "g1 eggs" 272 yield "g1 eggs"
420 finally: 273 finally:
421 print("Finishing g1") 274 trace.append("Finishing g1")
422 275 def g2():
423 def g2(): 276 try:
424 try: 277 trace.append("Starting g2")
425 print("Starting g2")
426 yield "g2 spam" 278 yield "g2 spam"
427 yield "g2 more spam" 279 yield "g2 more spam"
428 finally: 280 finally:
429 print("Finishing g2") 281 trace.append("Finishing g2")
430 raise ValueError("nybbles have exploded with delight") 282 raise ValueError("nybbles have exploded with delight")
431 283 try:
432 g = g1() 284 g = g1()
433 for i in range(2): 285 for i in range(2):
434 x = next(g) 286 x = next(g)
435 print("Yielded", x) 287 trace.append("Yielded %s" % (x,))
436 g.close() 288 g.close()
437 289 except ValueError as e:
438 290 self.assertEqual(e.args[0], "nybbles have exploded with delight")
439 class Test10(PEP380Test): 291 self.assertIsInstance(e.__context__, GeneratorExit)
440 """ 292 else:
441 Test delegating 'throw' 293 self.fail("subgenerator failed to raise ValueError")
442 """ 294 self.assertEqual(trace,[
443 295 "Starting g1",
444 expected = """\ 296 "Yielded g1 ham",
445 Starting g1 297 "Starting g2",
446 Yielded g1 ham 298 "Yielded g2 spam",
447 Starting g2 299 "Finishing g2",
448 Yielded g2 spam 300 "Finishing g1",
449 Finishing g2 301 ])
450 Finishing g1 302
451 Traceback (most recent call last): 303 def test_delegating_throw(self):
452 File "{0}", line 484, in case 304 """
453 g.throw(e) 305 Test delegating 'throw'
454 File "{0}", line 466, in g1 306 """
455 yield from g2() 307 trace = []
456 File "{0}", line 474, in g2 308 def g1():
457 yield "g2 spam" 309 try:
458 ValueError: tomato ejected 310 trace.append("Starting g1")
459 """.format(__file__)
460
461 def case(self):
462 def g1():
463 try:
464 print("Starting g1")
465 yield "g1 ham" 311 yield "g1 ham"
466 yield from g2() 312 yield from g2()
467 yield "g1 eggs" 313 yield "g1 eggs"
468 finally: 314 finally:
469 print("Finishing g1") 315 trace.append("Finishing g1")
470 316 def g2():
471 def g2(): 317 try:
472 try: 318 trace.append("Starting g2")
473 print("Starting g2")
474 yield "g2 spam" 319 yield "g2 spam"
475 yield "g2 more spam" 320 yield "g2 more spam"
476 finally: 321 finally:
477 print("Finishing g2") 322 trace.append("Finishing g2")
478 323 try:
479 g = g1() 324 g = g1()
480 for i in range(2): 325 for i in range(2):
481 x = next(g) 326 x = next(g)
482 print("Yielded", x) 327 trace.append("Yielded %s" % (x,))
483 e = ValueError("tomato ejected") 328 e = ValueError("tomato ejected")
484 g.throw(e) 329 g.throw(e)
485 330 except ValueError as e:
486 331 self.assertEqual(e.args[0], "tomato ejected")
487 class Test11(PEP380Test): 332 else:
488 """ 333 self.fail("subgenerator failed to raise ValueError")
489 Test 'value' attribute of StopIteration exception 334 self.assertEqual(trace,[
490 """ 335 "Starting g1",
491 336 "Yielded g1 ham",
492 expected = """\ 337 "Starting g2",
493 StopIteration: 338 "Yielded g2 spam",
494 value = None 339 "Finishing g2",
495 StopIteration: spam 340 "Finishing g1",
496 value = spam 341 ])
497 StopIteration: spam 342
498 value = eggs 343 def test_value_attribute_of_StopIteration_exception(self):
499 """.format(__file__) 344 """
500 345 Test 'value' attribute of StopIteration exception
501 def case(self): 346 """
347 trace = []
502 def pex(e): 348 def pex(e):
503 print("%s: %s" % (e.__class__.__name__, e)) 349 trace.append("%s: %s" % (e.__class__.__name__, e))
504 print("value =", e.value) 350 trace.append("value = %s" % (e.value,))
505
506 e = StopIteration() 351 e = StopIteration()
507 pex(e) 352 pex(e)
508 e = StopIteration("spam") 353 e = StopIteration("spam")
509 pex(e) 354 pex(e)
510 e.value = "eggs" 355 e.value = "eggs"
511 pex(e) 356 pex(e)
512 357 self.assertEqual(trace,[
513 358 "StopIteration: ",
514 class Test12(PEP380Test): 359 "value = None",
515 """ 360 "StopIteration: spam",
516 Test generator return value 361 "value = spam",
517 """ 362 "StopIteration: spam",
518 363 "value = eggs",
519 expected = """\ 364 ])
520 Starting g1 365
521 Yielded g1 ham 366
522 Starting g2 367 def test_generator_return_value(self):
523 Yielded g2 spam 368 """
524 Yielded g2 more spam 369 Test generator return value
525 Finishing g2 370 """
526 g2 returned None 371 trace = []
527 Starting g2 372 def g1():
528 Yielded g2 spam 373 trace.append("Starting g1")
529 Yielded g2 more spam
530 Finishing g2
531 g2 returned 42
532 Yielded g1 eggs
533 Finishing g1
534 """.format(__file__)
535
536 def case(self):
537 def g1():
538 print("Starting g1")
539 yield "g1 ham" 374 yield "g1 ham"
540 ret = yield from g2() 375 ret = yield from g2()
541 print("g2 returned", ret) 376 trace.append("g2 returned %s" % (ret,))
542 ret = yield from g2(42) 377 ret = yield from g2(42)
543 print("g2 returned", ret) 378 trace.append("g2 returned %s" % (ret,))
544 yield "g1 eggs" 379 yield "g1 eggs"
545 print("Finishing g1") 380 trace.append("Finishing g1")
546
547 def g2(v = None): 381 def g2(v = None):
548 print("Starting g2") 382 trace.append("Starting g2")
549 yield "g2 spam" 383 yield "g2 spam"
550 yield "g2 more spam" 384 yield "g2 more spam"
551 print("Finishing g2") 385 trace.append("Finishing g2")
552 if v: 386 if v:
553 return v 387 return v
554
555 for x in g1(): 388 for x in g1():
556 print("Yielded", x) 389 trace.append("Yielded %s" % (x,))
557 390 self.assertEqual(trace,[
558 391 "Starting g1",
559 class Test13(PEP380Test): 392 "Yielded g1 ham",
560 """ 393 "Starting g2",
561 Test delegation of next() to non-generator 394 "Yielded g2 spam",
562 """ 395 "Yielded g2 more spam",
563 396 "Finishing g2",
564 expected = """\ 397 "g2 returned None",
565 Yielded 0 398 "Starting g2",
566 Yielded 1 399 "Yielded g2 spam",
567 Yielded 2 400 "Yielded g2 more spam",
568 """.format(__file__) 401 "Finishing g2",
569 402 "g2 returned 42",
570 def case(self): 403 "Yielded g1 eggs",
404 "Finishing g1",
405 ])
406
407 def test_delegation_of_next_to_non_generator(self):
408 """
409 Test delegation of next() to non-generator
410 """
411 trace = []
571 def g(): 412 def g():
572 yield from range(3) 413 yield from range(3)
573
574 for x in g(): 414 for x in g():
575 print("Yielded", x) 415 trace.append("Yielded %s" % (x,))
576 416 self.assertEqual(trace,[
577 417 "Yielded 0",
578 class Test14(PEP380Test): 418 "Yielded 1",
579 """ 419 "Yielded 2",
580 Test conversion of send(None) to next() 420 ])
581 """ 421
582 422
583 expected = """\ 423 def test_conversion_of_sendNone_to_next(self):
584 Yielded: 0 424 """
585 Yielded: 1 425 Test conversion of send(None) to next()
586 Yielded: 2 426 """
587 """.format(__file__) 427 trace = []
588
589 def case(self):
590 def g(): 428 def g():
591 yield from range(3) 429 yield from range(3)
592
593 gi = g() 430 gi = g()
594 for x in range(3): 431 for x in range(3):
595 y = gi.send(None) 432 y = gi.send(None)
596 print("Yielded:", y) 433 trace.append("Yielded: %s" % (y,))
597 434 self.assertEqual(trace,[
598 435 "Yielded: 0",
599 class Test15(PEP380Test): 436 "Yielded: 1",
600 """ 437 "Yielded: 2",
601 Test delegation of close() to non-generator 438 ])
602 """ 439
603 440 def test_delegation_of_close_to_non_generator(self):
604 expected = """\ 441 """
605 starting g 442 Test delegation of close() to non-generator
606 finishing g 443 """
607 """.format(__file__) 444 trace = []
608
609 def case(self):
610 def g(): 445 def g():
611 try: 446 try:
612 print("starting g") 447 trace.append("starting g")
613 yield from range(3) 448 yield from range(3)
614 print("g should not be here") 449 trace.append("g should not be here")
615 finally: 450 finally:
616 print("finishing g") 451 trace.append("finishing g")
617
618 gi = g() 452 gi = g()
619 next(gi) 453 next(gi)
620 gi.close() 454 with captured_stderr() as output:
621 455 gi.close()
622 456 self.assertEqual(output.getvalue(), '')
623 class Test16(PEP380Test): 457 self.assertEqual(trace,[
624 """ 458 "starting g",
625 Test delegating 'throw' to non-generator 459 "finishing g",
626 """ 460 ])
627 461
628 expected = """\ 462 def test_delegating_throw_to_non_generator(self):
629 Starting g 463 """
630 Yielded 0 464 Test delegating 'throw' to non-generator
631 Yielded 1 465 """
632 Yielded 2 466 trace = []
633 Yielded 3
634 Yielded 4
635 Finishing g
636 Traceback (most recent call last):
637 File "{0}", line 657, in case
638 gi.throw(e)
639 File "{0}", line 648, in g
640 yield from range(10)
641 ValueError: tomato ejected
642 """.format(__file__)
643
644 def case(self):
645 def g(): 467 def g():
646 try: 468 try:
647 print("Starting g") 469 trace.append("Starting g")
648 yield from range(10) 470 yield from range(10)
649 finally: 471 finally:
650 print("Finishing g") 472 trace.append("Finishing g")
651 473 try:
652 gi = g() 474 gi = g()
653 for i in range(5): 475 for i in range(5):
654 x = next(gi) 476 x = next(gi)
655 print("Yielded", x) 477 trace.append("Yielded %s" % (x,))
656 e = ValueError("tomato ejected") 478 e = ValueError("tomato ejected")
657 gi.throw(e) 479 gi.throw(e)
658 480 except ValueError as e:
659 481 self.assertEqual(e.args[0],"tomato ejected")
660 class Test17(PEP380Test): 482 else:
661 """ 483 self.fail("subgenerator failed to raise ValueError")
662 Test attempting to send to non-generator 484 self.assertEqual(trace,[
663 """ 485 "Starting g",
664 486 "Yielded 0",
665 expected = """\ 487 "Yielded 1",
666 starting g 488 "Yielded 2",
667 finishing g 489 "Yielded 3",
668 Traceback (most recent call last): 490 "Yielded 4",
669 File "{0}", line 688, in case 491 "Finishing g",
670 y = gi.send(42) 492 ])
671 File "{0}", line 680, in g 493
672 yield from range(3) 494 def test_attempting_to_send_to_non_generator(self):
673 AttributeError: send 495 """
674 """.format(__file__) 496 Test attempting to send to non-generator
675 497 """
676 def case(self): 498 trace = []
677 def g(): 499 def g():
678 try: 500 try:
679 print("starting g") 501 trace.append("starting g")
680 yield from range(3) 502 yield from range(3)
681 print("g should not be here") 503 trace.append("g should not be here")
682 finally: 504 finally:
683 print("finishing g") 505 trace.append("finishing g")
684 506 try:
685 gi = g() 507 gi = g()
686 next(gi) 508 next(gi)
687 for x in range(3): 509 for x in range(3):
688 y = gi.send(42) 510 y = gi.send(42)
689 print("Should not have yielded:", y) 511 trace.append("Should not have yielded:", y)
690 512 except AttributeError as e:
691 513 self.assertIn("send", e.args[0])
692 class Test18(PEP380Test): 514 else:
693 """ 515 self.fail("was able to send into non-generator")
694 Test exception in initial next() call 516 self.assertEqual(trace,[
695 """ 517 "starting g",
696 518 "finishing g",
697 expected = """\ 519 ])
698 g1 about to yield from g2 520
699 Traceback (most recent call last): 521 def test_broken_getattr_handling(self):
700 File "{0}", line 719, in case 522 """
701 next(gi) 523 Test subiterator with a broken getattr implementation
702 File "{0}", line 712, in g1 524 """
703 yield from g2() 525 class Broken:
704 File "{0}", line 716, in g2 526 def __iter__(self):
705 yield 1/0 527 return self
706 ZeroDivisionError: division by zero 528 def __next__(self):
707 """.format(__file__) 529 return 1
708 530 def __getattr__(self, attr):
709 def case(self): 531 1/0
710 def g1(): 532
711 print("g1 about to yield from g2") 533 def g():
534 yield from Broken()
535
536 with self.assertRaises(ZeroDivisionError):
537 gi = g()
538 self.assertEqual(next(gi), 1)
539 gi.send(1)
540
541 with self.assertRaises(ZeroDivisionError):
542 gi = g()
543 self.assertEqual(next(gi), 1)
544 gi.throw(AttributeError)
545
546 with captured_stderr() as output:
547 gi = g()
548 self.assertEqual(next(gi), 1)
549 gi.close()
550 self.assertIn('ZeroDivisionError', output.getvalue())
551
552 def test_exception_in_initial_next_call(self):
553 """
554 Test exception in initial next() call
555 """
556 trace = []
557 def g1():
558 trace.append("g1 about to yield from g2")
712 yield from g2() 559 yield from g2()
713 print("g1 should not be here") 560 trace.append("g1 should not be here")
714
715 def g2(): 561 def g2():
716 yield 1/0 562 yield 1/0
717 563 def run():
718 gi = g1() 564 gi = g1()
719 next(gi) 565 next(gi)
720 566 self.assertRaises(ZeroDivisionError,run)
721 567 self.assertEqual(trace,[
722 class Test19(PEP380Test): 568 "g1 about to yield from g2"
723 """ 569 ])
724 Test attempted yield-from loop 570
725 """ 571 def test_attempted_yield_from_loop(self):
726 572 """
727 expected = """\ 573 Test attempted yield-from loop
728 g1: starting 574 """
729 Yielded: y1 575 trace = []
730 g1: about to yield from g2 576 def g1():
731 g2: starting 577 trace.append("g1: starting")
732 Yielded: y2
733 g2: about to yield from g1
734 Traceback (most recent call last):
735 File "{0}", line 760, in case
736 for y in gi:
737 File "{0}", line 756, in g2
738 yield from gi
739 File "{0}", line 749, in g1
740 yield from g2()
741 ValueError: generator already executing
742 """.format(__file__)
743
744 def case(self):
745 def g1():
746 print("g1: starting")
747 yield "y1" 578 yield "y1"
748 print("g1: about to yield from g2") 579 trace.append("g1: about to yield from g2")
749 yield from g2() 580 yield from g2()
750 print("g1 should not be here") 581 trace.append("g1 should not be here")
751 582
752 def g2(): 583 def g2():
753 print("g2: starting") 584 trace.append("g2: starting")
754 yield "y2" 585 yield "y2"
755 print("g2: about to yield from g1") 586 trace.append("g2: about to yield from g1")
756 yield from gi 587 yield from gi
757 print("g2 should not be here") 588 trace.append("g2 should not be here")
758 589 try:
759 gi = g1() 590 gi = g1()
760 for y in gi: 591 for y in gi:
761 print("Yielded:", y) 592 trace.append("Yielded: %s" % (y,))
762 593 except ValueError as e:
763 594 self.assertEqual(e.args[0],"generator already executing")
764 class Test20(PEP380Test): 595 else:
765 """ 596 self.fail("subgenerator didn't raise ValueError")
766 Test returning value from delegated 'throw' 597 self.assertEqual(trace,[
767 """ 598 "g1: starting",
768 599 "Yielded: y1",
769 expected = """\ 600 "g1: about to yield from g2",
770 Starting g1 601 "g2: starting",
771 Yielded g1 ham 602 "Yielded: y2",
772 Starting g2 603 "g2: about to yield from g1",
773 Yielded g2 spam 604 ])
774 Caught LunchError in g2 605
775 Yielded g2 yet more spam 606 def test_returning_value_from_delegated_throw(self):
776 Yielded g1 eggs 607 """
777 Finishing g1 608 Test returning value from delegated 'throw'
778 """.format(__file__) 609 """
779 610 trace = []
780 def case(self): 611 def g1():
781 def g1(): 612 try:
782 try: 613 trace.append("Starting g1")
783 print("Starting g1")
784 yield "g1 ham" 614 yield "g1 ham"
785 yield from g2() 615 yield from g2()
786 yield "g1 eggs" 616 yield "g1 eggs"
787 finally: 617 finally:
788 print("Finishing g1") 618 trace.append("Finishing g1")
789 619 def g2():
790 def g2(): 620 try:
791 try: 621 trace.append("Starting g2")
792 print("Starting g2")
793 yield "g2 spam" 622 yield "g2 spam"
794 yield "g2 more spam" 623 yield "g2 more spam"
795 except LunchError: 624 except LunchError:
796 print("Caught LunchError in g2") 625 trace.append("Caught LunchError in g2")
797 yield "g2 lunch saved" 626 yield "g2 lunch saved"
798 yield "g2 yet more spam" 627 yield "g2 yet more spam"
799
800 class LunchError(Exception): 628 class LunchError(Exception):
801 pass 629 pass
802
803 g = g1() 630 g = g1()
804 for i in range(2): 631 for i in range(2):
805 x = next(g) 632 x = next(g)
806 print("Yielded", x) 633 trace.append("Yielded %s" % (x,))
807 e = LunchError("tomato ejected") 634 e = LunchError("tomato ejected")
808 g.throw(e) 635 g.throw(e)
809 for x in g: 636 for x in g:
810 print("Yielded", x) 637 trace.append("Yielded %s" % (x,))
811 638 self.assertEqual(trace,[
812 639 "Starting g1",
813 class Test21(PEP380Test): 640 "Yielded g1 ham",
814 """ 641 "Starting g2",
815 Test next and return with value 642 "Yielded g2 spam",
816 """ 643 "Caught LunchError in g2",
817 644 "Yielded g2 yet more spam",
818 expected = """\ 645 "Yielded g1 eggs",
819 g starting 646 "Finishing g1",
820 f resuming g 647 ])
821 g returning None 648
822 f caught StopIteration() 649 def test_next_and_return_with_value(self):
823 g starting 650 """
824 f resuming g 651 Test next and return with value
825 g returning 42 652 """
826 f caught StopIteration(42,) 653 trace = []
827 """.format(__file__)
828
829 def case(self):
830 def f(r): 654 def f(r):
831 gi = g(r) 655 gi = g(r)
832 next(gi) 656 next(gi)
833 try: 657 try:
834 print("f resuming g") 658 trace.append("f resuming g")
835 next(gi) 659 next(gi)
836 print("f SHOULD NOT BE HERE") 660 trace.append("f SHOULD NOT BE HERE")
837 except StopIteration as e: 661 except StopIteration as e:
838 print("f caught", repr(e)) 662 trace.append("f caught %s" % (repr(e),))
839
840 def g(r): 663 def g(r):
841 print("g starting") 664 trace.append("g starting")
842 yield 665 yield
843 print("g returning", r) 666 trace.append("g returning %s" % (r,))
844 return r 667 return r
845
846 f(None) 668 f(None)
847 f(42) 669 f(42)
848 670 self.assertEqual(trace,[
849 671 "g starting",
850 class Test22(PEP380Test): 672 "f resuming g",
851 """ 673 "g returning None",
852 Test send and return with value 674 "f caught StopIteration()",
853 """ 675 "g starting",
854 676 "f resuming g",
855 expected = """\ 677 "g returning 42",
856 g starting 678 "f caught StopIteration(42,)",
857 f sending spam to g 679 ])
858 g received spam 680
859 g returning None 681 def test_send_and_return_with_value(self):
860 f caught StopIteration() 682 """
861 g starting 683 Test send and return with value
862 f sending spam to g 684 """
863 g received spam 685 trace = []
864 g returning 42
865 f caught StopIteration(42,)
866 """.format(__file__)
867
868 def case(self):
869 def f(r): 686 def f(r):
870 gi = g(r) 687 gi = g(r)
871 next(gi) 688 next(gi)
872 try: 689 try:
873 print("f sending spam to g") 690 trace.append("f sending spam to g")
874 gi.send("spam") 691 gi.send("spam")
875 print("f SHOULD NOT BE HERE") 692 trace.append("f SHOULD NOT BE HERE")
876 except StopIteration as e: 693 except StopIteration as e:
877 print("f caught", repr(e)) 694 trace.append("f caught %r" % (e,))
878
879 def g(r): 695 def g(r):
880 print("g starting") 696 trace.append("g starting")
881 x = yield 697 x = yield
882 print("g received", x) 698 trace.append("g received %s" % (x,))
883 print("g returning", r) 699 trace.append("g returning %s" % (r,))
884 return r 700 return r
885
886 f(None) 701 f(None)
887 f(42) 702 f(42)
888 703 self.assertEqual(trace,[
889 704 "g starting",
890 class Test23(PEP380Test): 705 "f sending spam to g",
891 """ 706 "g received spam",
892 Test parsing yield from as function argument 707 "g returning None",
893 """ 708 "f caught StopIteration()",
894 709 "g starting",
895 expected = """\ 710 "f sending spam to g",
896 909 0 LOAD_GLOBAL 0 (f) 711 "g received spam",
897 3 LOAD_GLOBAL 1 (x) 712 "g returning 42",
898 6 YIELD_FROM 713 "f caught StopIteration(42,)",
899 7 CALL_FUNCTION 1 714 ])
900 10 POP_TOP 715
901 11 LOAD_CONST 0 (None) 716 def test_catching_exception_from_subgen_and_returning(self):
902 14 RETURN_VALUE 717 """
903 """.format(__file__) 718 Test catching an exception thrown into a
904 719 subgenerator and returning a value
905 def case(self): 720 """
906 from dis import dis 721 trace = []
907
908 def g():
909 f(yield from x)
910
911 dis(g)
912
913
914 class Test24(PEP380Test):
Benjamin Peterson 2011/07/09 18:41:14 This ought to be in test_parser.
Nick Coghlan 2011/09/20 13:21:02 Done.
915 """
916 Test parser module
917 """
918
919 expected = """\
920 (257, (268, (269, (270, (276, (280, (336, (1, 'yield'), (337, (1, 'from'), (302, (306, (307, (308, (309, (312, (313, (314, (315, (316, (317, (318, (319, (320, ( 2, '1')))))))))))))))))))), (4, ''))), (4, ''), (0, ''))
921 True
922 (257, (268, (269, (270, (271, (272, (302, (306, (307, (308, (309, (312, (313, (3 14, (315, (316, (317, (318, (319, (320, (1, 'f')), (322, (7, '('), (330, (331, ( 338, (1, 'yield'), (1, 'from'), (302, (306, (307, (308, (309, (312, (313, (314, (315, (316, (317, (318, (319, (320, (2, '1')))))))))))))))))), (8, ')')))))))))) )))))))), (4, ''))), (4, ''), (0, ''))
923 True
924 """.format(__file__)
925
926 def case(self):
927 import parser
928
929 def test(src):
930 st1 = parser.suite(src)
931 tup1 = st1.totuple()
932 print(tup1)
933 st2 = parser.sequence2st(tup1)
934 tup2 = st2.totuple()
935 print(tup1 == tup2)
936
937 test("yield from 1")
938 test("f(yield from 1)")
939
940
941 class Test25(PEP380Test):
942 """
943 Test catching an exception thrown into a
944 subgenerator and returning a value
945 """
946
947 expected = """\
948 1
949 inner caught ValueError
950 inner returned 2 to outer
951 2
952 """.format(__file__)
953
954 def case(self):
955 def inner(): 722 def inner():
956 try: 723 try:
957 yield 1 724 yield 1
958 except ValueError: 725 except ValueError:
959 print("inner caught ValueError") #pass 726 trace.append("inner caught ValueError")
960 return 2 727 return 2
961 728
962 def outer(): 729 def outer():
963 v = yield from inner() 730 v = yield from inner()
964 print("inner returned %r to outer" % v) 731 trace.append("inner returned %r to outer" % v)
965 yield v 732 yield v
966
967 g = outer() 733 g = outer()
968 print(next(g)) # prints 1 734 trace.append(next(g))
969 print(g.throw(ValueError)) # prints 2 735 trace.append(g.throw(ValueError))
970 736 self.assertEqual(trace,[
971 737 1,
972 class Test26(PEP380Test): 738 "inner caught ValueError",
973 """ 739 "inner returned 2 to outer",
974 Test throwing GeneratorExit into a subgenerator that 740 2,
975 catches it and returns normally. 741 ])
976 """ 742
977 743 def test_throwing_GeneratorExit_into_subgen_that_returns(self):
978 expected = """\ 744 """
979 Enter g 745 Test throwing GeneratorExit into a subgenerator that
980 Enter f 746 catches it and returns normally.
981 Traceback (most recent call last): 747 """
982 File "{0}", line 1005, in case 748 trace = []
983 gi.throw(GeneratorExit)
984 File "{0}", line 1000, in g
985 yield from f()
986 GeneratorExit
987 """.format(__file__)
988
989 def case(self):
990 def f(): 749 def f():
991 try: 750 try:
992 print("Enter f") 751 trace.append("Enter f")
993 yield 752 yield
994 print("Exit f") 753 trace.append("Exit f")
995 except GeneratorExit: 754 except GeneratorExit:
996 return 755 return
997
998 def g(): 756 def g():
999 print("Enter g") 757 trace.append("Enter g")
1000 yield from f() 758 yield from f()
1001 print("Exit g") 759 trace.append("Exit g")
1002 760 try:
1003 gi = g() 761 gi = g()
1004 next(gi) 762 next(gi)
1005 gi.throw(GeneratorExit) 763 gi.throw(GeneratorExit)
1006 764 except GeneratorExit:
1007 765 pass
1008 class Test27(PEP380Test): 766 else:
1009 """ 767 self.fail("subgenerator failed to raise GeneratorExit")
1010 Test throwing GeneratorExit into a subgenerator that 768 self.assertEqual(trace,[
1011 catches it and yields. 769 "Enter g",
1012 """ 770 "Enter f",
1013 771 ])
1014 expected = """\ 772
1015 Enter g 773 def test_throwing_GeneratorExit_into_subgenerator_that_yields(self):
1016 Enter f 774 """
1017 Traceback (most recent call last): 775 Test throwing GeneratorExit into a subgenerator that
1018 File "{0}", line 1041, in case 776 catches it and yields.
1019 gi.throw(GeneratorExit) 777 """
1020 File "{0}", line 1036, in g 778 trace = []
1021 yield from f()
1022 RuntimeError: generator ignored GeneratorExit
1023 """.format(__file__)
1024
1025 def case(self):
1026 def f(): 779 def f():
1027 try: 780 try:
1028 print("Enter f") 781 trace.append("Enter f")
1029 yield 782 yield
1030 print("Exit f") 783 trace.append("Exit f")
1031 except GeneratorExit: 784 except GeneratorExit:
1032 yield 785 yield
1033
1034 def g(): 786 def g():
1035 print("Enter g") 787 trace.append("Enter g")
1036 yield from f() 788 yield from f()
1037 print("Exit g") 789 trace.append("Exit g")
1038 790 try:
1039 gi = g() 791 gi = g()
1040 next(gi) 792 next(gi)
1041 gi.throw(GeneratorExit) 793 gi.throw(GeneratorExit)
1042 794 except RuntimeError as e:
1043 795 self.assertEqual(e.args[0], "generator ignored GeneratorExit")
1044 class Test28(PEP380Test): 796 else:
1045 """ 797 self.fail("subgenerator failed to raise GeneratorExit")
1046 Test throwing GeneratorExit into a subgenerator that 798 self.assertEqual(trace,[
1047 catches it and raises a different exception. 799 "Enter g",
1048 """ 800 "Enter f",
1049 801 ])
1050 expected = """\ 802
1051 Enter g 803 def test_throwing_GeneratorExit_into_subgen_that_raises(self):
1052 Enter f 804 """
1053 Traceback (most recent call last): 805 Test throwing GeneratorExit into a subgenerator that
1054 File "{0}", line 1074, in f 806 catches it and raises a different exception.
1055 yield 807 """
1056 GeneratorExit 808 trace = []
1057
1058 During handling of the above exception, another exception occurred:
1059
1060 Traceback (most recent call last):
1061 File "{0}", line 1086, in case
1062 gi.throw(GeneratorExit)
1063 File "{0}", line 1081, in g
1064 yield from f()
1065 File "{0}", line 1077, in f
1066 raise ValueError("Vorpal bunny encountered")
1067 ValueError: Vorpal bunny encountered
1068 """.format(__file__)
1069
1070 def case(self):
1071 def f(): 809 def f():
1072 try: 810 try:
1073 print("Enter f") 811 trace.append("Enter f")
1074 yield 812 yield
1075 print("Exit f") 813 trace.append("Exit f")
1076 except GeneratorExit: 814 except GeneratorExit:
1077 raise ValueError("Vorpal bunny encountered") 815 raise ValueError("Vorpal bunny encountered")
1078
1079 def g(): 816 def g():
1080 print("Enter g") 817 trace.append("Enter g")
1081 yield from f() 818 yield from f()
1082 print("Exit g") 819 trace.append("Exit g")
1083 820 try:
1084 gi = g() 821 gi = g()
1085 next(gi) 822 next(gi)
1086 gi.throw(GeneratorExit) 823 gi.throw(GeneratorExit)
824 except ValueError as e:
825 self.assertEqual(e.args[0], "Vorpal bunny encountered")
826 self.assertIsInstance(e.__context__, GeneratorExit)
827 else:
828 self.fail("subgenerator failed to raise ValueError")
829 self.assertEqual(trace,[
830 "Enter g",
831 "Enter f",
832 ])
1087 833
1088 834
1089 def test_main(): 835 def test_main():
1090 from test import support 836 from test import support
1091 test_classes = [Test1, Test2, Test3, Test4, Test5, Test6, Test7, Test8, Test 9, Test10, Test11, Test12, Test13, Test14, Test15, Test16, Test17, Test18, Test1 9, Test20, Test21, Test22, Test23, Test24, Test25, Test26, Test27, Test28] 837 test_classes = [TestPEP380Operation]
1092 support.run_unittest(*test_classes) 838 support.run_unittest(*test_classes)
1093 839
1094 840
1095 if __name__ == '__main__': 841 if __name__ == '__main__':
1096 test_main() 842 test_main()
LEFTRIGHT

RSS Feeds Recent Issues | This issue
This is Rietveld 894c83f36cb7+