Comment utiliser Python pour générer par programmation une partie de la documentation Sphinx

J'utilise Sphinx pour générer la documentation d'un de mes projets.

Dans ce projet, je décris une liste de commandes disponibles dans un fichier yaml qui, une fois chargé, aboutit à un dictionnaire sous la forme {command-name : command-description} par exemple:

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

Ce que je voudrais savoir, c'est s'il y a une méthode dans sphinx pour charger le fichier yaml pendant le cycle make html, traduisez le dictionnaire python dans un formatreStructuredText (par exemple une définition list) et include dans ma sortie html.

Je m'attendrais à ce que mon fichier .rst ressemble à:

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

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

Et à convertir en interne en:

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

Avant d'être traduit en HTML.

22
demandé sur Mogsdad 2011-08-31 02:46:33

6 réponses

A la fin, je trouve un moyen de réaliser ce que je voulais. Voici le mode d'emploi:

  1. Créer un script python (appelons - generate-includes.py) qui permettra de générer de la reStructuredText et l'enregistrer dans le myrst.inc fichier. (Dans mon exemple, ce serait le script de chargement et d'analyse du YAML, mais ce n'est pas pertinent). assurez-vous que ce fichier est exécutable!!!
  2. Utilisez la directive include dans votre main .premier document de votre documentation, dans le point où vous voulez que votre documentation générée dynamiquement soit insérée:

    .. include:: myrst.inc
    
  3. Modifiez le Makefile sphinx afin de générer le nécessaire .fichiers inc au moment de la construction:

    myrst.inc:
        ./generate-includes.py
    
    html: myrst.inc
        ...(other stuff here)
    
  4. Construire votre documentation normalement avec make html.

21
répondu mac 2011-08-31 15:17:44

Une amélioration basée sur le code de Michael et la directive intégrée:

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)

Celui-ci importe la sortie plus tôt afin qu'elle passe directement à travers l'analyseur. Il fonctionne également en Python 3.

14
répondu alex.forencich 2013-08-09 09:14:48

J'avais besoin de la même chose, alors j'ai jeté une nouvelle directive qui semble fonctionner (Je ne sais rien des directives Sphinx personnalisées, mais cela a fonctionné jusqu'à présent):

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)

Il est utilisé comme suit:

.. exec::
   print "Python code!"
   print "This text will show up in the document"
8
répondu Michael Mrozek 2012-04-13 18:34:19

Sphinx n'a rien intégré pour faire ce que vous aimez. Vous pouvez créer une directive personnalisée pour traiter vos fichiers ou générer le reStructuredText dans une étape distincte et inclure le fichier reStructuredText résultant à l'aide de la directive include.

4
répondu devin_s 2011-08-31 00:08:58

Je sais que cette question est ancienne, mais peut-être que quelqu'un d'autre va le trouver utile.

Il semble que vous n'ayez pas besoin d'exécuter de code python, mais vous avez juste besoin de reformater le contenu de votre fichier. Dans ce cas, vous voudrez peut-être regarder sphinx-jinja (https://pypi.python.org/pypi/sphinx-jinja).

Vous pouvez charger votre fichier YAML dans le conf.py:

jinja_contexts = yaml.load(yourFileHere)

Ensuite, vous pouvez utiliser Jinja templating pour écrire le contenu et les traiter comme reST entrée.

2
répondu Peter 2016-05-17 13:57:26

Sphinx prend en charge les extensions personnalisées qui serait probablement la meilleure façon de le faire http://sphinx.pocoo.org/ext/tutorial.html.

0
répondu Matti Pastell 2011-10-08 06:17:22