refactor(api): Pydantic request models for small route modules (R6 S1b)

payload:dict → typed request models across the single/double-endpoint modules:
- tags: TagCreateIn / TagUpdateIn (color:null clears → reads model_fields_set);
  _own_tag now delegates to owned_or_404.
- config: ConfigSetIn(value:Any) — keeps the "Missing 'value'" 400 via model_fields_set.
- me: SwitchAccountIn(user_id:int).
- scheduler: JobIntervalIn / MaintenanceSettingsIn — the manual int()+400 becomes a
  clean 422 on a non-number; the range checks stay 400.
- search: ClearSearchIn(video_ids:list[str]).
- public: WatchUnlockIn(password:str).

Gate: ruff clean, pytest 164 green.
This commit is contained in:
2026-07-26 04:51:25 +02:00
parent d982e8b9ae
commit a622470a28
6 changed files with 75 additions and 34 deletions
+7 -2
View File
@@ -16,6 +16,7 @@ from concurrent.futures import ThreadPoolExecutor
from datetime import datetime, timezone
from fastapi import APIRouter, Depends, HTTPException
from pydantic import BaseModel
from sqlalchemy import and_, delete, func, or_, select, update
from sqlalchemy.dialects.postgresql import insert as pg_insert
from sqlalchemy.orm import Session, aliased
@@ -323,9 +324,13 @@ def search_youtube(
}
class ClearSearchIn(BaseModel):
video_ids: list[str] = []
@router.post("/clear")
def clear_search(
payload: dict,
body: ClearSearchIn,
user: User = Depends(require_human),
db: Session = Depends(get_db),
) -> dict:
@@ -333,7 +338,7 @@ def clear_search(
for them, then hard-delete the now-orphaned ones — a via_search video nobody KEPT (no watch
state, not playlisted, channel not subscribed) and that no other user still has as a search
find. Kept videos and organically-owned ones are left untouched."""
ids = [str(v) for v in (payload.get("video_ids") or [])]
ids = body.video_ids
if not ids:
return {"removed": 0}
db.execute(