Sphinx¶
Sphinx est un outil écrit en python permettant la génération de documentation à partir de source écrit en RestructuredText.
le format de sortie peut être:
- latex
- html
- html help windows
- ebook / epub
- text
- doctest
- man
Installation / Premier pas¶
Pour installer sphinx il faut:
puis lancer la commande
easy_install -U Sphinx
Sous Debian il suffit d’installer pip
apt-get install python-pip
pip install sphinx
Pour créer un nouveau projet rien de plus simple, créer un dossier contenant votre futur projet. Dans ce dossier lancer la commande suivante
sphinx-quickstart
cela va créer:
- arborescence nécessaire au projet
- le fichier de configuration conf.py
- un buildeur du type make.bat
pour transformer vos sources en html rien de plus simple
make.bat html
ou
sphinx-build -b html sourcedir builddir
Themes et Plugins¶
Sphinx accepte de nombreux themes et plugins que vous retrouver respectivement dans le répertoire themes et ext.
les plugins ou extensions très utiles sont:
- sphinx.ext.todo
- sphinx.ext.graphviz
- sphinx.ext.dotplus
- sphinx.ext.sphinxgooglechart
- sphinxcontrib.aafig
Pour le plugins sphinxcontrib.aafig il faut pour l’installer
pip install sphinxcontrib-aafig
puis dans son fichier conf.py rajouter l’extension
extensions = ['sphinxcontrib.aafig']
et enfin si besoin modifier le fichier sphinxcontrib/aafig.py en ajoutant
from docutils.parsers.rst import directives
#ADD BY FAO
from docutils.parsers.rst.directives import images
#END ADD BY FAO
ce plugin permet de générer des schéma via une description ASCII
premier exemple
.. aafig::
:textual:
+-------+ +-----------+
| Hello +-------->+ aafigure! |
+-------+ +-----------+
deuxième exemple
.. aafig::
:textual:
+---------+ +---------+ +---------+
| Shape | | Line | | Point |
+---------+ +---------+ 2 +---------+
| draw +<--------+ start +----O+ x |
| move +<-+ | end | | y |
+---------+ \ +---------+ +---------+
\
\ +---------+
+--+ Circle |
+---------+
| center |
| radius |
+---------+
Note
si vous souhaitez avec aafigure générer des images png ou jpg il faut installer PIL via
pip uninstall pil
pil install Pillow
un excellent thème est https://github.com/snide/sphinx_rtd_theme
On peut ajouter dans le fichier breadcrumbs.html de ce theme sous le bloc display_bitbucket les éléments suivant
{% elif show_source and has_source and sourcename %}
<a href="{{ pathto('_sources/' + sourcename, true)|e }}" rel="nofollow" class="fa fa-code"></a>
{% endif %}
<a href="javascript:window.print()" class="fa fa-print"></a>
<a href="./Codiad" target="_blank" class="fa fa-edit"></a>
au lieu de
{% elif show_source and has_source and sourcename %}
<a href="{{ pathto('_sources/' + sourcename, true)|e }}" rel="nofollow">Edit</a>
{% endif %}
Utilisation de flasksphinx¶
Il est possible d’utiliser le module perso flask-sphinx qui permet de maintenir un site sphinx via un navigateur.
Installation¶
l’installation du minimum
apt-get install python-pip
pip install flask
pip install flask-login
pip install flasksphinx
ln -s /usr/local/lib/python2.7/dist-packages/flasksphinx/themes/rtdflask /usr/local/lib/python2.7/dist-packages/sphinx/themes/rtdflask
on génère des dossiers pour notre application
mkdir /var/www/mysite
mkdir /var/www/mydoc
cd /var/www/mydoc
sphinx-quickstart
Welcome to the Sphinx 1.3b1 quickstart utility.
Please enter values for the following settings (just press Enter to
accept a default value, if one is given in brackets).
Enter the root path for documentation.
> Root path for the documentation [.]:
You have two options for placing the build directory for Sphinx output.
Either, you use a directory "_build" within the root path, or you separate
"source" and "build" directories within the root path.
> Separate source and build directories (y/n) [n]: y
Inside the root directory, two more directories will be created; "_templates"
for custom HTML templates and "_static" for custom stylesheets and other static
files. You can enter another prefix (such as ".") to replace the underscore.
> Name prefix for templates and static dir [_]:
The project name will occur in several places in the built documentation.
> Project name: mydoc
> Author name(s): Frédéric Aoustin
Sphinx has the notion of a "version" and a "release" for the
software. Each version can have multiple releases. For example, for
Python the version is something like 2.5 or 3.0, while the release is
something like 2.5.1 or 3.0a1. If you don't need this dual structure,
just set both to the same value.
> Project version: 1
> Project release [1]: 0
If the documents are to be written in a language other than English,
you can select a language here by its language code. Sphinx will then
translate text that it generates into that language.
For a list of supported codes, see
http://sphinx-doc.org/config.html#confval-language.
> Project language [en]: fr
The file name suffix for source files. Commonly, this is either ".txt"
or ".rst". Only files with this suffix are considered documents.
> Source file suffix [.rst]:
One document is special in that it is considered the top node of the
"contents tree", that is, it is the root of the hierarchical structure
of the documents. Normally, this is "index", but if your "index"
document is a custom template, you can also set this to another filename.
> Name of your master document (without suffix) [index]:
Sphinx can also add configuration for epub output:
> Do you want to use the epub builder (y/n) [n]:
Please indicate if you want to use one of the following Sphinx extensions:
> autodoc: automatically insert docstrings from modules (y/n) [n]:
> doctest: automatically test code snippets in doctest blocks (y/n) [n]:
> intersphinx: link between Sphinx documentation of different projects (y/n) [n]:
> todo: write "todo" entries that can be shown or hidden on build (y/n) [n]:
> coverage: checks for documentation coverage (y/n) [n]:
> pngmath: include math, rendered as PNG images (y/n) [n]:
> mathjax: include math, rendered in the browser by MathJax (y/n) [n]:
> ifconfig: conditional inclusion of content based on config values (y/n) [n]:
> viewcode: include links to the source code of documented Python objects (y/n) [n]:
A Makefile and a Windows command file can be generated for you so that you
only have to run e.g. `make html' instead of invoking sphinx-build
directly.
> Create Makefile? (y/n) [y]:
> Create Windows command file? (y/n) [y]: n
Creating file ./source/conf.py.
Creating file ./source/index.rst.
Creating file ./Makefile.
Finished: An initial directory structure has been created.
You should now populate your master file ./source/index.rst and create other documentation
source files. Use the Makefile to build the docs, like so:
make builder
where "builder" is one of the supported builders, e.g. html, latex or linkcheck.cd
mkdir /var/www/mydoc/build
mkdir /var/www/mydoc/source/data
vi /var/www/mydoc/source/conf.py
extensions = ['sphinxcontrib.aafig','flasksphinx.todo']
# html_theme = "default"
html_theme = "rtdflask"
chmod -r 777 /var/www/mydoc
sphinx-build -b html /var/www/mydoc/source/ /var/www/mydoc/build/html/
mkdir /var/www/mydoc/wsgi-scripts
vi /var/www/mydoc/wsgi-scripts/myapp.wsgi
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys
import os, os.path
import logging, logging.handlers
from flask import Flask
import flasksphinx
app = Flask(__name__)
app.config.from_pyfile(os.path.splitext(__file__)[0]+'.cfg')
flasksphinx.init(app)
#for mod wsgi
application = app
if __name__ == "__main__":
handler = logging.StreamHandler()
handler.setLevel(app.config['LEVEL'])
app.logger.addHandler(handler)
handler = logging.handlers.RotatingFileHandler(os.path.splitext(__file__)[0]+'.log', maxBytes=2000000, backupCount=5)
handler.setLevel(app.config['LEVEL'])
app.logger.addHandler(handler)
app.run(host = app.config['HOST'],
port = app.config['PORT'])
chmod +x /var/www/mydoc/wsgi-scripts/myapp.wsgi
vi /var/www/mydoc/wsgi-scripts/myapp.conf
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import os
import logging
DEBUG = True
SPHINX_BUILD_DIR = '/var/www/mydoc/build'
SPHINX_CONF_DIR = '/var/www/mydoc/source'
UPLOAD_FOLDER = '/var/www/mydoc/source/data'
PORT = 5001
HOST = '0.0.0.0'
LEVEL = logging.DEBUG
SECRET_KEY = 'secret_key'
USERS = [
{ 'id' : 1,
'username' : 'admin',
'password' : 'keyadmin'
}
]
En ajoutant l’extension flasksphinx.todo il est possible de faire des listes à cocher
:x:`todo check`
:o:`todo no check`
Utilisation StandAlone¶
L’utilisation standAlone est assez simple
cd /var/www/mydoc/wsgi-scripts/
python myapp.wsgi
On a maintenant accès à notre application via http://localhost:5001/
Il est aussi possible de transformer notre application flask en service linux
Pour cela
cp /etc/init.d/skeleton /etc/init.d/mydoc
chmod +x /etc/init.d/mydoc
vi /etc/init.d/mydoc
...
PATH=/sbin:/usr/sbin:/bin:/usr/bin
DESC="flasksphinx for mydoc"
NAME=myapp.wsgi
DAEMON=/var/www/mydoc/wsgi-scripts/$NAME
DAEMON_ARGS=""
PIDFILE=/var/run/$NAME.pid
SCRIPTNAME=/etc/init.d/$NAME
...
do_start()
{
# Return
# 0 if daemon has been started
# 1 if daemon was already running
# 2 if daemon could not be started
start-stop-daemon --start --quiet --background --make-pidfile --pidfile $PIDFILE --exec $DAEMON --test > /dev/null \
|| return 1
start-stop-daemon --start --quiet --background --make-pidfile --pidfile $PIDFILE --exec $DAEMON -- \
$DAEMON_ARGS \
|| return 2
# Add code here, if necessary, that waits for the process to be ready
# to handle requests from services started subsequently which depend
# on this one. As a last resort, sleep for some time.
}
...
do_stop()
{
# Return
# 0 if daemon has been stopped
# 1 if daemon was already stopped
# 2 if daemon could not be stopped
# other if a failure occurred
start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile $PIDFILE
RETVAL="$?"
[ "$RETVAL" = 2 ] && return 2
# Wait for children to finish too if this is a daemon that forks
# and if the daemon is only ever run from this initscript.
# If the above conditions are not satisfied then add some other code
# that waits for the process to drop all resources that could be
# needed by services started subsequently. A last resort is to
# sleep for some time.
start-stop-daemon --stop --quiet --oknodo --retry=0/30/KILL/5 --exec $DAEMON
[ "$?" = 2 ] && return 2
# Many daemons don't delete their pidfiles when they exit.
rm -f $PIDFILE
return "$RETVAL"
}
...
on lance notre service
/etc/init.d/mydoc start
on a maintenant accès à notre application via le http://127.0.0.1:5001/
on peut installer notre service pour qu’il démarre automatiquement
update-rc.d mydoc defaults 99
Intégration dans Apache avec mod_python¶
On ajoute à l’installation minimum
apt-get install apache2 libapache2-mod-wsgi python-dev
mkdir /var/www/mysite
cd /var/www/mysite
echo "<html>hello mysite</html>" > index.html
et on edit le fichier conf du site dans /etc/apache2/site-enabled
<VirtualHost *:80>
ServerAdmin webmaster@localhost
DocumentRoot /var/www/mysite
<Directory />
Options FollowSymLinks
AllowOverride None
</Directory>
<Directory /var/www/mysite>
Options Indexes FollowSymLinks MultiViews
AllowOverride None
Order allow,deny
allow from all
</Directory>
# permet d optimiser les performances
Alias /mydoc/_static /var/www/mydoc/build/html/_static
Alias /mydoc/_static /var/www/mydoc/build/html/_images
Alias /mydoc/_static /var/www/mydoc/build/html/_sources
Alias /mydoc/_static /var/www/mydoc/build/html/_download
ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/
<Directory "/usr/lib/cgi-bin">
AllowOverride None
Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch
Order allow,deny
Allow from all
</Directory>
# WSGIScriptAlias /myapp "/var/www/myapp/wsgi-scripts/myapp.wsgi"
# <Directory "/var/www/myapp/wsgi-scripts">
# Order allow,deny
# Allow from all
#</Directory>
WSGIScriptAlias /mydoc "/var/www/mydoc/wsgi-scripts/myapp.wsgi"
<Directory "/var/www/mydoc/wsgi-scripts">
Order allow,deny
Allow from all
</Directory>
ErrorLog ${APACHE_LOG_DIR}/error.log
# Possible values include: debug, info, notice, warn, error, crit,
# alert, emerg.
LogLevel warn
CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>
On redémarre Apache
/etc/init.d/apache2 restart
On a maintenant accès à notre application via http://localhost/mydoc
Note
on peut sur un même site ajouter plusieurs application, accessible par exemple par http://127.0.0.1/mydoc et http://127.0.0.1/myapp comme dans notre exemple
Note
il est possible d’augmenter les performances de l’application en laissant à apache de gérer différentes partie du site (alors non protégé par l’appli). Cela est réalisé par les “Alias” dans le fichier conf d’apache
Intégration dans Apache en mode proxy¶
Il faut dabord comme en mode StandAlone créer un service pour démarrer automatiquement notre application
On ajoute à l’installation minimum
apt-get install apache2
cd /var/www/mysite
echo "<html>hello mysite</html>" > index.html
On active le mode proxy
a2enmod proxy proxy_http
/etc/init.d/apache2 restart
On paramètre pour que toutes les requêtes sur le port 80 soit redirigé vers notre application
et on edit le fichier conf du site dans /etc/apache2/site-enabled
<VirtualHost *:80>
ServerAdmin webmaster@localhost
DocumentRoot /var/www/mysite
<Directory />
Options FollowSymLinks
AllowOverride None
</Directory>
<Directory /var/www/mysite>
Options Indexes FollowSymLinks MultiViews
AllowOverride None
Order allow,deny
allow from all
</Directory>
ProxyPass / http://localhost:5001/
ProxyPassReverse / http://localhost:5001/
ProxyPreserveHost On
ErrorLog ${APACHE_LOG_DIR}/error.log
# Possible values include: debug, info, notice, warn, error, crit,
# alert, emerg.
LogLevel warn
CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>
On redémarre tout les services
/etc/init.d/mydoc stop
/etc/init.d/apache2 stop
/etc/init.d/mydoc start
/etc/init.d/apache2 start
On a maintenant accès à notre application via http://localhost/
Note
Aujourd’hui il n’est pas possible de faire un proxy de http://localhost/mydoc vers notre application soucis dans la redirection de flasksphinx et dans le template lui même
Warning
- et on ne gère pas le upload et doc en ligne
- installer aafigure et voir avec eux pour ajout couleur
- voir comment aller plus vite sur la production de sphinx (notament copie _download)
- voir gestion des todos
rst2pdf¶
rst2pdf est un outil qui permet à partir de fichier rst de générer un fichier pdf. Il peut être utilisé comme une extension de sphinx.
Pour installer rst2pdf il suffit de faire
easy_install rst2pdf
Pour l’intégrer dans un projet sphinx il faut:
modifier conf.py pour ajouter l’extensions rst2pdf
extensions = ['sphinx.ext.autodoc','rst2pdf.pdfbuilder']
ajouter dans conf.py les options de sortie pdf
# -- Options for PDF output -------------------------------------------------- # Grouping the document tree into PDF files. List of tuples # (source start file, target name, title, author, options). # # If there is more than one author, separate them with \\. # For example: r'Guido van Rossum\\Fred L. Drake, Jr., editor' # # The options element is a dictionary that lets you override # this config per-document. # For example, # ('index', u'MyProject', u'My Project', u'Author Name', # dict(pdf_compressed = True)) # would mean that specific document would be compressed # regardless of the global pdf_compressed setting. pdf_documents = [ ('index', u'MyProject', u'My Project', u'Author Name'), ] # A comma-separated list of custom stylesheets. Example: pdf_stylesheets = ['sphinx','kerning','a4'] # Create a compressed PDF # Use True/False or 1/0 # Example: compressed=True #pdf_compressed = False # A colon-separated list of folders to search for fonts. Example: # pdf_font_path = ['/usr/share/fonts', '/usr/share/texmf-dist/fonts/'] # Language to be used for hyphenation support #pdf_language = "en_US" # Mode for literal blocks wider than the frame. Can be # overflow, shrink or truncate #pdf_fit_mode = "shrink" # Section level that forces a break page. # For example: 1 means top-level sections start in a new page # 0 means disabled #pdf_break_level = 0 # When a section starts in a new page, force it to be 'even', 'odd', # or just use 'any' #pdf_breakside = 'any' # Insert footnotes where they are defined instead of # at the end. #pdf_inline_footnotes = True # verbosity level. 0 1 or 2 #pdf_verbosity = 0 # If false, no index is generated. #pdf_use_index = True # If false, no modindex is generated. #pdf_use_modindex = True # If false, no coverpage is generated. #pdf_use_coverpage = True # Name of the cover page template to use #pdf_cover_template = 'sphinxcover.tmpl' # Documents to append as an appendix to all manuals. #pdf_appendices = [] # Enable experimental feature to split table cells. Use it # if you get "DelayedTable too big" errors #pdf_splittables = False # Set the default DPI for images #pdf_default_dpi = 72 # Enable rst2pdf extension modules (default is empty list) # you need vectorpdf for better sphinx's graphviz support #pdf_extensions = ['vectorpdf'] # Page template name for "regular" pages #pdf_page_template = 'cutePage'
modifier vos builders, sous windows
if "%1" == "pdf" ( %SPHINXBUILD% -b pdf %ALLSPHINXOPTS% %BUILDDIR%/pdf echo. echo.Build finished. The PDF files are in %BUILDDIR%/pdf goto end )
sous unix
pdf:
$(SPHINXBUILD) -b pdf $(ALLSPHINXOPTS) _build/pdf
@echo
@echo "Build finished. The PDF files are in _build/pdf."
et voilà
Note
on utilise la feuille de style sphinx qu’on peut modifier
Vous pouvez trouver la doc ici
Note
afin de gérer les images il faut installer PIL
easy_install PIL
Warning
pour que graphviz fonctionne il faut modifier le fichier rst2pdf/sphinxnodes.py rechercher HandleSphinxGraphviz et remplacer if hasattr(VectorPdf,’load_xobj’) par if hasattr(VectorPdf,’load_xobj’) and 1==0 pour forcer le passage par png
Vous pouvez trouver un exemple complet ici
la commande utilisée est:
C:\Python27\Scripts\rst2pdf.exe sampler.txt -s sampler.style -o sampler.pdf
il est aussi possible de rajouter dans son fichier rst
.. footer:: Page ###Page###/###Total###
.. header:: ###Title### - ###Section###
Un autre exemple complet
rst2pdf -o test.pdf -s style.style --footer "###Page###/###Total###" --header "###Title### - ###Section###" emile.rst
et la fiche de style est
pageSetup:
size: A4
width: null
height: null
margin-top: 1cm
margin-bottom: 1cm
margin-left: 1cm
margin-right: 1cm
margin-gutter: 0cm
spacing-header: 5mm
spacing-footer: 5mm
firstTemplate: coverPage
defaultFooter : ###Page###/###Total###
defaultHeader : ###Section###
pageTemplates:
coverPage:
frames: []
[0cm, 0cm, 100%, 100%]
showHeader : false
showFooter : false
background : mascarille.pdf
styles:
footer:
parent: normal
alignment: TA_CENTER
styles:
admonition:
parent: normal
spaceBefore: 12
spaceAfter: 6
borderPadding: [4,4,4,4]
backColor: null
borderColor: null
borderWidth: 0
borderRadius : 5
commands:[]
[VALIGN, [ 0, 0 ], [ -1, -1 ], TOP ]
styles:
note:
parent: admonition
backColor: #EFF8FB
borderColor: #EFF8FB
styles:
attention:
parent: admonition
backColor: #FBEFEF
borderColor: #FBEFEF
styles:
warning:
parent: admonition
backColor: #FBF8EF
borderColor: #FBF8EF
styles:
admonition-title:
parent: normal
styles:
code:
parent: literal
leftIndent: 0
spaceBefore: 8
spaceAfter: 8
backColor: null
borderColor: darkgray
borderWidth: 0.5
borderPadding: 6
Il est possible de modifier le fonctionnement des admonitions en ajoutant l’extension fred dans le repertoire python de rst2pdf
Il est même possible via une extension de générer des presentions type powerpoint (ppt) en pdf ... dans ce cas il faut avoir des pdfs de page de taille A4.
Vous pouvez trouver cette extention ici
.
Il faudra pour utiliser cette extension lancer la commande
rst2pdf -o out.pdf -e fred in.rst
Vous pouvez trouver un exemple complet ici