Skip to main content

Async ASGI 3.0 framework with a from-scratch HTTP/1.1 parser, HTTP/2 frame layer, and WebSocket codec. HPACK delegates to the hpack library.

Project description

BlackBull

Early Alpha — API may break between MINOR versions. Conformance evidence: docs/about/conformance.md. Things to know before adopting: KNOWN_LIMITATIONS.md.

Async ASGI 3.0 framework with a from-scratch HTTP/1.1 parser, HTTP/2 frame layer, and WebSocket codec — no httptools, no uvicorn, no hypercorn underneath. HPACK header compression delegates to the hpack library (re-implementing a conformant HPACK encoder/decoder is a project of its own); everything else, including the ASGI server, event loop integration, prioritisation, push, flow control, and stream actor, is BlackBull's own code. Single deployable, no third-party C extensions in the protocol stack.

PyPI Python License

Why BlackBull

  • One package, one process — the framework is the server. No separate ASGI runner; app.run() opens the socket and serves.
  • From-scratch protocol stack for HTTP/1.1 (RFC 9112) parser, HTTP/2 (RFC 9113) frame layer + flow control + RFC 9218 prioritisation + push, and WebSocket (RFC 6455) codec. HPACK (RFC 7541) is the one exception — see headline above.
  • Pure-Python identity — no httptools, no uvloop dependency (uvloop available as an optional [speed] extra). The single third-party dependency in the protocol stack is hpack, also pure Python.
  • Conformance-tested against h2spec, Autobahn, and a differential nginx fuzz corpus.
  • Modern Python — requires 3.11+, full type hints, PEP 561 typed distribution.

Install

pip install blackbull
pip install 'blackbull[compression]'   # add brotli + zstandard codecs
pip install 'blackbull[speed]'         # add uvloop event loop
pip install 'blackbull[reload]'        # add watchfiles for --reload

Hello, world

from blackbull import BlackBull

app = BlackBull()

@app.route(path='/')
async def hello():
    return "Hello, world!"

if __name__ == '__main__':
    app.run(port=8000)

Run it:

python app.py              # HTTP/1.1 on :8000

Or via the bundled CLI:

blackbull app:app --bind 0.0.0.0:8000

Simplified handlers

Route handlers may return a str, bytes, dict, or Response; path parameters are coerced to the annotation type:

@app.route(path='/tasks/{task_id:int}')
async def get_task(task_id: int):
    return {"id": task_id, "title": "..."}

Drop down to full ASGI (scope, receive, send) whenever you need it — routes accept either shape.

TLS + HTTP/2

app.run(port=8443, certfile='cert.pem', keyfile='key.pem')

ALPN negotiates h2 automatically; HTTP/1.1 clients fall back via the same socket.

WebSocket

from http import HTTPMethod
from blackbull.utils import Scheme

@app.route(path='/ws', methods=[HTTPMethod.GET], scheme=Scheme.websocket)
async def ws_echo(scope, receive, send):
    await receive()                              # websocket.connect
    await send({'type': 'websocket.accept'})
    while True:
        msg = await receive()
        if msg['type'] == 'websocket.disconnect':
            break
        if msg['type'] == 'websocket.receive':
            await send({'type': 'websocket.send',
                        'text': msg.get('text') or ''})

Built-in middleware

Compose via app.use(...) or per-route middlewares=[...]:

Middleware What it does
Compression Negotiates br / zstd / gzip from Accept-Encoding
StaticFiles Serves files from a directory under a URL prefix
Cache Per-worker LRU + ETag / Cache-Control honouring
Session Signed-cookie sessions (HMAC-SHA256)
CORS Preflight + actual-request header injection
TrustedProxy Rewrites scope['client'] / scope['scheme'] from proxy headers

OpenAPI / Swagger UI

app.enable_openapi()   # publishes /openapi.json and /docs

Auto-generates an OpenAPI 3.1 spec from route signatures, path-param converters, docstrings, and @dataclass annotations on body parameters. Dataclass-typed bodies are also deserialized at runtime — async def h(body: CreateTask): ... receives a constructed instance, no manual json.loads.

Examples

Example Demonstrates
examples/SimpleTaskManager/ REST API + HTML UI, middleware pipeline, route groups, SQLite, Bearer token auth
examples/ChatServer/ WebSocket, SSE, long polling side by side; Session + Compression + custom auth
examples/typed_routes_ok.py {param:converter} syntax, url_path_for

Documentation

Versioning

BlackBull uses ZeroVer prior to a 1.0 commitment. MINOR advances at each sprint close; PATCH is for bug fixes and harness work between sprints. See CHANGELOG.md for the full release history.

License

Apache License 2.0 — © TOKUJI.

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

blackbull-0.31.2.tar.gz (192.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

blackbull-0.31.2-py3-none-any.whl (218.5 kB view details)

Uploaded Python 3

File details

Details for the file blackbull-0.31.2.tar.gz.

File metadata

  • Download URL: blackbull-0.31.2.tar.gz
  • Upload date:
  • Size: 192.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.13

File hashes

Hashes for blackbull-0.31.2.tar.gz
Algorithm Hash digest
SHA256 1734face7c0a4d9297443fa1839dae926678ac5a25bafef4837752bd8fcf3021
MD5 1f7a36b70f6b94ffe5336af42d494cbb
BLAKE2b-256 33199e7643ab5b9224f81e69d4f3aeaa0e3b169cb80e3efb32cdf8fe1df4fcbf

See more details on using hashes here.

Provenance

The following attestation bundles were made for blackbull-0.31.2.tar.gz:

Publisher: publish.yml on TOKUJI/BlackBull

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file blackbull-0.31.2-py3-none-any.whl.

File metadata

  • Download URL: blackbull-0.31.2-py3-none-any.whl
  • Upload date:
  • Size: 218.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.13

File hashes

Hashes for blackbull-0.31.2-py3-none-any.whl
Algorithm Hash digest
SHA256 4809b99e4ba3cb050d2cf08276cfc6f20073d5bbd24eb0e95b2dc0fe52a4fb0c
MD5 7047bcfbc0f38a3ccd78a92e5239db70
BLAKE2b-256 b606bb038299bbcf30ebb7682f45356e1527322006cd63224deb3d3dbedda882

See more details on using hashes here.

Provenance

The following attestation bundles were made for blackbull-0.31.2-py3-none-any.whl:

Publisher: publish.yml on TOKUJI/BlackBull

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

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