temp commit

This commit is contained in:
Justin Visser 2026-02-26 12:54:19 +01:00
parent 8760f27b51
commit 0e9e49df16
193 changed files with 23228 additions and 935 deletions

View file

@ -1,5 +1,6 @@
from __future__ import annotations
from datetime import datetime, timezone
import logging
from typing import Literal
@ -62,7 +63,6 @@ def _serialize_publication_item(item) -> dict[str, object]:
"citation_count": item.citation_count,
"venue_text": item.venue_text,
"pub_url": item.pub_url,
"doi": item.doi,
"display_identifier": _serialize_display_identifier(item.display_identifier),
"pdf_url": item.pdf_url,
"pdf_status": item.pdf_status,
@ -94,23 +94,27 @@ async def _publication_counts(
user_id: int,
selected_scholar_id: int | None,
favorite_only: bool,
snapshot_before: datetime | None,
) -> tuple[int, int, int, int]:
unread_count = await publication_service.count_unread_for_user(
db_session,
user_id=user_id,
scholar_profile_id=selected_scholar_id,
favorite_only=favorite_only,
snapshot_before=snapshot_before,
)
favorites_count = await publication_service.count_favorite_for_user(
db_session,
user_id=user_id,
scholar_profile_id=selected_scholar_id,
snapshot_before=snapshot_before,
)
latest_count = await publication_service.count_latest_for_user(
db_session,
user_id=user_id,
scholar_profile_id=selected_scholar_id,
favorite_only=favorite_only,
snapshot_before=snapshot_before,
)
total_count = await publication_service.count_for_user(
db_session,
@ -118,6 +122,7 @@ async def _publication_counts(
mode=publication_service.MODE_ALL,
scholar_profile_id=selected_scholar_id,
favorite_only=favorite_only,
snapshot_before=snapshot_before,
)
return unread_count, favorites_count, latest_count, total_count
@ -129,8 +134,12 @@ async def _list_publications_for_request(
mode: Literal["all", "unread", "latest", "new"] | None,
favorite_only: bool,
scholar_profile_id: int | None,
search: str | None,
sort_by: str,
sort_dir: str,
limit: int,
offset: int,
snapshot_before: datetime | None,
) -> tuple[str, int | None, list]:
resolved_mode = publication_service.resolve_publication_view_mode(mode)
selected_scholar_id = scholar_profile_id
@ -145,8 +154,12 @@ async def _list_publications_for_request(
mode=resolved_mode,
scholar_profile_id=selected_scholar_id,
favorite_only=favorite_only,
search=search,
sort_by=sort_by,
sort_dir=sort_dir,
limit=limit,
offset=offset,
snapshot_before=snapshot_before,
)
await publication_service.schedule_missing_pdf_enrichment_for_user(
db_session,
@ -162,6 +175,27 @@ async def _list_publications_for_request(
return resolved_mode, selected_scholar_id, hydrated
def _resolve_publications_snapshot(
*,
snapshot: str | None,
) -> tuple[datetime, str]:
if snapshot is None:
now_utc = datetime.now(timezone.utc)
return now_utc, now_utc.isoformat()
try:
parsed = datetime.fromisoformat(snapshot)
except ValueError as exc:
raise ApiException(
status_code=400,
code="invalid_snapshot",
message="Invalid publications snapshot cursor.",
) from exc
if parsed.tzinfo is None:
parsed = parsed.replace(tzinfo=timezone.utc)
normalized = parsed.astimezone(timezone.utc)
return normalized, normalized.isoformat()
def _resolve_publications_paging(
*,
page: int,
@ -188,6 +222,7 @@ def _publications_list_data(
page: int,
page_size: int,
offset: int,
snapshot: str,
) -> dict[str, object]:
return {
"mode": mode,
@ -200,6 +235,7 @@ def _publications_list_data(
"total_count": total_count,
"page": int(page),
"page_size": int(page_size),
"snapshot": snapshot,
"has_prev": int(offset) > 0,
"has_next": int(offset) + int(page_size) < int(total_count),
"publications": [_serialize_publication_item(item) for item in publications],
@ -322,7 +358,6 @@ def _log_retry_pdf_result(
"queued": queued,
"resolved_pdf": resolved_pdf,
"pdf_status": pdf_status,
"has_doi": bool(doi),
},
)
@ -336,10 +371,14 @@ async def list_publications(
mode: Literal["all", "unread", "latest", "new"] | None = Query(default=None),
favorite_only: bool = Query(default=False),
scholar_profile_id: int | None = Query(default=None, ge=1),
search: str | None = Query(default=None, min_length=1, max_length=200),
sort_by: Literal["first_seen", "title", "year", "citations", "scholar"] = Query(default="first_seen"),
sort_dir: Literal["asc", "desc"] = Query(default="desc"),
page: int = Query(default=1, ge=1),
page_size: int = Query(default=100, ge=1, le=500),
limit: int | None = Query(default=None, ge=1, le=1000),
offset: int | None = Query(default=None, ge=0),
snapshot: str | None = Query(default=None, min_length=1, max_length=64),
db_session: AsyncSession = Depends(get_db_session),
current_user: User = Depends(get_api_current_user),
):
@ -349,20 +388,27 @@ async def list_publications(
limit=limit,
offset=offset,
)
snapshot_before, snapshot_cursor = _resolve_publications_snapshot(snapshot=snapshot)
normalized_search = (search or "").strip() or None
resolved_mode, selected_scholar_id, publications = await _list_publications_for_request(
db_session,
current_user=current_user,
mode=mode,
favorite_only=favorite_only,
scholar_profile_id=scholar_profile_id,
search=normalized_search,
sort_by=sort_by,
sort_dir=sort_dir,
limit=resolved_limit,
offset=resolved_offset,
snapshot_before=snapshot_before,
)
unread_count, favorites_count, latest_count, total_count = await _publication_counts(
db_session,
user_id=current_user.id,
selected_scholar_id=selected_scholar_id,
favorite_only=favorite_only,
snapshot_before=snapshot_before,
)
data = _publications_list_data(
mode=resolved_mode,
@ -376,6 +422,7 @@ async def list_publications(
page=resolved_page,
page_size=resolved_limit,
offset=resolved_offset,
snapshot=snapshot_cursor,
)
return success_payload(request, data=data)
@ -480,7 +527,7 @@ async def retry_publication_pdf(
queued=queued,
resolved_pdf=resolved_pdf,
pdf_status=current.pdf_status,
doi=current.doi,
doi=None,
)
return success_payload(
request,