Skip to main content

WebSocket library for Trio

Project description

PyPI Python Versions MIT License Build Status Coverage

Trio WebSocket

This project implements the WebSocket protocol. It is based on the wsproto project, which is a Sans-IO state machine that implements the majority of the WebSocket protocol, including framing, codecs, and events. This library implements the I/O using Trio.

Installation

trio-websocket requires Python v3.5 or greater. To install from PyPI:

pip install trio-websocket

If you want to help develop trio-websocket, clone the repository and run this command from the repository root:

pip install --editable .[dev]

Sample client

The following example demonstrates opening a WebSocket by URL. The connection may also be opened with open_websocket(…), which takes a host, port, and resource as arguments.

import trio
from trio_websocket import open_websocket_url


async def main():
    try:
        async with open_websocket_url('ws://localhost/foo') as conn:
            await conn.send_message('hello world!')
    except OSError as ose:
        logging.error('Connection attempt failed: %s', ose)

trio.run(main)

A more detailed example is in examples/client.py. Note: if you want to run this example client with SSL, you'll need to install the trustme module from PyPI (installed automtically if you used the [dev] extras when installing trio-websocket) and then generate a self-signed certificate by running example/generate-cert.py.

Sample server

A WebSocket server requires a bind address, a port, and a coroutine to handle incoming connections. This example demonstrates an "echo server" that replies to each incoming message with an identical outgoing message.

import trio
from trio_websocket import serve_websocket, ConnectionClosed

async def echo_server(websocket):
    while True:
        try:
            message = await websocket.get_message()
            await websocket.send_message(message)
        except ConnectionClosed:
            break

async def main():
    await serve_websocket(echo_server, '127.0.0.1', 8000, ssl_context=None)

trio.run(main)

A longer example is in examples/server.py. See the note above about using SSL with the example client.

Unit Tests

Unit tests are written in the pytest style. You must install the development dependencies as described in the installation section above. The --cov=trio_websocket flag turns on code coverage.

$ pytest --cov=trio_websocket
=== test session starts ===
platform linux -- Python 3.6.6, pytest-3.8.0, py-1.6.0, pluggy-0.7.1
rootdir: /home/mhaase/code/trio-websocket, inifile: pytest.ini
plugins: trio-0.5.0, cov-2.6.0
collected 21 items

tests/test_connection.py ..................... [100%]

--- coverage: platform linux, python 3.6.6-final-0 ---
Name                         Stmts   Miss  Cover
------------------------------------------------
trio_websocket/__init__.py     297     40    87%
trio_websocket/_channel.py     140     52    63%
trio_websocket/version.py        1      0   100%
------------------------------------------------
TOTAL                          438     92    79%

=== 21 passed in 0.54 seconds ===

Integration Testing with Autobahn

The Autobahn Test Suite contains over 500 integration tests for WebSocket servers and clients. These test suites are contained in a Docker container. You will need to install Docker before you can run these integration tests.

Client Tests

To test the client, you will need two terminal windows. In the first terminal, run the following commands:

$ cd autobahn
$ docker run -it --rm \
      -v "${PWD}/config:/config" \
      -v "${PWD}/reports:/reports" \
      -p 9001:9001 \
      --name autobahn \
      crossbario/autobahn-testsuite

The first time you run this command, Docker will download some files, which may take a few minutes. When the test suite is ready, it will display:

Autobahn WebSocket 0.8.0/0.10.9 Fuzzing Server (Port 9001)
Ok, will run 249 test cases for any clients connecting

Now in the second terminal, run the Autobahn client:

$ cd autobahn
$ python client.py ws://localhost:9001
INFO:client:Case count=249
INFO:client:Running test case 1 of 249
INFO:client:Running test case 2 of 249
INFO:client:Running test case 3 of 249
INFO:client:Running test case 4 of 249
INFO:client:Running test case 5 of 249
<snip>

When the client finishes running, an HTML report is published to the autobahn/reports/clients directory. If any tests fail, you can debug individual tests by specifying the integer test case ID (not the dotted test case ID), e.g. to run test case #29:

$ python client.py ws://localhost:9001 29

Server Tests

Once again, you will need two terminal windows. In the first terminal, run:

$ cd autobahn
$ python server.py

In the second terminal, you will run the Docker image.

$ cd autobahn
$ docker run -it --rm \
      -v "${PWD}/config:/config" \
      -v "${PWD}/reports:/reports" \
      --name autobahn \
      crossbario/autobahn-testsuite \
      /usr/local/bin/wstest --mode fuzzingclient --spec /config/fuzzingclient.json

If a test fails, server.py does not support the same debug_cases argument as client.py, but you can modify fuzzingclient.json to specify a subset of cases to run, e.g. 3.* to run all test cases in section 3.

Release Process

  • Remove -dev suffix from version.py.
  • Commit and push version change.
  • Create and push tag, e.g. git tag 1.0.0 && git push origin 1.0.0.
  • Build package: python setup.py sdist
  • Upload to PyPI: twine upload dist/*
  • Increment version and add -dev suffix.
  • Commit and push version change.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

trio-websocket-0.2.0.tar.gz (12.9 kB view hashes)

Uploaded Source

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page