[Python-checkins] bpo-33649: Refresh Tasks and Futures pages (#9314)

Carol Willing webhook-mailer at python.org
Fri Sep 14 16:32:12 EDT 2018


https://github.com/python/cpython/commit/3faaa8857a42a36383bb18425444e597fc876797
commit: 3faaa8857a42a36383bb18425444e597fc876797
branch: master
author: Yury Selivanov <yury at magic.io>
committer: Carol Willing <carolcode at willingconsulting.com>
date: 2018-09-14T13:32:07-07:00
summary:

bpo-33649: Refresh Tasks and Futures pages (#9314)

* bpo-33649: Refresh Tasks and Futures pages

* Fixes

* Fix markup

files:
A Doc/library/asyncio-future.rst
M Doc/library/asyncio-eventloop.rst
M Doc/library/asyncio-protocol.rst
M Doc/library/asyncio-task.rst
M Doc/library/asyncio.rst

diff --git a/Doc/library/asyncio-eventloop.rst b/Doc/library/asyncio-eventloop.rst
index baa5234d3e51..e1b47d2588cd 100644
--- a/Doc/library/asyncio-eventloop.rst
+++ b/Doc/library/asyncio-eventloop.rst
@@ -1429,7 +1429,7 @@ event loop::
 
 .. seealso::
 
-   A similar :ref:`Hello World <asyncio-hello-world-coroutine>`
+   A similar :ref:`Hello World <coroutine>`
    example created with a coroutine and the :func:`run` function.
 
 
diff --git a/Doc/library/asyncio-future.rst b/Doc/library/asyncio-future.rst
new file mode 100644
index 000000000000..2c41c1c2165c
--- /dev/null
+++ b/Doc/library/asyncio-future.rst
@@ -0,0 +1,240 @@
+.. currentmodule:: asyncio
+
+
+=======
+Futures
+=======
+
+*Future* objects are used to bridge low-level callback-based code
+with high-level async/await code.
+
+
+Future Functions
+================
+
+.. function:: isfuture(obj)
+
+   Return ``True`` if *obj* is either of:
+
+   * an instance of :class:`asyncio.Future`,
+   * an instance of :class:`asyncio.Task`,
+   * a Future-like object with a ``_asyncio_future_blocking``
+     attribute.
+
+   .. versionadded:: 3.5
+
+
+.. function:: ensure_future(obj, \*, loop=None)
+
+   Return:
+
+   * *obj* argument as is, if *obj* is a :class:`Future`,
+     a :class:`Task`, or a Future-like object (:func:`isfuture`
+     is used for the test.)
+
+   * a :class:`Task` object wrapping *obj*, if *obj* is a
+     coroutine (:func:`iscoroutine` is used for the test.)
+
+   * a :class:`Task` object that would await on *obj*, if *obj* is an
+     awaitable (:func:`inspect.isawaitable` is used for the test.)
+
+   If *obj* is neither of the above a :exc:`TypeError` is raised.
+
+   .. important::
+
+      See also the :func:`create_task` function which is the
+      preferred way for creating new Tasks.
+
+   .. versionchanged:: 3.5.1
+      The function accepts any :term:`awaitable` object.
+
+
+.. function:: wrap_future(future, \*, loop=None)
+
+   Wrap a :class:`concurrent.futures.Future` object in a
+   :class:`asyncio.Future` object.
+
+
+Future Object
+=============
+
+.. class:: Future(\*, loop=None)
+
+   A Future represents an eventual result of an asynchronous
+   operation.  Not thread-safe.
+
+   Future is an :term:`awaitable` object.  Coroutines can await on
+   Future objects until they either have a result or an exception
+   set, or until they are cancelled.
+
+   Typically Futures are used to enable low-level
+   callback-based code (e.g. in protocols implemented using asyncio
+   :ref:`transports <asyncio-transports-protocols>`)
+   to interoperate with high-level async/await code.
+
+   The rule of thumb is to never expose Future objects in user-facing
+   APIs, and the recommended way to create a Future object is to call
+   :meth:`loop.create_future`.  This way alternative event loop
+   implementations can inject their own optimized implementations
+   of a Future object.
+
+   .. versionchanged:: 3.7
+      Added support for the :mod:`contextvars` module.
+
+   .. method:: result()
+
+      Return the result of the Future.
+
+      If the Future is *done* and has a result set by the
+      :meth:`set_result` method, the result value is returned.
+
+      If the Future is *done* and has an exception set by the
+      :meth:`set_exception` method, this method raises the exception.
+
+      If the Future has been *cancelled*, this method raises
+      a :exc:`CancelledError` exception.
+
+      If the Future's result isn't yet available, this method raises
+      a :exc:`InvalidStateError` exception.
+
+   .. method:: set_result(result)
+
+      Mark the Future as *done* and set its result.
+
+      Raises a :exc:`InvalidStateError` error if the Future is
+      already *done*.
+
+   .. method:: set_exception(exception)
+
+      Mark the Future as *done* and set an exception.
+
+      Raises a :exc:`InvalidStateError` error if the Future is
+      already *done*.
+
+   .. method:: done()
+
+      Return ``True`` if the Future is *done*.
+
+      A Future is *done* if it was *cancelled* or if it has a result
+      or an exception set with :meth:`set_result` or
+      :meth:`set_exception` calls.
+
+   .. method:: add_done_callback(callback, *, context=None)
+
+      Add a callback to be run when the Future is *done*.
+
+      The *callback* is called with the Future object as its only
+      argument.
+
+      If the Future is already *done* when this method is called,
+      the callback is scheduled with :meth:`loop.call_soon`.
+
+      An optional keyword-only *context* argument allows specifying a
+      custom :class:`contextvars.Context` for the *callback* to run in.
+      The current context is used when no *context* is provided.
+
+      :func:`functools.partial` can be used to pass parameters
+      to the callback, e.g.::
+
+          # Call 'print("Future:", fut)' when "fut" is done.
+          fut.add_done_callback(
+              functools.partial(print, "Future:"))
+
+      .. versionchanged:: 3.7
+         The *context* keyword-only parameter was added.
+         See :pep:`567` for more details.
+
+   .. method:: remove_done_callback(callback)
+
+      Remove *callback* from the callbacks list.
+
+      Returns the number of callbacks removed, which is typically 1,
+      unless a callback was added more than once.
+
+   .. method:: cancel()
+
+      Cancel the Future and schedule callbacks.
+
+      If the Future is already *done* or *cancelled*, return ``False``.
+      Otherwise, change the Future's state to *cancelled*,
+      schedule the callbacks, and return ``True``.
+
+   .. method:: exception()
+
+      Return the exception that was set on this Future.
+
+      The exception (or ``None`` if no exception was set) is
+      returned only if the Future is *done*.
+
+      If the Future has been *cancelled*, this method raises a
+      :exc:`CancelledError` exception.
+
+      If the Future isn't *done* yet, this method raises an
+      :exc:`InvalidStateError` exception.
+
+   .. method:: get_loop()
+
+      Return the event loop the Future object is bound to.
+
+      .. versionadded:: 3.7
+
+   .. method:: cancelled()
+
+      Return ``True`` if the Future was *cancelled*.
+
+
+This example creates a Future object, creates and schedules an
+asynchronous Task to set result for the Future, and waits until
+the Future has a result::
+
+    async def set_after(fut, delay, value):
+        # Sleep for *delay* seconds.
+        await asyncio.sleep(delay)
+
+        # Set *value* as a result of *fut* Future.
+        fut.set_result(value)
+
+    async def main():
+        # Get the current event loop.
+        loop = asyncio.get_running_loop()
+
+        # Create a new Future object.
+        fut = loop.create_future()
+
+        # Run "set_after()" coroutine in a parallel Task.
+        # We are using the low-level "loop.create_task()" API here because
+        # we already have a reference to the event loop at hand.
+        # Otherwise we could have just used "asyncio.create_task()".
+        loop.create_task(
+            set_after(fut, 1, '... world'))
+
+        print('hello ...')
+
+        # Wait until *fut* has a result (1 second) and print it.
+        print(await fut)
+
+    asyncio.run(main())
+
+
+.. important::
+
+   The Future object was designed to mimic
+   :class:`concurrent.futures.Future`.  Key differences include:
+
+   - unlike asyncio Futures, :class:`concurrent.futures.Future`
+     instances cannot be awaited.
+
+   - :meth:`asyncio.Future.result` and :meth:`asyncio.Future.exception`
+     do not accept the *timeout* argument.
+
+   - :meth:`asyncio.Future.result` and :meth:`asyncio.Future.exception`
+     raise an :exc:`InvalidStateError` exception when the Future is not
+     *done*.
+
+   - Callbacks registered with :meth:`asyncio.Future.add_done_callback`
+     are not called immediately.  They are scheduled with
+     :meth:`loop.call_soon` instead.
+
+   - asyncio Future is not compatible with the
+     :func:`concurrent.futures.wait` and
+     :func:`concurrent.futures.as_completed` functions.
diff --git a/Doc/library/asyncio-protocol.rst b/Doc/library/asyncio-protocol.rst
index d7ecb25bcea3..e4aed647c338 100644
--- a/Doc/library/asyncio-protocol.rst
+++ b/Doc/library/asyncio-protocol.rst
@@ -1,6 +1,9 @@
 .. currentmodule:: asyncio
 
 
+.. _asyncio-transports-protocols:
+
+
 ========================
 Transports and Protocols
 ========================
@@ -393,11 +396,13 @@ Subprocess Transports
 
 .. method:: SubprocessTransport.kill()
 
-   Kill the subprocess, as in :meth:`subprocess.Popen.kill`.
+   Kill the subprocess.
 
    On POSIX systems, the function sends SIGKILL to the subprocess.
    On Windows, this method is an alias for :meth:`terminate`.
 
+   See also :meth:`subprocess.Popen.kill`.
+
 .. method:: SubprocessTransport.send_signal(signal)
 
    Send the *signal* number to the subprocess, as in
@@ -405,17 +410,20 @@ Subprocess Transports
 
 .. method:: SubprocessTransport.terminate()
 
-   Ask the subprocess to stop, as in :meth:`subprocess.Popen.terminate`.
+   Stop the subprocess.
 
    On POSIX systems, this method sends SIGTERM to the subprocess.
    On Windows, the Windows API function TerminateProcess() is called to
    stop the subprocess.
 
+   See also :meth:`subprocess.Popen.terminate`.
+
 .. method:: SubprocessTransport.close()
 
-   Kill the subprocess by calling the :meth:`kill` method
-   if the subprocess hasn't returned yet, and close transports of all
-   pipes (*stdin*, *stdout* and *stderr*).
+   Kill the subprocess by calling the :meth:`kill` method.
+
+   If the subprocess hasn't returned yet, and close transports of
+   *stdin*, *stdout*, and *stderr* pipes.
 
 
 .. _asyncio-protocol:
diff --git a/Doc/library/asyncio-task.rst b/Doc/library/asyncio-task.rst
index 9f4433ddc339..7e09b166ebc9 100644
--- a/Doc/library/asyncio-task.rst
+++ b/Doc/library/asyncio-task.rst
@@ -1,96 +1,118 @@
 .. currentmodule:: asyncio
 
-Tasks and coroutines
+
+====================
+Coroutines and Tasks
 ====================
 
-**Source code:** :source:`Lib/asyncio/tasks.py`
+This section outlines high-level asyncio APIs to work with coroutines
+and Tasks.
+
+.. contents::
+   :depth: 1
+   :local:
 
-**Source code:** :source:`Lib/asyncio/coroutines.py`
 
 .. _coroutine:
 
 Coroutines
-----------
+==========
 
-Coroutines used with :mod:`asyncio` may be implemented using the
-:keyword:`async def` statement, or by using :term:`generators <generator>`.
-The :keyword:`async def` type of coroutine was added in Python 3.5, and
-is recommended if there is no need to support older Python versions.
+Coroutines declared with async/await syntax is the preferred way of
+writing asyncio applications.  For example, the following snippet
+of code prints "hello", waits 1 second, and prints "world"::
 
-Generator-based coroutines should be decorated with :func:`@asyncio.coroutine
-<asyncio.coroutine>`, although this is not strictly enforced.
-The decorator enables compatibility with :keyword:`async def` coroutines,
-and also serves as documentation.  Generator-based
-coroutines use the ``yield from`` syntax introduced in :pep:`380`,
-instead of the original ``yield`` syntax.
+    >>> import asyncio
 
-The word "coroutine", like the word "generator", is used for two
-different (though related) concepts:
+    >>> async def main():
+    ...     print('hello')
+    ...     await asyncio.sleep(1)
+    ...     print('world')
 
-- The function that defines a coroutine
-  (a function definition using :keyword:`async def` or
-  decorated with ``@asyncio.coroutine``).  If disambiguation is needed
-  we will call this a *coroutine function* (:func:`iscoroutinefunction`
-  returns ``True``).
+    >>> asyncio.run(main())
+    hello
+    world
 
-- The object obtained by calling a coroutine function.  This object
-  represents a computation or an I/O operation (usually a combination)
-  that will complete eventually.  If disambiguation is needed we will
-  call it a *coroutine object* (:func:`iscoroutine` returns ``True``).
+Note that simply calling a coroutine will not schedule it to
+be executed::
 
-Things a coroutine can do:
+    >>> main()
+    <coroutine object main at 0x1053bb7c8>
 
-- ``result = await future`` or ``result = yield from future`` --
-  suspends the coroutine until the
-  future is done, then returns the future's result, or raises an
-  exception, which will be propagated.  (If the future is cancelled,
-  it will raise a ``CancelledError`` exception.)  Note that tasks are
-  futures, and everything said about futures also applies to tasks.
+To actually run a coroutine asyncio provides three main mechanisms:
 
-- ``result = await coroutine`` or ``result = yield from coroutine`` --
-  wait for another coroutine to
-  produce a result (or raise an exception, which will be propagated).
-  The ``coroutine`` expression must be a *call* to another coroutine.
+* By using the :func:`asyncio.run` function to run the top-level
+  entry point "main()" function (see the above example.)
 
-- ``return expression`` -- produce a result to the coroutine that is
-  waiting for this one using :keyword:`await` or ``yield from``.
+* By awaiting on a coroutine.  The following snippet of code will
+  print "hello" after waiting for 1 second, and then print "world"
+  after waiting for *another* 2 seconds::
 
-- ``raise exception`` -- raise an exception in the coroutine that is
-  waiting for this one using :keyword:`await` or ``yield from``.
+      import asyncio
+      import time
 
-Calling a coroutine does not start its code running --
-the coroutine object returned by the call doesn't do anything until you
-schedule its execution.  There are two basic ways to start it running:
-call ``await coroutine`` or ``yield from coroutine`` from another coroutine
-(assuming the other coroutine is already running!), or schedule its execution
-using the :func:`ensure_future` function or the :meth:`loop.create_task`
-method.
+      async def say_after(delay, what):
+          await asyncio.sleep(delay)
+          print(what)
 
+      async def main():
+          print('started at', time.strftime('%X'))
 
-Coroutines (and tasks) can only run when the event loop is running.
+          await say_after(1, 'hello')
+          await say_after(2, 'world')
 
-.. decorator:: coroutine
+          print('finished at', time.strftime('%X'))
 
-    Decorator to mark generator-based coroutines.  This enables
-    the generator use :keyword:`!yield from` to call :keyword:`async
-    def` coroutines, and also enables the generator to be called by
-    :keyword:`async def` coroutines, for instance using an
-    :keyword:`await` expression.
+      asyncio.run(main())
 
-    There is no need to decorate :keyword:`async def` coroutines themselves.
+  Expected output::
 
-    If the generator is not yielded from before it is destroyed, an error
-    message is logged. See :ref:`Detect coroutines never scheduled
-    <asyncio-coroutine-not-scheduled>`.
+      started at 17:13:52
+      hello
+      world
+      finished at 17:13:55
 
-.. note::
+* By using the :func:`asyncio.create_task` function to run coroutines
+  concurrently as asyncio :class:`Tasks <Task>`.
+
+  Let's modify the above example and run two "set_after" coroutines
+  *concurrently*::
+
+      async def main():
+          task1 = asyncio.create_task(
+              say_after(1, 'hello'))
+
+          task2 = asyncio.create_task(
+              say_after(2, 'world'))
+
+          print('started at', time.strftime('%X'))
 
-    In this documentation, some methods are documented as coroutines,
-    even if they are plain Python functions returning a :class:`Future`.
-    This is intentional to have a freedom of tweaking the implementation
-    of these functions in the future. If such a function is needed to be
-    used in a callback-style code, wrap its result with :func:`ensure_future`.
+          # Wait until both tasks are completed (should take
+          # around 2 seconds.)
+          await task1
+          await task2
 
+          print('finished at', time.strftime('%X'))
+
+  Note that expected output now shows that the snippet runs
+  1 second faster than before::
+
+      started at 17:14:32
+      hello
+      world
+      finished at 17:14:34
+
+Note that in this documentation the term "coroutine" can be used for
+two closely related concepts:
+
+* a *coroutine function*: an :keyword:`async def` function;
+
+* a *coroutine object*: object returned by calling a
+  *coroutine function*.
+
+
+Running an asyncio Program
+==========================
 
 .. function:: run(coro, \*, debug=False)
 
@@ -101,7 +123,7 @@ Coroutines (and tasks) can only run when the event loop is running.
     This function cannot be called when another asyncio event loop is
     running in the same thread.
 
-    If debug is True, the event loop will be run in debug mode.
+    If *debug* is ``True``, the event loop will be run in debug mode.
 
     This function always creates a new event loop and closes it at
     the end.  It should be used as a main entry point for asyncio
@@ -112,34 +134,41 @@ Coroutines (and tasks) can only run when the event loop is running.
        on a :term:`provisional basis <provisional api>`.
 
 
-.. _asyncio-hello-world-coroutine:
+Creating Tasks
+==============
 
-Example: Hello World coroutine
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+.. function:: create_task(coro, \*, name=None)
 
-Example of coroutine displaying ``"Hello World"``::
+   Wrap a :ref:`coroutine <coroutine>` *coro* into a task and schedule
+   its execution. Return the task object.
 
-    import asyncio
+   If *name* is not ``None``, it is set as the name of the task using
+   :meth:`Task.set_name`.
+
+   The task is executed in :func:`get_running_loop` context,
+   :exc:`RuntimeError` is raised if there is no running loop in
+   current thread.
+
+   .. versionadded:: 3.7
 
-    async def hello_world():
-        print("Hello World!")
+   .. versionchanged:: 3.8
+      Added the ``name`` parameter.
 
-    asyncio.run(hello_world())
 
-.. seealso::
+Sleeping
+========
 
-   The :ref:`Hello World with call_soon() <asyncio-hello-world-callback>`
-   example uses the :meth:`loop.call_soon` method to schedule a
-   callback.
+.. coroutinefunction:: sleep(delay, result=None, \*, loop=None)
 
+   Block for *delay* seconds.
 
-.. _asyncio-date-coroutine:
+   If *result* is provided, it is returned to the caller
+   when the coroutine completes.
 
-Example: Coroutine displaying the current date
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   .. _asyncio-date-coroutine:
 
-Example of coroutine displaying the current date every second during 5 seconds
-using the :meth:`sleep` function::
+   Example of coroutine displaying the current date every second
+   during 5 seconds::
 
     import asyncio
     import datetime
@@ -155,418 +184,279 @@ using the :meth:`sleep` function::
 
     asyncio.run(display_date())
 
-.. seealso::
-
-   The :ref:`display the current date with call_later()
-   <asyncio-date-callback>` example uses a callback with the
-   :meth:`loop.call_later` method.
-
-
-Example: Chain coroutines
-^^^^^^^^^^^^^^^^^^^^^^^^^
-
-Example chaining coroutines::
-
-    import asyncio
-
-    async def compute(x, y):
-        print("Compute %s + %s ..." % (x, y))
-        await asyncio.sleep(1.0)
-        return x + y
-
-    async def print_sum(x, y):
-        result = await compute(x, y)
-        print("%s + %s = %s" % (x, y, result))
-
-    loop = asyncio.get_event_loop()
-    loop.run_until_complete(print_sum(1, 2))
-    loop.close()
-
-``compute()`` is chained to ``print_sum()``: ``print_sum()`` coroutine waits
-until ``compute()`` is completed before returning its result.
-
-Sequence diagram of the example:
-
-.. image:: tulip_coro.png
-   :align: center
-
-The "Task" is created by the :meth:`loop.run_until_complete` method
-when it gets a coroutine object instead of a task.
-
-The diagram shows the control flow, it does not describe exactly how things
-work internally. For example, the sleep coroutine creates an internal future
-which uses :meth:`loop.call_later` to wake up the task in 1 second.
-
-
-Future
-------
-
-.. class:: Future(\*, loop=None)
-
-   This class is *almost* compatible with :class:`concurrent.futures.Future`.
-
-   Differences:
-
-   - :meth:`result` and :meth:`exception` do not take a timeout argument and
-     raise an exception when the future isn't done yet.
-
-   - Callbacks registered with :meth:`add_done_callback` are always called
-     via the event loop's :meth:`loop.call_soon`.
-
-   - This class is not compatible with the :func:`~concurrent.futures.wait` and
-     :func:`~concurrent.futures.as_completed` functions in the
-     :mod:`concurrent.futures` package.
-
-   This class is :ref:`not thread safe <asyncio-multithreading>`.
-
-   .. method:: cancel()
-
-      Cancel the future and schedule callbacks.
-
-      If the future is already done or cancelled, return ``False``. Otherwise,
-      change the future's state to cancelled, schedule the callbacks and return
-      ``True``.
-
-   .. method:: cancelled()
-
-      Return ``True`` if the future was cancelled.
-
-   .. method:: done()
-
-      Return ``True`` if the future is done.
-
-      Done means either that a result / exception are available, or that the
-      future was cancelled.
 
-   .. method:: result()
+Running Tasks Concurrently
+==========================
 
-      Return the result this future represents.
+.. coroutinefunction:: gather(\*fs, loop=None, return_exceptions=False)
 
-      If the future has been cancelled, raises :exc:`CancelledError`. If the
-      future's result isn't yet available, raises :exc:`InvalidStateError`. If
-      the future is done and has an exception set, this exception is raised.
+   Return a Future aggregating results from the given coroutine objects,
+   Tasks, or Futures.
 
-   .. method:: exception()
+   If all Tasks/Futures are completed successfully, the result is an
+   aggregate list of returned values.  The result values are in the
+   order of the original *fs* sequence.
 
-      Return the exception that was set on this future.
+   All coroutines in the *fs* list are automatically
+   wrapped in :class:`Tasks <Task>`.
 
-      The exception (or ``None`` if no exception was set) is returned only if
-      the future is done. If the future has been cancelled, raises
-      :exc:`CancelledError`. If the future isn't done yet, raises
-      :exc:`InvalidStateError`.
+   If *return_exceptions* is ``True``, exceptions in the Tasks/Futures
+   are treated the same as successful results, and gathered in the
+   result list.  Otherwise, the first raised exception is immediately
+   propagated to the returned Future.
 
-   .. method:: add_done_callback(callback, *, context=None)
+   If the outer Future is *cancelled*, all submitted Tasks/Futures
+   (that have not completed yet) are also *cancelled*.
 
-      Add a callback to be run when the future becomes done.
+   If any child is *cancelled*, it is treated as if it raised
+   :exc:`CancelledError` -- the outer Future is **not** cancelled in
+   this case.  This is to prevent the cancellation of one submitted
+   Task/Future to cause other Tasks/Futures to be cancelled.
 
-      The *callback* is called with a single argument - the future object. If the
-      future is already done when this is called, the callback is scheduled
-      with :meth:`loop.call_soon`.
+   All futures must share the same event loop.
 
-      An optional keyword-only *context* argument allows specifying a custom
-      :class:`contextvars.Context` for the *callback* to run in.  The current
-      context is used when no *context* is provided.
-
-      :ref:`Use functools.partial to pass parameters to the callback
-      <asyncio-pass-keywords>`. For example,
-      ``fut.add_done_callback(functools.partial(print, "Future:",
-      flush=True))`` will call ``print("Future:", fut, flush=True)``.
-
-      .. versionchanged:: 3.7
-         The *context* keyword-only parameter was added. See :pep:`567`
-         for more details.
-
-   .. method:: remove_done_callback(fn)
-
-      Remove all instances of a callback from the "call when done" list.
-
-      Returns the number of callbacks removed.
-
-   .. method:: set_result(result)
-
-      Mark the future done and set its result.
-
-      If the future is already done when this method is called, raises
-      :exc:`InvalidStateError`.
-
-   .. method:: set_exception(exception)
-
-      Mark the future done and set an exception.
-
-      If the future is already done when this method is called, raises
-      :exc:`InvalidStateError`.
-
-   .. method:: get_loop()
-
-      Return the event loop the future object is bound to.
+   .. versionchanged:: 3.7
+      If the *gather* itself is cancelled, the cancellation is
+      propagated regardless of *return_exceptions*.
 
-      .. versionadded:: 3.7
+   Example::
 
+      import asyncio
 
-Example: Future with run_until_complete()
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+      async def factorial(name, number):
+          f = 1
+          for i in range(2, number + 1):
+              print(f"Task {name}: Compute factorial({i})...")
+              await asyncio.sleep(1)
+              f *= i
+          print(f"Task {name}: factorial({number}) = {f}")
 
-Example combining a :class:`Future` and a :ref:`coroutine function
-<coroutine>`::
+      async def main():
+          await asyncio.gather(
+              factorial("A", 2),
+              factorial("B", 3),
+              factorial("C", 4),
+          ))
 
-    import asyncio
+      asyncio.run(main())
 
-    async def slow_operation(future):
-        await asyncio.sleep(1)
-        future.set_result('Future is done!')
+      # Expected output:
+      #
+      #     Task A: Compute factorial(2)...
+      #     Task B: Compute factorial(2)...
+      #     Task C: Compute factorial(2)...
+      #     Task A: factorial(2) = 2
+      #     Task B: Compute factorial(3)...
+      #     Task C: Compute factorial(3)...
+      #     Task B: factorial(3) = 6
+      #     Task C: Compute factorial(4)...
+      #     Task C: factorial(4) = 24
 
-    loop = asyncio.get_event_loop()
-    future = asyncio.Future()
-    asyncio.ensure_future(slow_operation(future))
-    loop.run_until_complete(future)
-    print(future.result())
-    loop.close()
 
-The coroutine function is responsible for the computation (which takes 1 second)
-and it stores the result into the future. The
-:meth:`loop.run_until_complete` method waits for the completion of
-the future.
+Shielding Tasks From Cancellation
+=================================
 
-.. note::
-   The :meth:`loop.run_until_complete` method uses internally the
-   :meth:`~Future.add_done_callback` method to be notified when the future is
-   done.
+.. coroutinefunction:: shield(fut, \*, loop=None)
 
+   Wait for a Future/Task while protecting it from being cancelled.
 
-Example: Future with run_forever()
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   *fut* can be a coroutine, a Task, or a Future-like object.  If
+   *fut* is a coroutine it is automatically wrapped in a
+   :class:`Task`.
 
-The previous example can be written differently using the
-:meth:`Future.add_done_callback` method to describe explicitly the control
-flow::
+   The statement::
 
-    import asyncio
+       res = await shield(something())
 
-    async def slow_operation(future):
-        await asyncio.sleep(1)
-        future.set_result('Future is done!')
+   is equivalent to the statement::
 
-    def got_result(future):
-        print(future.result())
-        loop.stop()
+       res = await something()
 
-    loop = asyncio.get_event_loop()
-    future = asyncio.Future()
-    asyncio.ensure_future(slow_operation(future))
-    future.add_done_callback(got_result)
-    try:
-        loop.run_forever()
-    finally:
-        loop.close()
+   *except* that if the coroutine containing it is cancelled, the
+   Task running in ``something()`` is not cancelled.  From the point
+   of view of ``something()``, the cancellation did not happen.
+   Although its caller is still cancelled, so the "await" expression
+   still raises :exc:`CancelledError`.
 
-In this example, the future is used to link ``slow_operation()`` to
-``got_result()``: when ``slow_operation()`` is done, ``got_result()`` is called
-with the result.
+   If ``something()`` is cancelled by other means (i.e. from within
+   itself) that would also cancel ``shield()``.
 
+   If it is desired to completely ignore cancellation (not recommended)
+   the ``shield()`` function should be combined with a try/except
+   clause, as follows::
 
-Task
-----
+       try:
+           res = await shield(something())
+       except CancelledError:
+           res = None
 
-.. function:: create_task(coro, \*, name=None)
 
-   Wrap a :ref:`coroutine <coroutine>` *coro* into a task and schedule
-   its execution. Return the task object.
+Timeouts
+========
 
-   If *name* is not ``None``, it is set as the name of the task using
-   :meth:`Task.set_name`.
+.. coroutinefunction:: wait_for(fut, timeout, \*, loop=None)
 
-   The task is executed in :func:`get_running_loop` context,
-   :exc:`RuntimeError` is raised if there is no running loop in
-   current thread.
+   Wait for the coroutine, Task, or Future to complete with timeout.
 
-   .. versionadded:: 3.7
+   *fut* can be a coroutine, a Task, or a Future-like object.  If
+   *fut* is a coroutine it is automatically wrapped in a
+   :class:`Task`.
 
-   .. versionchanged:: 3.8
-      Added the ``name`` parameter.
+   *timeout* can either be ``None`` or a float or int number of seconds
+   to wait for.  If *timeout* is ``None``, block until the future
+   completes.
 
-.. class:: Task(coro, \*, loop=None, name=None)
+   If a timeout occurs, it cancels the task and raises
+   :exc:`asyncio.TimeoutError`.
 
-   A unit for concurrent running of :ref:`coroutines <coroutine>`,
-   subclass of :class:`Future`.
+   To avoid the task cancellation, wrap it in :func:`shield`.
 
-   A task is responsible for executing a coroutine object in an event loop.  If
-   the wrapped coroutine yields from a future, the task suspends the execution
-   of the wrapped coroutine and waits for the completion of the future. When
-   the future is done, the execution of the wrapped coroutine restarts with the
-   result or the exception of the future.
+   The function will wait until the future is actually cancelled,
+   so the total wait time may exceed the *timeout*.
 
-   Event loops use cooperative scheduling: an event loop only runs one task at
-   a time. Other tasks may run in parallel if other event loops are
-   running in different threads. While a task waits for the completion of a
-   future, the event loop executes a new task.
+   If the wait is cancelled, the future *fut* is also cancelled.
 
-   The cancellation of a task is different from the cancellation of a
-   future. Calling :meth:`cancel` will throw a
-   :exc:`~concurrent.futures.CancelledError` to the wrapped
-   coroutine. :meth:`~Future.cancelled` only returns ``True`` if the
-   wrapped coroutine did not catch the
-   :exc:`~concurrent.futures.CancelledError` exception, or raised a
-   :exc:`~concurrent.futures.CancelledError` exception.
+   Example::
 
-   If a pending task is destroyed, the execution of its wrapped :ref:`coroutine
-   <coroutine>` did not complete. It is probably a bug and a warning is
-   logged: see :ref:`Pending task destroyed <asyncio-pending-task-destroyed>`.
+       async def eternity():
+           # Sleep for one hour
+           await asyncio.sleep(3600)
+           print('yay!')
 
-   Don't directly create :class:`Task` instances: use the :func:`create_task`
-   function or the :meth:`loop.create_task` method.
+       async def main():
+           # Wait for at most 1 second
+           try:
+               await asyncio.wait_for(eternity(), timeout=1.0)
+           except asyncio.TimeoutError:
+               print('timeout!')
 
-   Tasks support the :mod:`contextvars` module.  When a Task
-   is created it copies the current context and later runs its coroutine
-   in the copied context.  See :pep:`567` for more details.
+       asyncio.run(main())
 
-   This class is :ref:`not thread safe <asyncio-multithreading>`.
+       # Expected output:
+       #
+       #     timeout!
 
    .. versionchanged:: 3.7
-      Added support for the :mod:`contextvars` module.
-
-   .. versionchanged:: 3.8
-      Added the ``name`` parameter.
+      When *fut* is cancelled due to a timeout, ``wait_for`` waits
+      for *fut* to be cancelled.  Previously, it raised
+      :exc:`asyncio.TimeoutError` immediately.
 
-   .. classmethod:: all_tasks(loop=None)
 
-      Return a set of all tasks for an event loop.
+Waiting Primitives
+==================
 
-      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)
-
-      Return the currently running task in an event loop or ``None``.
-
-      By default the current task for the current event loop is returned.
-
-      ``None`` is returned when called not in the context of a :class:`Task`.
-
-   .. method:: cancel()
-
-      Request that this task cancel itself.
-
-      This arranges for a :exc:`~concurrent.futures.CancelledError` to be
-      thrown into the wrapped coroutine on the next cycle through the event
-      loop. The coroutine then has a chance to clean up or even deny the
-      request using try/except/finally.
+.. coroutinefunction:: wait(fs, \*, loop=None, timeout=None,\
+                            return_when=ALL_COMPLETED)
 
-      Unlike :meth:`Future.cancel`, this does not guarantee that the task
-      will be cancelled: the exception might be caught and acted upon, delaying
-      cancellation of the task or preventing cancellation completely. The task
-      may also return a value or raise a different exception.
+   Wait for a set of Futures to complete.
 
-      Immediately after this method is called, :meth:`~Future.cancelled` will
-      not return ``True`` (unless the task was already cancelled). A task will
-      be marked as cancelled when the wrapped coroutine terminates with a
-      :exc:`~concurrent.futures.CancelledError` exception (even if
-      :meth:`cancel` was not called).
+   *fs* is a list of coroutines, Futures, and/or Tasks.  Coroutines
+   are automatically wrapped in :class:`Tasks <Task>`.
 
-   .. method:: get_stack(\*, limit=None)
+   Returns two sets of Tasks/Futures: ``(done, pending)``.
 
-      Return the list of stack frames for this task's coroutine.
+   *timeout* (a float or int), if specified, can be used to control
+   the maximum number of seconds to wait before returning.
 
-      If the coroutine is not done, this returns the stack where it is
-      suspended.  If the coroutine has completed successfully or was
-      cancelled, this returns an empty list.  If the coroutine was
-      terminated by an exception, this returns the list of traceback
-      frames.
+   Note that this function does not raise :exc:`asyncio.TimeoutError`.
+   Futures or Tasks that aren't done when the timeout occurs are just
+   returned in the second set.
 
-      The frames are always ordered from oldest to newest.
+   *return_when* indicates when this function should return.  It must
+   be one of the following constants:
 
-      The optional limit gives the maximum number of frames to return; by
-      default all available frames are returned.  Its meaning differs depending
-      on whether a stack or a traceback is returned: the newest frames of a
-      stack are returned, but the oldest frames of a traceback are returned.
-      (This matches the behavior of the traceback module.)
+   .. tabularcolumns:: |l|L|
 
-      For reasons beyond our control, only one stack frame is returned for a
-      suspended coroutine.
+   +-----------------------------+----------------------------------------+
+   | Constant                    | Description                            |
+   +=============================+========================================+
+   | :const:`FIRST_COMPLETED`    | The function will return when any      |
+   |                             | future finishes or is cancelled.       |
+   +-----------------------------+----------------------------------------+
+   | :const:`FIRST_EXCEPTION`    | The function will return when any      |
+   |                             | future finishes by raising an          |
+   |                             | exception.  If no future raises an     |
+   |                             | exception then it is equivalent to     |
+   |                             | :const:`ALL_COMPLETED`.                |
+   +-----------------------------+----------------------------------------+
+   | :const:`ALL_COMPLETED`      | The function will return when all      |
+   |                             | futures finish or are cancelled.       |
+   +-----------------------------+----------------------------------------+
 
-   .. method:: print_stack(\*, limit=None, file=None)
+   Unlike :func:`~asyncio.wait_for`, ``wait()`` does not cancel the
+   futures when a timeout occurs.
 
-      Print the stack or traceback for this task's coroutine.
+   Usage::
 
-      This produces output similar to that of the traceback module, for the
-      frames retrieved by get_stack().  The limit argument is passed to
-      get_stack().  The file argument is an I/O stream to which the output
-      is written; by default output is written to sys.stderr.
+        done, pending = await asyncio.wait(fs)
 
-   .. method:: get_name()
 
-      Return the name of the task.
+.. function:: as_completed(fs, \*, loop=None, timeout=None)
 
-      If no name has been explicitly assigned to the task, the default
-      ``Task`` implementation generates a default name during instantiation.
+   Return an iterator which values, when waited for, are
+   :class:`Future` instances.
 
-      .. versionadded:: 3.8
+   Raises :exc:`asyncio.TimeoutError` if the timeout occurs before
+   all Futures are done.
 
-   .. method:: set_name(value)
+   Example::
 
-      Set the name of the task.
+       for f in as_completed(fs):
+           result = await f
+           # ...
 
-      The *value* argument can be any object, which is then converted to a
-      string.
 
-      In the default ``Task`` implementation, the name will be visible in the
-      :func:`repr` output of a task object.
+Scheduling From Other Threads
+=============================
 
-      .. versionadded:: 3.8
+.. function:: run_coroutine_threadsafe(coro, loop)
 
+   Submit a coroutine to the given event loop.  Thread-safe.
 
-Example: Parallel execution of tasks
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   Return a :class:`concurrent.futures.Future` to access the result.
 
-Example executing 3 tasks (A, B, C) in parallel::
+   This function is meant to be called from a different OS thread
+   than the one where the event loop is running.  Example::
 
-    import asyncio
+     # Create a coroutine
+     coro = asyncio.sleep(1, result=3)
 
-    async def factorial(name, number):
-        f = 1
-        for i in range(2, number+1):
-            print("Task %s: Compute factorial(%s)..." % (name, i))
-            await asyncio.sleep(1)
-            f *= i
-        print("Task %s: factorial(%s) = %s" % (name, number, f))
+     # Submit the coroutine to a given loop
+     future = asyncio.run_coroutine_threadsafe(coro, loop)
 
-    loop = asyncio.get_event_loop()
-    loop.run_until_complete(asyncio.gather(
-        factorial("A", 2),
-        factorial("B", 3),
-        factorial("C", 4),
-    ))
-    loop.close()
+     # Wait for the result with an optional timeout argument
+     assert future.result(timeout) == 3
 
-Output::
+   If an exception is raised in the coroutine, the returned Future
+   will be notified.  It can also be used to cancel the task in
+   the event loop::
 
-    Task A: Compute factorial(2)...
-    Task B: Compute factorial(2)...
-    Task C: Compute factorial(2)...
-    Task A: factorial(2) = 2
-    Task B: Compute factorial(3)...
-    Task C: Compute factorial(3)...
-    Task B: factorial(3) = 6
-    Task C: Compute factorial(4)...
-    Task C: factorial(4) = 24
+     try:
+         result = future.result(timeout)
+     except asyncio.TimeoutError:
+         print('The coroutine took too long, cancelling the task...')
+         future.cancel()
+     except Exception as exc:
+         print('The coroutine raised an exception: {!r}'.format(exc))
+     else:
+         print('The coroutine returned: {!r}'.format(result))
 
-A task is automatically scheduled for execution when it is created. The event
-loop stops when all tasks are done.
+   See the :ref:`concurrency and multithreading <asyncio-multithreading>`
+   section of the documentation.
 
+   Unlike other asyncio functions this functions requires the *loop*
+   argument to be passed explicitly.
 
-Task functions
---------------
+   .. versionadded:: 3.5.1
 
-.. note::
 
-   In the functions below, the optional *loop* argument allows explicitly setting
-   the event loop object used by the underlying task or coroutine.  If it's
-   not provided, the default event loop is used.
+Introspection
+=============
 
 
 .. function:: current_task(loop=None)
 
-   Return the current running :class:`Task` instance or ``None``, if
+   Return the currently running :class:`Task` instance, or ``None`` if
    no task is running.
 
    If *loop* is ``None`` :func:`get_running_loop` is used to get
@@ -577,246 +467,259 @@ Task functions
 
 .. function:: all_tasks(loop=None)
 
-   Return a set of :class:`Task` objects created for the loop.
+   Return a set of not yet finished :class:`Task` objects run by
+   the 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`.)
+   current loop.
 
    .. versionadded:: 3.7
 
 
-.. function:: as_completed(fs, \*, loop=None, timeout=None)
+Task Object
+===========
 
-   Return an iterator whose values, when waited for, are :class:`Future`
-   instances.
+.. class:: Task(coro, \*, loop=None, name=None)
 
-   Raises :exc:`asyncio.TimeoutError` if the timeout occurs before all Futures
-   are done.
+   A :class:`Future`-like object that wraps a Python
+   :ref:`coroutine <coroutine>`.  Not thread-safe.
 
-   Example::
+   Tasks are used to run coroutines in event loops.
+   If a coroutine awaits on a Future, the Task suspends
+   the execution of the coroutine and waits for the completion
+   of the Future.  When the Future is *done*, the execution of
+   the wrapped coroutine resumes.
 
-       for f in as_completed(fs):
-           result = await f  # The 'await' may raise
-           # Use result
+   Event loops use cooperative scheduling: an event loop runs
+   one Task at a time.  While a Task awaits for the completion of a
+   Future, the event loop runs other Tasks, callbacks, or performs
+   IO operations.
 
-   .. note::
+   Use the high-level :func:`asyncio.create_task` function to create
+   Tasks, or low-level :meth:`loop.create_task` or
+   :func:`ensure_future` functions.  Manually instantiating Task
+   objects is discouraged.
 
-      The futures ``f`` are not necessarily members of fs.
+   To cancel a running Task use the :meth:`cancel` method.  Calling it
+   will cause the Task to throw a :exc:`CancelledError` exception into
+   the wrapped coroutine.  If a coroutine is awaiting on a Future
+   object during cancellation, the Future object will be cancelled.
 
-.. function:: ensure_future(coro_or_future, \*, loop=None)
+   :meth:`cancelled` can be used to check if the Task was cancelled.
+   The method returns ``True`` if the wrapped coroutine did not
+   suppress the :exc:`CancelledError` exception and was actually
+   cancelled.
 
-   Schedule the execution of a :ref:`coroutine object <coroutine>`: wrap it in
-   a future. Return a :class:`Task` object.
+   :class:`asyncio.Task` inherits from :class:`Future` all of its
+   APIs except :meth:`Future.set_result` and
+   :meth:`Future.set_exception`.
 
-   If the argument is a :class:`Future`, it is returned directly.
+   Tasks support the :mod:`contextvars` module.  When a Task
+   is created it copies the current context and later runs its
+   coroutine in the copied context.
 
-   .. versionadded:: 3.4.4
+   .. versionchanged:: 3.7
+      Added support for the :mod:`contextvars` module.
 
-   .. versionchanged:: 3.5.1
-      The function accepts any :term:`awaitable` object.
+   .. versionchanged:: 3.8
+      Added the ``name`` parameter.
 
-   .. note::
+   .. method:: cancel()
 
-      :func:`create_task` (added in Python 3.7) is the preferable way
-      for spawning new tasks.
+      Request the Task to be cancelled.
 
-   .. seealso::
+      This arranges for a :exc:`CancelledError` exception to be thrown
+      into the wrapped coroutine on the next cycle of the event loop.
 
-      The :func:`create_task` function and
-      :meth:`loop.create_task` method.
+      The coroutine then has a chance to clean up or even deny the
+      request by suppressing the exception with a :keyword:`try` ...
+      ... ``except CancelledError`` ... :keyword:`finally` block.
+      Therefore, unlike :meth:`Future.cancel`, :meth:`Task.cancel` does
+      not guarantee that the Task will be cancelled, although
+      suppressing cancellation completely is not common and is actively
+      discouraged.
 
-.. function:: wrap_future(future, \*, loop=None)
+      The following example illustrates how coroutines can intercept
+      the cancellation request::
 
-   Wrap a :class:`concurrent.futures.Future` object in a :class:`Future`
-   object.
+          async def cancel_me():
+              print('cancel_me(): before sleep')
 
-.. function:: gather(\*coros_or_futures, loop=None, return_exceptions=False)
+              try:
+                  # Wait for 1 hour
+                  await asyncio.sleep(3600)
+              except asyncio.CancelledError:
+                  print('cancel_me(): cancel sleep')
+                  raise
+              finally:
+                  print('cancel_me(): after sleep')
 
-   Return a future aggregating results from the given coroutine objects or
-   futures.
+          async def main():
+              # Create a "cancel_me" Task
+              task = asyncio.create_task(cancel_me())
 
-   All futures must share the same event loop.  If all the tasks are done
-   successfully, the returned future's result is the list of results (in the
-   order of the original sequence, not necessarily the order of results
-   arrival).  If *return_exceptions* is true, exceptions in the tasks are
-   treated the same as successful results, and gathered in the result list;
-   otherwise, the first raised exception will be immediately propagated to the
-   returned future.
+              # Wait for 1 second
+              await asyncio.sleep(1)
 
-   Cancellation: if the outer Future is cancelled, all children (that have not
-   completed yet) are also cancelled.  If any child is cancelled, this is
-   treated as if it raised :exc:`~concurrent.futures.CancelledError` -- the
-   outer Future is *not* cancelled in this case.  (This is to prevent the
-   cancellation of one child to cause other children to be cancelled.)
+              task.cancel()
+              try:
+                  await task
+              except asyncio.CancelledError:
+                  print("main(): cancel_me is cancelled now")
 
-   .. versionchanged:: 3.7.0
-      If the *gather* itself is cancelled, the cancellation is propagated
-      regardless of *return_exceptions*.
+          asyncio.run(main())
 
-.. function:: iscoroutine(obj)
+          # Expected output:
+          #
+          #     cancel_me(): before sleep
+          #     cancel_me(): cancel sleep
+          #     cancel_me(): after sleep
+          #     main(): cancel_me is cancelled now
 
-   Return ``True`` if *obj* is a :ref:`coroutine object <coroutine>`,
-   which may be based on a generator or an :keyword:`async def` coroutine.
+   .. method:: cancelled()
 
-.. function:: iscoroutinefunction(func)
+      Return ``True`` if the Task is *cancelled*.
 
-   Return ``True`` if *func* is determined to be a :ref:`coroutine function
-   <coroutine>`, which may be a decorated generator function or an
-   :keyword:`async def` function.
+      The Task is *cancelled* when the cancellation was requested with
+      :meth:`cancel` and the wrapped coroutine propagated the
+      :exc:`CancelledError` exception thrown into it.
 
-.. function:: run_coroutine_threadsafe(coro, loop)
+   .. method:: done()
 
-   Submit a :ref:`coroutine object <coroutine>` to a given event loop.
+      Return ``True`` if the Task is *done*.
 
-   Return a :class:`concurrent.futures.Future` to access the result.
+      A Task is *done* when the wrapped coroutine either returned
+      a value, raised an exception, or the Task was cancelled.
 
-   This function is meant to be called from a different thread than the one
-   where the event loop is running. Usage::
+   .. method:: get_stack(\*, limit=None)
 
-     # Create a coroutine
-     coro = asyncio.sleep(1, result=3)
-     # Submit the coroutine to a given loop
-     future = asyncio.run_coroutine_threadsafe(coro, loop)
-     # Wait for the result with an optional timeout argument
-     assert future.result(timeout) == 3
+      Return the list of stack frames for this Task.
 
-   If an exception is raised in the coroutine, the returned future will be
-   notified. It can also be used to cancel the task in the event loop::
+      If the wrapped coroutine is not done, this returns the stack
+      where it is suspended.  If the coroutine has completed
+      successfully or was cancelled, this returns an empty list.
+      If the coroutine was terminated by an exception, this returns
+      the list of traceback frames.
 
-     try:
-         result = future.result(timeout)
-     except asyncio.TimeoutError:
-         print('The coroutine took too long, cancelling the task...')
-         future.cancel()
-     except Exception as exc:
-         print('The coroutine raised an exception: {!r}'.format(exc))
-     else:
-         print('The coroutine returned: {!r}'.format(result))
+      The frames are always ordered from oldest to newest.
 
-   See the :ref:`concurrency and multithreading <asyncio-multithreading>`
-   section of the documentation.
+      Only one stack frame is returned for a suspended coroutine.
 
-   .. note::
+      The optional *limit* argument sets the maximum number of frames
+      to return; by default all available frames are returned.
+      The ordering of the returned list differs depending on whether
+      a stack or a traceback is returned: the newest frames of a
+      stack are returned, but the oldest frames of a traceback are
+      returned.  (This matches the behavior of the traceback module.)
 
-      Unlike other functions from the module,
-      :func:`run_coroutine_threadsafe` requires the *loop* argument to
-      be passed explicitly.
+   .. method:: print_stack(\*, limit=None, file=None)
 
-   .. versionadded:: 3.5.1
+      Print the stack or traceback for this Task.
 
-.. coroutinefunction:: sleep(delay, result=None, \*, loop=None)
+      This produces output similar to that of the traceback module
+      for the frames retrieved by :meth:`get_stack`.
 
-   Create a :ref:`coroutine <coroutine>` that completes after a given
-   time (in seconds).  If *result* is provided, it is produced to the caller
-   when the coroutine completes.
+      The *limit* argument is passed to :meth:`get_stack` directly.
 
-   The resolution of the sleep depends on the :ref:`granularity of the event
-   loop <asyncio-delayed-calls>`.
+      The *file* argument is an I/O stream to which the output
+      is written; by default output is written to :data:`sys.stderr`.
 
-   This function is a :ref:`coroutine <coroutine>`.
+   .. method:: get_name()
 
-.. coroutinefunction:: shield(arg, \*, loop=None)
+      Return the name of the Task.
 
-   Wait for a future, shielding it from cancellation.
+      If no name has been explicitly assigned to the Task, the default
+      asyncio Task implementation generates a default name during
+      instantiation.
 
-   The statement::
+      .. versionadded:: 3.8
 
-       res = await shield(something())
+   .. method:: set_name(value)
 
-   is exactly equivalent to the statement::
+      Set the name of the Task.
 
-       res = await something()
+      The *value* argument can be any object, which is then
+      converted to a string.
 
-   *except* that if the coroutine containing it is cancelled, the task running
-   in ``something()`` is not cancelled.  From the point of view of
-   ``something()``, the cancellation did not happen.  But its caller is still
-   cancelled, so the yield-from expression still raises
-   :exc:`~concurrent.futures.CancelledError`.  Note: If ``something()`` is
-   cancelled by other means this will still cancel ``shield()``.
+      In the default Task implementation, the name will be visible
+      in the :func:`repr` output of a task object.
 
-   If you want to completely ignore cancellation (not recommended) you can
-   combine ``shield()`` with a try/except clause, as follows::
+      .. versionadded:: 3.8
 
-       try:
-           res = await shield(something())
-       except CancelledError:
-           res = None
+   .. classmethod:: all_tasks(loop=None)
 
+      Return a set of all tasks for an event loop.
 
-.. coroutinefunction:: wait(futures, \*, loop=None, timeout=None,\
-                            return_when=ALL_COMPLETED)
+      By default all tasks for the current event loop are returned.
+      If *loop* is ``None``, the :func:`get_event_loop` function
+      is used to get the current loop.
 
-   Wait for the Futures and coroutine objects given by the sequence *futures*
-   to complete.  Coroutines will be wrapped in Tasks. Returns two sets of
-   :class:`Future`: (done, pending).
+      This function is **deprecated** and scheduled for removal in
+      Python 3.9.  Use the :func:`all_tasks` function instead.
 
-   The sequence *futures* must not be empty.
+   .. classmethod:: current_task(loop=None)
 
-   *timeout* can be used to control the maximum number of seconds to wait before
-   returning.  *timeout* can be an int or float.  If *timeout* is not specified
-   or ``None``, there is no limit to the wait time.
+      Return the currently running task or ``None``.
 
-   *return_when* indicates when this function should return.  It must be one of
-   the following constants of the :mod:`concurrent.futures` module:
+      If *loop* is ``None``, the :func:`get_event_loop` function
+      is used to get the current loop.
 
-   .. tabularcolumns:: |l|L|
+      This function is **deprecated** and scheduled for removal in
+      Python 3.9.  Use the :func:`current_task` function instead.
 
-   +-----------------------------+----------------------------------------+
-   | Constant                    | Description                            |
-   +=============================+========================================+
-   | :const:`FIRST_COMPLETED`    | The function will return when any      |
-   |                             | future finishes or is cancelled.       |
-   +-----------------------------+----------------------------------------+
-   | :const:`FIRST_EXCEPTION`    | The function will return when any      |
-   |                             | future finishes by raising an          |
-   |                             | exception.  If no future raises an     |
-   |                             | exception then it is equivalent to     |
-   |                             | :const:`ALL_COMPLETED`.                |
-   +-----------------------------+----------------------------------------+
-   | :const:`ALL_COMPLETED`      | The function will return when all      |
-   |                             | futures finish or are cancelled.       |
-   +-----------------------------+----------------------------------------+
 
-   Unlike :func:`~asyncio.wait_for`, ``wait()`` will not cancel the futures
-   when a timeout occurs.
+.. _asyncio_generator_based_coro:
 
-   This function is a :ref:`coroutine <coroutine>`.
+Generator-based Coroutines
+==========================
 
-   Usage::
+.. note::
 
-        done, pending = await asyncio.wait(fs)
+   Support for generator-based coroutines is **deprecated** and
+   scheduled for removal in Python 4.0.
 
-   .. note::
+Generator-based coroutines predate async/await syntax.  They are
+Python generators that use ``yield from`` expression is to await
+on Futures and other coroutines.
 
-      This does not raise :exc:`asyncio.TimeoutError`! Futures that aren't done
-      when the timeout occurs are returned in the second set.
+Generator-based coroutines should be decorated with
+:func:`@asyncio.coroutine <asyncio.coroutine>`, although this is not
+enforced.
 
 
-.. coroutinefunction:: wait_for(fut, timeout, \*, loop=None)
+.. decorator:: coroutine
 
-   Wait for the single :class:`Future` or :ref:`coroutine object <coroutine>`
-   to complete with timeout. If *timeout* is ``None``, block until the future
-   completes.
+    Decorator to mark generator-based coroutines.
 
-   Coroutine will be wrapped in :class:`Task`.
+    This decorator enables legacy generator-based coroutines to be
+    compatible with async/await code::
 
-   Returns result of the Future or coroutine.  When a timeout occurs, it
-   cancels the task and raises :exc:`asyncio.TimeoutError`. To avoid the task
-   cancellation, wrap it in :func:`shield`.  The function will wait until
-   the future is actually cancelled, so the total wait time may exceed
-   the *timeout*.
+        @asyncio.coroutine
+        def old_style_coroutine():
+            yield from asyncio.sleep(1)
 
-   If the wait is cancelled, the future *fut* is also cancelled.
+        async def main():
+            await old_style_coroutine()
+
+    This decorator is **deprecated** and is scheduled for removal in
+    Python 4.0.
 
-   This function is a :ref:`coroutine <coroutine>`, usage::
+    This decorator should not be used for :keyword:`async def`
+    coroutines.
 
-       result = await asyncio.wait_for(fut, 60.0)
+.. function:: iscoroutine(obj)
 
-   .. versionchanged:: 3.4.3
-      If the wait is cancelled, the future *fut* is now also cancelled.
+   Return ``True`` if *obj* is a :ref:`coroutine object <coroutine>`.
 
-   .. versionchanged:: 3.7
-      When *fut* is cancelled due to a timeout, ``wait_for`` now waits
-      for *fut* to be cancelled.  Previously,
-      it raised :exc:`~asyncio.TimeoutError` immediately.
+   This method is different from :func:`inspect.iscoroutine` because
+   it returns ``True`` for generator-based coroutines decorated with
+   :func:`@coroutine <coroutine>`.
+
+.. function:: iscoroutinefunction(func)
+
+   Return ``True`` if *func* is a :ref:`coroutine function
+   <coroutine>`.
+
+   This method is different from :func:`inspect.iscoroutinefunction`
+   because it returns ``True`` for generator-based coroutine functions
+   decorated with :func:`@coroutine <coroutine>`.
diff --git a/Doc/library/asyncio.rst b/Doc/library/asyncio.rst
index 0d58a94c8b9b..2c8ccbb390f0 100644
--- a/Doc/library/asyncio.rst
+++ b/Doc/library/asyncio.rst
@@ -1,15 +1,13 @@
-:mod:`asyncio` --- Asynchronous I/O, event loop, coroutines and tasks
-=====================================================================
+:mod:`asyncio` --- Asynchronous I/O
+===================================
 
 .. module:: asyncio
-   :synopsis: Asynchronous I/O, event loop, coroutines and tasks.
-
-.. versionadded:: 3.4
-
-**Source code:** :source:`Lib/asyncio/`
+   :synopsis: Asynchronous I/O.
 
 --------------
 
+.. TODO: rewrite the introduction section
+
 This module provides infrastructure for writing single-threaded concurrent
 code using coroutines, multiplexing I/O access over sockets and other
 resources, running network clients and servers, and other related primitives.
@@ -44,25 +42,40 @@ programming: see the :ref:`Develop with asyncio <asyncio-dev>` page which lists
 common traps and explains how to avoid them. :ref:`Enable the debug mode
 <asyncio-debug-mode>` during development to detect common issues.
 
-Table of contents:
+High-level APIs:
 
 .. toctree::
-   :maxdepth: 3
+   :maxdepth: 1
 
-   asyncio-eventloop.rst
-   asyncio-policy.rst
-   asyncio-platforms.rst
    asyncio-task.rst
-   asyncio-protocol.rst
    asyncio-stream.rst
-   asyncio-subprocess.rst
    asyncio-sync.rst
+   asyncio-subprocess.rst
    asyncio-queue.rst
-   asyncio-dev.rst
    asyncio-exceptions.rst
 
-.. seealso::
+Low-level APIs:
+
+.. toctree::
+   :maxdepth: 1
 
-   The :mod:`asyncio` module was designed in :PEP:`3156`. For a
-   motivational primer on transports and protocols, see :PEP:`3153`.
+   asyncio-eventloop.rst
+   asyncio-future.rst
+   asyncio-protocol.rst
+   asyncio-policy.rst
+   asyncio-platforms.rst
+
+Guides and Tutorials:
+
+.. toctree::
+   :maxdepth: 1
+
+   asyncio-dev.rst
+
+
+.. seealso::
 
+   The :mod:`asyncio` module was proposed in :PEP:`3156`.
+   Since the acceptance of the PEP many new APIs were added and many
+   original APIs were altered.  The PEP should be treated as a
+   historical document.



More information about the Python-checkins mailing list