我有一个简单的Sphinx扩展如下:
from docutils import nodes
from docutils.parsers.rst import directives
from sphinx.util.compat import Directive
class testnode(nodes.Element):
def __init__(self, *args, **kwargs):
super(testnode, self).__init__(*args, **kwargs)
self['foo'] = '?'
def visit_testnode_latex(self, node):
self.body.append('Test: %s' % node['foo'])
def depart_testnode_latex(self, node):
pass
def visit_testnode_html(self, node):
self.body.append('<p>Test: %s</p>' % node['foo'])
def depart_testnode_html(self, node):
pass
class TestDirective(Directive):
has_content = False
required_arguments = 0
optional_arguments = 0
final_argument_whitespace = False
option_spec = {
'foo': directives.unchanged,
}
def run(self):
node = testnode()
node['foo'] = self.options.get('foo')
return [node]
def setup(app):
app.add_directive("testdirective", TestDirective)
app.add_node(testnode,
html=(visit_testnode_html,
depart_testnode_html),
latex=(visit_testnode_latex,
depart_testnode_latex))
给定一个包含
的文档.. testdirective::
:foo: bar
HTML输出包含»Test:bar«但LaTeX输出包含»Test:?«(默认值)。我在node['foo']
中分配后检查TestDirective.run()
是否具有正确的值,但在LaTeX编写器运行之前,这似乎没有。
我做错了什么?
答案 0 :(得分:3)
在单步执行Sphinx的LaTeX编写器之后,我发现了这个问题。这是您在'foo'
初始值设定项中为testnode
关键字设置默认值的方式。
LaTeX编写器中有一点是它对整个文档树进行深度复制,以便在另一棵树中内联它。 Element
节点上的深度复制初始化同一类的新节点,并通过构造函数传递原始节点的所有属性和内容。因此,当您的testnode
被复制时,您的构造函数会覆盖传递给构造函数的原始'foo'属性。而是像这样写它,它应该工作:
class testnode(nodes.Element):
def __init__(self, *args, **kwargs):
super(testnode, self).__init__(*args, **kwargs)
if 'foo' not in self:
self['foo'] = '?'
这将防止您的默认值覆盖已传递给构造函数的属性的任何显式值。还有其他几种变体。