Skip to content

py: bindings Phase 0–1 — pyo3 0.29, fixtures, _native layout, stubs, release wheels - #20

Draft
asg017 wants to merge 13 commits into
mainfrom
python-phase0
Draft

asg017 wants to merge 13 commits into
mainfrom
python-phase0

Conversation

@asg017

@asg017 asg017 commented Sep 18, 2026

Copy link
Copy Markdown
Owner
🤖 Claude-generated PR description

Phases 0 and 1 of plans/python/05-roadmap.md (tickets todos/python/0111). Each ticket is one commit, in dependency order.

Phase 0 — stop the bleeding

  • pyo3 0.22 → 0.29, abi3-py311 (89fa6af). Fixes the segfault on CPython 3.14: Filing(path) killed the interpreter with pyo3 0.22, and because the wheel is abi3 it installed on 3.14 without complaint. extension-module dropped (maturin ≥ 1.9.4 sets it), so cargo test -p libfec_parser links again. requires-python = ">=3.11", dead [project.scripts] removed.
  • Dead weight (2935fed): foo.bar() -> 42 scaffold, the phantom root pyproject.toml/uv.lock, crates/fec-py/uv.lock.
  • License (d15e139): MIT OR Apache-2.0 for the whole repo; LICENSE-MIT/LICENSE-APACHE at the root, symlinked into the two pyproject crates so PEP 639 license-files picks them up (verified inside the wheel's METADATA).
  • Fixtures + honest tests (2a30b91): five small real filings committed under crates/fec-py/tests/fixtures/ (271 KB total, .gitignore negation for that dir), one conftest.py, slow/network markers off by default, from_http tests mocked instead of try/except: pass. Suite goes from 66 passed in 2m37s (parsing a gitignored 91 MB file ~25×; 62 skips on any other machine) to 89 passed / 1 skipped in 0.1 s on a fresh clone.
  • CI actually runs pytest (c67be63): test-python.yml builds a release wheel, installs it, runs pytest and a Filing() smoke test on ubuntu/macos/windows × {3.11, 3.14}. Actions SHA-pinned, maturin@1.15.0 pinned. Guards against uv resolving 3.14 to the free-threaded build (where the wheel installs but can't import).

Phase 1 — layout, packaging, first wheels

  • Private _native module (72512eb): python/libfec_parser/{__init__,parser,fecfile}.py over libfec_parser._native; declarative #[pymodule] mod _native { … }; Filing.__module__ == "libfec_parser.parser"; no more sys.modules patching. pyo3 0.29 registers nested modules as attributes, not importable submodules, so the shims bind by attribute.
  • One version number (21f949a): dynamic = ["version"] from Cargo.toml, set to the workspace's 0.0.32; libfec_parser.__version__; full [project] metadata, [project.urls], [dependency-groups] dev, committed uv.lock.
  • Dev loop (cef073d): make develop (maturin develop --uv, ~1.4 s incremental) / test / build / stubs / notebook; no hardcoded wheel filenames; demo*.py deleted (the notebook is the demo).
  • Type stubs (9bb348c): parser.pyi, fecfile.pyi, py.typed; mypy.stubtest + mypy --check-untyped-defs tests clean, run in CI against the installed wheel. Note: Filing()/from_file() don't accept os.PathLike today — the stubs say str; Phase 2 fixes the input path.
  • Notebook in CI (735d88b): examples/quickstart.ipynb reads the committed fixture (download only as a fallback); executed on one CI job; make notebook-check re-records outputs locally.
  • Release wheels (21a4c58): build-python-bindings.yml builds manylinux_2_17 x86_64/aarch64 (native arm runner, maturin-action container — fixes the manylinux_2_34 mistake the CLI wheel makes), macOS x86_64/arm64, Windows x64, plus an sdist; each job installs its own wheel and constructs a Filing before uploading. publish-python-bindings.yml attaches them to the GitHub Release with gh release upload (cargo-dist doesn't attach custom-job artifacts itself). Registered in dist-workspace.toml with a github-custom-job-permissions override for contents: write; release.yml regenerated with dist generate (not hand-edited). Artifact prefix wheels_libfec_parser-* deliberately doesn't match publish-pypi.yml's wheels_libfec-* glob — nothing from crates/fec-py goes to PyPI (decision D1). README gets an alpha banner, release-URL install instructions (3.11+, uv-first), and a known-issues list for the three deferred parser bugs.

What this PR can't prove locally

  • test-python.yml (6 jobs) — this PR is the first run.
  • The release wheel builds. release.yml only runs custom build jobs on a PR when pr-run-mode = "upload" (default is plan-only), so the six wheel artifacts will first appear either on the next tag or after temporarily setting that. Riskiest bits: the Windows smoke step (.venv-smoke + glob under git-bash) and the gh release upload permissions on the publish job — a 403 there means the permissions override didn't take.
  • Free-threaded 3.14t still can't import the wheel (clean SystemError now, not a segfault). Not in scope (decision D8).

Verified locally

Release wheel libfec_parser-0.0.32-cp311-abi3-macosx_11_0_arm64.whl; 89 passed / 1 skipped on CPython 3.11.11 and 3.14.3; python -m mypy.stubtest libfec_parser and mypy tests clean; dist generate --check passes; cargo clippy -p fec-cli and -p libfec_parser clean; cargo test -p libfec_parser links.

🤖 Generated with Claude Code

asg017 and others added 13 commits September 18, 2026 13:04
The downloaded bytes were wrapped in a list before being handed to
loads(), which only accepts str, list[str], or bytes. Pass the response
body through directly.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Rewrite the README around usage instead of build notes, add
examples/quickstart.ipynb with a `make notebook` target, and pass
--no-cache in test-pytest so uv doesn't reuse a stale wheel.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
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.

1 participant