blob: 3413a12d6f00d795184c27a31686f594c9fe4231 [file] [log] [blame]
Yury Selivanov75445082015-05-11 22:57:16 -04001import contextlib
Yury Selivanov8085b802015-05-18 12:50:52 -04002import inspect
Yury Selivanov75445082015-05-11 22:57:16 -04003import sys
4import types
5import unittest
6import warnings
7from test import support
8
9
10class AsyncYieldFrom:
11 def __init__(self, obj):
12 self.obj = obj
13
14 def __await__(self):
15 yield from self.obj
16
17
18class AsyncYield:
19 def __init__(self, value):
20 self.value = value
21
22 def __await__(self):
23 yield self.value
24
25
26def run_async(coro):
Yury Selivanov5376ba92015-06-22 12:19:30 -040027 assert coro.__class__ in {types.GeneratorType, types.CoroutineType}
Yury Selivanov75445082015-05-11 22:57:16 -040028
29 buffer = []
30 result = None
31 while True:
32 try:
33 buffer.append(coro.send(None))
34 except StopIteration as ex:
35 result = ex.args[0] if ex.args else None
36 break
37 return buffer, result
38
39
Yury Selivanov5376ba92015-06-22 12:19:30 -040040def run_async__await__(coro):
41 assert coro.__class__ is types.CoroutineType
42 aw = coro.__await__()
43 buffer = []
44 result = None
45 i = 0
46 while True:
47 try:
48 if i % 2:
49 buffer.append(next(aw))
50 else:
51 buffer.append(aw.send(None))
52 i += 1
53 except StopIteration as ex:
54 result = ex.args[0] if ex.args else None
55 break
56 return buffer, result
57
58
Yury Selivanov75445082015-05-11 22:57:16 -040059@contextlib.contextmanager
60def silence_coro_gc():
61 with warnings.catch_warnings():
62 warnings.simplefilter("ignore")
63 yield
64 support.gc_collect()
65
66
67class AsyncBadSyntaxTest(unittest.TestCase):
68
69 def test_badsyntax_1(self):
70 with self.assertRaisesRegex(SyntaxError, 'invalid syntax'):
71 import test.badsyntax_async1
72
73 def test_badsyntax_2(self):
74 with self.assertRaisesRegex(SyntaxError, 'invalid syntax'):
75 import test.badsyntax_async2
76
77 def test_badsyntax_3(self):
78 with self.assertRaisesRegex(SyntaxError, 'invalid syntax'):
79 import test.badsyntax_async3
80
81 def test_badsyntax_4(self):
82 with self.assertRaisesRegex(SyntaxError, 'invalid syntax'):
83 import test.badsyntax_async4
84
85 def test_badsyntax_5(self):
86 with self.assertRaisesRegex(SyntaxError, 'invalid syntax'):
87 import test.badsyntax_async5
88
89 def test_badsyntax_6(self):
90 with self.assertRaisesRegex(
91 SyntaxError, "'yield' inside async function"):
92
93 import test.badsyntax_async6
94
95 def test_badsyntax_7(self):
96 with self.assertRaisesRegex(
97 SyntaxError, "'yield from' inside async function"):
98
99 import test.badsyntax_async7
100
101 def test_badsyntax_8(self):
102 with self.assertRaisesRegex(SyntaxError, 'invalid syntax'):
103 import test.badsyntax_async8
104
105 def test_badsyntax_9(self):
106 with self.assertRaisesRegex(SyntaxError, 'invalid syntax'):
107 import test.badsyntax_async9
108
Yury Selivanov9dec0352015-06-30 12:49:04 -0400109 def test_badsyntax_10(self):
110 ns = {}
111 for comp in {'(await a for a in b)',
112 '[await a for a in b]',
113 '{await a for a in b}',
114 '{await a: c for a in b}'}:
115
Yury Selivanov86cd7d62015-06-30 12:51:12 -0400116 with self.assertRaisesRegex(SyntaxError, 'await.*in comprehen'):
Yury Selivanov9dec0352015-06-30 12:49:04 -0400117 exec('async def f():\n\t{}'.format(comp), ns, ns)
118
Yury Selivanov75445082015-05-11 22:57:16 -0400119
Yury Selivanov8085b802015-05-18 12:50:52 -0400120class TokenizerRegrTest(unittest.TestCase):
121
122 def test_oneline_defs(self):
123 buf = []
124 for i in range(500):
125 buf.append('def i{i}(): return {i}'.format(i=i))
126 buf = '\n'.join(buf)
127
128 # Test that 500 consequent, one-line defs is OK
129 ns = {}
130 exec(buf, ns, ns)
131 self.assertEqual(ns['i499'](), 499)
132
133 # Test that 500 consequent, one-line defs *and*
134 # one 'async def' following them is OK
135 buf += '\nasync def foo():\n return'
136 ns = {}
137 exec(buf, ns, ns)
138 self.assertEqual(ns['i499'](), 499)
139 self.assertTrue(inspect.iscoroutinefunction(ns['foo']))
140
141
Yury Selivanov75445082015-05-11 22:57:16 -0400142class CoroutineTest(unittest.TestCase):
143
144 def test_gen_1(self):
145 def gen(): yield
146 self.assertFalse(hasattr(gen, '__await__'))
147
148 def test_func_1(self):
149 async def foo():
150 return 10
151
152 f = foo()
Yury Selivanov5376ba92015-06-22 12:19:30 -0400153 self.assertIsInstance(f, types.CoroutineType)
154 self.assertTrue(bool(foo.__code__.co_flags & inspect.CO_COROUTINE))
155 self.assertFalse(bool(foo.__code__.co_flags & inspect.CO_GENERATOR))
156 self.assertTrue(bool(f.cr_code.co_flags & inspect.CO_COROUTINE))
157 self.assertFalse(bool(f.cr_code.co_flags & inspect.CO_GENERATOR))
Yury Selivanov75445082015-05-11 22:57:16 -0400158 self.assertEqual(run_async(f), ([], 10))
159
Yury Selivanov5376ba92015-06-22 12:19:30 -0400160 self.assertEqual(run_async__await__(foo()), ([], 10))
161
Yury Selivanov75445082015-05-11 22:57:16 -0400162 def bar(): pass
Yury Selivanov5376ba92015-06-22 12:19:30 -0400163 self.assertFalse(bool(bar.__code__.co_flags & inspect.CO_COROUTINE))
Yury Selivanov75445082015-05-11 22:57:16 -0400164
165 def test_func_2(self):
166 async def foo():
167 raise StopIteration
168
169 with self.assertRaisesRegex(
Yury Selivanov5376ba92015-06-22 12:19:30 -0400170 RuntimeError, "coroutine raised StopIteration"):
Yury Selivanov75445082015-05-11 22:57:16 -0400171
172 run_async(foo())
173
174 def test_func_3(self):
175 async def foo():
176 raise StopIteration
177
178 with silence_coro_gc():
179 self.assertRegex(repr(foo()), '^<coroutine object.* at 0x.*>$')
180
181 def test_func_4(self):
182 async def foo():
183 raise StopIteration
184
185 check = lambda: self.assertRaisesRegex(
Yury Selivanov5376ba92015-06-22 12:19:30 -0400186 TypeError, "'coroutine' object is not iterable")
Yury Selivanov75445082015-05-11 22:57:16 -0400187
188 with check():
189 list(foo())
190
191 with check():
192 tuple(foo())
193
194 with check():
195 sum(foo())
196
197 with check():
198 iter(foo())
199
Yury Selivanov75445082015-05-11 22:57:16 -0400200 with silence_coro_gc(), check():
201 for i in foo():
202 pass
203
204 with silence_coro_gc(), check():
205 [i for i in foo()]
206
207 def test_func_5(self):
208 @types.coroutine
209 def bar():
210 yield 1
211
212 async def foo():
213 await bar()
214
215 check = lambda: self.assertRaisesRegex(
Yury Selivanov5376ba92015-06-22 12:19:30 -0400216 TypeError, "'coroutine' object is not iterable")
Yury Selivanov75445082015-05-11 22:57:16 -0400217
218 with check():
219 for el in foo(): pass
220
221 # the following should pass without an error
222 for el in bar():
223 self.assertEqual(el, 1)
224 self.assertEqual([el for el in bar()], [1])
225 self.assertEqual(tuple(bar()), (1,))
226 self.assertEqual(next(iter(bar())), 1)
227
228 def test_func_6(self):
229 @types.coroutine
230 def bar():
231 yield 1
232 yield 2
233
234 async def foo():
235 await bar()
236
237 f = foo()
Zachary Ware37ac5902015-05-13 01:03:06 -0500238 self.assertEqual(f.send(None), 1)
239 self.assertEqual(f.send(None), 2)
Yury Selivanov75445082015-05-11 22:57:16 -0400240 with self.assertRaises(StopIteration):
241 f.send(None)
242
243 def test_func_7(self):
244 async def bar():
245 return 10
246
247 def foo():
248 yield from bar()
249
250 with silence_coro_gc(), self.assertRaisesRegex(
251 TypeError,
Yury Selivanov5376ba92015-06-22 12:19:30 -0400252 "cannot 'yield from' a coroutine object in a non-coroutine generator"):
Yury Selivanov75445082015-05-11 22:57:16 -0400253
254 list(foo())
255
256 def test_func_8(self):
257 @types.coroutine
258 def bar():
259 return (yield from foo())
260
261 async def foo():
262 return 'spam'
263
264 self.assertEqual(run_async(bar()), ([], 'spam') )
265
266 def test_func_9(self):
267 async def foo(): pass
268
269 with self.assertWarnsRegex(
270 RuntimeWarning, "coroutine '.*test_func_9.*foo' was never awaited"):
271
272 foo()
273 support.gc_collect()
274
Yury Selivanov5376ba92015-06-22 12:19:30 -0400275 def test_func_10(self):
276 N = 0
277
278 @types.coroutine
279 def gen():
280 nonlocal N
281 try:
282 a = yield
283 yield (a ** 2)
284 except ZeroDivisionError:
285 N += 100
286 raise
287 finally:
288 N += 1
289
290 async def foo():
291 await gen()
292
293 coro = foo()
294 aw = coro.__await__()
295 self.assertIs(aw, iter(aw))
296 next(aw)
297 self.assertEqual(aw.send(10), 100)
298
299 self.assertEqual(N, 0)
300 aw.close()
301 self.assertEqual(N, 1)
302
303 coro = foo()
304 aw = coro.__await__()
305 next(aw)
306 with self.assertRaises(ZeroDivisionError):
307 aw.throw(ZeroDivisionError, None, None)
308 self.assertEqual(N, 102)
309
310 def test_func_11(self):
311 async def func(): pass
312 coro = func()
313 # Test that PyCoro_Type and _PyCoroWrapper_Type types were properly
314 # initialized
315 self.assertIn('__await__', dir(coro))
316 self.assertIn('__iter__', dir(coro.__await__()))
317 self.assertIn('coroutine_wrapper', repr(coro.__await__()))
318 coro.close() # avoid RuntimeWarning
319
320 def test_func_12(self):
321 async def g():
322 i = me.send(None)
323 await foo
324 me = g()
325 with self.assertRaisesRegex(ValueError,
326 "coroutine already executing"):
327 me.send(None)
328
329 def test_func_13(self):
330 async def g():
331 pass
332 with self.assertRaisesRegex(
333 TypeError,
334 "can't send non-None value to a just-started coroutine"):
335
336 g().send('spam')
337
338 def test_func_14(self):
339 @types.coroutine
340 def gen():
341 yield
342 async def coro():
343 try:
344 await gen()
345 except GeneratorExit:
346 await gen()
347 c = coro()
348 c.send(None)
349 with self.assertRaisesRegex(RuntimeError,
350 "coroutine ignored GeneratorExit"):
351 c.close()
352
353 def test_corotype_1(self):
354 ct = types.CoroutineType
355 self.assertIn('into coroutine', ct.send.__doc__)
356 self.assertIn('inside coroutine', ct.close.__doc__)
357 self.assertIn('in coroutine', ct.throw.__doc__)
358 self.assertIn('of the coroutine', ct.__dict__['__name__'].__doc__)
359 self.assertIn('of the coroutine', ct.__dict__['__qualname__'].__doc__)
360 self.assertEqual(ct.__name__, 'coroutine')
361
362 async def f(): pass
363 c = f()
364 self.assertIn('coroutine object', repr(c))
365 c.close()
366
Yury Selivanov75445082015-05-11 22:57:16 -0400367 def test_await_1(self):
368
369 async def foo():
370 await 1
371 with self.assertRaisesRegex(TypeError, "object int can.t.*await"):
372 run_async(foo())
373
374 def test_await_2(self):
375 async def foo():
376 await []
377 with self.assertRaisesRegex(TypeError, "object list can.t.*await"):
378 run_async(foo())
379
380 def test_await_3(self):
381 async def foo():
382 await AsyncYieldFrom([1, 2, 3])
383
384 self.assertEqual(run_async(foo()), ([1, 2, 3], None))
Yury Selivanov5376ba92015-06-22 12:19:30 -0400385 self.assertEqual(run_async__await__(foo()), ([1, 2, 3], None))
Yury Selivanov75445082015-05-11 22:57:16 -0400386
387 def test_await_4(self):
388 async def bar():
389 return 42
390
391 async def foo():
392 return await bar()
393
394 self.assertEqual(run_async(foo()), ([], 42))
395
396 def test_await_5(self):
397 class Awaitable:
398 def __await__(self):
399 return
400
401 async def foo():
402 return (await Awaitable())
403
404 with self.assertRaisesRegex(
405 TypeError, "__await__.*returned non-iterator of type"):
406
407 run_async(foo())
408
409 def test_await_6(self):
410 class Awaitable:
411 def __await__(self):
412 return iter([52])
413
414 async def foo():
415 return (await Awaitable())
416
417 self.assertEqual(run_async(foo()), ([52], None))
418
419 def test_await_7(self):
420 class Awaitable:
421 def __await__(self):
422 yield 42
423 return 100
424
425 async def foo():
426 return (await Awaitable())
427
428 self.assertEqual(run_async(foo()), ([42], 100))
429
430 def test_await_8(self):
431 class Awaitable:
432 pass
433
434 async def foo():
435 return (await Awaitable())
436
437 with self.assertRaisesRegex(
438 TypeError, "object Awaitable can't be used in 'await' expression"):
439
440 run_async(foo())
441
442 def test_await_9(self):
443 def wrap():
444 return bar
445
446 async def bar():
447 return 42
448
449 async def foo():
450 b = bar()
451
452 db = {'b': lambda: wrap}
453
454 class DB:
455 b = wrap
456
457 return (await bar() + await wrap()() + await db['b']()()() +
458 await bar() * 1000 + await DB.b()())
459
460 async def foo2():
461 return -await bar()
462
463 self.assertEqual(run_async(foo()), ([], 42168))
464 self.assertEqual(run_async(foo2()), ([], -42))
465
466 def test_await_10(self):
467 async def baz():
468 return 42
469
470 async def bar():
471 return baz()
472
473 async def foo():
474 return await (await bar())
475
476 self.assertEqual(run_async(foo()), ([], 42))
477
478 def test_await_11(self):
479 def ident(val):
480 return val
481
482 async def bar():
483 return 'spam'
484
485 async def foo():
486 return ident(val=await bar())
487
488 async def foo2():
489 return await bar(), 'ham'
490
491 self.assertEqual(run_async(foo2()), ([], ('spam', 'ham')))
492
493 def test_await_12(self):
494 async def coro():
495 return 'spam'
496
497 class Awaitable:
498 def __await__(self):
499 return coro()
500
501 async def foo():
502 return await Awaitable()
503
504 with self.assertRaisesRegex(
505 TypeError, "__await__\(\) returned a coroutine"):
506
507 run_async(foo())
508
509 def test_await_13(self):
510 class Awaitable:
511 def __await__(self):
512 return self
513
514 async def foo():
515 return await Awaitable()
516
517 with self.assertRaisesRegex(
518 TypeError, "__await__.*returned non-iterator of type"):
519
520 run_async(foo())
521
Yury Selivanovf2701522015-07-01 12:29:55 -0400522 def test_await_14(self):
523 class Wrapper:
524 # Forces the interpreter to use CoroutineType.__await__
525 def __init__(self, coro):
526 assert coro.__class__ is types.CoroutineType
527 self.coro = coro
528 def __await__(self):
529 return self.coro.__await__()
530
531 class FutureLike:
532 def __await__(self):
533 return (yield)
534
535 class Marker(Exception):
536 pass
537
538 async def coro1():
539 try:
540 return await FutureLike()
541 except ZeroDivisionError:
542 raise Marker
543 async def coro2():
544 return await Wrapper(coro1())
545
546 c = coro2()
547 c.send(None)
548 with self.assertRaisesRegex(StopIteration, 'spam'):
549 c.send('spam')
550
551 c = coro2()
552 c.send(None)
553 with self.assertRaises(Marker):
554 c.throw(ZeroDivisionError)
555
Yury Selivanov75445082015-05-11 22:57:16 -0400556 def test_with_1(self):
557 class Manager:
558 def __init__(self, name):
559 self.name = name
560
561 async def __aenter__(self):
562 await AsyncYieldFrom(['enter-1-' + self.name,
563 'enter-2-' + self.name])
564 return self
565
566 async def __aexit__(self, *args):
567 await AsyncYieldFrom(['exit-1-' + self.name,
568 'exit-2-' + self.name])
569
570 if self.name == 'B':
571 return True
572
573
574 async def foo():
575 async with Manager("A") as a, Manager("B") as b:
576 await AsyncYieldFrom([('managers', a.name, b.name)])
577 1/0
578
579 f = foo()
580 result, _ = run_async(f)
581
582 self.assertEqual(
583 result, ['enter-1-A', 'enter-2-A', 'enter-1-B', 'enter-2-B',
584 ('managers', 'A', 'B'),
585 'exit-1-B', 'exit-2-B', 'exit-1-A', 'exit-2-A']
586 )
587
588 async def foo():
589 async with Manager("A") as a, Manager("C") as c:
590 await AsyncYieldFrom([('managers', a.name, c.name)])
591 1/0
592
593 with self.assertRaises(ZeroDivisionError):
594 run_async(foo())
595
596 def test_with_2(self):
597 class CM:
598 def __aenter__(self):
599 pass
600
601 async def foo():
602 async with CM():
603 pass
604
605 with self.assertRaisesRegex(AttributeError, '__aexit__'):
606 run_async(foo())
607
608 def test_with_3(self):
609 class CM:
610 def __aexit__(self):
611 pass
612
613 async def foo():
614 async with CM():
615 pass
616
617 with self.assertRaisesRegex(AttributeError, '__aenter__'):
618 run_async(foo())
619
620 def test_with_4(self):
621 class CM:
622 def __enter__(self):
623 pass
624
625 def __exit__(self):
626 pass
627
628 async def foo():
629 async with CM():
630 pass
631
632 with self.assertRaisesRegex(AttributeError, '__aexit__'):
633 run_async(foo())
634
635 def test_with_5(self):
636 # While this test doesn't make a lot of sense,
637 # it's a regression test for an early bug with opcodes
638 # generation
639
640 class CM:
641 async def __aenter__(self):
642 return self
643
644 async def __aexit__(self, *exc):
645 pass
646
647 async def func():
648 async with CM():
649 assert (1, ) == 1
650
651 with self.assertRaises(AssertionError):
652 run_async(func())
653
654 def test_with_6(self):
655 class CM:
656 def __aenter__(self):
657 return 123
658
659 def __aexit__(self, *e):
660 return 456
661
662 async def foo():
663 async with CM():
664 pass
665
666 with self.assertRaisesRegex(
667 TypeError, "object int can't be used in 'await' expression"):
668 # it's important that __aexit__ wasn't called
669 run_async(foo())
670
671 def test_with_7(self):
672 class CM:
673 async def __aenter__(self):
674 return self
675
676 def __aexit__(self, *e):
Nick Coghlanbaaadbf2015-05-13 15:54:02 +1000677 return 444
Yury Selivanov75445082015-05-11 22:57:16 -0400678
679 async def foo():
680 async with CM():
Nick Coghlanbaaadbf2015-05-13 15:54:02 +1000681 1/0
682
683 try:
684 run_async(foo())
685 except TypeError as exc:
686 self.assertRegex(
687 exc.args[0], "object int can't be used in 'await' expression")
688 self.assertTrue(exc.__context__ is not None)
689 self.assertTrue(isinstance(exc.__context__, ZeroDivisionError))
690 else:
691 self.fail('invalid asynchronous context manager did not fail')
692
693
694 def test_with_8(self):
695 CNT = 0
696
697 class CM:
698 async def __aenter__(self):
699 return self
700
701 def __aexit__(self, *e):
702 return 456
703
704 async def foo():
705 nonlocal CNT
706 async with CM():
707 CNT += 1
708
Yury Selivanov75445082015-05-11 22:57:16 -0400709
710 with self.assertRaisesRegex(
711 TypeError, "object int can't be used in 'await' expression"):
712
713 run_async(foo())
714
Nick Coghlanbaaadbf2015-05-13 15:54:02 +1000715 self.assertEqual(CNT, 1)
716
717
718 def test_with_9(self):
719 CNT = 0
720
721 class CM:
722 async def __aenter__(self):
723 return self
724
725 async def __aexit__(self, *e):
726 1/0
727
728 async def foo():
729 nonlocal CNT
730 async with CM():
731 CNT += 1
732
733 with self.assertRaises(ZeroDivisionError):
734 run_async(foo())
735
736 self.assertEqual(CNT, 1)
737
738 def test_with_10(self):
739 CNT = 0
740
741 class CM:
742 async def __aenter__(self):
743 return self
744
745 async def __aexit__(self, *e):
746 1/0
747
748 async def foo():
749 nonlocal CNT
750 async with CM():
751 async with CM():
752 raise RuntimeError
753
754 try:
755 run_async(foo())
756 except ZeroDivisionError as exc:
757 self.assertTrue(exc.__context__ is not None)
758 self.assertTrue(isinstance(exc.__context__, ZeroDivisionError))
759 self.assertTrue(isinstance(exc.__context__.__context__,
760 RuntimeError))
761 else:
762 self.fail('exception from __aexit__ did not propagate')
763
764 def test_with_11(self):
765 CNT = 0
766
767 class CM:
768 async def __aenter__(self):
769 raise NotImplementedError
770
771 async def __aexit__(self, *e):
772 1/0
773
774 async def foo():
775 nonlocal CNT
776 async with CM():
777 raise RuntimeError
778
779 try:
780 run_async(foo())
781 except NotImplementedError as exc:
782 self.assertTrue(exc.__context__ is None)
783 else:
784 self.fail('exception from __aenter__ did not propagate')
785
786 def test_with_12(self):
787 CNT = 0
788
789 class CM:
790 async def __aenter__(self):
791 return self
792
793 async def __aexit__(self, *e):
794 return True
795
796 async def foo():
797 nonlocal CNT
798 async with CM() as cm:
799 self.assertIs(cm.__class__, CM)
800 raise RuntimeError
801
802 run_async(foo())
803
Yury Selivanov9113dc72015-05-13 16:49:35 -0400804 def test_with_13(self):
805 CNT = 0
806
807 class CM:
808 async def __aenter__(self):
809 1/0
810
811 async def __aexit__(self, *e):
812 return True
813
814 async def foo():
815 nonlocal CNT
816 CNT += 1
817 async with CM():
818 CNT += 1000
819 CNT += 10000
820
821 with self.assertRaises(ZeroDivisionError):
822 run_async(foo())
823 self.assertEqual(CNT, 1)
824
Yury Selivanov75445082015-05-11 22:57:16 -0400825 def test_for_1(self):
826 aiter_calls = 0
827
828 class AsyncIter:
829 def __init__(self):
830 self.i = 0
831
832 async def __aiter__(self):
833 nonlocal aiter_calls
834 aiter_calls += 1
835 return self
836
837 async def __anext__(self):
838 self.i += 1
839
840 if not (self.i % 10):
841 await AsyncYield(self.i * 10)
842
843 if self.i > 100:
844 raise StopAsyncIteration
845
846 return self.i, self.i
847
848
849 buffer = []
850 async def test1():
851 async for i1, i2 in AsyncIter():
852 buffer.append(i1 + i2)
853
854 yielded, _ = run_async(test1())
855 # Make sure that __aiter__ was called only once
856 self.assertEqual(aiter_calls, 1)
857 self.assertEqual(yielded, [i * 100 for i in range(1, 11)])
858 self.assertEqual(buffer, [i*2 for i in range(1, 101)])
859
860
861 buffer = []
862 async def test2():
863 nonlocal buffer
864 async for i in AsyncIter():
865 buffer.append(i[0])
866 if i[0] == 20:
867 break
868 else:
869 buffer.append('what?')
870 buffer.append('end')
871
872 yielded, _ = run_async(test2())
873 # Make sure that __aiter__ was called only once
874 self.assertEqual(aiter_calls, 2)
875 self.assertEqual(yielded, [100, 200])
876 self.assertEqual(buffer, [i for i in range(1, 21)] + ['end'])
877
878
879 buffer = []
880 async def test3():
881 nonlocal buffer
882 async for i in AsyncIter():
883 if i[0] > 20:
884 continue
885 buffer.append(i[0])
886 else:
887 buffer.append('what?')
888 buffer.append('end')
889
890 yielded, _ = run_async(test3())
891 # Make sure that __aiter__ was called only once
892 self.assertEqual(aiter_calls, 3)
893 self.assertEqual(yielded, [i * 100 for i in range(1, 11)])
894 self.assertEqual(buffer, [i for i in range(1, 21)] +
895 ['what?', 'end'])
896
897 def test_for_2(self):
898 tup = (1, 2, 3)
899 refs_before = sys.getrefcount(tup)
900
901 async def foo():
902 async for i in tup:
903 print('never going to happen')
904
905 with self.assertRaisesRegex(
906 TypeError, "async for' requires an object.*__aiter__.*tuple"):
907
908 run_async(foo())
909
910 self.assertEqual(sys.getrefcount(tup), refs_before)
911
912 def test_for_3(self):
913 class I:
914 def __aiter__(self):
915 return self
916
917 aiter = I()
918 refs_before = sys.getrefcount(aiter)
919
920 async def foo():
921 async for i in aiter:
922 print('never going to happen')
923
924 with self.assertRaisesRegex(
925 TypeError,
926 "async for' received an invalid object.*__aiter.*\: I"):
927
928 run_async(foo())
929
930 self.assertEqual(sys.getrefcount(aiter), refs_before)
931
932 def test_for_4(self):
933 class I:
934 async def __aiter__(self):
935 return self
936
937 def __anext__(self):
938 return ()
939
940 aiter = I()
941 refs_before = sys.getrefcount(aiter)
942
943 async def foo():
944 async for i in aiter:
945 print('never going to happen')
946
947 with self.assertRaisesRegex(
948 TypeError,
949 "async for' received an invalid object.*__anext__.*tuple"):
950
951 run_async(foo())
952
953 self.assertEqual(sys.getrefcount(aiter), refs_before)
954
955 def test_for_5(self):
956 class I:
957 async def __aiter__(self):
958 return self
959
960 def __anext__(self):
961 return 123
962
963 async def foo():
964 async for i in I():
965 print('never going to happen')
966
967 with self.assertRaisesRegex(
968 TypeError,
969 "async for' received an invalid object.*__anext.*int"):
970
971 run_async(foo())
972
973 def test_for_6(self):
974 I = 0
975
976 class Manager:
977 async def __aenter__(self):
978 nonlocal I
979 I += 10000
980
981 async def __aexit__(self, *args):
982 nonlocal I
983 I += 100000
984
985 class Iterable:
986 def __init__(self):
987 self.i = 0
988
989 async def __aiter__(self):
990 return self
991
992 async def __anext__(self):
993 if self.i > 10:
994 raise StopAsyncIteration
995 self.i += 1
996 return self.i
997
998 ##############
999
1000 manager = Manager()
1001 iterable = Iterable()
1002 mrefs_before = sys.getrefcount(manager)
1003 irefs_before = sys.getrefcount(iterable)
1004
1005 async def main():
1006 nonlocal I
1007
1008 async with manager:
1009 async for i in iterable:
1010 I += 1
1011 I += 1000
1012
1013 run_async(main())
1014 self.assertEqual(I, 111011)
1015
1016 self.assertEqual(sys.getrefcount(manager), mrefs_before)
1017 self.assertEqual(sys.getrefcount(iterable), irefs_before)
1018
1019 ##############
1020
1021 async def main():
1022 nonlocal I
1023
1024 async with Manager():
1025 async for i in Iterable():
1026 I += 1
1027 I += 1000
1028
1029 async with Manager():
1030 async for i in Iterable():
1031 I += 1
1032 I += 1000
1033
1034 run_async(main())
1035 self.assertEqual(I, 333033)
1036
1037 ##############
1038
1039 async def main():
1040 nonlocal I
1041
1042 async with Manager():
1043 I += 100
1044 async for i in Iterable():
1045 I += 1
1046 else:
1047 I += 10000000
1048 I += 1000
1049
1050 async with Manager():
1051 I += 100
1052 async for i in Iterable():
1053 I += 1
1054 else:
1055 I += 10000000
1056 I += 1000
1057
1058 run_async(main())
1059 self.assertEqual(I, 20555255)
1060
Yury Selivanov9113dc72015-05-13 16:49:35 -04001061 def test_for_7(self):
1062 CNT = 0
1063 class AI:
1064 async def __aiter__(self):
1065 1/0
1066 async def foo():
1067 nonlocal CNT
1068 async for i in AI():
1069 CNT += 1
1070 CNT += 10
1071 with self.assertRaises(ZeroDivisionError):
1072 run_async(foo())
1073 self.assertEqual(CNT, 0)
1074
Yury Selivanov75445082015-05-11 22:57:16 -04001075
1076class CoroAsyncIOCompatTest(unittest.TestCase):
1077
1078 def test_asyncio_1(self):
1079 import asyncio
1080
1081 class MyException(Exception):
1082 pass
1083
1084 buffer = []
1085
1086 class CM:
1087 async def __aenter__(self):
1088 buffer.append(1)
1089 await asyncio.sleep(0.01)
1090 buffer.append(2)
1091 return self
1092
1093 async def __aexit__(self, exc_type, exc_val, exc_tb):
1094 await asyncio.sleep(0.01)
1095 buffer.append(exc_type.__name__)
1096
1097 async def f():
1098 async with CM() as c:
1099 await asyncio.sleep(0.01)
1100 raise MyException
1101 buffer.append('unreachable')
1102
Yury Selivanovfdba8382015-05-12 14:28:08 -04001103 loop = asyncio.new_event_loop()
1104 asyncio.set_event_loop(loop)
Yury Selivanov75445082015-05-11 22:57:16 -04001105 try:
1106 loop.run_until_complete(f())
1107 except MyException:
1108 pass
1109 finally:
1110 loop.close()
Yury Selivanovfdba8382015-05-12 14:28:08 -04001111 asyncio.set_event_loop(None)
Yury Selivanov75445082015-05-11 22:57:16 -04001112
1113 self.assertEqual(buffer, [1, 2, 'MyException'])
1114
1115
1116class SysSetCoroWrapperTest(unittest.TestCase):
1117
1118 def test_set_wrapper_1(self):
1119 async def foo():
1120 return 'spam'
1121
1122 wrapped = None
1123 def wrap(gen):
1124 nonlocal wrapped
1125 wrapped = gen
1126 return gen
1127
1128 self.assertIsNone(sys.get_coroutine_wrapper())
1129
1130 sys.set_coroutine_wrapper(wrap)
1131 self.assertIs(sys.get_coroutine_wrapper(), wrap)
1132 try:
1133 f = foo()
1134 self.assertTrue(wrapped)
1135
1136 self.assertEqual(run_async(f), ([], 'spam'))
1137 finally:
1138 sys.set_coroutine_wrapper(None)
1139
1140 self.assertIsNone(sys.get_coroutine_wrapper())
1141
1142 wrapped = None
1143 with silence_coro_gc():
1144 foo()
1145 self.assertFalse(wrapped)
1146
1147 def test_set_wrapper_2(self):
1148 self.assertIsNone(sys.get_coroutine_wrapper())
1149 with self.assertRaisesRegex(TypeError, "callable expected, got int"):
1150 sys.set_coroutine_wrapper(1)
1151 self.assertIsNone(sys.get_coroutine_wrapper())
1152
Yury Selivanovaab3c4a2015-06-02 18:43:51 -04001153 def test_set_wrapper_3(self):
1154 async def foo():
1155 return 'spam'
1156
1157 def wrapper(coro):
1158 async def wrap(coro):
1159 return await coro
1160 return wrap(coro)
1161
1162 sys.set_coroutine_wrapper(wrapper)
1163 try:
Yury Selivanov94c22632015-06-04 10:16:51 -04001164 with silence_coro_gc(), self.assertRaisesRegex(
Yury Selivanovaab3c4a2015-06-02 18:43:51 -04001165 RuntimeError,
1166 "coroutine wrapper.*\.wrapper at 0x.*attempted to "
Yury Selivanov94c22632015-06-04 10:16:51 -04001167 "recursively wrap .* wrap .*"):
Yury Selivanovaab3c4a2015-06-02 18:43:51 -04001168
1169 foo()
1170 finally:
1171 sys.set_coroutine_wrapper(None)
1172
Yury Selivanov5376ba92015-06-22 12:19:30 -04001173 def test_set_wrapper_4(self):
1174 @types.coroutine
1175 def foo():
1176 return 'spam'
1177
1178 wrapped = None
1179 def wrap(gen):
1180 nonlocal wrapped
1181 wrapped = gen
1182 return gen
1183
1184 sys.set_coroutine_wrapper(wrap)
1185 try:
1186 foo()
1187 self.assertIs(
1188 wrapped, None,
1189 "generator-based coroutine was wrapped via "
1190 "sys.set_coroutine_wrapper")
1191 finally:
1192 sys.set_coroutine_wrapper(None)
1193
Yury Selivanov75445082015-05-11 22:57:16 -04001194
1195class CAPITest(unittest.TestCase):
1196
1197 def test_tp_await_1(self):
1198 from _testcapi import awaitType as at
1199
1200 async def foo():
1201 future = at(iter([1]))
1202 return (await future)
1203
1204 self.assertEqual(foo().send(None), 1)
1205
1206 def test_tp_await_2(self):
1207 # Test tp_await to __await__ mapping
1208 from _testcapi import awaitType as at
1209 future = at(iter([1]))
1210 self.assertEqual(next(future.__await__()), 1)
1211
1212 def test_tp_await_3(self):
1213 from _testcapi import awaitType as at
1214
1215 async def foo():
1216 future = at(1)
1217 return (await future)
1218
1219 with self.assertRaisesRegex(
1220 TypeError, "__await__.*returned non-iterator of type 'int'"):
1221 self.assertEqual(foo().send(None), 1)
1222
1223
Yury Selivanov75445082015-05-11 22:57:16 -04001224if __name__=="__main__":
Zachary Ware37ac5902015-05-13 01:03:06 -05001225 unittest.main()