From 58de62d8beb931995ec8bf2677f1714dfa004719 Mon Sep 17 00:00:00 2001 From: Chris Johns Date: Wed, 9 Aug 2017 20:19:22 +1000 Subject: Revert "Add the sphinxcontrib.bibtex extension to the repo." This reverts commit aa4f8e2e436d6c49e1524a4a3fb164b28632d894. The contrib has too many dependencies to add into the repo. --- common/sphinxcontrib/__init__.py | 13 - common/sphinxcontrib/bibtex/__init__.py | 148 ----------- common/sphinxcontrib/bibtex/cache.py | 406 ------------------------------ common/sphinxcontrib/bibtex/directives.py | 221 ---------------- common/sphinxcontrib/bibtex/nodes.py | 17 -- common/sphinxcontrib/bibtex/roles.py | 43 ---- common/sphinxcontrib/bibtex/transforms.py | 127 ---------- common/waf.py | 1 + 8 files changed, 1 insertion(+), 975 deletions(-) delete mode 100644 common/sphinxcontrib/__init__.py delete mode 100644 common/sphinxcontrib/bibtex/__init__.py delete mode 100644 common/sphinxcontrib/bibtex/cache.py delete mode 100644 common/sphinxcontrib/bibtex/directives.py delete mode 100644 common/sphinxcontrib/bibtex/nodes.py delete mode 100644 common/sphinxcontrib/bibtex/roles.py delete mode 100644 common/sphinxcontrib/bibtex/transforms.py (limited to 'common') diff --git a/common/sphinxcontrib/__init__.py b/common/sphinxcontrib/__init__.py deleted file mode 100644 index 35d34fc..0000000 --- a/common/sphinxcontrib/__init__.py +++ /dev/null @@ -1,13 +0,0 @@ -# -*- coding: utf-8 -*- -""" - sphinxcontrib - ~~~~~~~~~~~~~ - - This package is a namespace package that contains all extensions - distributed in the ``sphinx-contrib`` distribution. - - :copyright: Copyright 2007-2009 by the Sphinx team, see AUTHORS. - :license: BSD, see LICENSE for details. -""" - -__import__('pkg_resources').declare_namespace(__name__) diff --git a/common/sphinxcontrib/bibtex/__init__.py b/common/sphinxcontrib/bibtex/__init__.py deleted file mode 100644 index d79e688..0000000 --- a/common/sphinxcontrib/bibtex/__init__.py +++ /dev/null @@ -1,148 +0,0 @@ -# -*- coding: utf-8 -*- -""" - Sphinx Interface - ~~~~~~~~~~~~~~~~ - - .. autofunction:: setup - .. autofunction:: init_bibtex_cache - .. autofunction:: purge_bibtex_cache - .. autofunction:: process_citations - .. autofunction:: process_citation_references - .. autofunction:: check_duplicate_labels -""" - -import docutils.nodes -import docutils.parsers.rst -from sphinxcontrib.bibtex.cache import Cache -from sphinxcontrib.bibtex.nodes import bibliography -from sphinxcontrib.bibtex.roles import CiteRole -from sphinxcontrib.bibtex.directives import BibliographyDirective -from sphinxcontrib.bibtex.transforms import BibliographyTransform -import six - - -def init_bibtex_cache(app): - """Create ``app.env.bibtex_cache`` if it does not exist yet. - - :param app: The sphinx application. - :type app: :class:`sphinx.application.Sphinx` - """ - if not hasattr(app.env, "bibtex_cache"): - app.env.bibtex_cache = Cache() - - -def purge_bibtex_cache(app, env, docname): - """Remove all information related to *docname* from the cache. - - :param app: The sphinx application. - :type app: :class:`sphinx.application.Sphinx` - :param env: The sphinx build environment. - :type env: :class:`sphinx.environment.BuildEnvironment` - """ - env.bibtex_cache.purge(docname) - - -def process_citations(app, doctree, docname): - """Replace labels of citation nodes by actual labels. - - :param app: The sphinx application. - :type app: :class:`sphinx.application.Sphinx` - :param doctree: The document tree. - :type doctree: :class:`docutils.nodes.document` - :param docname: The document name. - :type docname: :class:`str` - """ - for node in doctree.traverse(docutils.nodes.citation): - key = node[0].astext() - try: - label = app.env.bibtex_cache.get_label_from_key(key) - except KeyError: - app.warn("could not relabel citation [%s]" % key) - else: - node[0] = docutils.nodes.label('', label) - - -def process_citation_references(app, doctree, docname): - """Replace text of citation reference nodes by actual labels. - - :param app: The sphinx application. - :type app: :class:`sphinx.application.Sphinx` - :param doctree: The document tree. - :type doctree: :class:`docutils.nodes.document` - :param docname: The document name. - :type docname: :class:`str` - """ - # sphinx has already turned citation_reference nodes - # into reference nodes, so iterate over reference nodes - for node in doctree.traverse(docutils.nodes.reference): - # exclude sphinx [source] labels - if isinstance(node[0], docutils.nodes.Element): - if 'viewcode-link' in node[0]['classes']: - continue - text = node[0].astext() - if text.startswith('[') and text.endswith(']'): - key = text[1:-1] - try: - label = app.env.bibtex_cache.get_label_from_key(key) - except KeyError: - app.warn("could not relabel citation reference [%s]" % key) - else: - node[0] = docutils.nodes.Text('[' + label + ']') - - -def check_duplicate_labels(app, env): - """Check and warn about duplicate citation labels. - - :param app: The sphinx application. - :type app: :class:`sphinx.application.Sphinx` - :param env: The sphinx build environment. - :type env: :class:`sphinx.environment.BuildEnvironment` - """ - label_to_key = {} - for info in env.bibtex_cache.get_all_bibliography_caches(): - for key, label in six.iteritems(info.labels): - if label in label_to_key: - app.warn( - "duplicate label for keys %s and %s" - % (key, label_to_key[label])) - else: - label_to_key[label] = key - - -def setup(app): - """Set up the bibtex extension: - - * register config values - * register directives - * register nodes - * register roles - * register transforms - * connect events to functions - - :param app: The sphinx application. - :type app: :class:`sphinx.application.Sphinx` - """ - - app.add_config_value("bibtex_default_style", "alpha", "html") - app.connect("builder-inited", init_bibtex_cache) - app.connect("doctree-resolved", process_citations) - app.connect("doctree-resolved", process_citation_references) - app.connect("env-purge-doc", purge_bibtex_cache) - app.connect("env-updated", check_duplicate_labels) - - # docutils keeps state around during testing, so to avoid spurious - # warnings, we detect here whether the directives have already been - # registered... very ugly hack but no better solution so far - _directives = docutils.parsers.rst.directives._directives - if "bibliography" not in _directives: - app.add_directive("bibliography", BibliographyDirective) - app.add_role("cite", CiteRole()) - app.add_node(bibliography) - app.add_transform(BibliographyTransform) - else: - assert _directives["bibliography"] is BibliographyDirective - - # Parallel read is not safe at the moment: in the current design, - # the document that contains references must be read last for all - # references to be resolved. - return {'parallel_read_safe': False} diff --git a/common/sphinxcontrib/bibtex/cache.py b/common/sphinxcontrib/bibtex/cache.py deleted file mode 100644 index aa9064f..0000000 --- a/common/sphinxcontrib/bibtex/cache.py +++ /dev/null @@ -1,406 +0,0 @@ -# -*- coding: utf-8 -*- -""" - Cached Information - ~~~~~~~~~~~~~~~~~~ - - Classes and methods to maintain any information that is stored - outside the doctree. - - .. autoclass:: Cache - :members: - - .. autoclass:: BibfileCache - :members: - - .. autoclass:: BibliographyCache - :members: -""" - -import six -try: # pragma: no cover - from collections import OrderedDict -except ImportError: # pragma: no cover - from ordereddict import OrderedDict -import ast -import collections -import copy -from oset import oset -import re - - -def _raise_invalid_node(node): - """Helper method to raise an exception when an invalid node is - visited. - """ - raise ValueError("invalid node %s in filter expression" % node) - - -class _FilterVisitor(ast.NodeVisitor): - - """Visit the abstract syntax tree of a parsed filter expression.""" - - entry = None - """The bibliographic entry to which the filter must be applied.""" - - cited_docnames = False - """The documents where the entry is cited (empty if not cited).""" - - def __init__(self, entry, docname, cited_docnames): - self.entry = entry - self.docname = docname - self.cited_docnames = cited_docnames - - def visit_Module(self, node): - if len(node.body) != 1: - raise ValueError( - "filter expression cannot contain multiple expressions") - return self.visit(node.body[0]) - - def visit_Expr(self, node): - return self.visit(node.value) - - def visit_BoolOp(self, node): - outcomes = (self.visit(value) for value in node.values) - if isinstance(node.op, ast.And): - return all(outcomes) - elif isinstance(node.op, ast.Or): - return any(outcomes) - else: # pragma: no cover - # there are no other boolean operators - # so this code should never execute - assert False, "unexpected boolean operator %s" % node.op - - def visit_UnaryOp(self, node): - if isinstance(node.op, ast.Not): - return not self.visit(node.operand) - else: - _raise_invalid_node(node) - - def visit_BinOp(self, node): - left = self.visit(node.left) - op = node.op - right = self.visit(node.right) - if isinstance(op, ast.Mod): - # modulo operator is used for regular expression matching - if not isinstance(left, six.string_types): - raise ValueError( - "expected a string on left side of %s" % node.op) - if not isinstance(right, six.string_types): - raise ValueError( - "expected a string on right side of %s" % node.op) - return re.search(right, left, re.IGNORECASE) - elif isinstance(op, ast.BitOr): - return left | right - elif isinstance(op, ast.BitAnd): - return left & right - else: - _raise_invalid_node(node) - - def visit_Compare(self, node): - # keep it simple: binary comparators only - if len(node.ops) != 1: - raise ValueError("syntax for multiple comparators not supported") - left = self.visit(node.left) - op = node.ops[0] - right = self.visit(node.comparators[0]) - if isinstance(op, ast.Eq): - return left == right - elif isinstance(op, ast.NotEq): - return left != right - elif isinstance(op, ast.Lt): - return left < right - elif isinstance(op, ast.LtE): - return left <= right - elif isinstance(op, ast.Gt): - return left > right - elif isinstance(op, ast.GtE): - return left >= right - elif isinstance(op, ast.In): - return left in right - elif isinstance(op, ast.NotIn): - return left not in right - else: - # not used currently: ast.Is | ast.IsNot - _raise_invalid_node(op) - - def visit_Name(self, node): - """Calculate the value of the given identifier.""" - id_ = node.id - if id_ == 'type': - return self.entry.type.lower() - elif id_ == 'key': - return self.entry.key.lower() - elif id_ == 'cited': - return bool(self.cited_docnames) - elif id_ == 'docname': - return self.docname - elif id_ == 'docnames': - return self.cited_docnames - elif id_ == 'True': - return True - elif id_ == 'False': - return False - elif id_ == 'author' or id_ == 'editor': - if id_ in self.entry.persons: - return u' and '.join( - six.text_type(person) # XXX needs fix in pybtex? - for person in self.entry.persons[id_]) - else: - return u'' - else: - return self.entry.fields.get(id_, "") - - def visit_Set(self, node): - return frozenset(self.visit(elt) for elt in node.elts) - - def visit_Str(self, node): - return node.s - - # NameConstant is Python 3.4 only so do not insist on coverage - def visit_NameConstant(self, node): # pragma: no cover - return node.value - - def generic_visit(self, node): - _raise_invalid_node(node) - - -class Cache: - - """Global bibtex extension information cache. Stored in - ``app.env.bibtex_cache``, so must be picklable. - """ - - bibfiles = None - """A :class:`dict` mapping .bib file names (relative to the top - source folder) to :class:`BibfileCache` instances. - """ - - _bibliographies = None - """Each bibliography directive is assigned an id of the form - bibtex-bibliography-xxx. This :class:`dict` maps each docname - to another :class:`dict` which maps each id - to information about the bibliography directive, - :class:`BibliographyCache`. We need to store this extra - information separately because it cannot be stored in the - :class:`~sphinxcontrib.bibtex.nodes.bibliography` nodes - themselves. - """ - - _cited = None - """A :class:`dict` mapping each docname to a :class:`set` of - citation keys. - """ - - _enum_count = None - """A :class:`dict` mapping each docname to an :class:`int` - representing the current bibliography enumeration counter. - """ - - def __init__(self): - - self.bibfiles = {} - self._bibliographies = collections.defaultdict(dict) - self._cited = collections.defaultdict(oset) - self._enum_count = {} - - def purge(self, docname): - """Remove all information related to *docname*. - - :param docname: The document name. - :type docname: :class:`str` - """ - self._bibliographies.pop(docname, None) - self._cited.pop(docname, None) - self._enum_count.pop(docname, None) - - def inc_enum_count(self, docname): - """Increment enumeration list counter for document *docname*.""" - self._enum_count[docname] += 1 - - def set_enum_count(self, docname, value): - """Set enumeration list counter for document *docname* to *value*.""" - self._enum_count[docname] = value - - def get_enum_count(self, docname): - """Get enumeration list counter for document *docname*.""" - return self._enum_count[docname] - - def add_cited(self, key, docname): - """Add the given *key* to the set of cited keys for - *docname*. - - :param key: The citation key. - :type key: :class:`str` - :param docname: The document name. - :type docname: :class:`str` - """ - self._cited[docname].add(key) - - def get_cited_docnames(self, key): - """Return the *docnames* from which the given *key* is cited. - - :param key: The citation key. - :type key: :class:`str` - """ - return frozenset([ - docname for docname, keys in six.iteritems(self._cited) - if key in keys]) - - def get_label_from_key(self, key): - """Return label for the given key.""" - for bibcache in self.get_all_bibliography_caches(): - if key in bibcache.labels: - return bibcache.labels[key] - else: - raise KeyError("%s not found" % key) - - def get_all_cited_keys(self): - """Yield all citation keys, sorted first by document - (alphabetical), then by citation order in the document. - """ - for docname in sorted(self._cited): - for key in self._cited[docname]: - yield key - - def set_bibliography_cache(self, docname, id_, bibcache): - """Register *bibcache* (:class:`BibliographyCache`) - with id *id_* for document *docname*. - """ - assert id_ not in self._bibliographies[docname] - self._bibliographies[docname][id_] = bibcache - - def get_bibliography_cache(self, docname, id_): - """Return :class:`BibliographyCache` with id *id_* in - document *docname*. - """ - return self._bibliographies[docname][id_] - - def get_all_bibliography_caches(self): - """Return all bibliography caches.""" - for bibcaches in six.itervalues(self._bibliographies): - for bibcache in six.itervalues(bibcaches): - yield bibcache - - def _get_bibliography_entries(self, docname, id_, warn): - """Return filtered bibliography entries, sorted by occurence - in the bib file. - """ - # get the information of this bibliography node - bibcache = self.get_bibliography_cache(docname=docname, id_=id_) - # generate entries - for bibfile in bibcache.bibfiles: - data = self.bibfiles[bibfile].data - for entry in six.itervalues(data.entries): - # beware: the prefix is not stored in the data - # to allow reusing the data for multiple bibliographies - cited_docnames = self.get_cited_docnames( - bibcache.keyprefix + entry.key) - visitor = _FilterVisitor( - entry=entry, - docname=docname, - cited_docnames=cited_docnames) - try: - success = visitor.visit(bibcache.filter_) - except ValueError as err: - warn("syntax error in :filter: expression; %s" % err) - # recover by falling back to the default - success = bool(cited_docnames) - if success: - # entries are modified in an unpickable way - # when formatting, so fetch a deep copy - # and return this copy with prefixed key - # we do not deep copy entry.collection because that - # consumes enormous amounts of memory - entry.collection = None - entry2 = copy.deepcopy(entry) - entry2.key = bibcache.keyprefix + entry.key - entry2.collection = data - entry.collection = data - yield entry2 - - def get_bibliography_entries(self, docname, id_, warn): - """Return filtered bibliography entries, sorted by citation order.""" - # get entries, ordered by bib file occurrence - entries = OrderedDict( - (entry.key, entry) for entry in - self._get_bibliography_entries( - docname=docname, id_=id_, warn=warn)) - # order entries according to which were cited first - # first, we add all keys that were cited - # then, we add all remaining keys - sorted_entries = [] - for key in self.get_all_cited_keys(): - try: - entry = entries.pop(key) - except KeyError: - pass - else: - sorted_entries.append(entry) - sorted_entries += six.itervalues(entries) - return sorted_entries - - -class BibfileCache(collections.namedtuple('BibfileCache', 'mtime data')): - - """Contains information about a parsed .bib file. - - .. attribute:: mtime - - A :class:`float` representing the modification time of the .bib - file when it was last parsed. - - .. attribute:: data - - A :class:`pybtex.database.BibliographyData` containing the - parsed .bib file. - - """ - - -class BibliographyCache(collections.namedtuple( - 'BibliographyCache', - """bibfiles style encoding -list_ enumtype start labels labelprefix -filter_ curly_bracket_strip keyprefix -""")): - - """Contains information about a bibliography directive. - - .. attribute:: bibfiles - - A :class:`list` of :class:`str`\\ s containing the .bib file - names (relative to the top source folder) that contain the - references. - - .. attribute:: style - - The bibtex style. - - .. attribute:: list_ - - The list type. - - .. attribute:: enumtype - - The sequence type (only used for enumerated lists). - - .. attribute:: start - - The first ordinal of the sequence (only used for enumerated lists). - - .. attribute:: labels - - Maps citation keys to their final labels. - - .. attribute:: labelprefix - - This bibliography's string prefix for pybtex generated labels. - - .. attribute:: keyprefix - - This bibliography's string prefix for citation keys. - - .. attribute:: filter_ - - An :class:`ast.AST` node, containing the parsed filter expression. - """ diff --git a/common/sphinxcontrib/bibtex/directives.py b/common/sphinxcontrib/bibtex/directives.py deleted file mode 100644 index af8e9db..0000000 --- a/common/sphinxcontrib/bibtex/directives.py +++ /dev/null @@ -1,221 +0,0 @@ -""" - New Doctree Directives - ~~~~~~~~~~~~~~~~~~~~~~ - - .. autoclass:: BibliographyDirective - - .. automethod:: run - .. automethod:: process_bibfile - .. automethod:: update_bibfile_cache - .. automethod:: parse_bibfile - - .. autofunction:: process_start_option -""" - -import ast # parse(), used for filter -import os.path # getmtime() - -from docutils.parsers.rst import directives # for Directive.option_spec -from sphinx.util.compat import Directive -from sphinx.util.console import bold, standout - -from pybtex.database.input import bibtex -from pybtex.database import BibliographyData - -from sphinxcontrib.bibtex.cache import BibliographyCache, BibfileCache -from sphinxcontrib.bibtex.nodes import bibliography - -# register the latex codec -import latexcodec # noqa - - -def process_start_option(value): - """Process and validate the start option value - of a :rst:dir:`bibliography` directive. - If *value* is ``continue`` then this function returns -1, - otherwise *value* is converted into a positive integer. - """ - if value == "continue": - return -1 - else: - return directives.positive_int(value) - - -class BibliographyDirective(Directive): - - """Class for processing the :rst:dir:`bibliography` directive. - - Parses the bibliography files, and produces a - :class:`~sphinxcontrib.bibtex.nodes.bibliography` node. - - .. seealso:: - - Further processing of the resulting - :class:`~sphinxcontrib.bibtex.nodes.bibliography` node is done - by - :class:`~sphinxcontrib.bibtex.transforms.BibliographyTransform`. - """ - - required_arguments = 1 - optional_arguments = 0 - final_argument_whitespace = True - has_content = False - option_spec = { - 'cited': directives.flag, - 'notcited': directives.flag, - 'all': directives.flag, - 'filter': directives.unchanged, - 'style': directives.unchanged, - 'list': directives.unchanged, - 'enumtype': directives.unchanged, - 'start': process_start_option, - 'encoding': directives.encoding, - 'disable-curly-bracket-strip': directives.flag, - 'labelprefix': directives.unchanged, - 'keyprefix': directives.unchanged, - } - - def run(self): - """Process .bib files, set file dependencies, and create a - node that is to be transformed to the entries of the - bibliography. - """ - env = self.state.document.settings.env - # create id and cache for this node - # this id will be stored with the node - # and is used to look up additional data in env.bibtex_cache - # (implementation note: new_serialno only guarantees unique - # ids within a single document, but we need the id to be - # unique across all documents, so we also include the docname - # in the id) - id_ = 'bibtex-bibliography-%s-%s' % ( - env.docname, env.new_serialno('bibtex')) - if "filter" in self.options: - if "all" in self.options: - env.app.warn(standout(":filter: overrides :all:")) - if "notcited" in self.options: - env.app.warn(standout(":filter: overrides :notcited:")) - if "cited" in self.options: - env.app.warn(standout(":filter: overrides :cited:")) - try: - filter_ = ast.parse(self.options["filter"]) - except SyntaxError: - env.app.warn( - standout("syntax error in :filter: expression") + - " (" + self.options["filter"] + "); " - "the option will be ignored" - ) - filter_ = ast.parse("cited") - elif "all" in self.options: - filter_ = ast.parse("True") - elif "notcited" in self.options: - filter_ = ast.parse("not cited") - else: - # the default filter: include only cited entries - filter_ = ast.parse("cited") - bibcache = BibliographyCache( - list_=self.options.get("list", "citation"), - enumtype=self.options.get("enumtype", "arabic"), - start=self.options.get("start", 1), - style=self.options.get( - "style", env.app.config.bibtex_default_style), - filter_=filter_, - encoding=self.options.get( - 'encoding', - 'latex+' + self.state.document.settings.input_encoding), - curly_bracket_strip=( - 'disable-curly-bracket-strip' not in self.options), - labelprefix=self.options.get("labelprefix", ""), - keyprefix=self.options.get("keyprefix", ""), - labels={}, - bibfiles=[], - ) - if (bibcache.list_ not in set(["bullet", "enumerated", "citation"])): - env.app.warn( - "unknown bibliography list type '{0}'.".format(bibcache.list_)) - for bibfile in self.arguments[0].split(): - # convert to normalized absolute path to ensure that the same file - # only occurs once in the cache - bibfile = os.path.normpath(env.relfn2path(bibfile.strip())[1]) - self.process_bibfile(bibfile, bibcache.encoding) - env.note_dependency(bibfile) - bibcache.bibfiles.append(bibfile) - env.bibtex_cache.set_bibliography_cache(env.docname, id_, bibcache) - return [bibliography('', ids=[id_])] - - def parse_bibfile(self, bibfile, encoding): - """Parse *bibfile*, and return parsed data. - - :param bibfile: The bib file name. - :type bibfile: ``str`` - :return: The parsed bibliography data. - :rtype: :class:`pybtex.database.BibliographyData` - """ - app = self.state.document.settings.env.app - parser = bibtex.Parser(encoding) - app.info( - bold("parsing bibtex file {0}... ".format(bibfile)), nonl=True) - parser.parse_file(bibfile) - app.info("parsed {0} entries" - .format(len(parser.data.entries))) - return parser.data - - def update_bibfile_cache(self, bibfile, mtime, encoding): - """Parse *bibfile* (see :meth:`parse_bibfile`), and store the - parsed data, along with modification time *mtime*, in the - bibtex cache. - - :param bibfile: The bib file name. - :type bibfile: ``str`` - :param mtime: The bib file's modification time. - :type mtime: ``float`` - :return: The parsed bibliography data. - :rtype: :class:`pybtex.database.BibliographyData` - """ - data = self.parse_bibfile(bibfile, encoding) - env = self.state.document.settings.env - env.bibtex_cache.bibfiles[bibfile] = BibfileCache( - mtime=mtime, - data=data) - return data - - def process_bibfile(self, bibfile, encoding): - """Check if ``env.bibtex_cache.bibfiles[bibfile]`` is still - up to date. If not, parse the *bibfile* (see - :meth:`update_bibfile_cache`), and store parsed data in the - bibtex cache. - - :param bibfile: The bib file name. - :type bibfile: ``str`` - :return: The parsed bibliography data. - :rtype: :class:`pybtex.database.BibliographyData` - """ - env = self.state.document.settings.env - cache = env.bibtex_cache.bibfiles - # get modification time of bibfile - try: - mtime = os.path.getmtime(bibfile) - except OSError: - env.app.warn( - standout("could not open bibtex file {0}.".format(bibfile))) - cache[bibfile] = BibfileCache( # dummy cache - mtime=-float("inf"), data=BibliographyData()) - return cache[bibfile].data - # 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 - env.app.info( - bold("checking for {0} in bibtex cache... ".format(bibfile)), - nonl=True) - try: - bibfile_cache = cache[bibfile] - except KeyError: - env.app.info("not found") - self.update_bibfile_cache(bibfile, mtime, encoding) - else: - if mtime != bibfile_cache.mtime: - env.app.info("out of date") - self.update_bibfile_cache(bibfile, mtime, encoding) - else: - env.app.info('up to date') - return cache[bibfile].data diff --git a/common/sphinxcontrib/bibtex/nodes.py b/common/sphinxcontrib/bibtex/nodes.py deleted file mode 100644 index 426aed9..0000000 --- a/common/sphinxcontrib/bibtex/nodes.py +++ /dev/null @@ -1,17 +0,0 @@ -""" - New Doctree Nodes - ~~~~~~~~~~~~~~~~~ - - .. autoclass:: bibliography -""" - -from docutils import nodes - - -class bibliography(nodes.General, nodes.Element): - - """Node for representing a bibliography. Replaced by a list of - citations by - :class:`~sphinxcontrib.bibtex.transforms.BibliographyTransform`. - """ - pass diff --git a/common/sphinxcontrib/bibtex/roles.py b/common/sphinxcontrib/bibtex/roles.py deleted file mode 100644 index bbbd1f0..0000000 --- a/common/sphinxcontrib/bibtex/roles.py +++ /dev/null @@ -1,43 +0,0 @@ -""" - New Doctree Roles - ~~~~~~~~~~~~~~~~~ - - .. autoclass:: CiteRole - :show-inheritance: - - .. automethod:: result_nodes -""" - -from pybtex.plugin import find_plugin -import pybtex.database -from sphinx.roles import XRefRole # for :cite: - - -class CiteRole(XRefRole): - - """Class for processing the :rst:role:`cite` role.""" - backend = find_plugin('pybtex.backends', 'docutils')() - - def result_nodes(self, document, env, node, is_ref): - """Transform reference node into a citation reference, - and note that the reference was cited. - """ - keys = node['reftarget'].split(',') - # Note that at this point, usually, env.bibtex_cache.bibfiles - # is still empty because the bibliography directive may not - # have been processed yet, so we cannot get the actual entry. - # Instead, we simply fake an entry with the desired key, and - # fix the label at doctree-resolved time. This happens in - # process_citation_references. - refnodes = [ - self.backend.citation_reference(_fake_entry(key), document) - for key in keys] - for key in keys: - env.bibtex_cache.add_cited(key, env.docname) - return refnodes, [] - - -def _fake_entry(key): - entry = pybtex.database.Entry(type_="") - entry.key = key - return entry diff --git a/common/sphinxcontrib/bibtex/transforms.py b/common/sphinxcontrib/bibtex/transforms.py deleted file mode 100644 index 8e4cdcb..0000000 --- a/common/sphinxcontrib/bibtex/transforms.py +++ /dev/null @@ -1,127 +0,0 @@ -""" - New Doctree Transforms - ~~~~~~~~~~~~~~~~~~~~~~ - - .. autoclass:: BibliographyTransform - :show-inheritance: - - .. autoattribute:: default_priority - .. automethod:: apply - - .. autofunction:: node_text_transform - - .. autofunction:: transform_curly_bracket_strip - - .. autofunction:: transform_url_command -""" - -import docutils.nodes -import docutils.transforms - -from pybtex.plugin import find_plugin - -from sphinxcontrib.bibtex.nodes import bibliography - - -def node_text_transform(node, transform): - """Apply transformation to all Text nodes within node.""" - for child in node.children: - if isinstance(child, docutils.nodes.Text): - node.replace(child, transform(child)) - else: - node_text_transform(child, transform) - - -def transform_curly_bracket_strip(textnode): - """Strip curly brackets from text.""" - text = textnode.astext() - if '{' in text or '}' in text: - text = text.replace('{', '').replace('}', '') - return docutils.nodes.Text(text) - else: - return textnode - - -def transform_url_command(textnode): - """Convert '\\\\url{...}' into a proper docutils hyperlink.""" - text = textnode.astext() - if '\\url' in text: - text1, _, text = text.partition('\\url') - text2, _, text3 = text.partition('}') - text2 = text2.lstrip(' {') - ref = docutils.nodes.reference(refuri=text2) - ref += docutils.nodes.Text(text2) - node = docutils.nodes.inline() - node += transform_url_command(docutils.nodes.Text(text1)) - node += ref - node += transform_url_command(docutils.nodes.Text(text3)) - return node - else: - return textnode - - -class BibliographyTransform(docutils.transforms.Transform): - - """A docutils transform to generate citation entries for - bibliography nodes. - """ - - # transform must be applied before references are resolved - default_priority = 10 - """Priority of the transform. See - http://docutils.sourceforge.net/docs/ref/transforms.html - """ - - def apply(self): - """Transform each - :class:`~sphinxcontrib.bibtex.nodes.bibliography` node into a - list of citations. - """ - env = self.document.settings.env - docname = env.docname - for bibnode in self.document.traverse(bibliography): - id_ = bibnode['ids'][0] - bibcache = env.bibtex_cache.get_bibliography_cache( - docname=docname, id_=id_) - entries = env.bibtex_cache.get_bibliography_entries( - docname=docname, id_=id_, warn=env.app.warn) - # locate and instantiate style and backend plugins - style = find_plugin('pybtex.style.formatting', bibcache.style)() - backend = find_plugin('pybtex.backends', 'docutils')() - # create citation nodes for all references - if bibcache.list_ == "enumerated": - nodes = docutils.nodes.enumerated_list() - nodes['enumtype'] = bibcache.enumtype - if bibcache.start >= 1: - nodes['start'] = bibcache.start - env.bibtex_cache.set_enum_count( - env.docname, bibcache.start) - else: - nodes['start'] = env.bibtex_cache.get_enum_count( - env.docname) - elif bibcache.list_ == "bullet": - nodes = docutils.nodes.bullet_list() - else: # "citation" - nodes = docutils.nodes.paragraph() - # remind: style.format_entries modifies entries in unpickable way - for entry in style.format_entries(entries): - if bibcache.list_ in ["enumerated", "bullet"]: - citation = docutils.nodes.list_item() - citation += backend.paragraph(entry) - else: # "citation" - citation = backend.citation(entry, self.document) - # backend.citation(...) uses entry.key as citation label - # we change it to entry.label later onwards - # but we must note the entry.label now; - # at this point, we also already prefix the label - key = citation[0].astext() - bibcache.labels[key] = bibcache.labelprefix + entry.label - node_text_transform(citation, transform_url_command) - if bibcache.curly_bracket_strip: - node_text_transform( - citation, - transform_curly_bracket_strip) - nodes += citation - if bibcache.list_ == "enumerated": - env.bibtex_cache.inc_enum_count(env.docname) - bibnode.replace_self(nodes) diff --git a/common/waf.py b/common/waf.py index 3ee4435..7947829 100644 --- a/common/waf.py +++ b/common/waf.py @@ -206,6 +206,7 @@ def cmd_configure(ctx): check_sphinx_extension(ctx, 'sphinx.ext.graphviz') check_sphinx_extension(ctx, 'sphinx.ext.intersphinx') check_sphinx_extension(ctx, 'sphinx.ext.mathjax') + check_sphinx_extension(ctx, 'sphinxcontrib.bibtex') # # Optional builds. -- cgit v1.2.3