Source code for rs_files_templates.models.citation

"""Model for ``CITATION.cff``."""

from __future__ import annotations

from typing import Any

from rsm_schema.generated import Person, Publication

from .base import rsm_template_base
from .utils import (
    AUTHOR_ROLES,
    MAINTAINER_ROLES,
    contributors_with_roles,
    metadata_keywords,
    normalize_orcid,
    person_name,
    primary_affiliation,
)

_CitationRSM = rsm_template_base(
    "_CitationRSM",
    "project_name",
    "project_slug",
    "project_short_description",
    "project_long_description",
    "versioning",
    "urls",
    "contributors",
    "keywords",
    "topics",
    "persistent_identifiers",
    "publications",
)

CFF_SCHEMA_URL = "https://citation-file-format.github.io/1.2.0/schema.json"


[docs] class CitationModel(_CitationRSM): """Input model for ``CITATION.cff``.""" template_name = "CITATION.cff.j2" output_name = "CITATION.cff" schema_url = CFF_SCHEMA_URL media_type = "yaml" @staticmethod def _person(person: Person) -> dict[str, Any]: """Prepare one person for the CFF layout.""" structured = bool(person.family_names or person.given_names) result: dict[str, Any] = { "family_names": person.family_names or (person_name(person) if structured else None), "given_names": person.given_names, "name": None if structured else person_name(person), "affiliation": affiliation.name if (affiliation := primary_affiliation(person)) else None, "email": person.email, "orcid": f"https://orcid.org/{normalize_orcid(person.orcid)}" if person.orcid else None, "website": person.url, } return result @staticmethod def _publication_title(publication: Publication) -> str: """Choose the best available title for a CFF reference.""" return ( publication.title or publication.citation or (f"Publication {publication.doi}" if publication.doi else "") or (f"Publication {publication.url}" if publication.url else "") or (f"Publication PMID {publication.pmid}" if publication.pmid else "") or (f"Publication {publication.pmcid}" if publication.pmcid else "") or "Associated publication" ) def _publication(self, publication: Publication) -> dict[str, Any]: """Prepare one publication reference for CFF.""" requested = (publication.type or "article").lower().replace(" ", "-") cff_types = { "art", "article", "audiovisual", "bill", "blog", "book", "catalogue", "conference-paper", "conference", "data", "database", "dictionary", "edited-work", "encyclopedia", "film-broadcast", "generic", "government-document", "grant", "hearing", "historical-work", "legal-case", "legal-rule", "magazine-article", "manual", "map", "multimedia", "music", "newspaper-article", "pamphlet", "patent", "personal-communication", "proceedings", "report", "serial", "slides", "software-code", "software-container", "software-executable", "software-virtual-machine", "software", "sound-recording", "standard", "statute", "thesis", "unpublished", "video", "website", } result: dict[str, Any] = { "type": requested if requested in cff_types else "generic", "title": self._publication_title(publication), "authors": [self._person(author) for author in (publication.authors or [])], "doi": (publication.doi or "") .replace("https://doi.org/", "") .replace("http://dx.doi.org/", "") .replace("http://doi.org/", ""), "pmcid": publication.pmcid, "url": publication.url, "pmid": publication.pmid, "note": publication.note, } return result
[docs] def template_data(self) -> dict[str, Any]: """Prepare identifiers and references for the readable CFF template.""" identifiers = [] for identifier in self.persistent_identifiers.entries: item: dict[str, Any] = { "type": identifier.type if identifier.type in {"doi", "url", "swh"} else "other", "value": identifier.identifier, "description": None, } if identifier.associated_version: item["description"] = ( f"Persistent identifier for version {identifier.associated_version}" ) identifiers.append(item) publications = [ self._publication(publication) for publication in self.publications.entries if publication.authors ] preferred = next( ( self._publication(publication) for publication in self.publications.entries if publication.preferred and publication.authors ), None, ) return { "project_name": self.project_name or self.project_slug, "version": self.versioning.version or "0.1.0", "abstract": self.project_long_description or self.project_short_description, "repository_url": self.urls.repository, "url": self.urls.homepage or self.urls.documentation, "authors": [ self._person(author) for author in contributors_with_roles(self.contributors.entries, AUTHOR_ROLES) ], "maintainers": [ self._person(person) for person in contributors_with_roles(self.contributors.entries, MAINTAINER_ROLES) ], "keywords": metadata_keywords(self.keywords.entries, self.topics.entries), "identifiers": identifiers, "preferred_citation": preferred, "references": publications, }