fix: tombstone releases so sub-3.12 pip install fails loudly - #240
Merged
Conversation
Raising `requires-python` does not retract anything. 2026.7.29.2 was the first release published with `Requires-Python >=3.12`; everything at or below 2026.7.29.1 was published with `>=3.9`, and PyPI metadata is immutable, so those releases stay valid pip candidates forever. On 3.9/3.10/3.11 `pip install autolens` therefore does not fail — it backtracks to 2026.7.29.1 and installs the whole stack silently, no JAX and no warning. The install docs claim a "no matching distribution" error that does not happen. Adds `autohands/tombstone.py`: builds one sdist-only release per package at 2026.7.29.1.post1 with `Requires-Python <3.12`, whose build raises with an explanation naming the user's Python version. It outranks every sub-floor candidate and is invisible at or above the floor, so pip below 3.12 reports why instead of quietly installing stale code. Verified against the real PyPI candidate set with the real artifacts: py3.9/3.10/3.11 pip install autolens -> loud failure, correct version named py3.12 pip install autolens -> 2026.8.17.1, unaffected py3.10 autolens==2026.7.29.1 -> still resolves (pins keep working) The one hole — `--only-binary=:all:` skips sdists and still lands on the old wheel — is documented rather than hidden; no packaging mechanism closes it. One-off publish, deliberately not wired into release.yml: future releases all declare >=3.12, so the tombstone stays the top sub-floor candidate forever. Issue: #238 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The tombstones cannot be published from a laptop — the PyPI tokens live in Actions secrets, and they should stay there. This adds a workflow_dispatch-only job that builds via autohands/tombstone.py and uploads with the same twine version, retry policy and --skip-existing behaviour as release.yml. Deliberately not wired into release.yml: the tombstones are one-off, and republishing a deliberately-broken artifact on every release would be noise. Publishing to the real index requires typing `publish tombstones` as the confirm input. A released filename is permanent — TestPyPI is the rehearsal. Issue: #238 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The tenant firewall flagged `url="https://github.com/PyAutoLabs"` as an instance fact hardcoded in organ code. Removing the field is the right fix rather than allowlisting the file: a tombstone's PyPI page has no use for a homepage link, and its README already carries the whole explanation. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Collaborator
Author
|
CI green on The earlier red on |
This was referenced Aug 19, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes part 1 of #238.
What this fixes
pip install autolenson Python 3.9, 3.10 or 3.11 does not fail — it silentlybacktracks to
2026.7.29.1and installs the whole stack: no JAX, no warning,exit 0, three weeks stale and predating the JAX-default install (PyAutoLens#702).
The install docs claim it "will fail with a no matching distribution error". It
does not.
Reproduced on real interpreters (3.9/3.10/3.11 venvs, pip 26.2.1), not simulated:
pip install autolensThe cause is not a defect in our metadata.
2026.7.29.2was the first releasepublished with
Requires-Python >=3.12; everything at or below2026.7.29.1was published with
>=3.9, and PyPI metadata is immutable, so those releasesremain valid pip candidates forever. Raising a floor never retracts the back
catalogue.
What this adds
autohands/tombstone.py— builds one sdist-only release per package at2026.7.29.1.post1, declaringRequires-Python <3.12, whose build raiseswith an explanation naming the user's actual Python version. It outranks every
sub-floor candidate and is invisible at or above the floor.
.github/workflows/publish_tombstone.yml—workflow_dispatch-onlypublish. The PyPI tokens live in Actions secrets and should stay there; the
real index additionally requires typing
publish tombstonesas confirmation.tests/test_tombstone.py— 15 tests.Deliberately not wired into
release.yml. The tombstones are one-off: everyfuture release declares
>=3.12, so it is invisible below the floor and thetombstone stays the top sub-floor candidate indefinitely. Republishing a
deliberately-broken artifact on each release would be noise.
Verification
Not just unit-tested — the built artifacts were resolved against the real
PyPI candidate set on real interpreters:
pip install autolenspip install autolens2026.8.17.1— unaffected, tombstone never seenautolens==2026.7.29.1--only-binary=:all:That last row is a real limit, documented rather than hidden. Closing it would
mean retracting the back catalogue, and yanking ~330 releases per package is
both semantically wrong and impossible in bulk (PyPI exposes no yank API).
Full suite: 329 passed.
API Changes
None. No PyAuto* library API is touched — this adds a build tool and a manual
workflow to PyAutoHands, and no existing entry point changes behaviour.
There is an outward-facing change once the workflow is run, which is a
separate human act:
pip installof the five packages below Python 3.12 startsfailing with an explanation instead of installing
2026.7.29.1. Resolution at3.12+ is byte-for-byte unchanged, and exact pins of historical releases continue
to resolve on old Pythons.
No
pending-releaselabel: this does not depend on a release, and gating it onone would block the fix. Most PyAutoHands PRs carry no label.
Follow-ups (tracked in #238)
workflow_dispatchonly registers on the default branch.publish_tombstoneagainst testpypi, verify, then pypi with theconfirm phrase.
docs/installation/pip.mdfor PyAutoLens,PyAutoGalaxy and PyAutoFit (they also name the wrong cut release — the real
one is
2026.7.29.2, not2026.4.5.3), and extend PyAutoHeartverify_installCheck B to assert the unpinned sub-3.12 install fails.Heart at ship time:
verdict: stale, score 85, zero red and zero yellowreasons. The single stale reason — "release validation stale: source moved
since rehearsal (PyAutoNerves, PyAutoFit, PyAutoArray, PyAutoGalaxy,
PyAutoLens)" — concerns the five library repos and is unrelated to this change.
🤖 Generated with Claude Code