如何将对象添加到 Sphinx 的全局索引,或通过别名进行交叉引用?
How to add objects to Sphinx's global index, or cross-reference by alias?
每次我不得不引用一个方法时,我宁愿不:func:`package.subpackage.module.method`
,尤其是对于经常使用的方法。有没有办法以某种方式 "register" package.subpackage
使得只有 module.method
就足够了? (更好的是,package.subpackage.module
,所以 method
就足够了,假设没有冲突)。
解决方案不应涉及向 package
或 subpackage
添加目录,但我可以向 docs/
添加任何内容。请注意,这里的问题涉及在文档字符串模块之外定义的 method
(否则 .method
有效)。
从你能看到class、函数或方法的那一刻起,在索引中你就可以省略名字的写法了。
例如,
而不是使用完全限定名称编写交叉引用:
:func:`~package.subpackage.module.method`
:meth:`~package.subpackage.module.method`
你可以简单地写:
:func:`.method`
:meth:`.method`
请注意,如果您要交叉引用本地范围之外的内容,则 使用点 .
是必要的。例如,如果您在编写交叉引用的 class 中引用属性或方法,则以下内容有效:
:meth:`method`
:attr:`method`
另请注意,在范围内 :meth:
和 :func:
两者可以互换使用。但是,在范围之外,您必须使用精确的角色,具体取决于您引用的是方法还是函数。
请注意,您可能会遇到名称冲突,因为相同的名称可能会在不同的模块中用于不同的对象。在那种情况下,您应该使用完全限定名称来准确区分您引用的是哪个对象。
重要的是检查索引以验证对象是否已插入(这是由 .rst
文件中的 autodoc 或域指令自动完成的)。正常索引会显示"object name (fully qualified name)",如果在索引中就可以交叉引用
编辑:下面是将 .method
显示为 class.method
的解决方法;以上信息适用。
`ClassName.`:meth:`.method`
您可以添加一个简单的扩展来解析您定义的别名。下面的例子是一个简短的概念证明:
# 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)
现在所有 refs :role:`foo.spam`
都将替换为 :role:`spam <foo.bar.baz.spam>`
,而不管确切的角色是什么(class
、func
、mod
,等等)。当然,这只是草稿且未经测试,但您应该明白了。甚至可能是新 Sphinx 扩展项目的良好起点:-)
每次我不得不引用一个方法时,我宁愿不:func:`package.subpackage.module.method`
,尤其是对于经常使用的方法。有没有办法以某种方式 "register" package.subpackage
使得只有 module.method
就足够了? (更好的是,package.subpackage.module
,所以 method
就足够了,假设没有冲突)。
解决方案不应涉及向 package
或 subpackage
添加目录,但我可以向 docs/
添加任何内容。请注意,这里的问题涉及在文档字符串模块之外定义的 method
(否则 .method
有效)。
从你能看到class、函数或方法的那一刻起,在索引中你就可以省略名字的写法了。 例如, 而不是使用完全限定名称编写交叉引用:
:func:`~package.subpackage.module.method`
:meth:`~package.subpackage.module.method`
你可以简单地写:
:func:`.method`
:meth:`.method`
请注意,如果您要交叉引用本地范围之外的内容,则 使用点 .
是必要的。例如,如果您在编写交叉引用的 class 中引用属性或方法,则以下内容有效:
:meth:`method`
:attr:`method`
另请注意,在范围内 :meth:
和 :func:
两者可以互换使用。但是,在范围之外,您必须使用精确的角色,具体取决于您引用的是方法还是函数。
请注意,您可能会遇到名称冲突,因为相同的名称可能会在不同的模块中用于不同的对象。在那种情况下,您应该使用完全限定名称来准确区分您引用的是哪个对象。
重要的是检查索引以验证对象是否已插入(这是由 .rst
文件中的 autodoc 或域指令自动完成的)。正常索引会显示"object name (fully qualified name)",如果在索引中就可以交叉引用
编辑:下面是将 .method
显示为 class.method
的解决方法;以上信息适用。
`ClassName.`:meth:`.method`
您可以添加一个简单的扩展来解析您定义的别名。下面的例子是一个简短的概念证明:
# 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)
现在所有 refs :role:`foo.spam`
都将替换为 :role:`spam <foo.bar.baz.spam>`
,而不管确切的角色是什么(class
、func
、mod
,等等)。当然,这只是草稿且未经测试,但您应该明白了。甚至可能是新 Sphinx 扩展项目的良好起点:-)