summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTakeshi KOMIYA <i.tkomiya@gmail.com>2016-08-16 01:24:43 +0900
committerTakeshi KOMIYA <i.tkomiya@gmail.com>2016-08-16 01:38:20 +0900
commitd5a770b59280cd65d5bf4577f320cbd138ab22cc (patch)
tree590fce4e92701d895ece0229c732525d968b9486
parentb03b7e543f5e135d046d2fe407def219336c12b2 (diff)
downloadsphinx-git-d5a770b59280cd65d5bf4577f320cbd138ab22cc.tar.gz
std domain handles citations
-rw-r--r--sphinx/domains/std.py45
-rw-r--r--sphinx/environment.py45
-rw-r--r--sphinx/transforms.py2
-rw-r--r--tests/test_domain_std.py2
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']: