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.9.tar.gz (72.2 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.9-py3-none-any.whl (57.0 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: dyadpy-0.1.9.tar.gz
  • Upload date:
  • Size: 72.2 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.9.tar.gz
Algorithm Hash digest
SHA256 ce1315f239f67b2b32c6563c78228697d800848ee2c0a653a2a0e8f8dc5cc5a0
MD5 1cfc13cfd3dc4c89c2e5eca99a7ca520
BLAKE2b-256 b83957faf638186b5bc8d3a692f4a15cc8e45a96d910e47c1eb2efde0afd63cd

See more details on using hashes here.

Provenance

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

File metadata

  • Download URL: dyadpy-0.1.9-py3-none-any.whl
  • Upload date:
  • Size: 57.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.9-py3-none-any.whl
Algorithm Hash digest
SHA256 5ae3cc9c386755f0027407b8b2e74d3d966d9e57cce0f5f112be78bff90e8b56
MD5 274fbb6c09b877ba4733b8b9160d431d
BLAKE2b-256 bd49b5fd5554a12b444858783ffe4b4d063155f2186507a4efd4bae9ef4b16a7

See more details on using hashes here.

Provenance

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