Python 如何将对象添加到Sphinx';s全局索引,还是按别名交叉引用?
每次我必须引用一个方法,而不是Python 如何将对象添加到Sphinx';s全局索引,还是按别名交叉引用?,python,python-sphinx,cross-reference,Python,Python Sphinx,Cross Reference,每次我必须引用一个方法,而不是:func:`package.subpackage.module.method`,特别是对于常用方法。是否有一种方法可以通过某种方式“注册”package.subpackage,这样只有module.method就足够了?(更好的是,package.subpackage.module,这样方法就足够了,假设没有冲突) 解决方案不应该包括向包或子包添加目录,但我可以向文档/添加任何内容。请注意,这里的问题涉及在docstring模块之外定义的方法(否则.method有
:func:`package.subpackage.module.method`
,特别是对于常用方法。是否有一种方法可以通过某种方式“注册”package.subpackage
,这样只有module.method
就足够了?(更好的是,package.subpackage.module
,这样方法就足够了,假设没有冲突)
解决方案不应该包括向包
或子包
添加目录,但我可以向文档/
添加任何内容。请注意,这里的问题涉及在docstring模块之外定义的方法(否则.method
有效)。从您看到类、函数或方法的那一刻起,您就可以在索引中省去名称的书写。
例如
不使用完全限定名称编写交叉引用:
:func:`~package.subpackage.module.method`
:meth:`~package.subpackage.module.method`
你可以简单地写:
:func:`.method`
:meth:`。方法`
请注意,如果要交叉引用本地范围之外的内容,则必须使用点
。例如,如果您正在编写交叉引用的类中引用属性或方法,则以下操作不起作用:
:meth:`method`
:attr:`方法`
还请注意,在范围:meth:
和:func:
中,这两种方法都可以互换工作。但是,在范围之外,您必须使用确切的角色,这取决于您是引用方法还是函数
请注意,您可能会发生名称冲突,因为相同的名称可用于不同对象的不同模块中。在这种情况下,您应该使用完全限定名来准确区分所引用的对象
检查索引以验证对象是否已插入其中非常重要(这由.rst
文件中的autodoc或domain指令自动完成)。普通索引将显示“对象名(完全限定名)”,如果它在索引中,则可以交叉引用
编辑:下面是一个变通方法,可以将方法
显示为类.方法
;以上信息适用
`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)
现在,所有引用:role:`foo.spam`
将替换为:role:`spam`
,而不考虑确切的角色(class
,func
,mod
,等等)。当然,这只是一个草稿,未经测试,但你应该了解这个想法。甚至可能是一个新的Sphinx扩展项目的良好起点:-)“因此,对于Sphinx中的交叉引用,没有“索引X为Y”的方法。使用这个,:meth:'X.Y'
看起来很有希望,“重命名”部分可以工作,但不能“重定目标”;没有超链接/交叉引用。我做到了:{'Class.method':('package.subpackage.module.Class.method','Class.method')}
-我认为这是预期用途。恐怕我对“草稿”做不了什么"由于我对docutils
&其余部分一无所知,但是如果你编辑一个工作代码,它将是我正在寻找的确切答案。链接用于实际项目、和的参考。@OverLordGoldDragon你是对的,这只是intersphinx引用解决方案的一部分——我误读了你的问题,出于某种原因考虑了intersphinx引用n、 我添加了一个用于解析内部引用的类似代码,方法基本相同;可以在单独的函数中提取重复的代码等。此外,如果不使用intersphinx,您可以安全地删除缺少引用事件的侦听器,只保留doctree read
一个。我将与您共享此-事实上,它应该是一个扩展,一旦是,我们会问“这怎么就不是一件事了”。@OverLordGoldDragon我不打算对我的conf.py
进行猴子补丁,原因有几个。首先,docutils没有完整的API规范(这一部分说:“todo”),我认为这是“放手”。然后,你破坏了信任,给试图阅读你的代码的人带来了一个不合理的问题。没有文档,理解reST和Sphinx就足够困难了。不能保证这不会破坏你的Sphinx,任何后续的错误或错误都会让你猜测是否是猴子补丁造成的。从工程角度来看,这是一个糟糕的做法。