Developpez.com

Club des développeurs et IT pro
Plus de 4 millions de visiteurs uniques par mois

Pyreverse

Génération automatique de diagrammes UML

Lorsque l'on développe un logiciel un tant soit peu important, en termes de code, on se trouve rapidement face au besoin de tracer les noms des classes, des variables…

Pour y parvenir, nous utilisons habituellement les diagrammes UML. Il peut cependant s'avérer pénible, selon la taille de notre projet de le faire à la main.

Bonne nouvelle, il existe en Python, un moyen d'automatiser tout cela. Partons à la découverte de Pyreverse.

6 commentaires Donner une note à l'article (5)

Article lu   fois.

L'auteur

Profil ProSite personnel

Liens sociaux

Viadeo Twitter Facebook Share on Google+   

I. Introduction

Pyreverse est un outil en ligne de commande qui permet de scanner le code Python d'un projet afin de générer, de façon entièrement automatique, un diagramme UML.

Cet outil, développé par la société Logilab, est depuis septembre 2008 intégré à Pylint. Une simple installation via pip vous permettra alors d'en disposer pleinement.

Dans cet article, tous les codes sont exécutés en Python 3 exclusivement.

II. Possibilités offertes

Pyreverse permet de générer des diagrammes UML avec les caractéristiques suivantes :

  • attributs de classes, avec si possible leur type ;
  • méthodes de classe ;
  • liens d'héritage entre classes ;
  • liens d'association entre classes ;
  • représentations des exceptions.

Côté fichier de sortie, Pyreverse ne propose nativement que deux formats : le dot et le vcg.

Même si le fichier généré ne correspond pas à 100 % à vos attentes, il vous permettra tout de même de vous simplifier un minimum le travail.

III. Ajoutons des formats de sortie

Comme vu précédemment, par défaut, seuls deux formats de sortie sont possibles : dot et vcg.

Cela limitant, basiquement, beaucoup les possibilités, il est possible d'augmenter la quantité des formats de sortie : l'installation de GraphViz.

Graphviz ne doit pas être installé depuis pip, mais depuis l'installeur dédié à votre OS, que vous pourrez trouver sur le site officiel de l'outil.
Une fois installé, il vous faudra modifier votre variable d'environnement PATH sous Windows, afin d'y ajouter le chemin vers le dossier « GraphvizX.YZ\bin ».

Pyreverse vous propose alors les formats suivants en sus :

canon

cmap

cmap_np

dia

dot

eps

fig

gd

gd2

gif

hpgl

imap

imap_np

ismap

jpe

jpeg

jpg

mif

mp

pcl

pdf

pic

plain

plain-ext

png

ps

ps2

svg

svgz

tk

vml

vmlz

vrml

vtx

wbmp

xdot

xlib

                     

Les formats proposés deviennent tout de suite plus appréciables, je pense notamment aux formats images (png, jpg), au pdf, ou encore le format dia pour faire de l'édition facilement.

Vous l'aurez compris, dans les faits, Pyreverse sera quasiment toujours utilisé avec Graphviz.

Pour l'ensemble des manipulations qui suivront, nous considérerons que vous avez correctement installé et paramétré Pyreverse et Graphviz.

IV. Les options

Pyreverse dispose d'un certain nombre d'options. Voici un récapitulatif des principales :

Option courte

Option verbeuse

Description

-a <level>

--show-ancestors=<level>

Permet de stipuler combien de niveaux d'héritage afficher.

-A

--all-ancestors

Permet d'afficher tout l'arbre d'héritage.

-b

--show-builtin

Permet d'afficher les classes des objets builtin dans le diagramme.

-f <mode>

--filter-mode=<mode>

Permet de filtrer ce qu'il faut faire apparaître dans le diagramme. Quatre filtres sont possibles :

  • PUB_ONLY ;
  • SPECIAL ;
  • OTHER ;
  • ALL.

Par défaut, le filtre est à PUB_ONLY.

-k

--only-classnames

Génère un diagramme exclusivement avec les noms des classes.

-m [yn]

--module-names=[yn]

Permet d'inclure ou non ([yn] à y pour oui (yes) ou à n pour non (no)) le nom des modules dans la représentation des classes. Pas de valeur par défaut.

-o <format>

--output=<format>

Permet de stipuler le format de sortie. Le format doit être l'un de ceux stipulés précédemment. Par défaut, il s'agit du format dot.

-p <project name>

--project=<project name>

Permet de stipuler le nom du projet pour la génération du nom du fichier de sortie.

-s <level>

--show-associated=<level>

Permet d'afficher les liaisons liées aux imports (création d'objets) sur le nombre de niveaux stipulés.

-S

--all-associated

Permet d'afficher toutes les liaisons liées aux imports.

V. Mise en œuvre

Pour mettre en œuvre cet outil, nous allons nous appuyer sur un exemple déjà utilisé dans le tutoriel sur l'héritage. Nous aurons quatre classes :

  • Voiture
  • Citroen
  • CB
  • CitroenDs

La dernière héritera des deux premières et possédera des attributs privés et protégés. On y surchargera également la fonction spéciale « __del__ ». Enfin, nous considérerons que le propriétaire ajoute une CB dans sa voiture.

La commande est à exécuter dans le dossier où se trouve le code que l'on désire analyser.

Nous aurons donc la structure suivante :

voiture.py
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
class Voiture():
    def __init__(self):
        self.nombre_roues = 4
        self.nombre_fauteuils = 1
        self.moteur = False
        self.volant = True

    def start_moteur(self):
        self.moteur = True
        return self.moteur

    def stop_moteur(self):
        self.moteur = False
        return self.moteur

    def statut_moteur(self):
        return self.moteur


if __name__ == "__main__":
    ma_voiture_basique = Voiture()
    print(ma_voiture_basique.statut_moteur())
    ma_voiture_basique.start_moteur()
    print(ma_voiture_basique.statut_moteur())
citroen.py
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
class Citroen():
    def __init__(self):
        self.type_suspension = "Hydractives"
        self.logo = "Chevrons"
        self.marque = "Citroen"


if __name__ == "__main__":
    ma_citroen = Citroen()
    print(ma_citroen.type_suspension)
    print(ma_citroen.logo)
cb.py
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
class CB():
    def __init__(self):
        self.marque = "Citizen-Band"


if __name__ == "__main__":
    ma_cb = CB()
    print(ma_cb.marque)
citroen_ds.py
Sélectionnez
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.
from voiture import Voiture
from citroen import Citroen
from cb import CB


class CitroenDs(Voiture, Citroen):
    def __init__(self):
        Voiture.__init__(self)
        Citroen.__init__(self)
        self.modele = "DS moderne (>2000)"
        self._option_payante_ds_01 = False
        self._option_payante_ds_02 = False
        self._option_payante_ds_03 = False
        self.__option_calculateur_ds_01 = False
        self.__option_calculateur_ds_02 = False
        self.__option_calculateur_ds_03 = False
        self.start_options()
        self.cb = CB()

    def __del__(self):
        print("Suppression de la voiture")

    def start_options(self):
        if _option_payante_ds_01:
            print("GPS activé")
        if _option_payante_ds_02:
            print("Anti dépassement lignes blanches activé")
        if _option_payante_ds_03:
            print("Freinage urgence activé")

        if __option_calculateur_ds_01:
            print("Puissance moteur: 120 cv")
        elif __option_calculateur_ds_02:
            print("Puissance moteur: 150 cv")
        elif __option_calculateur_ds_03:
            print("Puissance moteur: 180 cv")


if __name__ == "__main__":
    ma_ds = CitroenDs()
    print(ma_ds.marque)
    print(ma_ds.modele)
    print(ma_ds.type_suspension)
    print(ma_ds.statut_moteur())
    ma_ds.start_moteur()
    print(ma_ds.statut_moteur())

Afin de mieux appréhender le fonctionnement des principales options, je vous propose d'y aller progressivement.

V-A. Utilisation basique

Tout d'abord, aucune option précisée :

 
Sélectionnez
1.
Pyreverse -o png citroen_DS.py

Nous récupérons un fichier nommé « classes_No_Name.png ». Ce diagramme représente la classe présente dans le module, avec ses attributs et méthodes.

Image non disponible

Le « No_Name » du nom du fichier vient du fait que nous n'avons stipulé aucun nom de classe lors de l'appel de Pyreverse, chose que nous corrigerons à partir de maintenant.

V-B. Stipuler le nom du fichier généré

 
Sélectionnez
1.
Pyreverse -o png -p demo_DVP citroen_DS.py

Le fichier généré porte désormais le nom de « classes_demo_DVP.png ».

V-C. Afficher les noms des modules

Remarquons tout de même que si les classes figurent bien, nous ne savons dans quel module elles se trouvent. Cela peut être mis à jour via l'option « -my » :

 
Sélectionnez
1.
Pyreverse -o png -p demo_DVP -my citroen_DS.py

Le diagramme généré est désormais plus clair.

Image non disponible

Le nom du module y figure désormais, rendant plus aisée la localisation du code.

V-D. Afficher l'héritage

V-D-1. Afficher tous les héritages

Voyons maintenant l'option « -A » :

 
Sélectionnez
1.
Pyreverse -o png -p demo_DVP -A -my citroen_DS.py

Le nouveau diagramme montre clairement les divers héritages de notre classe CitroenDs.

Image non disponible

V-D-2. Stipuler le niveau d'héritage à afficher

Si vous le désirez, vous pouvez stipuler expressément combien de niveaux d'héritage afficher, afin de vous concentrer sur une classe précise par exemple, ou encore alléger le diagramme.

Notre exemple ne contenant qu'un seul niveau, je vous propose de demander à n'avoir aucun héritage affiché en stipulant comme nombre de niveaux « 0 ».

 
Sélectionnez
1.
Pyreverse -o png -p demo_DVP -a0 -my citroen_DS.py
Image non disponible

V-E. Afficher les imports et les objets

Quand vous générez le diagramme d'une classe, il peut être pratique de connaître les liaisons avec les divers imports.

V-E-1. Afficher toutes les liaisons

Pour cela, nous allons utiliser l'option « -S ».

 
Sélectionnez
1.
Pyreverse -o png -p demo_DVP -A -my -S citroen_DS.py
Image non disponible

Dans ce diagramme, nous voyons clairement, que l'objet « cb » de notre classe CitroenDs dérive de la classe « cb.CB ». Au passage, remarquez en vert le nom de l'objet ; et que la classe dont provient « cb » figurant sur le diagramme, n'est plus stipulé au niveau de la classe « CitroenDs ».

V-E-2. Afficher n niveaux de liaison

Nous allons utiliser ici l'option « -s ». Cette option fonctionne exactement comme l'option « -a ». Pour obtenir le diagramme précédent, il suffit de saisir la ligne de commande suivante.

 
Sélectionnez
1.
Pyreverse -o png -p demo_DVP -A -my -s1 citroen_DS.py

V-E-3. Afficher les objets builtins

S'il est possible d'afficher les imports et objets de notre code, on peut également vouloir faire apparaître ceux fournis par défaut avec Python, ce qu'on appelle les builtins. Pour cela, il faut utiliser l'option « -b ». Et en Python, tout étant objet, votre diagramme va rapidement prendre un peu d'espace.

 
Sélectionnez
1.
Pyreverse -o png -p demo_DVP -A -my -S -b citroen_DS.py
Image non disponible

V-F. Filtrer les informations

Vous disposez de la possibilité de filtrer les méthodes et attributs affichés sur le diagramme, via l'option « -f ». Quatre possibilités vous sont offertes, vous permettant de coller au plus près de vos besoins.

V-F-1. Filtre PUB_ONLY

Il s'agit de l'option « -f PUB_ONLY ».

 
Sélectionnez
1.
Pyreverse -o png -p demo_DVP -A -my -f PUB_ONLY citroen_DS.py

Vous ne voyez aucune différence avec la commande sans l'option « -f ». Normal, il s'agit de l'option par défaut.

Image non disponible

V-F-2. Filtre SPECIAL

Le filtre « -f SPECIAL » filtre les méthodes spéciales (__init__, __del__…). En revanche, aucun filtrage n'est effectué sur les attributs.

 
Sélectionnez
1.
Pyreverse -o png -p demo_DVP -A -my -f SPECIAL citroen_DS.py
Image non disponible

V-F-3. Filtre OTHER

L'option « -f OTHER », est l'inverse du filtre SPECIAL. Il vous permet de ne pas afficher les attributs protégés et privés, mais d'afficher tout de même, toutes les méthodes, quelles qu'elles soient.

 
Sélectionnez
1.
Pyreverse -o png -p demo_DVP -A -my -f OTHER citroen_DS.py
Image non disponible

V-F-4. Filtre ALL

Si vous désirez tout afficher sans distinction, ni filtrage précis, il vous suffit d'utiliser « -f ALL ».

 
Sélectionnez
1.
Pyreverse -o png -p demo_DVP -A -my -f ALL citroen_DS.py
Image non disponible

V-G. Épurer le diagramme

Vient enfin la dernière option, « -k ». Cette dernière vous permet d'épurer l'affichage en le limitant simplement aux modules, classes et objets. Comprenez que nous ne ferons alors figurer ni attributs, ni méthodes.

 
Sélectionnez
1.
Pyreverse -o png -p demo_DVP -A -my -S -b -k citroen_DS.py
Image non disponible

VI. Conclusion

Comme nous venons de le voir, l'outil Pyreverse est très simple d'emploi.

Couplé avec Graphviz, il vous permettra de générer simplement des diagrammes UML, éditables ou non selon le format utilisé, qui vous seront fort utiles.

J'espère que cet article vous a plu et que la découverte de cet outil vous permettra de vous simplifier la vie pour vos futurs développements.

VII. Remerciements

Merci aux personnes suivantes pour leur aide :

Vous avez aimé ce tutoriel ? Alors partagez-le en cliquant sur les boutons suivants : Viadeo Twitter Facebook Share on Google+   

  

Licence Creative Commons
Le contenu de cet article est rédigé par Alexandre GALODE et est mis à disposition selon les termes de la Licence Creative Commons Attribution - Pas d’Utilisation Commerciale - Partage dans les Mêmes Conditions 3.0 non transposé.
Les logos Developpez.com, en-tête, pied de page, css, et look & feel de l'article sont Copyright © 2013 Developpez.com.