Jak użyć autodoc Sphinx do udokumentowania metody __init __ (self) klasy?

107

Sphinx domyślnie nie generuje dokumentów dla __init __ (self). Próbowałem następujących rzeczy:

.. automodule:: mymodule
    :members:

i

..autoclass:: MyClass
    :members:

W conf.py ustawienie następujących elementów tylko dołącza __init __ (self) docstring do klasy docstring ( dokumentacja Sphinx autodoc wydaje się zgadzać, że jest to oczekiwane zachowanie, ale nie wspomina o problemie, który próbuję rozwiązać):

autoclass_content = 'both'
Jacob Marble
źródło
Nie, to nie jest to, co dokumentacja pisze na dzień dzisiejszy, przynajmniej: "both" Both the class’ and the __init__ method’s docstring are concatenated and inserted.-> Dlatego powinna to być nie tylko dokumentacja __init__(self), ale także dokumentacja klasowa, jeśli to masz. Czy możesz podać przypadek testowy, ponieważ jeśli tak jest, wygląda to jak błąd, prawda?
lpapp

Odpowiedzi:

116

Oto trzy alternatywy:

  1. Aby upewnić się, że __init__()jest to zawsze udokumentowane, możesz użyć autodoc-skip-memberw conf.py. Lubię to:

    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)

    To wyraźnie określa, że __init__nie należy go pomijać (co jest domyślne). Ta konfiguracja jest określana raz i nie wymaga żadnych dodatkowych znaczników dla każdej klasy w źródle .rst.

  2. special-membersOpcja została dodana w Sfinksa 1.1 . To sprawia, że ​​"specjalni" członkowie (ci o takich nazwach __special__) są dokumentowani przez autodoc.

    Od Sphinx 1.2 ta opcja przyjmuje argumenty, co czyni ją bardziej użyteczną niż poprzednio.

  3. Zastosowanie automethod:

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

    Należy to dodać dla każdej klasy (nie można tego używać z automodule, jak wskazano w komentarzu do pierwszej wersji tej odpowiedzi).

mzjn
źródło
7
To nie pomaga w przypadku automodułu, ponieważ trzeba go dodać do każdej klasy.
Roger Binns,
3
Pierwsza alternatywa zadziałała. W moim przypadku było to lepsze niż druga i trzecia alternatywa, ponieważ nie trzeba edytować plików .rst.
jcarballo
9
W Sphinx 1.2.1 special-membersdziała dobrze przy użyciu automodule. Używaj :special-members: __init__tylko do dokumentowania __init__.
Florian Brucker,
67

Byłeś blisko. Możesz skorzystać z autoclass_contentopcji w swoim conf.pypliku:

autoclass_content = 'both'
gotgenes
źródło
1
@MichaelMrozek: Też się nad tym zastanawiam ... Czy zrozumiałeś wysoki wskaźnik pozytywnych głosów tej odpowiedzi? Na początku wygląda na odpowiedź, którą należy wyczyścić.
lpapp
1
Próbowałem ustawić autoclass_content = 'both'opcję, która udokumentowała metodę init , ale spowodowała dwukrotne wyświetlenie autopodsumowania.
Rozciągnij
To powinna być akceptowana odpowiedź. Jest prostszy i odnosi się do oficjalnej dokumentacji sfinksa.
BerriJ
6

W ciągu ostatnich lat pisałem kilka wariantów autodoc-skip-memberwywołań zwrotnych dla różnych niepowiązanych projektów Pythona, ponieważ chciałem metody podoba __init__(), __enter__()i __exit__()aby pokazać się w moim dokumentacji API (wszak te „specjalne” metody są częścią API i co lepsze miejsce do udokumentować je niż wewnątrz dokumentacji metody specjalnej).

Niedawno zrobiłem najlepszą implementację i uczyniłem ją częścią jednego z moich projektów w Pythonie ( tutaj jest dokumentacja ). Wdrożenie w zasadzie sprowadza się do tego:

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

Tak, jest więcej dokumentacji niż logiki :-). Zaletą zdefiniowania takiego autodoc-skip-memberwywołania zwrotnego nad użyciem special-membersopcji (dla mnie) jest to, że special-membersopcja umożliwia również dokumentację właściwości, takich jak __weakref__(dostępne we wszystkich klasach nowego stylu, AFAIK), które uważam za szum i w ogóle nie są przydatne. Metoda wywołania zwrotnego unika tego (ponieważ działa tylko na funkcjach / metodach i ignoruje inne atrybuty).

xolox
źródło
Jak tego używam? Wygląda na to, że metoda musi zostać nazwana setup(app), aby została wykonana przez Sphinx.
oarfish
Nie rozumiem wszystkiego, ale zobacz implementację xolox, jeśli chcesz się przeanalizować. Wydaje mi się, że zbudował rozszerzenie sfinksa, które łączy wywołanie zwrotne ze zdarzeniem autodoc-skip-member. Gdy sfinks próbuje dowiedzieć się, czy coś powinno zostać uwzględnione / pominięte, to zdarzenie się uruchamia, a jego kod działa. Jeśli jego kod wykryje specjalnego członka, który został jawnie zdefiniowany przez użytkownika (dziedziczony, jak to często bywa), wówczas mówi Sphinxowi, aby go dołączył. W ten sposób możesz dokumentować członków specjalnych, których sam piszesz
Andrew,
Dzięki za wyjaśnienia Andrew i tak, masz rację, oarfish, potrzebna jest funkcja konfiguracji. Dodałem to do przykładu, aby uniknąć dalszych nieporozumień.
xolox
@JoelB: Przykładowy kod w moim poście został napisany tak, aby zakładać, że Twoja __init__metoda ma niepusty ciąg znaków. Czy to?
xolox
2

Mimo, że jest to starszy post, dla tych, którzy go teraz szukają, pojawiło się również inne rozwiązanie wprowadzone w wersji 1.8. Zgodnie z dokumentacją możesz dodać special-memberklucz w opcji autodoc_default_options do pliku conf.py.

Przykład:

autodoc_default_options = {
    'members': True,
    'member-order': 'bysource',
    'special-members': '__init__',
    'undoc-members': True,
    'exclude-members': '__weakref__'
}
dheinz
źródło
0

To jest wariant, który obejmuje tylko __init__wtedy, gdy ma argumenty:

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
źródło