animedex.backends.kitsu.models

Rich Kitsu dataclasses (one per JSON:API resource type).

Kitsu serves data in the JSON:API shape: every resource is wrapped as {id, type, attributes, relationships, links} and listings come back as {data: [...], meta, links}. The high-level _fetch helper extracts the inner data block, and these classes model the resources directly.

Per the project’s lossless rich-model contract every class inherits from BackendRichModel (extra='allow', populate_by_name=True, frozen=True). Only the fields the high-level API touches are spelled out as typed attributes; the JSON:API attributes block carries dozens more fields that upstream may add or remove between releases, and they round-trip through model_dump(by_alias=True) via extra='allow'.

The KitsuAnime.to_common() and KitsuManga.to_common() projections map onto Anime and Manga so a downstream pipeline that already speaks the cross-source common shape doesn’t need to know JSON:API.

KitsuAnimeAttributes

class animedex.backends.kitsu.models.KitsuAnimeAttributes(*, canonicalTitle: str | None = None, titles: Dict[str, str | None] | None = None, abbreviatedTitles: List[str] | None = None, synopsis: str | None = None, description: str | None = None, averageRating: str | None = None, userCount: int | None = None, favoritesCount: int | None = None, startDate: str | None = None, endDate: str | None = None, ageRating: str | None = None, ageRatingGuide: str | None = None, subtype: str | None = None, status: str | None = None, episodeCount: int | None = None, episodeLength: int | None = None, showType: str | None = None, youtubeVideoId: str | None = None, nsfw: bool | None = None, **extra_data: Any)[source]

Bases: BackendRichModel

The attributes block on an /anime/{id} resource.

canonicalTitle: str | None
titles: Dict[str, str | None] | None
abbreviatedTitles: List[str] | None
synopsis: str | None
description: str | None
averageRating: str | None
userCount: int | None
favoritesCount: int | None
startDate: str | None
endDate: str | None
ageRating: str | None
ageRatingGuide: str | None
subtype: str | None
status: str | None
episodeCount: int | None
episodeLength: int | None
showType: str | None
youtubeVideoId: str | None
nsfw: bool | None

KitsuMangaAttributes

class animedex.backends.kitsu.models.KitsuMangaAttributes(*, canonicalTitle: str | None = None, titles: Dict[str, str | None] | None = None, abbreviatedTitles: List[str] | None = None, synopsis: str | None = None, description: str | None = None, averageRating: str | None = None, userCount: int | None = None, favoritesCount: int | None = None, startDate: str | None = None, endDate: str | None = None, status: str | None = None, chapterCount: int | None = None, volumeCount: int | None = None, mangaType: str | None = None, serialization: str | None = None, **extra_data: Any)[source]

Bases: BackendRichModel

The attributes block on a /manga/{id} resource.

canonicalTitle: str | None
titles: Dict[str, str | None] | None
abbreviatedTitles: List[str] | None
synopsis: str | None
description: str | None
averageRating: str | None
userCount: int | None
favoritesCount: int | None
startDate: str | None
endDate: str | None
status: str | None
chapterCount: int | None
volumeCount: int | None
mangaType: str | None
serialization: str | None

KitsuMappingAttributes

class animedex.backends.kitsu.models.KitsuMappingAttributes(*, externalSite: str | None = None, externalId: str | None = None, **extra_data: Any)[source]

Bases: BackendRichModel

The attributes block on an /anime/{id}/mappings row.

externalSite: str | None
externalId: str | None

KitsuStreamingLinkAttributes

class animedex.backends.kitsu.models.KitsuStreamingLinkAttributes(*, url: str | None = None, subs: List[str] | None = None, dubs: List[str] | None = None, **extra_data: Any)[source]

Bases: BackendRichModel

The attributes block on an /anime/{id}/streaming-links row.

url: str | None
subs: List[str] | None
dubs: List[str] | None

KitsuCategoryAttributes

class animedex.backends.kitsu.models.KitsuCategoryAttributes(*, title: str | None = None, description: str | None = None, slug: str | None = None, nsfw: bool | None = None, childCount: int | None = None, **extra_data: Any)[source]

Bases: BackendRichModel

The attributes block on a /categories row.

title: str | None
description: str | None
slug: str | None
nsfw: bool | None
childCount: int | None

KitsuCharacterAttributes

class animedex.backends.kitsu.models.KitsuCharacterAttributes(*, slug: str | None = None, name: str | None = None, description: str | None = None, malId: Any | None = None, **extra_data: Any)[source]

Bases: BackendRichModel

The attributes block on a /characters row.

Note that some upstream fields are deprecated and now carry explanatory strings instead of their original values (e.g. malId may be a string "Moved to mappings relationship." rather than an int). They surface as Any so the lossless contract still validates regardless of upstream’s chosen deprecation marker.

slug: str | None
name: str | None
description: str | None
malId: Any | None

KitsuPersonAttributes

class animedex.backends.kitsu.models.KitsuPersonAttributes(*, name: str | None = None, description: str | None = None, malId: Any | None = None, **extra_data: Any)[source]

Bases: BackendRichModel

The attributes block on a /people row.

See KitsuCharacterAttributes for the malId deprecation note.

name: str | None
description: str | None
malId: Any | None

KitsuProducerAttributes

class animedex.backends.kitsu.models.KitsuProducerAttributes(*, slug: str | None = None, name: str | None = None, **extra_data: Any)[source]

Bases: BackendRichModel

The attributes block on a /producers row.

slug: str | None
name: str | None

KitsuGenreAttributes

class animedex.backends.kitsu.models.KitsuGenreAttributes(*, name: str | None = None, slug: str | None = None, description: str | None = None, **extra_data: Any)[source]

Bases: BackendRichModel

The attributes block on a /genres row.

name: str | None
slug: str | None
description: str | None

KitsuStreamerAttributes

class animedex.backends.kitsu.models.KitsuStreamerAttributes(*, siteName: str | None = None, logo: str | None = None, streamingLinksCount: int | None = None, **extra_data: Any)[source]

Bases: BackendRichModel

The attributes block on a /streamers row.

siteName: str | None
streamingLinksCount: int | None

KitsuFranchiseAttributes

class animedex.backends.kitsu.models.KitsuFranchiseAttributes(*, slug: str | None = None, titles: Dict[str, str | None] | None = None, canonicalTitle: str | None = None, **extra_data: Any)[source]

Bases: BackendRichModel

The attributes block on a /franchises row.

slug: str | None
titles: Dict[str, str | None] | None
canonicalTitle: str | None

KitsuUserAttributes

class animedex.backends.kitsu.models.KitsuUserAttributes(*, name: str | None = None, pastNames: List[str] | None = None, slug: str | None = None, about: str | None = None, location: str | None = None, waifuOrHusbando: str | None = None, followersCount: int | None = None, followingCount: int | None = None, lifeSpentOnAnime: int | None = None, birthday: str | None = None, gender: str | None = None, **extra_data: Any)[source]

Bases: BackendRichModel

The attributes block on a /users row (public read).

name: str | None
pastNames: List[str] | None
slug: str | None
about: str | None
location: str | None
waifuOrHusbando: str | None
followersCount: int | None
followingCount: int | None
lifeSpentOnAnime: int | None
birthday: str | None
gender: str | None

KitsuAnime

class animedex.backends.kitsu.models.KitsuAnime(*, id: str, type: str = 'anime', attributes: KitsuAnimeAttributes | None = None, relationships: Dict[str, Any] | None = None, links: Dict[str, Any] | None = None, source_tag: SourceTag | None = None, **extra_data: Any)[source]

Bases: BackendRichModel

JSON:API anime resource from /anime/{id} or /anime?filter[text]=....

Variables:
  • id (str) – Kitsu numeric ID (as a string per JSON:API convention).

  • type (str) – JSON:API type tag — always "anime".

  • attributes (KitsuAnimeAttributes or None) – Typed anime attributes.

  • relationships (dict or None) – JSON:API relationships block (link descriptors for genres / categories / streamingLinks / mappings / etc.).

  • links (dict or None) – JSON:API links block.

  • source_tag (SourceTag or None) – Provenance tag.

id: str
type: str
attributes: KitsuAnimeAttributes | None
relationships: Dict[str, Any] | None
source_tag: SourceTag | None
to_common() Anime[source]

Project this resource onto the cross-source Anime shape.

Returns:

Cross-source projection.

Return type:

animedex.models.anime.Anime

KitsuManga

class animedex.backends.kitsu.models.KitsuManga(*, id: str, type: str = 'manga', attributes: KitsuMangaAttributes | None = None, relationships: Dict[str, Any] | None = None, links: Dict[str, Any] | None = None, source_tag: SourceTag | None = None, **extra_data: Any)[source]

Bases: BackendRichModel

JSON:API manga resource from /manga/{id} or /manga?filter[text]=....

id: str
type: str
attributes: KitsuMangaAttributes | None
relationships: Dict[str, Any] | None
source_tag: SourceTag | None
to_common() Manga[source]

Project this resource onto the cross-source Manga shape.

Note that the common Manga models chapters as a list of Chapter records (not a count); Kitsu’s /manga/{id} only carries the count, so the projection sets chapters=[]. Use the rich shape’s attributes.chapterCount for the integer.

Returns:

Cross-source projection.

Return type:

animedex.models.manga.Manga

KitsuMapping

class animedex.backends.kitsu.models.KitsuMapping(*, id: str, type: str = 'mappings', attributes: KitsuMappingAttributes | None = None, relationships: Dict[str, Any] | None = None, links: Dict[str, Any] | None = None, source_tag: SourceTag | None = None, **extra_data: Any)[source]

Bases: BackendRichModel

JSON:API mapping resource from /anime/{id}/mappings.

Each mapping row carries an externalSite + externalId pair, identifying the anime on a peer upstream (e.g. externalSite='myanimelist/anime', externalId='52991').

id: str
type: str
attributes: KitsuMappingAttributes | None
relationships: Dict[str, Any] | None
source_tag: SourceTag | None

KitsuCategory

class animedex.backends.kitsu.models.KitsuCategory(*, id: str, type: str = 'categories', attributes: KitsuCategoryAttributes | None = None, relationships: Dict[str, Any] | None = None, links: Dict[str, Any] | None = None, source_tag: SourceTag | None = None, **extra_data: Any)[source]

Bases: BackendRichModel

JSON:API category resource from /categories.

id: str
type: str
attributes: KitsuCategoryAttributes | None
relationships: Dict[str, Any] | None
source_tag: SourceTag | None

KitsuCharacter

class animedex.backends.kitsu.models.KitsuCharacter(*, id: str, type: str = 'characters', attributes: KitsuCharacterAttributes | None = None, relationships: Dict[str, Any] | None = None, links: Dict[str, Any] | None = None, source_tag: SourceTag | None = None, **extra_data: Any)[source]

Bases: BackendRichModel

JSON:API character resource from /characters/{id} and /characters?filter[name]=....

id: str
type: str
attributes: KitsuCharacterAttributes | None
relationships: Dict[str, Any] | None
source_tag: SourceTag | None
to_common() Character[source]

Project this resource onto the cross-source character shape.

KitsuPerson

class animedex.backends.kitsu.models.KitsuPerson(*, id: str, type: str = 'people', attributes: KitsuPersonAttributes | None = None, relationships: Dict[str, Any] | None = None, links: Dict[str, Any] | None = None, source_tag: SourceTag | None = None, **extra_data: Any)[source]

Bases: BackendRichModel

JSON:API person resource from /people/{id} and /people?filter[name]=....

id: str
type: str
attributes: KitsuPersonAttributes | None
relationships: Dict[str, Any] | None
source_tag: SourceTag | None
to_common() Staff[source]

Project this resource onto the cross-source staff shape.

KitsuProducer

class animedex.backends.kitsu.models.KitsuProducer(*, id: str, type: str = 'producers', attributes: KitsuProducerAttributes | None = None, relationships: Dict[str, Any] | None = None, links: Dict[str, Any] | None = None, source_tag: SourceTag | None = None, **extra_data: Any)[source]

Bases: BackendRichModel

JSON:API producer resource from /producers.

id: str
type: str
attributes: KitsuProducerAttributes | None
relationships: Dict[str, Any] | None
source_tag: SourceTag | None
to_common() Studio[source]

Project this resource onto the cross-source studio shape.

KitsuGenre

class animedex.backends.kitsu.models.KitsuGenre(*, id: str, type: str = 'genres', attributes: KitsuGenreAttributes | None = None, relationships: Dict[str, Any] | None = None, links: Dict[str, Any] | None = None, source_tag: SourceTag | None = None, **extra_data: Any)[source]

Bases: BackendRichModel

JSON:API genre resource from /genres.

id: str
type: str
attributes: KitsuGenreAttributes | None
relationships: Dict[str, Any] | None
source_tag: SourceTag | None

KitsuStreamer

class animedex.backends.kitsu.models.KitsuStreamer(*, id: str, type: str = 'streamers', attributes: KitsuStreamerAttributes | None = None, relationships: Dict[str, Any] | None = None, links: Dict[str, Any] | None = None, source_tag: SourceTag | None = None, **extra_data: Any)[source]

Bases: BackendRichModel

JSON:API streamer resource from /streamers.

id: str
type: str
attributes: KitsuStreamerAttributes | None
relationships: Dict[str, Any] | None
source_tag: SourceTag | None

KitsuFranchise

class animedex.backends.kitsu.models.KitsuFranchise(*, id: str, type: str = 'franchises', attributes: KitsuFranchiseAttributes | None = None, relationships: Dict[str, Any] | None = None, links: Dict[str, Any] | None = None, source_tag: SourceTag | None = None, **extra_data: Any)[source]

Bases: BackendRichModel

JSON:API franchise resource from /franchises.

id: str
type: str
attributes: KitsuFranchiseAttributes | None
relationships: Dict[str, Any] | None
source_tag: SourceTag | None

KitsuUser

class animedex.backends.kitsu.models.KitsuUser(*, id: str, type: str = 'users', attributes: KitsuUserAttributes | None = None, relationships: Dict[str, Any] | None = None, links: Dict[str, Any] | None = None, source_tag: SourceTag | None = None, **extra_data: Any)[source]

Bases: BackendRichModel

JSON:API user resource from /users/{id} (public read).

id: str
type: str
attributes: KitsuUserAttributes | None
relationships: Dict[str, Any] | None
source_tag: SourceTag | None

KitsuRelatedResource

class animedex.backends.kitsu.models.KitsuRelatedResource(*, id: str, type: str, attributes: Dict[str, Any] | None = None, relationships: Dict[str, Any] | None = None, links: Dict[str, Any] | None = None, source_tag: SourceTag | None = None, **extra_data: Any)[source]

Bases: BackendRichModel

Catch-all JSON:API resource for sub-relationship fetches.

Used for /anime/{id}/characters, /anime/{id}/staff, /anime/{id}/episodes, /anime/{id}/reviews, /anime/{id}/media-relationships, /anime/{id}/anime-productions, /manga/{id}/chapters, /people/{id}/voices, /people/{id}/castings, /library-entries (filtered), /users/{id}/stats, etc. The shape is uniform JSON:API (id / type / attributes / relationships); the typed-attribute story for these endpoints is extensive enough that we surface attributes as a dict rather than typing each one. extra='allow' round-trips every upstream key.

id: str
type: str
attributes: Dict[str, Any] | None
relationships: Dict[str, Any] | None
source_tag: SourceTag | None

selftest

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

Smoke-test the Kitsu rich models.

Validates a synthetic KitsuAnime round-trips through model_dump_json / model_validate_json and projects to a well-formed Anime.

Returns:

True on success; raises on schema drift.

Return type:

bool