Repository navigation
Avoid .abi3t extension suffixes on Python 3.13t and 3.14t - #5363
Conversation
jameshilliard
left a comment
There was a problem hiding this comment.
The version-specific fallback looks correct. I reproduced the original import failure on 3.14t without this guard, then verified the PR with 79 passing tests (2 skipped) across test_build_ext.py and test_bdist_wheel.py on 3.14t, plus 48 focused tests on 3.15t.
There is one integration detail with #5362: its cross-build filename assertion currently expects .abi3t.so for a 3.14t target. When these changes are combined, that expectation needs to use the target EXT_SUFFIX instead. The version-specific fallback here is the correct behavior.
Two inline suggestions below: a fix for the Cygwin test failure and an optional simplification of the guard.
| with ZipFile(wheel_path) as archive: | ||
| archive.extractall(installed) |
There was a problem hiding this comment.
ZipFile.extractall() does not restore the executable permissions recorded in the wheel, which Cygwin needs to load the extension DLL. Both parameterizations are failing with ImportError: Permission denied in the Cygwin job.
Could this use unpack_zipfile from setuptools.archive_util instead? That existing helper preserves permissions. We made the same change in #5362. With that import added, this block becomes:
| with ZipFile(wheel_path) as archive: | |
| archive.extractall(installed) | |
| unpack_zipfile(wheel_path, installed) |
| abi = '.abi3' | ||
| if get_config_var('Py_GIL_DISABLED'): | ||
| # The 3.13t and 3.14t loaders cannot import .abi3t files. | ||
| if suffix.startswith(('.cpython-313t', '.cpython-314t')): | ||
| return None | ||
| abi = '.abi3t' |
There was a problem hiding this comment.
Optional simplification: the t in these target suffixes already identifies the free-threaded builds we need to exclude, so this could be another early return alongside the existing unsupported-platform checks. That preserves the existing ABI-selection expression and avoids the extra nesting:
| abi = '.abi3' | |
| if get_config_var('Py_GIL_DISABLED'): | |
| # The 3.13t and 3.14t loaders cannot import .abi3t files. | |
| if suffix.startswith(('.cpython-313t', '.cpython-314t')): | |
| return None | |
| abi = '.abi3t' | |
| # The 3.13t and 3.14t loaders cannot import .abi3t files. | |
| if suffix.startswith(('.cpython-313t', '.cpython-314t')): | |
| return None | |
| abi = '.abi3t' if get_config_var('Py_GIL_DISABLED') else '.abi3' |
I also checked this form against the extension tests and the limited-/version-specific wheel tests on 3.14t and 3.15t: 48 passed on each.
|
Applied suggestions from @jameshilliard and I made a comment on #5362 with a suggestion for the tests there to resolve conflicts with this PR. |
|
I think the pypy test failure is unrelated but please let me know if you want me to take a closer look. |
Note that the old behavior did at least result in useable extensions, though -- |
I think it was harmless before because they are importable. Unfortunately the |
|
The previous #5363 addresses that regression by using the normal version-specific extension suffix on 3.13t and 3.14t instead of Could you confirm whether building with this PR resolves the issue? The added regression test builds and imports the extension with |
|
Building with |
The nightly backend tests failed at collection on Linux and macOS: https://github.com/rotki/rotki/actions/runs/40451047174/job/122013590635 OSError: Cannot load native module 'Crypto.Util._cpuid_c': Not found '_cpuid_c.cpython-314t-x86_64-linux-gnu.so', Not found '_cpuid_c.abi3.so', Not found '_cpuid_c.so' On Python 3.14t pycryptodome and pycryptodomex only have abi3 wheels, which uv will not use, so they are built from the sdist with an unpinned setuptools. The 1 week exclude-newer cooldown resolved that build environment to setuptools 84.2.0, which names free-threaded limited-API extensions `.abi3t.so`. The pycryptodome loader does not look for that suffix. setuptools 84.2.1 (pypa/setuptools#5363) goes back to the regular `.cpython-314t-*.so` name. Pin setuptools to 84.2.1 for every build environment with build-constraint-dependencies, and use the same version for the rotkehlchen build backend and the docs and packaging groups so they agree. The exclude-newer-package entry only exists to let 84.2.1 through the cooldown window. Checked with `uv sync --locked` on Linux x86_64, Python 3.14.4 free-threaded. macOS, Windows, the docs build and the packaged binaries are left to CI.
Summary of changes
Just before the 84.2.0 release #5193 and #5352 were merged. As a consequence of #5352 and the new capability in #5193, setuptools began naming
py_limited_api=Trueextensions.abi3t.soon Python 3.13t and 3.14t. Those interpreters cannot import that suffix: on 3.14t,import probefails for a version-specific wheel containingprobe.abi3t.so.Use the interpreter-specific extension suffix instead, such as
probe.cpython-314t-darwin.so, so these builds remain importable without claiming stable-ABI support. This also fixes the old behavior, which incorrectly labeled these as.abi3.soextensions.Pull Request Checklist
newsfragments/