GH-99388: add `loop_factory` parameter to `asyncio.run` (#99462)

This commit is contained in:
Kumar Aditya 2022-11-14 23:48:51 +05:30 committed by GitHub
parent f5e326e2b6
commit f63002755d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 29 additions and 6 deletions

View File

@ -22,7 +22,7 @@ to simplify async code usage for common wide-spread scenarios.
Running an asyncio Program Running an asyncio Program
========================== ==========================
.. function:: run(coro, *, debug=None) .. function:: run(coro, *, debug=None, loop_factory=None)
Execute the :term:`coroutine` *coro* and return the result. Execute the :term:`coroutine` *coro* and return the result.
@ -37,9 +37,11 @@ Running an asyncio Program
debug mode explicitly. ``None`` is used to respect the global debug mode explicitly. ``None`` is used to respect the global
:ref:`asyncio-debug-mode` settings. :ref:`asyncio-debug-mode` settings.
This function always creates a new event loop and closes it at If *loop_factory* is not ``None``, it is used to create a new event loop;
the end. It should be used as a main entry point for asyncio otherwise :func:`asyncio.new_event_loop` is used. The loop is closed at the end.
programs, and should ideally only be called once. This function should be used as a main entry point for asyncio programs,
and should ideally only be called once. It is recommended to use
*loop_factory* to configure the event loop instead of policies.
The executor is given a timeout duration of 5 minutes to shutdown. The executor is given a timeout duration of 5 minutes to shutdown.
If the executor hasn't finished within that duration, a warning is If the executor hasn't finished within that duration, a warning is
@ -62,6 +64,10 @@ Running an asyncio Program
*debug* is ``None`` by default to respect the global debug mode settings. *debug* is ``None`` by default to respect the global debug mode settings.
.. versionchanged:: 3.12
Added *loop_factory* parameter.
Runner context manager Runner context manager
====================== ======================

View File

@ -217,6 +217,11 @@ asyncio
and will be removed in Python 3.14. and will be removed in Python 3.14.
(Contributed by Kumar Aditya in :gh:`94597`.) (Contributed by Kumar Aditya in :gh:`94597`.)
* Add *loop_factory* parameter to :func:`asyncio.run` to allow specifying
a custom event loop factory.
(Contributed by Kumar Aditya in :gh:`99388`.)
pathlib pathlib
------- -------

View File

@ -157,7 +157,7 @@ class Runner:
raise KeyboardInterrupt() raise KeyboardInterrupt()
def run(main, *, debug=None): def run(main, *, debug=None, loop_factory=None):
"""Execute the coroutine and return the result. """Execute the coroutine and return the result.
This function runs the passed coroutine, taking care of This function runs the passed coroutine, taking care of
@ -190,7 +190,7 @@ def run(main, *, debug=None):
raise RuntimeError( raise RuntimeError(
"asyncio.run() cannot be called from a running event loop") "asyncio.run() cannot be called from a running event loop")
with Runner(debug=debug) as runner: with Runner(debug=debug, loop_factory=loop_factory) as runner:
return runner.run(main) return runner.run(main)

View File

@ -257,6 +257,16 @@ class RunTests(BaseTest):
with self.assertRaises(asyncio.CancelledError): with self.assertRaises(asyncio.CancelledError):
asyncio.run(main()) asyncio.run(main())
def test_asyncio_run_loop_factory(self):
factory = mock.Mock()
loop = factory.return_value = self.new_loop()
async def main():
self.assertEqual(asyncio.get_running_loop(), loop)
asyncio.run(main(), loop_factory=factory)
factory.assert_called_once_with()
class RunnerTests(BaseTest): class RunnerTests(BaseTest):

View File

@ -0,0 +1,2 @@
Add *loop_factory* parameter to :func:`asyncio.run` to allow specifying a custom event loop factory.
Patch by Kumar Aditya.