summaryrefslogtreecommitdiffstats
path: root/Lib/test/test_asyncio
diff options
context:
space:
mode:
authorAndrew Svetlov <andrew.svetlov@gmail.com>2022-03-24 19:51:16 (GMT)
committerGitHub <noreply@github.com>2022-03-24 19:51:16 (GMT)
commit4119d2d7c9e25acd4f16994fb92d656f8b7816d7 (patch)
tree13f5086fc5ad0247381d347c4271a8ca79a20fd7 /Lib/test/test_asyncio
parent2f49b97cc5426087b46515254b9a97a22ee8c807 (diff)
downloadcpython-4119d2d7c9e25acd4f16994fb92d656f8b7816d7.zip
cpython-4119d2d7c9e25acd4f16994fb92d656f8b7816d7.tar.gz
cpython-4119d2d7c9e25acd4f16994fb92d656f8b7816d7.tar.bz2
bpo-47062: Implement asyncio.Runner context manager (GH-31799)
Co-authored-by: Zachary Ware <zach@python.org>
Diffstat (limited to 'Lib/test/test_asyncio')
-rw-r--r--Lib/test/test_asyncio/test_runners.py133
1 files changed, 133 insertions, 0 deletions
diff --git a/Lib/test/test_asyncio/test_runners.py b/Lib/test/test_asyncio/test_runners.py
index 1122736..2919412 100644
--- a/Lib/test/test_asyncio/test_runners.py
+++ b/Lib/test/test_asyncio/test_runners.py
@@ -1,4 +1,7 @@
import asyncio
+import contextvars
+import gc
+import re
import unittest
from unittest import mock
@@ -186,5 +189,135 @@ class RunTests(BaseTest):
self.assertFalse(spinner.ag_running)
+class RunnerTests(BaseTest):
+
+ def test_non_debug(self):
+ with asyncio.Runner(debug=False) as runner:
+ self.assertFalse(runner.get_loop().get_debug())
+
+ def test_debug(self):
+ with asyncio.Runner(debug=True) as runner:
+ self.assertTrue(runner.get_loop().get_debug())
+
+ def test_custom_factory(self):
+ loop = mock.Mock()
+ with asyncio.Runner(factory=lambda: loop) as runner:
+ self.assertIs(runner.get_loop(), loop)
+
+ def test_run(self):
+ async def f():
+ await asyncio.sleep(0)
+ return 'done'
+
+ with asyncio.Runner() as runner:
+ self.assertEqual('done', runner.run(f()))
+ loop = runner.get_loop()
+
+ with self.assertRaisesRegex(
+ RuntimeError,
+ "Runner is closed"
+ ):
+ runner.get_loop()
+
+ self.assertTrue(loop.is_closed())
+
+ def test_run_non_coro(self):
+ with asyncio.Runner() as runner:
+ with self.assertRaisesRegex(
+ ValueError,
+ "a coroutine was expected"
+ ):
+ runner.run(123)
+
+ def test_run_future(self):
+ with asyncio.Runner() as runner:
+ with self.assertRaisesRegex(
+ ValueError,
+ "a coroutine was expected"
+ ):
+ fut = runner.get_loop().create_future()
+ runner.run(fut)
+
+ def test_explicit_close(self):
+ runner = asyncio.Runner()
+ loop = runner.get_loop()
+ runner.close()
+ with self.assertRaisesRegex(
+ RuntimeError,
+ "Runner is closed"
+ ):
+ runner.get_loop()
+
+ self.assertTrue(loop.is_closed())
+
+ def test_double_close(self):
+ runner = asyncio.Runner()
+ loop = runner.get_loop()
+
+ runner.close()
+ self.assertTrue(loop.is_closed())
+
+ # the second call is no-op
+ runner.close()
+ self.assertTrue(loop.is_closed())
+
+ def test_second_with_block_raises(self):
+ ret = []
+
+ async def f(arg):
+ ret.append(arg)
+
+ runner = asyncio.Runner()
+ with runner:
+ runner.run(f(1))
+
+ with self.assertRaisesRegex(
+ RuntimeError,
+ "Runner is closed"
+ ):
+ with runner:
+ runner.run(f(2))
+
+ self.assertEqual([1], ret)
+
+ def test_run_keeps_context(self):
+ cvar = contextvars.ContextVar("cvar", default=-1)
+
+ async def f(val):
+ old = cvar.get()
+ await asyncio.sleep(0)
+ cvar.set(val)
+ return old
+
+ async def get_context():
+ return contextvars.copy_context()
+
+ with asyncio.Runner() as runner:
+ self.assertEqual(-1, runner.run(f(1)))
+ self.assertEqual(1, runner.run(f(2)))
+
+ self.assertEqual({cvar: 2}, dict(runner.run(get_context())))
+
+ def test_recursine_run(self):
+ async def g():
+ pass
+
+ async def f():
+ runner.run(g())
+
+ with asyncio.Runner() as runner:
+ with self.assertWarnsRegex(
+ RuntimeWarning,
+ "coroutine .+ was never awaited",
+ ):
+ with self.assertRaisesRegex(
+ RuntimeError,
+ re.escape(
+ "Runner.run() cannot be called from a running event loop"
+ ),
+ ):
+ runner.run(f())
+
+
if __name__ == '__main__':
unittest.main()