Module 04 — Maturin
Goal
Package the Rust library so Python can import it as an ordinary module.
From the Python consumer’s point of view there should be no Cargo, no .so hunting, and no special knowledge of the build system.
What Maturin does
| Concern | Maturin responsibility |
|---|---|
| Compile the Rust crate | Yes |
| Produce a Python extension module | Yes |
| Build wheels | Yes |
| Development installs | maturin develop |
| Release artifacts | maturin build |
Create a virtual environment first
maturin develop installs into the active Python environment. Maturin expects a virtualenv (or conda env); it will refuse to install into the system Python.
From the kernel/ directory:
# 1. Create a venv (once)
python3 -m venv .venv
# 2. Activate it
# Linux / macOS:
source .venv/bin/activate
# Windows (cmd):
# .venv\Scripts\activate.bat
# Windows (PowerShell):
# .venv\Scripts\Activate.ps1
# 3. Confirm you are inside the venv
which python # should point at .../kernel/.venv/bin/python
python -c "import sys; print(sys.prefix)"
# 4. Install Maturin into this venv
pip install -U maturinWhen the venv is active, your prompt often shows (.env).
To leave the venv later:
deactivateOptional: named venv elsewhere
python3 -m venv ~/venvs/oe-kernel
source ~/venvs/oe-kernel/bin/activate
pip install -U maturinDevelopment workflow
# Inside kernel/
maturin develop # builds + installs into the active environment
python -c "import open_engineering_kernel; print('ok')"maturin develop is the iterative loop while writing the course exercises.
If you see:
Couldn't find a virtualenv or conda environment
the venv is not active - run source .venv/bin/activate (or Windows equivalent) and try againc.
Release workflow
maturin build --release
# → target/wheels/open_engineering_kernel-…‑….whl
ls target/wheels/# Absolute path to the wheel
WHEEL=$(realpath target/wheels/open_engineering_kernel-*.whl)
echo "$WHEEL"Then in a fresh environment (definition of done for packaging):
python3 -m venv /tmp/oe-clean
source /tmp/oe-clean/bin/activate
pip install "$WHEEL" # path/to/open_engineering_kernel-*.whl
python -c "from open_engineering_kernel import Identifier; print(Identifier.parse('oe.course.pico'))"The course must not stop at maturin develop. Shipping a wheel that installs cleanly is part of the definition of done.
Concepts to understand (without drowning)
- Virtual environment — isolated Python prefix; keeps course packages off the system interpreter
- Native extension — compiled code loaded by the Python interpreter
- Wheel — the standard binary distribution format for Python packages
- Platform tags — Linux / macOS / Windows × CPU architecture × Python ABI
- Development vs release builds — speed of iteration vs optimised artifacts
Design rule
Downstream Python code should treat the kernel like any other package:
from open_engineering_kernel import Identifier, validate_manifestNo sys.path hacks, no ctypes loading, no knowledge of target/debug.
Exercise
- Create and activate a venv under
kernel/.venv. - Install Maturin with
pip install maturin. - Run
maturin developsuccessfully. - Import the module from a Python REPL while the venv is active.
- Build a release wheel with
maturin build --release. - Install that wheel into a second clean venv and import again.