feat: require Python >= 3.10 and re-resolve the lockfile - #289
Open
jooyoungseo wants to merge 1 commit into
Open
feat: require Python >= 3.10 and re-resolve the lockfile#289jooyoungseo wants to merge 1 commit into
jooyoungseo wants to merge 1 commit into
Conversation
Python 3.9 reached end-of-life in October 2025, and keeping it in `requires-python` made uv's resolution unsatisfiable: patched `requests` and `urllib3` need Python >= 3.10, while the dev pin `python-semantic-release==9.21.0` requires `requests>=2.25`. Dependabot's grouped security-update run failed on exactly that conflict, so most security alerts could not be fixed automatically. - Raise `requires-python` to `>=3.10` and drop the 3.9 classifier - Drop 3.9 from the CI and release test matrices and from tox's envlist - Update the Python support claims in the Quarto docs - Re-resolve `uv.lock` with `uv lock --upgrade` This is a breaking change to the published Python support matrix: Python 3.9 users can no longer install new releases of `maidr`.
ReviewThis is a clean, well-scoped packaging change — bumping Code quality / correctness
Versioning (the one thing worth a maintainer decision before merge)
Test coverage
Security
Minor
Overall: solid, well-documented change. The only actionable item is nailing down the version-bump type (minor vs. major) before merge so semantic-release does the right thing. |
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.
Pull Request
Description
Dependabot's grouped security-update run has been failing, which is why most of the repository's open security alerts could not be fixed automatically. The root cause is
requires-python = ">=3.9": patchedrequests/urllib3require Python >= 3.10, and the exact dev pinpython-semantic-release==9.21.0requiresrequests>=2.25, so uv cannot find a resolution for thepython_full_version == '3.9.*'split:Python 3.9 reached end-of-life in October 2025. This PR raises the floor to Python 3.10 and re-resolves the lockfile, which unblocks the security upgrades.
Important
This is a breaking change to py-maidr's published Python support matrix. Python 3.9 users can no longer install new releases of
maidr(pip will fall back to the last 3.9-compatible release).Decision: ship this as a minor bump (1.19.1 → 1.20.0). The commit is typed
feat:, which python-semantic-release maps to a minor bump, and that holds under a squash merge too since the squash message comes from this PR'sfeat:title. NoBREAKING CHANGE:footer is intended — if a maintainer later wants 2.0.0 instead, add that footer to the squash body at merge time.Related Issues
Changes Made
pyproject.tomlrequires-python = ">=3.9"→">=3.10"; removed theProgramming Language :: Python :: 3.9classifier.github/workflows/ci.yml["3.9", "3.10", "3.11", "3.12"]→["3.10", "3.11", "3.12"].github/workflows/release.ymluv sync --lockedand would have failed on 3.9 against the newrequires-pythontox.inipy39fromenvlistand the3.9: py39[gh-actions]mappingdocs/_quarto.ymlruntimePlatform:"Python 3.9+"→"Python 3.10+"docs/index.qmduv.lockuv lock --upgradeREADME.mdandCONTRIBUTING.mdwere checked and make no Python-version claims, so they are unchanged. No source code changes.Security impact
Method
The Dependabot alerts API is not reachable from this session, so the alert list could not be read directly. Instead, every
(package, version)pair in the lockfile before and after this change was queried against the OSV database and the results were reduced to distinct GHSA advisories per package — the same unit Dependabot counts. That model reproduces the three reported per-package counts exactly (pillow 19, jupyterlab 6, jupyter-server 2), which is good evidence it matches how the alerts were counted.Before → after
The old lockfile carried 64 distinct GHSA advisories across 15 packages. The new lockfile carries 1.
Every advisory-carrying package except
pytestis now past its fix version, so all open alerts should close except any alert filed againstpytest.On the count: the OSV-derived total of 64 is slightly higher than the 59 open alerts reported. The per-package figures match exactly where they were known, so the gap is most likely advisory-database drift since the alert count was taken (plus any dismissed alerts). Please treat 64 → 1 as the shape of the change rather than an exact alert-by-alert reconciliation.
Critical alert #86 — confirmed fixed ✅
Alert #86 is GHSA-fcw5-x6j4-ccmp, "Jupyter Server: Stored XSS in
NbconvertFileHandler/NbconvertPostHandlervia missingsandboxCSP" (CRITICAL,CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:A/VC:H/VI:H/VA:H/SC:H/SI:H/SA:H).The advisory's fixed version is jupyter-server 2.20.0. The new lockfile pins jupyter-server 2.20.0 (up from 2.18.0), and OSV reports no known vulnerabilities for that version. This alert is fixed by this PR.
The second jupyter-server alert, GHSA-gf7q-q4j7-hp7c (path traversal in
_get_os_path(), Moderate, fixed in 2.18.2), is also resolved.Known remaining exposure
GHSA-6w46-j5rx-g56g — "pytest has vulnerable tmpdir handling" (Moderate, local attack vector, test-only dependency). The fix landed in pytest 9.0.3, but this repo pins
pytest>=7.3.2,<8in both thetestextra and the dev group, so the upgrade is out of reach here. Lifting that pin is a separate change with its own test-compatibility risk, so it is intentionally not bundled into this PR.Relationship to #288
This PR supersedes #288. #288 bumps 7 packages —
bleach,gitpython,idna,mistune,setuptools,soupsieve,tornado— and this lockfile already advances every one of them to the same version or newer (gitpython3.1.57 vs 3.1.54,idna3.18 vs 3.15,mistune3.3.4 vs 3.3.0,soupsieve2.9.1 vs 2.8.4;setuptoolsis dropped from the lock entirely). It also covers the packages #288 could not touch, includingpillow,jupyterlab, andjupyter-server.Either order works, but merging this one and closing #288 is the cleaner path: landing #288 first only creates a
uv.lockconflict that this branch would have to resolve, with no additional coverage. Note that #288 currently reportsmergeable_state: unstablewith a pending status check rather than a fully green run.Verification
Run locally against the new lockfile:
uv lock --check— lockfile in sync withpyproject.toml✅uv sync --locked --all-extras --dev— resolves and installs cleanly on 3.10, 3.11, and 3.12 ✅uv run pytest -vvv— 178 passed on 3.10.20, 3.11.15, and 3.12.3 ✅ruff check --diff— clean ✅CI on this branch is green: Python 3.10 / 3.11 / 3.12 tests,
lint,commit-lint, workflow lint, and all three CodeQL analyses pass. The singleskippedjob isci.yml's duplicate-run guard behaving as designed — internal PRs are covered by the push-event run rather than thepull_requestrun.Scope of the lockfile churn
uv lock --upgradepulled in unrelated transitive bumps alongside the security fixes — notably numpy 2.5.1, pandas 3.0.5, matplotlib 3.11.1 (on newer Pythons), plotly 6.9.0, and notebook 7.6.1. Flagging that explicitly, since it rode along with therequires-pythonchange rather than being requested.This does not change what end users resolve.
uv.lockis not shipped: the wheel ispackages = ["maidr"]and the sdist include list ismaidr/**/*.py,maidr/static/**,README.md,LICENSE,pyproject.toml. So the lockfile governs CI and local dev environments only. No constraint in[project.dependencies]or any extra was touched, sopip install maidrresolves exactly as it did before — the only user-visible change is the Python floor.One behavioral note from the newer pins: the pre-existing
vert:deprecation warning frommaidr/patch/boxplot.pyis now aMatplotlibDeprecationWarningunder matplotlib 3.11 (it was aPendingDeprecationWarningbefore). Non-fatal and unrelated to this change, but it will need addressing before matplotlib 3.13 removes the parameter.Checklist
Additional Notes
The minimum supported Python is now 3.10, matching the floor that
urllib32.7+ and currentrequestsalready impose. Once this lands, Dependabot's grouped security-update run should resolve successfully again and can keep the remaining alerts current on its own.