Skip to main content

A type-safe RPC bridge between Python and TypeScript. The function signature is the contract.

Project description

dyadpy (Python)

A type-safe RPC bridge between Python and TypeScript.

uv add 'dyadpy==0.1.0a0'   # alpha — drop the pin once v0.1.0 ships

This is the Python half of Dyadpy. It ships:

  • A thin ASGI framework (dyadpy.App) that uses your function signatures as the contract — no separate Pydantic models declared above the handler.
  • A type extractor that walks inspect.signature + typing.get_type_hints, normalizes through msgspec's native JSON Schema export, and produces a canonical IR.
  • A codegen that turns the IR into a single client.ts for your frontend.
  • A CLI (dyadpy dev, dyadpy build, dyadpy codegen, dyadpy init) that runs the whole loop in one process.

For the full story, the design rationale, and a side-by-side comparison vs. FastAPI + openapi-typescript / tRPC / Encore.ts / Connect-RPC, see the repo README.

30-second example

from dyadpy import App, stream, raises
from dataclasses import dataclass
import msgspec

app = App()

class CreatePost(msgspec.Struct):
    title: str
    body: str

class Post(msgspec.Struct):
    id: int
    title: str
    body: str

@dataclass
class PostNotFound(Exception):
    post_id: int

@app.post("/posts")
async def create_post(data: CreatePost) -> Post: ...

@app.get("/posts/{post_id}")
@raises(PostNotFound)
async def get_post(post_id: int) -> Post: ...

class Tick(msgspec.Struct, tag="tick"):
    seq: int

@app.get("/ticks")
async def ticks(count: int) -> stream[Tick]:
    for i in range(count):
        yield Tick(seq=i)

Run it:

dyadpy dev server.app:app

The watcher writes frontend/src/lib/dyadpy/client.ts automatically. Then in your frontend:

import { api } from "@/lib/dyadpy/client";

const post = await api.posts.create({ data: { title: "hi", body: "world" } });

for await (const ev of api.ticks.list({ count: 10 })) {
  /* typed */
}

Primitives in this package

Primitive Purpose
App + @app.{get,post,put,patch,delete} Route decorators.
Annotated[T, Body / Query / Path / Header / Cookie / File / Form] Parameter location markers.
Annotated[list[T], Query()] Repeated query params (?tag=a&tag=b).
Bytes Raw request / response bodies. Skips the JSON envelope.
stream[T] Typed SSE — client gets AsyncIterable<T>.
@raises(E1, E2, …) Typed error union → Result<T, E1 | E2> on the TS side.
Context.set_status / set_header / set_cookie / after Shape the response without dropping to Starlette.
Depends(provider) DI in the FastAPI shape.
after(fn, …) Run a callback after the response is sent.
InMemoryBackend + TaskBackend Protocol Background jobs.
dyadpy.otel.instrument(app) One OpenTelemetry span per request (dyadpy[otel]).
dyadpy openapi / swift / kotlin (CLI) Emit OpenAPI 3.1, Swift, or Kotlin clients off the same IR.

Full reference: https://github.com/tamimbinhakim/dyadpy/blob/main/docs/reference.md

Optional extras

uv add 'dyadpy[pydantic]'  # Pydantic plugin (model_validate + model_json_schema)
uv add 'dyadpy[otel]'      # OpenTelemetry middleware
uv add 'dyadpy[all]'       # everything

Scope

Dyadpy ships at the wire level: RPC, typed streaming, typed errors, cancellation, file uploads, dependency injection. It does not ship vertical integrations — no LLM types, no React hooks in core, no chat-bot primitives. Those layers compose on top of the fundamentals and live in their own packages.

License

MIT

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

dyadpy-0.1.8.tar.gz (71.7 kB view details)

Uploaded Source

Built Distribution

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

dyadpy-0.1.8-py3-none-any.whl (56.7 kB view details)

Uploaded Python 3

File details

Details for the file dyadpy-0.1.8.tar.gz.

File metadata

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

File hashes

Hashes for dyadpy-0.1.8.tar.gz
Algorithm Hash digest
SHA256 4fbf3ecabcb329c86738ffb2a521bbb29c9fb7ef32e784ad6ed0dc21c724d847
MD5 5022e8366e4429dfa2ccb9a3a552859a
BLAKE2b-256 2b9d5ac878ab967ee809acb7f60534ca01f345150c2419785d10c93b51a8b170

See more details on using hashes here.

Provenance

The following attestation bundles were made for dyadpy-0.1.8.tar.gz:

Publisher: release.yml on tamimbinhakim/dyadpy

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

File details

Details for the file dyadpy-0.1.8-py3-none-any.whl.

File metadata

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

File hashes

Hashes for dyadpy-0.1.8-py3-none-any.whl
Algorithm Hash digest
SHA256 d3e08826153760c02dab2c8c88c78b81946aafb1ea35ef4a5b14b9fedb0f79b7
MD5 2b2ac5916354f8d9d9d2e1cf7ad871b4
BLAKE2b-256 fe7a29846f554797b5071ec540d5becec9d22bda99f7a2e9e20e4e1d02d82253

See more details on using hashes here.

Provenance

The following attestation bundles were made for dyadpy-0.1.8-py3-none-any.whl:

Publisher: release.yml on tamimbinhakim/dyadpy

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