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.