chore: swap build backend from setuptools to maturin - #975
Conversation
Replace the setuptools build backend with maturin so the project builds as a mixed Rust/Python package. This is the backend swap only — the Rust side is an empty placeholder module (src.rs, importable as `from src import rs`) that real functionality will fill in via a follow-up. - pyproject.toml: build-system -> maturin; drop [tool.setuptools.packages.find]; add [tool.maturin] (module-name = "src.rs", manifest-path = "rust/Cargo.toml"); add maturin to the dev dependency group. - rust/: new Cargo.toml + src/lib.rs stub (empty #[pymodule] `rs`, pyo3 abi3). Rust source lives under rust/ to avoid colliding with the Python src/ dir. - .gitignore: ignore rust/target/ and the maturin-develop .so/.pyd/.dylib. - CI/Docker: install a Rust toolchain (dtolnay/rust-toolchain in test.yml, apt cargo in Dockerfile) since every `uv sync` now compiles via cargo. - uv.lock + rust/Cargo.lock regenerated. The importable package stays `src`; nothing under src/ moves or renames, and all console scripts and subpackages are preserved (verified: 402 unit tests pass; wheel bundles src/* plus src/rs.abi3.so).
|
This would allow me to expose rust code directly to python. This backend is the base commit I need before I can start refactoring in that direction |
astral-sh/ruff-action@v3 floats to the latest ruff, now 0.16.0 (pyproject pins only a floor, >=0.14.14). Ruff 0.16.0 formats Python code fences inside *.md, which overlaps with the dedicated rumdl Markdown check and was failing 'Check Python formatting with ruff' on every open PR. Exclude *.md from ruff format so ruff stays scoped to Python and Markdown formatting CI is deterministic across ruff releases.
There was a problem hiding this comment.
Pull request overview
This PR switches Babel’s packaging/build backend from setuptools to maturin so the project can build as a mixed Python/Rust distribution, while keeping the importable Python package layout unchanged (src remains the top-level package). It adds a minimal Rust/PyO3 stub extension to satisfy maturin’s requirements and updates CI/Docker to include a Rust toolchain for builds.
Changes:
- Swap PEP 517 build backend to
maturinand configure it to bundle the existingsrcPython package while emitting an extension module atsrc/rs.*. - Add a placeholder Rust crate (
rust/) with an empty PyO3#[pymodule]importable asfrom src import rs. - Update CI and Docker build prerequisites to install Rust, and add ignores/locks for new build artifacts and dependencies.
Reviewed changes
Copilot reviewed 5 out of 8 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
pyproject.toml |
Switch build backend to maturin; configure [tool.maturin]; add dev dependency; adjust ruff formatter config. |
uv.lock |
Record maturin in the dev dependency set and lock resolution. |
rust/Cargo.toml |
Define the Rust crate and PyO3 dependency for the placeholder extension module. |
rust/src/lib.rs |
Add the empty #[pymodule] fn rs stub importable from Python. |
rust/Cargo.lock |
Commit the Rust dependency lockfile for reproducible cargo builds. |
.github/workflows/test.yml |
Install a Rust toolchain in CI before uv sync so maturin/cargo builds can run. |
Dockerfile |
Install cargo in the container image so uv sync can build the maturin extension. |
.gitignore |
Ignore Rust build outputs and local maturin develop-produced extension binaries. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| # Rust toolchain — required because the build backend is maturin (compiles a native extension). | ||
| RUN apt-get update && apt-get install -y cargo | ||
|
|
| - uses: dtolnay/rust-toolchain@stable | ||
| - run: uv sync --frozen |
Swaps the build backend from setuptools to maturin so Babel builds as a mixed Rust/Python
package, ahead of landing native (Rust) functionality. This is the backend swap only — the Rust
side is an inert placeholder module, the importable package stays
src, and nothing under itmoves or renames.
Build backend
pyproject.toml:[build-system]is nowrequires = ["maturin>=1.0,<2.0"]/build-backend = "maturin"; dropped[tool.setuptools.packages.find].[tool.maturin]:module-name = "src.rs"places the compiled extension atsrc/rs.*andtells maturin to bundle the
srcpackage (auto-resolved to the repo root — src-layout detectiondoesn't fire because there's no
src/babel_pipeline/__init__.py);manifest-path = "rust/Cargo.toml"keeps Cargo off the Pythonsrc/dir.devgroup: addedmaturin>=1.0,<2.0souv run maturin developworks locally (the[build-system].requiresentry is build-isolation only).Rust stub
rust/Cargo.toml+rust/src/lib.rs: empty#[pymodule] fn rs(pyo3,abi3-py311+extension-module), importable asfrom src import rs. Real functionality lands in a follow-up.rust/so Cargo's defaultsrc/lib.rsnever collides with thePython
src/package.Build prerequisites (CI + Docker)
.github/workflows/test.yml: addeddtolnay/rust-toolchain@stablebeforeuv syncin bothjobs — every
uv syncnow compiles via cargo, andubuntu-latestships no Rust.Dockerfile:apt-get install -y cargo(system-wide, beforeUSER nru) for the same reason.downstream installs) — the cost of adopting maturin before the Rust code exists.
Housekeeping
.gitignore: ignorerust/target/and thematurin developbinaries(
src/rs.*.so/.pyd/.dylib).uv.lock+rust/Cargo.lock: regenerated and committed (CI runsuv sync --frozen).Design
supports requires a
Cargo.toml, so a bare backend swap with no Rust won't build. The empty#[pymodule]is the smallest thing that makes maturin viable now.module-name = "src.rs": the import package is literally namedsrc(flat layout).Verified against maturin's resolver (
project_layout.rs/module_writer/mod.rs): this bundlesall of
src/*and drops the extension atsrc/rs.<so>without moving or renaming anything.local
cp311-abi3wheel).Testing
uv sync— buildsbabel-pipelinevia maturin → cargo; installsmaturin==1.14.1.uv run python -c "import src; from src import rs; from src.tools.clique_diff import cli"— ok.uv run pytest -m unit -q→402 passed, 105 deselected.uv build→babel_pipeline-1.17-cp311-abi3-linux_x86_64.whl;unzip -lshowssrc/__init__.py,src/node.py,src/tools/...,src/rs.abi3.so, and all 4 console scripts inentry_points.txt.uv run babel-clique-diff --help— resolves.Questions for the reviewer
stub-only PR, or would you rather gate the maturin switch behind the PR that adds real Rust?