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.createPost({ data: { title: "hi", body: "world" } });

for await (const ev of api.ticks({ 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.7.tar.gz (69.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.7-py3-none-any.whl (55.2 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: dyadpy-0.1.7.tar.gz
  • Upload date:
  • Size: 69.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.7.tar.gz
Algorithm Hash digest
SHA256 ea17fe067c0e4968501a4c365605808f41aa34b8c6824fe7f61dadd6c43bf03a
MD5 bc5e9a5759ba83fba34fc7892473fc74
BLAKE2b-256 bcc3b224fdee3cda45104ae2872a922051cc001ffec601caf06ca516abca6c4c

See more details on using hashes here.

Provenance

The following attestation bundles were made for dyadpy-0.1.7.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.7-py3-none-any.whl.

File metadata

  • Download URL: dyadpy-0.1.7-py3-none-any.whl
  • Upload date:
  • Size: 55.2 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.7-py3-none-any.whl
Algorithm Hash digest
SHA256 f8de54a4a1213935a607f99025178719608a29912a8564260985b8a0ea7ccf6e
MD5 a1ae9aee7d6a14ed8241fa91161ac92c
BLAKE2b-256 856e1690e32a6e2682521a7fbdd3470e0cb62dd96477a97b18550db483752e32

See more details on using hashes here.

Provenance

The following attestation bundles were made for dyadpy-0.1.7-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