From 7619d7bfae53b8dc540e444a5088f501e53531a9 Mon Sep 17 00:00:00 2001 From: Guido van Rossum Date: Mon, 25 Nov 2013 11:44:59 -0800 Subject: [PATCH] Document open_connection(), start_server(), and related Stream* classes. --- pep-3156.txt | 94 ++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 91 insertions(+), 3 deletions(-) diff --git a/pep-3156.txt b/pep-3156.txt index 20731d9b6..a022682c8 100644 --- a/pep-3156.txt +++ b/pep-3156.txt @@ -1680,6 +1680,97 @@ transport can be used -- these do not return Futures. A standard protocol implementation should be provided that sets this up and kicks off the coroutine when ``connection_made()`` is called. +Convenience Utilities +--------------------- + +A few functions and classes are provided to simplify the writing of +basic stream-based clients and servers. Thes are: + +- ``asyncio.open_connection(host, port)``: A wrapper for + ``EventLoop.create_connection()`` that does not require you to + provide a ``Protocol`` factory or class. This is a coroutine that + returns a ``(reader, writer)`` pair, where ``reader`` is an instance + of ``StreamReader`` and ``writer`` is an instance of + ``StreamWriter`` (both described below). + +- ``asyncio.start_server(client_connected_cb, host, port)``: A wrapper + for ``EventLoop.create_server()`` that takes a simple callback + function rather than a ``Protocol`` factory or class. This is a + coroutine that returns a ``Server`` object just as + ``create_server()`` does. Each time a client connection is + accepted, ``client_connected_cb(reader, writer)`` is called, where + ``reader`` is an instance of ``StreamReader`` and ``writer`` is an + instance of ``StreamWriter`` (both described below). If the result + returned by ``client_connected_cb()`` is a coroutine, it is + automatically wrapped in a ``Task``. + +- ``StreamReader``: A class offering an interface not unlike that of a + read-only binary stream, except that the various reading methods are + coroutines. It is normally driven by a ``StreamReaderProtocol`` + instance. Note that there should be only one reader. The interface + for the reader is: + + - ``readline()``: A coroutine that reads a string of bytes + representing a line of text ending in ``'\n'``, or until the end + of the stream, whichever comes first. + + - ``read(n)``: A coroutine that reads up to ``n`` bytes. If ``n`` + is omitted or negative, it reads until the end of the stream. + + - ``readexactly(n)``: A coroutine that reads exactly ``n`` bytes, or + until the end of the stream, whichever comes first. + + - ``exception()``: Return the exception that has been set on the + stream using ``set_exception()``, or None if no exception is set. + + The interface for the driver is: + + - ``feed_data(data)``: Append ``data`` (a ``bytes`` object) to the + internal buffer. This unblocks a blocked reading coroutine if it + provides sufficient data to fulfill the reader's contract. + + - ``feed_eof()``: Signal the end of the buffer. This unclocks a + blocked reading coroutine. No more data should be fed to the + reader after this call. + + - ``set_exception(exc)``: Set an exception on the stream. All + subsequent reading methods will raise this exception. No more + data should be fed to the reader after this call. + +- ``StreamWriter``: A class offering an interface not unlike that of a + write-only binary stream. It wraps a transport. The interface is + an extended subset of the transport interface: the following methods + behave the same as the corresponding transport methods: ``write()``, + ``writelines()``, ``write_eof()``, ``can_write_eof()``, + ``get_extra_info()``, ``close()``. Note that the writing methods + are _not_ coroutines (this is the same as for transports, but + different from the ``StreamReader`` class). The following method is + in addition to the transport interface: + + - ``drain()``: This should be called with ``yield from`` after + writing significant data, for the purpose of flow control. The + intended use is like this:: + + writer.write(data) + yield from writer.drain() + + Note that this is not technically a coroutine: it returns either a + Future or an empty tuple (both can be passed to ``yield from``). + Use of this method is optional. However, when it is not used, the + internal buffer of the transport underlying the ``StreamWriter`` + may fill up with all data that was ever written to the writer. If + an app does not have a strict limit on how much data it writes, it + _should_ call ``yield from drain()`` occasionally to avoid filling + up the transport buffer. + +- ``StreamReaderProtocol``: A protocol implementation used as an + adapter between the bidirectional stream transport/protocol + interface and the ``StreamReader`` and ``StreamWriter`` classes. It + acts as a driver for a specific ``StreamReader`` instance, calling + its methods ``feed_data()``, ``feed_eof()``, and ``set_exception()`` + in response to various protocol callbacks. It also controls the + behavior of the ``drain()`` method of the ``StreamWriter`` instance. + Synchronization =============== @@ -1754,9 +1845,6 @@ The following classes and exceptions are provided by ``asyncio.queues``. TO DO ===== -- Document ``StreamReader``, ``StreamWriter``, ``open_connection()``, - and ``start_server()``. - - Document all places that take a ``loop`` keyword argument. - Document ``logger`` object.