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.
6 réponses
A la fin, je trouve un moyen de réaliser ce que je voulais. Voici le mode d'emploi:
-
Créer un script python (appelons -
generate-includes.py
) qui permettra de générer de la reStructuredText et l'enregistrer dans lemyrst.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!!! -
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
-
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)
Construire votre documentation normalement avec
make html
.
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.
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"
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.
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.
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.