Desenvolvendo uma extensão “Hello world”

O objetivo deste tutorial é criar uma extensão muito básica que adicione uma nova diretiva. Esta diretiva produzirá um parágrafo contendo “hello world” (olá mundo).

Apenas informações básicas são fornecidas neste tutorial. Para mais informações, consulte outros tutoriais que entram em mais detalhes.

Aviso

Para esta extensão, você precisará de algum conhecimento básico de docutils e Python.

Visão geral

Queremos que a extensão adicione o seguinte ao Sphinx:

  • Uma diretiva helloworld, que simplesmente produzirá o texto “hello world”.

Pré-requisitos

Não distribuiremos este plugin via PyPI e, em vez disso, incluiremos ele como parte de um projeto existente. Isso significa que você precisará usar um projeto existente ou criar um novo usando sphinx-quickstart.

Presumimos que você esteja usando pastas de fonte (source) e de construção (build) separadas. Seu arquivo de extensão pode estar em qualquer pasta do seu projeto. No nosso caso, vamos fazer o seguinte:

  1. Crie uma pasta _ext em source

  2. Crie um novo arquivo Python na pasta _ext chamado helloworld.py

Aqui está um exemplo da estrutura de pastas que você pode obter:

└── source
    ├── _ext
    │   └── helloworld.py
    ├── _static
    ├── conf.py
    ├── somefolder
    ├── index.rst
    ├── somefile.rst
    └── someotherfile.rst

Escrevendo a extensão

Abra helloworld.py e cole o seguinte código nele:

 1from docutils import nodes
 2from docutils.parsers.rst import Directive
 3
 4from sphinx.application import Sphinx
 5from sphinx.util.typing import ExtensionMetadata
 6
 7
 8class HelloWorld(Directive):
 9    def run(self):
10        paragraph_node = nodes.paragraph(text='Hello World!')
11        return [paragraph_node]
12
13
14def setup(app: Sphinx) -> ExtensionMetadata:
15    app.add_directive('helloworld', HelloWorld)
16
17    return {
18        'version': '0.1',
19        'parallel_read_safe': True,
20        'parallel_write_safe': True,
21    }

Algumas coisas essenciais estão acontecendo neste exemplo e você as verá em todas as diretivas.

A classe da diretiva

Nossa nova diretiva é declarada na classe HelloWorld.

1from sphinx.util.typing import ExtensionMetadata
2
3
4class HelloWorld(Directive):
5    def run(self):

Esta classe estende a classe Directive do docutils. Todas as extensões que criam diretivas devem estender esta classe.

Esta classe contém um método run. Este método é um requisito e faz parte de todas as diretivas. Ele contém a lógica principal da diretiva e retorna uma lista de nós do docutils a serem processados pelo Sphinx. Esses nós são a forma dos docutils representarem o conteúdo de um documento. Existem muitos tipos de nós disponíveis: texto, parágrafo, referência, tabela, etc.

A classe nodes.paragraph cria um novo nó de parágrafo. Um nó de parágrafo normalmente contém algum texto que podemos definir durante a instanciação usando o parâmetro text.

A função setup

Esta função é um requisito. Nós o usamos para conectar nossa nova diretiva ao Sphinx.

 1
 2
 3def setup(app: Sphinx) -> ExtensionMetadata:
 4    app.add_directive('helloworld', HelloWorld)
 5
 6    return {
 7        'version': '0.1',
 8        'parallel_read_safe': True,
 9        'parallel_write_safe': True,
10    }

A coisa mais simples que você pode fazer é chamar o método add_directive(), que é o que fizemos aqui. Para esta chamada específica, o primeiro argumento é o nome da própria diretiva usada em um arquivo reST. Neste caso, usaríamos helloworld. Por exemplo:

Some intro text here...

.. helloworld::

Some more text here...

Também retornamos os metadados da extensão que indicam a versão da nossa extensão, juntamente com o fato de que é seguro usar a extensão tanto para leitura quanto para escrita paralela.

Usando a extensão

A extensão deve ser declarada em seu arquivo conf.py para que o Sphinx saiba disso. Existem duas etapas necessárias aqui:

  1. Adicione o diretório _ext ao caminho do Python usando sys.path.append. Isso deve ser colocado no topo do arquivo.

  2. Atualize ou crie a lista extensions e adicione o nome do arquivo de extensão à lista

Por exemplo:

import os
import sys

sys.path.append(os.path.abspath("./_ext"))

extensions = ['helloworld']

Dica

Não estamos distribuindo esta extensão como um pacote Python, precisamos modificar o caminho Python para que o Sphinx possa encontrar nossa extensão. É por isso que precisamos da chamada para sys.path.append.

Agora você pode usar a extensão em um arquivo. Por exemplo:

Some intro text here...

.. helloworld::

Some more text here...

A exemplo acima geraria:

Some intro text here...

Hello World!

Some more text here...

Leitura adicional

Este é o princípio básico de uma extensão que cria uma nova diretiva.

Para um exemplo mais avançado, consulte Developing a “TODO” extension.