Bonjour,
pour le plaisir, mais aussi par nécessité, je me suis lancé dans la création d'un outil pour récupérer les docstrings d'un fichier Python. Voici un 1er brouillon qui montre les grandes lignes :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#! /usr/bin/env python3
 
# Source :
#    http://docs.python.org/py3k/library/ast.html
#    http://pypi.python.org/pypi/pyRegurgitator/0.1.1
 
import ast
 
IaNDENT_INCREASE = 4
 
def astStupidPrint(oneNode):
    """To quickly see what is done by the module "ast"."""
    for oneNode in ast.iter_child_nodes(astTree):
        print('--', oneNode._fields, ast.dump(oneNode), sep="\n")
 
def docstringPrint(oneNode, indentLevel = -INDENT_INCREASE, className = '', infoToPrint = ''):
    #print(type(oneNode))
 
    if isinstance(oneNode, ast.Expr) and isinstance(oneNode.value, ast.Str):
        print(' '*indentLevel + '=== DOCSTRING {} ==='.format(infoToPrint),
              ' '*(indentLevel + INDENT_INCREASE) + oneNode.value.s.replace('\n',
                                                                      '\n' + ' '*(indentLevel + INDENT_INCREASE)),
              sep="\n")
 
    elif 'body' in oneNode._fields:
        if isinstance(oneNode, ast.FunctionDef):
            if className:
                infoToPrint = 'METHOD OF "{0}" :: {1}'.format(className,
                                                              oneNode.name)
            else:
                infoToPrint = 'FUNCTION :: ' + oneNode.name
        elif isinstance(oneNode, ast.ClassDef):
            infoToPrint = 'CLASS :: ' + oneNode.name
            className = oneNode.name
        else:
            infoToPrint = 'CURRENT MODULE OR FILE'
 
        content = getattr(oneNode, 'body')
        if content:
            for onePiece in content:
                docstringPrint(oneNode = onePiece,
                               indentLevel = indentLevel + INDENT_INCREASE,
                               className = className,
                               infoToPrint = infoToPrint)
 
if __name__ == '__main__':
    file = open('test.py')
    astTree = ast.parse(file.read())
#    astStupidPrint(astTree)
#    print()
    docstringPrint(astTree)
Le fichier test.py est le suivant :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#! /usr/bin/env python3
 
"""1ère doc du fichier
sur deux lignes"""
 
def myFunction(x=0, y="1"):
    """Doc de la fonction nommée myFunction"""
    x=3
# Un commentaire.
    z = x+y
    return z
 
"""2nde docstring mal placée..."""
 
print(myFunction(5,6))
 
class bidon():
    """Doc de la classe bidon"""
 
    def __init__(self):
        """1ère doc de la méthode __init__ de la classe bidon"""
        ...
        """2ème doc mal placée de la méthode __init__"""
Ceci me renvoie :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
=== DOCSTRING CURRENT MODULE OR FILE ===
    1ère doc du fichier
    sur deux lignes
    === DOCSTRING FUNCTION :: myFunction ===
        Doc de la fonction nommée myFunction
=== DOCSTRING CURRENT MODULE OR FILE ===
    2nde docstring mal placée...
    === DOCSTRING CLASS :: bidon ===
        Doc de la classe bidon
        === DOCSTRING METHOD OF "bidon" :: __init__ ===
            1ère doc de la méthode __init__ de la classe bidon
        === DOCSTRING METHOD OF "bidon" :: __init__ ===
            2ème doc mal placée de la méthode __init__
J'essaierais d'améliorer ceci pour obtenir un mini outil de documentation à la sauce epydoc mais en plus facile à personnaliser.

De plus en ayant toutes les docstrings, on peut envisager un moyen de faire des tutos qui affichent le code morcelé avec entre chaque morceau des commentaires en ayant juste à taper quelque chose comme :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
for i in range(5):
    print(i)
""" Nous avons ici une première façon de taper une boucle..."""
i = 0
while(i < 5):
    print(i)
"""Voici une autre méthode pour obtenir le même résultat que précédemment..."""
Ensuite un petit prog. Python donnerait la mise en forme suivante :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
for i in range(5):
    print(i)
Nous avons ici une première façon de taper une boucle...
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
i = 0
while(i < 5):
    print(i)
Voici une autre méthode pour obtenir le même résultat que précédemment...
PS : merci à nardo47 de m'avoir dirigé vers ast.