Source code for relaton.models.bibdata

"""
Some of Relaton models implemented as Pydantic models.
"""

# NOTE: Docstrings for dataclasses and models below
# may be used when rendering OpenAPI schemas,
# where ReSTructuredText syntax is not
# supported. Stick to plain text.

from __future__ import annotations
# Required for circular dependency
# between BibliographicItem and Relation.

from typing import List, Union, Optional
import datetime

from pydantic import BaseModel, Extra, validator
from pydantic.dataclasses import dataclass

from .copyrights import Copyright
from .strings import Title, GenericStringValue
from .people import Person
from .orgs import Organization
from .links import Link
from .dates import Date, validate_relaxed_date


__all__ = (
    'DocID',
    'BibliographicItem',
    'Relation',
    'Contributor',
    'Series',
    'BiblioNote',
)


[docs]@dataclass class DocID: """Typed :term:`document identifier`. May be given by publisher or issued by some third-party system. """ id: str type: str """:term:`document identifier type`. Determines the format of the ``id`` field. """ primary: Optional[bool] = None """If ``True``, this identifier is considered a :term:`primary document identifier`. """ scope: Optional[str] = None """ .. todo:: Clarify the meaning of scope. """
[docs]@dataclass class BiblioNote: """Bibliographic note.""" content: str """Note content.""" type: Optional[str] = None """The class of the note associated with the bibliographic item. May be used to differentiate rendering of notes in bibliographies. """
[docs]class Series(BaseModel): """ A series that given document belongs to. Note: formattedref is exclusive with other properties. """ # TODO: Don’t make all properties optional, use union types or something formattedref: Optional[Union[GenericStringValue, str]] = None """References a bibliographic item via a primary ID. Exclusive with other properties. """ title: Optional[Union[ GenericStringValue, List[GenericStringValue]]] = None abbrev: Optional[str] = None place: Optional[str] = None number: Optional[str] = None organization: Optional[str] = None run: Optional[str] = None partnumber: Optional[str] = None type: Optional[str] = 'main'
[docs]@dataclass class Contributor: """Anyone who helped create or publish the document.""" role: Union[List[str], str] person: Optional[Person] = None organization: Optional[Organization] = None
@dataclass class Edition: content: str number: Optional[str] = None @dataclass class VersionInfo: """Describes a version. Could be used for drafts.""" draft: Optional[str] = None """Draft version.""" # revdate: Optional[Union[str, datetime.date]] = None # """Revision date (format not clear)"""
[docs]class BibliographicItem(BaseModel, extra=Extra.allow): """ Relaton’s primary entity, bibliographic item. Note: formattedref is exclusive with other properties. In some contexts (such as relations) bibliographic item can be specified as a “pointer”, which callers can resolve to full metadata. formattedref is that pointer. It is expected to have a shape of a primary docid. """ # TODO: Don’t make all optional, use union types or something # if Relaton spec makes it clear which properties # are mandatory in absence of formattedref. formattedref: Optional[GenericStringValue] = None """References a bibliographic item via a primary ID. Exclusive with other properties. Tends to be used, for example, when this bibliographic item is used as :data:`.Relation.bibitem`. """ docid: Optional[Union[List[DocID], DocID]] = None docnumber: Optional[str] = None language: Optional[Union[List[str], str]] = None type: Optional[str] = None doctype: Optional[str] = None script: Optional[Union[List[str], str]] = None date: Optional[Union[List[Date], Date]] = None link: Optional[Union[List[Link], Link]] = None relation: 'Optional[List[Relation]]' = None version: Optional[VersionInfo] = None title: Optional[Union[List[Title], Title]] = None edition: Optional[Edition] = None abstract: Optional[Union[List[GenericStringValue], GenericStringValue]] = \ None fetched: Optional[datetime.date] = None revdate: Optional[Union[str, datetime.date, List[Union[str, datetime.date]]]] = None biblionote: Optional[Union[List[BiblioNote], BiblioNote]] = None contributor: Optional[List[Contributor]] = None place: Optional[Union[List[str], str]] = None series: Optional[List[Series]] = None keyword: Optional[Union[List[str], str]] = None copyright: Optional[Union[List[Copyright], Copyright]] = None
[docs] @validator('revdate', pre=True) def validate_revdate(cls, v, **kwargs): """Validates ``revdate``, allowing it to be unspecific.""" if isinstance(v, list): return [ validate_relaxed_date(i) for i in v if i ] return validate_relaxed_date(v, optional=True)
[docs]class Relation(BaseModel, extra=Extra.allow): """ Indicates a relationship from given bibliographic item to another. """ type: str """Describes the relationship.""" bibitem: BibliographicItem """Relationship target.""" description: Optional[GenericStringValue] """Describes the relationship in more detail."""
BibliographicItem.update_forward_refs()