bpo-34790: Remove passing coroutine objects to asyncio.wait() by asvetlov · Pull Request #31964 · python/cpython · GitHub
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 3 additions & 43 deletions Doc/library/asyncio-task.rst
14 changes: 4 additions & 10 deletions Lib/asyncio/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -387,7 +387,7 @@ def create_task(coro, *, name=None, context=None):


async def wait(fs, *, timeout=None, return_when=ALL_COMPLETED):
"""Wait for the Futures and coroutines given by fs to complete.
"""Wait for the Futures or Tasks given by fs to complete.

The fs iterable must not be empty.

Expand All @@ -405,22 +405,16 @@ async def wait(fs, *, timeout=None, return_when=ALL_COMPLETED):
if futures.isfuture(fs) or coroutines.iscoroutine(fs):
raise TypeError(f"expect a list of futures, not {type(fs).__name__}")
if not fs:
raise ValueError('Set of coroutines/Futures is empty.')
raise ValueError('Set of Tasks/Futures is empty.')
if return_when not in (FIRST_COMPLETED, FIRST_EXCEPTION, ALL_COMPLETED):
raise ValueError(f'Invalid return_when value: {return_when}')

loop = events.get_running_loop()

fs = set(fs)

if any(coroutines.iscoroutine(f) for f in fs):
warnings.warn("The explicit passing of coroutine objects to "
"asyncio.wait() is deprecated since Python 3.8, and "
"scheduled for removal in Python 3.11.",
DeprecationWarning, stacklevel=2)

fs = {ensure_future(f, loop=loop) for f in fs}
raise TypeError("Passing coroutines is forbidden, use tasks explicitly.")

loop = events.get_running_loop()
return await _wait(fs, timeout, return_when, loop)


Expand Down
55 changes: 7 additions & 48 deletions Lib/test/test_asyncio/test_tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -997,13 +997,12 @@ def test_wait_duplicate_coroutines(self):

async def coro(s):
return s
c = coro('test')
c = self.loop.create_task(coro('test'))
task = self.new_task(
self.loop,
asyncio.wait([c, c, coro('spam')]))
asyncio.wait([c, c, self.loop.create_task(coro('spam'))]))

with self.assertWarns(DeprecationWarning):
done, pending = self.loop.run_until_complete(task)
done, pending = self.loop.run_until_complete(task)

self.assertFalse(pending)
self.assertEqual(set(f.result() for f in done), {'test', 'spam'})
Expand Down Expand Up @@ -1380,11 +1379,9 @@ def gen():
async def test():
futs = list(asyncio.as_completed(fs))
self.assertEqual(len(futs), 2)
waiter = asyncio.wait(futs)
# Deprecation from passing coros in futs to asyncio.wait()
with self.assertWarns(DeprecationWarning) as cm:
done, pending = await waiter
self.assertEqual(cm.warnings[0].filename, __file__)
done, pending = await asyncio.wait(
[asyncio.ensure_future(fut) for fut in futs]
)
self.assertEqual(set(f.result() for f in done), {'a', 'b'})

loop = self.new_test_loop(gen)
Expand Down Expand Up @@ -1434,21 +1431,6 @@ async def test():

loop.run_until_complete(test())

def test_as_completed_coroutine_use_global_loop(self):
# Deprecated in 3.10
async def coro():
return 42

loop = self.new_test_loop()
asyncio.set_event_loop(loop)
self.addCleanup(asyncio.set_event_loop, None)
futs = asyncio.as_completed([coro()])
with self.assertWarns(DeprecationWarning) as cm:
futs = list(futs)
self.assertEqual(cm.warnings[0].filename, __file__)
self.assertEqual(len(futs), 1)
self.assertEqual(loop.run_until_complete(futs[0]), 42)

def test_sleep(self):

def gen():
Expand Down Expand Up @@ -1751,7 +1733,7 @@ async def inner():
async def outer():
nonlocal proof
with self.assertWarns(DeprecationWarning):
d, p = await asyncio.wait([inner()])
d, p = await asyncio.wait([asyncio.create_task(inner())])
proof += 100

f = asyncio.ensure_future(outer(), loop=self.loop)
Expand Down Expand Up @@ -3220,29 +3202,6 @@ async def coro():
self.assertEqual(result, 11)


class WaitTests(test_utils.TestCase):
def setUp(self):
super().setUp()
self.loop = asyncio.new_event_loop()
self.set_event_loop(self.loop)

def tearDown(self):
self.loop.close()
self.loop = None
super().tearDown()

def test_coro_is_deprecated_in_wait(self):
# Remove test when passing coros to asyncio.wait() is removed in 3.11
with self.assertWarns(DeprecationWarning):
self.loop.run_until_complete(
asyncio.wait([coroutine_function()]))

task = self.loop.create_task(coroutine_function())
with self.assertWarns(DeprecationWarning):
self.loop.run_until_complete(
asyncio.wait([task, coroutine_function()]))


class CompatibilityTests(test_utils.TestCase):
# Tests for checking a bridge between old-styled coroutines
# and async/await syntax
Expand Down