¿Cómo usar el autodoc de Sphinx para documentar el método __init __ (self) de una clase?

107

Sphinx no genera documentos para __init __ (self) de forma predeterminada. He probado lo siguiente:

.. automodule:: mymodule
    :members:

y

..autoclass:: MyClass
    :members:

En conf.py, estableciendo la siguiente sólo se añade la __init __ (self) docstring a la cadena de documentación de clase ( la documentación autodoc Esfinge parece estar de acuerdo que este es el comportamiento esperado, pero no menciona nada sobre el problema que estoy tratando de resolver):

autoclass_content = 'both'
Jacob mármol
fuente
No, eso no es lo que escribe la documentación a partir de hoy, al menos: "both" Both the class’ and the __init__ method’s docstring are concatenated and inserted.-> Por lo tanto, no debería ser solo el __init__(self), sino también el docstring de la clase si lo tiene. ¿Puede proporcionar un caso de prueba porque si es así, se siente como un error, verdad?
lpapp

Respuestas:

116

Aquí hay tres alternativas:

  1. Para asegurarse de que __init__()siempre esté documentado, puede usar autodoc-skip-memberen conf.py. Me gusta esto:

    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)

    Esto define explícitamente que __init__no se debe omitir (que es de forma predeterminada). Esta configuración se especifica una vez y no requiere ningún marcado adicional para cada clase en la fuente .rst.

  2. La special-membersopción se agregó en Sphinx 1.1 . Hace que los miembros "especiales" (aquellos con nombres como __special__) sean documentados por autodoc.

    Desde Sphinx 1.2, esta opción toma argumentos que la hacen más útil que antes.

  3. Utilizar automethod:

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

    Esto debe agregarse para cada clase (no se puede usar con automodule, como se señala en un comentario a la primera revisión de esta respuesta).

mzjn
fuente
7
Eso no ayuda con el módulo automático, ya que debe agregarse a cada clase.
Roger Binns
3
La primera alternativa funcionó. En mi caso fue mejor que la segunda y tercera alternativa, ya que no necesita editar archivos .rst.
jcarballo
9
En Sphinx 1.2.1, special-membersfunciona bien usando automodule. Úselo :special-members: __init__solo para documentar __init__.
Florian Brucker
67

Estabas cerca. Puede utilizar la autoclass_contentopción en su conf.pyarchivo:

autoclass_content = 'both'
gotgenes
fuente
1
@MichaelMrozek: También me pregunto sobre eso ... ¿Entendiste la alta tasa de votos positivos de esta respuesta? Al principio, parece una respuesta que debería eliminarse.
lpapp
1
Intenté configurar la autoclass_content = 'both'opción, que documentó el método de inicio , pero hizo que el resumen automático apareciera dos veces.
Estirar el
Esta debería ser la respuesta aceptada. Es más simple y se refiere a la documentación oficial de Sphinx.
BerriJ
6

En los últimos años, he escrito varias variantes de autodoc-skip-memberdevoluciones de llamada para varios proyectos de Python no relacionados porque quería métodos como __init__(), __enter__()y __exit__()que aparecieran en la documentación de mi API (después de todo, estos "métodos especiales" son parte de la API y qué mejor lugar para documentarlos que dentro de la cadena de documentos del método especial).

Recientemente tomé la mejor implementación y la hice parte de uno de mis proyectos de Python ( aquí está la documentación ). La implementación básicamente se reduce a esto:

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

Sí, hay más documentación que lógica :-). La ventaja de definir una autodoc-skip-memberdevolución de llamada como esta sobre el uso de la special-membersopción (para mí) es que la special-membersopción también habilita la documentación de propiedades como __weakref__(disponible en todas las clases de estilo nuevo, AFAIK) que considero ruido y no son útiles en absoluto. El enfoque de devolución de llamada evita esto (porque solo funciona en funciones / métodos e ignora otros atributos).

xolox
fuente
¿Cómo utilizo esto? Parece que el método debe tener un nombre setup(app)para que Sphinx lo ejecute.
pez remo
No lo entiendo todo, pero vea la implementación de xolox si desea analizarlo usted mismo. Creo que construyó una extensión Sphinx que conecta una devolución de llamada al evento autodoc-skip-member. Cuando Sphinx intenta averiguar si se debe incluir / omitir algo, ese evento se activa y su código se ejecuta. Si su código detecta un miembro especial que fue definido explícitamente por el usuario (heredado como sucede a menudo) entonces le dice a Sphinx que lo incluya. De esa manera, puedes documentar miembros especiales que escribes tú mismo
Andrew
Gracias por las aclaraciones, Andrew, y sí, tienes razón, se necesita una función de configuración. Lo agregué al ejemplo para evitar más confusión.
xolox
@JoelB: El código de ejemplo en mi publicación está escrito para asumir que su __init__método tiene una cadena de documentos no vacía. ¿Lo hace?
xolox
2

Aunque esta es una publicación anterior, para aquellos que la estén buscando a partir de ahora, también hay otra solución introducida en la versión 1.8. De acuerdo con la documentación , puede agregar la special-memberclave en autodoc_default_options a su conf.py.

Ejemplo:

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

Esta es una variante que solo incluye __init__si tiene 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
fuente