Skip to content

Run CI on this branch and on a free-threaded interpreter, and fix the collection error that exposes - #236

Merged
lelit merged 2 commits into
python-rapidjson:free-threadedfrom
espressolee:ft-ci
Aug 9, 2026
Merged

Run CI on this branch and on a free-threaded interpreter, and fix the collection error that exposes#236
lelit merged 2 commits into
python-rapidjson:free-threadedfrom
espressolee:ft-ci

Conversation

@espressolee

@espressolee espressolee commented Aug 8, 2026

Copy link
Copy Markdown

Follows up on #235, where you wrote:

On the CI: yes, I think it should be added, especially because I do not have (yet?) use cases requiring the FT interpreter.

Two commits, and the second one is there because the first one made it visible.

1. Run CI on this branch, on a free-threaded interpreter

The workflow triggers on master only:

on:
  push:
    branches: [ master ]
  pull_request:
    branches: [ master ]

so nothing on free-threaded — including pull requests into it — has ever been exercised by CI. And no job runs a free-threaded interpreter, so the branch that exists in order to be free-threaded is not tested as one.

This adds free-threaded to both filters and one job running the suite on 3.14t.

The job asserts sys._is_gil_enabled() is False before installing anything. Without that, the job can go green while proving nothing: if the runner ever resolves 3.14t to a GIL-enabled interpreter, every test still passes and the tick would mean "the default build works", which the existing job already covers.

Deliberately minimal — build and pytest only. Doctests and stubtest are left to the existing job rather than duplicated.

2. Guard the free-threading skips so they import on Python < 3.13

Turning CI on immediately produced three red jobs from one cause. Both skip conditions call sys._is_gil_enabled() at module scope, and that attribute only exists on 3.13+:

ERROR collecting tests/test_circular.py
    not sys._is_gil_enabled(),
E   AttributeError: module 'sys' has no attribute '_is_gil_enabled'

pytest aborts during collection, so not a single test runs. This branch's CI pins 3.11, and cibuildwheel runs the suite against every wheel it builds, so the same error took out the test job, the debug job and the macOS wheel job.

getattr(sys, "_is_gil_enabled", lambda: True)() keeps the behaviour identical on 3.13+ and treats older interpreters as GIL-enabled, which they are.

Verified before sending

Both commits were pushed to my fork's free-threaded branch so the workflow actually ran, rather than reasoning about it.

Before the second commitrun: the new free-threaded job passed, and All tests (3.11), Memory leak tests (3.11) and Build wheels arm64/macos-14 all failed with the collection error above.

Afterrun: every job that had failed is green.

job before after
Tests on the free-threaded interpreter (3.14t) did not exist success
All tests, on current Python (3.11) failure success
Memory leak tests, debug build (3.11) failure success
Build wheels, arm64 / macos-13 / windows / ubuntu failure / cancelled success

At the time of writing, the two QEMU-emulated wheel builds (aarch64, ppc64le) were still running — they are slow and CIBW_TEST_SKIP excludes the suite on emulated hardware, so they do not exercise the change. No job has failed.

Not in scope

No change to the fix in #235, and no opinion here on the truncation vs. raise question still open there.


(As on #235: developed with AI assistance. The CI runs linked above are real runs on my fork, and the before/after table is read off them.)

The workflow only triggers on master, so nothing on this branch — including
pull requests into it — has ever been exercised by CI. And no job uses a
free-threaded interpreter, so the branch that exists in order to be
free-threaded is not tested as one.

This adds `free-threaded` to the push and pull_request filters, and one job
that runs the test suite on 3.14t.

The job asserts `sys._is_gil_enabled()` is False before it installs anything.
Without that check the job can go green while proving nothing: if the runner
ever resolves 3.14t to a GIL-enabled interpreter, every test below still
passes, and the tick would mean "the default build works", which the existing
job already covers.

Deliberately minimal — build and pytest only. Doctests and stubtest are left
to the existing job rather than duplicated here.
Both skip conditions call sys._is_gil_enabled() at module scope, and that
attribute only exists on 3.13+. On anything older the call raises
AttributeError during collection, so pytest aborts before running a single
test:

    ERROR collecting tests/test_circular.py
        not sys._is_gil_enabled(),
    E   AttributeError: module 'sys' has no attribute '_is_gil_enabled'

That is not hypothetical on this branch. Its CI pins 3.11, and cibuildwheel
runs the suite against every wheel it builds, so the same error takes out the
test job, the debug job and the macOS wheel job — one cause, three red jobs.
It went unseen because the workflow only triggers on master, so CI has never
run on this branch at all; the previous commit fixes that half.

getattr(..., lambda: True) keeps the behaviour identical on 3.13+ and treats
older interpreters as GIL-enabled, which they are.
@lelit
lelit merged commit 851369b into python-rapidjson:free-threaded Aug 9, 2026
@lelit

lelit commented Aug 9, 2026

Copy link
Copy Markdown
Contributor

Thank you, merged this!

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