Come usare l'autodoc di Sphinx per documentare il metodo __init __ (self) di una classe?


107

Sphinx non genera documenti per __init __ (self) per impostazione predefinita. Ho provato quanto segue:

.. automodule:: mymodule
    :members:

e

..autoclass:: MyClass
    :members:

In conf.py, l'impostazione di quanto segue aggiunge solo __init __ (self) docstring alla docstring di classe ( la documentazione dell'autodoc di Sphinx sembra concordare sul fatto che questo è il comportamento previsto, ma non menziona nulla riguardo al problema che sto cercando di risolvere):

autoclass_content = 'both'

No, questo non è quello che scrive la documentazione fino ad oggi, almeno: "both" Both the class’ and the __init__ method’s docstring are concatenated and inserted.-> Pertanto, non dovrebbe essere solo la __init__(self), ma anche la docstring di classe se ce l'hai. Puoi fornire un test case perché se è così, sembra un bug, giusto?
lpapp

Risposte:


116

Ecco tre alternative:

  1. Per assicurarti che __init__()sia sempre documentato, puoi usare autodoc-skip-memberin conf.py. Come questo:

    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)
    

    Questo definisce esplicitamente di __init__non essere saltato (che è per impostazione predefinita). Questa configurazione viene specificata una volta e non richiede alcun markup aggiuntivo per ogni classe nel sorgente .rst.

  2. L' special-membersopzione è stata aggiunta in Sphinx 1.1 . Fa in modo che i membri "speciali" (quelli con nomi simili __special__) vengano documentati da autodoc.

    A partire da Sphinx 1.2, questa opzione accetta argomenti che la rendono più utile di quanto non fosse in precedenza.

  3. Usa automethod:

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

    Questo deve essere aggiunto per ogni classe (non può essere usato con automodule, come sottolineato in un commento alla prima revisione di questa risposta).


7
Ciò non aiuta con automodule poiché deve essere aggiunto a ogni classe.
Roger Binns

3
La prima alternativa ha funzionato. Nel mio caso era migliore della seconda e della terza alternativa, poiché non è necessario modificare i file .rst.
jcarballo

9
In Sphinx 1.2.1, special-membersfunziona bene usando automodule. Utilizzare :special-members: __init__solo per documentare __init__.
Florian Brucker

67

Eri vicino. Puoi usare l' autoclass_contentopzione nel tuo conf.pyfile:

autoclass_content = 'both'

1
@MichaelMrozek: Mi chiedo anche questo ... Hai capito l'alto tasso di voti positivi di questa risposta? In un primo momento, sembra una risposta che dovrebbe essere eliminata.
lpapp

1
Ho provato a impostare l' autoclass_content = 'both'opzione, che ha documentato il metodo init , ma ha fatto apparire due volte l'autosummary.
Stretch

Questa dovrebbe essere la risposta accettata. È più semplice e fa riferimento alla documentazione ufficiale della sfinge.
BerriJ

6

Negli ultimi anni ho scritto diverse varianti di autodoc-skip-membercallback per vari progetti Python non correlati perché volevo metodi come __init__(), __enter__()e __exit__()da mostrare nella mia documentazione API (dopotutto, questi "metodi speciali" fanno parte dell'API e quale posto migliore per documentarli che all'interno della docstring del metodo speciale).

Recentemente ho preso la migliore implementazione e l'ho inserita in uno dei miei progetti Python ( ecco la documentazione ). L'implementazione si riduce sostanzialmente a questo:

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ì, c'è più documentazione che logica :-). Il vantaggio di definire un autodoc-skip-membercallback come questo rispetto all'uso special-membersdell'opzione (per me) è che l' special-membersopzione abilita anche la documentazione di proprietà come __weakref__(disponibile su tutte le classi di nuovo stile, AFAIK) che considero rumorose e per niente utili. L'approccio callback lo evita (perché funziona solo su funzioni / metodi e ignora altri attributi).


Come lo uso? Sembra che il metodo debba essere nominato setup(app)per essere eseguito da Sphinx.
oarfish

Non capisco tutto, ma guarda l' implementazione di xolox se vuoi analizzare te stesso. Credo che abbia costruito un'estensione sfinge che collega una richiamata all'evento autodoc-skip-member. Quando sphinx cerca di capire se qualcosa dovrebbe essere incluso / ignorato, quell'evento si attiva e il suo codice viene eseguito. Se il suo codice rileva un membro speciale che è stato definito esplicitamente dall'utente (ereditato come spesso accade), allora dice a Sphinx di includerlo. In questo modo puoi documentare i membri speciali che scrivi tu stesso
Andrew

Grazie per i chiarimenti Andrew e sì, hai ragione oarfish, è necessaria una funzione di configurazione. L'ho aggiunto all'esempio per evitare ulteriore confusione.
xolox

@ JoelB: Il codice di esempio nel mio post è scritto per presumere che il tuo __init__metodo abbia una docstring non vuota. Lo fa?
xolox

2

Anche se questo è un post più vecchio, per coloro che lo stanno cercando fin da ora, c'è anche un'altra soluzione introdotta nella versione 1.8. Secondo la documentazione , puoi aggiungere la special-memberchiave in autodoc_default_options al tuo file conf.py.

Esempio:

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

0

Questa è una variante che include solo __init__se ha argomenti:

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)
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.