Dokumentation in Python-Programmen validieren

Aus LinuxUser 04/2024

Dokumentation in Python-Programmen validieren

© parilovv / 123RF.com

Bügeleisen

Zu gutem Code gehört eine saubere Dokumentation. Wurde alles im Code dokumentiert? Funktionieren die Beispiele? Wir zeigen, wie Sie das überprüfen.

Teil 1

Code prüfen

LU 02/2024, S. 84

Teil 2

Code optimieren

LU 03/2024, S. 78

Teil 3

Dokumentation prüfen

LU 04/2023, S. 86

Der erste [1] und zweite Teil [2] unserer Artikelserie rund um guten Python-Code legten den Schwerpunkt auf das Validieren und Optimieren von Python-Code, beispielsweise durch das Identifizieren unnötiger Funktionen und Module. Zu jedem Programmierprojekt gehört, auch wenn sich dieser Schritt kaum großer Beliebtheit erfreut, jedoch genauso Dokumentation. Ohne sie lässt sich der Programmcode nur bedingt nutzen, weil keiner dessen Daseinszweck versteht [3]. Dementsprechend kümmern wir uns nun darum, den Code auf bestehende Dokumentation sowie deren Vollständigkeit und Korrektheit zu überprüfen [4]. Der Fokus liegt hier auf Methoden, die sich automatisieren lassen, um damit im Idealfall CI/CD-Pipelines ausstatten zu können.

Die Tabelle “Werkzeugübersicht” vergleicht die verfügbaren, unter einer freien Lizenz stehenden Werkzeuge und deren Funktion. Darin finden sich Werkzeuge zur stilistischen und orthografischen Prüfung wie PyDocstyle [5], PyLint [6] und PyEnchant [7].

Aufgabe/Funktion

PyDocstyle

Darglint [8]

Interrogate [9]

PyEnchant

PyLint

Docstr-coverage [10]

Doctest [11]

Xdoctest [12]

Pyment [13]

Stil prüfen

x

x

x

Stil umwandeln

x

Rechtschreibprüfung

x

x

Vollständigkeit prüfen

x

x

x

Beispiele prüfen

x

x

Docstrings

Als Docstrings bezeichnet man speziell formatierte Kommentare im Python-Programmcode. Sie bilden die Basis, um daraus später automatisiert Dokumentation zu erzeugen [14]. Verbreitet sind derzeit sechs Stile: gemäß Python Enhancement Proposal (PEP) 257 [15], für Sphinx [16], NumPy [17] / SciPy [18] (Listing 1), Pydoc [19], Epydoc/Epytext [20] und Google Docstrings [21] (Listing 2). Beide Listing-Beispiele stammen aus der Sphinx-Dokumentation.

In welchem Stil Sie die Kommentare schreiben, hängt von dem Werkzeug ab, das die Kommentare in einem nachfolgenden Schritt auswertet und zu Dokumentation in einem anderen Format verarbeitet, beispielsweise zu HTML. Dabei sollten Sie darauf achten, nicht mehrere verschiedene Stile zu mischen, da ansonsten das Werkzeug beim Erstellen der Dokumentation durcheinanderkommt. Sphinx kann ursprünglich nur mit ReStructuredText [22] umgehen. Die Dokumentationsstile NumPy/SciPy [23] erfordern die Erweiterung Napoleon [24], die Sphinx ab Version 1.3 bereits enthält.

Listing 1

Docstrings im Stil von NumPy/SciPy

def func1(arg1, arg2):
  """Summary line.
  Extended description of function.
  Parameters
  ----------
  arg1 : int
    Description of arg1
  arg2 : str
    Description of arg2
  Returns
  -------
  bool
    Description of return value
  """
  return True

Listing 2

Docstrings gemäß Google Python Style Guide

def func2(arg1, arg2):
  """Summary line.
  Extended description of function.
  Args:
    arg1 (int): Description of arg1
    arg2 (str): Description of arg2
  Returns:
    bool: Description of return value
  """
  return True

Stilistisch prüfen

Nun prüfen Sie mithilfe von PyDocstyle, ob die Schreibweise der Docstrings dem gewünschten Stil entspricht und ob alle einheitlich sind. Dazu kennt PyDocstyle den Parameter --convention, gefolgt von der Angabe des Stils: pep257 für PEP 257, numpy für NumPy/SciPy und google für Google Docstrings.

Hinsichtlich der beiden Formate Pydoc und Epydoc/Epytext kann PyDocstyle nicht prüfen. Listing 3 zeigt das Ergebnis für den Stil NumPy/SciPy für Listing 1 und Listing 2. Zusammengefasst finden Sie es in der lokalen Datei docstring-test.py. Dabei identifiziert PyDocstyle auf Grundlage der Stile PEP 257 und Google Docstrings lediglich den ersten Fehler (dritte Zeile). Das entspricht allerdings nicht den Erwartungen.

Listing 3

Konformitätstest NumPy/SciPy

$ pydocstyle --convention=numpy docstring-test.py
docstring-test.py:1 at module level:
    D100: Missing docstring in public module
docstring-test.py:22 in public function `func2`:
    D407: Missing dashed underline after section ('Returns')
docstring-test.py:22 in public function `func2`:
    D406: Section name should end with a newline ('Returns', not 'Returns:')

Umwandeln

Die Prüfung der Docstrings hat mehrere anzupassende Stellen offenbart. Bei wenigen zu korrigierenden Zeilen wie in Listing 3 geht das durchaus von Hand. Steigt die Zahl, greifen Sie auf das Werkzeug Pyment zurück. Es wandelt die Docstrings aus einem Format in ein anderes um und vereinheitlicht so die Dokumentation. Dabei unterstützt es Javadoc [25], ReStructuredText, NumPy/SciPy und das Google-Format.

Im ersten Beispiel (Listing 4, erster Aufruf) erhält Pyment beim Aufruf kein Eingabeformat als Parameter und versucht es dementsprechend automatisch zu erkennen. Als Ausgabeformat ist ReStructuredText voreingestellt. Als Ergebnis liefert Pyment eine Patch-Datei im Format ReStructuredText mit den vorgeschlagenen Änderungen auf der Basis der automatischen Erkennung des Docstring-Formats. Explizite Formatangaben machen Sie gegebenenfalls mithilfe der beiden Parameter -i (--input) und -o (--output), jeweils gefolgt vom gewünschten Format.

Listing 4

Patch-Datei

#### datei.py.patch erzeugen
$ pyment datei.py
#### Patch anwenden
$ patch -p1 < datei.py.patch

Die letzte Zeile des Listings veranschaulicht das Einspielen des erzeugten Patches, Abbildung 1 zeigt seinen Inhalt. Zeilen, die mit einem Minuszeichen beginnen, verschwinden beim Einspielen des Patches in der Zieldatei, Zeilen mit einem vorangestellten Pluszeichen fließen dagegen ein.

Abbildung 1: Die Software markiert einzuf&uuml;gende und zu entfernende Zeilen in der Patch-Datei mithilfe von Plus- und Minuszeichen.

Abbildung 1: Die Software markiert einzufügende und zu entfernende Zeilen in der Patch-Datei mithilfe von Plus- und Minuszeichen.

Der erste Aufruf in Listing 5 zeigt das Erzeugen eines Patches mit NumPy/SciPy als Eingabeformat und dem Google-Stil als Ausgabeformat. Die Option -b (--backup) bewirkt, dass Patch vor dem Einspielen des Patches eine Sicherheitskopie der Zieldatei erzeugt (zweiter Aufruf). Die dadurch erstellte Backup-Datei heißt docstring-test.py.orig. Möchten Sie hingegen direkt korrigieren und somit weder Patch noch Backup erzeugen lassen, nutzen Sie den Parameter -w (letzter Aufruf).

Listing 5

Patches erzeugen

#### datei.py.patch erzeugen
$ pyment -i numpy -o google datei.py
#### Patch mit Backup anwenden
$ patch -b -p1 < datei.py.patch
#### direkte Korrektur
$ pyment -i numpy -o google -w datei.py

Inhaltlich prüfen

Dokumentation hilft nur dann tatsächlich weiter, wenn sie stimmt. Mithilfe des Werkzeugs Darglint kommen Sie Unstimmigkeiten zwischen Programmcode und der Dokumentation auf die Schliche. Es prüft, ob die Angaben im Docstring mit dem Funktionskopf übereinstimmen und somit die Dokumentation aller Parameter vollständig ist. Als Formate des Docstrings akzeptiert Darglint Sphinx, NumPy/SciPy und Google.

Listing 6 zeigt den Aufruf von Darglint mit dem Parameter -s (--docstring-style), gefolgt von der Angabe numpy für das Docstring-Format von NumPy/SciPy. Ganz zu Recht bemängelt das Tool die fehlerhaften Parameter und den nicht beschriebenen Rückgabewert für func2(), da die Dokumentation im falschen Format vorliegt.

Listing 6

Darglint

$ darglint -s numpy docstring-test.py
docstring-test.py:func2:21: DAR101: - arg1
docstring-test.py:func2:21: DAR101: - arg2
docstring-test.py:func2:21: DAR201: - return

Eine ähnliche Ausgabe liefert Darglint, wenn Parameter entweder im Funktionskopf oder der Dokumentation fehlen (Listing 7). Ein Minuszeichen in der Ausgabe besagt, dass der Parameter zwar im Funktionskopf vorhanden, aber nicht dokumentiert ist. Ein Pluszeichen bedeutet das Gegenteil – der Parameter ist zwar dokumentiert, fehlt aber im Funktionskopf. Auf diese Weise kommen zudem Tippfehler und falsche Schreibweisen ans Licht, beispielsweise Buchstabendreher im Namen des Parameters.

Listing 7

Fehlende Parameter aufspüren

$ darglint -s google docstring-test.py
docstring-test.py:func3:41: DAR101: - arg3
docstring-test.py:func3:43: DAR102: + arg2

Vollständigkeit prüfen

Nachdem Sie alle Docstrings vereinheitlicht haben und feststeht, dass keine Parameter unter den Tisch gefallen sind, werfen Sie mithilfe von Docstring-coverage einen Blick auf die Vollständigkeit. Das gewährleistet, dass Sie nicht noch andere Dinge vergessen haben. Listing 8 zeigt die Ausgabe des Werkzeugs, die daran erinnert, noch die Dokumentation für das Modul hinzuzufügen (Zeile 4).

Listing 8

Docstr-coverage

$ docstr-coverage docstring-test.py
Checking python files: 100%|??????????????| 1.00/1.00 [00:00<00:00, 574files/s]
File: "docstring-test.py"
 - No module docstring
 Needed: 4; Found: 3; Missing: 1; Coverage: 75.0%

Häufig finden sich in der Dokumentation kleine Grafiken für unterstützte Formate, sogenannte Badges. Mithilfe des Parameters -b, gefolgt von Pfad und Namen der Bilddatei, erzeugt Docstr-coverage ein Badge zur Abdeckung im SVG-Format.

Rechtschreibung prüfen

Wirkt bestehende Dokumentation stilistisch sauber, heißt das noch nicht automatisch, dass dasselbe für die Orthografie gilt. Fehlern bezüglich Rechtschreibung und Grammatik kommen Sie mit einer passenden Rechtschreibprüfung auf die Spur.

Über PyEnchant besteht von Python aus Zugriff auf die Enchant-Bibliothek [26]. PyLint bietet eine Schnittstelle zu den Unix/Linux-Werkzeugen Ispell, Aspell und Myspell an. Für Flake8 [27] gibt es ein Modul namens Flake8-spellcheck [28], das sich so konfigurieren lässt, dass es ausschließlich Python Docstrings überprüft. Dazu setzt es intern auf das bereits erwähnte PyDocstyle auf.

Beispiele prüfen

Fehlerhafte Beispiele in der Dokumentation erweisen sich häufig als großes Ärgernis. Führen Sie hinterlegte Beispiele aus und entdecken gravierende Unterschiede zwischen den gezeigten und den tatsächlich erzielten Ergebnissen, stellt sich die Frage, was nicht stimmt. Nicht immer sitzt die Fehlerursache vor dem Rechner.

Hier kommen die zwei Pakete Doctest und Xdoctest ins Spiel. Beide suchen nach Programmcode, der in den Docstrings als Beispiel mit passender Ausgabe hinterlegt ist. Doctest und Xdoctest führen den Programmcode aus und prüfen, ob die hinterlegte Ausgabe mit der tatsächlichen Ausgabe übereinstimmt. Sie schlagen Alarm, falls dabei Diskrepanzen auftreten.

Die beiden Werkzeuge unterscheiden sich in zweierlei Hinsicht: Während es sich bei Doctest um einen festen Bestandteil der Python-Distribution handelt, müssen Sie Xdoctest nachinstallieren. Intern setzt Doctest auf reguläre Ausdrücke zum Identifizieren von Fehlern, Xdoctest dagegen auf das Ast-Modul für abstrakte Syntaxbäume [29]. Abbildung 2 zeigt einen Aufruf zur Prüfung von Listing 9, mit dem Ergebnis, dass der erste Aufruf von add() im Beispiel zum dokumentierten Ergebnis passt, der zweite sich jedoch als fehlerhaft erweist.

Listing 9

Python-Code mit Codebeispiel in Docstrings

# calculations.py
def add(a, b):
    """Berechne die Summe aus zwei Zahlenwerten
    Beispielaufruf:
    >>> add(4.0, 2.0)
    6.0
    >>> add(4, 2)
    7.0
    """
    return float(a + b)

Abbildung 2: In <code>calculation.py</code> entspricht lediglich der erste Aufruf von <code>add()</code> der dokumentierten Ausgabe.

Abbildung 2: In calculation.py entspricht lediglich der erste Aufruf von add() der dokumentierten Ausgabe.

Dokumentation erzeugen

Jetzt stimmt Ihre Dokumentation – ein guter Moment, sie in andere Ausgabeformate umzuwandeln. Für eine Ausgabe im Pager wie in Abbildung 3 genügt der Aufruf pydoc3 docstring-test mittels Pydoc völlig. Das Werkzeug liest damit die lokale Datei docstring-test.py aus Listing 1 und Listing 2 und generiert eine passende Ausgabe als Text.

Abbildung 3: Ausgewertete Docstrings lassen sich beispielsweise im Terminal (Pager) ausgeben.

Abbildung 3: Ausgewertete Docstrings lassen sich beispielsweise im Terminal (Pager) ausgeben.

Für eine Ausgabe im Webbrowser erweist sich Pydoc ebenfalls als nützlich. Listing 10 zeigt die nötigten Aufrufe, um aus den enthaltenen Docstrings passende HTML-Dateien zu erzeugen (Abbildung 4).

Listing 10

HTML-Dateien erzeugen

$ pydoc3 -b docstring-test
Server ready at http://localhost:35757/
Server commands: [b]rowser, [q]uit
server>
[...]

Abbildung 4: Ausgewertete Docstrings sehen Sie auf Wunsch optisch aufbereitet im Webbrowser ein.

Abbildung 4: Ausgewertete Docstrings sehen Sie auf Wunsch optisch aufbereitet im Webbrowser ein.

Für Dokumentation mit komplexerer Struktur gilt Sphinx als passendes Mittel der Wahl [30]. Das erfordert jedoch mehr Vorarbeit im Programmcode, die den Rahmen des Artikels sprengen würde. Ausführliche Informationen dazu finden sich in der Dokumentation zu Sphinx und im Python Basics Tutorial.

Zusammenfassung

Fehler und Unstimmigkeiten in einer Dokumentation kommen im Alltag häufig vor. Mit den hier vorgestellten Werkzeugen überprüfen und bereinigen Sie Ihre Dokumentation Schritt für Schritt. Für die regelmäßige Praxis empfiehlt es sich, die Anwendungen projektbezogen in einer Werkzeugkette aneinanderzureihen, um den gesamten Vorgang automatisieren zu können. csi

Danksagung

Der Autor bedankt sich bei Veit Schiele für seine Hilfe und Kritik bei der Vorbereitung des Artikels.

Über den Autor

Frank Hofmann arbeitet bevorzugt von Berlin, Genf und Kapstadt aus als Entwickler, Trainer und Autor. Er gehört zu den Verfassern des Debian-Paketmanagement-Buches [31].

Glossar

CI/CD

Continuous Integration / Continuous Deployment. Bezeichnet in der Softwareentwicklung die Praxis von kontinuierlicher Integration und kontinuierlicher Bereitstellung.

Infos

  1. Guten Python-Code schreiben (Teil 1): Frank Hofmann, “Schnüffelnase”, LU 02/2024, S. 84: https://www.linux-community.de/50379

  2. Guten Python-Code schreiben (Teil 2): Frank Hofmann, “Auf Diät setzen”, LU 03/2024, S. 78: https://www.linux-community.de/50220

  3. “Documenting Python Code and Projects”: https://testdriven.io/blog/documenting-python/

  4. Python Basics Tutorial, Dokumentieren: https://python-basics-tutorial.readthedocs.io/de/latest/document/index.html

  5. PyDocstyle: http://www.pydocstyle.org/en/stable/

  6. PyLint: https://pylint.org

  7. PyEnchant: https://pypi.org/project/pyenchant/

  8. Darglint: https://github.com/terrencepreilly/darglint

  9. Interrogate: https://pypi.org/project/interrogate/

  10. Docstr-coverage: https://pypi.org/project/docstr-coverage/

  11. Doctest: https://docs.python.org/3/library/doctest.html

  12. Xdoctest: https://github.com/Erotemic/xdoctest

  13. Pyment: https://pypi.org/project/pyment/

  14. Docstrings im Python Tutorial: https://www.datacamp.com/tutorial/docstrings-python

  15. PEP 257: https://peps.python.org/pep-0257/

  16. Python Sphinx: https://www.sphinx-doc.org

  17. NumPy: https://numpy.org

  18. SciPy: https://scipy.org

  19. Pydoc: https://docs.python.org/3/library/pydoc.html

  20. Epydoc: https://epydoc.sourceforge.net

  21. Google Python Style Guide: https://google.github.io/styleguide/pyguide.html

  22. ReStructuredText: https://docutils.sourceforge.io/rst.html

  23. “Documenting Python code”: https://cerfacs.fr/coop/python-docs

  24. Napoleon: https://pypi.org/project/sphinxcontrib-napoleon/

  25. Javadoc: https://www.oracle.com/java/technologies/javase/javadoc.html

  26. Enchant: https://abiword.github.io/enchant/

  27. Flake8: https://github.com/pycqa/flake8

  28. Flake8-spellcheck: https://github.com/MichaelAquilina/flake8-spellcheck

  29. Sphinx vs. Asciidoc(tor): Frank Hofmann, Veit Schiele, “Gut angeleitet”, LU 04/2021, S. 86, https://www.linux-community.de/45730

  30. “Automatic documentation generation from code using Sphinx”: https://www.sphinx-doc.org/en/master/tutorial/automatic-doc-generation.html

  31. Debian-Paketmanagement-Buch: https://dpmb.org

DIESEN ARTIKEL ALS PDF KAUFEN
EXPRESS-KAUF ALS PDF
LinuxUser 04/2024 KAUFEN
EINZELNE AUSGABE
ABONNEMENTS
TABLET & SMARTPHONE APPS
E-Mail Benachrichtigung
Benachrichtige mich zu:

Hinweis: Dieser Artikel ist älter als ein Jahr, enthaltene Informationen sind möglicherweise veraltet.

0 Kommentare
Älteste
Neuste Beste Bewertung
Inline Feedbacks
Alle Kommentare anzeigen
Nach oben