Implementation:Nautechsystems Nautilus trader Generate Stubs Script
| Knowledge Sources | |
|---|---|
| Domains | Build_Tooling, Python, Rust |
| Last Updated | 2026-02-10 08:00 GMT |
Overview
Custom build and stub-generation script that produces .pyi type stubs from Rust PyO3 bindings and relocates generated classes into their correct Python submodule namespaces.
Description
The generate_stubs.py script bridges the gap between Rust PyO3 bindings (compiled into a single _libnautilus.so) and Python's type system. Without this script, IDE autocompletion and mypy static analysis would have no type information for the Rust extension. The script operates in two stages: (1) Stub generation invokes cargo run --bin python-stub-gen in crates/pyo3/ to produce raw .pyi stubs via pyo3-stub-gen. (2) Post-processing performs extensive fixups: adds ruff ignore headers, renames py_new methods to __init__, normalizes type references, and critically, relocates specific classes from the monolithic _libnautilus stub into their target submodule stubs (e.g., model, adapters.blockchain) using a MODULE_FIXUPS configuration table. The script also cleans orphaned decorators and updates __all__ exports.
The script supports three modes: standalone stub generation (python generate_stubs.py), build step (python generate_stubs.py build), and integration as a maturin pre-build hook via pyproject.toml.
Usage
Run this script after compiling the Rust PyO3 extension to regenerate type stubs. It is automatically invoked as a maturin pre-build hook in the v2 build pipeline. For v1 development, run it manually after Rust changes that affect the Python API surface.
Code Reference
Source Location
- Repository: Nautechsystems_Nautilus_trader
- File: python/generate_stubs.py
- Lines: 1-620
Signature
@dataclass(frozen=True)
class StubFixup:
"""Configuration for relocating and patching stub content for a module."""
classes: tuple[str, ...] = ()
imports: tuple[str, ...] = ()
all_exports: tuple[str, ...] = ()
MODULE_FIXUPS: dict[str, StubFixup] = {
"adapters.blockchain": StubFixup(
classes=("BlockchainDataClientConfig", "BlockchainDataClientFactory", "DexPoolFilters"),
imports=("import builtins", "import typing", ...),
),
"model": StubFixup(
classes=(...), # Classes to relocate from _libnautilus to model
),
}
METHOD_RENAMES: dict[str, str] = {
"py_new": "__init__",
}
def generate_stubs(project_root: Path) -> None:
"""Generate and post-process .pyi stubs from PyO3 bindings."""
def main(argv: Sequence[str] | None = None) -> int:
"""Entry point supporting 'generate' and 'build' subcommands."""
Import
# Standalone stub generation
python python/generate_stubs.py
# Build mode (maturin integration)
python python/generate_stubs.py build
# Automatic via maturin pre-build hook (configured in python/pyproject.toml)
I/O Contract
Inputs
| Name | Type | Required | Description |
|---|---|---|---|
| crates/pyo3/ | Directory | Yes | PyO3 crate with python-stub-gen binary |
| MODULE_FIXUPS | Config | Yes | Mapping of target modules to classes to relocate |
| METHOD_RENAMES | Config | Yes | Method name transformations (py_new to __init__) |
Outputs
| Name | Type | Description |
|---|---|---|
| .pyi files | Stub files | Type stubs for all Python submodules |
| _libnautilus.pyi | Stub file | Pruned stub for the raw PyO3 extension |
| __all__ exports | Lists | Updated module-level export declarations |
Usage Examples
# Generate stubs after Rust changes
cd python/
python generate_stubs.py
# Build the maturin package (stubs generated automatically as pre-build hook)
cd python/
maturin develop
# Verify stubs are correct
mypy nautilus_trader/
# The generated stubs enable IDE autocompletion:
from nautilus_trader.model import Price # Type info available from .pyi stub
price = Price(1.2345, precision=4) # IDE shows constructor signature