diff --git a/README.md b/README.md index 63091a9..cc2ca07 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ Generates `.pyi` type stub files for Cap'n Proto schemas, providing IDE autocomp | Arch Linux | `sudo pacman -S capnproto` | | Ubuntu/Debian | `sudo apt install capnproto` | | macOS | `brew install capnp` | -| Windows | Download from [capnproto.org](https://capnproto.org) | +| Windows | Download from [capnproto.org](https://capnproto.org/install.html) | ## Installation @@ -33,82 +33,90 @@ capnp compile -opy myschema.capnp This generates `myschema_capnp.pyi` — a Python type stub file that type checkers can use. Runtime import (`import myschema_capnp`) is handled automatically by pycapnp's import hook. -### Generated output +### Multi-file projects -For a schema like: +```bash +capnp compile -opy --src-prefix=. src/schema.capnp +``` + +Cross-file type references automatically produce relative imports in the generated stubs. + +## Example + +Input (`addressbook.capnp`): ```capnp struct Person { name @0 :Text; age @1 :Int32; -} + phones @2 :List(PhoneNumber); -enum Gender { male @0; female @1; } + struct PhoneNumber { + number @0 :Text; + type @1 :Type; + enum Type { mobile @0; home @1; work @2; } + } +} ``` -`myschema_capnp.pyi`: +Output (`addressbook_capnp.pyi`): ```python -"""Auto-generated type stub for myschema.capnp""" +"""Auto-generated type stub for addressbook.capnp""" from __future__ import annotations from collections.abc import Iterator, Sequence from contextlib import contextmanager from typing import IO, Literal -Gender = Literal["male", "female"] - class Person: name: str age: int + phones: Sequence[Person.PhoneNumber | Person.PhoneNumberBuilder | Person.PhoneNumberReader] + + class PhoneNumber: + Type = Literal["mobile", "home", "work"] + type: Type + number: str + ... @staticmethod def new_message(**kwargs) -> PersonBuilder: ... - @staticmethod - @contextmanager - def from_bytes(data: bytes, ...) -> Iterator[PersonReader]: ... - @staticmethod - def from_bytes_packed(data: bytes, ...) -> PersonReader: ... def to_dict(self) -> dict: ... class PersonReader(Person): def as_builder(self) -> PersonBuilder: ... class PersonBuilder(Person): - @staticmethod - def from_dict(dictionary: dict) -> PersonBuilder: ... - def copy(self) -> PersonBuilder: ... def to_bytes(self) -> bytes: ... - def to_bytes_packed(self) -> bytes: ... - def to_segments(self) -> list[bytes]: ... def as_reader(self) -> PersonReader: ... - @staticmethod - def write(file: IO[bytes]): ... - @staticmethod - def write_packed(file: IO[bytes]): ... -``` - -## Development - -Uses [PDM](https://pdm-project.org/) for project management. - -```bash -git clone https://github.com/capnproto/pycapnp # or your fork -cd capnp-py -pdm install # installs dependencies + dev tools -pdm run pytest # run tests + ... ``` ## Supported Features | Feature | Status | |---------|--------| -| Structs (Reader/Builder classes) | ✅ | -| Enums (Literal aliases) | ✅ | +| Structs (Reader / Builder classes) | ✅ | +| Enums (`Literal[...]` aliases) | ✅ | | Nested types | ✅ | -| Lists (Sequence[T]) | ✅ | -| Unions (which/init) | ✅ | +| Lists (`Sequence[T]`) | ✅ | +| Unions (`which()` / `@overload init()`) | ✅ | +| Groups | ✅ | | Self-referencing structs | ✅ | -| Interfaces (RPC) | ⏳ Phase 3 | -| Constants | ⏳ Phase 2 | -| Generics | ⏳ Phase 2 | +| Constants (primitives, enums) | ✅ | +| Generics (`TypeVar`, `Generic[T]`, brand resolution) | ✅ | +| Interfaces (RPC: Client / Server classes) | ✅ | +| Cross-file imports (relative `.` imports) | ✅ | +| Annotations (`$Cxx.name`, etc.) | ⏳ | + +## Development + +Uses [PDM](https://pdm-project.org/) for project management. + +```bash +git clone https://github.com/NCBM/capnpc-py +cd capnp-py +pdm install # installs dependencies + dev tools +pdm run pytest # run tests +``` ## License