8000 bpo-32610: Fix asyncio.all_tasks() to return only pending tasks. by 1st1 · Pull Request #7174 · python/cpython · GitHub
[go: up one dir, main page]

Skip to content

bpo-32610: Fix asyncio.all_tasks() to return only pending tasks. #7174

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
May 28, 2018
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
7 changes: 5 additions & 2 deletions Doc/library/asyncio-task.rst
8000
Original file line number Diff line number Diff line change
Expand Up @@ -443,6 +443,8 @@ Task
Return a set of all tasks for an event loop.

By default all tasks for the current event loop are returned.
If *loop* is ``None``, :func:`get_event_loop` function
is used to get the current loop.

.. classmethod:: current_task(loop=None)

Expand Down Expand Up @@ -567,8 +569,9 @@ Task functions

Return a set of :class:`Task` objects created for the loop.

If *loop* is ``None`` :func:`get_event_loop` is used for getting
current loop.
If *loop* is ``None``, :func:`get_running_loop` is used for getting
current loop (contrary to the deprecated :meth:`Task.all_tasks` method
that uses :func:`get_event_loop`.)

.. versionadded:: 3.7

Expand Down
4 changes: 4 additions & 0 deletions Lib/asyncio/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@
from .tasks import *
from .transports import *

# Exposed for _asynciomodule.c to implement now deprecated
# Task.all_tasks() method. This function will be removed in 3.9.
from .tasks import _all_tasks_compat # NoQA

__all__ = (base_events.__all__ +
coroutines.__all__ +
events.__all__ +
Expand Down
3 changes: 1 addition & 2 deletions Lib/asyncio/runners.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,7 @@ async def main():


def _cancel_all_tasks(loop):
to_cancel = [task for task in tasks.all_tasks(loop)
if not task.done()]
to_cancel = tasks.all_tasks(loop)
if not to_cancel:
return

Expand Down
12 changes: 11 additions & 1 deletion Lib/asyncio/tasks.py
8000
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,16 @@ def current_task(loop=None):

def all_tasks(loop=None):
"""Return a set of all tasks for the loop."""
if loop is None:
loop = events.get_running_loop()
return {t for t in _all_tasks
if futures._get_loop(t) is loop and not t.done()}


def _all_tasks_compat(loop=None):
# Different from "all_task()" by returning *all* Tasks, including
# the completed ones. Used to implement deprecated "Tasks.all_task()"
# method.
if loop is None:
loop = events.get_event_loop()
return {t for t in _all_tasks if futures._get_loop(t) is loop}
Expand Down Expand Up @@ -82,7 +92,7 @@ def all_tasks(cls, loop=None):
"use asyncio.all_tasks() instead",
PendingDeprecationWarning,
stacklevel=2)
return all_tasks(loop)
return _all_tasks_compat(loop)

def __init__(self, coro, *, loop=None):
super().__init__(loop=loop)
Expand Down
29 changes: 27 additions & 2 deletions Lib/test/test_asyncio/test_tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -1897,8 +1897,10 @@ def kill_me(loop):
# See http://bugs.python.org/issue29271 for details:
asyncio.set_event_loop(self.loop)
try:
self.assertEqual(asyncio.all_tasks(), {task})
self.assertEqual(asyncio.all_tasks(None), {task})
with self.assertWarns(PendingDeprecationWarning):
self.assertEqual(Task.all_tasks(), {task})
with self.assertWarns(PendingDeprecationWarning):
self.assertEqual(Task.all_tasks(None), {task})
finally:
asyncio.set_event_loop(None)

Expand Down Expand Up @@ -2483,6 +2485,9 @@ class TaskLike:
def _loop(self):
return loop

def done(self):
return False

task = TaskLike()
loop = mock.Mock()

Expand All @@ -2496,6 +2501,9 @@ class TaskLike:
def get_loop(self):
return loop

def done(self):
return False

task = TaskLike()
loop = mock.Mock()

Expand All @@ -2504,6 +2512,23 @@ def get_loop(self):
self.assertEqual(asyncio.all_tasks(loop), {task})
self._unregister_task(task)

def test__register_task_3(self):
class TaskLike:
def get_loop(self):
return loop

def done(self):
return True

task = TaskLike()
loop = mock.Mock()

self.assertEqual(asyncio.all_tasks(loop), set())
self._register_task(task)
self.assertEqual(asyncio.all_tasks(loop), set())
self.assertEqual(asyncio.Task.all_tasks(loop), {task})
self._unregister_task(task)

def test__enter_task(self):
task = mock.Mock()
loop = mock.Mock()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Make asyncio.all_tasks() return only pending tasks.
4 changes: 2 additions & 2 deletions Modules/_asynciomodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ module _asyncio
/* identifiers used from some functions */
_Py_IDENTIFIER(__asyncio_running_event_loop__);
_Py_IDENTIFIER(add_done_callback);
_Py_IDENTIFIER(all_tasks);
_Py_IDENTIFIER(_all_tasks_compat);
_Py_IDENTIFIER(call_soon);
_Py_IDENTIFIER(cancel);
_Py_IDENTIFIER(current_task);
Expand Down Expand Up @@ -2125,7 +2125,7 @@ _asyncio_Task_all_tasks_impl(PyTypeObject *type, PyObject *loop)
return NULL;
}

all_tasks_func = _PyObject_GetAttrId(asyncio_mod, &PyId_all_tasks);
all_tasks_func = _PyObject_GetAttrId(asyncio_mod, &PyId__all_tasks_compat);
if (all_tasks_func == NULL) {
return NULL;
}
Expand Down
0