如何使用Python以编程方式生成Sphinx文档的一部分?

发布于 2024-12-01 23:24:07 字数 1202 浏览 2 评论 0原文

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

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

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

我想知道的是,sphinx 中是否有一种方法可以在 make html< 期间加载 yaml 文件/code> 循环,翻译python字典一些reStructuredText格式(例如定义列表)并包含在我的 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 之前

I am using Sphinx to generate the documentation for a project of mine.

In this project, I describe a list of available commands in a yaml file which, once loaded, results in a dictionary in the form {command-name : command-description} for example:

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

What I would like to know, is if there is a method in sphinx to load the yaml file during the make html cycle, translate the python dictionary in some reStructuredText format (e.g. a definition list) and include in my html output.

I would expect my .rst file to look like:

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

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

and to be converted internally to:

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

before being translated to HTML.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

夏夜暖风 2024-12-08 23:24:07

最后我找到了一种方法来实现我想要的。操作方法如下:

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

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

    myrst.inc:
        ./生成-includes.py
    
    html: myrst.inc
        ...(这里还有其他东西)
    
  4. 使用 正常构建文档make html

At the end I find a way to achieve what I wanted. Here's the how-to:

  1. Create a python script (let's call it generate-includes.py) that will generate the reStructuredText and save it in the myrst.inc file. (In my example, this would be the script loading and parsing the YAML, but this is irrelevant). Make sure this file is executable!!!
  2. Use the include directive in your main .rst document of your documentation, in the point where you want your dynamically-generated documentation to be inserted:

    .. include:: myrst.inc
    
  3. Modify the sphinx Makefile in order to generate the required .inc files at build time:

    myrst.inc:
        ./generate-includes.py
    
    html: myrst.inc
        ...(other stuff here)
    
  4. Build your documentation normally with make html.

感情洁癖 2024-12-08 23:24:07

基于 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。

An improvement based on Michael's code and the built-in include directive:

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)

This one imports the output earlier so that it goes straight through the parser. It also works in Python 3.

小草泠泠 2024-12-08 23:24:07

我需要同样的东西,所以我组合了一个似乎有效的新指令(我对自定义 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"

I needed the same thing, so I threw together a new directive that seems to work (I know nothing about custom Sphinx directives, but it's worked so far):

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)

It's used as follows:

.. exec::
   print "Python code!"
   print "This text will show up in the document"
我很坚强 2024-12-08 23:24:07

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

Sphinx doesn't have anything built-in to do what you like. You can either create a custom directive to process your files or generate the reStructuredText in a separate step and include the resulting reStructuredText file using the include directive.

何以笙箫默 2024-12-08 23:24:07

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

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

您可以在 conf.py 中加载 YAML 文件:

jinja_contexts = yaml.load(yourFileHere)

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

I know this question is old, but maybe someone else will find it useful as well.

It sounds like you don't actually need to execute any python code, but you just need to reformat the contents of your file. In that case you might want to look at sphinx-jinja (https://pypi.python.org/pypi/sphinx-jinja).

You can load your YAML file in the conf.py:

jinja_contexts = yaml.load(yourFileHere)

Then you can use jinja templating to write out the contents and have them treated as reST input.

她比我温柔 2024-12-08 23:24:07

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

Sphinx does support custom extensions that would probably be the best way to do this http://sphinx.pocoo.org/ext/tutorial.html.

随梦而飞# 2024-12-08 23:24:07

Not quite the answer you're after, but perhaps a close approximation: yaml2rst. It's a converter from YAML to RST. Doesn't do anything explicitly fancy with the YAML itself, but looks for comment lines (starts with #) and pulls them out into RST chunks (with the YAML going into code-blocks). Allows for a sort-of literate YAML.

Also, the syntax-highlighted YAML is quite readable (heck, it's YAML, not JSON!).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文