Backend: track the runtime with mypy's python_version (3.14) #89

Merged
claude-bot merged 1 commit from chore/mypy-target-tracks-runtime into main 2026-08-31 19:25:39 +00:00
Contributor

Follow-up to #37, which moved the runtime to Python 3.14.

The drift

#37 bumped both Dockerfile stages and all four setup-python references (three in ci.yml, one in audit.yml) from 3.12 to 3.14. But backend/pyproject.toml still had:

[tool.mypy]
python_version = "3.12"

Renovate does not manage that field, so it drifts silently. mypy was applying 3.12 semantics to code that only ever runs on 3.14 — it would not flag anything the older interpreter couldn't do, and nothing would ever have told us.

Verification

All run locally before pushing:

mypy app/               Success: no issues found in 61 source files
ruff check .            All checks passed!
ruff format --check .   91 files already formatted
pytest -q               253 passed

I also checked the target before changing the config, via mypy --python-version 3.14, so the bump was known-clean rather than hopeful.

What I deliberately did not change

requires-python still reads ">=3.12", while CI and the published image only ever exercise 3.14.

Now that mypy targets 3.14, it will not catch code that breaks on 3.12 — a latent trap if anyone actually runs 3.12. The two honest resolutions are:

  • narrow requires-python to ">=3.14", matching what we actually test and ship; or
  • add 3.12 to the CI matrix, making the declared support real.

Either is a scope decision beyond aligning the type-check target, so it is flagged here rather than taken unilaterally. Worth settling before v1.0.0, since requires-python is a published claim about what the package supports.

On making this track automatically

The underlying problem is that three places encode the runtime and Renovate only manages two of them. A Renovate customManagers regex rule could keep python_version in step, which would make it track for good rather than needing this PR again at 3.15. I have not added one because a malformed renovate.json breaks dependency management repo-wide, and I would be guessing at the current schema (fileMatch vs managerFilePatterns moved between Renovate versions). Happy to add it if you want, verified against your Renovate version first.

Follow-up to #37, which moved the runtime to Python 3.14. ## The drift #37 bumped **both Dockerfile stages** and **all four `setup-python` references** (three in `ci.yml`, one in `audit.yml`) from 3.12 to 3.14. But `backend/pyproject.toml` still had: ```toml [tool.mypy] python_version = "3.12" ``` Renovate does not manage that field, so it drifts silently. mypy was applying **3.12 semantics to code that only ever runs on 3.14** — it would not flag anything the older interpreter couldn't do, and nothing would ever have told us. ## Verification All run locally before pushing: ``` mypy app/ Success: no issues found in 61 source files ruff check . All checks passed! ruff format --check . 91 files already formatted pytest -q 253 passed ``` I also checked the target *before* changing the config, via `mypy --python-version 3.14`, so the bump was known-clean rather than hopeful. ## What I deliberately did not change `requires-python` still reads `">=3.12"`, while CI and the published image only ever exercise 3.14. Now that mypy targets 3.14, it **will not catch code that breaks on 3.12** — a latent trap if anyone actually runs 3.12. The two honest resolutions are: - narrow `requires-python` to `">=3.14"`, matching what we actually test and ship; or - add 3.12 to the CI matrix, making the declared support real. Either is a scope decision beyond aligning the type-check target, so it is flagged here rather than taken unilaterally. Worth settling before v1.0.0, since `requires-python` is a published claim about what the package supports. ## On making this track automatically The underlying problem is that three places encode the runtime and Renovate only manages two of them. A Renovate `customManagers` regex rule could keep `python_version` in step, which would make it track for good rather than needing this PR again at 3.15. I have not added one because a malformed `renovate.json` breaks dependency management repo-wide, and I would be guessing at the current schema (`fileMatch` vs `managerFilePatterns` moved between Renovate versions). Happy to add it if you want, verified against your Renovate version first.
Backend: track the runtime with mypy's python_version (3.14)
All checks were successful
CI / Alembic migration check (pull_request) Successful in 33s
CI / Frontend lint, test & build (pull_request) Successful in 1m8s
CI / Python tests (pull_request) Successful in 1m48s
CI / Python lint & type-check (pull_request) Successful in 2m34s
CI / Docker build, health smoke & E2E (pull_request) Successful in 2m0s
a85c83dd58
#37 moved the runtime to Python 3.14 -- both Dockerfile stages and all four
setup-python references -- but mypy's target stayed at 3.12. Renovate does not
manage that field, so it drifts silently: mypy was applying 3.12 semantics to
code that only ever runs on 3.14, and would not have flagged anything the older
interpreter could not do.

Verified locally: mypy passes clean at 3.14 across 61 source files, ruff and
ruff format are unchanged, and the 253-test suite still passes.

Note on requires-python, deliberately left alone: it still reads ">=3.12" while
CI and the image only ever exercise 3.14. mypy now targets 3.14, so it will no
longer catch code that would break on 3.12 -- a latent trap if anyone actually
runs 3.12. The honest options are to narrow requires-python to ">=3.14" (we test
and ship only that) or to start testing 3.12 in CI. That is a scope decision
beyond aligning the type-check target, so it is flagged rather than taken here.

Refs #37.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
claude-bot deleted branch chore/mypy-target-tracks-runtime 2026-08-31 19:25:39 +00:00
Sign in to join this conversation.
No description provided.