1010
1111import abc
1212import enum
13- from typing import List , Optional , Union
13+ from typing import Iterable , List , Optional , Union
1414
1515from pydantic import BaseModel
1616
1717from few .utils .exceptions import InvalidInputFile
1818
1919
20+ def _hyphen_replace (field : str ) -> str :
21+ return field .replace ("_" , "-" )
22+
23+
2024class HyphenUnderscoreAliasModel (BaseModel ):
2125 """Pydantic model were hyphen replace underscore in field names."""
2226
2327 class Config :
24- def hyphen_replace (field : str ) -> str :
25- return field .replace ("_" , "-" )
26-
27- alias_generator = hyphen_replace
28+ alias_generator = _hyphen_replace
2829 extra = "ignore"
2930 frozen = True
3031
@@ -74,7 +75,7 @@ class ArticleReference(ReferenceABC):
7475 abbreviation : str
7576 authors : List [Author ]
7677 title : str
77- journal : str
78+ journal : Optional [ str ] = None
7879 year : int
7980 month : Optional [int ] = None
8081 issue : Optional [int ] = None
@@ -97,6 +98,9 @@ def arxiv_preprint(self) -> Optional[ArxivIdentifier]:
9798 - The arXiv reference (e.g. "arxiv:1912.07609")
9899 - The primary class followed by '/' and the reference (e.g. "arxiv:gr-qc/1912.07609")
99100 """
101+ if self .identifiers is None :
102+ return None
103+
100104 for identifier in self .identifiers :
101105 if identifier .type != "other" :
102106 continue
@@ -134,7 +138,8 @@ def format_line(key: str, value: str, format: str = line_format) -> str:
134138 )
135139 )
136140 lines .append (format_line ("title" , "{" + self .title + "}" ))
137- lines .append (format_line ("journal" , self .journal ))
141+ if self .journal is not None :
142+ lines .append (format_line ("journal" , self .journal ))
138143 lines .append (format_line ("year" , str (self .year )))
139144 if self .month is not None :
140145 lines .append (format_line ("month" , str (self .month )))
@@ -181,6 +186,9 @@ class SoftwareReference(ReferenceABC):
181186 @property
182187 def doi (self ) -> Optional [str ]:
183188 """Return the first DOI in identifiers if any"""
189+ if self .identifiers is None :
190+ return None
191+
184192 for identifier in self .identifiers :
185193 if identifier .type == "doi" :
186194 return identifier .value
@@ -238,6 +246,7 @@ class REFERENCE(enum.Enum):
238246 AAK2 = "Chua:2017ujo"
239247 AK = "Barack:2003fp"
240248 FD = "Speri:2023jte"
249+ KERR_ECC_EQ = "Chapman-Bird:2025xtd"
241250
242251 def __str__ (self ) -> str :
243252 return str (self .value )
@@ -255,6 +264,9 @@ def get(self, key: Union[str, REFERENCE]) -> Reference:
255264 """Return a Reference object from its key."""
256265 return self .registry [key if isinstance (key , str ) else key .value ]
257266
267+ def all (self ) -> Iterable [Reference ]:
268+ return self .registry .values ()
269+
258270
259271def build_citation_registry () -> CitationRegistry :
260272 """Read the package CITATION.cff and build the corresponding registry."""
@@ -307,7 +319,12 @@ def to_reference(ref_dict) -> Reference:
307319 return CitationRegistry (** references , ** {cff ["title" ]: to_reference (cff )})
308320
309321
310- COMMON_REFERENCES = [REFERENCE .FEW , REFERENCE .LARGER_FEW , REFERENCE .FEW_SOFTWARE ]
322+ COMMON_REFERENCES = [
323+ REFERENCE .KERR_ECC_EQ ,
324+ REFERENCE .FEW ,
325+ REFERENCE .LARGER_FEW ,
326+ REFERENCE .FEW_SOFTWARE ,
327+ ]
311328
312329
313330class Citable :
@@ -320,18 +337,29 @@ def citation(cls) -> str:
320337 """Return the module references as a printable BibTeX string."""
321338 references = cls .module_references ()
322339
323- if Citable .registry is None :
324- from few import get_logger
340+ registry = cls ._get_registry ()
325341
326- get_logger ().debug ("Building the Citation Registry from CITATION.cff" )
327- Citable .registry = build_citation_registry ()
342+ bibtex_entries = [registry .get (str (key )).to_bibtex () for key in references ]
343+ return "\n \n " .join (bibtex_entries )
344+
345+ @classmethod
346+ def all_citations (cls ) -> str :
347+ """Return all the citations from the registry as printable BibTeX string"""
348+ registry = cls ._get_registry ()
328349
329- bibtex_entries = [
330- Citable .registry .get (str (key )).to_bibtex () for key in references
331- ]
350+ bibtex_entries = [entry .to_bibtex () for entry in registry .all ()]
332351 return "\n \n " .join (bibtex_entries )
333352
334353 @classmethod
335- def module_references (cls ) -> List [Union [REFERENCE , str ]]:
354+ def module_references (cls ) -> Iterable [Union [REFERENCE , str ]]:
336355 """Method implemented by each class to define its list of references"""
337356 return COMMON_REFERENCES
357+
358+ @classmethod
359+ def _get_registry (cls ) -> CitationRegistry :
360+ if Citable .registry is None :
361+ from few import get_logger
362+
363+ get_logger ().debug ("Building the Citation Registry from CITATION.cff" )
364+ Citable .registry = build_citation_registry ()
365+ return Citable .registry
0 commit comments