blob: 0814451d3175710112b484badc80fe020c9dac36 [file] [log] [blame]
Yury Selivanoveb636452016-09-08 22:01:51 -07001import inspect
Yury Selivanoveb636452016-09-08 22:01:51 -07002import types
3import unittest
4
Hai Shi46605972020-08-04 00:49:18 +08005from test.support.import_helper import import_module
Miss Islington (bot)2ad114d2021-09-04 13:37:56 -07006from test.support import gc_collect
Martin Panter94332cb2016-10-20 05:10:44 +00007asyncio = import_module("asyncio")
8
Yury Selivanoveb636452016-09-08 22:01:51 -07009
10class AwaitException(Exception):
11 pass
12
13
14@types.coroutine
15def awaitable(*, throw=False):
16 if throw:
17 yield ('throw',)
18 else:
19 yield ('result',)
20
21
22def run_until_complete(coro):
23 exc = False
24 while True:
25 try:
26 if exc:
27 exc = False
28 fut = coro.throw(AwaitException)
29 else:
30 fut = coro.send(None)
31 except StopIteration as ex:
32 return ex.args[0]
33
34 if fut == ('throw',):
35 exc = True
36
37
38def to_list(gen):
39 async def iterate():
40 res = []
41 async for i in gen:
42 res.append(i)
43 return res
44
45 return run_until_complete(iterate())
46
47
48class AsyncGenSyntaxTest(unittest.TestCase):
49
50 def test_async_gen_syntax_01(self):
51 code = '''async def foo():
52 await abc
53 yield from 123
54 '''
55
56 with self.assertRaisesRegex(SyntaxError, 'yield from.*inside async'):
57 exec(code, {}, {})
58
59 def test_async_gen_syntax_02(self):
60 code = '''async def foo():
61 yield from 123
62 '''
63
64 with self.assertRaisesRegex(SyntaxError, 'yield from.*inside async'):
65 exec(code, {}, {})
66
67 def test_async_gen_syntax_03(self):
68 code = '''async def foo():
69 await abc
70 yield
71 return 123
72 '''
73
74 with self.assertRaisesRegex(SyntaxError, 'return.*value.*async gen'):
75 exec(code, {}, {})
76
77 def test_async_gen_syntax_04(self):
78 code = '''async def foo():
79 yield
80 return 123
81 '''
82
83 with self.assertRaisesRegex(SyntaxError, 'return.*value.*async gen'):
84 exec(code, {}, {})
85
86 def test_async_gen_syntax_05(self):
87 code = '''async def foo():
88 if 0:
89 yield
90 return 12
91 '''
92
93 with self.assertRaisesRegex(SyntaxError, 'return.*value.*async gen'):
94 exec(code, {}, {})
95
96
97class AsyncGenTest(unittest.TestCase):
98
99 def compare_generators(self, sync_gen, async_gen):
100 def sync_iterate(g):
101 res = []
102 while True:
103 try:
104 res.append(g.__next__())
105 except StopIteration:
106 res.append('STOP')
107 break
108 except Exception as ex:
109 res.append(str(type(ex)))
110 return res
111
112 def async_iterate(g):
113 res = []
114 while True:
Yury Selivanov52698c72018-06-07 20:31:26 -0400115 an = g.__anext__()
116 try:
117 while True:
118 try:
119 an.__next__()
120 except StopIteration as ex:
121 if ex.args:
122 res.append(ex.args[0])
123 break
124 else:
125 res.append('EMPTY StopIteration')
126 break
127 except StopAsyncIteration:
128 raise
129 except Exception as ex:
130 res.append(str(type(ex)))
131 break
132 except StopAsyncIteration:
133 res.append('STOP')
134 break
135 return res
136
Yury Selivanoveb636452016-09-08 22:01:51 -0700137 sync_gen_result = sync_iterate(sync_gen)
138 async_gen_result = async_iterate(async_gen)
139 self.assertEqual(sync_gen_result, async_gen_result)
140 return async_gen_result
141
142 def test_async_gen_iteration_01(self):
143 async def gen():
144 await awaitable()
145 a = yield 123
146 self.assertIs(a, None)
147 await awaitable()
148 yield 456
149 await awaitable()
150 yield 789
151
152 self.assertEqual(to_list(gen()), [123, 456, 789])
153
154 def test_async_gen_iteration_02(self):
155 async def gen():
156 await awaitable()
157 yield 123
158 await awaitable()
159
160 g = gen()
161 ai = g.__aiter__()
Yury Selivanovfc4a0442019-09-29 22:59:11 -0700162
163 an = ai.__anext__()
164 self.assertEqual(an.__next__(), ('result',))
Yury Selivanoveb636452016-09-08 22:01:51 -0700165
166 try:
Yury Selivanovfc4a0442019-09-29 22:59:11 -0700167 an.__next__()
Yury Selivanoveb636452016-09-08 22:01:51 -0700168 except StopIteration as ex:
169 self.assertEqual(ex.args[0], 123)
170 else:
171 self.fail('StopIteration was not raised')
172
Yury Selivanovfc4a0442019-09-29 22:59:11 -0700173 an = ai.__anext__()
174 self.assertEqual(an.__next__(), ('result',))
Yury Selivanoveb636452016-09-08 22:01:51 -0700175
176 try:
Yury Selivanovfc4a0442019-09-29 22:59:11 -0700177 an.__next__()
Yury Selivanoveb636452016-09-08 22:01:51 -0700178 except StopAsyncIteration as ex:
179 self.assertFalse(ex.args)
180 else:
181 self.fail('StopAsyncIteration was not raised')
182
183 def test_async_gen_exception_03(self):
184 async def gen():
185 await awaitable()
186 yield 123
187 await awaitable(throw=True)
188 yield 456
189
190 with self.assertRaises(AwaitException):
191 to_list(gen())
192
193 def test_async_gen_exception_04(self):
194 async def gen():
195 await awaitable()
196 yield 123
197 1 / 0
198
199 g = gen()
200 ai = g.__aiter__()
Yury Selivanovfc4a0442019-09-29 22:59:11 -0700201 an = ai.__anext__()
202 self.assertEqual(an.__next__(), ('result',))
Yury Selivanoveb636452016-09-08 22:01:51 -0700203
204 try:
Yury Selivanovfc4a0442019-09-29 22:59:11 -0700205 an.__next__()
Yury Selivanoveb636452016-09-08 22:01:51 -0700206 except StopIteration as ex:
207 self.assertEqual(ex.args[0], 123)
208 else:
209 self.fail('StopIteration was not raised')
210
211 with self.assertRaises(ZeroDivisionError):
212 ai.__anext__().__next__()
213
214 def test_async_gen_exception_05(self):
215 async def gen():
216 yield 123
217 raise StopAsyncIteration
218
219 with self.assertRaisesRegex(RuntimeError,
220 'async generator.*StopAsyncIteration'):
221 to_list(gen())
222
223 def test_async_gen_exception_06(self):
224 async def gen():
225 yield 123
226 raise StopIteration
227
228 with self.assertRaisesRegex(RuntimeError,
229 'async generator.*StopIteration'):
230 to_list(gen())
231
232 def test_async_gen_exception_07(self):
233 def sync_gen():
234 try:
235 yield 1
236 1 / 0
237 finally:
238 yield 2
239 yield 3
240
241 yield 100
242
243 async def async_gen():
244 try:
245 yield 1
246 1 / 0
247 finally:
248 yield 2
249 yield 3
250
251 yield 100
252
253 self.compare_generators(sync_gen(), async_gen())
254
255 def test_async_gen_exception_08(self):
256 def sync_gen():
257 try:
258 yield 1
259 finally:
260 yield 2
261 1 / 0
262 yield 3
263
264 yield 100
265
266 async def async_gen():
267 try:
268 yield 1
269 await awaitable()
270 finally:
271 await awaitable()
272 yield 2
273 1 / 0
274 yield 3
275
276 yield 100
277
278 self.compare_generators(sync_gen(), async_gen())
279
280 def test_async_gen_exception_09(self):
281 def sync_gen():
282 try:
283 yield 1
284 1 / 0
285 finally:
286 yield 2
287 yield 3
288
289 yield 100
290
291 async def async_gen():
292 try:
293 await awaitable()
294 yield 1
295 1 / 0
296 finally:
297 yield 2
298 await awaitable()
299 yield 3
300
301 yield 100
302
303 self.compare_generators(sync_gen(), async_gen())
304
305 def test_async_gen_exception_10(self):
306 async def gen():
307 yield 123
308 with self.assertRaisesRegex(TypeError,
309 "non-None value .* async generator"):
310 gen().__anext__().send(100)
311
Yury Selivanov52698c72018-06-07 20:31:26 -0400312 def test_async_gen_exception_11(self):
313 def sync_gen():
314 yield 10
315 yield 20
316
317 def sync_gen_wrapper():
318 yield 1
319 sg = sync_gen()
320 sg.send(None)
321 try:
322 sg.throw(GeneratorExit())
323 except GeneratorExit:
324 yield 2
325 yield 3
326
327 async def async_gen():
328 yield 10
329 yield 20
330
331 async def async_gen_wrapper():
332 yield 1
333 asg = async_gen()
334 await asg.asend(None)
335 try:
336 await asg.athrow(GeneratorExit())
337 except GeneratorExit:
338 yield 2
339 yield 3
340
341 self.compare_generators(sync_gen_wrapper(), async_gen_wrapper())
342
Yury Selivanoveb636452016-09-08 22:01:51 -0700343 def test_async_gen_api_01(self):
344 async def gen():
345 yield 123
346
347 g = gen()
348
349 self.assertEqual(g.__name__, 'gen')
350 g.__name__ = '123'
351 self.assertEqual(g.__name__, '123')
352
353 self.assertIn('.gen', g.__qualname__)
354 g.__qualname__ = '123'
355 self.assertEqual(g.__qualname__, '123')
356
357 self.assertIsNone(g.ag_await)
358 self.assertIsInstance(g.ag_frame, types.FrameType)
359 self.assertFalse(g.ag_running)
360 self.assertIsInstance(g.ag_code, types.CodeType)
361
362 self.assertTrue(inspect.isawaitable(g.aclose()))
363
364
365class AsyncGenAsyncioTest(unittest.TestCase):
366
367 def setUp(self):
368 self.loop = asyncio.new_event_loop()
369 asyncio.set_event_loop(None)
370
371 def tearDown(self):
372 self.loop.close()
373 self.loop = None
Brett Cannon8425de42018-06-01 20:34:09 -0700374 asyncio.set_event_loop_policy(None)
Yury Selivanoveb636452016-09-08 22:01:51 -0700375
Dennis Sweeneydfb45322021-04-11 00:51:35 -0400376 def check_async_iterator_anext(self, ait_class):
377 g = ait_class()
Joshua Bronsonf0a6fde2021-03-23 18:47:21 -0400378 async def consume():
379 results = []
380 results.append(await anext(g))
381 results.append(await anext(g))
382 results.append(await anext(g, 'buckle my shoe'))
383 return results
384 res = self.loop.run_until_complete(consume())
385 self.assertEqual(res, [1, 2, 'buckle my shoe'])
386 with self.assertRaises(StopAsyncIteration):
387 self.loop.run_until_complete(consume())
388
Dennis Sweeneydfb45322021-04-11 00:51:35 -0400389 async def test_2():
390 g1 = ait_class()
391 self.assertEqual(await anext(g1), 1)
392 self.assertEqual(await anext(g1), 2)
393 with self.assertRaises(StopAsyncIteration):
394 await anext(g1)
395 with self.assertRaises(StopAsyncIteration):
396 await anext(g1)
397
398 g2 = ait_class()
399 self.assertEqual(await anext(g2, "default"), 1)
400 self.assertEqual(await anext(g2, "default"), 2)
401 self.assertEqual(await anext(g2, "default"), "default")
402 self.assertEqual(await anext(g2, "default"), "default")
403
404 return "completed"
405
406 result = self.loop.run_until_complete(test_2())
407 self.assertEqual(result, "completed")
408
409 def test_async_generator_anext(self):
410 async def agen():
411 yield 1
412 yield 2
413 self.check_async_iterator_anext(agen)
414
415 def test_python_async_iterator_anext(self):
416 class MyAsyncIter:
417 """Asynchronously yield 1, then 2."""
418 def __init__(self):
419 self.yielded = 0
420 def __aiter__(self):
421 return self
422 async def __anext__(self):
423 if self.yielded >= 2:
424 raise StopAsyncIteration()
425 else:
426 self.yielded += 1
427 return self.yielded
428 self.check_async_iterator_anext(MyAsyncIter)
429
430 def test_python_async_iterator_types_coroutine_anext(self):
431 import types
432 class MyAsyncIterWithTypesCoro:
433 """Asynchronously yield 1, then 2."""
434 def __init__(self):
435 self.yielded = 0
436 def __aiter__(self):
437 return self
438 @types.coroutine
439 def __anext__(self):
440 if False:
441 yield "this is a generator-based coroutine"
442 if self.yielded >= 2:
443 raise StopAsyncIteration()
444 else:
445 self.yielded += 1
446 return self.yielded
447 self.check_async_iterator_anext(MyAsyncIterWithTypesCoro)
448
Joshua Bronsonf0a6fde2021-03-23 18:47:21 -0400449 def test_async_gen_aiter(self):
450 async def gen():
451 yield 1
452 yield 2
453 g = gen()
454 async def consume():
455 return [i async for i in aiter(g)]
456 res = self.loop.run_until_complete(consume())
457 self.assertEqual(res, [1, 2])
458
459 def test_async_gen_aiter_class(self):
460 results = []
461 class Gen:
462 async def __aiter__(self):
463 yield 1
464 yield 2
465 g = Gen()
466 async def consume():
467 ait = aiter(g)
468 while True:
469 try:
470 results.append(await anext(ait))
471 except StopAsyncIteration:
472 break
473 self.loop.run_until_complete(consume())
474 self.assertEqual(results, [1, 2])
475
476 def test_aiter_idempotent(self):
477 async def gen():
478 yield 1
479 applied_once = aiter(gen())
480 applied_twice = aiter(applied_once)
481 self.assertIs(applied_once, applied_twice)
482
483 def test_anext_bad_args(self):
484 async def gen():
485 yield 1
486 async def call_with_too_few_args():
487 await anext()
488 async def call_with_too_many_args():
489 await anext(gen(), 1, 3)
490 async def call_with_wrong_type_args():
491 await anext(1, gen())
Dennis Sweeneydfb45322021-04-11 00:51:35 -0400492 async def call_with_kwarg():
493 await anext(aiterator=gen())
Joshua Bronsonf0a6fde2021-03-23 18:47:21 -0400494 with self.assertRaises(TypeError):
495 self.loop.run_until_complete(call_with_too_few_args())
496 with self.assertRaises(TypeError):
497 self.loop.run_until_complete(call_with_too_many_args())
498 with self.assertRaises(TypeError):
499 self.loop.run_until_complete(call_with_wrong_type_args())
Dennis Sweeneydfb45322021-04-11 00:51:35 -0400500 with self.assertRaises(TypeError):
501 self.loop.run_until_complete(call_with_kwarg())
502
503 def test_anext_bad_await(self):
504 async def bad_awaitable():
505 class BadAwaitable:
506 def __await__(self):
507 return 42
508 class MyAsyncIter:
509 def __aiter__(self):
510 return self
511 def __anext__(self):
512 return BadAwaitable()
513 regex = r"__await__.*iterator"
514 awaitable = anext(MyAsyncIter(), "default")
515 with self.assertRaisesRegex(TypeError, regex):
516 await awaitable
517 awaitable = anext(MyAsyncIter())
518 with self.assertRaisesRegex(TypeError, regex):
519 await awaitable
520 return "completed"
521 result = self.loop.run_until_complete(bad_awaitable())
522 self.assertEqual(result, "completed")
523
524 async def check_anext_returning_iterator(self, aiter_class):
525 awaitable = anext(aiter_class(), "default")
526 with self.assertRaises(TypeError):
527 await awaitable
528 awaitable = anext(aiter_class())
529 with self.assertRaises(TypeError):
530 await awaitable
531 return "completed"
532
533 def test_anext_return_iterator(self):
534 class WithIterAnext:
535 def __aiter__(self):
536 return self
537 def __anext__(self):
538 return iter("abc")
539 result = self.loop.run_until_complete(self.check_anext_returning_iterator(WithIterAnext))
540 self.assertEqual(result, "completed")
541
542 def test_anext_return_generator(self):
543 class WithGenAnext:
544 def __aiter__(self):
545 return self
546 def __anext__(self):
547 yield
548 result = self.loop.run_until_complete(self.check_anext_returning_iterator(WithGenAnext))
549 self.assertEqual(result, "completed")
550
551 def test_anext_await_raises(self):
552 class RaisingAwaitable:
553 def __await__(self):
554 raise ZeroDivisionError()
555 yield
556 class WithRaisingAwaitableAnext:
557 def __aiter__(self):
558 return self
559 def __anext__(self):
560 return RaisingAwaitable()
561 async def do_test():
562 awaitable = anext(WithRaisingAwaitableAnext())
563 with self.assertRaises(ZeroDivisionError):
564 await awaitable
565 awaitable = anext(WithRaisingAwaitableAnext(), "default")
566 with self.assertRaises(ZeroDivisionError):
567 await awaitable
568 return "completed"
569 result = self.loop.run_until_complete(do_test())
570 self.assertEqual(result, "completed")
Joshua Bronsonf0a6fde2021-03-23 18:47:21 -0400571
572 def test_aiter_bad_args(self):
573 async def gen():
574 yield 1
575 async def call_with_too_few_args():
576 await aiter()
577 async def call_with_too_many_args():
578 await aiter(gen(), 1)
579 async def call_with_wrong_type_arg():
580 await aiter(1)
581 with self.assertRaises(TypeError):
582 self.loop.run_until_complete(call_with_too_few_args())
583 with self.assertRaises(TypeError):
584 self.loop.run_until_complete(call_with_too_many_args())
585 with self.assertRaises(TypeError):
586 self.loop.run_until_complete(call_with_wrong_type_arg())
587
Yury Selivanoveb636452016-09-08 22:01:51 -0700588 async def to_list(self, gen):
589 res = []
590 async for i in gen:
591 res.append(i)
592 return res
593
594 def test_async_gen_asyncio_01(self):
595 async def gen():
596 yield 1
Yury Selivanov9012a0f2018-10-02 13:53:06 -0400597 await asyncio.sleep(0.01)
Yury Selivanoveb636452016-09-08 22:01:51 -0700598 yield 2
Yury Selivanov9012a0f2018-10-02 13:53:06 -0400599 await asyncio.sleep(0.01)
Yury Selivanoveb636452016-09-08 22:01:51 -0700600 return
601 yield 3
602
603 res = self.loop.run_until_complete(self.to_list(gen()))
604 self.assertEqual(res, [1, 2])
605
606 def test_async_gen_asyncio_02(self):
607 async def gen():
608 yield 1
Yury Selivanov9012a0f2018-10-02 13:53:06 -0400609 await asyncio.sleep(0.01)
Yury Selivanoveb636452016-09-08 22:01:51 -0700610 yield 2
611 1 / 0
612 yield 3
613
614 with self.assertRaises(ZeroDivisionError):
615 self.loop.run_until_complete(self.to_list(gen()))
616
617 def test_async_gen_asyncio_03(self):
618 loop = self.loop
619
620 class Gen:
621 async def __aiter__(self):
622 yield 1
Yury Selivanov9012a0f2018-10-02 13:53:06 -0400623 await asyncio.sleep(0.01)
Yury Selivanoveb636452016-09-08 22:01:51 -0700624 yield 2
625
626 res = loop.run_until_complete(self.to_list(Gen()))
627 self.assertEqual(res, [1, 2])
628
629 def test_async_gen_asyncio_anext_04(self):
630 async def foo():
631 yield 1
Yury Selivanov9012a0f2018-10-02 13:53:06 -0400632 await asyncio.sleep(0.01)
Yury Selivanoveb636452016-09-08 22:01:51 -0700633 try:
634 yield 2
635 yield 3
636 except ZeroDivisionError:
637 yield 1000
Yury Selivanov9012a0f2018-10-02 13:53:06 -0400638 await asyncio.sleep(0.01)
Yury Selivanoveb636452016-09-08 22:01:51 -0700639 yield 4
640
641 async def run1():
642 it = foo().__aiter__()
643
644 self.assertEqual(await it.__anext__(), 1)
645 self.assertEqual(await it.__anext__(), 2)
646 self.assertEqual(await it.__anext__(), 3)
647 self.assertEqual(await it.__anext__(), 4)
648 with self.assertRaises(StopAsyncIteration):
649 await it.__anext__()
650 with self.assertRaises(StopAsyncIteration):
651 await it.__anext__()
652
653 async def run2():
654 it = foo().__aiter__()
655
656 self.assertEqual(await it.__anext__(), 1)
657 self.assertEqual(await it.__anext__(), 2)
658 try:
659 it.__anext__().throw(ZeroDivisionError)
660 except StopIteration as ex:
661 self.assertEqual(ex.args[0], 1000)
662 else:
663 self.fail('StopIteration was not raised')
664 self.assertEqual(await it.__anext__(), 4)
665 with self.assertRaises(StopAsyncIteration):
666 await it.__anext__()
667
668 self.loop.run_until_complete(run1())
669 self.loop.run_until_complete(run2())
670
671 def test_async_gen_asyncio_anext_05(self):
672 async def foo():
673 v = yield 1
674 v = yield v
675 yield v * 100
676
677 async def run():
678 it = foo().__aiter__()
679
680 try:
681 it.__anext__().send(None)
682 except StopIteration as ex:
683 self.assertEqual(ex.args[0], 1)
684 else:
685 self.fail('StopIteration was not raised')
686
687 try:
688 it.__anext__().send(10)
689 except StopIteration as ex:
690 self.assertEqual(ex.args[0], 10)
691 else:
692 self.fail('StopIteration was not raised')
693
694 try:
695 it.__anext__().send(12)
696 except StopIteration as ex:
697 self.assertEqual(ex.args[0], 1200)
698 else:
699 self.fail('StopIteration was not raised')
700
701 with self.assertRaises(StopAsyncIteration):
702 await it.__anext__()
703
704 self.loop.run_until_complete(run())
705
Yury Selivanov41782e42016-11-16 18:16:17 -0500706 def test_async_gen_asyncio_anext_06(self):
707 DONE = 0
708
709 # test synchronous generators
710 def foo():
711 try:
712 yield
713 except:
714 pass
715 g = foo()
716 g.send(None)
717 with self.assertRaises(StopIteration):
718 g.send(None)
719
720 # now with asynchronous generators
721
722 async def gen():
723 nonlocal DONE
724 try:
725 yield
726 except:
727 pass
728 DONE = 1
729
730 async def run():
731 nonlocal DONE
732 g = gen()
733 await g.asend(None)
734 with self.assertRaises(StopAsyncIteration):
735 await g.asend(None)
736 DONE += 10
737
738 self.loop.run_until_complete(run())
739 self.assertEqual(DONE, 11)
740
Serhiy Storchaka60e49aa2016-11-06 18:47:03 +0200741 def test_async_gen_asyncio_anext_tuple(self):
742 async def foo():
743 try:
744 yield (1,)
745 except ZeroDivisionError:
746 yield (2,)
747
748 async def run():
749 it = foo().__aiter__()
750
751 self.assertEqual(await it.__anext__(), (1,))
752 with self.assertRaises(StopIteration) as cm:
753 it.__anext__().throw(ZeroDivisionError)
754 self.assertEqual(cm.exception.args[0], (2,))
755 with self.assertRaises(StopAsyncIteration):
756 await it.__anext__()
757
758 self.loop.run_until_complete(run())
759
760 def test_async_gen_asyncio_anext_stopiteration(self):
761 async def foo():
762 try:
763 yield StopIteration(1)
764 except ZeroDivisionError:
765 yield StopIteration(3)
766
767 async def run():
768 it = foo().__aiter__()
769
770 v = await it.__anext__()
771 self.assertIsInstance(v, StopIteration)
772 self.assertEqual(v.value, 1)
773 with self.assertRaises(StopIteration) as cm:
774 it.__anext__().throw(ZeroDivisionError)
775 v = cm.exception.args[0]
776 self.assertIsInstance(v, StopIteration)
777 self.assertEqual(v.value, 3)
778 with self.assertRaises(StopAsyncIteration):
779 await it.__anext__()
780
781 self.loop.run_until_complete(run())
782
Yury Selivanoveb636452016-09-08 22:01:51 -0700783 def test_async_gen_asyncio_aclose_06(self):
784 async def foo():
785 try:
786 yield 1
787 1 / 0
788 finally:
Yury Selivanov9012a0f2018-10-02 13:53:06 -0400789 await asyncio.sleep(0.01)
Yury Selivanoveb636452016-09-08 22:01:51 -0700790 yield 12
791
792 async def run():
793 gen = foo()
794 it = gen.__aiter__()
795 await it.__anext__()
796 await gen.aclose()
797
798 with self.assertRaisesRegex(
799 RuntimeError,
800 "async generator ignored GeneratorExit"):
801 self.loop.run_until_complete(run())
802
803 def test_async_gen_asyncio_aclose_07(self):
804 DONE = 0
805
806 async def foo():
807 nonlocal DONE
808 try:
809 yield 1
810 1 / 0
811 finally:
Yury Selivanov9012a0f2018-10-02 13:53:06 -0400812 await asyncio.sleep(0.01)
813 await asyncio.sleep(0.01)
Yury Selivanoveb636452016-09-08 22:01:51 -0700814 DONE += 1
815 DONE += 1000
816
817 async def run():
818 gen = foo()
819 it = gen.__aiter__()
820 await it.__anext__()
821 await gen.aclose()
822
823 self.loop.run_until_complete(run())
824 self.assertEqual(DONE, 1)
825
826 def test_async_gen_asyncio_aclose_08(self):
827 DONE = 0
828
829 fut = asyncio.Future(loop=self.loop)
830
831 async def foo():
832 nonlocal DONE
833 try:
834 yield 1
835 await fut
836 DONE += 1000
837 yield 2
838 finally:
Yury Selivanov9012a0f2018-10-02 13:53:06 -0400839 await asyncio.sleep(0.01)
840 await asyncio.sleep(0.01)
Yury Selivanoveb636452016-09-08 22:01:51 -0700841 DONE += 1
842 DONE += 1000
843
844 async def run():
845 gen = foo()
846 it = gen.__aiter__()
847 self.assertEqual(await it.__anext__(), 1)
Yury Selivanoveb636452016-09-08 22:01:51 -0700848 await gen.aclose()
Yury Selivanoveb636452016-09-08 22:01:51 -0700849
Yury Selivanovfc4a0442019-09-29 22:59:11 -0700850 self.loop.run_until_complete(run())
Yury Selivanoveb636452016-09-08 22:01:51 -0700851 self.assertEqual(DONE, 1)
852
853 # Silence ResourceWarnings
854 fut.cancel()
Yury Selivanov9012a0f2018-10-02 13:53:06 -0400855 self.loop.run_until_complete(asyncio.sleep(0.01))
Yury Selivanoveb636452016-09-08 22:01:51 -0700856
857 def test_async_gen_asyncio_gc_aclose_09(self):
858 DONE = 0
859
860 async def gen():
861 nonlocal DONE
862 try:
863 while True:
864 yield 1
865 finally:
Yury Selivanov9012a0f2018-10-02 13:53:06 -0400866 await asyncio.sleep(0.01)
867 await asyncio.sleep(0.01)
Yury Selivanoveb636452016-09-08 22:01:51 -0700868 DONE = 1
869
870 async def run():
871 g = gen()
872 await g.__anext__()
873 await g.__anext__()
874 del g
875
Yury Selivanov9012a0f2018-10-02 13:53:06 -0400876 await asyncio.sleep(0.1)
Yury Selivanoveb636452016-09-08 22:01:51 -0700877
878 self.loop.run_until_complete(run())
879 self.assertEqual(DONE, 1)
880
Yury Selivanov41782e42016-11-16 18:16:17 -0500881 def test_async_gen_asyncio_aclose_10(self):
882 DONE = 0
883
884 # test synchronous generators
885 def foo():
886 try:
887 yield
888 except:
889 pass
890 g = foo()
891 g.send(None)
892 g.close()
893
894 # now with asynchronous generators
895
896 async def gen():
897 nonlocal DONE
898 try:
899 yield
900 except:
901 pass
902 DONE = 1
903
904 async def run():
905 nonlocal DONE
906 g = gen()
907 await g.asend(None)
908 await g.aclose()
909 DONE += 10
910
911 self.loop.run_until_complete(run())
912 self.assertEqual(DONE, 11)
913
914 def test_async_gen_asyncio_aclose_11(self):
915 DONE = 0
916
917 # test synchronous generators
918 def foo():
919 try:
920 yield
921 except:
922 pass
923 yield
924 g = foo()
925 g.send(None)
926 with self.assertRaisesRegex(RuntimeError, 'ignored GeneratorExit'):
927 g.close()
928
929 # now with asynchronous generators
930
931 async def gen():
932 nonlocal DONE
933 try:
934 yield
935 except:
936 pass
937 yield
938 DONE += 1
939
940 async def run():
941 nonlocal DONE
942 g = gen()
943 await g.asend(None)
944 with self.assertRaisesRegex(RuntimeError, 'ignored GeneratorExit'):
945 await g.aclose()
946 DONE += 10
947
948 self.loop.run_until_complete(run())
949 self.assertEqual(DONE, 10)
950
Vincent Michel8e0de2a2019-11-19 05:53:52 -0800951 def test_async_gen_asyncio_aclose_12(self):
952 DONE = 0
953
954 async def target():
955 await asyncio.sleep(0.01)
956 1 / 0
957
958 async def foo():
959 nonlocal DONE
960 task = asyncio.create_task(target())
961 try:
962 yield 1
963 finally:
964 try:
965 await task
966 except ZeroDivisionError:
967 DONE = 1
968
969 async def run():
970 gen = foo()
971 it = gen.__aiter__()
972 await it.__anext__()
973 await gen.aclose()
974
975 self.loop.run_until_complete(run())
976 self.assertEqual(DONE, 1)
977
Yury Selivanoveb636452016-09-08 22:01:51 -0700978 def test_async_gen_asyncio_asend_01(self):
979 DONE = 0
980
981 # Sanity check:
982 def sgen():
983 v = yield 1
984 yield v * 2
985 sg = sgen()
986 v = sg.send(None)
987 self.assertEqual(v, 1)
988 v = sg.send(100)
989 self.assertEqual(v, 200)
990
991 async def gen():
992 nonlocal DONE
993 try:
Yury Selivanov9012a0f2018-10-02 13:53:06 -0400994 await asyncio.sleep(0.01)
Yury Selivanoveb636452016-09-08 22:01:51 -0700995 v = yield 1
Yury Selivanov9012a0f2018-10-02 13:53:06 -0400996 await asyncio.sleep(0.01)
Yury Selivanoveb636452016-09-08 22:01:51 -0700997 yield v * 2
Yury Selivanov9012a0f2018-10-02 13:53:06 -0400998 await asyncio.sleep(0.01)
Yury Selivanoveb636452016-09-08 22:01:51 -0700999 return
1000 finally:
Yury Selivanov9012a0f2018-10-02 13:53:06 -04001001 await asyncio.sleep(0.01)
1002 await asyncio.sleep(0.01)
Yury Selivanoveb636452016-09-08 22:01:51 -07001003 DONE = 1
1004
1005 async def run():
1006 g = gen()
1007
1008 v = await g.asend(None)
1009 self.assertEqual(v, 1)
1010
1011 v = await g.asend(100)
1012 self.assertEqual(v, 200)
1013
1014 with self.assertRaises(StopAsyncIteration):
1015 await g.asend(None)
1016
1017 self.loop.run_until_complete(run())
1018 self.assertEqual(DONE, 1)
1019
1020 def test_async_gen_asyncio_asend_02(self):
1021 DONE = 0
1022
1023 async def sleep_n_crash(delay):
Yury Selivanov9012a0f2018-10-02 13:53:06 -04001024 await asyncio.sleep(delay)
Yury Selivanoveb636452016-09-08 22:01:51 -07001025 1 / 0
1026
1027 async def gen():
1028 nonlocal DONE
1029 try:
Yury Selivanov9012a0f2018-10-02 13:53:06 -04001030 await asyncio.sleep(0.01)
Yury Selivanoveb636452016-09-08 22:01:51 -07001031 v = yield 1
1032 await sleep_n_crash(0.01)
1033 DONE += 1000
1034 yield v * 2
1035 finally:
Yury Selivanov9012a0f2018-10-02 13:53:06 -04001036 await asyncio.sleep(0.01)
1037 await asyncio.sleep(0.01)
Yury Selivanoveb636452016-09-08 22:01:51 -07001038 DONE = 1
1039
1040 async def run():
1041 g = gen()
1042
1043 v = await g.asend(None)
1044 self.assertEqual(v, 1)
1045
1046 await g.asend(100)
1047
1048 with self.assertRaises(ZeroDivisionError):
1049 self.loop.run_until_complete(run())
1050 self.assertEqual(DONE, 1)
1051
1052 def test_async_gen_asyncio_asend_03(self):
1053 DONE = 0
1054
1055 async def sleep_n_crash(delay):
Yury Selivanov9012a0f2018-10-02 13:53:06 -04001056 fut = asyncio.ensure_future(asyncio.sleep(delay),
Yury Selivanoveb636452016-09-08 22:01:51 -07001057 loop=self.loop)
1058 self.loop.call_later(delay / 2, lambda: fut.cancel())
1059 return await fut
1060
1061 async def gen():
1062 nonlocal DONE
1063 try:
Yury Selivanov9012a0f2018-10-02 13:53:06 -04001064 await asyncio.sleep(0.01)
Yury Selivanoveb636452016-09-08 22:01:51 -07001065 v = yield 1
1066 await sleep_n_crash(0.01)
1067 DONE += 1000
1068 yield v * 2
1069 finally:
Yury Selivanov9012a0f2018-10-02 13:53:06 -04001070 await asyncio.sleep(0.01)
1071 await asyncio.sleep(0.01)
Yury Selivanoveb636452016-09-08 22:01:51 -07001072 DONE = 1
1073
1074 async def run():
1075 g = gen()
1076
1077 v = await g.asend(None)
1078 self.assertEqual(v, 1)
1079
1080 await g.asend(100)
1081
1082 with self.assertRaises(asyncio.CancelledError):
1083 self.loop.run_until_complete(run())
1084 self.assertEqual(DONE, 1)
1085
1086 def test_async_gen_asyncio_athrow_01(self):
1087 DONE = 0
1088
1089 class FooEr(Exception):
1090 pass
1091
1092 # Sanity check:
1093 def sgen():
1094 try:
1095 v = yield 1
1096 except FooEr:
1097 v = 1000
1098 yield v * 2
1099 sg = sgen()
1100 v = sg.send(None)
1101 self.assertEqual(v, 1)
1102 v = sg.throw(FooEr)
1103 self.assertEqual(v, 2000)
1104 with self.assertRaises(StopIteration):
1105 sg.send(None)
1106
1107 async def gen():
1108 nonlocal DONE
1109 try:
Yury Selivanov9012a0f2018-10-02 13:53:06 -04001110 await asyncio.sleep(0.01)
Yury Selivanoveb636452016-09-08 22:01:51 -07001111 try:
1112 v = yield 1
1113 except FooEr:
1114 v = 1000
Yury Selivanov9012a0f2018-10-02 13:53:06 -04001115 await asyncio.sleep(0.01)
Yury Selivanoveb636452016-09-08 22:01:51 -07001116 yield v * 2
Yury Selivanov9012a0f2018-10-02 13:53:06 -04001117 await asyncio.sleep(0.01)
Yury Selivanoveb636452016-09-08 22:01:51 -07001118 # return
1119 finally:
Yury Selivanov9012a0f2018-10-02 13:53:06 -04001120 await asyncio.sleep(0.01)
1121 await asyncio.sleep(0.01)
Yury Selivanoveb636452016-09-08 22:01:51 -07001122 DONE = 1
1123
1124 async def run():
1125 g = gen()
1126
1127 v = await g.asend(None)
1128 self.assertEqual(v, 1)
1129
1130 v = await g.athrow(FooEr)
1131 self.assertEqual(v, 2000)
1132
1133 with self.assertRaises(StopAsyncIteration):
1134 await g.asend(None)
1135
1136 self.loop.run_until_complete(run())
1137 self.assertEqual(DONE, 1)
1138
1139 def test_async_gen_asyncio_athrow_02(self):
1140 DONE = 0
1141
1142 class FooEr(Exception):
1143 pass
1144
1145 async def sleep_n_crash(delay):
Yury Selivanov9012a0f2018-10-02 13:53:06 -04001146 fut = asyncio.ensure_future(asyncio.sleep(delay),
Yury Selivanoveb636452016-09-08 22:01:51 -07001147 loop=self.loop)
1148 self.loop.call_later(delay / 2, lambda: fut.cancel())
1149 return await fut
1150
1151 async def gen():
1152 nonlocal DONE
1153 try:
Yury Selivanov9012a0f2018-10-02 13:53:06 -04001154 await asyncio.sleep(0.01)
Yury Selivanoveb636452016-09-08 22:01:51 -07001155 try:
1156 v = yield 1
1157 except FooEr:
1158 await sleep_n_crash(0.01)
1159 yield v * 2
Yury Selivanov9012a0f2018-10-02 13:53:06 -04001160 await asyncio.sleep(0.01)
Yury Selivanoveb636452016-09-08 22:01:51 -07001161 # return
1162 finally:
Yury Selivanov9012a0f2018-10-02 13:53:06 -04001163 await asyncio.sleep(0.01)
1164 await asyncio.sleep(0.01)
Yury Selivanoveb636452016-09-08 22:01:51 -07001165 DONE = 1
1166
1167 async def run():
1168 g = gen()
1169
1170 v = await g.asend(None)
1171 self.assertEqual(v, 1)
1172
1173 try:
1174 await g.athrow(FooEr)
1175 except asyncio.CancelledError:
1176 self.assertEqual(DONE, 1)
1177 raise
1178 else:
1179 self.fail('CancelledError was not raised')
1180
1181 with self.assertRaises(asyncio.CancelledError):
1182 self.loop.run_until_complete(run())
1183 self.assertEqual(DONE, 1)
1184
Yury Selivanov41782e42016-11-16 18:16:17 -05001185 def test_async_gen_asyncio_athrow_03(self):
1186 DONE = 0
1187
1188 # test synchronous generators
1189 def foo():
1190 try:
1191 yield
1192 except:
1193 pass
1194 g = foo()
1195 g.send(None)
1196 with self.assertRaises(StopIteration):
1197 g.throw(ValueError)
1198
1199 # now with asynchronous generators
1200
1201 async def gen():
1202 nonlocal DONE
1203 try:
1204 yield
1205 except:
1206 pass
1207 DONE = 1
1208
1209 async def run():
1210 nonlocal DONE
1211 g = gen()
1212 await g.asend(None)
1213 with self.assertRaises(StopAsyncIteration):
1214 await g.athrow(ValueError)
1215 DONE += 10
1216
1217 self.loop.run_until_complete(run())
1218 self.assertEqual(DONE, 11)
1219
Serhiy Storchaka60e49aa2016-11-06 18:47:03 +02001220 def test_async_gen_asyncio_athrow_tuple(self):
1221 async def gen():
1222 try:
1223 yield 1
1224 except ZeroDivisionError:
1225 yield (2,)
1226
1227 async def run():
1228 g = gen()
1229 v = await g.asend(None)
1230 self.assertEqual(v, 1)
1231 v = await g.athrow(ZeroDivisionError)
1232 self.assertEqual(v, (2,))
1233 with self.assertRaises(StopAsyncIteration):
1234 await g.asend(None)
1235
1236 self.loop.run_until_complete(run())
1237
1238 def test_async_gen_asyncio_athrow_stopiteration(self):
1239 async def gen():
1240 try:
1241 yield 1
1242 except ZeroDivisionError:
1243 yield StopIteration(2)
1244
1245 async def run():
1246 g = gen()
1247 v = await g.asend(None)
1248 self.assertEqual(v, 1)
1249 v = await g.athrow(ZeroDivisionError)
1250 self.assertIsInstance(v, StopIteration)
1251 self.assertEqual(v.value, 2)
1252 with self.assertRaises(StopAsyncIteration):
1253 await g.asend(None)
1254
1255 self.loop.run_until_complete(run())
1256
Yury Selivanoveb636452016-09-08 22:01:51 -07001257 def test_async_gen_asyncio_shutdown_01(self):
1258 finalized = 0
1259
1260 async def waiter(timeout):
1261 nonlocal finalized
1262 try:
Yury Selivanov9012a0f2018-10-02 13:53:06 -04001263 await asyncio.sleep(timeout)
Yury Selivanoveb636452016-09-08 22:01:51 -07001264 yield 1
1265 finally:
Yury Selivanov9012a0f2018-10-02 13:53:06 -04001266 await asyncio.sleep(0)
Yury Selivanoveb636452016-09-08 22:01:51 -07001267 finalized += 1
1268
1269 async def wait():
1270 async for _ in waiter(1):
1271 pass
1272
1273 t1 = self.loop.create_task(wait())
1274 t2 = self.loop.create_task(wait())
1275
Yury Selivanov9012a0f2018-10-02 13:53:06 -04001276 self.loop.run_until_complete(asyncio.sleep(0.1))
Yury Selivanoveb636452016-09-08 22:01:51 -07001277
Yury Selivanoveb636452016-09-08 22:01:51 -07001278 # Silence warnings
1279 t1.cancel()
1280 t2.cancel()
Yury Selivanoveb636452016-09-08 22:01:51 -07001281
Yury Selivanovfc4a0442019-09-29 22:59:11 -07001282 with self.assertRaises(asyncio.CancelledError):
1283 self.loop.run_until_complete(t1)
1284 with self.assertRaises(asyncio.CancelledError):
1285 self.loop.run_until_complete(t2)
Yury Selivanoveb636452016-09-08 22:01:51 -07001286
Yury Selivanoveb636452016-09-08 22:01:51 -07001287 self.loop.run_until_complete(self.loop.shutdown_asyncgens())
1288
Yury Selivanovfc4a0442019-09-29 22:59:11 -07001289 self.assertEqual(finalized, 2)
Yury Selivanoveb636452016-09-08 22:01:51 -07001290
Miss Islington (bot)2ad114d2021-09-04 13:37:56 -07001291 def test_async_gen_asyncio_shutdown_02(self):
1292 messages = []
1293
1294 def exception_handler(loop, context):
1295 messages.append(context)
1296
1297 async def async_iterate():
1298 yield 1
1299 yield 2
1300
1301 it = async_iterate()
1302 async def main():
1303 loop = asyncio.get_running_loop()
1304 loop.set_exception_handler(exception_handler)
1305
1306 async for i in it:
1307 break
1308
1309 asyncio.run(main())
1310
1311 self.assertEqual(messages, [])
1312
1313 def test_async_gen_asyncio_shutdown_exception_01(self):
1314 messages = []
1315
1316 def exception_handler(loop, context):
1317 messages.append(context)
1318
1319 async def async_iterate():
1320 try:
1321 yield 1
1322 yield 2
1323 finally:
1324 1/0
1325
1326 it = async_iterate()
1327 async def main():
1328 loop = asyncio.get_running_loop()
1329 loop.set_exception_handler(exception_handler)
1330
1331 async for i in it:
1332 break
1333
1334 asyncio.run(main())
1335
1336 message, = messages
1337 self.assertEqual(message['asyncgen'], it)
1338 self.assertIsInstance(message['exception'], ZeroDivisionError)
1339 self.assertIn('an error occurred during closing of asynchronous generator',
1340 message['message'])
1341
1342 def test_async_gen_asyncio_shutdown_exception_02(self):
1343 messages = []
1344
1345 def exception_handler(loop, context):
1346 messages.append(context)
1347
1348 async def async_iterate():
1349 try:
1350 yield 1
1351 yield 2
1352 finally:
1353 1/0
1354
1355 async def main():
1356 loop = asyncio.get_running_loop()
1357 loop.set_exception_handler(exception_handler)
1358
1359 async for i in async_iterate():
1360 break
1361 gc_collect()
1362
1363 asyncio.run(main())
1364
1365 message, = messages
1366 self.assertIsInstance(message['exception'], ZeroDivisionError)
1367 self.assertIn('unhandled exception during asyncio.run() shutdown',
1368 message['message'])
1369
Yury Selivanovb8ab9d32017-10-06 02:58:28 -04001370 def test_async_gen_expression_01(self):
1371 async def arange(n):
1372 for i in range(n):
Yury Selivanov9012a0f2018-10-02 13:53:06 -04001373 await asyncio.sleep(0.01)
Yury Selivanovb8ab9d32017-10-06 02:58:28 -04001374 yield i
1375
1376 def make_arange(n):
1377 # This syntax is legal starting with Python 3.7
1378 return (i * 2 async for i in arange(n))
1379
1380 async def run():
1381 return [i async for i in make_arange(10)]
1382
1383 res = self.loop.run_until_complete(run())
1384 self.assertEqual(res, [i * 2 for i in range(10)])
1385
1386 def test_async_gen_expression_02(self):
1387 async def wrap(n):
Yury Selivanov9012a0f2018-10-02 13:53:06 -04001388 await asyncio.sleep(0.01)
Yury Selivanovb8ab9d32017-10-06 02:58:28 -04001389 return n
1390
1391 def make_arange(n):
1392 # This syntax is legal starting with Python 3.7
1393 return (i * 2 for i in range(n) if await wrap(i))
1394
1395 async def run():
1396 return [i async for i in make_arange(10)]
1397
1398 res = self.loop.run_until_complete(run())
1399 self.assertEqual(res, [i * 2 for i in range(1, 10)])
1400
Andrew Svetlovc2753122019-09-17 15:59:49 +03001401 def test_asyncgen_nonstarted_hooks_are_cancellable(self):
1402 # See https://bugs.python.org/issue38013
1403 messages = []
1404
1405 def exception_handler(loop, context):
1406 messages.append(context)
1407
1408 async def async_iterate():
1409 yield 1
1410 yield 2
1411
1412 async def main():
1413 loop = asyncio.get_running_loop()
1414 loop.set_exception_handler(exception_handler)
1415
1416 async for i in async_iterate():
1417 break
1418
1419 asyncio.run(main())
1420
1421 self.assertEqual([], messages)
1422
Nathaniel J. Smith925dc7f2020-02-13 00:15:38 -08001423 def test_async_gen_await_same_anext_coro_twice(self):
Andrew Svetlova96e06d2020-01-21 00:49:30 +02001424 async def async_iterate():
1425 yield 1
1426 yield 2
1427
1428 async def run():
1429 it = async_iterate()
1430 nxt = it.__anext__()
1431 await nxt
1432 with self.assertRaisesRegex(
1433 RuntimeError,
1434 r"cannot reuse already awaited __anext__\(\)/asend\(\)"
1435 ):
1436 await nxt
1437
1438 await it.aclose() # prevent unfinished iterator warning
1439
1440 self.loop.run_until_complete(run())
1441
Nathaniel J. Smith925dc7f2020-02-13 00:15:38 -08001442 def test_async_gen_await_same_aclose_coro_twice(self):
Andrew Svetlova96e06d2020-01-21 00:49:30 +02001443 async def async_iterate():
1444 yield 1
1445 yield 2
1446
1447 async def run():
1448 it = async_iterate()
1449 nxt = it.aclose()
1450 await nxt
1451 with self.assertRaisesRegex(
1452 RuntimeError,
1453 r"cannot reuse already awaited aclose\(\)/athrow\(\)"
1454 ):
1455 await nxt
1456
1457 self.loop.run_until_complete(run())
1458
Nathaniel J. Smith925dc7f2020-02-13 00:15:38 -08001459 def test_async_gen_aclose_twice_with_different_coros(self):
1460 # Regression test for https://bugs.python.org/issue39606
1461 async def async_iterate():
1462 yield 1
1463 yield 2
1464
1465 async def run():
1466 it = async_iterate()
1467 await it.aclose()
1468 await it.aclose()
1469
1470 self.loop.run_until_complete(run())
1471
1472 def test_async_gen_aclose_after_exhaustion(self):
1473 # Regression test for https://bugs.python.org/issue39606
1474 async def async_iterate():
1475 yield 1
1476 yield 2
1477
1478 async def run():
1479 it = async_iterate()
1480 async for _ in it:
1481 pass
1482 await it.aclose()
1483
1484 self.loop.run_until_complete(run())
Yury Selivanovb8ab9d32017-10-06 02:58:28 -04001485
Lidi Zheng44823372020-03-02 04:45:54 -08001486 def test_async_gen_aclose_compatible_with_get_stack(self):
1487 async def async_generator():
1488 yield object()
1489
1490 async def run():
1491 ag = async_generator()
1492 asyncio.create_task(ag.aclose())
1493 tasks = asyncio.all_tasks()
1494 for task in tasks:
1495 # No AttributeError raised
1496 task.get_stack()
1497
1498 self.loop.run_until_complete(run())
1499
1500
Yury Selivanoveb636452016-09-08 22:01:51 -07001501if __name__ == "__main__":
1502 unittest.main()