Python bindings expose the core Rust functionality (Mesh Transport, State Sync, Integration) as a high‑level Python API, enabling rapid prototyping, scripting, and integration with existing Python‑based robotics stacks (ROS2, OpenCV, etc.).
-
Full Feature Parity
- All major Rust structs and functions accessible from Python.
- Asynchronous support compatible with
asyncio. - Error translation (Rust
Result→ Python exceptions).
-
Ease of Use
- Idiomatic Python naming (snake_case, context managers, etc.).
- Comprehensive docstrings with examples.
- Type hints (PEP 484) for better IDE support.
-
Performance
- Minimal overhead for crossing the language boundary.
- Zero‑copy data sharing where possible (e.g., bytes, arrays).
- Ability to run callbacks from Rust on Python objects.
-
Distribution
- Package on PyPI as
offline-first-autonomy. - Support Linux, macOS, Windows (with Rust toolchain).
- Provide pre‑built wheels for common platforms.
- Package on PyPI as
- Startup time: < 100 ms for importing the module.
- Memory overhead: < 5 MB per imported module.
- Thread safety: Safe to use from multiple Python threads.
- Binding framework: PyO3 (with
maturinfor building). - Async runtime:
pyo3‑asyncioto bridge Tokio andasyncio. - Serialization:
serde+pyo3‑serdefor automatic conversion of complex types.
offline_first_autonomy/
├── __init__.py
├── transport.py # Mesh Transport
├── state_sync.py # CRDT map & sequences
├── integration.py # Integrated adapter
├── agent.py # High‑level Agent class
├── exceptions.py # Custom exceptions
└── utils.py # Helper functions
class MeshTransport:
def __init__(self, config: TransportConfig) -> None: ...
async def start(self) -> None: ...
async def stop(self) -> None: ...
async def broadcast(self, data: bytes) -> None: ...
async def send_to(self, peer_id: PeerId, data: bytes) -> None: ...
def peers(self) -> List[PeerInfo]: ...
async def events(self) -> AsyncIterator[TransportEvent]: ...class CrdtMap:
def __init__(self) -> None: ...
def get(self, key: str) -> Optional[Any]: ...
def set(self, key: str, value: Any) -> None: ...
def delete(self, key: str) -> None: ...
def merge(self, other: CrdtMap) -> None: ...
def to_dict(self) -> Dict[str, Any]: ...class SyncAgent:
def __init__(self, transport: MeshTransport, crdt_map: CrdtMap) -> None: ...
async def sync(self) -> None: ...
def subscribe(self, pattern: str) -> None: ...
async def wait_for_key(self, key: str, timeout: float = None) -> Any: ...- Rust
Vec<u8>↔ Pythonbytes(zero‑copy viaPyBytes). - Rust
String↔ Pythonstr. - Rust
HashMap↔ Pythondict. - Rust
enum↔ PythonEnumor discriminated unions. - Custom types (e.g.,
PeerId) become opaque Python objects with__repr__and__str__.
- Rust async functions are exposed as Python coroutines.
- Use
pyo3‑asyncioto run Tokio futures on the same event loop asasyncio. - Example:
import asyncio
from offline_first_autonomy import MeshTransport
async def main():
transport = MeshTransport(config)
await transport.start()
await transport.broadcast(b"hello")- Rust
anyhow::Error→ PythonRuntimeErrorwith a descriptive message. - Custom error types (e.g.,
TransportError,MergeConflictError) become dedicated Python exception classes.
- Create
python/directory withpyproject.tomlandCargo.toml(as a PyO3 crate). - Define a minimal Rust module that exports a “hello world” function.
- Build with
maturin developand verify import works.
- Wrap the Rust
MeshTransportstruct with PyO3. - Expose essential methods (
start,stop,broadcast). - Implement conversion of
TransportEventto Python objects. - Write Python unit tests using
pytest.
- Wrap
CrdtMapandCrdtSeq. - Provide Pythonic
__getitem__/__setitem__for map‑like access. - Implement
mergeandto_dict.
- Create
SyncAgentclass that combines transport and CRDT. - Add subscription and delta‑streaming callbacks.
- Provide example scripts.
- Configure
maturinto produce wheels. - Add GitHub Actions workflow to build and upload to PyPI on tags.
- Write installation instructions.
pyo3 = "0.21"pyo3‑asyncio = { version = "0.21", features = ["tokio‑runtime"] }maturin(build‑time)pytest(dev)
- Unit tests: Rust‑side tests for PyO3 bindings (using
pyo3‑test). - Integration tests: Python scripts that import the built module and verify functionality.
- End‑to‑end tests: Spawn multiple Python processes that communicate via the bindings and assert consistency.
- Should we support Python 3.7? (PyO3 supports 3.7+ but 3.8 is recommended.)
- How to handle Rust panics across the FFI boundary? (PyO3 converts them to
SystemError.) - Should we provide a synchronous API for simplicity, or force users to use
asyncio?