summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGES2
-rw-r--r--doc/intro.rst3
-rw-r--r--sphinx/domains/python.py38
3 files changed, 30 insertions, 13 deletions
diff --git a/CHANGES b/CHANGES
index 1710c543..af0a3ef1 100644
--- a/CHANGES
+++ b/CHANGES
@@ -54,6 +54,8 @@ Features added
- The :rst:role:`ref` role can now also reference tables by caption.
- The :rst:dir:`include` directive now supports absolute paths, which
are interpreted as relative to the source directory.
+ - In the Python domain, references like ``:func:`.name``` now look for
+ matching names with any prefix if no direct match is found.
* Configuration:
diff --git a/doc/intro.rst b/doc/intro.rst
index 33f97a3f..33a89fa6 100644
--- a/doc/intro.rst
+++ b/doc/intro.rst
@@ -16,6 +16,9 @@ Though there is support for that kind of docs as well (which is intended to be
freely mixed with hand-written content), if you need pure API docs have a look
at `Epydoc <http://epydoc.sf.net/>`_, which also understands reST.
+.. function:: Sphinxy.add_domain()
+
+:func:`.add_domain`
Conversion from other systems
-----------------------------
diff --git a/sphinx/domains/python.py b/sphinx/domains/python.py
index b97b9b42..fc808699 100644
--- a/sphinx/domains/python.py
+++ b/sphinx/domains/python.py
@@ -547,7 +547,7 @@ class PythonDomain(Domain):
def find_obj(self, env, modname, classname, name, type, searchorder=0):
"""
Find a Python object for "name", perhaps using the given module and/or
- classname.
+ classname. Returns a list of (name, object entry) tuples.
"""
# skip parens
if name[-2:] == '()':
@@ -557,6 +557,7 @@ class PythonDomain(Domain):
return None, None
objects = self.data['objects']
+ matches = []
newname = None
if searchorder == 1:
@@ -567,6 +568,11 @@ class PythonDomain(Domain):
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)]
else:
if name in objects:
newname = name
@@ -585,14 +591,14 @@ class PythonDomain(Domain):
elif type in ('func', 'meth') and '.' not in name and \
'object.' + name in objects:
newname = 'object.' + name
- if newname is None:
- return None, None
- return newname, objects[newname]
+ if newname is not None:
+ matches.append((newname, objects[newname]))
+ return matches
def resolve_xref(self, env, fromdocname, builder,
- typ, target, node, contnode):
- if (typ == 'mod' or
- typ == 'obj' and target in self.data['modules']):
+ 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:
@@ -607,13 +613,19 @@ class PythonDomain(Domain):
modname = node.get('py:module')
clsname = node.get('py:class')
searchorder = node.hasattr('refspecific') and 1 or 0
- name, obj = self.find_obj(env, modname, clsname,
- target, typ, searchorder)
- if not obj:
+ matches = self.find_obj(env, modname, clsname, target,
+ type, searchorder)
+ if not matches:
return None
- else:
- return make_refnode(builder, fromdocname, obj[0], name,
- contnode, name)
+ 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)
def get_objects(self):
for modname, info in self.data['modules'].iteritems():