Source code for sphinxcontrib.bibtex.bibfile

"""
    Classes and methods to work with bib files.

    .. autoclass:: BibFile
        :members:

    .. autofunction:: normpath_filename

    .. autofunction:: parse_bibfile

    .. autofunction:: process_bibfile

    .. autofunction:: get_bibliography_entry
"""

import os.path
from typing import NamedTuple, Dict, Optional

from pybtex.database.input import bibtex
from pybtex.database import BibliographyData, Entry
import sphinx.util
from sphinx.environment import BuildEnvironment


logger = sphinx.util.logging.getLogger(__name__)


[docs]class BibFile(NamedTuple): """Contains information about a parsed bib file.""" mtime: float #: modification time of bib file when last parsed data: BibliographyData #: parsed data from pybtex
[docs]def normpath_filename(env: BuildEnvironment, filename: str) -> str: """Return normalised path to *filename* for the given environment *env*.""" return os.path.normpath(env.relfn2path(filename.strip())[1])
[docs]def parse_bibfile(bibfilename: str, encoding: str) -> BibliographyData: """Parse *bibfilename* with given *encoding*, and return parsed data.""" parser = bibtex.Parser(encoding) logger.info("parsing bibtex file {0}... ".format(bibfilename), nonl=True) parser.parse_file(bibfilename) logger.info("parsed {0} entries" .format(len(parser.data.entries))) return parser.data
[docs]def process_bibfile(bibfiles: Dict[str, BibFile], bibfilename: str, encoding: str) -> None: """Check if *bibfiles* is still up to date. If not, parse *bibfilename* and store parsed data in *bibfiles*. """ try: mtime = os.path.getmtime(bibfilename) except OSError: logger.warning( "could not open bibtex file {0}.".format(bibfilename)) return # get cache and check if it is still up to date # if it is not up to date, parse the bibtex file # and store it in the cache logger.info("checking for {0} in bibtex cache... ".format(bibfilename), nonl=True) try: bibfile = bibfiles[bibfilename] except KeyError: logger.info("not found") bibfiles[bibfilename] = BibFile( mtime=mtime, data=parse_bibfile(bibfilename, encoding)) else: if mtime != bibfile.mtime: logger.info("out of date") bibfiles[bibfilename] = BibFile( mtime=mtime, data=parse_bibfile(bibfilename, encoding)) else: logger.info('up to date')
[docs]def get_bibliography_entry( bibfiles: Dict[str, BibFile], key: str) -> Optional[Entry]: """Return bibliography entry from *bibfiles* for the given *key*.""" for bibfile in bibfiles.values(): try: return bibfile.data.entries[key] except KeyError: pass else: logger.warning("could not find bibtex key {0}.".format(key)) return None