Source code for yamdb.yamref

"""yamref ... BibTeX references for yamdb (Yet Another Materials Database)."""
import os
from importlib import resources as ir
import bibtexparser
from bibtexparser.customization import convert_to_unicode
from bibtexparser.bparser import BibTexParser
from yamdb.yamdb import get_file_digest

_db_cache = {}


[docs] class BibTexDB: """Provide the content of a BibTeX file to resolve references. Parameters ---------- fname : str Filename of the BibTeX database file. """ # this handling of formatting needs minimal effort but relies on # order preservation of python dicts, which is standard only from 3.7 on # # http://gandenberger.org/2018/03/10/ordered-dicts-vs-ordereddict/ # # "However, this situation is changing. Standard dict objects # preserve order in the reference (CPython) implementations of # Python 3.5 and 3.6, and this order-preserving property is # becoming a language feature in Python 3.7." # # _formats could as well be read from a yaml file # _formats = { 'article': { 'author': "%s ", 'year': "(%s) ", 'title': "%s. ", 'journal': "%s, ", 'volume': "%s, ", 'pages': "%s.", }, 'book': { 'author': "%s ", 'year': "(%s) ", 'title': "%s. ", 'publisher': "%s. ", 'address': "%s.", }, 'techreport': { 'author': "%s ", 'year': "(%s) ", 'title': "%s. ", 'number': "%s, ", 'institution': "%s.", }, 'phdthesis': { 'author': "%s ", 'year': "(%s) ", 'title': "%s. ", 'school': "PhD Thesis %s.", }, 'misc': { 'author': "%s ", 'year': "(%s) ", 'title': "%s. ", }, 'incollection': { 'author': "%s ", 'year': "(%s) ", 'title': "%s. ", 'booktitle': "In: %s. ", 'volume': "%s, ", 'pages': "%s.", } } def __init__(self, fname): """Load a BibTeX database file. Parameters ---------- fname : str Filename of the BibTeX database file. """ self._load_database(fname) def _format(self, refdict, field): """Format a field of a BibTeX entry for later use in the reference string. Parameters ---------- refdict : dictionary Entry/record in the BibTeX database corresponding to a cite key. field : str Field of the entry/record to be formatted, e.g. 'author'. Returns ------- str or None Formatted field of the entry/record. See Also -------- bibtexparser """ type_ = refdict['ENTRYTYPE'] if field in self._formats[type_].keys(): fieldstr = self._formats[type_][field] % refdict[field].rstrip('.') else: fieldstr = None return fieldstr
[docs] def get_unformatted_entry(self, key): """Get the unformatted BibTeX entry (dict) for cite key. Parameters ---------- key : str Citation key of the entry, e.g 'IidaGuthrie1988'. Returns ------- dict or None Unformatted entry/record corresponding to the BibTeX entry. See Also -------- bibtexparser """ if key in self.references.entries_dict.keys(): return self.references.entries_dict[key] else: return None
def _load_database(self, fname): """Parse BibTeX file into corresponding dictionary. Parameters ---------- fname : str Name of the BibTeX file to be parsed, e.g. 'references.bib'. See Also -------- bibtexparser """ with open(fname) as bibtex_file: parser = BibTexParser() parser.customization = convert_to_unicode self.references = bibtexparser.load(bibtex_file, parser=parser)
[docs] def get_entry(self, key): """Get the formatted BibTeX entry (string) for cite key. Parameters ---------- key : str Citation key of the entry, e.g 'IidaGuthrie1988'. Returns ------- str or None Formatted entry/record belonging to the cite key. See Also -------- bibtexparser """ refdict = self.get_unformatted_entry(key) if refdict is not None: entry = "" for field in self._formats[refdict['ENTRYTYPE']].keys(): fieldstr = None if field in refdict.keys(): fieldstr = self._format(refdict, field) # this is for books with editor but without author elif field == 'author': if 'editor' in refdict.keys(): refdict['author'] = refdict['editor'] fieldstr = self._format(refdict, field) if fieldstr is not None: entry += fieldstr else: entry = None return entry
[docs] def get_source_filename(self, key): """Get the filename of the pdf containing the cited paper. **Not meaningful for general use.** Parameters ---------- key : str Citation key of the entry, e.g 'IidaGuthrie1988'. Returns ------- str or None Filename of the cited paper. """ fname = None refdict = self.get_unformatted_entry(key) if refdict is not None: if 'file' in refdict.keys(): fname = refdict['file'] return fname
[docs] def get_references_from_db(db_file, key): """Get reference for key from db_file. Parameters ---------- db_file : str Name of the reference database BibTeX file, e.g. 'references.bib' key : str Citation key of the reference, e.g. 'IidaGuthrie1988'. Returns ------- str Reference corresponding to the supplied citation key. """ hash = get_file_digest(db_file) if hash in _db_cache.keys(): db = _db_cache[hash] else: db = BibTexDB(db_file) _db_cache[hash] = db return db.get_entry(key)
def _get_references_from_included_db(db_file, key): """Get reference for key from db_file supplied in yamdb/data. Parameters ---------- db_file : str Name of the reference database BibTeX file, typically 'references.bib' key : str Citation key of the reference, e.g. 'IidaGuthrie1988'. Returns ------- str Reference corresponding to the supplied citation key. """ fname = os.path.join(ir.files('yamdb'), 'data', db_file) return get_references_from_db(fname, key)
[docs] def get_from_references(key): """Get reference for key from the references.bib file included in yamdb/data. Parameters ---------- key : str Citation key of the reference, e.g. 'IidaGuthrie1988'. Returns ------- str Reference corresponding to the supplied citation key. """ return _get_references_from_included_db('references.bib', key)