Skip to content

Models

Typed pydantic v2 data models for vgmdb-client.

Album

Bases: VgmdbModel

A vgmdb album (core subset of fields).

Source code in src/vgmdb_client/models/album.py
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
class Album(VgmdbModel):
    """A vgmdb album (core subset of fields)."""

    id: int
    link: str | None = None
    titles: LocalizedText
    catalog: str | None = None
    release_date: PartialDate | None = None
    classification: str | None = None
    cover_small: str | None = None
    cover_full: str | None = None
    discs: list[Disc] = Field(default_factory=list)
    credits: list[Credit] = Field(default_factory=list)
    notes: str | None = None
    release_event: EventRef | None = None

AlbumSearchResult

Bases: VgmdbModel

A single album entry in search results.

Source code in src/vgmdb_client/models/search.py
10
11
12
13
14
15
16
17
class AlbumSearchResult(VgmdbModel):
    """A single album entry in search results."""

    id: int
    link: str | None = None
    titles: LocalizedText
    catalog: str | None = None
    release_date: PartialDate | None = None

Artist

Bases: VgmdbModel

A vgmdb artist (person or unit), core subset of fields.

type is stored verbatim as vgmdb shows it (e.g. "Person", "Unit"). members lists a unit's members; units lists the groups a person belongs to. Discography is out of scope this pass.

Source code in src/vgmdb_client/models/artist.py
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class Artist(VgmdbModel):
    """A vgmdb artist (person or unit), core subset of fields.

    ``type`` is stored verbatim as vgmdb shows it (e.g. "Person", "Unit"). ``members`` lists a unit's
    members; ``units`` lists the groups a person belongs to. Discography is out of scope this pass.
    """

    id: int
    link: str | None = None
    names: LocalizedText
    aliases: list[str] = Field(default_factory=list)
    type: str | None = None
    birthdate: PartialDate | None = None
    notes: str | None = None
    members: list[ArtistRef] = Field(default_factory=list)
    units: list[ArtistRef] = Field(default_factory=list)

ArtistRef

Bases: VgmdbModel

A lightweight pointer to an artist (distinct from the full Artist entity).

Source code in src/vgmdb_client/models/common.py
100
101
102
103
104
105
class ArtistRef(VgmdbModel):
    """A lightweight pointer to an artist (distinct from the full Artist entity)."""

    names: LocalizedText
    id: int | None = None
    link: str | None = None

Credit

Bases: VgmdbModel

An album credit: a normalized role, the verbatim source label, and its artists.

Source code in src/vgmdb_client/models/album.py
27
28
29
30
31
32
class Credit(VgmdbModel):
    """An album credit: a normalized role, the verbatim source label, and its artists."""

    role: Role
    role_raw: str
    artists: list[ArtistRef] = Field(default_factory=list)

Disc

Bases: VgmdbModel

A disc within an album, holding its tracks.

Source code in src/vgmdb_client/models/album.py
19
20
21
22
23
24
class Disc(VgmdbModel):
    """A disc within an album, holding its tracks."""

    number: int | None = None
    name: str | None = None
    tracks: list[Track] = Field(default_factory=list)

Event

Bases: VgmdbModel

A vgmdb event (concert, convention, ...), core subset of fields.

type is stored verbatim when the page shows one. end_date is None for a single-day event or when no distinct end is shown. Released-album / related lists are out of scope this pass.

Source code in src/vgmdb_client/models/event.py
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
class Event(VgmdbModel):
    """A vgmdb event (concert, convention, ...), core subset of fields.

    ``type`` is stored verbatim when the page shows one. ``end_date`` is ``None`` for a single-day
    event or when no distinct end is shown. Released-album / related lists are out of scope this pass.
    """

    id: int
    link: str | None = None
    names: LocalizedText
    type: str | None = None
    start_date: PartialDate | None = None
    end_date: PartialDate | None = None
    notes: str | None = None

EventRef

Bases: VgmdbModel

A lightweight pointer to an event (distinct from the full Event entity).

Source code in src/vgmdb_client/models/common.py
124
125
126
127
128
129
class EventRef(VgmdbModel):
    """A lightweight pointer to an event (distinct from the full Event entity)."""

    names: LocalizedText
    id: int | None = None
    link: str | None = None

LocalizedText

Bases: RootModel[dict[str, str]]

Multi-language text (language label -> text) with selection helpers.

vgmdb labels languages as e.g. "English", "Japanese", "Romaji"; those labels are stored verbatim.

Source code in src/vgmdb_client/models/common.py
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
class LocalizedText(RootModel[dict[str, str]]):
    """Multi-language text (language label -> text) with selection helpers.

    vgmdb labels languages as e.g. "English", "Japanese", "Romaji"; those
    labels are stored verbatim.
    """

    model_config = ConfigDict(frozen=True)

    @property
    def all(self) -> dict[str, str]:
        """The raw language -> text mapping."""
        return self.root

    @property
    def default(self) -> str | None:
        """Best available text, preferring English then Romaji, else any; None if empty."""
        for language in _DEFAULT_PREFERENCE:
            if language in self.root:
                return self.root[language]
        return next(iter(self.root.values()), None)

    def prefer(self, *languages: str) -> str | None:
        """First text among the requested languages, else the default."""
        for language in languages:
            if language in self.root:
                return self.root[language]
        return self.default

    def __str__(self) -> str:
        return self.default or ""

all property

The raw language -> text mapping.

default property

Best available text, preferring English then Romaji, else any; None if empty.

prefer(*languages)

First text among the requested languages, else the default.

Source code in src/vgmdb_client/models/common.py
45
46
47
48
49
50
def prefer(self, *languages: str) -> str | None:
    """First text among the requested languages, else the default."""
    for language in languages:
        if language in self.root:
            return self.root[language]
    return self.default

OrgRef

Bases: VgmdbModel

A lightweight pointer to an organization (distinct from the full Organization entity).

Source code in src/vgmdb_client/models/common.py
116
117
118
119
120
121
class OrgRef(VgmdbModel):
    """A lightweight pointer to an organization (distinct from the full Organization entity)."""

    names: LocalizedText
    id: int | None = None
    link: str | None = None

Organization

Bases: VgmdbModel

A vgmdb organization (company, doujin circle, label, ...), core subset of fields.

type is stored verbatim (e.g. "Company", "Doujin Circle", "Label"). Released-album lists are out of scope this pass.

Source code in src/vgmdb_client/models/organization.py
 8
 9
10
11
12
13
14
15
16
17
18
19
class Organization(VgmdbModel):
    """A vgmdb organization (company, doujin circle, label, ...), core subset of fields.

    ``type`` is stored verbatim (e.g. "Company", "Doujin Circle", "Label"). Released-album lists are
    out of scope this pass.
    """

    id: int
    link: str | None = None
    names: LocalizedText
    type: str | None = None
    notes: str | None = None

PartialDate

Bases: VgmdbModel

A possibly-incomplete date: a required year with optional month and day.

Source code in src/vgmdb_client/models/common.py
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
class PartialDate(VgmdbModel):
    """A possibly-incomplete date: a required year with optional month and day."""

    year: int
    month: int | None = Field(default=None, ge=1, le=12)
    day: int | None = Field(default=None, ge=1, le=31)

    @model_validator(mode="after")
    def _day_requires_month(self) -> PartialDate:
        if self.day is not None and self.month is None:
            msg = "day requires month"
            raise ValueError(msg)
        return self

    @property
    def precision(self) -> Literal["year", "month", "day"]:
        if self.day is not None:
            return "day"
        if self.month is not None:
            return "month"
        return "year"

    def __str__(self) -> str:
        if self.day is not None:
            return f"{self.year:04d}-{self.month:02d}-{self.day:02d}"
        if self.month is not None:
            return f"{self.year:04d}-{self.month:02d}"
        return f"{self.year:04d}"

    @classmethod
    def parse(cls, value: str) -> PartialDate | None:
        """Parse YYYY / YYYY-MM / YYYY-MM-DD; return None if unparseable or invalid."""
        match = _PARTIAL_DATE_RE.match(value.strip()) if value else None
        if match is None:
            return None
        year = int(match.group(1))
        month = int(match.group(2)) if match.group(2) else None
        day = int(match.group(3)) if match.group(3) else None
        try:
            return cls(year=year, month=month, day=day)
        except ValidationError:
            return None

parse(value) classmethod

Parse YYYY / YYYY-MM / YYYY-MM-DD; return None if unparseable or invalid.

Source code in src/vgmdb_client/models/common.py
85
86
87
88
89
90
91
92
93
94
95
96
97
@classmethod
def parse(cls, value: str) -> PartialDate | None:
    """Parse YYYY / YYYY-MM / YYYY-MM-DD; return None if unparseable or invalid."""
    match = _PARTIAL_DATE_RE.match(value.strip()) if value else None
    if match is None:
        return None
    year = int(match.group(1))
    month = int(match.group(2)) if match.group(2) else None
    day = int(match.group(3)) if match.group(3) else None
    try:
        return cls(year=year, month=month, day=day)
    except ValidationError:
        return None

Product

Bases: VgmdbModel

A vgmdb product (game, franchise, animation, ...), core subset of fields.

type is stored verbatim (e.g. "Game", "Franchise"). franchises lists parent/related products; organizations lists developers/publishers. Related-album lists are out of scope.

Source code in src/vgmdb_client/models/product.py
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class Product(VgmdbModel):
    """A vgmdb product (game, franchise, animation, ...), core subset of fields.

    ``type`` is stored verbatim (e.g. "Game", "Franchise"). ``franchises`` lists parent/related
    products; ``organizations`` lists developers/publishers. Related-album lists are out of scope.
    """

    id: int
    link: str | None = None
    names: LocalizedText
    type: str | None = None
    notes: str | None = None
    franchises: list[ProductRef] = Field(default_factory=list)
    organizations: list[OrgRef] = Field(default_factory=list)

ProductRef

Bases: VgmdbModel

A lightweight pointer to a product (distinct from the full Product entity).

Source code in src/vgmdb_client/models/common.py
108
109
110
111
112
113
class ProductRef(VgmdbModel):
    """A lightweight pointer to a product (distinct from the full Product entity)."""

    names: LocalizedText
    id: int | None = None
    link: str | None = None

Role

Bases: str, Enum

Normalized credit role. OTHER is the conservative fallback.

Source code in src/vgmdb_client/models/roles.py
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
class Role(str, Enum):
    """Normalized credit role. ``OTHER`` is the conservative fallback."""

    COMPOSER = "composer"
    ARRANGER = "arranger"
    PERFORMER = "performer"
    VOCALIST = "vocalist"
    LYRICIST = "lyricist"
    PRODUCER = "producer"
    ENGINEER = "engineer"
    MIXING = "mixing"
    MASTERING = "mastering"
    DIRECTOR = "director"
    CONDUCTOR = "conductor"
    ARTWORK = "artwork"
    OTHER = "other"

SearchResults

Bases: VgmdbModel

Results of an album search.

Source code in src/vgmdb_client/models/search.py
20
21
22
23
24
class SearchResults(VgmdbModel):
    """Results of an album search."""

    query: str
    albums: list[AlbumSearchResult] = Field(default_factory=list)

Track

Bases: VgmdbModel

A single track on a disc.

Source code in src/vgmdb_client/models/album.py
11
12
13
14
15
16
class Track(VgmdbModel):
    """A single track on a disc."""

    titles: LocalizedText
    number: int | None = None
    length: str | None = None

normalize_role(raw)

Map a freeform vgmdb role label to a :class:Role (conservative; unknown -> OTHER).

Source code in src/vgmdb_client/models/roles.py
 95
 96
 97
 98
 99
100
101
102
103
def normalize_role(raw: str) -> Role:
    """Map a freeform vgmdb role label to a :class:`Role` (conservative; unknown -> OTHER)."""
    label = raw.casefold().strip()
    if label in _EXACT:
        return _EXACT[label]
    for keyword, role in _RULES:
        if keyword in label:
            return role
    return Role.OTHER