Initial commit
This commit is contained in:
193
documentation/11-code-documentation.md
Normal file
193
documentation/11-code-documentation.md
Normal file
@ -0,0 +1,193 @@
|
||||
---
|
||||
title: Documenter du code Python
|
||||
author: Steve Kossouho
|
||||
---
|
||||
|
||||
# Documenter du code Python
|
||||
|
||||
----
|
||||
|
||||
## Documenter du code ?
|
||||
|
||||
En Python, comme dans d'autres langages, vous savez que l'on peut introduire des commentaires dans le code.
|
||||
Il suffit d'utiliser le symbole `(#)` dans une ligne de code, et ce qui suit sera considéré comme commentaire.
|
||||
|
||||
Mais saviez-vous que Python considère le concept de documentation comme étant à part ?
|
||||
|
||||
----
|
||||
|
||||
```{.python .numberLines}
|
||||
print(__doc__) # Ne provoque pas d'erreur, mais affiche `None`
|
||||
```
|
||||
|
||||
Les modules, packages, classes, fonctions et méthodes sont toujours, lorsque vous exécutez l'interpréteur Python,
|
||||
équipés d'attributs nommés `__doc__`. (C'est l'interpréteur qui ajoute l'attribut automatiquement, entre autres
|
||||
fonctionnements magiques)
|
||||
Tout module possède implicitement une variable `__doc__` disponible dans son namespace/scope.
|
||||
Cet attribut « magique » laisse entendre que la notion de documentation fait partie intégrante du langage Python.
|
||||
|
||||
----
|
||||
|
||||
### Documentation dans la bibliothèque standard
|
||||
|
||||
```{.python .numberLines}
|
||||
import sqlite3
|
||||
|
||||
print(sqlite3.__doc__) # documentation du module SQLite3
|
||||
```
|
||||
|
||||
Ici, on importe un module écrit par un développeur tiers, pour voir si l'on est capable de
|
||||
récupérer quelque chose dans son attribut `__doc__`{.python}.
|
||||
|
||||
----
|
||||
|
||||
## Comment on fait pareil qu'eux ?
|
||||
|
||||
Pour documenter un module, c'est finalement assez simple :
|
||||
|
||||
```{.python .numberLines}
|
||||
"""Texte de documentation du module."""
|
||||
import os, sys
|
||||
print(os.linesep, sys.getwindowsversion())
|
||||
```
|
||||
|
||||
Il faut, en première instruction du module, écrire une chaîne de caractères. Par convention, il faut écrire une chaîne à trois guillemets. En Python, on appelle cela une docstring. (consultez PEP8 docstrings)
|
||||
|
||||
----
|
||||
|
||||
## Qu'est-ce qu'on peut documenter ?
|
||||
|
||||
On peut documenter pas mal de choses avec cette méthode :
|
||||
|
||||
1. Modules et packages;
|
||||
2. fonctions et méthodes;
|
||||
3. classes.
|
||||
|
||||
Les variables ne sont pas documentables directement : elles
|
||||
récupèrent automatiquement la **documentation de leur classe**.
|
||||
|
||||
----
|
||||
|
||||
## Qu'est-ce qu'on met ?
|
||||
|
||||
Pour documenter, par exemple, un module, il y a deux façons de faire :
|
||||
|
||||
1. Si votre documentation tient en une phrase courte.
|
||||
2. Si votre documentation va contenir davantage de texte.
|
||||
|
||||
----
|
||||
|
||||
### Documentation super courte
|
||||
|
||||
Vous pouvez considérer qu'une seule petite phrase peut servir à décrire votre module :
|
||||
|
||||
```{.python .numberLines}
|
||||
"""Traitement des données d'épuration des eaux."""
|
||||
```
|
||||
|
||||
----
|
||||
|
||||
### Documentation plus longue
|
||||
|
||||
```{.python .numberLines}
|
||||
"""
|
||||
Traitement des données d'épuration des eaux.
|
||||
|
||||
Paragraphes de description, d'explication du contenu du module.
|
||||
Possibilité d'ajouter des sections, des exemples, soyez exhaustifs si vous le souhaitez !
|
||||
"""
|
||||
```
|
||||
|
||||
- Une phrase courte de résumé, sur sa propre ligne.
|
||||
- Une ligne vide.
|
||||
- Le corps de la documentation.
|
||||
|
||||
----
|
||||
|
||||
## Documenter une classe, fonction, méthode, package
|
||||
|
||||
- Pour documenter une classe, il suffit d'ajouter une docstring, juste en-dessous de la signature de la classe.
|
||||
- Pour une fonction, ajoutez vos triples guillemets en-dessous de la signature de méthode/fonction.
|
||||
- Pour un package, mettez une docstring au sommet du module `__init__.py`
|
||||
|
||||
----
|
||||
|
||||
## Outils de génération de documentation HTML etc.
|
||||
|
||||
Mieux qu'un long discours, une démo s'impose, avec la bibliothèque `pdoc`.
|
||||
Un outil beaucoup plus long à mettre en place est `sphinx`, qui permet encore davantage.
|
||||
|
||||
```{.bash .numberLines}
|
||||
pip install pdoc # installer la bibliothèque
|
||||
pdoc [nom du module ou nom du script python] # lance un serveur pour tester
|
||||
```
|
||||
|
||||
- [Documentation de pdoc](https://pdoc.dev/docs/pdoc.html)
|
||||
- [Documentation de Sphinx](https://www.sphinx-doc.org/en/master/)
|
||||
|
||||
----
|
||||
|
||||
## Bonus : Donner des indications sur le type des variables et arguments
|
||||
|
||||
Depuis Python 3.5 (fin 2015), le langage propose un moyen d'indiquer aux développeurs, le type attendu de variables et d'arguments de fonctions.
|
||||
|
||||
**Attention cependant** : les indications en question n'ont aucune incidence sur l'exécution du code, c'est-à-dire que l'interpréteur les ignore. Par contre, les développeurs et les environnements de développement, eux, peuvent se servir de ces indications pour proposer de l'autocomplétion dans certains cas.
|
||||
|
||||
----
|
||||
|
||||
Pour annoter une variable et définir quel est son type attendu, on peut :
|
||||
|
||||
```{.python .numberLines}
|
||||
from tartempion import MyClass
|
||||
|
||||
variable1: int = 15 # on indique qu'on attend un entier
|
||||
variable2: str = "Hello" # on attend une chaîne
|
||||
variable3: list = [] # on attend une liste
|
||||
object1: MyClass = MyClass() # on attend un objet d'une classe
|
||||
```
|
||||
|
||||
Un éditeur (tel que PyCharm) ou un outil de vérification en ligne de commande saura vous dire
|
||||
si ailleurs dans votre code, vous ne respectez pas ces indications.
|
||||
|
||||
----
|
||||
|
||||
Le module `typing` de la bibliothèque standard permet de décrire de façon plus avancée des types attendus :
|
||||
|
||||
```python {.numberLines}
|
||||
from typing import Optional, Union, Any, Literal, Callable
|
||||
|
||||
variable: Optional[int] = None # on attend `None` ou un entier
|
||||
multi_types: Union[int, float] = 25 # on attend un entier ou float
|
||||
collection: list[str] = [] # ne fonctionne que dans Python 3.9+
|
||||
shapeshifter: Any = [] # tout et n'importe quoi, explicitement
|
||||
finite_values: Literal["Monday", "Tuesday"] = "Monday" # Valeurs finies
|
||||
function_reference: Callable = range # on attend une fonction
|
||||
```
|
||||
|
||||
À partir de Python 3.11 (novembre 2022), il est possible de remplacer l'`Union` par un opérateur `|` :
|
||||
|
||||
```{.python .numberLines}
|
||||
variable: int | float = 15 # soit un entier soit un flottant devrait y être associé
|
||||
```
|
||||
|
||||
[Section de la documentation officielle de Typing](https://docs.python.org/3/library/typing.html#module-contents)
|
||||
|
||||
----
|
||||
|
||||
On peut faire la même chose avec des arguments de fonctions :
|
||||
|
||||
```{.python .numberLines}
|
||||
# value et default devraient être des entiers
|
||||
def do_some_important_things(value: int, default: int = 1):
|
||||
print(value, default)
|
||||
return None
|
||||
```
|
||||
|
||||
----
|
||||
|
||||
Et on peut également décrire le type attendu du retour des fonctions et méthodes :
|
||||
|
||||
```{.python .numberLines}
|
||||
def do_trivial_things() -> float: # on indique que la fonction retourne un flottant
|
||||
return 100 / 15
|
||||
```
|
Reference in New Issue
Block a user