Implement §2 method translators — OSchema → Rust trait methods + Python dataclass methods #60
Labels
No labels
prio_critical
prio_low
type_bug
type_contact
type_issue
type_lead
type_question
type_story
type_task
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
lhumina_code/hero_rpc#60
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Context
Follow-up from #55. The hybrid hero_rpc2 SDK rails landed on branch
issue-55-codegen-alignment(commits up through479a558) but two method-translator pieces were deliberately scoped out — the per-method codegen that turns OSchema-defined RPC methods into actual Rust trait methods (hero_rpc2#[rpc(server, client)]shape) and Python dataclass methods. Both havecompile_error!/# TODOmarkers in the generated output today.What's done (rails)
Per #55 closing summary and the vendor commits:
crates/hero_rpc2/vendored fromdelandtj/hero_rpc2(e2f4d27).HeroRequestContexttypes +ServerBuilderheader-lift config (479a558).OschemaBuildConfig/ generator dispatch.compile_error!("TODO: method translator")/# TODOplaceholders where method bodies should go.What this issue does
Part A — OSchema → Rust trait methods
For every OSchema-defined service method, emit a
#[method(name = "...")]entry inside the generated trait (the one annotated withhero_rpc2::prelude::#[rpc(server, client)]). Signature must:ctx: Option<HeroRequestContext>as the first arg (per the parent META locked decision).crate::generate::Generator).RpcResult<T>matching the OSchema return type.compile_error!placeholder.Server impl stub stays preserved (don't regenerate body — only the trait signature is generated; the impl
rpc.rsis contributor-owned).Part B — OSchema → Python dataclass methods
For every OSchema-defined service method, emit a Python method on the SDK class:
hero_rpc2vendor work).# TODO: method translatormarkers.Cross-target consistency
Both translators read the same OSchema method definitions. Factor shared parsing logic to keep them in sync.
Constraints
issue-55-codegen-alignmentbranch until that PR merges. Coordinate with the merger.example/recipe_servershould compile and the generated Rust client + Python SDK should be usable end-to-end against the running server.Acceptance
compile_error!("TODO: method translator")in generated Rust output.# TODO: method translatorin generated Python output.recipe_serverbuilds with the generated Rust client; round-trip RPC call test passes.system.pingover UDS) passes.Related
Pushed
issue-60-method-translatorson top ofissue-55-codegen-alignmentwith the §2 method translators.What landed
Rust (
crates/generator/src/build/emit/rust_rpc2.rs)compile_error!stub with full OSchema → trait emission.service Foo { ... }method becomes#[method(name = "<svc>.<m>")] async fn <svc>_<m>(&self, ctx: Option<HeroRequestContext>, …) -> RpcResult<T>inside the#[rpc(server, client)]trait.<sdk>/src/<domain>.rsso the trait file is self-contained (nohero_rpc_osisdep — SDK-friendly).crates/hero_rpc2/src/context.rs:HeroRequestContextnow derivesSerialize/Deserializewith#[serde(default)]so the locked trait shape survives jsonrpsee'sParams::parsewhile staying interoperable with the existing header-lift transport (JSONnull→None).Python (
crates/generator/src/build/emit/python_sdk.rs)# TODO method translatorstub with@dataclass(kw_only=True)+ per-methodasync defemission._transport.pynext to the domain modules:UdsJsonRpcTransport(socket_path, headers=…)wrappinghttpx.AsyncClientover UDS.paramsand await the transport's JSON-RPC 2.0 dispatch.Acceptance evidence
cargo test -p hero_rpc_generator --lib build::emit— 10/10 pass, covering scalar params, struct params, list returns, thectx: Option<HeroRequestContext>first-arg shape, and the no-schema fallback.cargo build -p recipe_sdk_rpc2— a new workspace crate that pulls inexample/recipe_server/schemas/recipes/, runs the rpc2 + Python emitters, and compiles the generated trait. ✓ builds end-to-end.HERO_RPC_PYTHON=<venv>/bin/python3 cargo test -p recipe_sdk_rpc2 --features python-e2e --test python_ping_e2e— spins uphero_rpc2's HTTP-on-UDS server with a hand-registeredsystem.ping, subprocesses Python through the generatedUdsJsonRpcTransport, and asserts the echoed payload. ✓ round-trip passes. Skips gracefully whenpython3/httpxaren't on PATH so bare-image CI stays green.Files
crates/generator/src/build/emit/rust_rpc2.rs— method translator + testscrates/generator/src/build/emit/python_sdk.rs— method translator + transport module + testscrates/generator/src/build/builder.rs— passschemas_dirthrough to the emitterscrates/hero_rpc2/src/context.rs—Serialize/DeserializeonHeroRequestContextexample/recipe_sdk_rpc2/— end-to-end validation crate (Cargo.toml, build.rs, lib.rs,tests/python_ping_e2e.rs,tests/debug_curl.rs)Notes
issue-60-method-translatorsbuilt onissue-55-codegen-alignmentper the parent META's tier-2 instructions; once #55 lands ondevelopment, this rebases on top.#[rpc(server, client)]macro requires a directjsonrpseedep on consumer crates so the proc-macro'sproc_macro_cratelookup resolves —recipe_sdk_rpc2/Cargo.tomlcarries that as a small dep alongsidehero_rpc2.