Make the declared Python version consistent, and keep it that way #90

Merged
claude-bot merged 1 commit from chore/python-version-consistency into main 2026-08-31 19:53:32 +00:00
Contributor

Closes the two loose ends from #37 / #89.

1. requires-python now matches reality

It said ">=3.12" while CI and the published image only ever exercised 3.14. That was an untested claim — and once #89 moved mypy's target to 3.14, it became an unchecked one too: nothing would catch code that breaks on 3.12.

Narrowed to ">=3.14", so the declaration matches what is actually built, tested and shipped.

The alternative was adding 3.12 to the CI matrix, which would make the wider claim real. I didn't, because it costs a second matrix leg on an already-contended runner for a version nothing runs — but that's the option if you'd rather keep 3.12 support genuine.

2. mypy's python_version now tracks automatically

Three places encode the runtime — the Dockerfile, every setup-python, and this field — and Renovate managed only the first two. So it drifts silently, which is exactly what happened.

"customManagers": [
  {
    "customType": "regex",
    "managerFilePatterns": ["backend/pyproject.toml"],
    "matchStrings": ["python_version\\s*=\\s*\"(?<currentValue>\\d+\\.\\d+)\""],
    "depNameTemplate": "python",
    "datasourceTemplate": "docker",
    "versioningTemplate": "docker"
  }
]

docker/python as datasource matches how the Dockerfile's python:3.14-slim is already tracked, so both move from the same source.

Verification — I did not guess at the schema

A malformed renovate.json breaks dependency management repo-wide, so this was checked rather than assumed:

  • renovate.json validates against the official schema at docs.renovatebot.com/renovate-schema.json (the one this repo's $schema points at).
  • managerFilePatterns is the correct key. I'd flagged uncertainty between it and fileMatch; the schema settles it — 352 occurrences of managerFilePatterns, zero of fileMatch. The older key would have been wrong.
  • The regex matches exactly once in backend/pyproject.toml, captures 3.14, and does not match the requires-python line.
  • The pattern uses JS named-group syntax (?<name>...), because Renovate evaluates regexes in JavaScript. Python's re rejects it — my first test run failed on precisely that, which is a harness quirk, not a config bug.

Backend gate re-run locally after both changes: ruff clean, mypy clean across 61 files, 253 tests passing.

What to watch on the next Renovate run

If the custom manager is wrong in some way the schema can't catch, the visible symptom would be a spurious PR against backend/pyproject.toml proposing an odd version, or no PR at all when the runtime next moves. Worth a glance at the dependency dashboard after Renovate's next cycle — backend/pyproject.toml should start appearing under Detected Dependencies.

Closes the two loose ends from #37 / #89. ## 1. `requires-python` now matches reality It said `">=3.12"` while CI and the published image only ever exercised **3.14**. That was an untested claim — and once #89 moved mypy's target to 3.14, it became an *unchecked* one too: nothing would catch code that breaks on 3.12. Narrowed to `">=3.14"`, so the declaration matches what is actually built, tested and shipped. The alternative was adding 3.12 to the CI matrix, which would make the wider claim real. I didn't, because it costs a second matrix leg on an already-contended runner for a version nothing runs — but that's the option if you'd rather keep 3.12 support genuine. ## 2. mypy's `python_version` now tracks automatically Three places encode the runtime — the Dockerfile, every `setup-python`, and this field — and Renovate managed only the first two. So it drifts silently, which is exactly what happened. ```json "customManagers": [ { "customType": "regex", "managerFilePatterns": ["backend/pyproject.toml"], "matchStrings": ["python_version\\s*=\\s*\"(?<currentValue>\\d+\\.\\d+)\""], "depNameTemplate": "python", "datasourceTemplate": "docker", "versioningTemplate": "docker" } ] ``` `docker`/`python` as datasource matches how the Dockerfile's `python:3.14-slim` is already tracked, so both move from the same source. ## Verification — I did not guess at the schema A malformed `renovate.json` breaks dependency management repo-wide, so this was checked rather than assumed: - **`renovate.json` validates against the official schema** at `docs.renovatebot.com/renovate-schema.json` (the one this repo's `$schema` points at). - **`managerFilePatterns` is the correct key.** I'd flagged uncertainty between it and `fileMatch`; the schema settles it — **352 occurrences of `managerFilePatterns`, zero of `fileMatch`**. The older key would have been wrong. - **The regex matches exactly once** in `backend/pyproject.toml`, captures `3.14`, and does **not** match the `requires-python` line. - **The pattern uses JS named-group syntax** `(?<name>...)`, because Renovate evaluates regexes in JavaScript. Python's `re` rejects it — my first test run failed on precisely that, which is a harness quirk, not a config bug. Backend gate re-run locally after both changes: `ruff` clean, `mypy` clean across 61 files, **253 tests passing**. ## What to watch on the next Renovate run If the custom manager is wrong in some way the schema can't catch, the visible symptom would be a spurious PR against `backend/pyproject.toml` proposing an odd version, or no PR at all when the runtime next moves. Worth a glance at the dependency dashboard after Renovate's next cycle — `backend/pyproject.toml` should start appearing under Detected Dependencies.
Make the declared Python version consistent, and keep it that way
All checks were successful
CI / Alembic migration check (pull_request) Successful in 40s
CI / Python lint & type-check (pull_request) Successful in 1m5s
CI / Frontend lint, test & build (pull_request) Successful in 1m15s
CI / Python tests (pull_request) Successful in 1m53s
CI / Docker build, health smoke & E2E (pull_request) Successful in 1m57s
0f75a6537d
Two halves of the same problem, surfaced by #37 moving the runtime to 3.14.

1. requires-python said ">=3.12" while CI and the published image only ever
   exercised 3.14. That was an untested claim, and once mypy's target moved to
   3.14 it also became an unchecked one -- nothing would catch code that broke
   on 3.12. Narrowed to ">=3.14" so the declaration matches what is actually
   built, tested and shipped. The alternative was adding 3.12 to the CI matrix,
   which would make the wider claim real but costs a second matrix leg for a
   version nothing runs.

2. Added a Renovate customManager so mypy's python_version tracks the runtime
   automatically instead of drifting until someone notices. Three places encode
   the version -- the Dockerfile, every setup-python, and this field -- and
   Renovate managed only the first two.

The custom manager was verified rather than assumed:

  - renovate.json is valid JSON and validates against the official schema at
    docs.renovatebot.com/renovate-schema.json
  - managerFilePatterns is the correct key: that schema mentions it 352 times
    and contains no fileMatch at all, so the older key would have been wrong
  - the regex matches exactly once in backend/pyproject.toml, captures "3.14",
    and does not match the requires-python line
  - the pattern uses JS named-group syntax (?<name>...) because Renovate
    evaluates it in JavaScript, not Python's (?P<name>...)

Backend gate re-run locally after both changes: ruff clean, mypy clean across
61 files, 253 tests passing.

Refs #37.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
claude-bot deleted branch chore/python-version-consistency 2026-08-31 19:53:32 +00:00
Sign in to join this conversation.
No description provided.