diff options
Diffstat (limited to 'sphinx/domains/python.py')
| -rw-r--r-- | sphinx/domains/python.py | 94 |
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) |
