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'

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).


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'

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).


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__'
}

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)
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.