Подтвердить что ты не робот

Как использовать Python для программной генерации части документации Sphinx

Я использую 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 во время цикла make html, переведите словарь 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.

4b9b3361

Ответ 1

В конце я нахожу способ добиться того, чего хочу. Вот как это сделать:

  • Создайте python script (позвоните ему generate-includes.py), который сгенерирует reStructuredText и сохранит его в файле myrst.inc. (В моем примере это будет script загрузка и анализ YAML, но это не имеет значения). Убедитесь, что этот файл является исполняемым.
  • Используйте директиву include в основном документе .rst вашей документации в том месте, где вы хотите вставить вашу динамически создаваемую документацию:

    .. include:: myrst.inc
    
  • Измените файл makefile sphinx, чтобы сгенерировать требуемые файлы .inc во время сборки:

    myrst.inc:
        ./generate-includes.py
    
    html: myrst.inc
        ...(other stuff here)
    
  • Создайте свою документацию обычно с помощью make html.

Ответ 2

Улучшение, основанное на коде Михаэля и встроенной директиве include:

import sys
from os.path import basename

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

from sphinx.util.compat 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.

Ответ 3

Мне нужно было то же самое, поэтому я собрал новую директиву, которая, кажется, работает (я ничего не знаю о пользовательских директивах 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"

Ответ 4

Sphinx не имеет ничего встроенного, чтобы делать то, что вам нравится. Вы можете создать пользовательскую директиву для обработки ваших файлов или сгенерировать reStructuredText на отдельном шаге и включить результирующий файл reStructuredText с помощью директивы include.

Ответ 5

Я знаю, что этот вопрос старый, но, возможно, кто-то еще найдет его полезным.

Похоже, вам действительно не нужно выполнять какой-либо код на Python, но вам просто нужно переформатировать содержимое вашего файла. В этом случае вы можете посмотреть на sphinx-jinja (https://pypi.python.org/pypi/sphinx-jinja).

Вы можете загрузить свой файл YAML в conf.py:

jinja_contexts = yaml.load(yourFileHere)

Затем вы можете использовать jinja templating для записи содержимого и обработать их как вкладку reST.

Ответ 6

Sphinx поддерживает пользовательские расширения, которые, вероятно, будут лучшим способом сделать это http://sphinx.pocoo.org/ext/tutorial.html.