Projet

Général

Profil

DocumentationCodeBonnesPratiques » Historique » Version 23

Philippe Caseiro, 25/04/2014 11:01

1 20 Daniel Dehennin
{{toc}}
2 20 Daniel Dehennin
3 1 Emmanuel GARETTE
h1. DocumentationCodeBonnesPratiques
4 1 Emmanuel GARETTE
5 18 Gwenael Remond
**cette page concerne la documentation développeur**
6 18 Gwenael Remond
(voir aussi [[TestsCodeBonnesPratiques]] pour les autres bonnes pratiques développeur)
7 18 Gwenael Remond
8 1 Emmanuel GARETTE
h2. Généralité
9 1 Emmanuel GARETTE
10 1 Emmanuel GARETTE
* La documentation technique doit être en anglais.
11 5 Gérald Schwartzmann
* Elle est placée dans les docstrings du code.
12 1 Emmanuel GARETTE
13 1 Emmanuel GARETTE
h2. Description du module
14 1 Emmanuel GARETTE
15 12 Daniel Dehennin
La docstring du module est placée en haut du fichier juste après le "shebang":https://fr.wikipedia.org/wiki/Shebang, la déclaration d’"encodage des caractères":https://fr.wikipedia.org/wiki/Codage_de_caract%C3%A8res et la licence du code.
16 2 Gwenael Remond
17 1 Emmanuel GARETTE
<pre>
18 12 Daniel Dehennin
#!/usr/bin/python
19 12 Daniel Dehennin
# -*- coding: utf-8 -*-
20 12 Daniel Dehennin
#
21 16 Emmanuel GARETTE
##########################################################################
22 16 Emmanuel GARETTE
# <nom du projet>
23 19 Daniel Dehennin
# Copyright © 2013 Pôle de compétences EOLE <eole@ac-dijon.fr>
24 14 Daniel Dehennin
#
25 16 Emmanuel GARETTE
# License CeCILL:
26 16 Emmanuel GARETTE
#  * in french: http://www.cecill.info/licences/Licence_CeCILL_V2-fr.html
27 16 Emmanuel GARETTE
#  * in english http://www.cecill.info/licences/Licence_CeCILL_V2-en.html
28 16 Emmanuel GARETTE
##########################################################################
29 2 Gwenael Remond
</pre>
30 2 Gwenael Remond
31 11 Daniel Dehennin
La docstring doit contenir :
32 1 Emmanuel GARETTE
* description rapide en une phrase du module ;
33 1 Emmanuel GARETTE
* description avancée qui explique le rôle du module ;
34 1 Emmanuel GARETTE
* des exemples simples d'utilisation.
35 1 Emmanuel GARETTE
36 1 Emmanuel GARETTE
Les exemples peuvent être un prompt :
37 1 Emmanuel GARETTE
38 1 Emmanuel GARETTE
<pre>
39 1 Emmanuel GARETTE
    >>> is_locked()
40 1 Emmanuel GARETTE
    True
41 1 Emmanuel GARETTE
</pre>
42 1 Emmanuel GARETTE
43 1 Emmanuel GARETTE
ou une portion de code :
44 1 Emmanuel GARETTE
45 1 Emmanuel GARETTE
<pre>
46 1 Emmanuel GARETTE
    ::
47 1 Emmanuel GARETTE
48 1 Emmanuel GARETTE
        from toto.titi import is_locked
49 1 Emmanuel GARETTE
50 1 Emmanuel GARETTE
        toto()
51 1 Emmanuel GARETTE
        is_locked()
52 1 Emmanuel GARETTE
</pre>
53 1 Emmanuel GARETTE
54 1 Emmanuel GARETTE
h2. Docstring des méthodes
55 1 Emmanuel GARETTE
56 3 Gwenael Remond
Seules les méthodes publiques (qui ne commencent pas par "_") seront mises dans la documentation (mais les méthodes privées sont aussi à documenter).
57 1 Emmanuel GARETTE
58 1 Emmanuel GARETTE
La docstring doit contenir :
59 1 Emmanuel GARETTE
60 1 Emmanuel GARETTE
* description rapide en une phrase de la méthode ;
61 1 Emmanuel GARETTE
* si nécessaire une description avancée qui explique le rôle du module ;
62 1 Emmanuel GARETTE
* si nécessaire des exemples simples d'utilisation.
63 1 Emmanuel GARETTE
* les paramètres de la façon suivante (xxx étant le nom du paramètre et yyyyyy la description) :
64 1 Emmanuel GARETTE
65 1 Emmanuel GARETTE
<pre>
66 1 Emmanuel GARETTE
    :param xxx: yyyyyy
67 1 Emmanuel GARETTE
</pre>
68 1 Emmanuel GARETTE
69 1 Emmanuel GARETTE
Si nécessaire les valeurs de retour (yyyyyy étant la description) :
70 1 Emmanuel GARETTE
71 1 Emmanuel GARETTE
<pre>
72 1 Emmanuel GARETTE
    :return: yyyyyy
73 1 Emmanuel GARETTE
</pre>
74 1 Emmanuel GARETTE
75 4 Gwenael Remond
plus d'info sur la syntaxe des docstrings: http://sphinx-doc.org/domains.html#info-field-lists
76 4 Gwenael Remond
77 1 Emmanuel GARETTE
h2. Docstring des classes
78 1 Emmanuel GARETTE
79 10 Gwenael Remond
comme pour la docstring des modules (mais sans la licence)
80 8 Gwenael Remond
81 8 Gwenael Remond
h2. Tips
82 8 Gwenael Remond
83 8 Gwenael Remond
il est possible de faire un lien portant directement sur le redmine de deux manières :
84 8 Gwenael Remond
85 8 Gwenael Remond
<pre> 
86 8 Gwenael Remond
87 8 Gwenael Remond
:issue:`410` 
88 8 Gwenael Remond
89 8 Gwenael Remond
</pre> 
90 8 Gwenael Remond
91 8 Gwenael Remond
est un lien qui porte directement sur la demande 410
92 8 Gwenael Remond
93 8 Gwenael Remond
et
94 8 Gwenael Remond
95 8 Gwenael Remond
<pre>
96 8 Gwenael Remond
97 8 Gwenael Remond
 :eole:`/projects/creole/wiki/Lock24`
98 8 Gwenael Remond
99 8 Gwenael Remond
</pre>
100 8 Gwenael Remond
101 8 Gwenael Remond
qui est simplement un raccourci vers http://dev-eole.ac-dijon.fr/projects/creole/wiki/Lock24
102 17 Daniel Dehennin
103 17 Daniel Dehennin
h2. Exemples
104 17 Daniel Dehennin
105 17 Daniel Dehennin
Plusieurs fichiers sources ont reçu une attention assez particulière sur la documentation :
106 17 Daniel Dehennin
107 17 Daniel Dehennin
- python-pyeole:source:pyeole/decorator.py
108 17 Daniel Dehennin
- python-pyeole:source:pyeole/log.py
109 17 Daniel Dehennin
- python-pyeole:source:pyeole/lock.py
110 21 Philippe Caseiro
111 21 Philippe Caseiro
h2. Traduction et python
112 22 Philippe Caseiro
113 22 Philippe Caseiro
Voici un petit aide mémoire pour traduire une application python de la manière la plus simple possible.
114 22 Philippe Caseiro
115 22 Philippe Caseiro
Pour traduire une application il faut en premier lieux une bibliothèque qui gère les traductions, la première
116 22 Philippe Caseiro
qui viens à l'esprit est gettext, donc logiquement nous allons nous tourner vers python-gettext.
117 22 Philippe Caseiro
118 22 Philippe Caseiro
Il faut noter qu'il est important de faire les choses dans l'ordre, les messages par défaut des applications doivent être dans une seule et unique langue, l'usage 
119 22 Philippe Caseiro
est de tout écrire en anglais et ensuite de mettre une traduction pour les autres langues.
120 22 Philippe Caseiro
121 22 Philippe Caseiro
Le principe de gettext est de remplacer tous les messages par l'appel à une "fonction/méthode/whatever" qui vais
122 22 Philippe Caseiro
faire les opérations de traduction.
123 22 Philippe Caseiro
124 22 Philippe Caseiro
Dans le monde gettext cette "fonction" a pour nom '_'. 
125 22 Philippe Caseiro
126 22 Philippe Caseiro
La première chose a faire est de mettre a disposition une "fonction" '_' dans votre appli python. (Les exemples suivants proviennent de pyeole)
127 22 Philippe Caseiro
128 22 Philippe Caseiro
h3. i18n.py
129 22 Philippe Caseiro
130 22 Philippe Caseiro
On crée un "module" i18n.py (mais il pourrais très bien avoir un autre nom) et on y fait les déclarations et les initialisation nécessaires pour la traduction.
131 22 Philippe Caseiro
132 22 Philippe Caseiro
* Dans ce module on importe gettext et les modules nécessaires a la gestion de la traduction (python-gettext)
133 22 Philippe Caseiro
<pre>
134 22 Philippe Caseiro
import gettext # Gettext lui même
135 22 Philippe Caseiro
import os      # Pour les variables d'environement LANG/LC_ALL
136 22 Philippe Caseiro
import sys     # Pour la gestion des fichiers de traduction
137 22 Philippe Caseiro
import locale  # Pour la gestion des "locale"
138 22 Philippe Caseiro
</pre>
139 22 Philippe Caseiro
* On définis le nom du domaine de traduction (le plus souvent le nom de l'application)
140 22 Philippe Caseiro
<pre>
141 22 Philippe Caseiro
APP_NAME = 'pyeole'
142 22 Philippe Caseiro
</pre>
143 22 Philippe Caseiro
* On récupère les répertoires qui vont contentir les traductions
144 22 Philippe Caseiro
<pre>
145 22 Philippe Caseiro
# Traduction dir
146 22 Philippe Caseiro
APP_DIR = os.path.join(sys.prefix, 'share')
147 22 Philippe Caseiro
LOCALE_DIR = os.path.join(APP_DIR, 'locale')
148 22 Philippe Caseiro
</pre>
149 22 Philippe Caseiro
* On récupère la langue par défaut et on y ajoute l'anglais pour les messages non traduits
150 23 Philippe Caseiro
<pre>
151 22 Philippe Caseiro
# Default Lanugage
152 22 Philippe Caseiro
DEFAULT_LANG = os.environ.get('LANG', '').split(':')
153 1 Emmanuel GARETTE
DEFAULT_LANG += ['en_US']
154 23 Philippe Caseiro
</pre>
155 23 Philippe Caseiro
* On définis la langue par défaut (je ne suis pas certain que cette partie ne soit pas inutile :)
156 23 Philippe Caseiro
<pre>
157 22 Philippe Caseiro
languages = []
158 22 Philippe Caseiro
lc, encoding = locale.getdefaultlocale()
159 22 Philippe Caseiro
if lc:
160 22 Philippe Caseiro
    languages = [lc]
161 1 Emmanuel GARETTE
162 1 Emmanuel GARETTE
languages += DEFAULT_LANG
163 23 Philippe Caseiro
</pre>
164 23 Philippe Caseiro
* On fait les initialisations gettext
165 23 Philippe Caseiro
<pre>
166 1 Emmanuel GARETTE
mo_location = LOCALE_DIR
167 1 Emmanuel GARETTE
168 23 Philippe Caseiro
gettext.find(APP_NAME, mo_location) # On cherche les traductions
169 23 Philippe Caseiro
gettext.textdomain(APP_NAME)        # On crée le domaine de traduction (ou il vas chercher les messages)
170 23 Philippe Caseiro
gettext.bind_textdomain_codeset(APP_NAME, "UTF-8") # On définis le jeux de caracètres des traductions (utf8)
171 23 Philippe Caseiro
</pre>
172 23 Philippe Caseiro
* On initialise l'objet qui vas réaliser les traductions pour notre application 
173 23 Philippe Caseiro
<pre>
174 22 Philippe Caseiro
t = gettext.translation(APP_NAME, fallback=True)
175 23 Philippe Caseiro
</pre>
176 23 Philippe Caseiro
* Enfin on créer la "fonction/methode/whatever" '_' :
177 23 Philippe Caseiro
<pre>
178 1 Emmanuel GARETTE
def _(msg):
179 23 Philippe Caseiro
    return t.ugettext(msg) # on retourne le résultat de la traduction ! ugettext peut poser problème il ne prend que des chaines utf8
180 1 Emmanuel GARETTE
</pre>