refactor: add explicit types to asset service functions

- Add typed result dataclasses: IngestResult, AddTagsResult,
  RemoveTagsResult, SetTagsResult, TagUsage
- Add UserMetadata type alias for user_metadata parameters
- Type helper functions with Session parameters
- Use TypedDicts at query layer to avoid circular imports
- Update manager.py and tests to use attribute access

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Luke Mino-Altherr
2026-02-03 20:32:14 -08:00
parent 4695694263
commit 2ddf91c6d9
10 changed files with 184 additions and 125 deletions

View File

@@ -37,6 +37,9 @@ from app.assets.database.queries.cache_state import (
upsert_cache_state,
)
from app.assets.database.queries.tags import (
AddTagsDict,
RemoveTagsDict,
SetTagsDict,
add_missing_tag_for_asset_id,
add_tags_to_asset_info,
bulk_insert_tags_and_meta,
@@ -90,4 +93,7 @@ __all__ = [
"remove_missing_tag_for_asset_id",
"list_tags_with_usage",
"bulk_insert_tags_and_meta",
"AddTagsDict",
"RemoveTagsDict",
"SetTagsDict",
]

View File

@@ -1,4 +1,4 @@
from typing import Iterable, Sequence
from typing import Iterable, Sequence, TypedDict
import sqlalchemy as sa
from sqlalchemy import delete, func, select
@@ -9,6 +9,24 @@ from sqlalchemy.orm import Session
from app.assets.database.models import AssetInfo, AssetInfoMeta, AssetInfoTag, Tag
from app.assets.helpers import escape_sql_like_string, get_utc_now, normalize_tags
class AddTagsDict(TypedDict):
added: list[str]
already_present: list[str]
total_tags: list[str]
class RemoveTagsDict(TypedDict):
removed: list[str]
not_present: list[str]
total_tags: list[str]
class SetTagsDict(TypedDict):
added: list[str]
removed: list[str]
total: list[str]
MAX_BIND_PARAMS = 800
@@ -60,7 +78,7 @@ def set_asset_info_tags(
asset_info_id: str,
tags: Sequence[str],
origin: str = "manual",
) -> dict:
) -> SetTagsDict:
desired = normalize_tags(tags)
current = set(
@@ -96,8 +114,8 @@ def add_tags_to_asset_info(
tags: Sequence[str],
origin: str = "manual",
create_if_missing: bool = True,
asset_info_row = None,
) -> dict:
asset_info_row: AssetInfo | None = None,
) -> AddTagsDict:
if not asset_info_row:
info = session.get(AssetInfo, asset_info_id)
if not info:
@@ -153,7 +171,7 @@ def remove_tags_from_asset_info(
session: Session,
asset_info_id: str,
tags: Sequence[str],
) -> dict:
) -> RemoveTagsDict:
info = session.get(AssetInfo, asset_info_id)
if not info:
raise ValueError(f"AssetInfo {asset_info_id} not found")