animedex.backends.trace.models

Lossless rich Trace.moe dataclasses.

The backend layer must round-trip the upstream payload field-for- field. The user-facing common types in animedex.models.trace rename fields for Pythonic ergonomics (fromstart_at_seconds etc.) and so they are projections, not the raw shape. These rich classes preserve the upstream verbatim:

  • RawTraceHit — single /search hit row, lossless.

  • RawTraceQuota/me body, lossless. The upstream’s id field carries the caller’s egress IP; surfacing it to the caller is fine (it’s the caller’s own datum), but it must never be hard-coded into a fixture committed to this repo. That guarantee lives in the fixture-capture pipeline (tools/fixtures/capture.py rewrites every public IPv4 in captured payloads to the RFC-5737 documentation address), not in the data model.

to_common() projects to TraceHit and TraceQuota respectively. Loss of information is permitted at and only at that boundary.

RawTraceAnilistInfo

class animedex.backends.trace.models.RawTraceAnilistInfo(*, id: int | None = None, idMal: int | None = None, **extra_data: Any)[source]

Bases: BackendRichModel

Inner anilist block when anilistInfo is set on the search call. Not a fixed schema — Trace.moe may inline arbitrary AniList fields here. extra='allow' keeps every key.

id: int | None
idMal: int | None

RawTraceHit

class animedex.backends.trace.models.RawTraceHit(*, anilist: int | RawTraceAnilistInfo | None = None, similarity: Annotated[float, Ge(ge=0.0), Le(le=1.0)], episode: Any | None = None, from_: float, at: float, to: float, filename: str | None = None, duration: float | None = None, video: str | None = None, image: str | None = None, source_tag: SourceTag, **extra_data: Any)[source]

Bases: BackendRichModel

Single /search result row, lossless to the upstream shape.

Field names mirror the upstream: from / to are Python keywords so they’re aliased onto from_ / to_; everything else uses upstream-native names directly.

anilist: int | RawTraceAnilistInfo | None
similarity: float
episode: Any | None
from_: float
at: float
to_: float
filename: str | None
duration: float | None
video: str | None
image: str | None
source_tag: SourceTag
to_common() TraceHit[source]

Project to the user-facing TraceHit (lossy: renames from/at/to to Pythonic, drops everything in anilist beyond title).

RawTraceQuota

class animedex.backends.trace.models.RawTraceQuota(*, id: str | None = None, priority: int, concurrency: int, quota: int, quotaUsed: int | str, source_tag: SourceTag, **extra_data: Any)[source]

Bases: BackendRichModel

/me body, lossless to the upstream shape.

The upstream’s id field carries the caller’s egress IP. We surface it on the rich model — it is the caller’s own datum, not something to filter on their behalf. The common-projection TraceQuota does not include id, so anyone who wants the IP reaches for the rich shape; anyone who just wants quota numbers reaches for the common shape.

The fixture-capture pipeline (tools/fixtures/capture.py) rewrites public IPv4 addresses in captured payloads to the RFC-5737 documentation address, so the repo’s fixtures never carry a real contributor IP — but a live request on a user’s own machine returns their actual IP, unmodified.

id: str | None
priority: int
concurrency: int
quota: int
quotaUsed: int | str
source_tag: SourceTag
to_common() TraceQuota[source]

selftest

animedex.backends.trace.models.selftest() bool[source]