"""plex person TMDB bio columns (E5 S6) Additive TMDB-sourced person fields on plex_people — biography, birth/death dates, place of birth, known-for department, also-known-as, and a `known_for` credit pool ([{tmdb_id, media_type, title}] resolved to library rows by guid at serve time) — plus a `tmdb_enriched_at` watermark. Filled the first time a person page is opened (from /person/{tmdb_person_id}), then SERVED FROM THE ROW. The `tmdb_person_id` link itself already exists (0071). ADD-only, all nullable → no table rewrite, no ACCESS EXCLUSIVE lock. `tmdb_enriched_at` starts NULL, so every person is enriched once on first view. """ from typing import Sequence, Union import sqlalchemy as sa from alembic import op from sqlalchemy.dialects import postgresql revision: str = "0072_plex_person_bio" down_revision: Union[str, None] = "0071_plex_tmdb_fields" branch_labels: Union[str, Sequence[str], None] = None depends_on: Union[str, Sequence[str], None] = None _COLS: tuple[tuple[str, sa.types.TypeEngine], ...] = ( ("biography", sa.Text()), ("birthday", sa.String(length=10)), ("deathday", sa.String(length=10)), ("place_of_birth", sa.Text()), ("known_for_department", sa.String(length=64)), ("also_known_as", postgresql.JSONB()), ("known_for", postgresql.JSONB()), ("tmdb_enriched_at", sa.DateTime(timezone=True)), ) def upgrade() -> None: for name, type_ in _COLS: op.add_column("plex_people", sa.Column(name, type_, nullable=True)) def downgrade() -> None: for name, _ in reversed(_COLS): op.drop_column("plex_people", name)