Editing .pyi Contracts

prik's generated .pyi files are editable wrapper contracts. They look like Python stubs, but they also describe native calls, storage, and results. Edit them to change the Python API without changing the native implementation.

This section explains supported edits and their effect. The complete grammar will be covered by the Semantic .pyi Format reference.

Workflow

Generate a starter contract:

python3 -m prik generate --pyi native/solver.f90 --out contracts/solver

Edit contracts/solver/__init__.pyi and its leaf .pyi files, then build from the entry contract:

python3 -m prik contracts/solver/__init__.pyi \
  --native-fortran-sources native/solver.f90 \
  --out-dir build/solver

You can provide compiled objects or libraries instead of source. In either case, the .pyi files define the Python API and the native files provide its implementation. prik does not reread the native source to restore declarations you removed from the contract.

Keep an unchanged generated copy while experimenting. It makes each edit easy to compare and undo.

What Do You Want to Change?

Names, Visibility, and Modules

Functions and Classes

Arguments, Calls, and Results

Most edits change the Python surface: names, visibility, grouping, or how native arguments appear as Python parameters and results.

Some facts must continue to match the supplied implementation:

  • native module and symbol names;
  • procedure kind and native argument order;
  • datatype, kind, rank, and storage category;
  • callback signature; and
  • required native imports.

prik checks that the contract is internally consistent. It cannot prove that an arbitrary object or shared library has the binary interface described by the contract. A contract that gives false native facts may fail while building, importing, or calling the extension.

Safety Checklist

Before rebuilding:

  • Start from a contract generated for the same native implementation.
  • Make one kind of edit at a time.
  • Keep native types, ranks, argument order, and symbol names accurate.
  • Do not invent optionality, ownership, or a release method.
  • Rebuild and call the edited path once before making the next change.

When prik rejects an incomplete or unsafe rule, fix the contract instead of removing metadata until the build happens to pass.

Understanding Errors

  • While loading the .pyi: check Python syntax, imports, decorators, annotations, and import cycles.
  • While checking the contract: check duplicate exports, missing links, invalid projections, and public declarations that expose private types.
  • While planning the wrapper: check ownership, lifetime, mutation, allocation, conversion, and release rules.
  • While building or calling: check that the supplied implementation matches the declared native symbol and binary interface.

Errors include the contract path and declaration when that information is available. Use --verbose to see the build commands; use --debug when a full Python traceback is needed.

Next

Start with Exports and Modules for the most common API edits.