9

次のような単純な 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 ライターが実行されるまで保持されないようです。

私は何を間違っていますか?

4

1 に答える 1

4

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'] = '?'

これにより、コンストラクターに渡された属性の明示的な値がデフォルトでオーバーライドされなくなります。他にもいくつかのバリエーションがあります。

于 2012-12-21T16:28:29.553 に答える