Come napoleone e autodoc interagiscono documentando i membri

Oct 29 2020

Ho notato un cambiamento nel comportamento nel modo in cui Sphinx rende le descrizioni delle classi. Dato questo codice

# my example happens to be a dataclass, but the behavior for 
# regular classes is the same
@dataclass
class TestClass:
    """This is a test class for dataclasses.

    This is the body of the docstring description.
    """
    var_int: int
    var_str: str

oltre ad alcune impostazioni Sphinx generiche, ho usato per ottenere questo circa due anni fa

E ora sto ottenendo questo

C'è un modo per dire a Sphinx di non aggiungere le variabili di classe in fondo alla definizione della classe? È particolarmente fastidioso che presuma che i loro valori siano None, solo perché non hanno valori predefiniti.


Questo problema è emerso durante le discussioni su questo post , che contiene anche un po 'più di contesto nei commenti riguardanti la configurazione di Sphinx, ecc.

Risposte

2 bad_coder Oct 30 2020 at 02:29

I membri di un oggetto sono inclusi da una direttiva autodoc a seconda se:

  • :members:viene utilizzata l' opzione (per i membri con docstrings).
  • :undoc-members:viene utilizzata l' opzione (per membri senza docstring).

Per esempio:

dc module
=========

.. autoclass:: dc.Foo

Nel .rstfile sopra la direttiva autodoc non ha opzioni esplicite impostate, ciò che Sphinx farà è applicare implicitamente i flag di opzione presi da autodoc_default_flagsin conf.py.

L'impostazione di quanto segue conf.pycausa l'inclusione da parte di Sphinx di tutti i membri di un oggetto (con o senza docstrings) in tutte le direttive che non specificano esplicitamente le opzioni.

# autodoc settings
autodoc_default_options = {
    'members':          True,
    'undoc-members':    True,
}

Il risultato:

Tuttavia, questo solleva una domanda: cosa fanno le estensioni autodoc e sphinx-napoleon se i membri sono specificati esplicitamente nella Attributes sezione docstring ma sono inclusi anche nell'estensione autodoc?

Docstrings

Napoleon interpreta ogni docstring che autodoc può trovare (...) All'interno di ogni docstring, le sezioni appositamente formattate vengono analizzate e convertite in reStructuredText .

Ad esempio, utilizzando la seguente docstring insieme alle opzioni specificate sopra in autodoc_default_options.

import dataclasses

@dataclasses.dataclass
class Foo:
    """Docstring for Foo

    Attributes:
        var_a (str): An integer.
        var_b (int): A string.
    """
    var_a: str
    var_b: int

In questo caso i membri saranno dichiarati due volte, una per ogni estensione, con la corrispondente dichiarazione reST generata come duplicato. Avere una dichiarazione reST duplicata porterà al solito avvertimento:

C: \ dc.py: docstring di dc.Foo.var_a: 1: ATTENZIONE: descrizione oggetto duplicata di dc.Foo.var_a, altra istanza in dc, usa: noindex: per uno di loro

C: \ dc.py: docstring di dc.Foo.var_b: 1: ATTENZIONE: descrizione oggetto duplicato di dc.Foo.var_b, altra istanza in dc, usa: noindex: per uno di loro

Qui si può notare una differenza: sphinx-napoleon dichiarerà il membro nella propria sezione docstring mentre autodoc lo renderà normalmente come altri membri. La differenza visiva dipenderà dal tema, ad esempio utilizzando il classictema:

Infine, se vuoi documentare i membri usando le sezioni di docstring sphinx-napoleon ed evitare una dichiarazione reST duplicata da autodoc mantenendo autodoc_default_optionscome mostrato, puoi usare esplicitamente l' :exclude-members:opzione in quella specifica direttiva, ad esempio:

dc module
=========

.. autoclass:: dc.Foo
    :exclude-members: var_a, var_b

Documenterebbe i membri usando solo le direttive reST generate dalla sfinge-napoleone: