28

我正在使用Sphinx为我的项目生成文档。

在这个项目中,我在一个yaml文件中描述了一个可用命令列表,一旦加载,就会生成一个字典,{command-name : command-description}例如:

commands = {"copy"  : "Copy the highlighted text in the clipboard",
            "paste" : "Paste the clipboard text to cursor location",
            ...}

我想知道的是,sphinx 中是否有一种方法可以在循环期间加载 yaml 文件,以某种reStructuredText格式(例如定义列表make html)翻译 python 字典并包含在我的 html 输出中。

我希望我的.rst文件看起来像:

Available commands
==================
The commands available in bla-bla-bla...

.. magic-directive-that-execute-python-code::
   :maybe python code or name of python file here:

并在内部转换为:

Available commands
==================
The commands available in bla-bla-bla...

copy
  Copy the highlighted text in the clipboard

paste
  Paste the clipboard text to cursor location

在被翻译成 HTML 之前。

4

6 回答 6

26

最后,我找到了实现我想要的方法。以下是操作方法:

  1. 创建一个 python 脚本(我们称之为generate-includes.py),它将生成reStructuredText并将其保存在myrst.inc文件中。(在我的示例中,这将是加载和解析 YAML 的脚本,但这无关紧要)。确保这个文件是可执行的!!!
  2. 在文档的主 .rst 文档中使用该include指令,在您希望插入动态生成的文档的位置:

    .. include:: myrst.inc
    
  3. 修改 sphinx Makefile以便在构建时生成所需的 .inc 文件:

    myrst.inc:
        ./generate-includes.py
    
    html: myrst.inc
        ...(other stuff here)
    
  4. 通常使用make html.

于 2011-08-31T15:17:44.243 回答
18

基于 Michael 的代码和内置 include 指令的改进:

import sys
from os.path import basename

try:
    from StringIO import StringIO
except ImportError:
    from io import StringIO

from docutils.parsers.rst import Directive    
from docutils import nodes, statemachine

class ExecDirective(Directive):
    """Execute the specified python code and insert the output into the document"""
    has_content = True

    def run(self):
        oldStdout, sys.stdout = sys.stdout, StringIO()

        tab_width = self.options.get('tab-width', self.state.document.settings.tab_width)
        source = self.state_machine.input_lines.source(self.lineno - self.state_machine.input_offset - 1)

        try:
            exec('\n'.join(self.content))
            text = sys.stdout.getvalue()
            lines = statemachine.string2lines(text, tab_width, convert_whitespace=True)
            self.state_machine.insert_input(lines, source)
            return []
        except Exception:
            return [nodes.error(None, nodes.paragraph(text = "Unable to execute python code at %s:%d:" % (basename(source), self.lineno)), nodes.paragraph(text = str(sys.exc_info()[1])))]
        finally:
            sys.stdout = oldStdout

def setup(app):
    app.add_directive('exec', ExecDirective)

这个更早地导入输出,以便它直接通过解析器。它也适用于 Python 3。

于 2013-08-09T09:14:48.847 回答
9

我需要同样的东西,所以我拼凑了一个似乎有效的新指令(我对自定义 Sphinx 指令一无所知,但到目前为止它已经有效):

import sys
from os.path import basename
from StringIO import StringIO

from sphinx.util.compat import Directive
from docutils import nodes

class ExecDirective(Directive):
    """Execute the specified python code and insert the output into the document"""
    has_content = True

    def run(self):
        oldStdout, sys.stdout = sys.stdout, StringIO()
        try:
            exec '\n'.join(self.content)
            return [nodes.paragraph(text = sys.stdout.getvalue())]
        except Exception, e:
            return [nodes.error(None, nodes.paragraph(text = "Unable to execute python code at %s:%d:" % (basename(self.src), self.srcline)), nodes.paragraph(text = str(e)))]
        finally:
            sys.stdout = oldStdout

def setup(app):
    app.add_directive('exec', ExecDirective)

它的用法如下:

.. exec::
   print "Python code!"
   print "This text will show up in the document"
于 2012-04-13T18:34:19.283 回答
4

Sphinx 没有内置任何东西来做你喜欢的事情。您可以创建自定义指令来处理文件或在单独的步骤中生成 reStructuredText 并使用 include 指令包含生成的 reStructuredText 文件。

于 2011-08-31T00:08:58.983 回答
3

我知道这个问题很老,但也许其他人也会觉得它有用。

听起来您实际上不需要执行任何 python 代码,但您只需要重新格式化文件的内容。在这种情况下,您可能想查看 sphinx-jinja ( https://pypi.python.org/pypi/sphinx-jinja )。

您可以在以下位置加载您的 YAML 文件conf.py

jinja_contexts = yaml.load(yourFileHere)

然后您可以使用 jinja 模板写出内容并将它们视为 reST 输入。

于 2016-05-17T13:57:26.480 回答
0

Sphinx 确实支持自定义扩展,这可能是执行此操作的最佳方式http://sphinx.pocoo.org/ext/tutorial.html

于 2011-10-08T06:17:22.873 回答