refactor(capture): the unit's tables move into downloads/models

The nine Capture tables (files, jobs, folders, shares, links, quota, cookies, profiles, library
resume points) leave app/models.py for the unit's own module; app.tables registers every unit's
tables for the migrations, the test database and the ownership check. No schema change.
This commit is contained in:
2026-10-18 23:45:53 +02:00
parent d66174ed16
commit 3a688fa0f5
48 changed files with 469 additions and 429 deletions
+1 -1
View File
@@ -25,7 +25,7 @@ from fastapi.testclient import TestClient
from sqlalchemy import create_engine, event, text
from starlette.requests import HTTPConnection
import app.models # register every model on Base.metadata
import app.tables # every table on Base.metadata
import app.state as app_state
from app import apitokens, security
from app.auth import current_user
+2 -10
View File
@@ -25,16 +25,8 @@ from app.config import settings
from app.db import SessionLocal, get_db
from app.main import app
from app.notifications import create_notification
from app.models import (
ApiToken,
ApiTokenGrant,
AuditLog,
DownloadJob,
FileFolder,
MediaAsset,
Notification,
User,
)
from app.models import ApiToken, ApiTokenGrant, AuditLog, Notification, User
from app.downloads.models import DownloadJob, FileFolder, MediaAsset
from app.ratelimit import RateLimiter
from app.routes import tokens as tokens_routes
from app.routes.auth import bump_session_epoch
+2 -1
View File
@@ -18,7 +18,8 @@ from app.downloads import errors as dlerrors
from app.downloads import formats, pipeline, quota, runner, service
from app.downloads import probe as probemod
from app.downloads.edit import INPUT_GUARD
from app.models import Channel, DownloadJob, MediaAsset, PlexItem, PlexLibrary, PlexShow, Video
from app.models import Channel, PlexItem, PlexLibrary, PlexShow, Video
from app.downloads.models import DownloadJob, MediaAsset
from app.plex import paths as plex_paths
# --- the spec -----------------------------------------------------------------------------------
+2 -1
View File
@@ -18,7 +18,8 @@ from cryptography.fernet import Fernet
from app import security
from app.downloads import credentials, formats, service
from app.models import DownloadCredential, DownloadJob, MediaAsset, User
from app.models import User
from app.downloads.models import DownloadCredential, DownloadJob, MediaAsset
@pytest.fixture(autouse=True)
@@ -24,7 +24,8 @@ from app import security
from app.config import settings
from app.db import engine
from app.downloads import credentials, formats, pipeline, service
from app.models import DownloadJob, DownloadQuota, MediaAsset, User
from app.models import User
from app.downloads.models import DownloadJob, DownloadQuota, MediaAsset
from app.worker import _process_job
_REEL = "https://www.facebook.com/reel/1736360027626346/?fs=e&fs=e"
+2 -1
View File
@@ -18,7 +18,8 @@ from sqlalchemy import select
from app.apitokens import FilesCaller
from app.db import SessionLocal
from app.downloads import service
from app.models import DownloadJob, MediaAsset, User
from app.models import User
from app.downloads.models import DownloadJob, MediaAsset
from app.routes.downloads import cancel_download, pause_download
from app.routes.files import delete_file, own_job_for_update
+2 -1
View File
@@ -13,7 +13,8 @@ its OWN session, so every test COMMITS its setup before calling it.
from app.config import settings
from app.downloads import errors as dlerrors
from app.downloads import formats, pipeline, quota
from app.models import DownloadJob, DownloadQuota, MediaAsset, User
from app.models import User
from app.downloads.models import DownloadJob, DownloadQuota, MediaAsset
from app.worker import _claim_job
+2 -1
View File
@@ -13,7 +13,8 @@ DB lane (`db` fixture) — skipped without Postgres.
from sqlalchemy import select, text
from app.downloads import service
from app.models import DownloadJob, MediaAsset, User
from app.models import User
from app.downloads.models import DownloadJob, MediaAsset
def _user(db, email="ref@example.com"):
+2 -1
View File
@@ -4,7 +4,8 @@ you") — the only place the title lived, so a Hungarian reader got the English.
from sqlalchemy import select
from app.models import DownloadJob, MediaAsset, Notification
from app.models import Notification
from app.downloads.models import DownloadJob, MediaAsset
def test_a_share_notice_carries_the_title_and_the_sharer(db, make_user, as_user):
+2 -1
View File
@@ -8,7 +8,8 @@ behaviour-equivalently. DB lane (`db` fixture) — skipped without Postgres.
from sqlalchemy import text
from app.models import DownloadJob, MediaAsset, User
from app.models import User
from app.downloads.models import DownloadJob, MediaAsset
def _seed(db, *, job_status, asset_status="ready", ref_count=1, rel_path=None):
+2 -1
View File
@@ -11,7 +11,8 @@ from sqlalchemy import text
from app.downloads import service
from app.downloads.status import JobStatus
from app.models import DownloadJob, User
from app.models import User
from app.downloads.models import DownloadJob
def _running_job(db) -> DownloadJob:
+1 -1
View File
@@ -13,7 +13,7 @@ from app.config import settings
from app.downloads import errors as dlerrors
from app.downloads import pipeline, quota, service
from app.downloads import upload as uploadmod
from app.models import DownloadJob, DownloadQuota, MediaAsset
from app.downloads.models import DownloadJob, DownloadQuota, MediaAsset
pytestmark = pytest.mark.skipif(shutil.which("ffmpeg") is None, reason="ffmpeg not available")
+1 -1
View File
@@ -20,7 +20,7 @@ import yt_dlp
from app import logs, sysconfig, worker
from app.downloads import pipeline
from app.downloads.stated import StatedFailure
from app.models import DownloadJob, MediaAsset
from app.downloads.models import DownloadJob, MediaAsset
from app.plex import stream as plex_stream
+2 -1
View File
@@ -17,7 +17,8 @@ from app.downloads import folders, formats, service
from app.downloads import gc as gcmod
from app.db import SessionLocal
from app.downloads.status import JobStatus
from app.models import DownloadJob, FileFolder, MediaAsset, Notification
from app.models import Notification
from app.downloads.models import DownloadJob, FileFolder, MediaAsset
NOW = datetime.now(timezone.utc)
+2 -1
View File
@@ -18,7 +18,8 @@ from app.config import settings
from app.downloads import folders, service
from app.downloads import upload as uploadmod
from app.downloads.status import JobStatus
from app.models import AuditLog, DownloadJob, DownloadShare, FileFolder, MediaAsset
from app.models import AuditLog
from app.downloads.models import DownloadJob, DownloadShare, FileFolder, MediaAsset
NOW = datetime.now(timezone.utc)
+1 -1
View File
@@ -11,7 +11,7 @@ from sqlalchemy import select
from app.config import settings
from app.downloads import folders, preview, service
from app.downloads.status import JobStatus
from app.models import DownloadJob, DownloadShare, MediaAsset
from app.downloads.models import DownloadJob, DownloadShare, MediaAsset
from app.routes.files import TRUNCATED_HEADER
+3 -2
View File
@@ -18,7 +18,8 @@ from app.config import settings
from app.db import engine
from app.downloads import folders, og
from app.downloads import probe as probemod
from app.models import AuditLog, DownloadJob, DownloadLink, FileFolder, MediaAsset
from app.models import AuditLog
from app.downloads.models import DownloadJob, DownloadLink, FileFolder, MediaAsset
_VIDEO = {
"streams": [
@@ -317,7 +318,7 @@ def test_a_password_file_link_says_it_opens_a_file(shelf, client):
def test_a_file_whose_bytes_are_gone_is_not_offered(shelf, client, db):
from pathlib import Path
from app.models import MediaAsset
from app.downloads.models import MediaAsset
token = _link(shelf)["token"]
gone = shelf["inside"][0]
+1 -1
View File
@@ -9,7 +9,7 @@ cannot reach, is ever read or written. DB-backed (real Postgres).
import pytest
from sqlalchemy import select
from app.models import DownloadJob, DownloadShare, LibraryState, MediaAsset
from app.downloads.models import DownloadJob, DownloadShare, LibraryState, MediaAsset
from app.routes._common import ProgressIn, kept_position
+2 -1
View File
@@ -18,7 +18,8 @@ from app import security
from app.config import settings
from app.db import engine
from app.downloads import probe as probemod
from app.models import AuditLog, DownloadLink
from app.models import AuditLog
from app.downloads.models import DownloadLink
_VIDEO = {
"streams": [
+1 -1
View File
@@ -7,7 +7,7 @@ the shared one, so every other owner check kept the English. Needs the DB.
"""
from app.auth import require_write_scope
from app.models import DownloadJob, MediaAsset
from app.downloads.models import DownloadJob, MediaAsset
def test_a_gone_view_tag_or_pin_says_what_is_gone(db, make_user, as_user):
+1 -1
View File
@@ -17,7 +17,7 @@ import pytest
from app.config import settings
from app.downloads import pipeline, playable, probe, service, storage
from app.downloads import upload as uploadmod
from app.models import DownloadJob, MediaAsset
from app.downloads.models import DownloadJob, MediaAsset
pytestmark = pytest.mark.skipif(shutil.which("ffmpeg") is None, reason="ffmpeg not available")
+1 -1
View File
@@ -17,7 +17,7 @@ import pytest
from app.config import settings
from app.downloads import pipeline, playable, probe
from app.models import DownloadJob, MediaAsset
from app.downloads.models import DownloadJob, MediaAsset
APP = Path(__file__).resolve().parents[1] / "app"
+2 -1
View File
@@ -17,7 +17,8 @@ still not reach into a unit's tables.
import ast
from pathlib import Path
from app.models import Base
import app.tables # noqa: F401 — every unit's tables, for the ownership check
from app.db import Base
APP = Path(__file__).parent.parent / "app"
ROUTES = APP / "routes"
+2 -1
View File
@@ -33,7 +33,8 @@ from app.downloads import mediakind, pipeline, playable, quota, service, storage
from app.downloads import probe as probemod
from app.downloads import upload as uploadmod
from app.downloads.stated import StatedFailure
from app.models import DISPLAY_TEXT_MAX, DownloadJob, DownloadQuota, MediaAsset
from app.models import DISPLAY_TEXT_MAX
from app.downloads.models import DownloadJob, DownloadQuota, MediaAsset
# --- pure: the kind invariant ---------------------------------------------------------------
+2 -1
View File
@@ -21,7 +21,8 @@ from app.downloads import pipeline, quota, storage
from app.downloads import probe as probemod
from app.downloads import upload as uploadmod
from app.downloads.stated import StatedFailure
from app.models import DownloadJob, DownloadQuota, MediaAsset, Notification
from app.models import Notification
from app.downloads.models import DownloadJob, DownloadQuota, MediaAsset
from sqlalchemy import select, update
from sqlalchemy.exc import OperationalError
from sqlalchemy.orm import Session
+1 -1
View File
@@ -12,7 +12,7 @@ from app.config import settings
from app.downloads import pipeline, runner, service, storage
from app.downloads import probe as probemod
from app.downloads import upload as uploadmod
from app.models import DownloadJob, MediaAsset
from app.downloads.models import DownloadJob, MediaAsset
@pytest.mark.parametrize(