1211 lines
		
	
	
		
			31 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			1211 lines
		
	
	
		
			31 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| import inspect
 | |
| import types
 | |
| import unittest
 | |
| 
 | |
| from test.support import import_module
 | |
| asyncio = import_module("asyncio")
 | |
| 
 | |
| 
 | |
| class AwaitException(Exception):
 | |
|     pass
 | |
| 
 | |
| 
 | |
| @types.coroutine
 | |
| def awaitable(*, throw=False):
 | |
|     if throw:
 | |
|         yield ('throw',)
 | |
|     else:
 | |
|         yield ('result',)
 | |
| 
 | |
| 
 | |
| def run_until_complete(coro):
 | |
|     exc = False
 | |
|     while True:
 | |
|         try:
 | |
|             if exc:
 | |
|                 exc = False
 | |
|                 fut = coro.throw(AwaitException)
 | |
|             else:
 | |
|                 fut = coro.send(None)
 | |
|         except StopIteration as ex:
 | |
|             return ex.args[0]
 | |
| 
 | |
|         if fut == ('throw',):
 | |
|             exc = True
 | |
| 
 | |
| 
 | |
| def to_list(gen):
 | |
|     async def iterate():
 | |
|         res = []
 | |
|         async for i in gen:
 | |
|             res.append(i)
 | |
|         return res
 | |
| 
 | |
|     return run_until_complete(iterate())
 | |
| 
 | |
| 
 | |
| class AsyncGenSyntaxTest(unittest.TestCase):
 | |
| 
 | |
|     def test_async_gen_syntax_01(self):
 | |
|         code = '''async def foo():
 | |
|             await abc
 | |
|             yield from 123
 | |
|         '''
 | |
| 
 | |
|         with self.assertRaisesRegex(SyntaxError, 'yield from.*inside async'):
 | |
|             exec(code, {}, {})
 | |
| 
 | |
|     def test_async_gen_syntax_02(self):
 | |
|         code = '''async def foo():
 | |
|             yield from 123
 | |
|         '''
 | |
| 
 | |
|         with self.assertRaisesRegex(SyntaxError, 'yield from.*inside async'):
 | |
|             exec(code, {}, {})
 | |
| 
 | |
|     def test_async_gen_syntax_03(self):
 | |
|         code = '''async def foo():
 | |
|             await abc
 | |
|             yield
 | |
|             return 123
 | |
|         '''
 | |
| 
 | |
|         with self.assertRaisesRegex(SyntaxError, 'return.*value.*async gen'):
 | |
|             exec(code, {}, {})
 | |
| 
 | |
|     def test_async_gen_syntax_04(self):
 | |
|         code = '''async def foo():
 | |
|             yield
 | |
|             return 123
 | |
|         '''
 | |
| 
 | |
|         with self.assertRaisesRegex(SyntaxError, 'return.*value.*async gen'):
 | |
|             exec(code, {}, {})
 | |
| 
 | |
|     def test_async_gen_syntax_05(self):
 | |
|         code = '''async def foo():
 | |
|             if 0:
 | |
|                 yield
 | |
|             return 12
 | |
|         '''
 | |
| 
 | |
|         with self.assertRaisesRegex(SyntaxError, 'return.*value.*async gen'):
 | |
|             exec(code, {}, {})
 | |
| 
 | |
| 
 | |
| class AsyncGenTest(unittest.TestCase):
 | |
| 
 | |
|     def compare_generators(self, sync_gen, async_gen):
 | |
|         def sync_iterate(g):
 | |
|             res = []
 | |
|             while True:
 | |
|                 try:
 | |
|                     res.append(g.__next__())
 | |
|                 except StopIteration:
 | |
|                     res.append('STOP')
 | |
|                     break
 | |
|                 except Exception as ex:
 | |
|                     res.append(str(type(ex)))
 | |
|             return res
 | |
| 
 | |
|         def async_iterate(g):
 | |
|             res = []
 | |
|             while True:
 | |
|                 an = g.__anext__()
 | |
|                 try:
 | |
|                     while True:
 | |
|                         try:
 | |
|                             an.__next__()
 | |
|                         except StopIteration as ex:
 | |
|                             if ex.args:
 | |
|                                 res.append(ex.args[0])
 | |
|                                 break
 | |
|                             else:
 | |
|                                 res.append('EMPTY StopIteration')
 | |
|                                 break
 | |
|                         except StopAsyncIteration:
 | |
|                             raise
 | |
|                         except Exception as ex:
 | |
|                             res.append(str(type(ex)))
 | |
|                             break
 | |
|                 except StopAsyncIteration:
 | |
|                     res.append('STOP')
 | |
|                     break
 | |
|             return res
 | |
| 
 | |
|         sync_gen_result = sync_iterate(sync_gen)
 | |
|         async_gen_result = async_iterate(async_gen)
 | |
|         self.assertEqual(sync_gen_result, async_gen_result)
 | |
|         return async_gen_result
 | |
| 
 | |
|     def test_async_gen_iteration_01(self):
 | |
|         async def gen():
 | |
|             await awaitable()
 | |
|             a = yield 123
 | |
|             self.assertIs(a, None)
 | |
|             await awaitable()
 | |
|             yield 456
 | |
|             await awaitable()
 | |
|             yield 789
 | |
| 
 | |
|         self.assertEqual(to_list(gen()), [123, 456, 789])
 | |
| 
 | |
|     def test_async_gen_iteration_02(self):
 | |
|         async def gen():
 | |
|             await awaitable()
 | |
|             yield 123
 | |
|             await awaitable()
 | |
| 
 | |
|         g = gen()
 | |
|         ai = g.__aiter__()
 | |
| 
 | |
|         an = ai.__anext__()
 | |
|         self.assertEqual(an.__next__(), ('result',))
 | |
| 
 | |
|         try:
 | |
|             an.__next__()
 | |
|         except StopIteration as ex:
 | |
|             self.assertEqual(ex.args[0], 123)
 | |
|         else:
 | |
|             self.fail('StopIteration was not raised')
 | |
| 
 | |
|         an = ai.__anext__()
 | |
|         self.assertEqual(an.__next__(), ('result',))
 | |
| 
 | |
|         try:
 | |
|             an.__next__()
 | |
|         except StopAsyncIteration as ex:
 | |
|             self.assertFalse(ex.args)
 | |
|         else:
 | |
|             self.fail('StopAsyncIteration was not raised')
 | |
| 
 | |
|     def test_async_gen_exception_03(self):
 | |
|         async def gen():
 | |
|             await awaitable()
 | |
|             yield 123
 | |
|             await awaitable(throw=True)
 | |
|             yield 456
 | |
| 
 | |
|         with self.assertRaises(AwaitException):
 | |
|             to_list(gen())
 | |
| 
 | |
|     def test_async_gen_exception_04(self):
 | |
|         async def gen():
 | |
|             await awaitable()
 | |
|             yield 123
 | |
|             1 / 0
 | |
| 
 | |
|         g = gen()
 | |
|         ai = g.__aiter__()
 | |
|         an = ai.__anext__()
 | |
|         self.assertEqual(an.__next__(), ('result',))
 | |
| 
 | |
|         try:
 | |
|             an.__next__()
 | |
|         except StopIteration as ex:
 | |
|             self.assertEqual(ex.args[0], 123)
 | |
|         else:
 | |
|             self.fail('StopIteration was not raised')
 | |
| 
 | |
|         with self.assertRaises(ZeroDivisionError):
 | |
|             ai.__anext__().__next__()
 | |
| 
 | |
|     def test_async_gen_exception_05(self):
 | |
|         async def gen():
 | |
|             yield 123
 | |
|             raise StopAsyncIteration
 | |
| 
 | |
|         with self.assertRaisesRegex(RuntimeError,
 | |
|                                     'async generator.*StopAsyncIteration'):
 | |
|             to_list(gen())
 | |
| 
 | |
|     def test_async_gen_exception_06(self):
 | |
|         async def gen():
 | |
|             yield 123
 | |
|             raise StopIteration
 | |
| 
 | |
|         with self.assertRaisesRegex(RuntimeError,
 | |
|                                     'async generator.*StopIteration'):
 | |
|             to_list(gen())
 | |
| 
 | |
|     def test_async_gen_exception_07(self):
 | |
|         def sync_gen():
 | |
|             try:
 | |
|                 yield 1
 | |
|                 1 / 0
 | |
|             finally:
 | |
|                 yield 2
 | |
|                 yield 3
 | |
| 
 | |
|             yield 100
 | |
| 
 | |
|         async def async_gen():
 | |
|             try:
 | |
|                 yield 1
 | |
|                 1 / 0
 | |
|             finally:
 | |
|                 yield 2
 | |
|                 yield 3
 | |
| 
 | |
|             yield 100
 | |
| 
 | |
|         self.compare_generators(sync_gen(), async_gen())
 | |
| 
 | |
|     def test_async_gen_exception_08(self):
 | |
|         def sync_gen():
 | |
|             try:
 | |
|                 yield 1
 | |
|             finally:
 | |
|                 yield 2
 | |
|                 1 / 0
 | |
|                 yield 3
 | |
| 
 | |
|             yield 100
 | |
| 
 | |
|         async def async_gen():
 | |
|             try:
 | |
|                 yield 1
 | |
|                 await awaitable()
 | |
|             finally:
 | |
|                 await awaitable()
 | |
|                 yield 2
 | |
|                 1 / 0
 | |
|                 yield 3
 | |
| 
 | |
|             yield 100
 | |
| 
 | |
|         self.compare_generators(sync_gen(), async_gen())
 | |
| 
 | |
|     def test_async_gen_exception_09(self):
 | |
|         def sync_gen():
 | |
|             try:
 | |
|                 yield 1
 | |
|                 1 / 0
 | |
|             finally:
 | |
|                 yield 2
 | |
|                 yield 3
 | |
| 
 | |
|             yield 100
 | |
| 
 | |
|         async def async_gen():
 | |
|             try:
 | |
|                 await awaitable()
 | |
|                 yield 1
 | |
|                 1 / 0
 | |
|             finally:
 | |
|                 yield 2
 | |
|                 await awaitable()
 | |
|                 yield 3
 | |
| 
 | |
|             yield 100
 | |
| 
 | |
|         self.compare_generators(sync_gen(), async_gen())
 | |
| 
 | |
|     def test_async_gen_exception_10(self):
 | |
|         async def gen():
 | |
|             yield 123
 | |
|         with self.assertRaisesRegex(TypeError,
 | |
|                                     "non-None value .* async generator"):
 | |
|             gen().__anext__().send(100)
 | |
| 
 | |
|     def test_async_gen_exception_11(self):
 | |
|         def sync_gen():
 | |
|             yield 10
 | |
|             yield 20
 | |
| 
 | |
|         def sync_gen_wrapper():
 | |
|             yield 1
 | |
|             sg = sync_gen()
 | |
|             sg.send(None)
 | |
|             try:
 | |
|                 sg.throw(GeneratorExit())
 | |
|             except GeneratorExit:
 | |
|                 yield 2
 | |
|             yield 3
 | |
| 
 | |
|         async def async_gen():
 | |
|             yield 10
 | |
|             yield 20
 | |
| 
 | |
|         async def async_gen_wrapper():
 | |
|             yield 1
 | |
|             asg = async_gen()
 | |
|             await asg.asend(None)
 | |
|             try:
 | |
|                 await asg.athrow(GeneratorExit())
 | |
|             except GeneratorExit:
 | |
|                 yield 2
 | |
|             yield 3
 | |
| 
 | |
|         self.compare_generators(sync_gen_wrapper(), async_gen_wrapper())
 | |
| 
 | |
|     def test_async_gen_api_01(self):
 | |
|         async def gen():
 | |
|             yield 123
 | |
| 
 | |
|         g = gen()
 | |
| 
 | |
|         self.assertEqual(g.__name__, 'gen')
 | |
|         g.__name__ = '123'
 | |
|         self.assertEqual(g.__name__, '123')
 | |
| 
 | |
|         self.assertIn('.gen', g.__qualname__)
 | |
|         g.__qualname__ = '123'
 | |
|         self.assertEqual(g.__qualname__, '123')
 | |
| 
 | |
|         self.assertIsNone(g.ag_await)
 | |
|         self.assertIsInstance(g.ag_frame, types.FrameType)
 | |
|         self.assertFalse(g.ag_running)
 | |
|         self.assertIsInstance(g.ag_code, types.CodeType)
 | |
| 
 | |
|         self.assertTrue(inspect.isawaitable(g.aclose()))
 | |
| 
 | |
| 
 | |
| class AsyncGenAsyncioTest(unittest.TestCase):
 | |
| 
 | |
|     def setUp(self):
 | |
|         self.loop = asyncio.new_event_loop()
 | |
|         asyncio.set_event_loop(None)
 | |
| 
 | |
|     def tearDown(self):
 | |
|         self.loop.close()
 | |
|         self.loop = None
 | |
|         asyncio.set_event_loop_policy(None)
 | |
| 
 | |
|     async def to_list(self, gen):
 | |
|         res = []
 | |
|         async for i in gen:
 | |
|             res.append(i)
 | |
|         return res
 | |
| 
 | |
|     def test_async_gen_asyncio_01(self):
 | |
|         async def gen():
 | |
|             yield 1
 | |
|             await asyncio.sleep(0.01)
 | |
|             yield 2
 | |
|             await asyncio.sleep(0.01)
 | |
|             return
 | |
|             yield 3
 | |
| 
 | |
|         res = self.loop.run_until_complete(self.to_list(gen()))
 | |
|         self.assertEqual(res, [1, 2])
 | |
| 
 | |
|     def test_async_gen_asyncio_02(self):
 | |
|         async def gen():
 | |
|             yield 1
 | |
|             await asyncio.sleep(0.01)
 | |
|             yield 2
 | |
|             1 / 0
 | |
|             yield 3
 | |
| 
 | |
|         with self.assertRaises(ZeroDivisionError):
 | |
|             self.loop.run_until_complete(self.to_list(gen()))
 | |
| 
 | |
|     def test_async_gen_asyncio_03(self):
 | |
|         loop = self.loop
 | |
| 
 | |
|         class Gen:
 | |
|             async def __aiter__(self):
 | |
|                 yield 1
 | |
|                 await asyncio.sleep(0.01)
 | |
|                 yield 2
 | |
| 
 | |
|         res = loop.run_until_complete(self.to_list(Gen()))
 | |
|         self.assertEqual(res, [1, 2])
 | |
| 
 | |
|     def test_async_gen_asyncio_anext_04(self):
 | |
|         async def foo():
 | |
|             yield 1
 | |
|             await asyncio.sleep(0.01)
 | |
|             try:
 | |
|                 yield 2
 | |
|                 yield 3
 | |
|             except ZeroDivisionError:
 | |
|                 yield 1000
 | |
|             await asyncio.sleep(0.01)
 | |
|             yield 4
 | |
| 
 | |
|         async def run1():
 | |
|             it = foo().__aiter__()
 | |
| 
 | |
|             self.assertEqual(await it.__anext__(), 1)
 | |
|             self.assertEqual(await it.__anext__(), 2)
 | |
|             self.assertEqual(await it.__anext__(), 3)
 | |
|             self.assertEqual(await it.__anext__(), 4)
 | |
|             with self.assertRaises(StopAsyncIteration):
 | |
|                 await it.__anext__()
 | |
|             with self.assertRaises(StopAsyncIteration):
 | |
|                 await it.__anext__()
 | |
| 
 | |
|         async def run2():
 | |
|             it = foo().__aiter__()
 | |
| 
 | |
|             self.assertEqual(await it.__anext__(), 1)
 | |
|             self.assertEqual(await it.__anext__(), 2)
 | |
|             try:
 | |
|                 it.__anext__().throw(ZeroDivisionError)
 | |
|             except StopIteration as ex:
 | |
|                 self.assertEqual(ex.args[0], 1000)
 | |
|             else:
 | |
|                 self.fail('StopIteration was not raised')
 | |
|             self.assertEqual(await it.__anext__(), 4)
 | |
|             with self.assertRaises(StopAsyncIteration):
 | |
|                 await it.__anext__()
 | |
| 
 | |
|         self.loop.run_until_complete(run1())
 | |
|         self.loop.run_until_complete(run2())
 | |
| 
 | |
|     def test_async_gen_asyncio_anext_05(self):
 | |
|         async def foo():
 | |
|             v = yield 1
 | |
|             v = yield v
 | |
|             yield v * 100
 | |
| 
 | |
|         async def run():
 | |
|             it = foo().__aiter__()
 | |
| 
 | |
|             try:
 | |
|                 it.__anext__().send(None)
 | |
|             except StopIteration as ex:
 | |
|                 self.assertEqual(ex.args[0], 1)
 | |
|             else:
 | |
|                 self.fail('StopIteration was not raised')
 | |
| 
 | |
|             try:
 | |
|                 it.__anext__().send(10)
 | |
|             except StopIteration as ex:
 | |
|                 self.assertEqual(ex.args[0], 10)
 | |
|             else:
 | |
|                 self.fail('StopIteration was not raised')
 | |
| 
 | |
|             try:
 | |
|                 it.__anext__().send(12)
 | |
|             except StopIteration as ex:
 | |
|                 self.assertEqual(ex.args[0], 1200)
 | |
|             else:
 | |
|                 self.fail('StopIteration was not raised')
 | |
| 
 | |
|             with self.assertRaises(StopAsyncIteration):
 | |
|                 await it.__anext__()
 | |
| 
 | |
|         self.loop.run_until_complete(run())
 | |
| 
 | |
|     def test_async_gen_asyncio_anext_06(self):
 | |
|         DONE = 0
 | |
| 
 | |
|         # test synchronous generators
 | |
|         def foo():
 | |
|             try:
 | |
|                 yield
 | |
|             except:
 | |
|                 pass
 | |
|         g = foo()
 | |
|         g.send(None)
 | |
|         with self.assertRaises(StopIteration):
 | |
|             g.send(None)
 | |
| 
 | |
|         # now with asynchronous generators
 | |
| 
 | |
|         async def gen():
 | |
|             nonlocal DONE
 | |
|             try:
 | |
|                 yield
 | |
|             except:
 | |
|                 pass
 | |
|             DONE = 1
 | |
| 
 | |
|         async def run():
 | |
|             nonlocal DONE
 | |
|             g = gen()
 | |
|             await g.asend(None)
 | |
|             with self.assertRaises(StopAsyncIteration):
 | |
|                 await g.asend(None)
 | |
|             DONE += 10
 | |
| 
 | |
|         self.loop.run_until_complete(run())
 | |
|         self.assertEqual(DONE, 11)
 | |
| 
 | |
|     def test_async_gen_asyncio_anext_tuple(self):
 | |
|         async def foo():
 | |
|             try:
 | |
|                 yield (1,)
 | |
|             except ZeroDivisionError:
 | |
|                 yield (2,)
 | |
| 
 | |
|         async def run():
 | |
|             it = foo().__aiter__()
 | |
| 
 | |
|             self.assertEqual(await it.__anext__(), (1,))
 | |
|             with self.assertRaises(StopIteration) as cm:
 | |
|                 it.__anext__().throw(ZeroDivisionError)
 | |
|             self.assertEqual(cm.exception.args[0], (2,))
 | |
|             with self.assertRaises(StopAsyncIteration):
 | |
|                 await it.__anext__()
 | |
| 
 | |
|         self.loop.run_until_complete(run())
 | |
| 
 | |
|     def test_async_gen_asyncio_anext_stopiteration(self):
 | |
|         async def foo():
 | |
|             try:
 | |
|                 yield StopIteration(1)
 | |
|             except ZeroDivisionError:
 | |
|                 yield StopIteration(3)
 | |
| 
 | |
|         async def run():
 | |
|             it = foo().__aiter__()
 | |
| 
 | |
|             v = await it.__anext__()
 | |
|             self.assertIsInstance(v, StopIteration)
 | |
|             self.assertEqual(v.value, 1)
 | |
|             with self.assertRaises(StopIteration) as cm:
 | |
|                 it.__anext__().throw(ZeroDivisionError)
 | |
|             v = cm.exception.args[0]
 | |
|             self.assertIsInstance(v, StopIteration)
 | |
|             self.assertEqual(v.value, 3)
 | |
|             with self.assertRaises(StopAsyncIteration):
 | |
|                 await it.__anext__()
 | |
| 
 | |
|         self.loop.run_until_complete(run())
 | |
| 
 | |
|     def test_async_gen_asyncio_aclose_06(self):
 | |
|         async def foo():
 | |
|             try:
 | |
|                 yield 1
 | |
|                 1 / 0
 | |
|             finally:
 | |
|                 await asyncio.sleep(0.01)
 | |
|                 yield 12
 | |
| 
 | |
|         async def run():
 | |
|             gen = foo()
 | |
|             it = gen.__aiter__()
 | |
|             await it.__anext__()
 | |
|             await gen.aclose()
 | |
| 
 | |
|         with self.assertRaisesRegex(
 | |
|                 RuntimeError,
 | |
|                 "async generator ignored GeneratorExit"):
 | |
|             self.loop.run_until_complete(run())
 | |
| 
 | |
|     def test_async_gen_asyncio_aclose_07(self):
 | |
|         DONE = 0
 | |
| 
 | |
|         async def foo():
 | |
|             nonlocal DONE
 | |
|             try:
 | |
|                 yield 1
 | |
|                 1 / 0
 | |
|             finally:
 | |
|                 await asyncio.sleep(0.01)
 | |
|                 await asyncio.sleep(0.01)
 | |
|                 DONE += 1
 | |
|             DONE += 1000
 | |
| 
 | |
|         async def run():
 | |
|             gen = foo()
 | |
|             it = gen.__aiter__()
 | |
|             await it.__anext__()
 | |
|             await gen.aclose()
 | |
| 
 | |
|         self.loop.run_until_complete(run())
 | |
|         self.assertEqual(DONE, 1)
 | |
| 
 | |
|     def test_async_gen_asyncio_aclose_08(self):
 | |
|         DONE = 0
 | |
| 
 | |
|         fut = asyncio.Future(loop=self.loop)
 | |
| 
 | |
|         async def foo():
 | |
|             nonlocal DONE
 | |
|             try:
 | |
|                 yield 1
 | |
|                 await fut
 | |
|                 DONE += 1000
 | |
|                 yield 2
 | |
|             finally:
 | |
|                 await asyncio.sleep(0.01)
 | |
|                 await asyncio.sleep(0.01)
 | |
|                 DONE += 1
 | |
|             DONE += 1000
 | |
| 
 | |
|         async def run():
 | |
|             gen = foo()
 | |
|             it = gen.__aiter__()
 | |
|             self.assertEqual(await it.__anext__(), 1)
 | |
|             await gen.aclose()
 | |
| 
 | |
|         self.loop.run_until_complete(run())
 | |
|         self.assertEqual(DONE, 1)
 | |
| 
 | |
|         # Silence ResourceWarnings
 | |
|         fut.cancel()
 | |
|         self.loop.run_until_complete(asyncio.sleep(0.01))
 | |
| 
 | |
|     def test_async_gen_asyncio_gc_aclose_09(self):
 | |
|         DONE = 0
 | |
| 
 | |
|         async def gen():
 | |
|             nonlocal DONE
 | |
|             try:
 | |
|                 while True:
 | |
|                     yield 1
 | |
|             finally:
 | |
|                 await asyncio.sleep(0.01)
 | |
|                 await asyncio.sleep(0.01)
 | |
|                 DONE = 1
 | |
| 
 | |
|         async def run():
 | |
|             g = gen()
 | |
|             await g.__anext__()
 | |
|             await g.__anext__()
 | |
|             del g
 | |
| 
 | |
|             await asyncio.sleep(0.1)
 | |
| 
 | |
|         self.loop.run_until_complete(run())
 | |
|         self.assertEqual(DONE, 1)
 | |
| 
 | |
|     def test_async_gen_asyncio_aclose_10(self):
 | |
|         DONE = 0
 | |
| 
 | |
|         # test synchronous generators
 | |
|         def foo():
 | |
|             try:
 | |
|                 yield
 | |
|             except:
 | |
|                 pass
 | |
|         g = foo()
 | |
|         g.send(None)
 | |
|         g.close()
 | |
| 
 | |
|         # now with asynchronous generators
 | |
| 
 | |
|         async def gen():
 | |
|             nonlocal DONE
 | |
|             try:
 | |
|                 yield
 | |
|             except:
 | |
|                 pass
 | |
|             DONE = 1
 | |
| 
 | |
|         async def run():
 | |
|             nonlocal DONE
 | |
|             g = gen()
 | |
|             await g.asend(None)
 | |
|             await g.aclose()
 | |
|             DONE += 10
 | |
| 
 | |
|         self.loop.run_until_complete(run())
 | |
|         self.assertEqual(DONE, 11)
 | |
| 
 | |
|     def test_async_gen_asyncio_aclose_11(self):
 | |
|         DONE = 0
 | |
| 
 | |
|         # test synchronous generators
 | |
|         def foo():
 | |
|             try:
 | |
|                 yield
 | |
|             except:
 | |
|                 pass
 | |
|             yield
 | |
|         g = foo()
 | |
|         g.send(None)
 | |
|         with self.assertRaisesRegex(RuntimeError, 'ignored GeneratorExit'):
 | |
|             g.close()
 | |
| 
 | |
|         # now with asynchronous generators
 | |
| 
 | |
|         async def gen():
 | |
|             nonlocal DONE
 | |
|             try:
 | |
|                 yield
 | |
|             except:
 | |
|                 pass
 | |
|             yield
 | |
|             DONE += 1
 | |
| 
 | |
|         async def run():
 | |
|             nonlocal DONE
 | |
|             g = gen()
 | |
|             await g.asend(None)
 | |
|             with self.assertRaisesRegex(RuntimeError, 'ignored GeneratorExit'):
 | |
|                 await g.aclose()
 | |
|             DONE += 10
 | |
| 
 | |
|         self.loop.run_until_complete(run())
 | |
|         self.assertEqual(DONE, 10)
 | |
| 
 | |
|     def test_async_gen_asyncio_aclose_12(self):
 | |
|         DONE = 0
 | |
| 
 | |
|         async def target():
 | |
|             await asyncio.sleep(0.01)
 | |
|             1 / 0
 | |
| 
 | |
|         async def foo():
 | |
|             nonlocal DONE
 | |
|             task = asyncio.create_task(target())
 | |
|             try:
 | |
|                 yield 1
 | |
|             finally:
 | |
|                 try:
 | |
|                     await task
 | |
|                 except ZeroDivisionError:
 | |
|                     DONE = 1
 | |
| 
 | |
|         async def run():
 | |
|             gen = foo()
 | |
|             it = gen.__aiter__()
 | |
|             await it.__anext__()
 | |
|             await gen.aclose()
 | |
| 
 | |
|         self.loop.run_until_complete(run())
 | |
|         self.assertEqual(DONE, 1)
 | |
| 
 | |
|     def test_async_gen_asyncio_asend_01(self):
 | |
|         DONE = 0
 | |
| 
 | |
|         # Sanity check:
 | |
|         def sgen():
 | |
|             v = yield 1
 | |
|             yield v * 2
 | |
|         sg = sgen()
 | |
|         v = sg.send(None)
 | |
|         self.assertEqual(v, 1)
 | |
|         v = sg.send(100)
 | |
|         self.assertEqual(v, 200)
 | |
| 
 | |
|         async def gen():
 | |
|             nonlocal DONE
 | |
|             try:
 | |
|                 await asyncio.sleep(0.01)
 | |
|                 v = yield 1
 | |
|                 await asyncio.sleep(0.01)
 | |
|                 yield v * 2
 | |
|                 await asyncio.sleep(0.01)
 | |
|                 return
 | |
|             finally:
 | |
|                 await asyncio.sleep(0.01)
 | |
|                 await asyncio.sleep(0.01)
 | |
|                 DONE = 1
 | |
| 
 | |
|         async def run():
 | |
|             g = gen()
 | |
| 
 | |
|             v = await g.asend(None)
 | |
|             self.assertEqual(v, 1)
 | |
| 
 | |
|             v = await g.asend(100)
 | |
|             self.assertEqual(v, 200)
 | |
| 
 | |
|             with self.assertRaises(StopAsyncIteration):
 | |
|                 await g.asend(None)
 | |
| 
 | |
|         self.loop.run_until_complete(run())
 | |
|         self.assertEqual(DONE, 1)
 | |
| 
 | |
|     def test_async_gen_asyncio_asend_02(self):
 | |
|         DONE = 0
 | |
| 
 | |
|         async def sleep_n_crash(delay):
 | |
|             await asyncio.sleep(delay)
 | |
|             1 / 0
 | |
| 
 | |
|         async def gen():
 | |
|             nonlocal DONE
 | |
|             try:
 | |
|                 await asyncio.sleep(0.01)
 | |
|                 v = yield 1
 | |
|                 await sleep_n_crash(0.01)
 | |
|                 DONE += 1000
 | |
|                 yield v * 2
 | |
|             finally:
 | |
|                 await asyncio.sleep(0.01)
 | |
|                 await asyncio.sleep(0.01)
 | |
|                 DONE = 1
 | |
| 
 | |
|         async def run():
 | |
|             g = gen()
 | |
| 
 | |
|             v = await g.asend(None)
 | |
|             self.assertEqual(v, 1)
 | |
| 
 | |
|             await g.asend(100)
 | |
| 
 | |
|         with self.assertRaises(ZeroDivisionError):
 | |
|             self.loop.run_until_complete(run())
 | |
|         self.assertEqual(DONE, 1)
 | |
| 
 | |
|     def test_async_gen_asyncio_asend_03(self):
 | |
|         DONE = 0
 | |
| 
 | |
|         async def sleep_n_crash(delay):
 | |
|             fut = asyncio.ensure_future(asyncio.sleep(delay),
 | |
|                                         loop=self.loop)
 | |
|             self.loop.call_later(delay / 2, lambda: fut.cancel())
 | |
|             return await fut
 | |
| 
 | |
|         async def gen():
 | |
|             nonlocal DONE
 | |
|             try:
 | |
|                 await asyncio.sleep(0.01)
 | |
|                 v = yield 1
 | |
|                 await sleep_n_crash(0.01)
 | |
|                 DONE += 1000
 | |
|                 yield v * 2
 | |
|             finally:
 | |
|                 await asyncio.sleep(0.01)
 | |
|                 await asyncio.sleep(0.01)
 | |
|                 DONE = 1
 | |
| 
 | |
|         async def run():
 | |
|             g = gen()
 | |
| 
 | |
|             v = await g.asend(None)
 | |
|             self.assertEqual(v, 1)
 | |
| 
 | |
|             await g.asend(100)
 | |
| 
 | |
|         with self.assertRaises(asyncio.CancelledError):
 | |
|             self.loop.run_until_complete(run())
 | |
|         self.assertEqual(DONE, 1)
 | |
| 
 | |
|     def test_async_gen_asyncio_athrow_01(self):
 | |
|         DONE = 0
 | |
| 
 | |
|         class FooEr(Exception):
 | |
|             pass
 | |
| 
 | |
|         # Sanity check:
 | |
|         def sgen():
 | |
|             try:
 | |
|                 v = yield 1
 | |
|             except FooEr:
 | |
|                 v = 1000
 | |
|             yield v * 2
 | |
|         sg = sgen()
 | |
|         v = sg.send(None)
 | |
|         self.assertEqual(v, 1)
 | |
|         v = sg.throw(FooEr)
 | |
|         self.assertEqual(v, 2000)
 | |
|         with self.assertRaises(StopIteration):
 | |
|             sg.send(None)
 | |
| 
 | |
|         async def gen():
 | |
|             nonlocal DONE
 | |
|             try:
 | |
|                 await asyncio.sleep(0.01)
 | |
|                 try:
 | |
|                     v = yield 1
 | |
|                 except FooEr:
 | |
|                     v = 1000
 | |
|                     await asyncio.sleep(0.01)
 | |
|                 yield v * 2
 | |
|                 await asyncio.sleep(0.01)
 | |
|                 # return
 | |
|             finally:
 | |
|                 await asyncio.sleep(0.01)
 | |
|                 await asyncio.sleep(0.01)
 | |
|                 DONE = 1
 | |
| 
 | |
|         async def run():
 | |
|             g = gen()
 | |
| 
 | |
|             v = await g.asend(None)
 | |
|             self.assertEqual(v, 1)
 | |
| 
 | |
|             v = await g.athrow(FooEr)
 | |
|             self.assertEqual(v, 2000)
 | |
| 
 | |
|             with self.assertRaises(StopAsyncIteration):
 | |
|                 await g.asend(None)
 | |
| 
 | |
|         self.loop.run_until_complete(run())
 | |
|         self.assertEqual(DONE, 1)
 | |
| 
 | |
|     def test_async_gen_asyncio_athrow_02(self):
 | |
|         DONE = 0
 | |
| 
 | |
|         class FooEr(Exception):
 | |
|             pass
 | |
| 
 | |
|         async def sleep_n_crash(delay):
 | |
|             fut = asyncio.ensure_future(asyncio.sleep(delay),
 | |
|                                         loop=self.loop)
 | |
|             self.loop.call_later(delay / 2, lambda: fut.cancel())
 | |
|             return await fut
 | |
| 
 | |
|         async def gen():
 | |
|             nonlocal DONE
 | |
|             try:
 | |
|                 await asyncio.sleep(0.01)
 | |
|                 try:
 | |
|                     v = yield 1
 | |
|                 except FooEr:
 | |
|                     await sleep_n_crash(0.01)
 | |
|                 yield v * 2
 | |
|                 await asyncio.sleep(0.01)
 | |
|                 # return
 | |
|             finally:
 | |
|                 await asyncio.sleep(0.01)
 | |
|                 await asyncio.sleep(0.01)
 | |
|                 DONE = 1
 | |
| 
 | |
|         async def run():
 | |
|             g = gen()
 | |
| 
 | |
|             v = await g.asend(None)
 | |
|             self.assertEqual(v, 1)
 | |
| 
 | |
|             try:
 | |
|                 await g.athrow(FooEr)
 | |
|             except asyncio.CancelledError:
 | |
|                 self.assertEqual(DONE, 1)
 | |
|                 raise
 | |
|             else:
 | |
|                 self.fail('CancelledError was not raised')
 | |
| 
 | |
|         with self.assertRaises(asyncio.CancelledError):
 | |
|             self.loop.run_until_complete(run())
 | |
|         self.assertEqual(DONE, 1)
 | |
| 
 | |
|     def test_async_gen_asyncio_athrow_03(self):
 | |
|         DONE = 0
 | |
| 
 | |
|         # test synchronous generators
 | |
|         def foo():
 | |
|             try:
 | |
|                 yield
 | |
|             except:
 | |
|                 pass
 | |
|         g = foo()
 | |
|         g.send(None)
 | |
|         with self.assertRaises(StopIteration):
 | |
|             g.throw(ValueError)
 | |
| 
 | |
|         # now with asynchronous generators
 | |
| 
 | |
|         async def gen():
 | |
|             nonlocal DONE
 | |
|             try:
 | |
|                 yield
 | |
|             except:
 | |
|                 pass
 | |
|             DONE = 1
 | |
| 
 | |
|         async def run():
 | |
|             nonlocal DONE
 | |
|             g = gen()
 | |
|             await g.asend(None)
 | |
|             with self.assertRaises(StopAsyncIteration):
 | |
|                 await g.athrow(ValueError)
 | |
|             DONE += 10
 | |
| 
 | |
|         self.loop.run_until_complete(run())
 | |
|         self.assertEqual(DONE, 11)
 | |
| 
 | |
|     def test_async_gen_asyncio_athrow_tuple(self):
 | |
|         async def gen():
 | |
|             try:
 | |
|                 yield 1
 | |
|             except ZeroDivisionError:
 | |
|                 yield (2,)
 | |
| 
 | |
|         async def run():
 | |
|             g = gen()
 | |
|             v = await g.asend(None)
 | |
|             self.assertEqual(v, 1)
 | |
|             v = await g.athrow(ZeroDivisionError)
 | |
|             self.assertEqual(v, (2,))
 | |
|             with self.assertRaises(StopAsyncIteration):
 | |
|                 await g.asend(None)
 | |
| 
 | |
|         self.loop.run_until_complete(run())
 | |
| 
 | |
|     def test_async_gen_asyncio_athrow_stopiteration(self):
 | |
|         async def gen():
 | |
|             try:
 | |
|                 yield 1
 | |
|             except ZeroDivisionError:
 | |
|                 yield StopIteration(2)
 | |
| 
 | |
|         async def run():
 | |
|             g = gen()
 | |
|             v = await g.asend(None)
 | |
|             self.assertEqual(v, 1)
 | |
|             v = await g.athrow(ZeroDivisionError)
 | |
|             self.assertIsInstance(v, StopIteration)
 | |
|             self.assertEqual(v.value, 2)
 | |
|             with self.assertRaises(StopAsyncIteration):
 | |
|                 await g.asend(None)
 | |
| 
 | |
|         self.loop.run_until_complete(run())
 | |
| 
 | |
|     def test_async_gen_asyncio_shutdown_01(self):
 | |
|         finalized = 0
 | |
| 
 | |
|         async def waiter(timeout):
 | |
|             nonlocal finalized
 | |
|             try:
 | |
|                 await asyncio.sleep(timeout)
 | |
|                 yield 1
 | |
|             finally:
 | |
|                 await asyncio.sleep(0)
 | |
|                 finalized += 1
 | |
| 
 | |
|         async def wait():
 | |
|             async for _ in waiter(1):
 | |
|                 pass
 | |
| 
 | |
|         t1 = self.loop.create_task(wait())
 | |
|         t2 = self.loop.create_task(wait())
 | |
| 
 | |
|         self.loop.run_until_complete(asyncio.sleep(0.1))
 | |
| 
 | |
|         # Silence warnings
 | |
|         t1.cancel()
 | |
|         t2.cancel()
 | |
| 
 | |
|         with self.assertRaises(asyncio.CancelledError):
 | |
|             self.loop.run_until_complete(t1)
 | |
|         with self.assertRaises(asyncio.CancelledError):
 | |
|             self.loop.run_until_complete(t2)
 | |
| 
 | |
|         self.loop.run_until_complete(self.loop.shutdown_asyncgens())
 | |
| 
 | |
|         self.assertEqual(finalized, 2)
 | |
| 
 | |
|     def test_async_gen_expression_01(self):
 | |
|         async def arange(n):
 | |
|             for i in range(n):
 | |
|                 await asyncio.sleep(0.01)
 | |
|                 yield i
 | |
| 
 | |
|         def make_arange(n):
 | |
|             # This syntax is legal starting with Python 3.7
 | |
|             return (i * 2 async for i in arange(n))
 | |
| 
 | |
|         async def run():
 | |
|             return [i async for i in make_arange(10)]
 | |
| 
 | |
|         res = self.loop.run_until_complete(run())
 | |
|         self.assertEqual(res, [i * 2 for i in range(10)])
 | |
| 
 | |
|     def test_async_gen_expression_02(self):
 | |
|         async def wrap(n):
 | |
|             await asyncio.sleep(0.01)
 | |
|             return n
 | |
| 
 | |
|         def make_arange(n):
 | |
|             # This syntax is legal starting with Python 3.7
 | |
|             return (i * 2 for i in range(n) if await wrap(i))
 | |
| 
 | |
|         async def run():
 | |
|             return [i async for i in make_arange(10)]
 | |
| 
 | |
|         res = self.loop.run_until_complete(run())
 | |
|         self.assertEqual(res, [i * 2 for i in range(1, 10)])
 | |
| 
 | |
|     def test_asyncgen_nonstarted_hooks_are_cancellable(self):
 | |
|         # See https://bugs.python.org/issue38013
 | |
|         messages = []
 | |
| 
 | |
|         def exception_handler(loop, context):
 | |
|             messages.append(context)
 | |
| 
 | |
|         async def async_iterate():
 | |
|             yield 1
 | |
|             yield 2
 | |
| 
 | |
|         async def main():
 | |
|             loop = asyncio.get_running_loop()
 | |
|             loop.set_exception_handler(exception_handler)
 | |
| 
 | |
|             async for i in async_iterate():
 | |
|                 break
 | |
| 
 | |
|         asyncio.run(main())
 | |
| 
 | |
|         self.assertEqual([], messages)
 | |
| 
 | |
|     def test_async_gen_await_same_anext_coro_twice(self):
 | |
|         async def async_iterate():
 | |
|             yield 1
 | |
|             yield 2
 | |
| 
 | |
|         async def run():
 | |
|             it = async_iterate()
 | |
|             nxt = it.__anext__()
 | |
|             await nxt
 | |
|             with self.assertRaisesRegex(
 | |
|                     RuntimeError,
 | |
|                     r"cannot reuse already awaited __anext__\(\)/asend\(\)"
 | |
|             ):
 | |
|                 await nxt
 | |
| 
 | |
|             await it.aclose()  # prevent unfinished iterator warning
 | |
| 
 | |
|         self.loop.run_until_complete(run())
 | |
| 
 | |
|     def test_async_gen_await_same_aclose_coro_twice(self):
 | |
|         async def async_iterate():
 | |
|             yield 1
 | |
|             yield 2
 | |
| 
 | |
|         async def run():
 | |
|             it = async_iterate()
 | |
|             nxt = it.aclose()
 | |
|             await nxt
 | |
|             with self.assertRaisesRegex(
 | |
|                     RuntimeError,
 | |
|                     r"cannot reuse already awaited aclose\(\)/athrow\(\)"
 | |
|             ):
 | |
|                 await nxt
 | |
| 
 | |
|         self.loop.run_until_complete(run())
 | |
| 
 | |
|     def test_async_gen_aclose_twice_with_different_coros(self):
 | |
|         # Regression test for https://bugs.python.org/issue39606
 | |
|         async def async_iterate():
 | |
|             yield 1
 | |
|             yield 2
 | |
| 
 | |
|         async def run():
 | |
|             it = async_iterate()
 | |
|             await it.aclose()
 | |
|             await it.aclose()
 | |
| 
 | |
|         self.loop.run_until_complete(run())
 | |
| 
 | |
|     def test_async_gen_aclose_after_exhaustion(self):
 | |
|         # Regression test for https://bugs.python.org/issue39606
 | |
|         async def async_iterate():
 | |
|             yield 1
 | |
|             yield 2
 | |
| 
 | |
|         async def run():
 | |
|             it = async_iterate()
 | |
|             async for _ in it:
 | |
|                 pass
 | |
|             await it.aclose()
 | |
| 
 | |
|         self.loop.run_until_complete(run())
 | |
| 
 | |
|     def test_async_gen_aclose_compatible_with_get_stack(self):
 | |
|         async def async_generator():
 | |
|             yield object()
 | |
| 
 | |
|         async def run():
 | |
|             ag = async_generator()
 | |
|             asyncio.create_task(ag.aclose())
 | |
|             tasks = asyncio.all_tasks()
 | |
|             for task in tasks:
 | |
|                 # No AttributeError raised
 | |
|                 task.get_stack()
 | |
| 
 | |
|         self.loop.run_until_complete(run())
 | |
| 
 | |
| 
 | |
| if __name__ == "__main__":
 | |
|     unittest.main()
 |