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.6.tar.gz (70.5 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.6-py3-none-any.whl (56.0 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: dyadpy-0.1.6.tar.gz
  • Upload date:
  • Size: 70.5 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.6.tar.gz
Algorithm Hash digest
SHA256 b08bb7c23b57954f6a5a719f7bc9b411413955138b64910bd1c36090f15151c1
MD5 06451757871cfb9d71b634823a690ebb
BLAKE2b-256 399fc16fd2cb457d309a9f7b50eb3cc11cad1341fc78e8bb3f47b4d505b9d096

See more details on using hashes here.

Provenance

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

File metadata

  • Download URL: dyadpy-0.1.6-py3-none-any.whl
  • Upload date:
  • Size: 56.0 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.6-py3-none-any.whl
Algorithm Hash digest
SHA256 0597564facd653a3578c73515d11b92f23c5b40cbb7e52ecfc57888c8d625216
MD5 5728171107093ea14bc0e404eac7a0e9
BLAKE2b-256 0265d92f46d92e289a914f7ab10d2870a83848b9b154c8c3422fa6204d3efe84

See more details on using hashes here.

Provenance

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