Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 0 additions & 11 deletions .coveragerc

This file was deleted.

41 changes: 26 additions & 15 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,37 +7,48 @@ on:
branches: ["master"]

jobs:
tox:
tests:
runs-on: ubuntu-latest
strategy:
max-parallel: 7
matrix:
python-version:
- 3.8
- 3.9
- "3.10"
- "3.11"
- "3.12"
- "3.13"
- pypy-3.9
- "3.14"
- pypy-3.10
- pypy-3.11

steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
allow-prereleases: true
- name: Install tox
run: |
python -m pip install --upgrade pip setuptools
pip install --upgrade tox tox-gh-actions
- name: Initialize tox envs
run: |
tox --parallel auto --notest
- name: Test with tox
run: |
tox --parallel 0
- uses: astral-sh/setup-uv@v6
with:
enable-cache: true
- name: Test
run: uv run --locked --no-default-groups --group testing --python "${{ matrix.python-version }}" pytest --cov=h11 --cov-report=term --cov-report=xml
- uses: codecov/codecov-action@v4
with:
file: ./coverage.xml
files: ./coverage.xml

checks:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: astral-sh/setup-uv@v6
with:
python-version: "3.10"
enable-cache: true
- run: uv sync --locked
- run: uv run --locked ruff check h11/ bench/ examples/ fuzz/
- run: uv run --locked ruff format --check --diff h11/ bench/ examples/ fuzz/
- run: uv run --locked mypy h11/
- run: uv build
- run: uv run --locked twine check dist/*
- run: sudo apt-get update && sudo apt-get install -y graphviz
- run: uv run --locked sphinx-build -W -b html docs/source docs/build/html
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ pip-log.txt
# Unit test / coverage reports
htmlcov/
.tox/
.venv/
.mypy_cache/
.ruff_cache/
.coverage
.cache
nosetests.xml
Expand Down
13 changes: 6 additions & 7 deletions .readthedocs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,12 @@ build:
apt_packages:
- graphviz
tools:
python: "3.8"
python: "3.13"
jobs:
post_create_environment:
- pip install uv
post_install:
- UV_PROJECT_ENVIRONMENT=$READTHEDOCS_VIRTUALENV_PATH uv sync --locked --no-default-groups --group docs --inexact

sphinx:
configuration: docs/source/conf.py

python:
install:
- method: pip
path: .
- requirements: docs/requirements.txt
30 changes: 20 additions & 10 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,15 +42,14 @@ other hand, the following are all very welcome:

* Code should work across all currently supported Python releases.

* Code must be formatted using
[black](https://github.com/python/black) and
[isort](https://github.com/timothycrosley/isort) as configured in
* Code must be linted and formatted using
[Ruff](https://docs.astral.sh/ruff/) as configured in
the project. With those projects installed the commands,

black h11/ bench/ examples/ fuzz/
isort --profile black --dt h11 bench examples fuzz
uv run --locked ruff check --fix h11/ bench/ examples/ fuzz/
uv run --locked ruff format h11/ bench/ examples/ fuzz/

will format your code for you.
will fix lint issues (including import ordering) and format your code.

* If you change the code, then you have to also add or fix at least
one test. (See below for how to run the test suite.) This helps us
Expand All @@ -66,17 +65,28 @@ other hand, the following are all very welcome:
* The test suite needs to pass. The easy way to check is:

```
pip install tox
tox
uv sync --locked
uv run --locked pytest --cov=h11
```

But note that: (1) this might print slightly misleading coverage
statistics, because it only shows coverage for individual python
versions, and there might be some lines that are only executed on some
python versions or implementations, and (2) the full test suite will
automatically get run when you submit a pull request, so you don't
need to worry too much about tracking down a version of cpython 3.3
or whatever just to run the tests.
need to install every supported Python version just to run the tests.
Install [uv](https://docs.astral.sh/uv/getting-started/installation/)
first. Python 3.10 or newer is required. To run the full interpreter
matrix and formatting/type checks locally, use `uv run --locked tox`
with the corresponding interpreters installed. Individual checks can
be run with `uv run --locked tox -e format,mypy`.

Development dependencies are defined in `pyproject.toml` and pinned in
`uv.lock`. After changing dependencies, run `uv lock` and commit both
files. Build distributions with `uv build`. To build the documentation,
install [Graphviz](https://graphviz.org/download/) (including the `dot`
executable), then run
`uv run --locked sphinx-build -b html docs/source docs/build/html`.

* Proposed speedups require some profiling and benchmarks to justify
the change.
Expand Down
6 changes: 5 additions & 1 deletion MANIFEST.in
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
include LICENSE.txt README.rst notes.org tiny-client-demo.py h11/py.typed
include LICENSE.txt README.rst CONTRIBUTING.md notes.org h11/py.typed uv.lock
recursive-include newsfragments *.rst
recursive-include docs *
recursive-include h11/tests *
recursive-include fuzz *
recursive-include bench *.py *.json *.rst
recursive-include examples *.py
prune docs/build
global-exclude *.py[cod]
2 changes: 1 addition & 1 deletion README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ library.
It has a test suite with 100.0% coverage for both statements and
branches.

Currently it supports Python 3 (testing on 3.8-3.12) and PyPy 3.
Currently it supports Python 3.10+ (testing on 3.10-3.14) and PyPy 3.10+.
The last Python 2-compatible version was h11 0.11.x.
(Originally it had a Cython wrapper for `http-parser
<https://github.com/nodejs/http-parser>`_ and a beautiful nested state
Expand Down
2 changes: 1 addition & 1 deletion bench/asv.conf.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@

// The Pythons you'd like to test against. If not provided, defaults
// to the current version of Python used to run `asv`.
"pythons": ["3.8", "pypy3"],
"pythons": ["3.10", "pypy3.10"],

// The matrix of dependencies to test. Each key is the name of a
// package (in PyPI) and the values are version numbers. An empty
Expand Down
6 changes: 0 additions & 6 deletions docs/requirements.txt

This file was deleted.

4 changes: 2 additions & 2 deletions docs/source/changes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -73,13 +73,13 @@ Features
- Add typing including a PEP 561 marker for usage by type checkers
(`#135 <https://github.com/python-hyper/h11/pull/135>`__).
- Expand the allowed status codes to [0, 999] from [0, 600] (`#134
https://github.com/python-hyper/h11/issues/134`__).
<https://github.com/python-hyper/h11/issues/134>`__).

Backwards **in**\compatible changes
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

- Ensure request method is a valid token (`#141
https://github.com/python-hyper/h11/pull/141>`__).
<https://github.com/python-hyper/h11/pull/141>`__).


v0.12.0 (2021-01-01)
Expand Down
11 changes: 6 additions & 5 deletions docs/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = [
'sphinxcontrib.jquery',
'sphinx.ext.autodoc',
'sphinx.ext.intersphinx',
'sphinx.ext.viewcode',
Expand All @@ -58,9 +59,9 @@
# Undocumented trick: if we def setup here in conf.py, it gets called just
# like an extension's setup function.
def setup(app):
app.add_javascript("show-code.js")
app.add_javascript("facebox.js")
app.add_stylesheet("facebox.css")
app.add_js_file("show-code.js")
app.add_js_file("facebox.js")
app.add_css_file("facebox.css")

# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
Expand Down Expand Up @@ -96,7 +97,7 @@ def setup(app):
#
# This is also used if you do content translation via gettext catalogs.
# Usually you set "language" from the command line for these cases.
language = None
language = 'en'

# There are two options for replacing |today|: either, you set today to some
# non-false value, then it is used:
Expand Down Expand Up @@ -321,5 +322,5 @@ def setup(app):

# Example configuration for intersphinx: refer to the Python standard library.
intersphinx_mapping = {
'python': ('https://docs.python.org/3.5', None),
'python': ('https://docs.python.org/3', None),
}
2 changes: 1 addition & 1 deletion docs/source/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ whatever. But h11 makes it much easier to implement something like
Vital statistics
----------------

* Requirements: Python 3.8+ (PyPy works great)
* Requirements: Python 3.10+ (PyPy works great)

The last Python 2-compatible version was h11 0.11.x.

Expand Down
2 changes: 0 additions & 2 deletions format-requirements.txt

This file was deleted.

6 changes: 4 additions & 2 deletions h11/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
# semantics to check that what you're asking to write to the wire is sensible,
# but at least it gets you out of dealing with the wire itself.

from h11._connection import Connection, NEED_DATA, PAUSED
from h11._connection import NEED_DATA, PAUSED, Connection
from h11._events import (
ConnectionClosed,
Data,
Expand All @@ -22,13 +22,15 @@
DONE,
ERROR,
IDLE,
MIGHT_SWITCH_PROTOCOL,
MUST_CLOSE,
SEND_BODY,
SEND_RESPONSE,
SERVER,
SWITCHED_PROTOCOL,
)
from h11._state import (
MIGHT_SWITCH_PROTOCOL as MIGHT_SWITCH_PROTOCOL,
)
from h11._util import LocalProtocolError, ProtocolError, RemoteProtocolError
from h11._version import __version__

Expand Down
15 changes: 6 additions & 9 deletions h11/_connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@
from typing import (
Any,
Callable,
cast,
Dict,
List,
Optional,
overload,
Tuple,
Type,
Union,
cast,
overload,
)

from ._events import (
Expand All @@ -29,13 +29,13 @@
_SWITCH_CONNECT,
_SWITCH_UPGRADE,
CLIENT,
ConnectionState,
DONE,
ERROR,
MIGHT_SWITCH_PROTOCOL,
SEND_BODY,
SERVER,
SWITCHED_PROTOCOL,
ConnectionState,
)
from ._util import ( # Import the internal things we need
LocalProtocolError,
Expand Down Expand Up @@ -501,18 +501,15 @@ def next_event(self) -> Union[Event, Type[NEED_DATA], Type[PAUSED]]:
raise

@overload
def send(self, event: ConnectionClosed) -> None:
...
def send(self, event: ConnectionClosed) -> None: ...

@overload
def send(
self, event: Union[Request, InformationalResponse, Response, Data, EndOfMessage]
) -> bytes:
...
) -> bytes: ...

@overload
def send(self, event: Event) -> Optional[bytes]:
...
def send(self, event: Event) -> Optional[bytes]: ...

def send(self, event: Event) -> Optional[bytes]:
"""Convert a high-level event into bytes that can be sent to the peer,
Expand Down
2 changes: 1 addition & 1 deletion h11/_events.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

from ._abnf import method, request_target
from ._headers import Headers, normalize_and_validate
from ._util import bytesify, LocalProtocolError, validate
from ._util import LocalProtocolError, bytesify, validate

# Everything in __all__ gets re-exported as part of the h11 public API.
__all__ = [
Expand Down
15 changes: 7 additions & 8 deletions h11/_headers.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import re
from typing import AnyStr, cast, List, overload, Sequence, Tuple, TYPE_CHECKING, Union
from typing import TYPE_CHECKING, List, Sequence, Tuple, Union, overload

from ._abnf import field_name, field_value
from ._util import bytesify, LocalProtocolError, validate
from ._util import LocalProtocolError, bytesify, validate

if TYPE_CHECKING:
from ._events import Request
Expand Down Expand Up @@ -133,20 +133,19 @@ def raw_items(self) -> List[Tuple[bytes, bytes]]:


@overload
def normalize_and_validate(headers: Headers, _parsed: Literal[True]) -> Headers:
...
def normalize_and_validate(headers: Headers, _parsed: Literal[True]) -> Headers: ...


@overload
def normalize_and_validate(headers: HeaderTypes, _parsed: Literal[False]) -> Headers:
...
def normalize_and_validate(
headers: HeaderTypes, _parsed: Literal[False]
) -> Headers: ...


@overload
def normalize_and_validate(
headers: Union[Headers, HeaderTypes], _parsed: bool = False
) -> Headers:
...
) -> Headers: ...


def normalize_and_validate(
Expand Down
1 change: 0 additions & 1 deletion h11/_receivebuffer.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import re
import sys
from typing import List, Optional, Union

__all__ = ["ReceiveBuffer"]
Expand Down
Loading