action0-client¶
Backend-agnostic, fully typed HTTP API clients: describe your API once — as typed operations — and run it synchronously, on asyncio or on Twisted, just by plugging in a different backend. Built on action0-req (the request/response representation) and action0-url (the URL representation).
The same typed operation, driven by three different backends:
client = APIClient(RequestsBackend(), "https://api.example.com/v1")
item = client.send(GetItem(item_id=42)) # Item
client = APIClient(AsyncHttpxBackend(), "https://api.example.com/v1")
item = await client.send(GetItem(item_id=42)) # Awaitable[Item]
client = APIClient(TwistedBackend(), "https://api.example.com/v1")
deferred = client.send(GetItem(item_id=42)) # Deferred[Item]
(GetItem is an ordinary typed operation class, written once — the
guide shows its definition.)
uv add "action0-client[httpx]"
Highlights:
One
Client/APIClient, four execution models: the backend decides whethersend()returns a value, an awaitable, a TwistedDeferredor aconcurrent.futures.Future— and the type checker knows which, including the per-operation result type (Item,Awaitable[Item],Deferred[Item],Future[Item]).One structural
Backendprotocol, generic over the execution model’s wrapper type — implement two methods and anything can drive the same clients, including execution models this library has never heard of (Client.sendreturns whatever your backend’ssendreturns). Built-in: requests, httpx (sync + async), aiohttp and Twisted — each behind an optional dependency — plus two stdlib-only ones:urlliband a thread-pool backend returningconcurrent.futures.Futureresults.Endpoints as typed dataclasses:
Operationfixes method and path per class, the field specifiers ofaction0.client.fieldsplace typed fields into query, headers, path templates or the JSON body.Instrumentation
Hooks (logging, metrics, tracing, request decoration) and uniform error translation into one exception family, in every execution model.Batteries for testing API clients without a server:
action0.client.testingships recording stub backends for all three execution models.Fully typed (checked with mypy strict, pyright and ty), Python 3.11+.
The action0 namespace is simply the one the author likes to use for
personal projects.