summaryrefslogtreecommitdiff
path: root/sphinx/domains/python.py
diff options
context:
space:
mode:
Diffstat (limited to 'sphinx/domains/python.py')
-rw-r--r--sphinx/domains/python.py94
1 files changed, 54 insertions, 40 deletions
diff --git a/sphinx/domains/python.py b/sphinx/domains/python.py
index fc808699..cd87bfbd 100644
--- a/sphinx/domains/python.py
+++ b/sphinx/domains/python.py
@@ -356,6 +356,9 @@ class PyModule(Directive):
env.domaindata['py']['modules'][modname] = \
(env.docname, self.options.get('synopsis', ''),
self.options.get('platform', ''), 'deprecated' in self.options)
+ # make a duplicate entry in 'objects' to facilitate searching for the
+ # module in PythonDomain.find_obj()
+ env.domaindata['py']['objects'][modname] = (env.docname, 'module')
targetnode = nodes.target('', '', ids=['module-' + modname], ismod=True)
self.state.document.note_explicit_target(targetnode)
ret = [targetnode]
@@ -544,7 +547,7 @@ class PythonDomain(Domain):
if fn == docname:
del self.data['modules'][modname]
- def find_obj(self, env, modname, classname, name, type, searchorder=0):
+ def find_obj(self, env, modname, classname, name, type, searchmode=0):
"""
Find a Python object for "name", perhaps using the given module and/or
classname. Returns a list of (name, object entry) tuples.
@@ -560,22 +563,31 @@ class PythonDomain(Domain):
matches = []
newname = None
- if searchorder == 1:
- if modname and classname and \
- modname + '.' + classname + '.' + name in objects:
- newname = modname + '.' + classname + '.' + name
- elif modname and modname + '.' + name in objects:
- newname = modname + '.' + name
- elif name in objects:
- newname = name
- else:
- # "fuzzy" searching mode
- searchname = '.' + name
- matches = [(name, objects[name]) for name in objects
- if name.endswith(searchname)]
+ if searchmode == 1:
+ objtypes = self.objtypes_for_role(type)
+ if modname and classname:
+ fullname = modname + '.' + classname + '.' + name
+ if fullname in objects and objects[fullname][1] in objtypes:
+ newname = fullname
+ if not newname:
+ if modname and modname + '.' + name in objects and \
+ objects[modname + '.' + name][1] in objtypes:
+ newname = modname + '.' + name
+ elif name in objects and objects[name][1] in objtypes:
+ newname = name
+ else:
+ # "fuzzy" searching mode
+ searchname = '.' + name
+ matches = [(name, objects[name]) for name in objects
+ if name.endswith(searchname)
+ and objects[name][1] in objtypes]
else:
+ # NOTE: searching for exact match, object type is not considered
if name in objects:
newname = name
+ elif type == 'mod':
+ # only exact matches allowed for modules
+ return []
elif classname and classname + '.' + name in objects:
newname = classname + '.' + name
elif modname and modname + '.' + name in objects:
@@ -597,33 +609,35 @@ class PythonDomain(Domain):
def resolve_xref(self, env, fromdocname, builder,
type, target, node, contnode):
- if (type == 'mod' or
- type == 'obj' and target in self.data['modules']):
- docname, synopsis, platform, deprecated = \
- self.data['modules'].get(target, ('','','', ''))
- if not docname:
- return None
- else:
- title = '%s%s%s' % ((platform and '(%s) ' % platform),
- synopsis,
- (deprecated and ' (deprecated)' or ''))
- return make_refnode(builder, fromdocname, docname,
- 'module-' + target, contnode, title)
+ modname = node.get('py:module')
+ clsname = node.get('py:class')
+ searchmode = node.hasattr('refspecific') and 1 or 0
+ matches = self.find_obj(env, modname, clsname, target,
+ type, searchmode)
+ if not matches:
+ return None
+ elif len(matches) > 1:
+ env.warn(fromdocname,
+ 'more than one target found for cross-reference '
+ '%r: %s' % (target,
+ ', '.join(match[0] for match in matches)),
+ node.line)
+ name, obj = matches[0]
+
+ if obj[1] == 'module':
+ # get additional info for modules
+ docname, synopsis, platform, deprecated = self.data['modules'][name]
+ assert docname == obj[0]
+ title = name
+ if synopsis:
+ title += ': ' + synopsis
+ if deprecated:
+ title += _(' (deprecated)')
+ if platform:
+ title += ' (' + platform + ')'
+ return make_refnode(builder, fromdocname, docname,
+ 'module-' + name, contnode, title)
else:
- modname = node.get('py:module')
- clsname = node.get('py:class')
- searchorder = node.hasattr('refspecific') and 1 or 0
- matches = self.find_obj(env, modname, clsname, target,
- type, searchorder)
- if not matches:
- return None
- elif len(matches) > 1:
- env.warn(fromdocname,
- 'more than one target found for cross-reference '
- '%r: %s' % (target,
- ', '.join(match[0] for match in matches)),
- node.line)
- name, obj = matches[0]
return make_refnode(builder, fromdocname, obj[0], name,
contnode, name)