Drop Python 3.9, add Python 3.14 - #720
Conversation
CI signal: Python 3.14 exposes a latent archive-hashing bug (not caused by this diff)The Root cause: Python 3.14 ships zlib-ng in some builds ( Implication beyond the test: archive hashes (epub, h5p, HTML zips) drive Studio dedup. On a zlib-ng interpreter the same content produces a different hash. Scope decision needed. A fix means either compression-independent hashing (e.g.
|
rtibbles
left a comment
There was a problem hiding this comment.
The predictable zipping is pinned not just in Python code in ricecooker but also in Javascript in Studio. This cannot be changed, and we must use regular zlib not zlib-ng, unless zlib-ng can be compelled to produce byte identical output under a specific mode. The current hashes are the acceptance test, and no other outcome will be satisfactory.
|
Checked whether zlib-ng can be compelled to match. It cannot. Evidence. On zlib-ng 2.2.5 vs zlib 1.3.1, I swept every knob CPython's So reference zlib is the only implementation that can produce the pinned hashes. What changed (6733c3d):
Every other 3.14 job builds against reference zlib. The full suite also passes locally on a 3.14 build with stock zlib 1.3.2, so the hashes are stable across zlib versions — just not across implementations. Consequence to flag: this drops Windows support at 3.14 and above, since every official CPython Windows build from 3.14 on links zlib-ng. Restoring it would mean ricecooker shipping its own reference-zlib DEFLATE encoder. |
6733c3d to
d88460d
Compare
|
Rebased onto The only conflict was in Full matrix green, including @rtibblesbot's comments are generated by an LLM, and should be evaluated accordingly |
4cbe37c to
24380db
Compare
Raise the supported floor to 3.10 and the ceiling to 3.14 across packaging metadata, CI, the runtime guard, and user-facing docs. Also remove a dead Python 2/3 shim in thumbscropping.py. - pyproject.toml: requires-python ">=3.10, <3.15"; classifiers 3.10-3.14 - pythontest.yml: matrix ['3.10'..'3.14'] - ricecooker/__init__.py: guard rejects < (3, 10, 0) - utils/thumbscropping.py: drop PY2/PY3 branch, inline str checks - docs/installation.md, CONTRIBUTING.md: name 3.10-3.14 Closes learningequality#719 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
zlib-ng emits different DEFLATE bytes than reference zlib for the same input, so archives built on such an interpreter get different MD5s. Those hashes are pinned here and in Studio's JavaScript and are already in use for deduplication, so they cannot change. No zlib-ng configuration reproduces reference zlib output (checked levels 0-9 and -1 x 5 strategies x memLevel 1-9), so detect it and refuse rather than silently emit unmatchable archives. CPython 3.14 on Windows links zlib-ng, so drop that combination from the CI matrix and the install docs. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Left over from the 3.9 floor. Inert with the current rule set (E, F, W, C90, I) and produces no formatting change, but stale in a change that drops 3.9. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
zlib.ZLIBNG_VERSION only exists from CPython 3.14 onwards, so a 3.10-3.13 interpreter linked against zlib-ng passed the guard and would have emitted archives whose MD5s cannot match the pinned hashes. zlib-ng's zlib-compat mode reports its version as "1.3.1.zlib-ng", which reaches us through ZLIB_RUNTIME_VERSION on every Python version; check that too. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
24380db to
d475523
Compare
|
Rebased onto Locally on 3.14 (reference zlib): 525 passed, 12 skipped; No new review feedback outstanding — the zlib-ng question is answered in #720 (comment). @rtibblesbot's comments are generated by an LLM, and should be evaluated accordingly |
Summary
Python 3.9 reached end-of-life in October 2025 and Python 3.14 is a supported release the project did not test. This raises the supported range to 3.10–3.14 across packaging metadata, the CI matrix, the runtime version guard, ruff's
target-version, and the install/contributor docs, and removes a dead Python 2/3 compatibility shim inthumbscropping.pythat only ever took its Python 3 branch.Testing 3.14 surfaced a blocker: CPython 3.14 on Windows links zlib-ng, whose DEFLATE output differs from reference zlib, so
create_predictable_zipwould emit archives that miss the MD5s Studio has pinned.ricecooker.utils.zipnow detects zlib-ng — viazlib.ZLIBNG_VERSIONwhere available, falling back toZLIB_RUNTIME_VERSIONon older interpreters — and raises rather than producing unmatchable hashes.References
Closes #719.
Reviewer guidance
windows-latest, 3.14is excluded from the matrix: that build links zlib-ng, whose DEFLATE bytes cannot reproduce the pinned archive hashes. Windows is therefore supported up to 3.13, anddocs/installation.mdsays so..github/workflows/pythontest.yml:67— the macOSpython@3.13unlink/link steps are untouched. Check the 3.14 job's "link 3.13" branch is acceptable.AI usage
Used Claude Code to apply the pre-approved plan. Verified with the full test suite, the thumbnail regression tests, and prek/ruff.
@rtibblesbot's comments are generated by an LLM, and should be evaluated accordingly
How was this generated?
Deviations from the issue spec
windows-latest, 3.14— that interpreter links zlib-ng and cannot reproduce the predictable-zip hashes Studio has pinned, so the AC "CI matrix runs 3.10–3.14" holds on Linux and macOS only.ricecooker/utils/zip.pyplus its tests, and the Windows note indocs/installation.md— not in the issue, but shipping 3.14 without it would let chefs silently produce archives Studio rejects.target-versiontopy310alongsiderequires-python; inert under the current rule set, but leaving it atpy39would misstate the floor.🟡 Waiting for feedback
Last updated: 2026-07-26 19:22 UTC