Skip to content

ci(python-wheels): publish free-threaded cp314t wheels and an sdist - #501

Merged
domenkozar merged 1 commit into
cachix:mainfrom
Finc3:ci/python-freethreaded-wheels
Oct 22, 2026
Merged

domenkozar merged 1 commit into
cachix:mainfrom
Finc3:ci/python-freethreaded-wheels

Conversation

@MaxDaten

Copy link
Copy Markdown
Contributor

Problem

The Python SDK can't be installed on free-threaded CPython. PyPI only has cp39-abi3 wheels and no sdist, and free-threaded interpreters can't load abi3 extensions:

$ uv run -p python3.14t --with secretspec python -c 'import secretspec'
× No solution found when resolving `--with` dependencies:
  Because all versions of secretspec have no wheels with a free-threading
  compatible ABI tag ...
hint: You require free-threaded CPython 3.14 (`cp314t`), but we only found
wheels for `secretspec` (v0.21.1) with the following Python ABI tag: `abi3`

Change

Only .github/workflows/python-wheels.yml changes. The abi3 wheels stay as they are.

  • linux: adds python3.14t entries for x86_64 and aarch64 (manylinux 2_28, which ships cp314-cp314t), built with --interpreter python3.14t.
  • native: adds macOS aarch64 and Windows x86_64 entries. setup-python installs 3.14t, and maturin gets that exact interpreter path from the step output.
  • sdist: a new job using maturin sdist, so any interpreter without a matching wheel can still build from source.
  • publish: now also waits for sdist.

No crate or binding change is needed. Built against a free-threaded interpreter, pyo3 drops abi3-py39 and produces a version-specific extension. Since pyo3 0.28, a bare #[pymodule] declares free-threading support, so with pyo3 0.29 importing the module leaves the GIL disabled.

Verification (local, macOS arm64, CPython 3.14.7t)

From the v0.21.1 tag:

$ uv run -p python3.14t --with 'secretspec @ git+…@v0.21.1#subdirectory=secretspec-py' python -c …
GIL enabled before import: False
GIL enabled after import:  False
native module: secretspec/_native.cpython-314t-darwin.so

From the sdist (maturin sdist). It bundles secretspec, secretspec-ipc and secretspec-py, then installs on 3.14t:

GIL enabled after import: False
native module: _native.cpython-314t-darwin.so

actionlint passes on the workflow.

Not verified locally: the CI matrix itself. In particular, whether maturin finds python3.14t by name inside the manylinux container will only show on the first run of this PR.

One judgement call: the binding has not been audited for free-threading. That said, secretspec-py/src/lib.rs holds no static, Mutex or RefCell state. If you'd rather opt out until an audit, #[pymodule(gil_used = true)] would keep the GIL on, and the wheels would still install.

@MaxDaten

Copy link
Copy Markdown
Contributor Author

I ran the changed workflow on the fork branch (workflow_dispatch, so publish was skipped): https://github.com/Finc3/secretspec/actions/runs/39679461729

All 9 build jobs pass. The free-threaded jobs produce real cp314t wheels, including inside the manylinux container, which was the one open question:

secretspec-0.21.1-cp314-cp314t-macosx_11_0_arm64.whl
secretspec-0.21.1-cp314-cp314t-manylinux_2_28_aarch64.whl
secretspec-0.21.1-cp314-cp314t-manylinux_2_28_x86_64.whl
secretspec-0.21.1-cp314-cp314t-win_amd64.whl
secretspec-0.21.1-cp39-abi3-macosx_11_0_arm64.whl
secretspec-0.21.1-cp39-abi3-manylinux_2_28_aarch64.whl
secretspec-0.21.1-cp39-abi3-manylinux_2_28_x86_64.whl
secretspec-0.21.1-cp39-abi3-win_amd64.whl
secretspec-0.21.1.tar.gz

I installed the CI-built macOS cp314t wheel on CPython 3.14.7t: import secretspec works and sys._is_gil_enabled() stays False.

@domenkozar
domenkozar merged commit 77728d9 into cachix:main Oct 22, 2026
23 checks passed
@MaxDaten
MaxDaten deleted the ci/python-freethreaded-wheels branch October 22, 2026 14:04
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.

2 participants