Code in Sphinx beschreiben¶
In den vorherigen Abschnitten des Tutorials können Sie lesen, wie man beschreibende oder Prosa-Dokumentation in Sphinx schreibt. In diesem Abschnitt werden Sie stattdessen Codeobjekte beschreiben.
Sphinx unterstützt die Dokumentation von Codeobjekten in mehreren Sprachen, nämlich Python, C, C++, JavaScript und reStructuredText. Jede davon kann mit einer Reihe von Direktiven und Rollen dokumentiert werden, die von Domänen gruppiert sind. Für den Rest des Tutorials werden Sie die Python-Domäne verwenden, aber alle Konzepte, die in diesem Abschnitt behandelt werden, gelten auch für die anderen Domänen.
Python¶
Python-Objekte dokumentieren¶
Sphinx bietet mehrere Rollen und Direktiven zur Dokumentation von Python-Objekten, die alle in der Python-Domäne zusammengefasst sind. Sie können beispielsweise die Direktive py:function verwenden, um eine Python-Funktion wie folgt zu dokumentieren:
Creating recipes
----------------
To retrieve a list of random ingredients,
you can use the ``lumache.get_random_ingredients()`` function:
.. py:function:: lumache.get_random_ingredients(kind=None)
Return a list of random ingredients as strings.
:param kind: Optional "kind" of ingredients.
:type kind: list[str] or None
:return: The ingredients list.
:rtype: list[str]
Was wie folgt gerendert wird:
Das gerenderte Ergebnis der Dokumentation einer Python-Funktion in Sphinx¶
Beachten Sie mehrere Dinge:
Sphinx hat das Argument der Direktive
.. py:functionanalysiert und das Modul, den Funktionsnamen und die Parameter entsprechend hervorgehoben.Der Inhalt der Direktive enthält eine einzeilige Beschreibung der Funktion sowie eine Info-Feldliste, die den Funktionsparameter, seinen erwarteten Typ, den Rückgabewert und den Rückgabetyp enthält.
Hinweis
Das Präfix py: gibt die Domäne an. Sie können die Standarddomäne konfigurieren, sodass Sie das Präfix weglassen können, entweder global über die Konfiguration primary_domain oder Sie verwenden die Direktive default-domain, um sie ab dem Zeitpunkt ihrer Verwendung bis zum Ende der Datei zu ändern. Wenn Sie sie beispielsweise auf py (Standard) setzen, können Sie .. function:: direkt schreiben.
Python-Objekte mit Querverweisen versehen¶
Standardmäßig generieren die meisten dieser Direktiven Entitäten, die von überall in der Dokumentation mithilfe von einer entsprechenden Rolle mit Querverweisen versehen werden können. Im Fall von Funktionen können Sie dafür py:func verwenden, wie folgt:
The ``kind`` parameter should be either ``"meat"``, ``"fish"``,
or ``"veggies"``. Otherwise, :py:func:`lumache.get_random_ingredients`
will raise an exception.
Beim Generieren von Code-Dokumentationen erstellt Sphinx automatisch einen Querverweis, indem es einfach den Namen des Objekts verwendet, ohne dass Sie explizit eine Rolle dafür verwenden müssen. Sie können beispielsweise die benutzerdefinierte Ausnahme, die von der Funktion ausgelöst wird, mithilfe der Direktive py:exception beschreiben:
.. py:exception:: lumache.InvalidKindError
Raised if the kind is invalid.
Fügen Sie dann diese Ausnahme zur ursprünglichen Beschreibung der Funktion hinzu:
.. py:function:: lumache.get_random_ingredients(kind=None)
Return a list of random ingredients as strings.
:param kind: Optional "kind" of ingredients.
:type kind: list[str] or None
:raise lumache.InvalidKindError: If the kind is invalid.
:return: The ingredients list.
:rtype: list[str]
Und schließlich sieht das Ergebnis wie folgt aus:
HTML-Ergebnis der Dokumentation einer Python-Funktion in Sphinx mit Querverweisen¶
Schön, nicht wahr?
Doctests in Ihre Dokumentation aufnehmen¶
Da Sie nun Code aus einer Python-Bibliothek beschreiben, wird es nützlich sein, sowohl die Dokumentation als auch den Code so synchron wie möglich zu halten. Eine Möglichkeit, dies in Sphinx zu tun, besteht darin, Code-Schnipsel in die Dokumentation aufzunehmen, sogenannte *Doctests*, die beim Erstellen der Dokumentation ausgeführt werden.
Um Doctests und andere in diesem Tutorial behandelte Sphinx-Funktionen zu demonstrieren, muss Sphinx in der Lage sein, den Code zu importieren. Um dies zu erreichen, schreiben Sie Folgendes am Anfang von conf.py:
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here.
import sys
from pathlib import Path
sys.path.insert(0, str(Path(__file__).resolve().parents[2]))
Hinweis
Eine Alternative zur Änderung der Variablen sys.path ist die Erstellung einer Datei pyproject.toml und die Sicherstellung, dass der Code installierbar ist, sodass er sich wie jede andere Python-Bibliothek verhält. Der Ansatz mit sys.path ist jedoch einfacher.
Aktivieren Sie dann, bevor Sie Doctests zu Ihrer Dokumentation hinzufügen, die Erweiterung doctest in conf.py:
extensions = [
'sphinx.ext.duration',
'sphinx.ext.doctest',
]
Schreiben Sie als Nächstes einen Doctest-Block wie folgt:
>>> import lumache
>>> lumache.get_random_ingredients()
['shells', 'gorgonzola', 'parsley']
Doctests enthalten die auszuführenden Python-Anweisungen, denen >>>, die Standard-Python-Interpreter-Eingabeaufforderung, vorangestellt ist, sowie die erwartete Ausgabe jeder Anweisung. Auf diese Weise kann Sphinx prüfen, ob die tatsächliche Ausgabe mit der erwarteten übereinstimmt.
Um zu sehen, wie ein Doctest-Fehler aussieht (im Gegensatz zu einem Codefehler wie oben), schreiben wir zunächst den Rückgabewert falsch. Fügen Sie daher eine Funktion get_random_ingredients wie folgt hinzu:
def get_random_ingredients(kind=None):
return ["eggs", "bacon", "spam"]
Sie können nun make doctest ausführen, um die Doctests Ihrer Dokumentation auszuführen. Anfangs wird dies einen Fehler anzeigen, da der tatsächliche Code nicht wie angegeben funktioniert.
(.venv) $ make doctest
Running Sphinx v4.2.0
loading pickled environment... done
...
running tests...
Document: usage
---------------
**********************************************************************
File "usage.rst", line 44, in default
Failed example:
lumache.get_random_ingredients()
Expected:
['shells', 'gorgonzola', 'parsley']
Got:
['eggs', 'bacon', 'spam']
**********************************************************************
...
make: *** [Makefile:20: doctest] Error 1
Wie Sie sehen können, meldet Doctest die erwarteten und tatsächlichen Ergebnisse zur einfachen Überprüfung. Es ist nun an der Zeit, die Funktion zu korrigieren:
def get_random_ingredients(kind=None):
return ["shells", "gorgonzola", "parsley"]
Und schließlich meldet make doctest Erfolg!
Bei großen Projekten kann dieser manuelle Ansatz jedoch etwas mühsam werden. Im nächsten Abschnitt erfahren Sie, wie Sie den Prozess automatisieren.
Andere Sprachen (C, C++, andere)¶
Objekte dokumentieren und Querverweise darauf erstellen¶
Sphinx unterstützt auch die Dokumentation und Querverweise auf Objekte, die in anderen Programmiersprachen geschrieben sind. Es gibt vier zusätzliche integrierte Domänen: C, C++, JavaScript und reStructuredText. Drittanbietererweiterungen können Domänen für weitere Sprachen definieren, wie z. B.:
Um beispielsweise eine C++-Typdefinition zu dokumentieren, würden Sie die integrierte Direktive cpp:type wie folgt verwenden:
.. cpp:type:: std::vector<int> CustomList
A typedef-like declaration of a type.
Was folgendes Ergebnis ergeben würde:
-
typedef std::vector<int> CustomList¶
Eine typedef-ähnliche Deklaration eines Typs.
Alle diese Direktiven generieren dann Referenzen, die mithilfe der entsprechenden Rolle mit Querverweisen versehen werden können. Um beispielsweise die vorherige Typdefinition zu referenzieren, können Sie die Rolle cpp:type wie folgt verwenden:
Cross reference to :cpp:type:`CustomList`.
Was zu einem Hyperlink zur vorherigen Definition führen würde: CustomList.