Action0-Req
Typed Python representations of HTTP requests and responses with convenient creation, duplication and manipulation. The companion of action0-url, which provides the URL representation.
Requires Python 3.11 or newer.
Full documentation including the API reference: https://laughinjar.github.io/action0-req/
Status: the core API is complete — the header name, status code and
method constants, the Headers mapping, Request and Response, and
sync/async body streaming via BodyProducer (BytesBody, FileBody,
IterableBody, AsyncIterableBody).
Usage
Header, Status and Method are StrEnum/IntEnum constants for the
IANA-registered header field names, status codes and request methods —
every member is its string or integer value:
from action0.req import Header, Method, Status
print(Header.CONTENT_TYPE) # Content-Type
print(Method.POST) # POST
print(Status.NOT_FOUND) # 404
print(Status.NOT_FOUND.phrase) # Not Found
print(Status.NOT_FOUND.is_client_error) # True
Headers is an ordered, case-insensitive, multi-value aware mapping of
header fields that preserves the representation (order and casing)
exactly:
from action0.req import Headers
headers = Headers({"Content-Type": "text/html"})
headers.add("Set-Cookie", "a=1")
headers.add("set-cookie", "b=2")
print(headers["CONTENT-TYPE"]) # text/html
print(headers.get_all("Set-Cookie")) # ['a=1', 'b=2']
print(headers.as_str(separator="\n")) # "\r\n" by default
# Content-Type: text/html
# Set-Cookie: a=1
# set-cookie: b=2
# repr()/str() redact secrets, only as_str() renders them
print(Headers({"Authorization": "Bearer tok"})) # Headers(Authorization: ***)
Request combines a method, a Url (from action0-url), Headers, a
meta dict for application metadata (never on the wire) and a body (bytes, str or a streaming BodyProducer — retrievable in any
of the three forms):
from action0.req import Request
req = Request("https://api.example.com/items", query={"page": 2})
req.headers["Accept"] = "application/json"
print(req.as_str(separator="\n")) # "\r\n" by default
# GET /items?page=2 HTTP/1.1
# Host: api.example.com
# Accept: application/json
post = req.copy(method="POST", body='{"a": 1}')
print(post.body_bytes()) # b'{"a": 1}'
print(post) # Request(POST https://api.example.com/items?page=2)
Response mirrors it for the server side — status (with reason phrase
fallback and category properties), headers, body:
from action0.req import Response, Status
resp = Response(Status.NOT_FOUND, headers={"Content-Type": "text/plain"}, body="not here")
print(resp.phrase, resp.is_client_error) # Not Found True
print(resp.as_str(separator="\n")) # "\r\n" by default
# HTTP/1.1 404 Not Found
# Content-Type: text/plain
Installation
Not published to PyPI yet; install straight from GitHub:
uv add "action0-req @ git+https://github.com/LaughInJar/action0-req"
Development
The project is managed with uv; uv run
creates and syncs the virtual environment automatically:
uv run pytest # run the tests (incl. the docstring examples as doctests)
uv run ruff check # lint
uv run ruff format # format
uv run mypy # type-check (also: uv run pyright, uv run ty check)
# build the docs (Sphinx; deployed to GitHub Pages on push to main)
uv run --group docs sphinx-build -W docs docs/_build/html
Releasing
The version lives only in src/action0/req/__init__.py (__version__).
To release: bump it, merge to main, then tag the release commit and push
the tag — the release workflow re-runs all checks, verifies the tag
matches __version__, builds sdist + wheel and publishes to PyPI via
trusted publishing:
git tag v0.1.0
git push origin v0.1.0
AI-assisted development
In the spirit of transparency: most of this project's code, tests and
documentation are written by Claude Code,
Anthropic's coding agent — under human direction and review. The designs
are specified, discussed and iterated by a human, and every change is
reviewed before it lands in main or in a release. AI-authored commits
carry a Co-Authored-By: Claude ... trailer.
About action0
This is just the namespace I like to use for my personal projects. I quite like namespaces.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file action0_req-0.1.0.tar.gz.
File metadata
- Download URL: action0_req-0.1.0.tar.gz
- Upload date:
- Size: 98.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
143debfd71c1ab8026d89e7b01c0dc5cb4ce278614f69cf35cf43eacb8728066
|
|
| MD5 |
bf7cbb9e39916644a842082dc7e71b7f
|
|
| BLAKE2b-256 |
e6a315efca2004782520b39cdf2fe51c6c506982ed29b52d47fcebc4f905cbb5
|
Provenance
The following attestation bundles were made for action0_req-0.1.0.tar.gz:
Publisher:
release.yml on LaughInJar/action0-req
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
action0_req-0.1.0.tar.gz -
Subject digest:
143debfd71c1ab8026d89e7b01c0dc5cb4ce278614f69cf35cf43eacb8728066 - Sigstore transparency entry: 2380005768
- Sigstore integration time:
-
Permalink:
LaughInJar/action0-req@979ac29b7570cc2ecbdcf09576487736080e6411 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/LaughInJar
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@979ac29b7570cc2ecbdcf09576487736080e6411 -
Trigger Event:
push
-
Statement type:
File details
Details for the file action0_req-0.1.0-py3-none-any.whl.
File metadata
- Download URL: action0_req-0.1.0-py3-none-any.whl
- Upload date:
- Size: 25.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d2d205566a3e2131c2dee0a9eb65de44ae071d5ee07e7a66f0ea889b55599d81
|
|
| MD5 |
f9eef5e8bb8e3a45552b92a0056b98c1
|
|
| BLAKE2b-256 |
a07cc0e01ac7cd97303d10faa088b37cf1acd5af0ee1a132c77f3e52dd0fc05c
|
Provenance
The following attestation bundles were made for action0_req-0.1.0-py3-none-any.whl:
Publisher:
release.yml on LaughInJar/action0-req
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
action0_req-0.1.0-py3-none-any.whl -
Subject digest:
d2d205566a3e2131c2dee0a9eb65de44ae071d5ee07e7a66f0ea889b55599d81 - Sigstore transparency entry: 2380005968
- Sigstore integration time:
-
Permalink:
LaughInJar/action0-req@979ac29b7570cc2ecbdcf09576487736080e6411 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/LaughInJar
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@979ac29b7570cc2ecbdcf09576487736080e6411 -
Trigger Event:
push
-
Statement type: