chore(python): prepare the bindings for wheel distribution #321

Merged
jqueuniet merged 2 commits from chore/python-packaging into main 2026-09-04 23:02:50 +02:00
Owner

Makes the Python bindings distributable as wheels. They worked from a checkout,
but the package version had drifted from the workspace, the wheel carried the
wrong tag and no license files, and nothing in CI touched them.

What's in it

  • Version and floor. pyproject.toml said 0.1.1 against a 0.2.0 workspace,
    so the wheel's pip metadata disagreed with the cdylib it bundles, and the
    suite's assertion was pinned to the stale literal and failed. Both sides now
    derive from the manifests. requires-python moves to >=3.11: 3.9 is EOL,
    3.10 nearly so, and one test could not even be imported below 3.11 for want
    of a __future__ import.
  • Wheel tag. infer_tag stamped the building interpreter's ABI, demanding
    a wheel per Python minor. Nothing links the CPython C API — the cdylib is
    reached through ctypes — so the tag is now py3-none-<platform>. The hook
    also wipes its staging directory, which previously let a cross-built wheel
    ship a second, wrong-platform library.
  • Metadata. Classifiers, keywords, project URLs, and copies of the two
    licenses (PEP 639 globs cannot reach outside the package directory, so CI
    diffs the copies against the originals).
  • No sdist. An sdist of bindings/python alone cannot build, since the
    cdylib it compiles lives in the workspace above it.
  • CI gains a python job that installs the package on a standalone 3.11
    and runs its suite.
  • Release becomes two build jobs feeding a publish job through Forgejo's
    upload-artifact: manylinux and Windows wheels attached alongside the CLI
    archives, SHA256SUMS covering them too, and nothing published unless every
    build succeeded.

Verification

One manylinux wheel was installed into 3.11, 3.12 and 3.14 and ran a byte-exact
save round-trip on each, which is the point of the tag change. Both wheel builds
were exercised in their real container images, as was the publish job's
tooling and changelog extraction. cargo fmt, cargo test --workspace and
cargo doc pass locally.

macOS and aarch64 Linux wheels are not built (no runner, no SDK); with no sdist
to fall back on, those platforms install from a checkout.

Makes the Python bindings distributable as wheels. They worked from a checkout, but the package version had drifted from the workspace, the wheel carried the wrong tag and no license files, and nothing in CI touched them. ## What's in it - **Version and floor.** `pyproject.toml` said 0.1.1 against a 0.2.0 workspace, so the wheel's pip metadata disagreed with the cdylib it bundles, and the suite's assertion was pinned to the stale literal and failed. Both sides now derive from the manifests. `requires-python` moves to `>=3.11`: 3.9 is EOL, 3.10 nearly so, and one test could not even be imported below 3.11 for want of a `__future__` import. - **Wheel tag.** `infer_tag` stamped the building interpreter's ABI, demanding a wheel per Python minor. Nothing links the CPython C API — the cdylib is reached through ctypes — so the tag is now `py3-none-<platform>`. The hook also wipes its staging directory, which previously let a cross-built wheel ship a second, wrong-platform library. - **Metadata.** Classifiers, keywords, project URLs, and copies of the two licenses (PEP 639 globs cannot reach outside the package directory, so CI diffs the copies against the originals). - **No sdist.** An sdist of `bindings/python` alone cannot build, since the cdylib it compiles lives in the workspace above it. - **CI** gains a `python` job that installs the package on a standalone 3.11 and runs its suite. - **Release** becomes two build jobs feeding a `publish` job through Forgejo's `upload-artifact`: manylinux and Windows wheels attached alongside the CLI archives, `SHA256SUMS` covering them too, and nothing published unless every build succeeded. ## Verification One manylinux wheel was installed into 3.11, 3.12 and 3.14 and ran a byte-exact save round-trip on each, which is the point of the tag change. Both wheel builds were exercised in their real container images, as was the `publish` job's tooling and changelog extraction. `cargo fmt`, `cargo test --workspace` and `cargo doc` pass locally. macOS and aarch64 Linux wheels are not built (no runner, no SDK); with no sdist to fall back on, those platforms install from a checkout.
The Python bindings worked from a checkout but were not distributable: the
package version had drifted, the wheel carried the wrong tag and no license
files, and nothing in CI touched them at all.

Version and floor. `pyproject.toml` still said 0.1.1 against a 0.2.0
workspace, so the wheel's pip metadata disagreed with the cdylib it bundles;
the suite's assertion was pinned to the stale literal and failed. Both sides
now derive from the manifests. `requires-python` moves to >=3.11 — 3.9 is EOL
and 3.10 nearly so, the floor was never exercised, and one test could not even
be imported below 3.11 for want of a `__future__` import.

Wheel tag. `infer_tag` stamped the building interpreter's ABI, which would
demand a wheel per Python minor. Nothing links the CPython C API — the cdylib
is reached through ctypes — so the tag is now py3-none-<platform> and one file
per platform serves every supported interpreter. The hook also wipes its
staging directory, which previously let a cross-built wheel ship a second,
wrong-platform library, and reads DM2_FFI_PREBUILT/DM2_WHEEL_PLATFORM so a
cross-build can supply its own payload and tag.

Metadata. Adds classifiers, keywords, project URLs and copies of the two
licenses; PEP 639 globs cannot reach outside the package directory, so CI
diffs the copies against the originals.

No sdist is published: an sdist of bindings/python alone cannot build, since
the cdylib it compiles lives in the workspace above it.

CI gains a `python` job that installs the package on a standalone 3.11 and
runs its suite, exercising the declared floor and the cdylib-bundling hook.

The release workflow becomes two build jobs feeding a `publish` job through
Forgejo's upload-artifact: manylinux and Windows wheels are attached alongside
the CLI archives, SHA256SUMS covers them too, and nothing is published unless
every build succeeded. A dispatch run leaves the assets downloadable without
cutting a release.
chore(ide): map the GitHub Workflow schema onto the Forgejo workflows
All checks were successful
CI / msrv (1.90) (pull_request) Successful in 49s
CI / stable (pull_request) Successful in 1m19s
CI / python bindings (3.11) (pull_request) Successful in 34s
CI / msrv (1.90) (push) Successful in 49s
CI / audit (pull_request) Successful in 21s
CI / audit (push) Successful in 20s
CI / stable (push) Successful in 1m18s
CI / python bindings (3.11) (push) Successful in 33s
aa6af87478
Forgejo Actions workflows are GitHub-Actions-compatible YAML, but they live
in .forgejo/workflows/, which the IDE does not associate with the workflow
schema on its own. Point the schemastore GitHub Workflow schema at ci.yml and
release.yml so both get completion and validation.
jqueuniet deleted branch chore/python-packaging 2026-09-04 23:02:50 +02:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
jqueuniet/dm2-tools!321
No description provided.