Escribir la documentación

Se escribe en los archivos .rst ubicados en docs/source/. Cada página se escribe en un archivo separado. Cada página puede importar documentación desde docstrings del código.

La documentacíon se escribe con formato reStructuredText, que tiene una sintaxis especial para describir texto en negrita, cursiva, etc. Además hay directivas para insertar imagenes, tablas, referencias, etc. Por ejemplo .. image:: foto.jpeg.

Lo importante, es que cada página que va a estar en la web generada viene de un archivo .rst. Originalmente estas páginas solamente muestran lo que tienen escrito en ellas, si uno quiere incluir documentación desde docstrings se usan unas directivas que indican qué módulos/funciones/clases mostrar.

Al final un archivo .rst se ve algo así:

Mi Programa
===========

Esta es la documentación para mi programa.

Este programa sirve para:

* Hacer algo
* Hacer otra cosa
* ...

Documentación:
--------------

.. automodule:: prog.py
   :members:

.. automodule:: es una directiva, se va a reemplazar por la documentación proveniente del módulo prog.py. :members: es una opción que indica que además de mostrar el docstring del módulo, se quiere mostrar la documentación de todas las clases y funciones que tiene dentro.

Ahora convendría ver un poco como se usa reStructuredText, una guía que explica como escribir es esta.

Para hacerlo más corto explico lo más importante acá:

Guía reStructuredText

Los saltos de línea (tecla Enter) son ignorados. La idea es que los párrafos están separados por una línea en blanco, los saltos de línea dentro de un párrafo no se ven en el resultado:

Lo que escribo: El resultado que veo:
Este es un
párrafo.

Este es otro párrafo.

Este es un párrafo.

Este es otro párrafo.

Para hacer títulos hay que subrayar con algún signo de puntuación. La jerarquía de títulos depende del orden en el que se haya utilizado por primera vez ese estilo de subrayado. Los subrayados y su orden que recomiendo son:

Título principal de la página
=============================

Título 1
--------

Título 2
~~~~~~~~

Título 3
^^^^^^^^

Título 4
""""""""

Para distintos tipos de letra:

Lo que escribo: El resultado que veo:
**negrita**, *cursiva*,
``código``.
negrita, cursiva, código.

Para hacer links hay varias formas, ya que está pongo las tres más fáciles:

Lo que escribo: El resultado que veo:
`Git <https://git-scm.com>`_

https://www.python.org/


`Sphinx`__

__ http://www.sphinx-doc.org

Git

https://www.python.org/

Sphinx

Para insertar imágenes:

.. image:: ./imagenes/imagen.jpg

Para escribir código fuente:

::

  Lo que escribo acá se ve como código fuente.

La identación recomendada es dos espacios, pero puede ser mayor. Por último para hacer listas:

* Elemento 1

* Elemento 2

  * Elemento 2.1

* Elemento 3

Y lo más importante es incluir documentación desde docstrings, para ello:

.. automodule: miprograma.funciones
   :members:

Eso incluye todo lo que hay en ese módulo (archivo .py). Para indicar la ruta al módulo se usa la misma sintaxis que la utilizada en Python para incluir módulos:

include miprograma.funciones

Ésta ruta es relativa a la carpeta que se haya agregado al path en conf.py. También hay directivas autoclass, autofunction para incluir documentación de forma más individual, pero no lo veo tan útil.

Página principal

Sphinx crea automáticamente la página principal con el nombre dado en la configuración, en este caso elegimos index.rst. El archivo se ve así:

.. Guia Sphinx documentation master file, created by
   sphinx-quickstart on Thu May 11 20:34:32 2017.
   You can adapt this file completely to your liking, but it should at least
   contain the root `toctree` directive.

Welcome to Guia Sphinx's documentation!
=======================================

.. toctree::
   :maxdepth: 2
   :caption: Contents:

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

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

Como lo indica el comentario ubicado en las primeras 4 líneas, la página principal debe tener una tabla de contenidos (la directiva .. toctree::). Los índices que están abajo en las últimas líneas son opcionales.

En la tabla de contenidos deben especificarse las páginas que uno quiera agregar dando el nombre de archivo sin la extensión. Por ejemplo:

.. toctree::
   :maxdepth: 3
   :caption: Contenidos:

   introduccion
   instalacion
   escribir
   publicar
   ejemplos
   recetas/inicio
   alternativas/inicio

Todas las páginas deben ser agregadas manualmente, Sphinx muestra una advertencia cuando hay paginas inaccesibles debido que no han sido agregadas a ningún índice. Cada página puede tener su propia tabla de contenidos para así crear un árbol jerárquico de páginas.

Los títulos y subtítulos de cada documento son incluidos automáticamente a la tabla de contenidos.

En el caso de usar carpetas para ordenar los documentos, no sen ve reflejadas en el árbol de contenidos. Pero sí debe especificarse la ruta relativa al documento como se ve en la últimas dos líneas del ejemplo de arriba.

Otras páginas

Hay que acordarse de poner un título principal que será mostrado en la tabla de contenidos. Después de eso no hay nada más que sea obligatorio escribir.

Se puede incluir una tabla de contenidos para agregar páginas que estarán debajo de este documento en la jerarquía, en la directiva no se incluye la opción :caption:. :maxdepth: es opcional:

.. toctree::

   pagina1
   pagina2

Normalmente la directiva va justo debajo del título de la página, pero puede ir en cualquier lado.

Páginas generadas a partir de docstrings

Lo único que tienen de especial estas páginas es que contienen directivas autoclass, automodule, autofunction, etc. Al generar la documentación, Sphinx importa esos módulos/clases/funciones, es por ello que en la configuración (conf.py) tuvimos que agregar la carpeta que contiene el código a sys.path.

La estructura de la documentación no necesariamente refleja la estructura de carpetas que hay en el código fuente. Las directivas se pueden poner en cualquier página. Creo que algo cómodo y fácil es crear una página por módulo.

Dentro del código fuente, la documentación de los docstrings debe estar escrita en reStructuredText puro, pero es recomendable usar la extensión Napoleón que ya instalamos y así escribir siguendo la convención Google Style.

APIdoc

Sitio web

Es un programa que te ahorra el trabajo de tener que crear un .rst para cada módulo y de poner en cada uno la directiva automodule. El problema es que genera demasiadas páginas para mi gusto. Prefiero en su lugar a la extensión autosummary que es más personalizable.

Autosummary

Es una extensión que viene incluida en Sphinx pero debe ser activada en conf.py al igual que las demás extensiones. Por lo tanto hay que acordarse de agregarla a la lista de extensiones:

extensions = ['sphinx.ext.autodoc',
        'sphinx.ext.intersphinx',
        'sphinx.ext.todo',
        'sphinx.ext.mathjax',
        'sphinx.ext.napoleon',
        'sphinx.ext.autosummary', # agregar
        'sphinx.ext.viewcode']

De paso, también en conf.py hay que agregar (no importa dónde):

autosummary_generate = True

Esta extensión te ahorra el trabajo de tener que crear un .rst para cada módulo y de poner en cada uno la directiva automodule. Necesita que por medio de la directiva autosummary uno le dé una lista de módulos/clases/funciones a incluir, a partir de esa lista y de unas plantillas, autosummary va a crear un .rst para cada elemento.

Entonces, la forma más fácil de trabajar es tener solamente index.rst y ningún archivo más. En index.rst se coloca la directiva autosummary con la lista de módulos. Al construir la documentación con make html, autosummary va a generar una carpeta llamada docs/source/_autosummary que contendrá a un .rst para cada módulo.

El único problema es que la plantilla que viene por defecto no muestra mucha información, no queda otra que cambiarla. Entonces lo último que queda es crear un archivo docs/source/_templates/autosummary/module.rst y dentro poner lo que va a estar en la página de cada módulo.

Yo hice una plantilla que creo que está bastante bien:

{{ fullname }}
{{ underline }}

.. currentmodule:: {{ fullname }}

{% block functions %}
{% if functions %}
.. rubric:: Functions

.. autosummary::
{% for item in functions %}
  {{ item }}
{%- endfor %}
{% endif %}
{% endblock %}

{% block classes %}
{% if classes %}
.. rubric:: Classes

.. autosummary::
{% for item in classes %}
  {{ item }}
{%- endfor %}
{% endif %}
{% endblock %}

{% block exceptions %}
{% if exceptions %}
.. rubric:: Exceptions

.. autosummary::
{% for item in exceptions %}
  {{ item }}
{%- endfor %}
{% endif %}
{% endblock %}

.. automodule:: {{ fullname }}
   :members:
   :private-members:

Nota

Al hacer make html se genera un .rst para cada módulo en docs/source/_autosummary pero no se actualizan los ya existentes en el caso de por ejemplo cambiar la plantilla. Entonces a veces hace falta borrar la carpeta docs/source/_autosummary para que se vean reflejados todos los cambios.