Add make_refnode() utility function.

This commit is contained in:
Georg Brandl 2009-07-13 18:27:34 +02:00
parent d4f957da8c
commit db8395f9e1
3 changed files with 58 additions and 69 deletions

View File

@ -15,6 +15,7 @@ import re
from sphinx import addnodes from sphinx import addnodes
from sphinx.roles import XRefRole from sphinx.roles import XRefRole
from sphinx.directives import DescDirective from sphinx.directives import DescDirective
from sphinx.util import make_refnode
class Domain(object): class Domain(object):
@ -50,7 +51,7 @@ class Domain(object):
inliner, options, content) inliner, options, content)
self._role_cache[name] = role_adapter self._role_cache[name] = role_adapter
return role_adapter return role_adapter
def directive(self, name): def directive(self, name):
""" """
Return a directive adapter class that always gives the registered Return a directive adapter class that always gives the registered
@ -384,8 +385,10 @@ class PythonDomain(Domain):
} }
def find_desc(self, env, modname, classname, name, type, searchorder=0): def find_desc(self, env, modname, classname, name, type, searchorder=0):
"""Find a description node matching "name", perhaps using """
the given module and/or classname.""" Find a Python object description for "name", perhaps using the given
module and/or classname.
"""
# skip parens # skip parens
if name[-2:] == '()': if name[-2:] == '()':
name = name[:-2] name = name[:-2]
@ -393,14 +396,6 @@ class PythonDomain(Domain):
if not name: if not name:
return None, None return None, None
# don't add module and class names for C things
if type[0] == 'c' and type not in ('class', 'const'):
# skip trailing star and whitespace
name = name.rstrip(' *')
if name in env.descrefs and env.descrefs[name][1][0] == 'c':
return name, env.descrefs[name]
return None, None
newname = None newname = None
if searchorder == 1: if searchorder == 1:
if modname and classname and \ if modname and classname and \
@ -432,28 +427,22 @@ class PythonDomain(Domain):
def resolve_xref(self, env, fromdocname, builder, def resolve_xref(self, env, fromdocname, builder,
typ, target, node, contnode): typ, target, node, contnode):
if (typ == 'mod' or
if typ == 'mod' or \ typ == 'obj' and target in env.modules):
typ == 'obj' and target in env.modules:
docname, synopsis, platform, deprecated = \ docname, synopsis, platform, deprecated = \
env.modules.get(target, ('','','', '')) env.modules.get(target, ('','','', ''))
if not docname: if not docname:
newnode = builder.app.emit_firstresult( return None
'missing-reference', env, node, contnode)
if not newnode:
newnode = contnode
elif docname == fromdocname: elif docname == fromdocname:
# don't link to self # don't link to self
newnode = contnode return contnode
else: else:
newnode = nodes.reference('', '') title = '%s%s%s' % ((platform and '(%s) ' % platform),
newnode['refuri'] = builder.get_relative_uri( synopsis,
fromdocname, docname) + '#module-' + target (deprecated and ' (deprecated)' or ''))
newnode['reftitle'] = '%s%s%s' % ( return make_refnode(builder, fromdocname, docname,
(platform and '(%s) ' % platform), 'module-' + target, contnode, title)
synopsis, (deprecated and ' (deprecated)' or '')) else:
newnode.append(contnode)
elif typ in env.descroles:
# "descrefs" # "descrefs"
modname = node['modname'] modname = node['modname']
clsname = node['classname'] clsname = node['classname']
@ -461,20 +450,10 @@ class PythonDomain(Domain):
name, desc = self.find_desc(env, modname, clsname, name, desc = self.find_desc(env, modname, clsname,
target, typ, searchorder) target, typ, searchorder)
if not desc: if not desc:
newnode = builder.app.emit_firstresult( return None
'missing-reference', env, node, contnode)
if not newnode:
newnode = contnode
else: else:
newnode = nodes.reference('', '') return make_refnode(builder, fromdocname, desc[0], name,
if desc[0] == fromdocname: contnode, name)
newnode['refid'] = name
else:
newnode['refuri'] = (
builder.get_relative_uri(fromdocname, desc[0])
+ '#' + name)
newnode['reftitle'] = name
newnode.append(contnode)
@ -620,6 +599,16 @@ class CDomain(Domain):
'type': XRefRole(), 'type': XRefRole(),
} }
def resolve_xref(self, env, fromdocname, builder,
typ, target, node, contnode):
# strip pointer asterisk
target = target.rstrip(' *')
# XXX descrefs
if target not in env.descrefs:
return None
desc = env.descrefs[target]
return make_refnode(builder, fromdocname, desc[0], contnode, target)
# this contains all registered domains # this contains all registered domains
all_domains = { all_domains = {

View File

@ -43,7 +43,7 @@ from docutils.transforms.parts import ContentsFilter
from sphinx import addnodes from sphinx import addnodes
from sphinx.util import movefile, get_matching_docs, SEP, ustrftime, \ from sphinx.util import movefile, get_matching_docs, SEP, ustrftime, \
docname_join, FilenameUniqDict, url_re docname_join, FilenameUniqDict, url_re, make_refnode
from sphinx.errors import SphinxError from sphinx.errors import SphinxError
from sphinx.directives import additional_xref_types from sphinx.directives import additional_xref_types
@ -1199,10 +1199,6 @@ class BuildEnvironment:
docname, refnode['refuri']) + refnode['anchorname'] docname, refnode['refuri']) + refnode['anchorname']
return newnode return newnode
descroles = frozenset(('data', 'exc', 'func', 'class', 'const',
'attr', 'obj', 'meth', 'cfunc', 'cmember',
'cdata', 'ctype', 'cmacro'))
def resolve_references(self, doctree, fromdocname, builder): def resolve_references(self, doctree, fromdocname, builder):
# XXX remove this # XXX remove this
reftarget_roles = set(('token', 'term', 'citation')) reftarget_roles = set(('token', 'term', 'citation'))
@ -1218,7 +1214,7 @@ class BuildEnvironment:
try: try:
if node.has_key('refdomain'): if node.has_key('refdomain'):
# let the domain resolve the reference # let the domain try to resolve the reference
try: try:
domain = builder.app.domains[node['refdomain']] domain = builder.app.domains[node['refdomain']]
except KeyError: except KeyError:
@ -1290,13 +1286,8 @@ class BuildEnvironment:
#self.warn(fromdocname, 'unknown keyword: %s' % target) #self.warn(fromdocname, 'unknown keyword: %s' % target)
newnode = contnode newnode = contnode
else: else:
newnode = nodes.reference('', '') newnode = make_refnode(builder, fromdocname, docname,
if docname == fromdocname: labelid, contnode)
newnode['refid'] = labelid
else:
newnode['refuri'] = builder.get_relative_uri(
fromdocname, docname) + '#' + labelid
newnode.append(contnode)
elif typ == 'option': elif typ == 'option':
progname = node['refprogram'] progname = node['refprogram']
docname, labelid = self.progoptions.get((progname, target), docname, labelid = self.progoptions.get((progname, target),
@ -1304,13 +1295,8 @@ class BuildEnvironment:
if not docname: if not docname:
newnode = contnode newnode = contnode
else: else:
newnode = nodes.reference('', '') newnode = make_refnode(builder, fromdocname, docname,
if docname == fromdocname: labelid, contnode)
newnode['refid'] = labelid
else:
newnode['refuri'] = builder.get_relative_uri(
fromdocname, docname) + '#' + labelid
newnode.append(contnode)
elif typ in reftarget_roles: elif typ in reftarget_roles:
docname, labelid = self.reftargets.get((typ, target), docname, labelid = self.reftargets.get((typ, target),
('', '')) ('', ''))
@ -1325,20 +1311,19 @@ class BuildEnvironment:
node.line) node.line)
newnode = contnode newnode = contnode
else: else:
newnode = nodes.reference('', '') newnode = make_refnode(builder, fromdocname, docname,
if docname == fromdocname: labelid, contnode)
newnode['refid'] = labelid
else:
newnode['refuri'] = builder.get_relative_uri(
fromdocname, docname, typ) + '#' + labelid
newnode.append(contnode)
else: else:
raise RuntimeError('unknown xfileref node encountered: %s' raise RuntimeError('unknown xfileref node encountered: %s'
% node) % node)
# no new node found? try the missing-reference event
if newnode is None:
newnode = builder.app.emit_firstresult(
'missing-reference', env, node, contnode)
except NoUri: except NoUri:
newnode = contnode newnode = contnode
if newnode: node.replace_self(newnode or contnode)
node.replace_self(newnode)
for node in doctree.traverse(addnodes.only): for node in doctree.traverse(addnodes.only):
try: try:

View File

@ -435,6 +435,21 @@ def split_explicit_title(text):
else: else:
return False, text, text return False, text, text
def make_refnode(builder, fromdocname, todocname, targetid, child, title=None):
"""Shortcut to create a reference node."""
node = nodes.reference('', '')
if fromdocname == todocname:
node['refid'] = targetid
else:
node['refuri'] = (builder.get_relative_uri(fromdocname, todocname)
+ '#' + targetid)
if title:
node['reftitle'] = title
node.append(child)
return node
# monkey-patch Node.traverse to get more speed # monkey-patch Node.traverse to get more speed
# traverse() is called so many times during a build that it saves # traverse() is called so many times during a build that it saves
# on average 20-25% overall build time! # on average 20-25% overall build time!