Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 43d71e2

Browse files
committed
asyncio: Make ensure_future() accept all kinds of awaitables.
2 parents 987f215 + 620279b commit 43d71e2

4 files changed

Lines changed: 41 additions & 2 deletions

File tree

Doc/whatsnew/3.5.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -803,6 +803,13 @@ Notable changes in the :mod:`asyncio` module since Python 3.4.0:
803803
:class:`asyncio.Queue` class.
804804
(Contributed by Victor Stinner.)
805805

806+
Updates in 3.5.1:
807+
808+
* The :func:`~asyncio.ensure_future` function and all functions that
809+
use it, such as :meth:`loop.run_until_complete() <asyncio.BaseEventLoop.run_until_complete>`,
810+
now accept all kinds of :term:`awaitable objects <awaitable>`.
811+
(Contributed by Yury Selivanov.)
812+
806813

807814
bz2
808815
---

Lib/asyncio/tasks.py

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -512,7 +512,7 @@ def async(coro_or_future, *, loop=None):
512512

513513

514514
def ensure_future(coro_or_future, *, loop=None):
515-
"""Wrap a coroutine in a future.
515+
"""Wrap a coroutine or an awaitable in a future.
516516
517517
If the argument is a Future, it is returned directly.
518518
"""
@@ -527,8 +527,20 @@ def ensure_future(coro_or_future, *, loop=None):
527527
if task._source_traceback:
528528
del task._source_traceback[-1]
529529
return task
530+
elif compat.PY35 and inspect.isawaitable(coro_or_future):
531+
return ensure_future(_wrap_awaitable(coro_or_future), loop=loop)
530532
else:
531-
raise TypeError('A Future or coroutine is required')
533+
raise TypeError('A Future, a coroutine or an awaitable is required')
534+
535+
536+
@coroutine
537+
def _wrap_awaitable(awaitable):
538+
"""Helper for asyncio.ensure_future().
539+
540+
Wraps awaitable (an object with __await__) into a coroutine
541+
that will later be wrapped in a Task by ensure_future().
542+
"""
543+
return (yield from awaitable.__await__())
532544

533545

534546
class _GatheringFuture(futures.Future):

Lib/test/test_asyncio/test_tasks.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,24 @@ def notmuch():
153153
t = asyncio.ensure_future(t_orig, loop=self.loop)
154154
self.assertIs(t, t_orig)
155155

156+
@unittest.skipUnless(PY35, 'need python 3.5 or later')
157+
def test_ensure_future_awaitable(self):
158+
class Aw:
159+
def __init__(self, coro):
160+
self.coro = coro
161+
def __await__(self):
162+
return (yield from self.coro)
163+
164+
@asyncio.coroutine
165+
def coro():
166+
return 'ok'
167+
168+
loop = asyncio.new_event_loop()
169+
self.set_event_loop(loop)
170+
fut = asyncio.ensure_future(Aw(coro()), loop=loop)
171+
loop.run_until_complete(fut)
172+
assert fut.result() == 'ok'
173+
156174
def test_ensure_future_neither(self):
157175
with self.assertRaises(TypeError):
158176
asyncio.ensure_future('ok')

Misc/NEWS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,8 @@ Library
152152
- Issue #23572: Fixed functools.singledispatch on classes with falsy
153153
metaclasses. Patch by Ethan Furman.
154154

155+
- asyncio: ensure_future() now accepts awaitable objects.
156+
155157
IDLE
156158
----
157159

0 commit comments

Comments
 (0)