Each time I have to reference a method I rather not :func:`package.subpackage.module.method`, especially for frequently used methods. Is there a way to somehow "register" package.subpackage so that only module.method suffices? (Better yet, package.subpackage.module, so method suffices, assuming no conflicts).
A solution shouldn't involve adding directories to package or subpackage, but I'm fine adding whatever to docs/. Note that the problem here concerns a method defined outside of the docstring's module (otherwise .method works).
You could add a simple extension that will resolve the aliases you define. The below example is a short proof of concept for that:
# add this to conf.py
from sphinx.addnodes import pending_xref
from sphinx.ext.intersphinx import missing_reference
from docutils.nodes import Text
# alias ref is mapped to a pair (real ref, text to render)
reftarget_aliases = {
'foo.spam': ('foo.bar.baz.spam', 'spam'),
}
def resolve_intersphinx_aliases(app, env, node, contnode):
alias = node.get('reftarget', None)
if alias is not None and alias in reftarget_aliases:
real_ref, text_to_render = reftarget_aliases[alias]
# this will resolve the ref
node['reftarget'] = real_ref
# this will rewrite the rendered text:
# find the text node child
text_node = next(iter(contnode.traverse(lambda n: n.tagname == '#text')))
# remove the old text node, add new text node with custom text
text_node.parent.replace(text_node, Text(text_to_render, ''))
# delegate all the rest of dull work to intersphinx
return missing_reference(app, env, node, contnode)
def resolve_internal_aliases(app, doctree):
pending_xrefs = doctree.traverse(condition=pending_xref)
for node in pending_xrefs:
alias = node.get('reftarget', None)
if alias is not None and alias in reftarget_aliases:
real_ref, text_to_render = reftarget_aliases[alias]
# this will resolve the ref
node['reftarget'] = real_ref
# this will rewrite the rendered text:
# find the text node child
text_node = next(iter(node.traverse(lambda n: n.tagname == '#text')))
# remove the old text node, add new text node with custom text
text_node.parent.replace(text_node, Text(text_to_render, ''))
def setup(app):
app.connect('doctree-read', resolve_internal_aliases)
app.connect('missing-reference', resolve_intersphinx_aliases)
Now all refs :role:`foo.spam` will be replaced with :role:`spam <foo.bar.baz.spam>`, regardless of the exact role (class, func, mod, whatever). Sure, this is only a draft and untested, but you should get the idea. May be even a good starting point for a new Sphinx extension project :-)
From the moment you can see the class, function or method, in the index you can abreviate the writing of the name. For example, instead of writing the cross-reference with the fully qualified name:
:func:`~package.subpackage.module.method`
:meth:`~package.subpackage.module.method`
you can simply write:
:func:`.method`
:meth:`.method`
Notice the use of the dot . is necessary if you are cross-referencing something outside of your local scope. If, for example, you are referencing an attribute or method within the class where you write the cross-reference, then the following does work:
:meth:`method`
:attr:`method`
Notice also, that within the scope :meth: and :func: both work interchangeably. However, outside the scope you have to use the precise role, depending if you are referencing a method, or a function.
Be reminded you can have name collisions, since the same name can be used in different modules for different objects. In that case, you should use the fully qualified name to distinguish exactly which object you are referencing.
It's important to check the index to verify the object has already been inserted there (which is done automatically by the autodoc or domain directives in your .rst files). The normal index will display "object name (fully qualified name)", if it's in the index then it can be cross-referenced.
Edit: below's a workaround to show .method as class.method; info above applies.
`ClassName.`:meth:`.method`
![]()
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With