std domain handles citations

This commit is contained in:
Takeshi KOMIYA 2016-08-16 01:24:43 +09:00
parent b03b7e543f
commit d5a770b592
4 changed files with 50 additions and 44 deletions

View File

@ -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:

View File

@ -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']

View File

@ -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

View File

@ -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']: