patx/wred
Release v0.04 with Peregrine server and updated benchmarks
Commit f2b7d04 · patx · 2026-10-14T22:50:19-04:00
Comments
No comments yet.
Diff
diff --git a/README.md b/README.md
index cec78ee..4eb63fb 100644
--- a/README.md
+++ b/README.md
@@ -10,7 +10,7 @@ Your API needs to return some JSON. It probably doesn't need a goddamn cathedral
- Headers, query parameters, cached body reads, and JSON parsing.
- JSON responses, custom response tuples, and a small-file helper.
- Callable ASGI response support and routing relative to mounted paths.
-- Depends on `granian` and `orjson`. You don't have to use Granian however.
+- Depends on `peregrine-server` and `orjson`. You can use any ASGI server.
## What you don't get
@@ -43,13 +43,13 @@ async def hello(request):
return {'hello': 'world'}
```
-Run it with Granian, or any other ASGI server you like:
+Run it with Peregrine, or any other ASGI server you like:
```bash
-granian --interface asginl app:app
+peregrine app:app
```
-Open <http://127.0.0.1:8000>. Wred is HTTP-only; `asginl` disables lifespan.
+Open <http://127.0.0.1:8000>. Wred is HTTP-only.
Unsupported protocols raise `RuntimeError` without sending HTTP messages,
following [ASGI guidance](https://asgi.readthedocs.io/en/latest/specs/main.html#protocol-specifications).
You can also export a middleware wrapper as `app`.
@@ -172,11 +172,11 @@ for application validation failures. Unsupported response types produce JSON
| Framework | Median requests/sec | Min | Max |
| --- | ---: | ---: | ---: |
-| Wred 0.03 | **272,088** | 262,187 | 277,656 |
-| BlackSheep 2.6.4 | 211,619 | 205,719 | 220,455 |
-| MicroPie 0.32 | 207,720 | 197,520 | 216,010 |
+| Wred 0.04 | **553,296** | 544,314 | 585,634 |
+| BlackSheep 2.6.4 | 398,900 | 384,661 | 415,871 |
+| MicroPie 0.32 | 374,680 | 367,513 | 391,136 |
-Python 3.14.4, Granian 2.8.4, eight workers, HTTP/1 keep-alive, asyncio,
+Python 3.14.4, Peregrine 1.1.7, eight workers, HTTP/1 keep-alive, asyncio,
no access logging. `wrk -t4 -c256 -d20s --latency`, five-second warmups.
Client and server shared a machine over loopback. All nine measured runs
had zero socket errors or non-success responses. It's a tiny JSON response,
diff --git a/docs/index.html b/docs/index.html
index ae42a3d..64d6a58 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -46,7 +46,7 @@ app = App()
async def index(request):
return {"hello": "world"}
-# run with `granian app:app`
+# run with `peregrine app:app`
</code></pre>
</section>
</main>
diff --git a/example_app/app.py b/example_app/app.py
index 2f78837..dff40ab 100644
--- a/example_app/app.py
+++ b/example_app/app.py
@@ -1,7 +1,7 @@
"""Run the notebook demo from the repository root:
uv sync
- uv run granian --interface asginl --workers 1 example_app.app:app
+ uv run peregrine example_app.app:app
Open http://127.0.0.1:8000. Users, tokens, and notes disappear on restart.
Login is restored with an HttpOnly refresh cookie; API calls use bearer tokens.
diff --git a/pyproject.toml b/pyproject.toml
index 57403f9..779eab4 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -11,5 +11,5 @@ requires-python = ">=3.11"
license = "BSD-3-Clause"
license-files = ["LICENSE"]
authors = [{ name = "Harrison Erd", email = "[email protected]" }]
-dependencies = ["orjson", "granian"]
+dependencies = ["orjson", "peregrine-server"]
diff --git a/wred.py b/wred.py
index eaac925..c73feca 100644
--- a/wred.py
+++ b/wred.py
@@ -10,7 +10,7 @@ Copyright (c) 2026, Harrison Erd.
__author__ = 'Harrison Erd'
__email__ = '[email protected]'
-__version__ = '0.03'
+__version__ = '0.04'
__license__ = 'BSD-3-Clause'
from collections.abc import Awaitable, Callable