summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Doc/library/asyncio-task.rst46
-rw-r--r--Lib/asyncio/tasks.py14
-rw-r--r--Lib/test/test_asyncio/test_tasks.py55
-rw-r--r--Misc/NEWS.d/next/Library/2022-03-17-19-38-40.bpo-34790.zQIiVJ.rst1
4 files changed, 15 insertions, 101 deletions
diff --git a/Doc/library/asyncio-task.rst b/Doc/library/asyncio-task.rst
index faf5910..294f5ab 100644
--- a/Doc/library/asyncio-task.rst
+++ b/Doc/library/asyncio-task.rst
@@ -534,7 +534,7 @@ Waiting Primitives
.. coroutinefunction:: wait(aws, *, timeout=None, return_when=ALL_COMPLETED)
- Run :ref:`awaitable objects <asyncio-awaitables>` in the *aws*
+ Run :class:`~asyncio.Future` and :class:`~asyncio.Task` instances in the *aws*
iterable concurrently and block until the condition specified
by *return_when*.
@@ -577,51 +577,11 @@ Waiting Primitives
Unlike :func:`~asyncio.wait_for`, ``wait()`` does not cancel the
futures when a timeout occurs.
- .. deprecated:: 3.8
-
- If any awaitable in *aws* is a coroutine, it is automatically
- scheduled as a Task. Passing coroutines objects to
- ``wait()`` directly is deprecated as it leads to
- :ref:`confusing behavior <asyncio_example_wait_coroutine>`.
-
- .. versionchanged:: 3.10
- Removed the *loop* parameter.
-
- .. _asyncio_example_wait_coroutine:
- .. note::
-
- ``wait()`` schedules coroutines as Tasks automatically and later
- returns those implicitly created Task objects in ``(done, pending)``
- sets. Therefore the following code won't work as expected::
-
- async def foo():
- return 42
-
- coro = foo()
- done, pending = await asyncio.wait({coro})
-
- if coro in done:
- # This branch will never be run!
-
- Here is how the above snippet can be fixed::
-
- async def foo():
- return 42
-
- task = asyncio.create_task(foo())
- done, pending = await asyncio.wait({task})
-
- if task in done:
- # Everything will work as expected now.
-
- .. deprecated-removed:: 3.8 3.11
-
- Passing coroutine objects to ``wait()`` directly is
- deprecated.
-
.. versionchanged:: 3.10
Removed the *loop* parameter.
+ .. versionchanged:: 3.11
+ Passing coroutine objects to ``wait()`` directly is forbidden.
.. function:: as_completed(aws, *, timeout=None)
diff --git a/Lib/asyncio/tasks.py b/Lib/asyncio/tasks.py
index 0b5f322..e876f8d 100644
--- a/Lib/asyncio/tasks.py
+++ b/Lib/asyncio/tasks.py
@@ -387,7 +387,7 @@ ALL_COMPLETED = concurrent.futures.ALL_COMPLETED
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.
@@ -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)
diff --git a/Lib/test/test_asyncio/test_tasks.py b/Lib/test/test_asyncio/test_tasks.py
index 141c019..b86646e 100644
--- a/Lib/test/test_asyncio/test_tasks.py
+++ b/Lib/test/test_asyncio/test_tasks.py
@@ -997,13 +997,12 @@ class BaseTaskTests:
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'})
@@ -1380,11 +1379,9 @@ class BaseTaskTests:
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)
@@ -1434,21 +1431,6 @@ class BaseTaskTests:
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():
@@ -1751,7 +1733,7 @@ class BaseTaskTests:
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)
@@ -3220,29 +3202,6 @@ class SleepTests(test_utils.TestCase):
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
diff --git a/Misc/NEWS.d/next/Library/2022-03-17-19-38-40.bpo-34790.zQIiVJ.rst b/Misc/NEWS.d/next/Library/2022-03-17-19-38-40.bpo-34790.zQIiVJ.rst
new file mode 100644
index 0000000..50a71b5
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2022-03-17-19-38-40.bpo-34790.zQIiVJ.rst
@@ -0,0 +1 @@
+Remove passing coroutine objects to :func:`asyncio.wait`.