pax_global_header 0000666 0000000 0000000 00000000064 14762124503 0014516 g ustar 00root root 0000000 0000000 52 comment=37c9bc0781f0cc5af7c729947ef1833c1e12b70d
websockets-15.0.1/ 0000775 0000000 0000000 00000000000 14762124503 0013753 5 ustar 00root root 0000000 0000000 websockets-15.0.1/.github/ 0000775 0000000 0000000 00000000000 14762124503 0015313 5 ustar 00root root 0000000 0000000 websockets-15.0.1/.github/FUNDING.yml 0000664 0000000 0000000 00000000120 14762124503 0017121 0 ustar 00root root 0000000 0000000 github: python-websockets
open_collective: websockets
tidelift: pypi/websockets
websockets-15.0.1/.github/ISSUE_TEMPLATE/ 0000775 0000000 0000000 00000000000 14762124503 0017476 5 ustar 00root root 0000000 0000000 websockets-15.0.1/.github/ISSUE_TEMPLATE/config.yml 0000664 0000000 0000000 00000000034 14762124503 0021463 0 ustar 00root root 0000000 0000000 blank_issues_enabled: false
websockets-15.0.1/.github/ISSUE_TEMPLATE/issue.md 0000664 0000000 0000000 00000001572 14762124503 0021155 0 ustar 00root root 0000000 0000000 ---
name: Report an issue
about: Let us know about a problem with websockets
title: ''
labels: ''
assignees: ''
---
websockets-15.0.1/.github/dependabot.yml 0000664 0000000 0000000 00000000277 14762124503 0020151 0 ustar 00root root 0000000 0000000 version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
day: "saturday"
time: "07:00"
timezone: "Europe/Paris"
websockets-15.0.1/.github/workflows/ 0000775 0000000 0000000 00000000000 14762124503 0017350 5 ustar 00root root 0000000 0000000 websockets-15.0.1/.github/workflows/release.yml 0000664 0000000 0000000 00000004675 14762124503 0021527 0 ustar 00root root 0000000 0000000 name: Make release
on:
push:
tags:
- '*'
workflow_dispatch:
jobs:
sdist:
name: Build source distribution and architecture-independent wheel
runs-on: ubuntu-latest
steps:
- name: Check out repository
uses: actions/checkout@v4
- name: Install Python 3.x
uses: actions/setup-python@v5
with:
python-version: 3.x
- name: Install build
run: pip install build
- name: Build sdist & wheel
run: python -m build
env:
BUILD_EXTENSION: no
- name: Save sdist & wheel
uses: actions/upload-artifact@v4
with:
name: dist-architecture-independent
path: |
dist/*.tar.gz
dist/*.whl
wheels:
name: Build architecture-specific wheels on ${{ matrix.os }}
runs-on: ${{ matrix.os }}
strategy:
matrix:
os:
- ubuntu-latest
- windows-latest
- macOS-latest
steps:
- name: Check out repository
uses: actions/checkout@v4
- name: Install Python 3.x
uses: actions/setup-python@v5
with:
python-version: 3.x
- name: Set up QEMU
if: runner.os == 'Linux'
uses: docker/setup-qemu-action@v3
with:
platforms: all
- name: Build wheels
uses: pypa/cibuildwheel@v2.22.0
env:
BUILD_EXTENSION: yes
- name: Save wheels
uses: actions/upload-artifact@v4
with:
name: dist-${{ matrix.os }}
path: wheelhouse/*.whl
upload:
name: Upload
needs:
- sdist
- wheels
runs-on: ubuntu-latest
# Don't release when running the workflow manually from GitHub's UI.
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/')
permissions:
id-token: write
attestations: write
contents: write
steps:
- name: Download artifacts
uses: actions/download-artifact@v4
with:
pattern: dist-*
merge-multiple: true
path: dist
- name: Attest provenance
uses: actions/attest-build-provenance@v2
with:
subject-path: dist/*
- name: Upload to PyPI
uses: pypa/gh-action-pypi-publish@release/v1
- name: Create GitHub release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: gh release -R python-websockets/websockets create ${{ github.ref_name }} --notes "See https://websockets.readthedocs.io/en/stable/project/changelog.html for details."
websockets-15.0.1/.github/workflows/tests.yml 0000664 0000000 0000000 00000003462 14762124503 0021242 0 ustar 00root root 0000000 0000000 name: Run tests
on:
push:
branches:
- main
pull_request:
branches:
- main
env:
WEBSOCKETS_TESTS_TIMEOUT_FACTOR: 10
jobs:
coverage:
name: Run test coverage checks
runs-on: ubuntu-latest
steps:
- name: Check out repository
uses: actions/checkout@v4
- name: Install Python 3.x
uses: actions/setup-python@v5
with:
python-version: "3.x"
- name: Install tox
run: pip install tox
- name: Run tests with coverage
run: tox -e coverage
- name: Run tests with per-module coverage
run: tox -e maxi_cov
quality:
name: Run code quality checks
runs-on: ubuntu-latest
steps:
- name: Check out repository
uses: actions/checkout@v4
- name: Install Python 3.x
uses: actions/setup-python@v5
with:
python-version: "3.x"
- name: Install tox
run: pip install tox
- name: Check code formatting & style
run: tox -e ruff
- name: Check types statically
run: tox -e mypy
matrix:
name: Run tests on Python ${{ matrix.python }}
needs:
- coverage
- quality
runs-on: ubuntu-latest
strategy:
matrix:
python:
- "3.9"
- "3.10"
- "3.11"
- "3.12"
- "3.13"
- "pypy-3.10"
is_main:
- ${{ github.event_name == 'push' && github.ref == 'refs/heads/main' }}
exclude:
- python: "pypy-3.10"
is_main: false
steps:
- name: Check out repository
uses: actions/checkout@v4
- name: Install Python ${{ matrix.python }}
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python }}
allow-prereleases: true
- name: Install tox
run: pip install tox
- name: Run tests
run: tox -e py
websockets-15.0.1/.gitignore 0000664 0000000 0000000 00000000270 14762124503 0015742 0 ustar 00root root 0000000 0000000 *.pyc
*.so
.coverage
.direnv/
.envrc
.idea/
.mypy_cache/
.tox/
.vscode/
build/
compliance/reports/
dist/
docs/_build/
experiments/compression/corpus/
htmlcov/
src/websockets.egg-info/
websockets-15.0.1/.readthedocs.yml 0000664 0000000 0000000 00000000340 14762124503 0017036 0 ustar 00root root 0000000 0000000 version: 2
build:
os: ubuntu-20.04
tools:
python: "3.10"
jobs:
post_checkout:
- git fetch --unshallow
sphinx:
configuration: docs/conf.py
python:
install:
- requirements: docs/requirements.txt
websockets-15.0.1/CODE_OF_CONDUCT.md 0000664 0000000 0000000 00000006251 14762124503 0016556 0 ustar 00root root 0000000 0000000 # Contributor Covenant Code of Conduct
## Our Pledge
In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
## Our Standards
Examples of behavior that contributes to creating a positive environment include:
* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery and unwelcome sexual attention or advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a professional setting
## Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
## Scope
This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at aymeric DOT augustin AT fractalideas DOT com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]
[homepage]: http://contributor-covenant.org
[version]: http://contributor-covenant.org/version/1/4/
websockets-15.0.1/LICENSE 0000664 0000000 0000000 00000002752 14762124503 0014766 0 ustar 00root root 0000000 0000000 Copyright (c) Aymeric Augustin and contributors
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
websockets-15.0.1/MANIFEST.in 0000664 0000000 0000000 00000000166 14762124503 0015514 0 ustar 00root root 0000000 0000000 include LICENSE
include src/websockets/py.typed
include src/websockets/speedups.c # required when BUILD_EXTENSION=no
websockets-15.0.1/Makefile 0000664 0000000 0000000 00000001406 14762124503 0015414 0 ustar 00root root 0000000 0000000 .PHONY: default style types tests coverage maxi_cov build clean
export PYTHONASYNCIODEBUG=1
export PYTHONPATH=src
export PYTHONWARNINGS=default
build:
python setup.py build_ext --inplace
style:
ruff format compliance src tests
ruff check --fix compliance src tests
types:
mypy --strict src
tests:
python -m unittest
coverage:
coverage run --source src/websockets,tests -m unittest
coverage html
coverage report --show-missing --fail-under=100
maxi_cov:
python tests/maxi_cov.py
coverage html
coverage report --show-missing --fail-under=100
clean:
find src -name '*.so' -delete
find . -name '*.pyc' -delete
find . -name __pycache__ -delete
rm -rf .coverage .mypy_cache build compliance/reports dist docs/_build htmlcov MANIFEST src/websockets.egg-info
websockets-15.0.1/README.rst 0000664 0000000 0000000 00000014377 14762124503 0015456 0 ustar 00root root 0000000 0000000 .. image:: logo/horizontal.svg
:width: 480px
:alt: websockets
|licence| |version| |pyversions| |tests| |docs| |openssf|
.. |licence| image:: https://img.shields.io/pypi/l/websockets.svg
:target: https://pypi.python.org/pypi/websockets
.. |version| image:: https://img.shields.io/pypi/v/websockets.svg
:target: https://pypi.python.org/pypi/websockets
.. |pyversions| image:: https://img.shields.io/pypi/pyversions/websockets.svg
:target: https://pypi.python.org/pypi/websockets
.. |tests| image:: https://img.shields.io/github/checks-status/python-websockets/websockets/main?label=tests
:target: https://github.com/python-websockets/websockets/actions/workflows/tests.yml
.. |docs| image:: https://img.shields.io/readthedocs/websockets.svg
:target: https://websockets.readthedocs.io/
.. |openssf| image:: https://bestpractices.coreinfrastructure.org/projects/6475/badge
:target: https://bestpractices.coreinfrastructure.org/projects/6475
What is ``websockets``?
-----------------------
websockets is a library for building WebSocket_ servers and clients in Python
with a focus on correctness, simplicity, robustness, and performance.
.. _WebSocket: https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API
Built on top of ``asyncio``, Python's standard asynchronous I/O framework, the
default implementation provides an elegant coroutine-based API.
An implementation on top of ``threading`` and a Sans-I/O implementation are also
available.
`Documentation is available on Read the Docs. `_
.. copy-pasted because GitHub doesn't support the include directive
Here's an echo server with the ``asyncio`` API:
.. code:: python
#!/usr/bin/env python
import asyncio
from websockets.asyncio.server import serve
async def echo(websocket):
async for message in websocket:
await websocket.send(message)
async def main():
async with serve(echo, "localhost", 8765) as server:
await server.serve_forever()
asyncio.run(main())
Here's how a client sends and receives messages with the ``threading`` API:
.. code:: python
#!/usr/bin/env python
from websockets.sync.client import connect
def hello():
with connect("ws://localhost:8765") as websocket:
websocket.send("Hello world!")
message = websocket.recv()
print(f"Received: {message}")
hello()
Does that look good?
`Get started with the tutorial! `_
.. raw:: html
websockets for enterprise
Available as part of the Tidelift Subscription
The maintainers of websockets and thousands of other packages are working with Tidelift to deliver commercial support and maintenance for the open source dependencies you use to build your applications. Save time, reduce risk, and improve code health, while paying the maintainers of the exact dependencies you use. Learn more.
(If you contribute to websockets and would like to become an official support provider, let me know.)
Why should I use ``websockets``?
--------------------------------
The development of ``websockets`` is shaped by four principles:
1. **Correctness**: ``websockets`` is heavily tested for compliance with
:rfc:`6455`. Continuous integration fails under 100% branch coverage.
2. **Simplicity**: all you need to understand is ``msg = await ws.recv()`` and
``await ws.send(msg)``. ``websockets`` takes care of managing connections
so you can focus on your application.
3. **Robustness**: ``websockets`` is built for production. For example, it was
the only library to `handle backpressure correctly`_ before the issue
became widely known in the Python community.
4. **Performance**: memory usage is optimized and configurable. A C extension
accelerates expensive operations. It's pre-compiled for Linux, macOS and
Windows and packaged in the wheel format for each system and Python version.
Documentation is a first class concern in the project. Head over to `Read the
Docs`_ and see for yourself.
.. _Read the Docs: https://websockets.readthedocs.io/
.. _handle backpressure correctly: https://vorpus.org/blog/some-thoughts-on-asynchronous-api-design-in-a-post-asyncawait-world/#websocket-servers
Why shouldn't I use ``websockets``?
-----------------------------------
* If you prefer callbacks over coroutines: ``websockets`` was created to
provide the best coroutine-based API to manage WebSocket connections in
Python. Pick another library for a callback-based API.
* If you're looking for a mixed HTTP / WebSocket library: ``websockets`` aims
at being an excellent implementation of :rfc:`6455`: The WebSocket Protocol
and :rfc:`7692`: Compression Extensions for WebSocket. Its support for HTTP
is minimal — just enough for an HTTP health check.
If you want to do both in the same server, look at HTTP + WebSocket servers
that build on top of ``websockets`` to support WebSocket connections, like
uvicorn_ or Sanic_.
.. _uvicorn: https://www.uvicorn.org/
.. _Sanic: https://sanic.dev/en/
What else?
----------
Bug reports, patches and suggestions are welcome!
To report a security vulnerability, please use the `Tidelift security
contact`_. Tidelift will coordinate the fix and disclosure.
.. _Tidelift security contact: https://tidelift.com/security
For anything else, please open an issue_ or send a `pull request`_.
.. _issue: https://github.com/python-websockets/websockets/issues/new
.. _pull request: https://github.com/python-websockets/websockets/compare/
Participants must uphold the `Contributor Covenant code of conduct`_.
.. _Contributor Covenant code of conduct: https://github.com/python-websockets/websockets/blob/main/CODE_OF_CONDUCT.md
``websockets`` is released under the `BSD license`_.
.. _BSD license: https://github.com/python-websockets/websockets/blob/main/LICENSE
websockets-15.0.1/SECURITY.md 0000664 0000000 0000000 00000000374 14762124503 0015550 0 ustar 00root root 0000000 0000000 # Security
## Policy
Only the latest version receives security updates.
## Contact information
Please report security vulnerabilities to the
[Tidelift security team](https://tidelift.com/security).
Tidelift will coordinate the fix and disclosure.
websockets-15.0.1/compliance/ 0000775 0000000 0000000 00000000000 14762124503 0016065 5 ustar 00root root 0000000 0000000 websockets-15.0.1/compliance/README.rst 0000664 0000000 0000000 00000005524 14762124503 0017562 0 ustar 00root root 0000000 0000000 Autobahn Testsuite
==================
General information and installation instructions are available at
https://github.com/crossbario/autobahn-testsuite.
Running the test suite
----------------------
All commands below must be run from the root directory of the repository.
To get acceptable performance, compile the C extension first:
.. code-block:: console
$ python setup.py build_ext --inplace
Run each command in a different shell. Testing takes several minutes to complete
— wstest is the bottleneck. When clients finish, stop servers with Ctrl-C.
You can exclude slow tests by modifying the configuration files as follows::
"exclude-cases": ["9.*", "12.*", "13.*"]
The test server and client applications shouldn't display any exceptions.
To test the servers:
.. code-block:: console
$ PYTHONPATH=src python compliance/asyncio/server.py
$ PYTHONPATH=src python compliance/sync/server.py
$ docker run --interactive --tty --rm \
--volume "${PWD}/compliance/config:/config" \
--volume "${PWD}/compliance/reports:/reports" \
--name fuzzingclient \
crossbario/autobahn-testsuite \
wstest --mode fuzzingclient --spec /config/fuzzingclient.json
$ open compliance/reports/servers/index.html
To test the clients:
.. code-block:: console
$ docker run --interactive --tty --rm \
--volume "${PWD}/compliance/config:/config" \
--volume "${PWD}/compliance/reports:/reports" \
--publish 9001:9001 \
--name fuzzingserver \
crossbario/autobahn-testsuite \
wstest --mode fuzzingserver --spec /config/fuzzingserver.json
$ PYTHONPATH=src python compliance/asyncio/client.py
$ PYTHONPATH=src python compliance/sync/client.py
$ open compliance/reports/clients/index.html
Conformance notes
-----------------
Some test cases are more strict than the RFC. Given the implementation of the
library and the test client and server applications, websockets passes with a
"Non-Strict" result in these cases.
In 3.2, 3.3, 4.1.3, 4.1.4, 4.2.3, 4.2.4, and 5.15 websockets notices the
protocol error and closes the connection at the library level before the
application gets a chance to echo the previous frame.
In 6.4.1, 6.4.2, 6.4.3, and 6.4.4, even though it uses an incremental decoder,
websockets doesn't notice the invalid utf-8 fast enough to get a "Strict" pass.
These tests are more strict than the RFC.
Test case 7.1.5 fails because websockets treats closing the connection in the
middle of a fragmented message as a protocol error. As a consequence, it sends
a close frame with code 1002. The test suite expects a close frame with code
1000, echoing the close code that it sent. This isn't required. RFC 6455 states
that "the endpoint typically echos the status code it received", which leaves
the possibility to send a close frame with a different status code.
websockets-15.0.1/compliance/asyncio/ 0000775 0000000 0000000 00000000000 14762124503 0017532 5 ustar 00root root 0000000 0000000 websockets-15.0.1/compliance/asyncio/client.py 0000664 0000000 0000000 00000002550 14762124503 0021364 0 ustar 00root root 0000000 0000000 import asyncio
import json
import logging
from websockets.asyncio.client import connect
from websockets.exceptions import WebSocketException
logging.basicConfig(level=logging.WARNING)
SERVER = "ws://localhost:9001"
AGENT = "websockets.asyncio"
async def get_case_count():
async with connect(f"{SERVER}/getCaseCount") as ws:
return json.loads(await ws.recv())
async def run_case(case):
async with connect(
f"{SERVER}/runCase?case={case}&agent={AGENT}",
max_size=2**25,
) as ws:
try:
async for msg in ws:
await ws.send(msg)
except WebSocketException:
pass
async def update_reports():
async with connect(
f"{SERVER}/updateReports?agent={AGENT}",
open_timeout=60,
):
pass
async def main():
cases = await get_case_count()
for case in range(1, cases + 1):
print(f"Running test case {case:03d} / {cases}... ", end="\t")
try:
await run_case(case)
except WebSocketException as exc:
print(f"ERROR: {type(exc).__name__}: {exc}")
except Exception as exc:
print(f"FAIL: {type(exc).__name__}: {exc}")
else:
print("OK")
print(f"Ran {cases} test cases")
await update_reports()
print("Updated reports")
if __name__ == "__main__":
asyncio.run(main())
websockets-15.0.1/compliance/asyncio/server.py 0000664 0000000 0000000 00000001226 14762124503 0021413 0 ustar 00root root 0000000 0000000 import asyncio
import logging
from websockets.asyncio.server import serve
from websockets.exceptions import WebSocketException
logging.basicConfig(level=logging.WARNING)
HOST, PORT = "0.0.0.0", 9002
async def echo(ws):
try:
async for msg in ws:
await ws.send(msg)
except WebSocketException:
pass
async def main():
async with serve(
echo,
HOST,
PORT,
server_header="websockets.sync",
max_size=2**25,
) as server:
try:
await server.serve_forever()
except KeyboardInterrupt:
pass
if __name__ == "__main__":
asyncio.run(main())
websockets-15.0.1/compliance/config/ 0000775 0000000 0000000 00000000000 14762124503 0017332 5 ustar 00root root 0000000 0000000 websockets-15.0.1/compliance/config/fuzzingclient.json 0000664 0000000 0000000 00000000314 14762124503 0023116 0 ustar 00root root 0000000 0000000
{
"servers": [{
"url": "ws://host.docker.internal:9002"
}, {
"url": "ws://host.docker.internal:9003"
}],
"outdir": "/reports/servers",
"cases": ["*"],
"exclude-cases": []
}
websockets-15.0.1/compliance/config/fuzzingserver.json 0000664 0000000 0000000 00000000161 14762124503 0023146 0 ustar 00root root 0000000 0000000
{
"url": "ws://localhost:9001",
"outdir": "/reports/clients",
"cases": ["*"],
"exclude-cases": []
}
websockets-15.0.1/compliance/sync/ 0000775 0000000 0000000 00000000000 14762124503 0017041 5 ustar 00root root 0000000 0000000 websockets-15.0.1/compliance/sync/client.py 0000664 0000000 0000000 00000002370 14762124503 0020673 0 ustar 00root root 0000000 0000000 import json
import logging
from websockets.exceptions import WebSocketException
from websockets.sync.client import connect
logging.basicConfig(level=logging.WARNING)
SERVER = "ws://localhost:9001"
AGENT = "websockets.sync"
def get_case_count():
with connect(f"{SERVER}/getCaseCount") as ws:
return json.loads(ws.recv())
def run_case(case):
with connect(
f"{SERVER}/runCase?case={case}&agent={AGENT}",
max_size=2**25,
) as ws:
try:
for msg in ws:
ws.send(msg)
except WebSocketException:
pass
def update_reports():
with connect(
f"{SERVER}/updateReports?agent={AGENT}",
open_timeout=60,
):
pass
def main():
cases = get_case_count()
for case in range(1, cases + 1):
print(f"Running test case {case:03d} / {cases}... ", end="\t")
try:
run_case(case)
except WebSocketException as exc:
print(f"ERROR: {type(exc).__name__}: {exc}")
except Exception as exc:
print(f"FAIL: {type(exc).__name__}: {exc}")
else:
print("OK")
print(f"Ran {cases} test cases")
update_reports()
print("Updated reports")
if __name__ == "__main__":
main()
websockets-15.0.1/compliance/sync/server.py 0000664 0000000 0000000 00000001126 14762124503 0020721 0 ustar 00root root 0000000 0000000 import logging
from websockets.exceptions import WebSocketException
from websockets.sync.server import serve
logging.basicConfig(level=logging.WARNING)
HOST, PORT = "0.0.0.0", 9003
def echo(ws):
try:
for msg in ws:
ws.send(msg)
except WebSocketException:
pass
def main():
with serve(
echo,
HOST,
PORT,
server_header="websockets.asyncio",
max_size=2**25,
) as server:
try:
server.serve_forever()
except KeyboardInterrupt:
pass
if __name__ == "__main__":
main()
websockets-15.0.1/docs/ 0000775 0000000 0000000 00000000000 14762124503 0014703 5 ustar 00root root 0000000 0000000 websockets-15.0.1/docs/Makefile 0000664 0000000 0000000 00000001345 14762124503 0016346 0 ustar 00root root 0000000 0000000 # Minimal makefile for Sphinx documentation
#
# You can set these variables from the command line, and also
# from the environment for the first two.
SPHINXOPTS ?=
SPHINXBUILD ?= sphinx-build
SOURCEDIR = .
BUILDDIR = _build
# Put it first so that "make" without argument is like "make help".
help:
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
.PHONY: help Makefile
# Catch-all target: route all unknown targets to Sphinx using the new
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
%: Makefile
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
livehtml:
sphinx-autobuild --watch "$(SOURCEDIR)/../src" "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
websockets-15.0.1/docs/_static/ 0000775 0000000 0000000 00000000000 14762124503 0016331 5 ustar 00root root 0000000 0000000 websockets-15.0.1/docs/_static/favicon.ico 0000777 0000000 0000000 00000000000 14762124503 0024154 2../../logo/favicon.ico ustar 00root root 0000000 0000000 websockets-15.0.1/docs/_static/tidelift.png 0000777 0000000 0000000 00000000000 14762124503 0024536 2../../logo/tidelift.png ustar 00root root 0000000 0000000 websockets-15.0.1/docs/_static/websockets.svg 0000777 0000000 0000000 00000000000 14762124503 0025136 2../../logo/vertical.svg ustar 00root root 0000000 0000000 websockets-15.0.1/docs/conf.py 0000664 0000000 0000000 00000014107 14762124503 0016205 0 ustar 00root root 0000000 0000000 # Configuration file for the Sphinx documentation builder.
#
# This file only contains a selection of the most common options. For a full
# list see the documentation:
# https://www.sphinx-doc.org/en/master/usage/configuration.html
import datetime
import importlib
import inspect
import os
import subprocess
import sys
# -- Path setup --------------------------------------------------------------
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
sys.path.insert(0, os.path.join(os.path.abspath(".."), "src"))
# -- Project information -----------------------------------------------------
project = "websockets"
copyright = f"2013-{datetime.date.today().year}, Aymeric Augustin and contributors"
author = "Aymeric Augustin"
from websockets.version import tag as version, version as release
# -- General configuration ---------------------------------------------------
nitpicky = True
nitpick_ignore = [
# topics/design.rst discusses undocumented APIs
("py:meth", "client.WebSocketClientProtocol.handshake"),
("py:meth", "server.WebSocketServerProtocol.handshake"),
("py:attr", "protocol.WebSocketCommonProtocol.is_client"),
("py:attr", "protocol.WebSocketCommonProtocol.messages"),
("py:meth", "protocol.WebSocketCommonProtocol.close_connection"),
("py:attr", "protocol.WebSocketCommonProtocol.close_connection_task"),
("py:meth", "protocol.WebSocketCommonProtocol.keepalive_ping"),
("py:attr", "protocol.WebSocketCommonProtocol.keepalive_ping_task"),
("py:meth", "protocol.WebSocketCommonProtocol.transfer_data"),
("py:attr", "protocol.WebSocketCommonProtocol.transfer_data_task"),
("py:meth", "protocol.WebSocketCommonProtocol.connection_open"),
("py:meth", "protocol.WebSocketCommonProtocol.ensure_open"),
("py:meth", "protocol.WebSocketCommonProtocol.fail_connection"),
("py:meth", "protocol.WebSocketCommonProtocol.connection_lost"),
("py:meth", "protocol.WebSocketCommonProtocol.read_message"),
("py:meth", "protocol.WebSocketCommonProtocol.write_frame"),
]
# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = [
"sphinx.ext.autodoc",
"sphinx.ext.intersphinx",
"sphinx.ext.linkcode",
"sphinx.ext.napoleon",
"sphinx_copybutton",
"sphinx_inline_tabs",
"sphinxcontrib.spelling",
"sphinxcontrib_trio",
"sphinxext.opengraph",
]
# It is currently inconvenient to install PyEnchant on Apple Silicon.
try:
import sphinxcontrib.spelling
except ImportError:
extensions.remove("sphinxcontrib.spelling")
autodoc_typehints = "description"
autodoc_typehints_description_target = "documented"
# Workaround for https://github.com/sphinx-doc/sphinx/issues/9560
from sphinx.domains.python import PythonDomain
assert PythonDomain.object_types["data"].roles == ("data", "obj")
PythonDomain.object_types["data"].roles = ("data", "class", "obj")
intersphinx_mapping = {
"python": ("https://docs.python.org/3", None),
"sesame": ("https://django-sesame.readthedocs.io/en/stable/", None),
"werkzeug": ("https://werkzeug.palletsprojects.com/en/stable/", None),
}
spelling_show_suggestions = True
# Add any paths that contain templates here, relative to this directory.
templates_path = ["_templates"]
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
# This pattern also affects html_static_path and html_extra_path.
exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"]
# Configure viewcode extension.
from websockets.version import commit
code_url = f"https://github.com/python-websockets/websockets/blob/{commit}"
def linkcode_resolve(domain, info):
# Non-linkable objects from the starter kit in the tutorial.
if domain == "js" or info["module"] == "connect4":
return
assert domain == "py", "expected only Python objects"
mod = importlib.import_module(info["module"])
if "." in info["fullname"]:
objname, attrname = info["fullname"].split(".")
obj = getattr(mod, objname)
try:
# object is a method of a class
obj = getattr(obj, attrname)
except AttributeError:
# object is an attribute of a class
return None
else:
obj = getattr(mod, info["fullname"])
try:
file = inspect.getsourcefile(obj)
lines = inspect.getsourcelines(obj)
except TypeError:
# e.g. object is a typing.Union
return None
file = os.path.relpath(file, os.path.abspath(".."))
if not file.startswith("src/websockets"):
# e.g. object is a typing.NewType
return None
start, end = lines[1], lines[1] + len(lines[0]) - 1
return f"{code_url}/{file}#L{start}-L{end}"
# Configure opengraph extension
# Social cards don't support the SVG logo. Also, the text preview looks bad.
ogp_social_cards = {"enable": False}
# -- Options for HTML output -------------------------------------------------
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
html_theme = "furo"
html_theme_options = {
"light_css_variables": {
"color-brand-primary": "#306998", # blue from logo
"color-brand-content": "#0b487a", # blue more saturated and less dark
},
"dark_css_variables": {
"color-brand-primary": "#ffd43bcc", # yellow from logo, more muted than content
"color-brand-content": "#ffd43bd9", # yellow from logo, transparent like text
},
"sidebar_hide_name": True,
}
html_logo = "_static/websockets.svg"
html_favicon = "_static/favicon.ico"
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ["_static"]
html_copy_source = False
html_show_sphinx = False
websockets-15.0.1/docs/deploy/ 0000775 0000000 0000000 00000000000 14762124503 0016177 5 ustar 00root root 0000000 0000000 websockets-15.0.1/docs/deploy/architecture.svg 0000664 0000000 0000000 00000035536 14762124503 0021416 0 ustar 00root root 0000000 0000000