"""media_assets.media_kind (E7 S5a: the video|audio|file discriminator for the media library) Adds a stored media-kind to each asset so the library can gate its actions on it (play/edit for media, download-only for a generic uploaded file) instead of re-deriving from codecs in prose. The column is the single home of the invariant `downloads.mediakind.derive` computes at finalize. Backfill for existing rows: a stored video codec -> 'video', an audio-only codec -> 'audio', an editor derivative (source_kind='edit', which carries no codecs but is always a video clip) -> 'video'. Rows still pending/errored (no codecs, not an edit) stay NULL — kind is set when they finalize. Empty `media_kind` never reaches the UI: only `ready`/`done` rows render actions, and those are all backfilled here. """ from typing import Sequence, Union import sqlalchemy as sa from alembic import op revision: str = "0076_media_asset_kind" down_revision: Union[str, None] = "0075_playlist_sync_baseline" branch_labels: Union[str, Sequence[str], None] = None depends_on: Union[str, Sequence[str], None] = None def upgrade() -> None: op.add_column("media_assets", sa.Column("media_kind", sa.String(length=16), nullable=True)) op.execute( """ UPDATE media_assets SET media_kind = CASE WHEN vcodec IS NOT NULL THEN 'video' WHEN acodec IS NOT NULL THEN 'audio' WHEN source_kind = 'edit' THEN 'video' ELSE NULL END """ ) def downgrade() -> None: op.drop_column("media_assets", "media_kind")