Documentação com docstrings e Sphinx

1. Introdução à Documentação em Python

Documentar código não é um luxo — é uma necessidade. Em projetos Python, sejam bibliotecas open-source ou sistemas internos, a documentação bem escrita reduz o tempo de onboarding, facilita a manutenção e evita retrabalho. No ecossistema Python, três níveis de documentação coexistem:

  • Comentários (#): explicam por que o código foi escrito de determinada forma, são ignorados pelo interpretador.
  • Docstrings: documentam o que um componente faz e como usá-lo, são acessíveis via help() e __doc__.
  • Documentação externa: guias, tutoriais e referências completas, geralmente geradas por ferramentas como o Sphinx.

O Sphinx transforma docstrings e arquivos reStructuredText em HTML, PDF, ePub e muito mais. Ele é o padrão de facto para projetos como Django, NumPy e Flask.

2. Docstrings: A Base da Documentação no Código

Docstrings são strings literais que aparecem como primeira declaração em módulos, classes, funções ou métodos. A PEP 257 define as convenções:

# Docstring de uma linha (função simples)
def somar(a: int, b: int) -> int:
    """Retorna a soma de dois inteiros."""
    return a + b

# Docstring multi-linha (função complexa)
def calcular_media(numeros: list[float]) -> float:
    """
    Calcula a média aritmética de uma lista de números.

    A função aceita listas vazias e retorna 0.0 nesse caso.
    """
    if not numeros:
        return 0.0
    return sum(numeros) / len(numeros)

Boas práticas:
- Use sempre """triplas aspas duplas""" (PEP 257).
- Para docstrings multi-linha, a primeira linha é um resumo, seguido de linha em branco e descrição detalhada.
- Documente módulos no topo do arquivo e pacotes no __init__.py.

3. Formatos de Docstrings Reconhecidos pelo Sphinx

O Sphinx suporta três formatos principais via extensões:

reStructuredText (nativo)

def dividir(a: float, b: float) -> float:
    """
    Divide dois números.

    :param a: Numerador
    :param b: Denominador (não pode ser zero)
    :returns: Resultado da divisão
    :raises ValueError: Se b for zero
    """
    if b == 0:
        raise ValueError("Denominador não pode ser zero")
    return a / b

Google Style (conciso)

def processar_dados(entrada: str, modo: str = "rápido") -> dict:
    """
    Processa dados de entrada conforme o modo especificado.

    Args:
        entrada: String com dados brutos
        modo: Modo de processamento ("rápido" ou "completo")

    Returns:
        Dicionário com resultados processados

    Raises:
        ValueError: Se modo for inválido
    """
    ...

NumPy Style (científico)

def analisar_serie_temporal(dados: np.ndarray, janela: int = 10) -> np.ndarray:
    """
    Aplica média móvel a uma série temporal.

    Parameters
    ----------
    dados : np.ndarray
        Array unidimensional com os dados
    janela : int, optional
        Tamanho da janela para média móvel (default=10)

    Returns
    -------
    np.ndarray
        Série suavizada com média móvel
    """
    ...

Para usar Google ou NumPy, ative a extensão napoleon no conf.py.

4. Configuração Inicial do Sphinx

Instale os pacotes necessários:

pip install sphinx sphinx-autobuild sphinx-rtd-theme

Crie a estrutura inicial:

mkdir docs && cd docs
sphinx-quickstart

Durante o assistente, separe as pastas source e build. A estrutura gerada será:

docs/
├── build/
├── source/
│   ├── conf.py
│   ├── index.rst
│   └── _static/
└── Makefile

Configure o conf.py:

import os
import sys
sys.path.insert(0, os.path.abspath('../src'))  # caminho do seu código

extensions = [
    'sphinx.ext.autodoc',
    'sphinx.ext.napoleon',   # suporte a Google/NumPy
    'sphinx.ext.viewcode',   # link para código fonte
    'sphinx.ext.intersphinx', # links para documentação externa
]

templates_path = ['_templates']
html_theme = 'sphinx_rtd_theme'  # tema Read the Docs

5. Geração Automática de Documentação a partir de Docstrings

A extensão autodoc é o coração da geração automática. No arquivo index.rst (ou em arquivos separados), use as diretivas:

Bem-vindo à Documentação do Meu Projeto
=========================================

.. automodule:: meu_modulo
   :members:
   :undoc-members:
   :show-inheritance:

.. autoclass:: meu_modulo.MinhaClasse
   :members:
   :private-members:

.. autofunction:: meu_modulo.minha_funcao

Para documentar um pacote inteiro:

.. automodule:: meu_pacote
   :members:
   :submodules:
   :imported-members:

Com napoleon ativado, docstrings nos formatos Google e NumPy são convertidas automaticamente para reST.

6. Recursos Avançados do Sphinx

Referências cruzadas

Veja a função :py:func:`meu_modulo.minha_funcao` para detalhes.
Consulte o :ref:`guia-de-instalacao` para configuração.

Blocos de código com destaque

.. code-block:: python

   from meu_modulo import minha_funcao
   resultado = minha_funcao(42)

Inclusão de diagramas (com extensão sphinx.ext.graphviz)

.. graphviz::

   digraph {
      A -> B;
      B -> C;
   }

Temas personalizados

Além do sphinx_rtd_theme, explore alabaster (padrão), furo ou temas customizados.

7. Publicação e Integração Contínua

Geração local

cd docs
make html
# ou no Windows: .\make.bat html

Desenvolvimento com auto-reload

sphinx-autobuild source build/html

Publicação no Read the Docs

  1. Conecte seu repositório GitHub/GitLab ao Read the Docs.
  2. Crie um arquivo .readthedocs.yaml na raiz do projeto:
version: 2
build:
  os: ubuntu-22.04
  tools:
    python: "3.11"
python:
  install:
    - requirements: docs/requirements.txt
sphinx:
  configuration: docs/source/conf.py

CI/CD com GitHub Actions

name: Documentação
on: [push]
jobs:
  docs:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with:
          python-version: '3.11'
      - run: pip install sphinx sphinx-rtd-theme
      - run: cd docs && make html

8. Boas Práticas e Considerações Finais

  • Docstrings primeiro: escreva a documentação junto com o código, não depois.
  • Mantenha atualizada: docstrings desatualizadas são piores que nenhuma documentação.
  • Seja concisa mas completa: inclua exemplos, parâmetros, retornos e exceções.
  • Evite redundância: não repita o que o código já diz (tipo de retorno óbvio).
  • Use ferramentas complementares:
  • pydocstyle: verifica conformidade com PEP 257.
  • interrogate: mede cobertura de docstrings no projeto.
  • sphinx-autodoc-typehints: integra type hints automaticamente.
pip install pydocstyle interrogate sphinx-autodoc-typehints

Documentar com docstrings e Sphinx não é apenas uma boa prática — é um investimento que se paga cada vez que alguém (inclusive você no futuro) precisar entender ou modificar o código.

Referências