diff --git a/README.rst b/README.rst index 53b5c2edd..ca96d3d94 100644 --- a/README.rst +++ b/README.rst @@ -1,20 +1,28 @@ -README -====== +WebSockets +========== -``websockets`` is an implementation of `RFC 6455`_, the WebSocket protocol, -with a focus on simplicity and correctness. +``websockets`` is a library for developing WebSocket servers_ and clients_ in +Python. It implements `RFC 6455`_ with a focus on correctness and simplicity. +It passes the `Autobahn Testsuite`_. -It's built on top on Python's asynchronous I/O features described in `PEP -3156`_. +Built on top on Python's asynchronous I/O support introduced in `PEP 3156`_, +it provides an API based on coroutines, making it easy to write highly +concurrent applications. -It requires Python ≥ 3.4 or Python 3.3 with the ``asyncio`` module, which is -available in the `Tulip`_ repository or simply with ``pip install asyncio``. +Installation is as simple as ``pip install websockets``. It requires Python ≥ +3.4 or Python 3.3 with the ``asyncio`` module, which is available with ``pip +install asyncio`` or in the `Tulip`_ repository. -It passes the `Autobahn Testsuite`_. +Documentation is available at http://aaugustin.github.io/websockets/. + +Bug reports, patches and suggestions welcome! Just open an issue_ or send a +`pull request`_. +.. _servers: https://github.com/aaugustin/websockets/blob/master/example/server.py +.. _clients: https://github.com/aaugustin/websockets/blob/master/example/client.py .. _RFC 6455: http://tools.ietf.org/html/rfc6455 +.. _Autobahn Testsuite: https://github.com/aaugustin/websockets/blob/master/compliance/README.rst .. _PEP 3156: http://www.python.org/dev/peps/pep-3156/ .. _Tulip: http://code.google.com/p/tulip/ -.. _Autobahn Testsuite: https://github.com/aaugustin/websockets/blob/master/compliance/README.rst - -The documentation is available at http://aaugustin.github.io/websockets/. +.. _issue: https://github.com/aaugustin/websockets/issues/new +.. _pull request: https://github.com/aaugustin/websockets/compare/ diff --git a/docs/index.rst b/docs/index.rst index 6b11da070..054d1f782 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -3,21 +3,29 @@ WebSockets ========== -``websockets`` is an implementation of `RFC 6455`_, the WebSocket protocol, -with a focus on simplicity and correctness. +``websockets`` is a library for developing WebSocket servers_ and clients_ in +Python. It implements `RFC 6455`_ with a focus on correctness and simplicity. +It passes the `Autobahn Testsuite`_. -It's built on top on Python's asynchronous I/O features described in `PEP -3156`_. +Built on top on Python's asynchronous I/O support introduced in `PEP 3156`_, +it provides an API based on coroutines, making it easy to write highly +concurrent applications. -It requires Python ≥ 3.4 or Python 3.3 with the ``asyncio`` module, which is -available in the `Tulip`_ repository or simply with ``pip install asyncio``. +Installation is as simple as ``pip install websockets``. It requires Python ≥ +3.4 or Python 3.3 with the ``asyncio`` module, which is available with ``pip +install asyncio`` or in the `Tulip`_ repository. -You can download the code and report issues `on GitHub`_. +Bug reports, patches and suggestions welcome! Just open an issue_ or send a +`pull request`_. +.. _servers: https://github.com/aaugustin/websockets/blob/master/example/server.py +.. _clients: https://github.com/aaugustin/websockets/blob/master/example/client.py .. _RFC 6455: http://tools.ietf.org/html/rfc6455 +.. _Autobahn Testsuite: https://github.com/aaugustin/websockets/blob/master/compliance/README.rst .. _PEP 3156: http://www.python.org/dev/peps/pep-3156/ .. _Tulip: http://code.google.com/p/tulip/ -.. _on GitHub: https://github.com/aaugustin/websockets +.. _issue: https://github.com/aaugustin/websockets/issues/new +.. _pull request: https://github.com/aaugustin/websockets/compare/ Example ------- @@ -25,7 +33,7 @@ Example .. _server-example: Here's a WebSocket server example. It reads a name from the client and sends a -greeting. +message. .. literalinclude:: ../example/server.py @@ -73,7 +81,7 @@ Server .. automodule:: websockets.server - .. autofunction:: serve(ws_handler, host=None, port=None, **kwargs) + .. autofunction:: serve(ws_handler, host=None, port=None, *, klass=WebSocketServerProtocol, **kwds) .. autoclass:: WebSocketServerProtocol(self, ws_handler, timeout=10) :members: handshake @@ -83,7 +91,7 @@ Client .. automodule:: websockets.client - .. autofunction:: connect(uri) + .. autofunction:: connect(uri, *, klass=WebSocketClientProtocol, **kwds) .. autoclass:: WebSocketClientProtocol(self, timeout=10) :members: handshake diff --git a/websockets/client.py b/websockets/client.py index 525ef534c..496ded4cc 100644 --- a/websockets/client.py +++ b/websockets/client.py @@ -17,7 +17,8 @@ class WebSocketClientProtocol(WebSocketCommonProtocol): """ Complete WebSocket client implementation as a Tulip protocol. - This class inherits :class:`~websockets.protocol.WebSocketCommonProtocol`. + This class inherits most of its methods from + :class:`~websockets.protocol.WebSocketCommonProtocol`. """ is_client = True diff --git a/websockets/protocol.py b/websockets/protocol.py index 37e970d84..381ea4ac6 100644 --- a/websockets/protocol.py +++ b/websockets/protocol.py @@ -29,26 +29,29 @@ class WebSocketCommonProtocol(asyncio.Protocol): """ This class implements common parts of the WebSocket protocol. - It assumes that the WebSocket connection is established. It runs a Task - that stores incoming data frames in a queue and deals with control frames - automatically. It sends outgoing data frames and performs the closing - handshake. + It assumes that the WebSocket connection is established. The handshake is + managed in subclasses such as + :class:`~websockets.server.WebSocketServerProtocol` and + :class:`~websockets.client.WebSocketClientProtocol`. + + It runs a task that stores incoming data frames in a queue and deals with + control frames automatically. It sends outgoing data frames and performs + the closing handshake. The `timeout` parameter defines the maximum wait time in seconds for - completing the closing handshake and for terminating the TCP connection. - :meth:`close()` will complete in at most twice this time. + completing the closing handshake and, only on the client side, for + terminating the TCP connection. :meth:`close()` will complete in at most + this time on the server side and twice this time on the client side. Once the connection is closed, the status code is available in the - :attr:`close_code` attribute and the reason in :attr:`close_reason`. If - you need to wait until the connection is closed, you can yield from - the :attr:`worker` attribute. - - There are only two differences between the client-side and the server-side - behavior: masking the payload and closing the underlying TCP connection. - This class implements the server-side behavior by default. To get the - client-side behavior, set the class attribute ``is_client`` to ``True``. + :attr:`close_code` attribute and the reason in :attr:`close_reason`. """ + # There are only two differences between the client-side and the server- + # side behavior: masking the payload and closing the underlying TCP + # connection. This class implements the server-side behavior by default. + # To get the client-side behavior, set is_client = True. + is_client = False state = 'OPEN' diff --git a/websockets/server.py b/websockets/server.py index ef456b4d4..f998173a0 100644 --- a/websockets/server.py +++ b/websockets/server.py @@ -21,7 +21,8 @@ class WebSocketServerProtocol(WebSocketCommonProtocol): """ Complete WebSocket server implementation as a Tulip protocol. - This class inherits :class:`~websockets.protocol.WebSocketCommonProtocol`. + This class inherits most of its methods from + :class:`~websockets.protocol.WebSocketCommonProtocol`. For the sake of simplicity, this protocol doesn't inherit a proper HTTP implementation, and it doesn't send appropriate HTTP responses when @@ -30,9 +31,9 @@ class WebSocketServerProtocol(WebSocketCommonProtocol): state = 'CONNECTING' - def __init__(self, ws_handler=None, *args, **kwargs): + def __init__(self, ws_handler=None, **kwargs): self.ws_handler = ws_handler - super().__init__(*args, **kwargs) + super().__init__(**kwargs) def connection_made(self, transport): super().connection_made(transport) @@ -98,8 +99,11 @@ def serve(ws_handler, host=None, port=None, *, """ This coroutine creates a WebSocket server. - It's a thin wrapper around the event loop's ``create_server`` method. It - returns a ``Server`` object with a ``close`` method to stop the server. + It's a thin wrapper around the event loop's ``create_server`` method. + ``host``, ``port`` as well as extra keyword arguments are passed to + ``create_server``. + + It returns a ``Server`` object with a ``close`` method to stop the server. `ws_handler` is the WebSocket handler. It must be a coroutine accepting two arguments: a :class:`~websockets.server.WebSocketServerProtocol` and