animedex.models.anime
Anime domain models.
The records in this module compose
SourceTag provenance into the typed
shape AniList, Jikan, Kitsu, and Shikimori backends populate.
The Anime class is intentionally a common projection: it
holds the fields that are reasonably comparable across at least
three of the upstreams we target. Per plans/05-python-api.md and
the design discussion in #1’s the initial scaffolding closeout, each backend will
ship a richer per-backend dataclass under
animedex.backends.<name>.models (e.g. AnilistAnime) that
exposes the long tail of upstream-specific fields, plus a
to_common() -> Anime mapping. Single-backend commands return
the rich type; cross-source aggregate commands return Anime.
Per plans/03 §5 every record carries source so attribution
survives every later hop (cache, render, JSON pipeline).
AnimeStatus
AnimeFormat
AnimeSeason
AnimeTitle
AnimeRating
AnimeStreamingLink
- class animedex.models.anime.AnimeStreamingLink(*, provider: str, url: str)[source]
Bases:
AnimedexModelA legal streaming destination from Kitsu’s
streaming-links.- Variables:
NextAiringEpisode
- class animedex.models.anime.NextAiringEpisode(*, airing_at: datetime, time_until_airing_seconds: int, episode: int)[source]
Bases:
AnimedexModelThe next-up unaired episode for a currently-airing series.
Populated from AniList’s
nextAiringEpisodeblock. The same information is occasionally available via Jikan’sbroadcastfield but with less precision (a weekday + time-of-day, not an absolute timestamp); the mapper for Jikan leaves this fieldNoneand surfaces broadcast info viaJikanAnime.broadcast.- Variables:
airing_at (datetime.datetime) – Exact UTC timestamp the episode airs.
time_until_airing_seconds (int) – Server-computed delta from the moment of the API call. The receiver should treat this as advisory;
airing_atis the authoritative value.episode (int) – Sequence number of the upcoming episode.
- airing_at: datetime
AiringScheduleRow
- class animedex.models.anime.AiringScheduleRow(*, title: str, airing_at: ~datetime.datetime | None = None, episode: int | None = None, weekday: str | None = None, local_time: str | None = None, source: ~animedex.models.common.SourceTag, core: ~typing.Dict[str, ~typing.Any] = <factory>, details: ~typing.Dict[str, ~typing.Any] = <factory>, source_payload: ~typing.Dict[str, ~typing.Any] = <factory>)[source]
Bases:
AnimedexModelCommon projection for a single airing schedule row.
- Variables:
title (str) – Display title of the airing series.
airing_at (datetime.datetime or None) – Exact UTC airing instant when available.
episode (int or None) – Episode number when reported.
weekday (str or None) – Lowercase weekday name when the upstream only reports a weekly schedule.
local_time (str or None) – Local clock time string from the upstream.
source (SourceTag) – Provenance tag.
core (dict) – Compact aggregate-facing summary. JSON consumers can read this first and then inspect
details/source_payloadfor the full source-specific row.details (dict) – Additional source-specific schedule fields kept in a namespaced dictionary for aggregate consumers.
source_payload (dict) – Full backend row payload when an aggregate command can preserve it.
Anime
- class animedex.models.anime.Anime(*, id: str, title: AnimeTitle, score: AnimeRating | None = None, episodes: int | None = None, studios: List[str] = [], streaming: List[AnimeStreamingLink] = [], description: str | None = None, genres: List[str] = [], tags: List[str] = [], status: Literal['airing', 'finished', 'upcoming', 'cancelled', 'hiatus', 'unknown'] | None = None, format: Literal['TV', 'TV_SHORT', 'MOVIE', 'OVA', 'ONA', 'SPECIAL', 'MUSIC'] | None = None, season: Literal['WINTER', 'SPRING', 'SUMMER', 'FALL'] | None = None, season_year: int | None = None, aired_from: date | None = None, aired_to: date | None = None, duration_minutes: int | None = None, cover_image_url: str | None = None, banner_image_url: str | None = None, trailer_url: str | None = None, source_material: str | None = None, country_of_origin: str | None = None, is_adult: bool | None = None, age_rating: str | None = None, title_synonyms: List[str] = [], popularity: int | None = None, favourites: int | None = None, trending: int | None = None, next_airing_episode: NextAiringEpisode | None = None, ids: Dict[str, str], source: SourceTag)[source]
Bases:
AnimedexModelAn anime record as returned by any single backend.
The field set is the cross-source projection: every field is expected to be populated by at least three of the upstreams we target (AniList, Jikan, Kitsu, Shikimori, ANN, AniDB), or is a backend-specific value that an aggregate consumer can ignore (e.g.
streaming, which is effectively Kitsu-only).Backends that expose richer data ship per-backend dataclasses under
animedex.backends.<name>.modelsand provideto_common() -> Animeto project onto this shape.- Variables:
id (str) – Canonical
"<source>:<id>"identifier.title (AnimeTitle) – Multi-locale title block.
score (AnimeRating or None) – Score from the answering backend, when reported.
episodes (int or None) – Episode count, when known.
studios (list of str) – Production studios, in the upstream’s order.
streaming (list of AnimeStreamingLink) – Legal streaming destinations.
description (str or None) – Synopsis / description (free text; may be markdown or HTML depending on the upstream).
genres (list of str) – Curated, broad genre tags (e.g.
"Adventure","Drama"). Smaller and stabler thantags; AniList separates these explicitly.tags (list of str) – Long-tail descriptive tags (e.g.
"Slow Burn","Magic"). May be empty when the upstream does not separate fromgenres.status (str or None) – Airing status, normalised to
AnimeStatus.format (str or None) – Media format, normalised to
AnimeFormat.season (str or None) – Broadcast season, normalised to
AnimeSeason.season_year (int or None) – Calendar year of the broadcast season.
aired_from (datetime.date or None) – Date of the first aired episode.
aired_to (datetime.date or None) – Date of the last aired episode (or
Nonewhen still airing).duration_minutes (int or None) – Per-episode duration in minutes.
cover_image_url (str or None) – Cover image URL.
banner_image_url (str or None) – Banner image URL when one is exposed.
trailer_url (str or None) – Trailer URL when one is exposed.
source_material (str or None) – Origin story type (e.g.
"manga","light_novel","original"); free-form because backend vocabularies vary.country_of_origin (str or None) – ISO 3166-1 alpha-2 country code.
is_adult (bool or None) –
Truefor adult-only content.Nonewhen the upstream does not expose the flag.age_rating (str or None) – Free-form rating string (e.g.
"PG-13","TV-MA"); upstream vocabularies vary.title_synonyms (list of str) – Alternative-language / fan-translation titles. Filled from Jikan
title_synonyms(transliterations, English short forms) and AniListsynonyms(community- contributed titles).popularity (int or None) – Popularity metric; the meaning is upstream- specific (rank, favourites, member count).
favourites (int or None) – Count of users who marked the title as favourite (AniList-only; Jikan reports this separately).
trending (int or None) – AniList trending rank at fetch time. Lower is more-trending;
Nonefrom non-AniList sources.next_airing_episode (NextAiringEpisode or None) – Upcoming episode for currently-airing series.
Nonefor finished / upcoming-but-no-schedule shows.ids (dict[str, str]) – Cross-service identifier map (e.g.
{"mal": "52991", "kitsu": "47390"}).source (SourceTag) – Provenance tag.
- title: AnimeTitle
- score: AnimeRating | None
- streaming: List[AnimeStreamingLink]
- next_airing_episode: NextAiringEpisode | None
selftest
- animedex.models.anime.selftest() bool[source]
Smoke-test the anime model graph.
Instantiates and JSON-round-trips an
Animecontaining every optional field so future schema regressions surface in the diagnostic, not at first real backend hit.- Returns:
Trueon success; raises on schema errors.- Return type: