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:
statusis already imported fromfastapiin every one of these files — no import changes.status.HTTP_422_UNPROCESSABLE_CONTENTis verified present in the installed starlette (evaluates to422).- No test file references the constant by name (
git grep UNPROCESSABLE -- testsis empty), so tests need no update. - The warnings attributed to
fastapi/routing.py:328are 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.iscoroutinefunctionwarning — upstream, no released fix. typing.Dictinapp/utils/holidays.pyanddatetime.timezone.utcinapp/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:
- The warnings summary contains only the 6
slowapi/extension.py:717lines — noUNPROCESSABLE_ENTITY, nopath_separator, count down from 26 to 6. - Failure list is exactly the 4 baseline failures above; pass count unchanged at 860.
- Coverage still ≥ the
--cov-fail-under=80gate (no gate changes). alembic upgrade headcompletes without thepath_separatorwarning.
Then graphify update ..