Skip to content

Add Rust, PyO3, and Maturin chapter (book, example, slides, instructor notes) - #1

Closed
thewtex wants to merge 19 commits into
mainfrom
rust
Closed

Add Rust, PyO3, and Maturin chapter (book, example, slides, instructor notes)#1
thewtex wants to merge 19 commits into
mainfrom
rust

Conversation

@thewtex

@thewtex thewtex commented Jul 11, 2026

Copy link
Copy Markdown
Owner

Summary

Adds a complete Rust, PyO3, and Maturin chapter to the SIMPLE-Py workshop — a
new book chapter, a runnable PyO3 example project, a Marp slide deck, and a set of
instructor-facing research notes. This fills the "Maturin, PyO3, and Rust" slot that
previously existed only as an empty heading in the Compiled section, giving the
workshop a first-class Rust track alongside its C++ material.

Why

The Compiled section covered pybind11/nanobind (C++) but left Rust as a stub. Rust +
PyO3 + maturin is now a mainstream way to ship compiled Python extensions, so the
workshop needed a self-contained, teachable chapter that mirrors the book's
existing "install-and-lock with pixi" approach and requires no rustup or system Rust.

What's included

Book chaptercontent/compiled/04_rust_pyo3.md (wired into myst.yml TOC and
cross-linked from content/compiled/02_binding.md). Walks from motivation through a
first extension to shipping wheels: Why Rust → the toolchain stack → pixi setup → a
first extension → build/iterate loop → benchmarking → classes → native-feeling errors
→ the GIL and free-threading → shipping wheels → exercises → where to go next.

Runnable exampleexamples/2_04_rust_pyo3/, a minimal pixi-managed PyO3
extension. src/lib.rs exposes a GIL-releasing count_primes, a Point #[pyclass],
a sum_as_string function, and a checked_div that raises a Python exception; with
a pytest suite (tests/) and a pure-Python-vs-Rust benchmark (bench.py). Everything
— the Rust compiler, maturin, Python, pytest — installs from conda-forge via pixi, and
pixi run test / pixi run bench chain a build in front so they never run against a
stale extension.

Slide deckslides/2_04_rust_pyo3.md, a Marp deck (theme: simplepy) tracking
the chapter for live presentation.

Instructor notesinstructor-notes/: four research notes (PyO3 current state,
maturin workflows, the pixi/conda-forge Rust toolchain, and the Rust-for-Pythonistas
landscape) plus a synthesis deep-dive with a 30-minute teaching runbook. These carry
Obsidian-style frontmatter and [[wiki-links]] and are deliberately kept out of the
myst.yml TOC, so they are never published into the book.

Supporting changes

  • AGENTS.md — documents the new examples/ and instructor-notes/ directories and
    scopes the "content, not code" note to the book itself (the example is runnable).
  • .pre-commit-config.yaml — excludes the pixi-generated pixi.lock from prettier
    (consistent with its linguist-generated marking in .gitattributes).
  • .gitignore — ignores agent-local .serena/ tool state.

Notes for reviewers

  • All prose is em-dash/en-dash free (ASCII punctuation throughout); the branch history
    was rewritten so no commit diff introduces those characters.
  • Instructor-note technical claims were fact-checked against primary sources (PyO3 0.29
    docs, maturin 1.14.1 CLI output, the conda-forge rust feedstock, PEP 803) and passed a
    CodeRabbit review; the benchmark timings were captured from a real pixi run bench.
  • prek (all hooks) passes and bun run build-book / build-slides both build cleanly.

🤖 Generated with Claude Code

henryiii and others added 12 commits July 10, 2026 17:26
* docs: add minimal compiled package example (collatz)

Fill in the pybind11/scikit-build-core snippets in the compiled intro
chapter and add a runnable copy under examples/2_01_package/collatz.

Assisted-by: ClaudeCode:claude-opus-4.8

* feat: add more to page

Signed-off-by: Henry Schreiner <henryfs@princeton.edu>

* docs: expand compiled package chapter and add slides

Add interactive material to the minimal compiled package chapter: a
benchmark comparing compiled vs pure Python, a binding-tool tab-set
(pybind11/nanobind), a mermaid SDist-vs-wheel flow, a glossary, and
exercises for the SDist, wheel, and extending the extension. Also add a
name-mismatch caution, an editable/debug iteration section, and fix
typos plus the invalid `callout` directive.

Add a Marp deck (slides/2_01_package.md) mirroring the chapter and link
it from the page.

Assisted-by: ClaudeCode:claude-opus-4.8

---------

Signed-off-by: Henry Schreiner <henryfs@princeton.edu>
Split the compiled "Binding tools" chapter into a pybind11/nanobind page
and a separate Rust (maturin, PyO3) page. Renumber the cibuildwheel
content and slide to 04 and update cross-references.

Assisted-by: ClaudeCode:claude-opus-4.8
The compiled intro chapter shared the `package` filename stem with the
basic-packaging chapter, so both produced a `/package` URL. Rename it
(and its slide deck) to `compiled`.

Assisted-by: ClaudeCode:claude-opus-4.8
Add pybind11 intro material to the binding chapter, covering the basic
Simple and Vector2D binding patterns before the Minuit2 example, and a
full walkthrough of binding Minuit2 with pybind11. Reorder so the
pybind11 intro comes before the Minuit2 sections.

Add buildable simpleclass and vectorclass example projects, plus the
pybind11 Minuit2 binding and cpponly/nanobind examples.

Assisted-by: ClaudeCode:claude-opus-4.8
…build#27)

Add an "Intro to nanobind" section before the Minuit2 example and present
the Minuit2 binding code, CMake, and pyproject in pybind11/nanobind tabs
(synced across the page), matching the new nanobind example.

Assisted-by: ClaudeCode:claude-opus-4.8
…les (scikit-build#28)

* docs: add free-threading page with pure, pybind11, and nanobind examples

Fills in the free-threading chapter with a Monte Carlo pi benchmark shown
three ways: pure Python, and compiled inner loops via pybind11 and nanobind
(shown side by side in tabs). Each example is a runnable scikit-build-core /
hatchling project that scales across cores on a free-threaded (3.14t) build.

Assisted-by: ClaudeCode:claude-opus-4.8

* docs: add free-threading slides

Marp deck (slides/6_01_free_threading.md) mirroring the chapter: GIL / PEP 703
background, the Monte Carlo pi example, pure Python vs pybind11/nanobind opt-in
side by side, and cp314t wheels. Links the deck from the page.

Assisted-by: ClaudeCode:claude-opus-4.8
* docs: add slides for the binding-tools chapter

The compiled/02_binding chapter (pybind11 and nanobind) was the only
non-stub chapter without a Marp deck. Add slides covering pybind11 basics,
nanobind's differences, and the Minuit2 wrapping walkthrough, using the
two-column layout to show both tools side by side.

Assisted-by: ClaudeCode:claude-opus-4.8

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Assisted-by: ClaudeCode:claude-opus-4.8
Fill out the lazy imports chapter from PEP 810 and the flake8-lazy blog
post: the problem, the `lazy import` keyword, the back-compat
`__lazy_modules__` list, when not to be lazy, the flake8-lazy tool, and
results. Add a matching Marp deck and link it from the chapter.

Assisted-by: ClaudeCode:claude-opus-4.8
@thewtex thewtex changed the title rust Add Rust, PyO3, and Maturin chapter (book, example, slides, instructor notes) Jul 11, 2026
thewtex and others added 7 commits July 11, 2026 15:34
Adds content/compiled/04_rust_pyo3.md from motivation through a first
working build: Why Rust?, the Rust-to-Python stack translation table,
pixi-managed toolchain setup, the annotated pyo3_example project files,
and the maturin develop / REPL loop. All embedded code is verbatim from
examples/2_04_rust_pyo3/ (committed here as well); all transcripts were
captured from real runs. In the example, the PyZeroDivisionError import
moved into checked_div so page excerpts are self-contained (pytest: 8
passed).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
From benchmark to shipping: 'How fast is it?' (bench.py + real 19x
measurement + debug-vs-release warning), 'Classes' (Point pyclass),
'Errors that feel native' (checked_div + genuine ZeroDivisionError
traceback), 'The GIL (and life without it)' (py.detach +
free-threading dropdown), 'Shipping wheels' (real maturin build
--release transcript, abi3 in plain text, generate-ci/cibuildwheel),
'Try it yourself' exercise, and 'Where to go next' links.

All code blocks verified verbatim against examples/2_04_rust_pyo3/;
all transcripts captured from real runs.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Snippet-verification pass over content/compiled/04_rust_pyo3.md: all 8
:filename: code blocks diff clean against examples/2_04_rust_pyo3/ (full
files or explicitly elided verbatim excerpts), and every pycon/console
transcript was replayed. The one transcript without a recorded capture
(pixi run develop) was re-run and re-pasted; all others reproduce.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Measured every rendered slide with a headless browser: seven slides ran
past the bottom of the 1280x720 Marp canvas even though every code block
respected the 15-line/80-char source guideline. Trimmed the pixi.toml
snippet to a 10-line elided subset, condensed bullets to fewer rendered
lines, elided two transcript lines, and unsplit the further-reading line
so it wraps naturally. All 16 slides now end at or above the density of
the existing 2_03 deck; no code block overflows horizontally.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Cross-checking the deck against the section found one rewritten (not
elided) console line: real maturin output is 'Built wheel for CPython
3.14 to <path>'. Use the deck's established '...' elision style instead.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- instructor-notes/: four research notes (PyO3 current state, maturin
  workflows, pixi Rust toolchain, Rust-for-Pythonistas landscape) plus
  a deep-dive synthesis for teaching the 30-minute segment
- AGENTS.md: document examples/ and instructor-notes/ in Structure and
  scope the 'no code to test' claim to the book itself
- .pre-commit-config.yaml: exclude generated pixi.lock from prettier
  (matches its linguist-generated marking in .gitattributes)
- .gitignore: ignore agent-local .serena/ state
- content/compiled/04_rust_pyo3.md: collapse the 'No rustup' tip into
  a dropdown
- examples/2_04_rust_pyo3/README.md: refresh benchmark timing from a
  fresh run

Code-review fixes (CodeRabbit findings verified against primary
sources before applying): recommend pixi install --locked over
--frozen; correct maturin generate-ci publishing default (API token
via uv publish; trusted publishing is opt-in); mark
pyo3/extension-module redundant with PyO3 0.26+ under maturin;
pyclass requires Send + Sync (unsendable waives Send); abi3t is
CPython 3.15+ while 3.14t needs cp314t wheels; precise rust-src/
rust-docs target list; per-language compiler-package rule of thumb.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@thewtex

thewtex commented Jul 11, 2026

Copy link
Copy Markdown
Owner Author

Superseded by the upstream PR against scikit-build/SIMPLE-Py: scikit-build#32 (branch rebased onto current upstream main; chapter folded into the existing 03_rust.md stub).

@thewtex thewtex closed this Jul 11, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants