Como usar o autodoc do Sphinx para documentar o método __init __ (self) de uma classe?

107

O Sphinx não gera documentos para __init __ (self) por padrão. Eu tentei o seguinte:

.. automodule:: mymodule
    :members:

e

..autoclass:: MyClass
    :members:

Em conf.py, definir o seguinte apenas anexa a docstring __init __ (self) à docstring da classe ( a documentação do autodoc do Sphinx parece concordar que esse é o comportamento esperado, mas não menciona nada sobre o problema que estou tentando resolver):

autoclass_content = 'both'
Jacob Marble
fonte
Não, não é isso que a documentação escreve até hoje, pelo menos: "both" Both the class’ and the __init__ method’s docstring are concatenated and inserted.-> Portanto, não deve ser apenas o __init__(self), mas também a docstring da classe, se você tiver isso. Você pode fornecer um caso de teste porque, se for assim, parece um bug, certo?
lpapp

Respostas:

116

Aqui estão três alternativas:

  1. Para garantir que __init__()esteja sempre documentado, você pode usar autodoc-skip-memberem conf.py. Como isso:

    def skip(app, what, name, obj, would_skip, options):
        if name == "__init__":
            return False
        return would_skip
    
    def setup(app):
        app.connect("autodoc-skip-member", skip)

    Isso define explicitamente __init__não deve ser ignorado (o que é por padrão). Essa configuração é especificada uma vez e não requer nenhuma marcação adicional para todas as classes na fonte .rst.

  2. A special-membersopção foi adicionada no Sphinx 1.1 . Faz com que membros "especiais" (aqueles com nomes como __special__) sejam documentados pelo autodoc.

    Desde o Sphinx 1.2, esta opção aceita argumentos que a tornam mais útil do que era anteriormente.

  3. Use automethod:

    .. autoclass:: MyClass     
       :members: 
    
       .. automethod:: __init__

    Isso deve ser adicionado para todas as classes (não pode ser usado com automodule, como apontado em um comentário à primeira revisão desta resposta).

mzjn
fonte
7
Isso não ajuda com o módulo automático, pois ele deve ser adicionado a todas as classes.
Roger Binns
3
A primeira alternativa funcionou. No meu caso foi melhor do que a segunda e a terceira alternativas, pois não precisa editar arquivos .rst.
jcarballo
9
No Sphinx 1.2.1, special-membersfunciona bem usando automodule. Use :special-members: __init__para documentar apenas __init__.
Florian Brucker
67

Você estava perto. Você pode usar a autoclass_contentopção em seu conf.pyarquivo:

autoclass_content = 'both'
Gotgenes
fonte
1
@MichaelMrozek: Também estou pensando sobre isso ... Você entendeu a alta taxa de votos positivos dessa resposta? A princípio, parece uma resposta que deve ser eliminada.
lpapp
1
Tentei definir a autoclass_content = 'both'opção, que documentou o método init , mas fez o resumo automático aparecer duas vezes.
Alongamento
Esta deve ser a resposta aceita. É mais simples e se refere à documentação oficial da esfinge.
BerriJ
6

Nos últimos anos tenho escrito várias variantes de autodoc-skip-memberretornos de chamada para vários projetos Python não relacionados porque eu queria métodos gosto __init__(), __enter__()e __exit__()para mostrar-se na minha documentação da API (afinal, esses "métodos especiais" são parte da API e que melhor lugar para documentá-los do que dentro da docstring do método especial).

Recentemente, peguei a melhor implementação e a incluí em um dos meus projetos Python ( aqui está a documentação ). A implementação basicamente se resume a isto:

import types

def setup(app):
    """Enable Sphinx customizations."""
    enable_special_methods(app)


def enable_special_methods(app):
    """
    Enable documenting "special methods" using the autodoc_ extension.

    :param app: The Sphinx application object.

    This function connects the :func:`special_methods_callback()` function to
    ``autodoc-skip-member`` events.

    .. _autodoc: http://www.sphinx-doc.org/en/stable/ext/autodoc.html
    """
    app.connect('autodoc-skip-member', special_methods_callback)


def special_methods_callback(app, what, name, obj, skip, options):
    """
    Enable documenting "special methods" using the autodoc_ extension.

    Refer to :func:`enable_special_methods()` to enable the use of this
    function (you probably don't want to call
    :func:`special_methods_callback()` directly).

    This function implements a callback for ``autodoc-skip-member`` events to
    include documented "special methods" (method names with two leading and two
    trailing underscores) in your documentation. The result is similar to the
    use of the ``special-members`` flag with one big difference: Special
    methods are included but other types of members are ignored. This means
    that attributes like ``__weakref__`` will always be ignored (this was my
    main annoyance with the ``special-members`` flag).

    The parameters expected by this function are those defined for Sphinx event
    callback functions (i.e. I'm not going to document them here :-).
    """
    if getattr(obj, '__doc__', None) and isinstance(obj, (types.FunctionType, types.MethodType)):
        return False
    else:
        return skip

Sim, há mais documentação do que lógica :-). A vantagem de definir um autodoc-skip-memberretorno de chamada como esse sobre o uso da special-membersopção (para mim) é que a special-membersopção também permite a documentação de propriedades como __weakref__(disponível em todas as classes de novo estilo, AFAIK) que considero ruído e nada útil. A abordagem de retorno de chamada evita isso (porque só funciona em funções / métodos e ignora outros atributos).

xolox
fonte
Como faço para usar isso? Parece que o método deve ser nomeado setup(app)para ser executado pelo Sphinx.
oarfish de
Eu não entendo tudo, mas veja a implementação do xolox se você quiser se dissecar. Acredito que ele construiu uma extensão esfinge que conecta um retorno de chamada ao evento autodoc-skip-member. Quando o sphinx tenta descobrir se algo deve ser incluído / pulado, esse evento é disparado e seu código é executado. Se seu código detectar um membro especial que foi definido explicitamente pelo usuário (herdado como acontece com frequência), ele diz ao Sphinx para incluí-lo. Dessa forma, você pode documentar membros especiais que você mesmo escreve
Andrew
Obrigado pelos esclarecimentos André e sim, você está oarfish correto, uma função de configuração é necessária. Eu o adicionei ao exemplo para evitar mais confusão.
xolox de
@JoelB: O código de exemplo em minha postagem foi escrito para assumir que seu __init__método possui uma docstring não vazia. É mesmo?
xolox
2

Embora esta seja uma postagem mais antiga, para quem está pesquisando a partir de agora, existe também outra solução introduzida na versão 1.8. De acordo com a documentação , você pode adicionar a special-memberchave em autodoc_default_options ao seu conf.py.

Exemplo:

autodoc_default_options = {
    'members': True,
    'member-order': 'bysource',
    'special-members': '__init__',
    'undoc-members': True,
    'exclude-members': '__weakref__'
}
Dheinz
fonte
0

Esta é uma variante que inclui apenas __init__se tiver argumentos:

import inspect

def skip_init_without_args(app, what, name, obj, would_skip, options):
    if name == '__init__':
        func = getattr(obj, '__init__')
        spec = inspect.getfullargspec(func)
        return not spec.args and not spec.varargs and not spec.varkw and not spec.kwonlyargs
    return would_skip

def setup(app):
    app.connect("autodoc-skip-member", skip_init_without_args)
letmaik
fonte