Skip to content

Cover CPython 3.14 and the sub-interpreter backend in CI - #296

Merged
seanwevans merged 1 commit into
claude/festive-johnson-fd03cl-subinterpreter-backendfrom
claude/festive-johnson-fd03cl-ci-freethreaded
Sep 17, 2026
Merged

seanwevans merged 1 commit into
claude/festive-johnson-fd03cl-subinterpreter-backendfrom
claude/festive-johnson-fd03cl-ci-freethreaded

Conversation

@seanwevans

Copy link
Copy Markdown
Owner

Fifth and last of the series. Stacked on #295 (base is that branch, so the diff here is only the CI change); merge that one first.

The gap

The sub-interpreter backend needs CPython 3.14+, and nothing in the matrix ran it:

  • tests-unit stops at 3.13;
  • the only free-threaded job is 3.13t, which cannot create a cell at all.

So the whole backend from #295 would land with its tests skipping everywhere in CI.

What this adds

  • 3.14 in the unit matrix (both runners).
  • A sub-interpreter cells / py3.14t job running the backend suite plus test_supervisor.py and test_nogil.py on a free-threaded build.
  • The 3.14 trove classifier in pyproject.toml.

The guard step is the point

- name: Verify this build actually has sub-interpreters
  run: |
    python - <<'PY'
    import sys
    from pyisolate.runtime import subinterpreter as s
    assert s.is_available(), f"no concurrent.interpreters on {sys.version}"
    assert not sys._is_gil_enabled(), "expected a free-threaded build"
    print("ok:", sys.version)
    PY

Every sub-interpreter test skips itself when the build cannot run it. That is right for the 3.11–3.13 matrix, but it means a runner that silently resolved to an older Python would skip everything and report this job green having tested nothing. Failing loudly is the difference between a job that covers the backend and a job that looks like it does.

Dependency installation follows the existing 3.13t job: install without the runtime deps that may not have free-threaded wheels, then re-add the pure-Python ones the import path needs. Nothing in this job's scope needs real crypto, and tests/conftest.py's stub covers it.

Testing

I ran every step of the new job locally against a free-threaded 3.14 build with only pytest pyyaml platformdirs installed — i.e. the exact dependency shape the job creates:

  • guard step: ok: 3.14.0rc2 free-threading build
  • guard step on 3.13, to confirm it fails rather than passing vacuously: AssertionError: no concurrent.interpreters on 3.13.12
  • tests/test_subinterpreter_backend.py + tests/test_supervisor.py: 77 passed, 2 skipped
  • tests/test_nogil.py: 16 passed

The workflow YAML is parsed and the job structure asserted, so the heredoc quoting is not taken on trust.

3.13 full suite: 544 passed, 43 skipped, plus the usual environmental test_apply_confinement_installs_seccomp_and_allows_normal_syscalls failure that reproduces on unmodified main. pre-commit run --all-files passes.

Caveat

I cannot verify from here that actions/setup-python offers 3.14t on ubuntu-24.04. If it does not, the guard step fails loudly rather than skipping quietly, which is the intended failure mode — but it may need a setup-python version bump or astral-sh/setup-uv on the first run.

🤖 Generated with Claude Code

https://claude.ai/code/session_01Fs1hTtmF4Hm9h617AG9Gse


Generated by Claude Code

The sub-interpreter backend needs 3.14+, and nothing in the matrix ran it:
unit tests stopped at 3.13 and the only free-threaded job was 3.13t, which
cannot create a cell at all.

Add 3.14 to the unit matrix, and a `sub-interpreter cells / py3.14t` job that
runs the backend suite on a free-threaded build.

That job asserts up front that the interpreter really is a free-threaded 3.14
before running any tests. Every sub-interpreter test skips itself when the
build cannot run it -- which is correct for the 3.11-3.13 matrix, but it means
a runner that silently resolved to an older Python would skip everything and
report the job green having tested nothing. Failing loudly is the difference
between a job that covers the backend and a job that looks like it does.

Dependency installation follows the existing 3.13t job: install without the
runtime deps that may not have free-threaded wheels, then re-add the
pure-Python ones the import path needs. Nothing in this job's scope needs real
crypto, and the suite's stub covers it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Fs1hTtmF4Hm9h617AG9Gse
@seanwevans
seanwevans merged commit b43fce7 into claude/festive-johnson-fd03cl-subinterpreter-backend Sep 17, 2026
10 of 22 checks passed
@seanwevans
seanwevans deleted the claude/festive-johnson-fd03cl-ci-freethreaded branch September 17, 2026 01:19
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