refactor: R12 S3 — invert scheduler->routes, publish cross-module privates

Layering cleanup, no behaviour change (ruff clean backend+scripts, pytest 193):

- Invert the scheduler->routes dependency: reset_demo_state (+ its demo-seed
  helpers) move from routes/admin.py to a new service module app/demo.py.
  Both routes/admin.py and scheduler.py now import it from app.demo, so the
  scheduler no longer reaches into the routes layer — its lazy import (the
  routes<->scheduler cycle workaround) is gone, hoisted to a top-level import.

- Publish the private symbols that were imported across module boundaries (the
  underscore convention was lying): feed._serialize -> serialize,
  feed._to_tsquery_str -> to_tsquery_str, videos._insert_stubs -> insert_stubs,
  videos._stub_from_playlist_item -> stub_from_playlist_item,
  worker._uploader_url -> uploader_url, plex._shared._item_or_404 ->
  item_or_404. Scoped renames — the 5 other route modules keep their own truly
  private _serialize helpers.

- _release_asset moves from routes/downloads.py to app/downloads/service.py as
  the public release_asset (asset bookkeeping is a service concern); the routes
  call it via service.release_asset.
This commit is contained in:
2026-08-11 22:58:10 +02:00
parent ac6383e92c
commit 51463b226e
16 changed files with 153 additions and 148 deletions
+4 -4
View File
@@ -32,8 +32,8 @@ from app.plex import sync as plex_sync
from app.plex.client import PlexClient, PlexError, PlexNotConfigured
from app.routes._common import owned_or_404
from app.routes.admin import admin_user
from app.routes.feed import _to_tsquery_str
from app.routes.plex._shared import _item_or_404
from app.routes.feed import to_tsquery_str
from app.routes.plex._shared import item_or_404
router = APIRouter(prefix="/api/plex", tags=["plex"])
@@ -258,7 +258,7 @@ def unified_library(
want_movies = scope in ("movie", "both") and bool(movie_lib_ids)
want_shows = scope in ("show", "both") and bool(show_lib_ids)
ts = _to_tsquery_str(q) if q else None
ts = to_tsquery_str(q) if q else None
tsq = func.to_tsquery(_TS_CONFIG, ts) if ts else None
selects = []
@@ -1561,7 +1561,7 @@ def item_detail(
) -> dict:
"""Everything the player needs: metadata, cast, intro/credit markers (from Plex), episode
prev/next, and the per-user resume position + watch status."""
it = _item_or_404(db, rating_key)
it = item_or_404(db, rating_key)
st = db.query(PlexState).filter_by(user_id=user.id, item_id=it.id).first()
rich: dict = {}