diff options
author | Takeshi KOMIYA <i.tkomiya@gmail.com> | 2016-08-16 01:24:43 +0900 |
---|---|---|
committer | Takeshi KOMIYA <i.tkomiya@gmail.com> | 2016-08-16 01:38:20 +0900 |
commit | d5a770b59280cd65d5bf4577f320cbd138ab22cc (patch) | |
tree | 590fce4e92701d895ece0229c732525d968b9486 | |
parent | b03b7e543f5e135d046d2fe407def219336c12b2 (diff) | |
download | sphinx-git-d5a770b59280cd65d5bf4577f320cbd138ab22cc.tar.gz |
std domain handles citations
-rw-r--r-- | sphinx/domains/std.py | 45 | ||||
-rw-r--r-- | sphinx/environment.py | 45 | ||||
-rw-r--r-- | sphinx/transforms.py | 2 | ||||
-rw-r--r-- | tests/test_domain_std.py | 2 |
4 files changed, 50 insertions, 44 deletions
diff --git a/sphinx/domains/std.py b/sphinx/domains/std.py index 001d9f6d9..ca82bcdd2 100644 --- a/sphinx/domains/std.py +++ b/sphinx/domains/std.py @@ -466,6 +466,7 @@ class StandardDomain(Domain): initial_data = { 'progoptions': {}, # (program, name) -> docname, labelid 'objects': {}, # (type, name) -> docname, labelid + 'citations': {}, # name -> docname, labelid 'labels': { # labelname -> docname, labelid, sectionname 'genindex': ('genindex', '', l_('Index')), 'modindex': ('py-modindex', '', l_('Module Index')), @@ -485,6 +486,7 @@ class StandardDomain(Domain): 'numref': 'undefined label: %(target)s', 'keyword': 'unknown keyword: %(target)s', 'option': 'unknown option: %(target)s', + 'citation': 'citation not found: %(target)s', } enumerable_nodes = { # node_class -> (figtype, title_getter) @@ -500,6 +502,9 @@ class StandardDomain(Domain): for key, (fn, _l) in list(self.data['objects'].items()): if fn == docname: del self.data['objects'][key] + for key, (fn, _l) in list(self.data['citations'].items()): + if fn == docname: + del self.data['citations'][key] for key, (fn, _l, _l) in list(self.data['labels'].items()): if fn == docname: del self.data['labels'][key] @@ -515,6 +520,9 @@ class StandardDomain(Domain): for key, data in otherdata['objects'].items(): if data[0] in docnames: self.data['objects'][key] = data + for key, data in otherdata['citations'].items(): + if data[0] in docnames: + self.data['citations'][key] = data for key, data in otherdata['labels'].items(): if data[0] in docnames: self.data['labels'][key] = data @@ -523,6 +531,19 @@ class StandardDomain(Domain): self.data['anonlabels'][key] = data def process_doc(self, env, docname, document): + self.note_citations(env, docname, document) + self.note_labels(env, docname, document) + + def note_citations(self, env, docname, document): + for node in document.traverse(nodes.citation): + label = node[0].astext() + if label in self.data['citations']: + path = env.doc2path(self.data['citations'][0]) + env.warn_node('duplicate citation %s, other instance in %s' % + (label, path), node) + self.data['citations'][label] = (docname, node['ids'][0]) + + def note_labels(self, env, docname, document): labels, anonlabels = self.data['labels'], self.data['anonlabels'] for name, explicit in iteritems(document.nametypes): if not explicit: @@ -593,6 +614,8 @@ class StandardDomain(Domain): resolver = self._resolve_keyword_xref elif typ == 'option': resolver = self._resolve_option_xref + elif typ == 'citation': + resolver = self._resolve_citation_xref else: resolver = self._resolve_obj_xref @@ -683,6 +706,28 @@ class StandardDomain(Domain): return make_refnode(builder, fromdocname, docname, labelid, contnode) + def _resolve_citation_xref(self, env, fromdocname, builder, typ, target, node, contnode): + from sphinx.environment import NoUri + + docname, labelid = self.data['citations'].get(target, ('', '')) + if not docname: + if 'ids' in node: + # remove ids attribute that annotated at + # transforms.CitationReference.apply. + del node['ids'][:] + return None + + try: + return make_refnode(builder, fromdocname, docname, + labelid, contnode) + except NoUri: + # remove the ids we added in the CitationReferences + # transform since they can't be transfered to + # the contnode (if it's a Text node) + if not isinstance(contnode, nodes.Element): + del node['ids'][:] + raise + def _resolve_obj_xref(self, env, fromdocname, builder, typ, target, node, contnode): objtypes = self.objtypes_for_role(typ) or [] for objtype in objtypes: diff --git a/sphinx/environment.py b/sphinx/environment.py index e31ebea47..e3c29c298 100644 --- a/sphinx/environment.py +++ b/sphinx/environment.py @@ -38,7 +38,7 @@ from sphinx import addnodes from sphinx.io import SphinxStandaloneReader, SphinxDummyWriter, SphinxFileInput from sphinx.util import url_re, get_matching_docs, docname_join, split_into, \ FilenameUniqDict, split_index_msg -from sphinx.util.nodes import clean_astext, make_refnode, WarningStream, is_translatable +from sphinx.util.nodes import clean_astext, WarningStream, is_translatable from sphinx.util.osutil import SEP, getcwd, fs_encoding, ensuredir from sphinx.util.images import guess_mimetype from sphinx.util.i18n import find_catalog_files, get_image_filename_for_language, \ @@ -76,7 +76,7 @@ default_settings = { # or changed to properly invalidate pickle files. # # NOTE: increase base version by 2 to have distinct numbers for Py2 and 3 -ENV_VERSION = 49 + (sys.version_info[0] - 2) +ENV_VERSION = 50 + (sys.version_info[0] - 2) dummy_reporter = Reporter('', 4, 4) @@ -199,7 +199,6 @@ class BuildEnvironment: self.domaindata = {} # domainname -> domain-specific dict # Other inventories - self.citations = {} # citation name -> docname, labelid self.indexentries = {} # docname -> list of # (type, string, target, aliasname) self.versionchanges = {} # version -> list of (type, docname, @@ -276,9 +275,6 @@ class BuildEnvironment: fnset.discard(docname) if not fnset: del self.files_to_rebuild[subfn] - for key, (fn, _ignore) in list(self.citations.items()): - if fn == docname: - del self.citations[key] for version, changes in self.versionchanges.items(): new = [change for change in changes if change[1] != docname] changes[:] = new @@ -318,10 +314,6 @@ class BuildEnvironment: for subfn, fnset in other.files_to_rebuild.items(): self.files_to_rebuild.setdefault(subfn, set()).update(fnset & docnames) - for key, data in other.citations.items(): - # XXX duplicates? - if data[0] in docnames: - self.citations[key] = data for version, changes in other.versionchanges.items(): self.versionchanges.setdefault(version, []).extend( change for change in changes if change[1] in docnames) @@ -745,7 +737,6 @@ class BuildEnvironment: self.process_refonly_bullet_lists(docname, doctree) self.create_title_from(docname, doctree) self.note_indexentries_from(docname, doctree) - self.note_citations_from(docname, doctree) self.build_toc_from(docname, doctree) for domain in itervalues(self.domains): domain.process_doc(self, docname, doctree) @@ -1100,15 +1091,6 @@ class BuildEnvironment: else: entries.append(entry + (None,)) - def note_citations_from(self, docname, document): - for node in document.traverse(nodes.citation): - label = node[0].astext() - if label in self.citations: - self.warn_node('duplicate citation %s, ' % label + - 'other instance in %s' % self.doc2path( - self.citations[label][0]), node) - self.citations[label] = (docname, node['ids'][0]) - def note_toctree(self, docname, toctreenode): """Note a TOC tree directive in a document and gather information about file relations from it. @@ -1527,8 +1509,6 @@ class BuildEnvironment: newnode = self._resolve_any_reference(builder, refdoc, node, contnode) elif typ == 'doc': newnode = self._resolve_doc_reference(builder, refdoc, node, contnode) - elif typ == 'citation': - newnode = self._resolve_citation(builder, refdoc, node, contnode) # no new node found? try the missing-reference event if newnode is None: newnode = builder.app.emit_firstresult( @@ -1565,8 +1545,6 @@ class BuildEnvironment: msg = domain.dangling_warnings[typ] elif typ == 'doc': msg = 'unknown document: %(target)s' - elif typ == 'citation': - msg = 'citation not found: %(target)s' elif node.get('refdomain', 'std') not in ('', 'std'): msg = '%s:%s reference target not found: %%(target)s' % \ (node['refdomain'], typ) @@ -1591,25 +1569,6 @@ class BuildEnvironment: newnode.append(innernode) return newnode - def _resolve_citation(self, builder, fromdocname, node, contnode): - docname, labelid = self.citations.get(node['reftarget'], ('', '')) - if docname: - try: - newnode = make_refnode(builder, fromdocname, - docname, labelid, contnode) - return newnode - except NoUri: - # remove the ids we added in the CitationReferences - # transform since they can't be transfered to - # the contnode (if it's a Text node) - if not isinstance(contnode, nodes.Element): - del node['ids'][:] - raise - elif 'ids' in node: - # remove ids attribute that annotated at - # transforms.CitationReference.apply. - del node['ids'][:] - def _resolve_any_reference(self, builder, refdoc, node, contnode): """Resolve reference generated by the "any" role.""" target = node['reftarget'] diff --git a/sphinx/transforms.py b/sphinx/transforms.py index cb4a5779b..7b09285a4 100644 --- a/sphinx/transforms.py +++ b/sphinx/transforms.py @@ -140,7 +140,7 @@ class CitationReferences(Transform): def apply(self): for citnode in self.document.traverse(nodes.citation_reference): cittext = citnode.astext() - refnode = addnodes.pending_xref(cittext, reftype='citation', + refnode = addnodes.pending_xref(cittext, refdomain='std', reftype='citation', reftarget=cittext, refwarn=True, ids=citnode["ids"]) refnode.source = citnode.source or citnode.parent.source diff --git a/tests/test_domain_std.py b/tests/test_domain_std.py index 2d31ada2e..5bd9f805b 100644 --- a/tests/test_domain_std.py +++ b/tests/test_domain_std.py @@ -26,6 +26,7 @@ def test_process_doc_handle_figure_caption(): nameids={'testname': 'testid'}, ids={'testid': figure_node}, ) + document.traverse.return_value = [] domain = StandardDomain(env) if 'testname' in domain.data['labels']: @@ -47,6 +48,7 @@ def test_process_doc_handle_table_title(): nameids={'testname': 'testid'}, ids={'testid': table_node}, ) + document.traverse.return_value = [] domain = StandardDomain(env) if 'testname' in domain.data['labels']: |