From cc672e84cff90668fe7cf5543552c5558f32b88c Mon Sep 17 00:00:00 2001 From: Ron Frederick Date: Sat, 15 Jun 2024 13:43:09 -0700 Subject: [PATCH 01/16] Enhance asyncio.Runner's run() method to accept more object types This commit makes asyncio.Runner's run() method accept the same object types as asyncio.run_until_complete(). Instead of accepting only a coroutine, run() will now accept an awaitable, coroutine, asyncio.Future, or asyncio.Task. --- Lib/asyncio/runners.py | 28 +++++++++++++++++++++++---- Lib/test/test_asyncio/test_runners.py | 25 ++++++++++++++++-------- 2 files changed, 41 insertions(+), 12 deletions(-) diff --git a/Lib/asyncio/runners.py b/Lib/asyncio/runners.py index 1b89236599aad7..1430283c4ee82a 100644 --- a/Lib/asyncio/runners.py +++ b/Lib/asyncio/runners.py @@ -3,11 +3,13 @@ import contextvars import enum import functools +import inspect import threading import signal from . import coroutines from . import events from . import exceptions +from . import futures from . import tasks from . import constants @@ -84,9 +86,13 @@ def get_loop(self): return self._loop def run(self, coro, *, context=None): - """Run a coroutine inside the embedded event loop.""" - if not coroutines.iscoroutine(coro): - raise ValueError("a coroutine was expected, got {!r}".format(coro)) + """Run code in the embedded event loop. + + The argument can be an awaitable, coroutine, Future, or Task. + If the argument is a coroutine, it is wrapped in a Task. + + Return the coro's result or raise an exception. + """ if events._get_running_loop() is not None: # fail fast with short traceback @@ -97,7 +103,21 @@ def run(self, coro, *, context=None): if context is None: context = self._context - task = self._loop.create_task(coro, context=context) + + if futures.isfuture(coro): + # This covers the argument being an asyncio.Future or asyncio.Task + task = coro + elif coroutines.iscoroutine(coro): + task = self._loop.create_task(coro, context=context) + elif inspect.isawaitable(coro): + async def _wrap_awaitable(awaitable): + return await awaitable + + task = _wrap_awaitable(coro) + else: + raise ValueError("An asyncio Future, asyncio.Task, " + "awaitable, or coroutine was expected, " + "got {!r}".format(coro)) if (threading.current_thread() is threading.main_thread() and signal.getsignal(signal.SIGINT) is signal.default_int_handler diff --git a/Lib/test/test_asyncio/test_runners.py b/Lib/test/test_asyncio/test_runners.py index 266f057f0776c3..a4b3974da9b190 100644 --- a/Lib/test/test_asyncio/test_runners.py +++ b/Lib/test/test_asyncio/test_runners.py @@ -94,7 +94,7 @@ def test_asyncio_run_only_coro(self): for o in {1, lambda: None}: with self.subTest(obj=o), \ self.assertRaisesRegex(ValueError, - 'a coroutine was expected'): + 'coroutine was expected'): asyncio.run(o) def test_asyncio_run_debug(self): @@ -320,18 +320,27 @@ def test_run_non_coro(self): with asyncio.Runner() as runner: with self.assertRaisesRegex( ValueError, - "a coroutine was expected" + "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) + fut = runner.get_loop().create_future() + fut.set_result('done') + self.assertEqual('done', runner.run(fut)) + + def test_run_awaitable(self): + class MyAwaitable: + def __await__(self): + return self.run().__await__() + + @staticmethod + async def run(): + return 'done' + + with asyncio.Runner() as runner: + self.assertEqual('done', runner.run(MyAwaitable())) def test_explicit_close(self): runner = asyncio.Runner() From 1b77a642ac1c993f056ba0cdd44bf56e08e83d1e Mon Sep 17 00:00:00 2001 From: "blurb-it[bot]" <43283697+blurb-it[bot]@users.noreply.github.com> Date: Sat, 15 Jun 2024 23:38:37 +0000 Subject: [PATCH 02/16] =?UTF-8?q?=F0=9F=93=9C=F0=9F=A4=96=20Added=20by=20b?= =?UTF-8?q?lurb=5Fit.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../next/Library/2024-06-15-23-38-36.gh-issue-120284.HwsAtY.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 Misc/NEWS.d/next/Library/2024-06-15-23-38-36.gh-issue-120284.HwsAtY.rst diff --git a/Misc/NEWS.d/next/Library/2024-06-15-23-38-36.gh-issue-120284.HwsAtY.rst b/Misc/NEWS.d/next/Library/2024-06-15-23-38-36.gh-issue-120284.HwsAtY.rst new file mode 100644 index 00000000000000..84d76418601e18 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2024-06-15-23-38-36.gh-issue-120284.HwsAtY.rst @@ -0,0 +1 @@ +Make asyncio.Runner's run() method accept the same object types as asyncio.run_until_complete(). Instead of accepting only a coroutine, run() will now accept an awaitable, coroutine, asyncio.Future, or asyncio.Task. From d29906b4c2e6aa7080231fdf57f907b593093389 Mon Sep 17 00:00:00 2001 From: Ron Frederick Date: Sun, 16 Jun 2024 07:10:49 -0700 Subject: [PATCH 03/16] Add RST markup to NEWS entry. --- .../Library/2024-06-15-23-38-36.gh-issue-120284.HwsAtY.rst | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Misc/NEWS.d/next/Library/2024-06-15-23-38-36.gh-issue-120284.HwsAtY.rst b/Misc/NEWS.d/next/Library/2024-06-15-23-38-36.gh-issue-120284.HwsAtY.rst index 84d76418601e18..eaa619eda3abf5 100644 --- a/Misc/NEWS.d/next/Library/2024-06-15-23-38-36.gh-issue-120284.HwsAtY.rst +++ b/Misc/NEWS.d/next/Library/2024-06-15-23-38-36.gh-issue-120284.HwsAtY.rst @@ -1 +1,4 @@ -Make asyncio.Runner's run() method accept the same object types as asyncio.run_until_complete(). Instead of accepting only a coroutine, run() will now accept an awaitable, coroutine, asyncio.Future, or asyncio.Task. +Enhance :meth:`asyncio.Runner.run` to accept the same object types as +:func:`asyncio.run_until_complete`. Instead of accepting only a coroutine, +it now accepts an awaitable, coroutine, :class:`asyncio.Future`, or +:class:`asyncio.Task`. From ca3415320de9ccb2e792de85374ae8334b0be131 Mon Sep 17 00:00:00 2001 From: Ron Frederick Date: Sun, 16 Jun 2024 08:18:49 -0700 Subject: [PATCH 04/16] Fix an incorrect reference in NEWS entry. --- .../Library/2024-06-15-23-38-36.gh-issue-120284.HwsAtY.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Misc/NEWS.d/next/Library/2024-06-15-23-38-36.gh-issue-120284.HwsAtY.rst b/Misc/NEWS.d/next/Library/2024-06-15-23-38-36.gh-issue-120284.HwsAtY.rst index eaa619eda3abf5..d38bd7f7eac69d 100644 --- a/Misc/NEWS.d/next/Library/2024-06-15-23-38-36.gh-issue-120284.HwsAtY.rst +++ b/Misc/NEWS.d/next/Library/2024-06-15-23-38-36.gh-issue-120284.HwsAtY.rst @@ -1,4 +1,4 @@ Enhance :meth:`asyncio.Runner.run` to accept the same object types as -:func:`asyncio.run_until_complete`. Instead of accepting only a coroutine, -it now accepts an awaitable, coroutine, :class:`asyncio.Future`, or -:class:`asyncio.Task`. +:meth:`asyncio.BaseEventLoop.run_until_complete`. Instead of accepting +only a coroutine, it now accepts an awaitable, coroutine, +:class:`asyncio.Future`, or :class:`asyncio.Task`. From be4afa74f4d8adc2fb437e859b0813fd0eda6ddf Mon Sep 17 00:00:00 2001 From: Kumar Aditya Date: Mon, 17 Jun 2024 21:32:10 +0530 Subject: [PATCH 05/16] Update Misc/NEWS.d/next/Library/2024-06-15-23-38-36.gh-issue-120284.HwsAtY.rst --- .../next/Library/2024-06-15-23-38-36.gh-issue-120284.HwsAtY.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Misc/NEWS.d/next/Library/2024-06-15-23-38-36.gh-issue-120284.HwsAtY.rst b/Misc/NEWS.d/next/Library/2024-06-15-23-38-36.gh-issue-120284.HwsAtY.rst index d38bd7f7eac69d..a3e921a7032bac 100644 --- a/Misc/NEWS.d/next/Library/2024-06-15-23-38-36.gh-issue-120284.HwsAtY.rst +++ b/Misc/NEWS.d/next/Library/2024-06-15-23-38-36.gh-issue-120284.HwsAtY.rst @@ -1,4 +1,4 @@ Enhance :meth:`asyncio.Runner.run` to accept the same object types as -:meth:`asyncio.BaseEventLoop.run_until_complete`. Instead of accepting +:meth:`~asyncio.loop.run_until_complete`. Instead of accepting only a coroutine, it now accepts an awaitable, coroutine, :class:`asyncio.Future`, or :class:`asyncio.Task`. From cc56a4ccca236fde37412b05d55f822ee7d164f0 Mon Sep 17 00:00:00 2001 From: Ron Frederick Date: Mon, 17 Jun 2024 22:27:50 -0700 Subject: [PATCH 06/16] Add term markup for awaitable and coroutine in NEWS item --- .../Library/2024-06-15-23-38-36.gh-issue-120284.HwsAtY.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Misc/NEWS.d/next/Library/2024-06-15-23-38-36.gh-issue-120284.HwsAtY.rst b/Misc/NEWS.d/next/Library/2024-06-15-23-38-36.gh-issue-120284.HwsAtY.rst index a3e921a7032bac..641bfcbadca7e1 100644 --- a/Misc/NEWS.d/next/Library/2024-06-15-23-38-36.gh-issue-120284.HwsAtY.rst +++ b/Misc/NEWS.d/next/Library/2024-06-15-23-38-36.gh-issue-120284.HwsAtY.rst @@ -1,4 +1,4 @@ Enhance :meth:`asyncio.Runner.run` to accept the same object types as :meth:`~asyncio.loop.run_until_complete`. Instead of accepting -only a coroutine, it now accepts an awaitable, coroutine, -:class:`asyncio.Future`, or :class:`asyncio.Task`. +only a :term:`coroutine`, it now accepts an :term:`awaitable`, +:term:`coroutine`, :class:`asyncio.Future`, or :class:`asyncio.Task`. From ca74887625594fa29e8e76be58d1b335d28d5682 Mon Sep 17 00:00:00 2001 From: Ron Frederick Date: Fri, 21 Jun 2024 17:26:48 -0700 Subject: [PATCH 07/16] Avoid duplicating code from ensure_future in Runner.run --- Lib/asyncio/runners.py | 17 +---------------- Lib/asyncio/tasks.py | 7 +++++-- Lib/test/test_asyncio/test_runners.py | 8 ++++---- 3 files changed, 10 insertions(+), 22 deletions(-) diff --git a/Lib/asyncio/runners.py b/Lib/asyncio/runners.py index 1430283c4ee82a..64194f3882b19a 100644 --- a/Lib/asyncio/runners.py +++ b/Lib/asyncio/runners.py @@ -3,13 +3,11 @@ import contextvars import enum import functools -import inspect import threading import signal from . import coroutines from . import events from . import exceptions -from . import futures from . import tasks from . import constants @@ -104,20 +102,7 @@ def run(self, coro, *, context=None): if context is None: context = self._context - if futures.isfuture(coro): - # This covers the argument being an asyncio.Future or asyncio.Task - task = coro - elif coroutines.iscoroutine(coro): - task = self._loop.create_task(coro, context=context) - elif inspect.isawaitable(coro): - async def _wrap_awaitable(awaitable): - return await awaitable - - task = _wrap_awaitable(coro) - else: - raise ValueError("An asyncio Future, asyncio.Task, " - "awaitable, or coroutine was expected, " - "got {!r}".format(coro)) + task = tasks.ensure_future(coro, loop=self._loop, context=context) if (threading.current_thread() is threading.main_thread() and signal.getsignal(signal.SIGINT) is signal.default_int_handler diff --git a/Lib/asyncio/tasks.py b/Lib/asyncio/tasks.py index 2112dd4b99d17f..e78756c83792e6 100644 --- a/Lib/asyncio/tasks.py +++ b/Lib/asyncio/tasks.py @@ -705,7 +705,7 @@ async def sleep(delay, result=None): h.cancel() -def ensure_future(coro_or_future, *, loop=None): +def ensure_future(coro_or_future, *, loop=None, context=None): """Wrap a coroutine or an awaitable in a future. If the argument is a Future, it is returned directly. @@ -730,7 +730,10 @@ async def _wrap_awaitable(awaitable): if loop is None: loop = events.get_event_loop() try: - return loop.create_task(coro_or_future) + if context is None: + return loop.create_task(coro_or_future) + else: + return loop.create_task(coro_or_future, context=context) except RuntimeError: if should_close: coro_or_future.close() diff --git a/Lib/test/test_asyncio/test_runners.py b/Lib/test/test_asyncio/test_runners.py index a4b3974da9b190..45f70d09a2083a 100644 --- a/Lib/test/test_asyncio/test_runners.py +++ b/Lib/test/test_asyncio/test_runners.py @@ -93,8 +93,8 @@ async def main(): def test_asyncio_run_only_coro(self): for o in {1, lambda: None}: with self.subTest(obj=o), \ - self.assertRaisesRegex(ValueError, - 'coroutine was expected'): + self.assertRaisesRegex(TypeError, + 'an awaitable is required'): asyncio.run(o) def test_asyncio_run_debug(self): @@ -319,8 +319,8 @@ async def f(): def test_run_non_coro(self): with asyncio.Runner() as runner: with self.assertRaisesRegex( - ValueError, - "coroutine was expected" + TypeError, + "an awaitable is required" ): runner.run(123) From 84ee424c17cf77cd6ba4854a1e559489b32efb2a Mon Sep 17 00:00:00 2001 From: Ron Frederick Date: Tue, 6 Aug 2024 18:10:34 -0700 Subject: [PATCH 08/16] Accept proposed doc change for asyncio/runners.py MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Bénédikt Tran <10796600+picnixz@users.noreply.github.com> --- Lib/asyncio/runners.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Lib/asyncio/runners.py b/Lib/asyncio/runners.py index 64194f3882b19a..d40c4a9a85ef37 100644 --- a/Lib/asyncio/runners.py +++ b/Lib/asyncio/runners.py @@ -86,10 +86,11 @@ def get_loop(self): def run(self, coro, *, context=None): """Run code in the embedded event loop. - The argument can be an awaitable, coroutine, Future, or Task. + The argument can be any awaitable object. + If the argument is a coroutine, it is wrapped in a Task. - Return the coro's result or raise an exception. + Return the awaitable's result or raise an exception. """ if events._get_running_loop() is not None: From 83ad0fe8f6e366b2a786a2d9eb65e2de7eda362e Mon Sep 17 00:00:00 2001 From: Ron Frederick Date: Tue, 6 Aug 2024 18:11:43 -0700 Subject: [PATCH 09/16] Accept proposed change in Misc/NEWS.d/next/Library/2024-06-15-23-38-36.gh-issue-120284.HwsAtY.rst MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Bénédikt Tran <10796600+picnixz@users.noreply.github.com> --- .../Library/2024-06-15-23-38-36.gh-issue-120284.HwsAtY.rst | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/Misc/NEWS.d/next/Library/2024-06-15-23-38-36.gh-issue-120284.HwsAtY.rst b/Misc/NEWS.d/next/Library/2024-06-15-23-38-36.gh-issue-120284.HwsAtY.rst index 641bfcbadca7e1..a2a6883c3d7686 100644 --- a/Misc/NEWS.d/next/Library/2024-06-15-23-38-36.gh-issue-120284.HwsAtY.rst +++ b/Misc/NEWS.d/next/Library/2024-06-15-23-38-36.gh-issue-120284.HwsAtY.rst @@ -1,4 +1,2 @@ -Enhance :meth:`asyncio.Runner.run` to accept the same object types as -:meth:`~asyncio.loop.run_until_complete`. Instead of accepting -only a :term:`coroutine`, it now accepts an :term:`awaitable`, -:term:`coroutine`, :class:`asyncio.Future`, or :class:`asyncio.Task`. +Allow :meth:`asyncio.Runner.run` to accept :term:`awaitable` +objects instead of simply :term:`coroutine`\s. From 365d94616da8333f803bb0dae9794e10e80d1ba3 Mon Sep 17 00:00:00 2001 From: Ron Frederick Date: Tue, 6 Aug 2024 18:41:12 -0700 Subject: [PATCH 10/16] Document new context argument in ensure_future() --- Doc/library/asyncio-future.rst | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Doc/library/asyncio-future.rst b/Doc/library/asyncio-future.rst index 9dce0731411940..abd87c0d073a82 100644 --- a/Doc/library/asyncio-future.rst +++ b/Doc/library/asyncio-future.rst @@ -31,7 +31,7 @@ Future Functions .. versionadded:: 3.5 -.. function:: ensure_future(obj, *, loop=None) +.. function:: ensure_future(obj, *, loop=None, context=None) Return: @@ -49,6 +49,9 @@ Future Functions If *obj* is neither of the above a :exc:`TypeError` is raised. + An optional keyword-only *context* argument allows specifying a + custom :class:`contextvars.Context` to use when creating a new task. + .. important:: See also the :func:`create_task` function which is the @@ -64,6 +67,8 @@ Future Functions Deprecation warning is emitted if *obj* is not a Future-like object and *loop* is not specified and there is no running event loop. + .. versionchanged:: 3.12 + Added the *context* parameter. .. function:: wrap_future(future, *, loop=None) From 78f05ce9de85b456b7fcd842c4ca771cdded747e Mon Sep 17 00:00:00 2001 From: Ron Frederick Date: Tue, 6 Aug 2024 18:46:22 -0700 Subject: [PATCH 11/16] Remove trailing whitespace. --- Lib/asyncio/runners.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/asyncio/runners.py b/Lib/asyncio/runners.py index d40c4a9a85ef37..bcf8e5c22d94b4 100644 --- a/Lib/asyncio/runners.py +++ b/Lib/asyncio/runners.py @@ -87,7 +87,7 @@ def run(self, coro, *, context=None): """Run code in the embedded event loop. The argument can be any awaitable object. - + If the argument is a coroutine, it is wrapped in a Task. Return the awaitable's result or raise an exception. From 6b34b6246f5ef771c306a44c91f90e87dbfdf63a Mon Sep 17 00:00:00 2001 From: Ron Frederick Date: Sat, 17 Aug 2024 07:34:14 -0700 Subject: [PATCH 12/16] Specify what happens in ensure_future with a context of None. --- Doc/library/asyncio-future.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/Doc/library/asyncio-future.rst b/Doc/library/asyncio-future.rst index abd87c0d073a82..889325d9d13383 100644 --- a/Doc/library/asyncio-future.rst +++ b/Doc/library/asyncio-future.rst @@ -51,6 +51,7 @@ Future Functions An optional keyword-only *context* argument allows specifying a custom :class:`contextvars.Context` to use when creating a new task. + A copy of the current context is used when no *context* is provided. .. important:: From 610fb8327d400b795987f741f7c4ca4dde5d07c7 Mon Sep 17 00:00:00 2001 From: Ron Frederick Date: Sat, 14 Sep 2024 11:51:47 -0700 Subject: [PATCH 13/16] Rework solution to address Yuri's review comments This version has reverted the change in ensure_future, and only changes Runner.run(). --- Doc/library/asyncio-future.rst | 8 +------- Lib/asyncio/runners.py | 13 ++++++++++++- Lib/asyncio/tasks.py | 7 ++----- 3 files changed, 15 insertions(+), 13 deletions(-) diff --git a/Doc/library/asyncio-future.rst b/Doc/library/asyncio-future.rst index 889325d9d13383..9dce0731411940 100644 --- a/Doc/library/asyncio-future.rst +++ b/Doc/library/asyncio-future.rst @@ -31,7 +31,7 @@ Future Functions .. versionadded:: 3.5 -.. function:: ensure_future(obj, *, loop=None, context=None) +.. function:: ensure_future(obj, *, loop=None) Return: @@ -49,10 +49,6 @@ Future Functions If *obj* is neither of the above a :exc:`TypeError` is raised. - An optional keyword-only *context* argument allows specifying a - custom :class:`contextvars.Context` to use when creating a new task. - A copy of the current context is used when no *context* is provided. - .. important:: See also the :func:`create_task` function which is the @@ -68,8 +64,6 @@ Future Functions Deprecation warning is emitted if *obj* is not a Future-like object and *loop* is not specified and there is no running event loop. - .. versionchanged:: 3.12 - Added the *context* parameter. .. function:: wrap_future(future, *, loop=None) diff --git a/Lib/asyncio/runners.py b/Lib/asyncio/runners.py index bcf8e5c22d94b4..729dfef6817878 100644 --- a/Lib/asyncio/runners.py +++ b/Lib/asyncio/runners.py @@ -3,6 +3,7 @@ import contextvars import enum import functools +import inspect import threading import signal from . import coroutines @@ -100,10 +101,20 @@ def run(self, coro, *, context=None): self._lazy_init() + if not coroutines.iscoroutine(coro): + if inspect.isawaitable(coro): + async def _wrap_awaitable(awaitable): + return await awaitable + + coro = _wrap_awaitable(coro) + else: + raise TypeError('An asyncio.Future, a coroutine or an ' + 'awaitable is required') + if context is None: context = self._context - task = tasks.ensure_future(coro, loop=self._loop, context=context) + task = self._loop.create_task(coro, context=context) if (threading.current_thread() is threading.main_thread() and signal.getsignal(signal.SIGINT) is signal.default_int_handler diff --git a/Lib/asyncio/tasks.py b/Lib/asyncio/tasks.py index e78756c83792e6..2112dd4b99d17f 100644 --- a/Lib/asyncio/tasks.py +++ b/Lib/asyncio/tasks.py @@ -705,7 +705,7 @@ async def sleep(delay, result=None): h.cancel() -def ensure_future(coro_or_future, *, loop=None, context=None): +def ensure_future(coro_or_future, *, loop=None): """Wrap a coroutine or an awaitable in a future. If the argument is a Future, it is returned directly. @@ -730,10 +730,7 @@ async def _wrap_awaitable(awaitable): if loop is None: loop = events.get_event_loop() try: - if context is None: - return loop.create_task(coro_or_future) - else: - return loop.create_task(coro_or_future, context=context) + return loop.create_task(coro_or_future) except RuntimeError: if should_close: coro_or_future.close() From 787eb8cf26cc3d09d04434e7647a8719f3ab1390 Mon Sep 17 00:00:00 2001 From: Ron Frederick Date: Fri, 20 Sep 2024 19:17:02 -0700 Subject: [PATCH 14/16] Update documentation in asyncio-runner.rst This commit updates the documentation for Runner.run() and asyncio.run() in asyncio-runner.rst. In the process, I removed documentation previously added in runners.py. --- Doc/library/asyncio-runner.rst | 22 ++++++++++++++-------- Lib/asyncio/runners.py | 10 +--------- 2 files changed, 15 insertions(+), 17 deletions(-) diff --git a/Doc/library/asyncio-runner.rst b/Doc/library/asyncio-runner.rst index 8312e55126a7c5..212f417b4df694 100644 --- a/Doc/library/asyncio-runner.rst +++ b/Doc/library/asyncio-runner.rst @@ -24,11 +24,13 @@ Running an asyncio Program .. function:: run(coro, *, debug=None, loop_factory=None) - Execute the :term:`coroutine` *coro* and return the result. + Execute code in an asyncio event loop and return the result. - This function runs the passed coroutine, taking care of - managing the asyncio event loop, *finalizing asynchronous - generators*, and closing the executor. + The argument can be any awaitable object. + + This function runs the awaitable, taking care of managing the + asyncio event loop, *finalizing asynchronous generators*, and + closing the executor. This function cannot be called when another asyncio event loop is running in the same thread. @@ -104,13 +106,17 @@ Runner context manager .. method:: run(coro, *, context=None) - Run a :term:`coroutine ` *coro* in the embedded loop. + Execute code in the embedded event loop. + + The argument can be any awaitable object. - Return the coroutine's result or raise its exception. + If the argument is a coroutine, it is wrapped in a Task. An optional keyword-only *context* argument allows specifying a - custom :class:`contextvars.Context` for the *coro* to run in. - The runner's default context is used if ``None``. + custom :class:`contextvars.Context` for the code to run in. + The runner's default context is used if context is ``None``. + + Returns the awaitable's result or raises an exception. This function cannot be called when another asyncio event loop is running in the same thread. diff --git a/Lib/asyncio/runners.py b/Lib/asyncio/runners.py index 729dfef6817878..0e63c34f60f4d9 100644 --- a/Lib/asyncio/runners.py +++ b/Lib/asyncio/runners.py @@ -85,15 +85,7 @@ def get_loop(self): return self._loop def run(self, coro, *, context=None): - """Run code in the embedded event loop. - - The argument can be any awaitable object. - - If the argument is a coroutine, it is wrapped in a Task. - - Return the awaitable's result or raise an exception. - """ - + """Run code in the embedded event loop.""" if events._get_running_loop() is not None: # fail fast with short traceback raise RuntimeError( From 83dbcba6f554adffd3ee6d49b0c003d337841cfa Mon Sep 17 00:00:00 2001 From: Kumar Aditya Date: Thu, 26 Sep 2024 11:14:45 +0530 Subject: [PATCH 15/16] add versionchanged --- Doc/library/asyncio-runner.rst | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Doc/library/asyncio-runner.rst b/Doc/library/asyncio-runner.rst index 212f417b4df694..7c06c7f7338cc0 100644 --- a/Doc/library/asyncio-runner.rst +++ b/Doc/library/asyncio-runner.rst @@ -72,6 +72,10 @@ Running an asyncio Program Added *loop_factory* parameter. + .. versionchanged:: 3.14 + + *coro* can be any awaitable object. + Runner context manager ====================== @@ -121,6 +125,10 @@ Runner context manager This function cannot be called when another asyncio event loop is running in the same thread. + .. versionchanged:: 3.14 + + *coro* can be any awaitable object. + .. method:: close() Close the runner. From 7cf8cbcd5ee72a422aab8e3652bf75a11e26b1c8 Mon Sep 17 00:00:00 2001 From: Kumar Aditya Date: Thu, 26 Sep 2024 11:18:18 +0530 Subject: [PATCH 16/16] code -> coro --- Doc/library/asyncio-runner.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Doc/library/asyncio-runner.rst b/Doc/library/asyncio-runner.rst index 7c06c7f7338cc0..28d5aaf3692baa 100644 --- a/Doc/library/asyncio-runner.rst +++ b/Doc/library/asyncio-runner.rst @@ -24,7 +24,7 @@ Running an asyncio Program .. function:: run(coro, *, debug=None, loop_factory=None) - Execute code in an asyncio event loop and return the result. + Execute *coro* in an asyncio event loop and return the result. The argument can be any awaitable object. @@ -110,7 +110,7 @@ Runner context manager .. method:: run(coro, *, context=None) - Execute code in the embedded event loop. + Execute *coro* in the embedded event loop. The argument can be any awaitable object.