Coverage for src / rendercv / schema / models / cv / entries / publication.py: 100%
32 statements
« prev ^ index » next coverage.py v7.13.4, created at 2026-03-25 13:49 +0000
« prev ^ index » next coverage.py v7.13.4, created at 2026-03-25 13:49 +0000
1import functools
2from typing import Self
4import pydantic
6from .bases.entry import BaseEntry
7from .bases.entry_with_date import BaseEntryWithDate
9url_validator = pydantic.TypeAdapter[pydantic.HttpUrl](pydantic.HttpUrl)
12class BasePublicationEntry(BaseEntry):
13 title: str = pydantic.Field(
14 examples=[
15 "Deep Learning for Computer Vision",
16 "Advances in Quantum Computing",
17 ],
18 )
19 authors: list[str] = pydantic.Field(
20 description="You can bold your name with **double asterisks**.",
21 examples=[["John Doe", "**Jane Smith**", "Bob Johnson"]],
22 )
23 summary: str | None = pydantic.Field(
24 default=None,
25 examples=["This paper presents a new method for computer vision."],
26 )
27 doi: str | None = pydantic.Field(
28 default=None,
29 description=(
30 "The DOI (Digital Object Identifier). If provided, it will be used as the"
31 " link instead of the URL."
32 ),
33 examples=["10.48550/arXiv.2310.03138"],
34 pattern=r"\b10\..*",
35 )
36 url: pydantic.HttpUrl | None = pydantic.Field(
37 default=None,
38 description="A URL link to the publication. Ignored if DOI is provided.",
39 )
40 journal: str | None = pydantic.Field(
41 default=None,
42 description="The journal, conference, or venue where it was published.",
43 examples=["Nature", "IEEE Conference on Computer Vision", "arXiv preprint"],
44 )
46 @pydantic.model_validator(mode="after")
47 def ignore_url_if_doi_is_given(self) -> Self:
48 """Prioritize DOI over custom URL when both provided.
50 Why:
51 DOI is canonical, stable identifier for publications. When provided,
52 ignore user's URL to ensure templates use official DOI link.
54 Returns:
55 Publication instance with url cleared if DOI exists.
56 """
57 doi_is_provided = self.doi is not None
59 if doi_is_provided:
60 self.url = None
62 return self
64 @pydantic.model_validator(mode="after")
65 def validate_doi_url(self) -> Self:
66 """Validate generated DOI URL is well-formed.
68 Why:
69 DOI URL generation from DOI string might produce invalid URLs.
70 Post-validation ensures generated URLs are valid.
72 Returns:
73 Validated publication instance.
74 """
75 if self.doi_url:
76 url_validator.validate_strings(self.doi_url)
78 return self
80 @functools.cached_property
81 def doi_url(self) -> str | None:
82 """Generate DOI URL from DOI identifier.
84 Why:
85 DOI identifiers need https://doi.org/ prefix for linking.
86 Property generates complete URL from DOI string.
88 Returns:
89 Complete DOI URL, or None if no DOI provided.
90 """
91 doi_is_provided = self.doi is not None
93 if doi_is_provided:
94 return f"https://doi.org/{self.doi}"
96 return None
99# This approach ensures PublicationEntryBase keys appear first in the key order:
100class PublicationEntry(BaseEntryWithDate, BasePublicationEntry):
101 pass