diff --git a/new-features/fix-deprecations-backend-plan.md b/new-features/fix-deprecations-backend-plan.md new file mode 100644 index 0000000..d6c8dfb --- /dev/null +++ b/new-features/fix-deprecations-backend-plan.md @@ -0,0 +1,69 @@ +# Fix backend deprecation warnings + +## Context + +`uv run pytest` on `backend/` emits 26 `DeprecationWarning`s. 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: + +```ini +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/`: + +```bash +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 .`.