Triage high-value ty diagnostics
Quality Gate / gate (push) Failing after 47s

Apply the highest-value typing fixes from the ty baseline pass:
- align migration row typing with SQLAlchemy RowMapping sequences
- accept refreshable callback return type in homepage gallery
- guard nullable media URL before ui.image in people photos
- guard nullable source MIME type before startswith checks
- fix tests/test_db collect() return annotation to match 4-tuple

This clears all actionable ty findings from that set and leaves only
known SQLModel/SQLAlchemy descriptor false positives.

Co-authored-by: Copilot App <[email protected]>
This commit is contained in:
Jim Lancaster
2026-08-23 16:54:34 -05:00
co-authored by Copilot App
parent 67feeb28af
commit 8a30231adf
5 changed files with 21 additions and 8 deletions
+7 -4
View File
@@ -3,6 +3,7 @@ from __future__ import annotations
import base64 import base64
import json import json
import shutil import shutil
from collections.abc import Sequence
from dataclasses import dataclass from dataclasses import dataclass
from datetime import UTC from datetime import UTC
from datetime import date from datetime import date
@@ -18,6 +19,7 @@ from sqlalchemy import Table
from sqlalchemy import create_engine from sqlalchemy import create_engine
from sqlalchemy import inspect as sqlalchemy_inspect from sqlalchemy import inspect as sqlalchemy_inspect
from sqlalchemy import select from sqlalchemy import select
from sqlalchemy.engine import RowMapping
from sqlalchemy.engine import make_url from sqlalchemy.engine import make_url
from sqlmodel import SQLModel from sqlmodel import SQLModel
@@ -69,7 +71,7 @@ def export_bundle(*, source_db_url: str, source_upload_dir: Path, bundle_dir: Pa
} }
engine = create_engine(source_db_url) engine = create_engine(source_db_url)
legacy_portrait_rows: list[dict[str, Any]] = [] legacy_portrait_rows: Sequence[RowMapping] = ()
try: # noqa: PLR1702 try: # noqa: PLR1702
inspector = sqlalchemy_inspect(engine) inspector = sqlalchemy_inspect(engine)
source_tables = set(inspector.get_table_names()) source_tables = set(inspector.get_table_names())
@@ -195,9 +197,10 @@ def default_sync_db_url(settings: Settings | None = None) -> str:
return get_database_url(runtime_settings).replace("+aiosqlite", "").replace("+asyncpg", "").replace("+psycopg", "") return get_database_url(runtime_settings).replace("+aiosqlite", "").replace("+asyncpg", "").replace("+psycopg", "")
def _serialize_row(row: dict[str, Any], *, table_name: str, source_upload_dir: Path) -> dict[str, Any]: def _serialize_row(row: RowMapping, *, table_name: str, source_upload_dir: Path) -> dict[str, Any]:
serialized: dict[str, Any] = {} serialized: dict[str, Any] = {}
for key, value in row.items(): for raw_key, value in row.items():
key = str(raw_key)
serialized_value = _serialize_value(value) serialized_value = _serialize_value(value)
if table_name == "source" and key == "file_path" and isinstance(serialized_value, str): if table_name == "source" and key == "file_path" and isinstance(serialized_value, str):
serialized[key] = _canonical_media_relative_path( serialized[key] = _canonical_media_relative_path(
@@ -315,7 +318,7 @@ def _prepare_photo_payload_and_uploads( # noqa: PLR0915
*, *,
payload: dict[str, Any], payload: dict[str, Any],
uploads_bundle_dir: Path, uploads_bundle_dir: Path,
legacy_portrait_rows: list[dict[str, Any]], legacy_portrait_rows: Sequence[RowMapping],
) -> None: ) -> None:
photo_rows = payload.setdefault("tables", {}).setdefault("photo", []) photo_rows = payload.setdefault("tables", {}).setdefault("photo", [])
photos_dir = uploads_bundle_dir / "photos" photos_dir = uploads_bundle_dir / "photos"
+1 -1
View File
@@ -43,7 +43,7 @@ def _render_homepage_gallery(
base_url: str, base_url: str,
enable_rotation: bool = False, enable_rotation: bool = False,
rotate_enabled: list[bool] | None = None, rotate_enabled: list[bool] | None = None,
on_change: Callable[[], None] | None = None, on_change: Callable[[], object] | None = None,
) -> None: ) -> None:
if not photos: if not photos:
render_empty_state("No homepage image uploaded yet.") render_empty_state("No homepage image uploaded yet.")
+4 -1
View File
@@ -283,7 +283,10 @@ def register_page() -> None: # noqa: PLR0915
base_url=str(request.base_url), base_url=str(request.base_url),
) )
with ui.element("div").classes("relative w-full"): with ui.element("div").classes("relative w-full"):
ui.image(photo_url).classes("w-full rounded-md") if photo_url is None:
ui.label("Image unavailable").classes("w-full text-sm ui-text-muted p-2")
else:
ui.image(photo_url).classes("w-full rounded-md")
description_text = photo.description or "No description" description_text = photo.description or "No description"
ui.label(description_text).classes( ui.label(description_text).classes(
"absolute inset-x-0 bottom-0 text-center text-white text-xs font-semibold " "absolute inset-x-0 bottom-0 text-center text-white text-xs font-semibold "
+1 -1
View File
@@ -407,7 +407,7 @@ def _render_source_metadata_column(
def _resolve_source_detail_layout(*, source: Source, settings: Settings) -> str: def _resolve_source_detail_layout(*, source: Source, settings: Settings) -> str:
media_type = lookup_source_mime_type(source.file_path) media_type = lookup_source_mime_type(source.file_path)
if not media_type.startswith("image/"): if media_type is None or not media_type.startswith("image/"):
return "standard" return "standard"
absolute = (settings.upload_dir / Path(source.file_path)).resolve() absolute = (settings.upload_dir / Path(source.file_path)).resolve()
dimensions = _read_image_dimensions(absolute) dimensions = _read_image_dimensions(absolute)
+8 -1
View File
@@ -141,7 +141,14 @@ async def test_create_all_declares_hot_path_indexes(tmp_path):
await create_all(engine=runtime.engine) await create_all(engine=runtime.engine)
async with runtime.engine.connect() as connection: async with runtime.engine.connect() as connection:
def collect(sync_connection) -> tuple[dict[str, list[list[str]]], list[list[str]]]: def collect(
sync_connection,
) -> tuple[
dict[str, list[list[str]]],
list[list[str]],
list[list[str]],
list[list[str]],
]:
database = inspect(sync_connection) database = inspect(sync_connection)
indexes = { indexes = {
table: [index["column_names"] for index in database.get_indexes(table)] table: [index["column_names"] for index in database.get_indexes(table)]