generated from john/python-template
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:
co-authored by
Copilot App
parent
67feeb28af
commit
8a30231adf
@@ -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"
|
||||||
|
|||||||
@@ -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.")
|
||||||
|
|||||||
@@ -283,6 +283,9 @@ 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"):
|
||||||
|
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")
|
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(
|
||||||
|
|||||||
@@ -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
@@ -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)]
|
||||||
|
|||||||
Reference in New Issue
Block a user