Files
F-r-ldraledigplannerare/new-features/fix-deprecations-backend-plan.md
T
2026-09-20 11:37:11 +02:00

4.0 KiB

Fix backend deprecation warnings

Context

uv run pytest on backend/ emits 26 DeprecationWarnings. They are noise in CI output and two of the four sources are real forward-compat debt in our own code — the Starlette 422 constant is already renamed upstream, and Alembic's version_path_separator is superseded. Goal: our code emits zero deprecation warnings.

Confirmed inventory (Python 3.14.0, fastapi 0.136.3, starlette 1.2.1, alembic 1.18.4, slowapi 0.1.9):

Source Count Ours?
HTTP_422_UNPROCESSABLE_ENTITY → use HTTP_422_UNPROCESSABLE_CONTENT 8 yes — 20 call sites
alembic/config.py:612 — No path_separator found in configuration 12 yes — backend/alembic.ini
slowapi/extension.py:717 — asyncio.iscoroutinefunction 6 no — upstream, out of scope

Decision made: fix our code only. No filterwarnings config is added; the slowapi warning stays visible as an upstream reminder.

Baseline: 4 tests already fail on main (test_migration_004_backfill.py::test_flexible_yearly_wish_keeps_the_same_bounding_range_every_year, test_leave_wish_repository.py::…test_flexible_series_keeps_one_bounding_range_per_year_unshifted, two in test_allocation_service.py). These come from the uncommitted in-flight work in app/entities/leave_wish.py / app/services/allocation_service.py and are unrelated to this change. Expected result after the change: still exactly those 4, no more.

Change 1 — rename the 422 constant (20 sites, 15 files)

Mechanical rename, same numeric value (422), so no wire-format or frontend impact:

status.HTTP_422_UNPROCESSABLE_ENTITY  →  status.HTTP_422_UNPROCESSABLE_CONTENT

All sites are in backend/app/routers/. Representative files: workspace.py (3 sites, lines 51/94/223 — inside conditional expressions, not plain raises), settings.py (3), fetch_data.py (2), leave_wishes.py (2), plan.py (2), preschool_planning_days.py (2), plus one each in auth.py, calendar.py, day_overrides.py, planned_day_exclusions.py, planned_days.py, vacation_days.py.

Notes:

  • status is already imported from fastapi in every one of these files — no import changes.
  • status.HTTP_422_UNPROCESSABLE_CONTENT is verified present in the installed starlette (evaluates to 422).
  • No test file references the constant by name (git grep UNPROCESSABLE -- tests is empty), so tests need no update.
  • The warnings attributed to fastapi/routing.py:328 are our handler frames raising through the dependency call — they disappear with this rename too.

Change 2 — Alembic path_separator

backend/alembic.ini currently has:

prepend_sys_path = .
version_path_separator = os

Replace version_path_separator = os with path_separator = os. In Alembic ≥1.16 path_separator governs both prepend_sys_path and version_locations, and its absence is what triggers the legacy-splitting warning. Leave prepend_sys_path = . and the annotated sqlalchemy.url fallback untouched.

Out of scope

  • slowapi's asyncio.iscoroutinefunction warning — upstream, no released fix.
  • typing.Dict in app/utils/holidays.py and datetime.timezone.utc in app/services/auth_service.py — older spellings, but not deprecated and not warning sources.
  • The 4 pre-existing test failures.

Verification

Delegate to a Haiku subagent (per the cost rule); require raw verbatim output, from backend/:

uv run ruff check .
uv run ruff format --check .
uv run pytest
uv run alembic upgrade head        # exercises the alembic.ini change directly

Acceptance criteria:

  1. The warnings summary contains only the 6 slowapi/extension.py:717 lines — no UNPROCESSABLE_ENTITY, no path_separator, count down from 26 to 6.
  2. Failure list is exactly the 4 baseline failures above; pass count unchanged at 860.
  3. Coverage still ≥ the --cov-fail-under=80 gate (no gate changes).
  4. alembic upgrade head completes without the path_separator warning.

Then graphify update ..