2017-06-26 4 views
1

Sphinx construit généralement de manière incrémentielle la documentation, ce qui signifie que seuls les fichiers qui ont été modifiés seront régénérés. Je me demande s'il existe un moyen de dire à Sphinx de toujours régénérer certains fichiers qui n'ont peut-être pas été directement modifiés mais qui sont influencés par des changements dans d'autres fichiers. Plus spécifique: existe-t-il un moyen de dire à Sphinx de toujours régénérer les fichiers contenant une certaine directive? La documentation sur laquelle je travaille repose sur la possibilité de collecter et de reformater des informations provenant d'autres pages à l'aide de directives assez fréquemment. Une construction propre (make clean && make [html]) et/ou complète (sphinx-build -a) prend beaucoup plus de temps qu'une construction incrémentielle. De plus, le suivi manuel des fichiers contenant la directive peut s'avérer compliqué. La documentation est rédigée par plus de 10 auteurs ayant une expérience limitée dans la rédaction de la documentation Sphinx.Toujours régénérer les documents Sphinx contenant une directive spécifique

Mais même dans les scénarios moins complexes que vous pourriez faire face à ce « problème »: Par exemple sphinx.ext.todo contient une directive appelée todolist qui recueille todos de toute la documentation. Si je crée un fichier contenant tous les todos de ma documentation (essentiellement un document vide contenant uniquement la directive todolist), la liste n'est pas mise à jour jusqu'à ce que je fasse une nouvelle génération ou que je modifie le fichier.

Si vous voulez tester vous-même: Créer une documentation avec sphinx-quickstart et respectez les valeurs par défaut, sauf pour

'> todo: write "todo" entries that can be shown or hidden on build (y/n) [n]: y' 

Ajouter un fichier dans source appelé todos.rst et référence ce fichier à partir index.rst.

Contenu du index.rst:

Welcome to sphinx-todo's documentation! 
======================================= 

.. toctree:: 
    :maxdepth: 2 

    todos 


.. todo:: 
I have to do this 


Indices and tables 
================== 

* :ref:`genindex` 
* :ref:`modindex` 
* :ref:`search` 

Contenu de todos.rst:

.. _`todos`: 

List of ToDos 
============= 

.. todolist:: 

En supposant que vous utilisez la sortie html vous remarquerez que todos.html ne changera pas lorsque vous ajoutez à todos index.html.

tl; dr: Comment - si possible - dois-je inclure des fichiers contenant une directive spécifique (par exemple todolist) dans une construction incrémentale du Sphinx sans qu'il soit nécessaire de garder une trace d'eux manuellement?

Répondre

2

Par défaut, Sphinx ne mettra à jour la sortie que pour les fichiers nouveaux ou modifiés. Ceci est enterré sous sphinx-build -a.

A la fin de la documentation des options de commande pour sphinx-build:

Vous pouvez aussi donner un ou plusieurs noms de fichiers sur la ligne de commande après la source et de construire des répertoires. Sphinx essaiera alors de ne construire que ces fichiers de sortie (et leurs dépendances).

Vous pouvez soit appeler sphinx-build directement ou par votre makefile, selon le makefile fourni avec votre version de Sphinx (vous pouvez personnaliser le makefile, aussi).

+0

Merci pour la réponse. Votre réponse supporte mon impression actuelle que vous devez tout construire ou spécifier directement les fichiers que vous voulez reconstruire. J'espérais un petit mot-clé «liste blanche» caché pour les directives/fichiers ou un pré-traitement des meilleures pratiques (par exemple, before-build-hook) mais cela ne semble pas exister. – aleneum

0

Juste pour le compte rendu: j'ai évalué plusieurs solutions.J'ai créé une fonction appelée touch_files dans conf.py. Il recherche des chaînes dans des fichiers et - si trouvés - touche le fichier pour déclencher une Reconstruit:

def touch_files(*args): 
    # recursively search the 'source' directory 
    for root, dirnames, filenames in os.walk('.'): 
     # check all rst files 
     for filename in fnmatch.filter(filenames, '*.rst'): 
      cur = os.path.join(root, filename) 
      f = open(cur) 
      # access content directly from disk 
      s = mmap.mmap(f.fileno(), 0, access=mmap.ACCESS_READ) 
      if any(s.find(d) != -1 for d in args): 
       # if a string pattern has been found alter the edit 
       # time of the file 
       os.utime(cur, None) 
      f.close() 

# actually call the function 
touch_files('.. todolist::') 

touch_files peut être appelé avec une quantité variable d'arguments et modifier un fichier lorsque l'un des arguments a été a trouvé. J'ai essayé d'optimiser la fonction avec une expression régulière, mais cela n'a pas beaucoup fonctionné. La lecture du contenu du fichier directement à partir du disque avec mmap semblait avoir un impact mineur.

Ceci est le résultat de 78 fichiers au total dont 36 contiennent l'une des deux directives.

Command         Time  Comment 
time make html       2.3 s No changes 
time sh -c 'make clean && make html' 13.3 s 
time make htmlfull      9.4 s sphinx-build -a  
time make html       8.4 s with 'touch_files' 
'touch_files'       0.2 s tested with testit 

Résultat: Chaque commande a été appelé à quelques reprises (sauf « touch_files ») et donc manque de fiabilité statistique. Sphinx nécessite environ 2,3 secondes pour vérifier la documentation des modifications sans rien faire. Une construction propre nécessite 13,3 secondes, ce qui est beaucoup plus long qu'une construction avec sphinx-build -a. Si nous avons juste reconstruit 36 ​​des 78 fichiers, le processus construit est légèrement plus rapide, bien que je doute qu'une différence significative puisse être trouvée ici. La surcharge de 'touch_files' est plutôt faible. Trouver les chaînes est assez bon marché comparé à l'édition des timestamps.

Conclusion: Comme l'a souligné Steve Piercy, l'utilisation de sphinx-build -a semble être l'approche la plus raisonnable. Au moins pour mon cas d'utilisation. Si un fichier qui ne contient pas de directive en question aboutit à de longs temps de construction, cela peut être utile pour touch_files.