Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .audit/oberstet_fix_1875.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
- [ ] I did **not** use any AI-assistance tools to help create this pull request.
- [x] I **did** use AI-assistance tools to *help* create this pull request.
- [x] I have read, understood and followed the projects' [AI Policy](https://github.com/crossbario/autobahn-python/blob/main/AI_POLICY.md) when creating code, documentation etc. for this pull request.

Submitted by: @oberstet
Date: 2026-07-01
Related issue(s): #1875
Branch: oberstet:fix_1875
2 changes: 2 additions & 0 deletions docs/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ Changelog

* Add CalVer / PEP 440 version-management ``just`` recipes (``file-version``, ``bump-dev``, ``bump-next``, ``prep-release``) mirroring Crossbar.io, and document the versioning policy in ``CONTRIBUTING.md`` (#1894)
* Add ``ruff check --select ANN,UP,TCH`` (annotation presence, ``pyupgrade`` modern syntax, ``TYPE_CHECKING`` imports) to the ``just check-typing`` recipe so annotation/style regressions are caught in the ``quality-checks`` CI job. The existing gaps in ``src/autobahn/`` are ratcheted via an explicit ``--ignore`` allowlist to be removed module-by-module (#1839); all other ``UP``/``TC`` rules are enforced immediately, and generated code is excluded. The annotation rules are scoped to this recipe via the command line rather than the global ``[tool.ruff.lint]`` select, so the repo-wide ``check-format`` gate is unaffected (#1840)
* Fix the aarch64 CPython 3.14 wheel shipping the free-threaded ABI (``cp314t``) in the GIL ``cp314`` slot (26.6.x). Root cause: manylinux images pre-install both the GIL and free-threaded 3.14 under ``/opt/python`` and prepend them to ``PATH``, and ``uv`` resolved ``cpython-3.14`` to the free-threaded interpreter (first on ``PATH``). The ``create`` recipe now drops free-threaded ``…t/bin`` dirs from ``PATH`` for GIL envs so ``uv`` selects the GIL build. As defence-in-depth, ``just build`` also asserts (via ``_check-venv-abi``) that the interpreter's GIL/free-threaded status matches the env and aborts on mismatch, so a wrong-ABI wheel can never be published. A reserved ``cpy314t`` env spec (``cpython-3.14t``) is added for a future free-threaded wheel variant (#1875)
* Bump the ``.cicd`` (wamp-cicd) submodule to include exact CPython ABI-tag matching in the shared ``check-release-fileset`` release-gate action, so a wrong-ABI wheel (e.g. ``cp314t`` in the ``cp314`` slot) is also rejected at release-fileset validation, not only by the build-time guard above (wamp-cicd #11, completes #1875)

26.6.2
------
Expand Down
40 changes: 39 additions & 1 deletion justfile
Original file line number Diff line number Diff line change
Expand Up @@ -81,13 +81,37 @@ _get-spec short_name:
set -e
case {{short_name}} in
cpy314) echo "cpython-3.14";; # cpython-3.14.0b3-linux-x86_64-gnu
cpy314t) echo "cpython-3.14t";; # CPython 3.14 free-threaded (no-GIL); reserved for #1875 Part 2
cpy313) echo "cpython-3.13";; # cpython-3.13.5-linux-x86_64-gnu
cpy312) echo "cpython-3.12";; # cpython-3.12.11-linux-x86_64-gnu
cpy311) echo "cpython-3.11";; # cpython-3.11.13-linux-x86_64-gnu
pypy311) echo "pypy-3.11";; # pypy-3.11.11-linux-x86_64-gnu
*) echo "Unknown environment: {{short_name}}" >&2; exit 1;;
esac

# Assert the venv interpreter's ABI (GIL vs free-threaded) matches the env name, so a wheel
# is never published with the wrong ABI tag -- e.g. a free-threaded cp314t wheel in the GIL
# cp314 slot, which shipped on aarch64 in 26.6.1 when an older uv resolved `cpython-3.14` to
# the free-threaded interpreter (autobahn #1875 / zlmdb #124). The wheel ABI tag is fixed by
# the building interpreter, so checking the interpreter catches the mismatch at build time.
_check-venv-abi venv:
#!/usr/bin/env bash
set -e
VENV_NAME="{{ venv }}"
VENV_PYTHON=$(just --quiet _get-venv-python "${VENV_NAME}")
case "${VENV_NAME}" in
pypy*) echo "==> ABI check skipped for '${VENV_NAME}' (PyPy)"; exit 0 ;;
*t) EXPECT_FT=1 ;; # e.g. cpy314t -> free-threaded (no-GIL)
*) EXPECT_FT=0 ;; # e.g. cpy314 -> GIL
esac
ACTUAL_FT=$(${VENV_PYTHON} -c "import sysconfig; print(1 if sysconfig.get_config_var('Py_GIL_DISABLED') else 0)")
if [ "${ACTUAL_FT}" != "${EXPECT_FT}" ]; then
echo "ERROR: interpreter ABI mismatch for '${VENV_NAME}': Py_GIL_DISABLED=${ACTUAL_FT}, expected free-threaded=${EXPECT_FT}." >&2
echo " Building would emit a wrong-ABI wheel (e.g. cp314t in the cp314 slot). Aborting." >&2
exit 1
fi
echo "==> ABI check OK: '${VENV_NAME}' interpreter free-threaded=${ACTUAL_FT} (expected ${EXPECT_FT})"

# uv python install pypy-3.11-linux-aarch64-gnu --preview --verbose
# file /home/oberstet/.local/share/uv/python/pypy-3.11.11-linux-aarch64-gnu/bin/pypy3.11
# /home/oberstet/.local/share/uv/python/pypy-3.11.11-linux-aarch64-gnu/bin/pypy3.11: ELF 64-bit LSB executable, ARM aarch64, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-aarch64.so.1, BuildID[sha1]=150f642a07dc36d3e465beaa0109e70da76ca67e, for GNU/Linux 3.7.0, stripped
Expand Down Expand Up @@ -256,9 +280,18 @@ create venv="":
# Get the Python spec just-in-time
PYTHON_SPEC=$(just --quiet _get-spec "${VENV_NAME}")

# For a GIL env, drop free-threaded CPython dirs (…t/bin, e.g. cp314t) that
# manylinux images pre-install on PATH ahead of the GIL build, so uv does not
# resolve e.g. cpy314 to a free-threaded cp314t interpreter (#1875). The dedicated
# cpy314t env is used to build free-threaded wheels. No-op off manylinux.
CREATE_PATH="${PATH}"
if [[ "${VENV_NAME}" != *t ]]; then
CREATE_PATH="$(printf '%s' "${PATH}" | tr ':' '\n' | grep -vE '/opt/python/[^/]*t/bin$' | paste -sd: -)"
fi

echo "==> Creating Python virtual environment '${VENV_NAME}' using ${PYTHON_SPEC} in ${VENV_PATH}..."
mkdir -p "{{ VENV_DIR }}"
uv venv --seed --python "${PYTHON_SPEC}" "${VENV_PATH}"
PATH="${CREATE_PATH}" uv venv --seed --python "${PYTHON_SPEC}" "${VENV_PATH}"
echo "==> Successfully created venv '${VENV_NAME}'."
else
echo "==> Python virtual environment '${VENV_NAME}' already exists in ${VENV_PATH}."
Expand Down Expand Up @@ -1673,6 +1706,11 @@ build venv="": (install-build-tools venv)
fi
VENV_PATH="{{ VENV_DIR }}/${VENV_NAME}"
VENV_PYTHON=$(just --quiet _get-venv-python "${VENV_NAME}")

# Fail fast if the interpreter ABI doesn't match the env (autobahn #1875 / zlmdb #124):
# prevents publishing e.g. a free-threaded cp314t wheel in the GIL cp314 slot.
just _check-venv-abi "${VENV_NAME}"

echo "==> Building wheel package..."

# Build the wheel with NVX acceleration
Expand Down
Loading