Source code for robonix_api.codegen
# SPDX-License-Identifier: MulanPSL-2.0
"""Locate codegen output for the calling package.
Every robonix package gets a single canonical codegen directory:
<pkg>/rbnx-build/codegen/
proto_gen/ # gRPC stubs (atlas_pb2, robonix_contracts_pb2_grpc, ...)
robonix_mcp_types/ # MCP typed-input dataclasses (when --mcp was passed)
`rbnx codegen -p <pkg>` writes there and `Capability(...)` reads from there.
Developers don't have to plumb either path anywhere — these helpers walk up
from the caller and add the right dirs to `sys.path`, idempotently.
"""
from __future__ import annotations
import sys
from pathlib import Path
def _add_to_path(p: Path) -> None:
s = str(p)
if s not in sys.path:
sys.path.insert(0, s)
[docs]
def ensure_proto_gen(start: Path | None = None) -> Path | None:
"""Walk up from `start` looking for `rbnx-build/codegen/`. Adds proto_gen and
(if present) robonix_mcp_types to sys.path. Returns the codegen dir, or None.
Kept under the historical name so existing callers keep working — does the
fuller "ensure_codegen" job now."""
d = (start or Path.cwd()).resolve()
for _ in range(20):
codegen = d / "rbnx-build" / "codegen"
proto_gen = codegen / "proto_gen"
if (proto_gen / "atlas_pb2.py").is_file():
_add_to_path(proto_gen)
mcp_types = codegen / "robonix_mcp_types"
if mcp_types.is_dir():
_add_to_path(mcp_types)
return codegen
if d.parent == d:
break
d = d.parent
return None
[docs]
def find_pkg_root(start: Path) -> Path | None:
"""Walk up looking for `package_manifest.yaml`. Returns the dir containing it."""
d = start.resolve()
for _ in range(20):
if (d / "package_manifest.yaml").is_file():
return d
if d.parent == d:
return None
d = d.parent
return None