Contenu | Rechercher | Menus

Annonce

Ubuntu 16.04 LTS
Commandez vos DVD et clés USB Ubuntu-fr !

Pour en savoir un peu plus sur l'équipe du forum.

Si vous avez des soucis pour rester connecté, déconnectez-vous puis reconnectez-vous depuis ce lien en cochant la case
Me connecter automatiquement lors de mes prochaines visites.

#1 Le 11/09/2017, à 16:02

Pierrot86

DéclaTravaux - Déclaration des travaux réalisés à proximité de réseaux

Bonjour à tous,

Je me permets d'ouvrir un sujet pour vous faire part d'un projet réalisé sur mon temps libre : DéclaTravaux.

Il s'agit d'un utilitaire, écrit en Python 3, dont le but est de permettre aux maîtres d'ouvrage et/ou exécutant de travaux de transmettre, par courriel, les déclarations requises auprès des exploitants de réseaux. Pour davantage d'informations sur ces obligations déclaratives, je vous renvoie vers la page dédiée du portail Service-Public.fr (https://www.service-public.fr/professionnels-entreprises/vosdroits/F23491).

À la base, j'ai écrit cet utilitaire pour l'un de mes proches, artisan maçon, qui est régulièrement amené à procéder à ce type de déclarations.

L'utilitaire a malheureusement encore été peu testé : il doit exister encore de nombreux bugs / crashs.

S'agissant de mon premier vrai projet, qui plus est en Python, je trouvais intéressant de le partager avec vous. Je précise ici que je suis développeur amateur et débutant, je vous prie donc de bien vouloir me pardonner par avance pour la piètre qualité du code et/ou son organisation.

Compte tenu de la spécificité du besoin auquel répond cet utilitaire, je sais bien que le public d'ubuntu-fr ne sera pas particulièrement intéressé par ce projet. Mais au cas où certains d'entre vous voudraient jeter un coup d'œil au code, voire seraient intéressés par ce projet, je suis bien évidemment preneur de tout commentaire ou toute remarque, notamment en ce qui concerne le code en lui-même, ou sur l'organisation du projet sur Gitlab.

Enfin, comme vous pourrez le constater sur la page du projet, le code est placé sous la licence libre CeCILL (version 2.1).

Hors ligne

#2 Le 11/09/2017, à 23:48

Vobul

Re : DéclaTravaux - Déclaration des travaux réalisés à proximité de réseaux

Salut,

Déjà bravo d'avoir fait ce logiciel qui je l'espère sera utile à beaucoup de monde et merci de le partager. Je vois que tu maîtrises la partie "l'open source c'est le bien" wink

Remarque : dans le code, mon avis perso c'est de toujours coder en anglais. Même si ton public est français, le code doit être en anglais. À chaque fois que je vois du code écrit en français je me dis que c'est dommage de couper la participation des non francophones (ça marche avec les autres langues que l'anglais hein). Tous les codeurs du monde savent lire l'anglais. Si ton code est en anglais, il pourra être repris et amélioré par une communauté bien plus grande que s'il est dans une langue autre. Certes beaucoup de gens parlent et lisent le français, mais on est plus au 17ème siècle, désormais c'est l'anglais qui domine.

Exemple concret : la fonction getParametres. En français ça devrait être Paramètres, et non pas Parametres. Et puis "get", c'est de l'anglais non ? Donc tu te retrouves avec un truc dans une langue hybride et ça craint du boudin. Alors que getParameters(), ça tout le monde comprend tout de suite. Francophone ou pas. De plus, l'anglais a pas mal d'avantage côté code, les mots de trois lettres (get/set/die/put), pas d'accents, moins de lettres à taper pour décrire la même chose qu'en français. Bien sûr cela ne doit pas empêcher que le logiciel parle français. Mais au lieu de hardcoder les strings en français, utilise un outil i18n pour qu'à l'avenir ajouter une langue soit aussi simple qu'ajouter un fichier de traductions. https://docs.python.org/3/library/i18n.html. Et puis python est tellement naturel comme language, c'est beaucoup plus lisible quand c'est en anglais… Là lire le code c'est passer sans cesse du français à l'anglais tous les deux mots c'est éreintant.

J'espère que j'ai made my point tongue

Remarque 2 : pourquoi cette ligne ? Un commentaire eut-été bienvenue !

Remarque 3 : la première ligne des fichiers devrait être #!/usr/bin/env python. Il est peut-être nécesssaire d'ajouter un check de la version de python dans le programme afin qu'il quitte si c'est python 2. Mais là t'as mis /usr/bin/python3.5. Or sur mon ordi (avec Archlinux) j'ai 3.6.2, donc si je fais ./main, ça marche pas.

Alors ensuite comme je suis pas trop neuneu je fais "python main.py" et là j'ai une erreur : ModuleNotFoundError: No module named 'PyPDF2'.

Ah tiens, t'aurais pas oublié une étape dans le readme genre pour installer les dépendences ? Regarde ce que c'est que requirements.txt wink

Alors comme je suis pas trop neuneu je fais "sudo pip install pypdf2".

Maintenant l'erreur c'est qu'il trouve pas XDG_CONFIG_HOME. Eh oui, sur mon système la variable XDG_CONFIG_HOME n'existe pas ! Donc il faut que t'ajoutes du code soit pour montrer une belle erreur explicative, soit tu mets ça dans le fichier de conf, soit tu cherches d'autres répertoires. Mais là c'est moche tongue

Alors comme je suis pas trop neuneu je fais "export XDG_CONFIG_HOME=/tmp/yep" et je relance. Ah j'ai une fenêtre, on avance smile Je clique sur paramètres et je rentre ma config. Et oh surprise je retrouve mon mot de passe de ma messagerie électronique dans un fichier texte dans la nature. Pas cool. Le mot de passe smtp devrait être chiffré. Alors oui c'est pas forcément facile à faire, mais ça vaut le coup. Personne ne pourra prendre ce programme au sérieux tant que le mot de passe est stocké en clair. https://www.google.fr/search?q=python+s … ypted+data Et conseil important : n'essaie pas d'inventer ta crypto, utilise une librairie, fais pas le foufou.

Ensuite je vois que par défaut tu mets /home/user/Téléchargements comme dossier. Mais tu devrais te baser sur XDG_DOWNLOAD_DIR vu que t'aimes bien XDG wink

Bon allez pour finir deux trois trucs en vrac :

- fais des paquets et mets sur pypi.org comme ça on peut "pip install declatravaux" et ça gère les dépendances, ça vérifie que c'est python 3 toussah.
- dans getCheminFichierConfig() t'as oublié les macs, non ?
- essaie de ne pas te répéter dans ton code. getParametres et setParametres sont identiques à 80%. Sors le code de là, mets-le dans une autre fonction (genre init()) au lieu de le copier coller ! (principe DRY)
- change le nom du fichier de licence en LICENCE
- ah oui aussi vire les whitespace qu'il y a partout. Dans mon éditeur je les affiche en rouge (https://github.com/ntpeters/vim-better-whitespace).
- pourquoi certains fichiers sont chmod +x et pas d'autres ?

Bon et pour finir sur une bonne note je dirai que pour un premier programme c'est pas mal du tout, on a vu bien pire, et je ne vise personne sur ce forum tongue C'est plutôt organisé et propre. Mais t'as encore un peu de boulot wink

À vous les studios.

Dernière modification par Vobul (Le 11/09/2017, à 23:49)


Vobul

Hors ligne

#3 Le 12/09/2017, à 12:23

Pierrot86

Re : DéclaTravaux - Déclaration des travaux réalisés à proximité de réseaux

Bonjour Vobul,

Tout d'abord un grand merci à toi pour ce retour, c'est vraiment intéressant de pouvoir échanger ici.

Vobul a écrit :

Remarque : dans le code, mon avis perso c'est de toujours coder en anglais. Même si ton public est français, le code doit être en anglais. À chaque fois que je vois du code écrit en français je me dis que c'est dommage de couper la participation des non francophones (ça marche avec les autres langues que l'anglais hein). Tous les codeurs du monde savent lire l'anglais. Si ton code est en anglais, il pourra être repris et amélioré par une communauté bien plus grande que s'il est dans une langue autre. Certes beaucoup de gens parlent et lisent le français, mais on est plus au 17ème siècle, désormais c'est l'anglais qui domine.

Exemple concret : la fonction getParametres. En français ça devrait être Paramètres, et non pas Parametres. Et puis "get", c'est de l'anglais non ? Donc tu te retrouves avec un truc dans une langue hybride et ça craint du boudin. Alors que getParameters(), ça tout le monde comprend tout de suite. Francophone ou pas. De plus, l'anglais a pas mal d'avantage côté code, les mots de trois lettres (get/set/die/put), pas d'accents, moins de lettres à taper pour décrire la même chose qu'en français. Bien sûr cela ne doit pas empêcher que le logiciel parle français. Mais au lieu de hardcoder les strings en français, utilise un outil i18n pour qu'à l'avenir ajouter une langue soit aussi simple qu'ajouter un fichier de traductions. https://docs.python.org/3/library/i18n.html. Et puis python est tellement naturel comme language, c'est beaucoup plus lisible quand c'est en anglais… Là lire le code c'est passer sans cesse du français à l'anglais tous les deux mots c'est éreintant.

J'espère que j'ai made my point tongue

À vrai dire, le choix du français est plutôt volontaire. L'utilitaire répondant à une problématique purement française (obligations déclaratives des exécutants de travaux en France), je sais que cet utilitaire n'aura pas d'utilité en-dehors des frontières du pays. Je trouvais donc le choix du français plutôt justifié ici.

Après, j'entends l'argument sur l'utilisation du « franglais » dans le code, et je reconnais que le résultat n'est effectivement pas satisfaisant : je procéderai certainement différemment à l'avenir.

En revanche, je pense maintenir, pour ce logiciel, l'utilisation du français pour les commentaires et l'interface du logiciel, pour la raison déjà évoquée que ce projet n'a pas vocation à être utilisé à l'international. Pour les commentaires, je pense effectivement que je perdrais en précision en utilisant l'anglais (en raison de mon faible niveau), alors que je suis persuadé que le public amené à le lire sera francophone à au moins 99 %.

Effectivement, un commentaire serait ici le bienvenu. Je l'avais ajouté car dans mes tests, en l'absence de cette instruction, « calendar.day_name » et « calendar.month_name » renvoyaient par défaut les noms des jours et des mois en anglais.

Après, si quelqu'un a son système dans une langue étrangère, cela aboutira à un mélange de langues. Compte tenu de ce que j'évoquais plus haut sur l'utilisation du programme en français, il serait peut plus cohérent d'utiliser quelque chose du type « locale.setlocale(locale.LC_ALL, 'fr_FR') » pour prendre le parti de forcer le français et d'avoir ainsi une interface cohérente, mais ça demanderait un peu plus de travail pour être propre (gérer l'absence de la langue française sur le système, modifier l'argument 'fr_FR' selon le système utilisé, etc.).

D'ailleurs, je constate que cette ligne apparaît également dans le fichier main.py (l'une des deux instructions est donc superflue).

Vobul a écrit :

Remarque 3 : la première ligne des fichiers devrait être #!/usr/bin/env python. Il est peut-être nécesssaire d'ajouter un check de la version de python dans le programme afin qu'il quitte si c'est python 2. Mais là t'as mis /usr/bin/python3.5. Or sur mon ordi (avec Archlinux) j'ai 3.6.2, donc si je fais ./main, ça marche pas.

Effectivement, il n'y pas lieu de bloquer la version sur la 3.5. En revanche, l'en-tête « #!/usr/bin/python3 » ne ferait-il pas l'affaire ?

Vobul a écrit :

Alors ensuite comme je suis pas trop neuneu je fais "python main.py" et là j'ai une erreur : ModuleNotFoundError: No module named 'PyPDF2'.

Ah tiens, t'aurais pas oublié une étape dans le readme genre pour installer les dépendences ? Regarde ce que c'est que requirements.txt wink

Alors comme je suis pas trop neuneu je fais "sudo pip install pypdf2".

Effectivement, PyPDF2 est nécessaire. Je vais jeter un coup d'oeil sur le fonctionnement de requirements.txt wink

Vobul a écrit :

Maintenant l'erreur c'est qu'il trouve pas XDG_CONFIG_HOME. Eh oui, sur mon système la variable XDG_CONFIG_HOME n'existe pas ! Donc il faut que t'ajoutes du code soit pour montrer une belle erreur explicative, soit tu mets ça dans le fichier de conf, soit tu cherches d'autres répertoires. Mais là c'est moche tongue

Je pensais naïvement que XDG_CONFIG_HOME était universel sur GNU/Linux. L'idéal serait de chercher le bon répertoire. Il n'y a pas, par défaut, de variable d'environnement renvoyant au « .config » de l'utilisateur courant sous Archlinux ?

Vobul a écrit :

Alors comme je suis pas trop neuneu je fais "export XDG_CONFIG_HOME=/tmp/yep" et je relance. Ah j'ai une fenêtre, on avance smile Je clique sur paramètres et je rentre ma config. Et oh surprise je retrouve mon mot de passe de ma messagerie électronique dans un fichier texte dans la nature. Pas cool. Le mot de passe smtp devrait être chiffré. Alors oui c'est pas forcément facile à faire, mais ça vaut le coup. Personne ne pourra prendre ce programme au sérieux tant que le mot de passe est stocké en clair. https://www.google.fr/search?q=python+s … ypted+data Et conseil important : n'essaie pas d'inventer ta crypto, utilise une librairie, fais pas le foufou.

La gestion du mot de passe est effectivement, à l'heure actuelle, le gros point noir de cet utilitaire.

Mes réflexions sur le sujet :
- comme le mot de passe doit être envoyé au serveur, j'ai besoin d'un algorithme permettant de déchiffrer le mot de passe avant l'envoi. Donc de ce que je comprends, je ne peux pas utiliser le module hashlib.
- j'ai vu le module base64 qui permet me semble-t-il d'encoder et de décoder à la volée. Mais stocker un mot de passe encodé en base64 est-il réellement utile niveau sécurité ? Ce sera toujours mieux que stocké en clair de toute façon.

Aurais-tu des recommandations sur le sujet ?

Vobul a écrit :

Ensuite je vois que par défaut tu mets /home/user/Téléchargements comme dossier. Mais tu devrais te baser sur XDG_DOWNLOAD_DIR vu que t'aimes bien XDG wink

Je ne connaissais pas. Effectivement, je pourrai l'utiliser (avec une solution de secours s'il n'est pas défini).

Vobul a écrit :

Bon allez pour finir deux trois trucs en vrac :

Vobul a écrit :

- fais des paquets et mets sur pypi.org comme ça on peut "pip install declatravaux" et ça gère les dépendances, ça vérifie que c'est python 3 toussah.

Ce serait effectivement plus propre.
Je pensais également utiliser cx_freeze pour créer des exécutables, afin de rendre le logiciel utilisable sans avoir à se soucier de l'installation de python (notamment) sur le système. Ça a l'air de fonctionner sous Windows, je n'ai pas encore testé cx_freeze sous Ubuntu (j'imagine qu'il crée un fichier en .sh).

Vobul a écrit :

- dans getCheminFichierConfig() t'as oublié les macs, non ?

En effet, Mac OS n'est pas du tout géré dans le code, tout simplement car je ne dispose pas du système pour tester. Mais pourquoi pas à terme, si j'ai déjà réglé tous les autres problèmes, ou s'il y a une demande particulière en ce sens !

Vobul a écrit :

- essaie de ne pas te répéter dans ton code. getParametres et setParametres sont identiques à 80%. Sors le code de là, mets-le dans une autre fonction (genre init()) au lieu de le copier coller ! (principe DRY)

Effectivement, c'est bien noté.

Vobul a écrit :

- change le nom du fichier de licence en LICENCE

C'est une convention ? Je crois d'ailleurs que Gitlab ne reconnaît que le fichier LICENSE (en anglais).

Vobul a écrit :

- ah oui aussi vire les whitespace qu'il y a partout. Dans mon éditeur je les affiche en rouge (https://github.com/ntpeters/vim-better-whitespace).

Il y a effectivement des tabulations inutiles sur les lignes vides. D'ailleurs, je crois avoir compris qu'il faut éviter les tabulations, et préférer les espaces (4 par niveau d'indentation) ?

Vobul a écrit :

- pourquoi certains fichiers sont chmod +x et pas d'autres ?

C'est totalement involontaire. Y a-t-il une bonne pratique en la matière ? Tout mettre en non exécutable ?

Vobul a écrit :

Bon et pour finir sur une bonne note je dirai que pour un premier programme c'est pas mal du tout, on a vu bien pire, et je ne vise personne sur ce forum tongue C'est plutôt organisé et propre. Mais t'as encore un peu de boulot wink

Merci smile

Il reste beaucoup de boulot, mais ce n'est pas comme si c'était une surprise.

En tout cas, je te remercie encore pour le temps que tu m'as consacré, sur un programme qui ne t'intéresse pas le moins du monde j'imagine wink. C'est vraiment très appréciable !

Hors ligne

#4 Le 12/09/2017, à 13:08

Vobul

Re : DéclaTravaux - Déclaration des travaux réalisés à proximité de réseaux

Pierrot86 a écrit :

Effectivement, il n'y pas lieu de bloquer la version sur la 3.5. En revanche, l'en-tête « #!/usr/bin/python3 » ne ferait-il pas l'affaire ?

Oui ça devrait faire l'affaire. Tu devrais utiliser docker pour tester différentes distributions. Ça ne m'étonnerai pas qu'il y ait des distribs où /usr/bin/python c'est python 3 et si t'installes python 2 c'est /usr/bin/python2, mais y'a pas /usr/bin/python3 comme lien symbolique. Tu peux aussi dire de démarrer le programme avec "python main.py" comme ça ça règle le problème.

Pierrot86 a écrit :

Je pensais naïvement que XDG_CONFIG_HOME était universel sur GNU/Linux. L'idéal serait de chercher le bon répertoire. Il n'y a pas, par défaut, de variable d'environnement renvoyant au « .config » de l'utilisateur courant sous Archlinux ?

Ben en fait Archlinux quand tu l'installes c'est juste un shell sur une console. Après l'utilisateur choisit d'installer X11 et un gestionnaire de fenêtre ou un environnement de bureau, donc tu peux vraiment avoir des millions de combinaisons. Le mieux c'est de tester pour la présence de XDG_CONFIG_HOME et si y'a pas tu demandes à l'utilisateur si c'est ok de prendre ~/.config/declaTravaux. Franchement y'a plein de softs qui se mettent direct dans le home ou direct dans .config sans trop se poser de question, donc pas besoin de passer trop de temps dessus à mon avis, si le directory .config existe, tu vas dedans et puis c'est tout.

Pierrot86 a écrit :

Mes réflexions sur le sujet :
- comme le mot de passe doit être envoyé au serveur, j'ai besoin d'un algorithme permettant de déchiffrer le mot de passe avant l'envoi. Donc de ce que je comprends, je ne peux pas utiliser le module hashlib.
- j'ai vu le module base64 qui permet me semble-t-il d'encoder et de décoder à la volée. Mais stocker un mot de passe encodé en base64 est-il réellement utile niveau sécurité ? Ce sera toujours mieux que stocké en clair de toute façon.

Aurais-tu des recommandations sur le sujet ?

Alors tu fais bien de poser la question. En effet tu ne peux pas utiliser de fonction de hashage (genre sha256, md5, sha1 ou même bcrypt) car tu veux pouvoir réutiliser le mot de passe pour l'envoyer au serveur. Ce qu'il te faut c'est le chiffrer avec une clé, pour pouvoir ensuite le déchiffrer avec cette même clé (voir http://pynacl.readthedocs.io/en/latest/secret/). Sauf que maintenant le problème c'est de stocker la clé correctement… Si tu mets la clé dans le fichier de config, certes c'est pas le mot de passe smtp direct, mais c'est trivial de le retrouver depuis la clé.

Je vois trois solutions:
- utiliser keyring : https://pypi.python.org/pypi/keyring
- demander à l'utilisateur le mot de passe smtp à chaque fois (1 fois par session). La solution radicale mais pas super niveau expérience utilisateur. Mais la plus safe et de loin ! Évidemment pas du tout pratique si le mot de passe SMTP est super long et compliqué.
- prévenir l'utilisateur que ce fichier stocke le mot de passe en clair et qu'il doit mettre des permissions restrictives dessus (chmod 600). Et refuser de démarrer si les permissions ne sont pas strictes (comme ssh le fait avec la clé privée). Ça peut être un bon compromis… (tu peux aussi mettre directement les bonnes permissions dans le programme bien sûr).

Y'a pas de solution ultime, à moins d'avoir un utilisateur qui sait se servir de GPG pour chiffrer/déchiffrer un fichier avec sa clé privée.

Oublie base64, ça n'a rien à voir avec le chiffrement !

Pierrot86 a écrit :

C'est une convention ? Je crois d'ailleurs que Gitlab ne reconnaît que le fichier LICENSE (en anglais).

Oui.

Pierrot86 a écrit :

Il y a effectivement des tabulations inutiles sur les lignes vides. D'ailleurs, je crois avoir compris qu'il faut éviter les tabulations, et préférer les espaces (4 par niveau d'indentation) ?

Oui vire toutes les tabs et garde 4 espaces pour l'indentation. Configure ton éditeur pour te montrer les erreurs lorsque t'écris du code qu'est pas PEP8 https://www.python.org/dev/peps/pep-0008/. PEP8 c'est une convention qui décrit justement qu'il faut utiliser 4 espaces et pas de tabs et autres choses.

Pierrot86 a écrit :

C'est totalement involontaire. Y a-t-il une bonne pratique en la matière ? Tout mettre en non exécutable ?

Oui. Tu peux aussi garder le main.py en executable pour pouvoir faire "./main.py". Mais c'est pas la fin du monde de faire "python main.py" à la place…

Pierrot86 a écrit :

En tout cas, je te remercie encore pour le temps que tu m'as consacré, sur un programme qui ne t'intéresse pas le moins du monde j'imagine wink. C'est vraiment très appréciable !

Je t'en prie smile

Dernière modification par Vobul (Le 12/09/2017, à 13:08)


Vobul

Hors ligne

#5 Le 12/09/2017, à 22:32

Pierrot86

Re : DéclaTravaux - Déclaration des travaux réalisés à proximité de réseaux

S'agissant du mot de passe, l'utilisation de keyring me paraît pas mal : j'aime bien l'idée de déléguer au système d'exploitation la gestion du mot de passe.

À première vue, la bibliothèque semble assez simple à utiliser.

Hors ligne

#6 Le 25/09/2017, à 22:12

Pierrot86

Re : DéclaTravaux - Déclaration des travaux réalisés à proximité de réseaux

Pour information, j'ai un peu travaillé sur le projet dernièrement, suite aux conseils de Vobul.

Entre autres choses, j'ai modifié la gestion du mot de passe pour utiliser keyring.

Par ailleurs, j'ai essayé de réorganiser le projet pour être un peu plus standard.

J'ai notamment tenté de faire usage de setuptools en vue de sa distribution.

Je rencontre toutefois un problème lorsque j'utilise :

python3 setup.py test

Ce dernier me renvoie effectivement des erreurs au niveau de l'import des modules internes au projet. Par exemple :

ERROR: main (unittest.loader._FailedTest)
----------------------------------------------------------------------
ImportError: Failed to import test module: main
Traceback (most recent call last):
  File "/usr/lib/python3.5/unittest/loader.py", line 153, in loadTestsFromName
    module = __import__(module_name)
  File "/home/pierre/Projets/DeclaTravaux/DeclaTravaux/main.py", line 47, in <module>
    from configuration import getParametres
ImportError: No module named 'configuration'

Or, je ne rencontre aucune erreur si je lance le logiciel par « python3 main.py ». Est-ce que quelqu'un pourrait m'expliquer la raison de cette erreur ?

Hors ligne