Contenu | Rechercher | Menus

Annonce

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.

À propos de l'équipe du forum.

#1 Le 01/02/2019, à 13:07

Compte supprimé

[Résolu]Pourquoi mon code n'est pas conforme à pep8/pylint ?

Bonjour,
Débutant en Python , je souhaite prendre les bonnes habitudes quant à la présentation de mon code en me conformant au pep8.
Je découvre pylint que j'exécute dans le terminal ...
Le code ci dessous, me renvoie des erreurs que je n'arrive pas à résoudre ...

#!/usr/bin/env python
# -*- coding: UTF8 -*-

"""module STOP TABAC. Ce module affiche une banderole animée avec pour 1er affichage
un message indiquant le nombre de jour passés depuis le 1er jour d'abstinence et le nombre de
restant avant le jour J convenu.
Le deuxième affichages et les suivants, afiichent une succession  de messages choisis aléatoirement
dont le but est de renforcer la motivation et à la compréhention des mécanismes de la dépendance .
Les boutons ajoutent (ajouterons) des fonctionnalités comme ...."""

import datetime
import time
import random
import tkinter.font
import tkinter as tk


def affiche(annonce, couleurTexte="black"):
    """Affiche un texte en mouvement de gauche à droite"""
    #création canvas texte annonce
    item = canvas.create_text(0, 0, anchor='nw', text=annonce,
                              font=("Helvetica", 100, 'bold'), fill=couleurTexte)
    #calcule longeur en pixel de la chaine annonce
    tailleannonce = tkinter.font.Font(family='Helvetica', size=100, weight='bold')
    compt = tailleannonce.measure(annonce)
    canvas.update()
    while compt > 0:
        canvas.move(item, -3, 0)
        canvas.update_idletasks()
        canvas.update()
        compt -= 3
    return

def datedujour():
    """retourn la date du jour sour forme d'un turple (annee,mois,jour)"""
    datedujour = time.strftime('20%y %m %d', time.localtime())
    datedujour = datedujour.split()
    annee = int(datedujour[0])
    mois = int(datedujour[1])
    jour = int(2)
    return annee, mois, jour

def tempsrestant(anneej, moisj, jourj):
    """retourne le nombre de jours entre la date du jour et le jour j"""
    #Quel jour sommes nous?
    annee, mois, jour = datedujour()
    # calcul nombre de jours jusqu'au jour j
    datedebut = datetime.date(annee, mois, jour)
    datefin = datetime.date(anneej, moisj, jourj)
    nbrjours = datefin - datedebut
    return nbrjours.days

def tempseffectue(anneepremier, moispremier, jourpremier):
    """retourne le nombre de jours entre le début du compte à rebour et le jour actuel"""
    #Quel jour sommes nous?
    annee, mois, jour = datedujour()
     #calcul du nombre de jours écoulé
    datepremier = datetime.date(anneepremier, moispremier, jourpremier)
    dateactu = datetime.date(annee, mois, jour) # Aujourd'hui
    nbrjours = dateactu - datepremier
    return nbrjours.days

def extraits():
    """retourne un extrait choisi au hasard"""
    liste = ["L'effet de la drogue est de supprimer toute logique dans son comportement.",
             "Fumer est une chaîne pour la vie -sauf si vous la brisez ",
             "C'est la peur qui fait continuer les gens àfumer .",
             "L'aspect le plus pathétique est que la satisfaction qu'un fumeur en retire est "
             "le plaisir de revenir à l'état de paix et de tranquilité de son corps avant qu'il ne tombe sous"
             "l'emprise de sa drogue ",
             "Seuls les fumeurs souffrent de symptômes de manque",
             "La cigarette ne comble pas un vide , elle le crée",
             "Les fumeurs ne fument pas parce que cela leur fait plaisir, mais parce qu'ils souffrent s'il"
             "ne le font pas.",
             "La vie d'un non-fumeur est meilleure et beaucoup plus agréable",
             "C'est si bon d'être libéré!",
             "C'est une joie incomparable, lorsque l'on ne fume plus, d'être libéré de cet exclavage ,"
             "de ne plus passer le plus clair de son temps  à crever d'envie de fumer et le reste à"
             "souhaiter ne plus jamais avoir à le faire",
             "Fumer est une réaction en chaîne , on ne gère pas une dépendance ... On l'arrête!",
             "N'oubliez pas : en essayant de réduire votre consommation , vous vous enfoncerez encore "
             "plus dans la dépendance.",
             "Combinaison gagnante : arrêter de fumer et de se morfondre à ce propos! La vie est belle!",
             "Par nature, l'homme cherche non à supporter son manque , mais à le soulager ...",
             "L'effet de la drogue est de supprimer toute logique dans son comportement.",
             "Quoi que vous fassiez, ne tombez pas dans le piège de vous dire <pas maintenant, "
             "plus tard> : cela finirait par ne plus devenir une priorité. Décidez maintenant du moment "
             "où vousallez arrêter et attendez le avec impatience",
             "La dépendance à une drogue , tend à s'accroître , pas l'inverse. Si vous pensez que ce sera "
             "plus facile d'arrêter demain , vous rêvez !",
             "Il n'y a absolument rien à abandonner ....",
             "Fumer est l'aliénation à une drogue. Le seul moyen d'y mettre un terme est d'arrêter, et,"
             "le meilleur moment, maintenant.",
             "La bonne attitude ne consiste pas à espèrer la victoire, mais à savoir que l'on a pris une"
             "décision irrévocable et que c'est gagné.",
             "Savourez la joie d'être libéré decet esclavage, de quitter cet univers d'idées noires.",
             "Il est facile d'arrêter de fumer , mais il est impossible de contrôler sa dépendance ",
             "Ne vous faites plus avoir . Décidez une fois pour toutes que plus jamais vous ne fumerez"
             "la moindre bouffée, quelle qu'en soit la raison",
             "Souvenez-vous que vous étiez malheureux lorsque vous fumiez . C'est pour cela que vous "
             "avez arrêté. Réjouissez-vous de plus être fumeur.",
             "Tu as toujours voulu t'arrêter , rejouis toi !"]
    return liste[random.randint(0, len(liste)-1)]

############# Initialisation fenettres et boutons ##############
root = tk.Tk()
root.title('La vie est belle')
root.geometry('+10+10')
root.grid()
frameA = tk.Frame(root)
frameA.grid(sticky=tk.NW) # gauche toute

bouton = tk.Button(frameA, text='Remettre le compteur à 0')
bouton.grid(column=1, row=0)

b_histo = tk.Button(frameA, text='Historique')
b_histo.grid(column=0, row=0)

b_eteint = tk.Button(frameA, text='Éteindre', width=50, command=root.destroy)#widh détermine la largeur du bouton
b_eteint.grid(column=2, row=0, padx=200)# padx permet de mettre une marge externe au widget b_eteint en pixel (décale le bouton)

b_jourfume = tk.Button(frameA, text="J'ai craqué")
b_jourfume.grid(column=3, row=0)

canvas = tk.Canvas(root, width=1400, height=200, bg="pink")
canvas.grid()

##########Constantes à modifier selon les besoins  ######

joursrestant = tempsrestant(2019, 4, 25)   # Ceci est le jour j , à modifier selon les besoins
tempseffectue = tempseffectue(2019, 1, 22) # Le 1er jour du compte à rebour

##########Début du coeur du programme ###########
canvas['bg'] = "pink"
affiche('                   <-------------Bravo, '+str(tempseffectue)+'  jours se sont écoulés. Dans '+
        str(joursrestant)+' jours champagne!!')

while True:
    canvas['bg'] = "black"
    extraitsTexte = str(extraits())
    affiche('                '+extraitsTexte, couleurTexte="white")

root.mainloop()

et le retour de pylint

~/mes_scripts jt'écoute :pylint Newcompte_rebourbis.py 
No config file found, using default configuration
************* Module Newcompte_rebourbis
C: 69, 0: Line too long (110/100) (line-too-long)
C: 73, 0: Line too long (107/100) (line-too-long)
C: 77, 0: Line too long (103/100) (line-too-long)
C: 81, 0: Line too long (103/100) (line-too-long)
C: 83, 0: Line too long (105/100) (line-too-long)
C: 87, 0: Line too long (105/100) (line-too-long)
C: 89, 0: Line too long (107/100) (line-too-long)
C: 92, 0: Line too long (104/100) (line-too-long)
C: 94, 0: Line too long (105/100) (line-too-long)
C: 96, 0: Line too long (102/100) (line-too-long)
C: 97, 0: Line too long (101/100) (line-too-long)
C: 98, 0: Line too long (103/100) (line-too-long)
C:100, 0: Line too long (102/100) (line-too-long)
C:119, 0: Line too long (113/100) (line-too-long)
C:120, 0: Line too long (128/100) (line-too-long)
C:135, 0: Line too long (103/100) (line-too-long)
C:  1, 0: Invalid module name "Newcompte_rebourbis" (invalid-name)
E: 14, 0: Unable to import 'tkinter.font' (import-error)
E: 15, 0: Unable to import 'tkinter' (import-error)
C: 18, 0: Invalid argument name "couleurTexte" (invalid-name)
W: 36, 4: Redefining name 'datedujour' from outer scope (line 34) (redefined-outer-name)
C:106, 0: Invalid constant name "root" (invalid-name)
C:110, 0: Invalid constant name "frameA" (invalid-name)
C:113, 0: Invalid constant name "bouton" (invalid-name)
C:116, 0: Invalid constant name "b_histo" (invalid-name)
C:119, 0: Invalid constant name "b_eteint" (invalid-name)
C:122, 0: Invalid constant name "b_jourfume" (invalid-name)
C:125, 0: Invalid constant name "canvas" (invalid-name)
C:130, 0: Invalid constant name "joursrestant" (invalid-name)
C:131, 0: Invalid constant name "tempseffectue" (invalid-name)
C:140, 4: Invalid constant name "extraitsTexte" (invalid-name)


Report
======
63 statements analysed.

Statistics by type
------------------

+---------+-------+-----------+-----------+------------+---------+
|type     |number |old number |difference |%documented |%badname |
+=========+=======+===========+===========+============+=========+
|module   |1      |1          |=          |100.00      |100.00   |
+---------+-------+-----------+-----------+------------+---------+
|class    |0      |0          |=          |0           |0        |
+---------+-------+-----------+-----------+------------+---------+
|method   |0      |0          |=          |0           |0        |
+---------+-------+-----------+-----------+------------+---------+
|function |5      |5          |=          |100.00      |0.00     |
+---------+-------+-----------+-----------+------------+---------+



Raw metrics
-----------

+----------+-------+------+---------+-----------+
|type      |number |%     |previous |difference |
+==========+=======+======+=========+===========+
|code      |65     |44.22 |65       |=          |
+----------+-------+------+---------+-----------+
|docstring |48     |32.65 |48       |=          |
+----------+-------+------+---------+-----------+
|comment   |11     |7.48  |11       |=          |
+----------+-------+------+---------+-----------+
|empty     |23     |15.65 |23       |=          |
+----------+-------+------+---------+-----------+



Duplication
-----------

+-------------------------+------+---------+-----------+
|                         |now   |previous |difference |
+=========================+======+=========+===========+
|nb duplicated lines      |0     |0        |=          |
+-------------------------+------+---------+-----------+
|percent duplicated lines |0.000 |0.000    |=          |
+-------------------------+------+---------+-----------+



Messages by category
--------------------

+-----------+-------+---------+-----------+
|type       |number |previous |difference |
+===========+=======+=========+===========+
|convention |28     |28       |=          |
+-----------+-------+---------+-----------+
|refactor   |0      |0        |=          |
+-----------+-------+---------+-----------+
|warning    |1      |1        |=          |
+-----------+-------+---------+-----------+
|error      |2      |2        |=          |
+-----------+-------+---------+-----------+



Messages
--------

+---------------------+------------+
|message id           |occurrences |
+=====================+============+
|line-too-long        |16          |
+---------------------+------------+
|invalid-name         |12          |
+---------------------+------------+
|import-error         |2           |
+---------------------+------------+
|redefined-outer-name |1           |
+---------------------+------------+



Global evaluation
-----------------
Your code has been rated at 3.81/10 (previous run: 3.81/10, +0.00)

~/mes_scripts jt'écoute :

J'ai regardé le man mais quand j'ai vu qu'il faisait plus de 500 pages , j'ai pris peur^^
Au delà , des questions relatives à mon code , je suis preneur de toutes ressources/conseils me permettant d'adopter les bonnes pratiques pour échanger ou travailler à plusieurs sur un projet (... quand je serais grand^^ )
Merci

Dernière modification par Compte supprimé (Le 05/02/2019, à 21:31)

#2 Le 01/02/2019, à 14:17

pingouinux

Re : [Résolu]Pourquoi mon code n'est pas conforme à pep8/pylint ?

Bonjour,
Je ne connais pas pylint, mais tkinter est un module de python3, et non de python.

Hors ligne

#3 Le 01/02/2019, à 14:32

Compte supprimé

Re : [Résolu]Pourquoi mon code n'est pas conforme à pep8/pylint ?

Bonjour @pingouinux ,
bien vu !
J'ai utilisé pour ce code python3 mais le pylint utilisé est pour python2.7 d'où les erreurs d'importations trouvées ...
Et de 2 erreurs dans pylint en moins ! wink

#4 Le 01/02/2019, à 19:43

Compte supprimé

Re : [Résolu]Pourquoi mon code n'est pas conforme à pep8/pylint ?

...

C:106, 0: Invalid constant name "root" (invalid-name)
C:110, 0: Invalid constant name "frameA" (invalid-name)
C:113, 0: Invalid constant name "bouton" (invalid-name)
C:116, 0: Invalid constant name "b_histo" (invalid-name)
C:119, 0: Invalid constant name "b_eteint" (invalid-name)
C:122, 0: Invalid constant name "b_jourfume" (invalid-name)
C:125, 0: Invalid constant name "canvas" (invalid-name)
C:130, 0: Invalid constant name "joursrestant" (invalid-name)
C:131, 0: Invalid constant name "tempseffectue" (invalid-name)
C:140, 4: Invalid constant name "extraitsTexte" (invalid-name)


du coup ces erreurs et les autres en sont la conséquence ...

Edit: je viens d'esssayer avec pylint3  et j'ai toujours les mêmes erreurs .
Merci @pingouinux, j'édite en résolu .

#Le pep8, c'est la dictée du code^^

Dernière modification par Compte supprimé (Le 01/02/2019, à 20:03)

#5 Le 04/02/2019, à 12:01

kholo

Re : [Résolu]Pourquoi mon code n'est pas conforme à pep8/pylint ?

salut,
je me demandais quand j'arriverai à trouver du temps pour regarder ton code...
voilà c'est fait...
en fait, j'ai pas vraiment de réponse à ta question mais je me suis demandé comment je ferais face à ton type de programme et en utilisant ces trucs si pratique et tant prise de tête que sont les thread, le temps, le GUI, tout ça...
voilà ce que j'ai pondu...

#!/usr/bin/env python3
# -*- coding: UTF8 -*-

import tkinter as tk
import tkinter.font

import threading
import time

class ScrollAffichage(tk.Tk):
    def __init__(self):
        super().__init__()
        
        self.init_data()
        self.init_gui()

        self.scroller(self.phrases)
        self.mainloop()

    def init_data(self):
        self.l_ecran = self.winfo_screenwidth()-20

        ## POSITIONS
        self.debut = self.l_ecran - 100
        self.fin = 0 - self.l_ecran

        self.phrases = ["fumer... euh... tue", ]

    def init_gui(self):
        self.title('La vie est belle')
        # self.geometry('+10+10')
        self.geometry('+10+300')

        self.canvas = tk.Canvas(self, width=self.l_ecran, height=200, bg="pink")
        self.canvas.grid()

        btn_on = tk.Button(self, text='ON', width=50, command=self.start)
        btn_on.grid()        
        btn_off = tk.Button(self, text='OFF', width=50, command=self.stop)
        btn_off.grid()        
        
        self.bind('<Key>',self.clavier)

    def clavier(self, event):
        touche = event.keysym
        if touche == 'Up' or touche == 'Right' or touche == 'KP_Add':
        # if touche == 'Up':
            self.plus()

        if touche == 'Down' or touche == 'Left' or touche == 'KP_Subtract':
        # if touche == 'Down':
            self.moins()

    def plus(self):
        self.canvas.move(self.item, +3, 0)
        # self.canvas.update_idletasks()
        self.canvas.update()

    def moins(self):
        self.canvas.move(self.item, -3, 0)
        # self.canvas.update_idletasks()
        self.canvas.update()
    
    def bouge(self):
        while self.compt > self.fin:
            if self.continuer:
                self.compt -= 3
                self.moins()
                time.sleep(self.vitesse)
            else:
                break

    def start(self):
        self.un_thread = threading.Thread(None, self.bouge, None)
        self.continuer = True
        self.un_thread.start()
        print("en marche")
    def stop(self):
        self.continuer = False
        print("en pause")


    def scroller(self, annonce):
        """Affiche un texte en mouvement de gauche à droite"""
        couleurTexte="black"
        ## création canvas texte annonce
        self.item = self.canvas.create_text(0, 0, anchor='nw', text=annonce, font=("Helvetica", 100, 'bold'), fill=couleurTexte)

        ## calcule longeur en pixel de la chaine annonce
        tailleannonce = tk.font.Font(family='Helvetica', size=100, weight='bold')
        self.compt = tailleannonce.measure(annonce)

        self.canvas.move(self.item, self.debut, 0)
        self.canvas.update()
        self.vitesse = 0.01 # la vitesse ;°)
        #self.start()

    def quitter(self):
        print(30*'-')
        print("quitter")
        self.destroy()

if __name__=="__main__":
    ScrollAffichage()

je me suis donné à fond : gestion du déplacement du texte avec les flèches lol , mise en pause fonctionnelle avec un start / stop par des boutons.

bon je pense qu'on peut aller beaucoup plus loin en créant un objet qui hérite de canvas et non de tk (voire le mettre dans une frame) mais j'apprends tous les jours, pour ne pas dire chaque heure... et là je me concentrais sur le threading... et là, je suis pas mal fier de moi ! cool

NB :
        TODO : on doit pouvoir mettre un with quelque part
        ou intersecpter la fermeture
        pour gérer l'arrêt externe (autre que le bouton pause)
        sinon le thread continue de tourner !

edit : comme je le dis dans le prochain post ; le retour le pylint

pylint3 affiche_001.py 
No config file found, using default configuration
************* Module affiche_001
C: 13, 0: Trailing whitespace (trailing-whitespace)
C: 38, 0: Trailing whitespace (trailing-whitespace)
C: 40, 0: Trailing whitespace (trailing-whitespace)
C: 41, 0: Trailing whitespace (trailing-whitespace)
C: 42, 0: Exactly one space required after comma
        self.bind('<Key>',self.clavier)
                         ^ (bad-whitespace)
C: 63, 0: Trailing whitespace (trailing-whitespace)
C: 85, 0: Exactly one space required around assignment
        couleurTexte="black"
                    ^ (bad-whitespace)
C: 87, 0: Line too long (128/100) (line-too-long)
C:103, 0: Exactly one space required around comparison
if __name__=="__main__":
           ^^ (bad-whitespace)
C:  1, 0: Missing module docstring (missing-docstring)
C: 10, 0: Missing class docstring (missing-docstring)
R: 10, 0: Too many instance attributes (10/7) (too-many-instance-attributes)
C: 20, 4: Missing method docstring (missing-docstring)
C: 29, 4: Missing method docstring (missing-docstring)
C: 44, 4: Missing method docstring (missing-docstring)
C: 54, 4: Missing method docstring (missing-docstring)
C: 59, 4: Missing method docstring (missing-docstring)
C: 64, 4: Missing method docstring (missing-docstring)
C: 73, 4: Missing method docstring (missing-docstring)
C: 78, 4: Missing method docstring (missing-docstring)
C: 85, 8: Invalid variable name "couleurTexte" (invalid-name)
C: 98, 4: Missing method docstring (missing-docstring)
W: 74, 8: Attribute 'un_thread' defined outside __init__ (attribute-defined-outside-init)
W: 75, 8: Attribute 'continuer' defined outside __init__ (attribute-defined-outside-init)
W: 79, 8: Attribute 'continuer' defined outside __init__ (attribute-defined-outside-init)
W:  5, 0: Unused import tkinter.font (unused-import)


Report
======
67 statements analysed.

Statistics by type
------------------

+---------+-------+-----------+-----------+------------+---------+
|type     |number |old number |difference |%documented |%badname |
+=========+=======+===========+===========+============+=========+
|module   |1      |NC         |NC         |0.00        |0.00     |
+---------+-------+-----------+-----------+------------+---------+
|class    |1      |NC         |NC         |0.00        |0.00     |
+---------+-------+-----------+-----------+------------+---------+
|method   |11     |NC         |NC         |18.18       |0.00     |
+---------+-------+-----------+-----------+------------+---------+
|function |0      |NC         |NC         |0           |0        |
+---------+-------+-----------+-----------+------------+---------+



Raw metrics
-----------

+----------+-------+------+---------+-----------+
|type      |number |%     |previous |difference |
+==========+=======+======+=========+===========+
|code      |70     |66.04 |NC       |NC         |
+----------+-------+------+---------+-----------+
|docstring |1      |0.94  |NC       |NC         |
+----------+-------+------+---------+-----------+
|comment   |11     |10.38 |NC       |NC         |
+----------+-------+------+---------+-----------+
|empty     |24     |22.64 |NC       |NC         |
+----------+-------+------+---------+-----------+



Duplication
-----------

+-------------------------+------+---------+-----------+
|                         |now   |previous |difference |
+=========================+======+=========+===========+
|nb duplicated lines      |0     |NC       |NC         |
+-------------------------+------+---------+-----------+
|percent duplicated lines |0.000 |NC       |NC         |
+-------------------------+------+---------+-----------+



Messages by category
--------------------

+-----------+-------+---------+-----------+
|type       |number |previous |difference |
+===========+=======+=========+===========+
|convention |21     |NC       |NC         |
+-----------+-------+---------+-----------+
|refactor   |1      |NC       |NC         |
+-----------+-------+---------+-----------+
|warning    |4      |NC       |NC         |
+-----------+-------+---------+-----------+
|error      |0      |NC       |NC         |
+-----------+-------+---------+-----------+



Messages
--------

+-------------------------------+------------+
|message id                     |occurrences |
+===============================+============+
|missing-docstring              |11          |
+-------------------------------+------------+
|trailing-whitespace            |5           |
+-------------------------------+------------+
|bad-whitespace                 |3           |
+-------------------------------+------------+
|attribute-defined-outside-init |3           |
+-------------------------------+------------+
|unused-import                  |1           |
+-------------------------------+------------+
|too-many-instance-attributes   |1           |
+-------------------------------+------------+
|line-too-long                  |1           |
+-------------------------------+------------+
|invalid-name                   |1           |
+-------------------------------+------------+



Global evaluation
-----------------
Your code has been rated at 6.12/10

Dernière modification par kholo (Le 04/02/2019, à 19:02)

Hors ligne

#6 Le 04/02/2019, à 12:31

Compte supprimé

Re : [Résolu]Pourquoi mon code n'est pas conforme à pep8/pylint ?

sympa wink
Je regarde ça de plus près ...

#7 Le 04/02/2019, à 18:54

kholo

Re : [Résolu]Pourquoi mon code n'est pas conforme à pep8/pylint ?

bon,
puisque ce fil est dédié à pylint, voilà où j'en arrive en suivant la majeure partie de ses "observations".
et je mettrai le résultat qui va avec le code dans le précédent post...

#!/usr/bin/env python3
# -*- coding: UTF8 -*-
""" class pour afficher une fenêtre avec un texte qui défile """

import tkinter as tk
import tkinter.font as font

import threading
import time

class ScrollAffichage(tk.Tk):
    """ class pour la fenêtre """
    def __init__(self, annonces):
        super().__init__()
        """ initialisation de l'interface graphique """
        self.title('La vie est belle')
        # self.geometry('+10+10') # je baisse un peu pour voir les retours sur mon écran ;°)
        self.geometry('+10+300')

        ## DONNEES
        """ informations sur l'écran """
        l_ecran = self.winfo_screenwidth() - 20
        self.debut = l_ecran - 100
        self.fin = 0 - l_ecran

        annonce = annonces[1]
        self.vitesse = 0.01 # la vitesse ;°)
        self.continuer = False

        ## OBJETS
        self.canvas = tk.Canvas(self, width=l_ecran, height=200, bg="pink")
        self.canvas.grid()

        btn_on = tk.Button(self, text='ON', width=50, command=self.start)
        btn_on.grid()
        btn_off = tk.Button(self, text='OFF', width=50, command=self.stop)
        btn_off.grid()

        self.bind('<Key>', self.clavier)

        """Affiche un texte en mouvement de gauche à droite"""
        ## création canvas texte annonce
        coul_txt = "black"
        le_f, le_t, le_s = "Helvetica", 100, 'bold'
        self.item = self.canvas.create_text(0, 0, anchor='nw', text=annonce, font=(le_f, le_t, le_s), fill=coul_txt)

        ## calcule longeur en pixel de la chaine annonce
        self.compt = font.Font(family=le_f, size=le_t, weight=le_s).measure(annonce)

        self.canvas.move(self.item, self.debut, 0)
        self.canvas.update()
        ## self.start()

        self.mainloop()

    def clavier(self, event):
        """ gestion des touches clavier """
        touche = event.keysym
        if touche == 'Up' or touche == 'Right' or touche == 'KP_Add':
        # if touche == 'Up':
            self.plus()

        if touche == 'Down' or touche == 'Left' or touche == 'KP_Subtract':
        # if touche == 'Down':
            self.moins()

    def plus(self):
        """ méthode pour faire défiler le texte vers la gauche """
        self.canvas.move(self.item, +3, 0)
        # self.canvas.update_idletasks()
        self.canvas.update()

    def moins(self):
        """ méthode pour faire défiler le texte vers la droite """
        self.canvas.move(self.item, -3, 0)
        # self.canvas.update_idletasks()
        self.canvas.update()

    def bouge(self):
        """ # TODO : on doit pouvoir mettre un with quelque part
        # ou intersecpter la fermeture
        # pour gérer l'arrêt externe (autre que le bouton pause)
        # sinon le thread continue de tourner ! """
        while self.compt > self.fin:
            if self.continuer:
                self.compt -= 3
                self.moins()
                time.sleep(self.vitesse)
            else:
                break

    def start(self):
        """ démarre le défilement """
        un_thread = threading.Thread(None, self.bouge, None)
        self.continuer = True
        un_thread.start()
        print("en marche")

    def stop(self):
        """ met le défilement en pause """
        self.continuer = False
        print("en pause")

    def quitter(self):
        """ méthode de fin """
        print(30*'-')
        print("quitter")
        self.destroy()

if __name__ == "__main__":
    annonces = ["fumer... euh... tue", "un autre petit dicton"]
    ScrollAffichage(annonces)

j'ai trouvé le travail de nettoyage très instructif...
voilà ce que me dit pylint :

pylint3 affiche.py 
No config file found, using default configuration
************* Module affiche
W: 80, 0: TODO : on doit pouvoir mettre un with quelque part (fixme)
C: 45, 0: Line too long (116/100) (line-too-long)
W: 13,23: Redefining name 'annonces' from outer scope (line 111) (redefined-outer-name)
W: 15, 8: String statement has no effect (pointless-string-statement)
W: 21, 8: String statement has no effect (pointless-string-statement)
W: 41, 8: String statement has no effect (pointless-string-statement)
C:111, 4: Invalid constant name "annonces" (invalid-name)


Report
======
66 statements analysed.

Statistics by type
------------------

+---------+-------+-----------+-----------+------------+---------+
|type     |number |old number |difference |%documented |%badname |
+=========+=======+===========+===========+============+=========+
|module   |1      |1          |=          |100.00      |0.00     |
+---------+-------+-----------+-----------+------------+---------+
|class    |1      |1          |=          |100.00      |0.00     |
+---------+-------+-----------+-----------+------------+---------+
|method   |8      |8          |=          |100.00      |0.00     |
+---------+-------+-----------+-----------+------------+---------+
|function |0      |0          |=          |0           |0        |
+---------+-------+-----------+-----------+------------+---------+



Raw metrics
-----------

+----------+-------+------+---------+-----------+
|type      |number |%     |previous |difference |
+==========+=======+======+=========+===========+
|code      |66     |57.89 |66       |=          |
+----------+-------+------+---------+-----------+
|docstring |15     |13.16 |15       |=          |
+----------+-------+------+---------+-----------+
|comment   |12     |10.53 |14       |-2.00      |
+----------+-------+------+---------+-----------+
|empty     |21     |18.42 |21       |=          |
+----------+-------+------+---------+-----------+



Duplication
-----------

+-------------------------+------+---------+-----------+
|                         |now   |previous |difference |
+=========================+======+=========+===========+
|nb duplicated lines      |0     |0        |=          |
+-------------------------+------+---------+-----------+
|percent duplicated lines |0.000 |0.000    |=          |
+-------------------------+------+---------+-----------+



Messages by category
--------------------

+-----------+-------+---------+-----------+
|type       |number |previous |difference |
+===========+=======+=========+===========+
|convention |2      |2        |=          |
+-----------+-------+---------+-----------+
|refactor   |0      |0        |=          |
+-----------+-------+---------+-----------+
|warning    |5      |5        |=          |
+-----------+-------+---------+-----------+
|error      |0      |0        |=          |
+-----------+-------+---------+-----------+



Messages
--------

+---------------------------+------------+
|message id                 |occurrences |
+===========================+============+
|pointless-string-statement |3           |
+---------------------------+------------+
|redefined-outer-name       |1           |
+---------------------------+------------+
|line-too-long              |1           |
+---------------------------+------------+
|invalid-name               |1           |
+---------------------------+------------+
|fixme                      |1           |
+---------------------------+------------+



Global evaluation
-----------------
Your code has been rated at 8.94/10 (previous run: 8.94/10, +0.00)

bon, il veut un fichier de configuration ?

No config file found, using default configuration

là, il préfère que je continue à coder au lieu d'aller me reposer...

W: 82, 0: TODO : on doit pouvoir mettre un with quelque part (fixme)

pour moi, c'est plus complexe là... comment on ampute une ligne ???

C: 47, 0: Line too long (116/100) (line-too-long)

bon, ça ira avec le fichier de configuration et une classe qui parse un fichier base de données avec les citations

W: 15,23: Redefining name 'annonces' from outer scope (line 113) (redefined-outer-name)

il veut quoi là ?

W: 17, 8: String statement has no effect (pointless-string-statement)
W: 23, 8: String statement has no effect (pointless-string-statement)
W: 43, 8: String statement has no effect (pointless-string-statement)

Hors ligne

#8 Le 05/02/2019, à 11:57

Compte supprimé

Re : [Résolu]Pourquoi mon code n'est pas conforme à pep8/pylint ?

kholo a écrit :

il veut quoi là ?

W: 17, 8: String statement has no effect (pointless-string-statement)
W: 23, 8: String statement has no effect (pointless-string-statement)
W: 43, 8: String statement has no effect (pointless-string-statement)

...peut être parce que ce ne sont pas des docstrings d'une fonction ...

Il nous faut un bon tuto sur pylint. Je vais regarder du coté des speak english...

Dernière modification par Compte supprimé (Le 05/02/2019, à 11:57)

#9 Le 05/02/2019, à 12:24

Compte supprimé

Re : [Résolu]Pourquoi mon code n'est pas conforme à pep8/pylint ?

@kholo:
J'ai essayé le programme pep8 sur ton code . Le retour m'est plus compréhensible ..

~ jt'écoute :pep8 kholo.py 
kholo.py:11:1: E302 expected 2 blank lines, found 1
kholo.py:17:80: E501 line too long (92 > 79 characters)
kholo.py:20:9: E266 too many leading '#' for block comment
kholo.py:27:28: E261 at least two spaces before inline comment
kholo.py:30:9: E266 too many leading '#' for block comment
kholo.py:42:9: E266 too many leading '#' for block comment
kholo.py:45:80: E501 line too long (116 > 79 characters)
kholo.py:47:9: E266 too many leading '#' for block comment
kholo.py:48:80: E501 line too long (84 > 79 characters)
kholo.py:52:9: E266 too many leading '#' for block comment
kholo.py:60:9: E115 expected an indented block (comment)
kholo.py:64:9: E115 expected an indented block (comment)

#10 Le 05/02/2019, à 21:06

Compte supprimé

Re : [Résolu]Pourquoi mon code n'est pas conforme à pep8/pylint ?

... La présentation du code est maintenant conforme à pep8(le logiciel) mais toujours pas à pylint

# #!/usr/bin/python3
# -*- coding: UTF8 -*-

"""module STOP TABAC. Ce module affiche une banderole animée avec pour
1er affichage un message indiquant le nombre de jour passés depuis le
1er jour d'abstinence et le nombre de restant avant le jour J convenu.
Le deuxième affichages et les suivants, afiichent une succession  de
messages choisis aléatoirement dont le but est de renforcer la
motivation et à la compréhention des mécanismes de la dépendance.
Les boutons ajoutent (ajouterons) des fonctionnalités comme ...."""

import datetime
import time
import random
import tkinter.font
import tkinter as tk


def affiche(annonce, couleurTexte="black"):
    """Affiche un texte en mouvement de gauche à droite"""
    # création canvas texte annonce
    item = canvas.create_text(0, 0, anchor='nw',
                              text=annonce,
                              font=("Helvetica", 100, 'bold'),
                              fill=couleurTexte)
    # calcule longeur en pixel de la chaine annonce
    tailleannonce = tkinter.font.Font(family='Helvetica',
                                      size=100, weight='bold')
    compt = tailleannonce.measure(annonce)
    canvas.update()
    while compt > 0:
        canvas.move(item, -3, 0)
        canvas.update_idletasks()
        canvas.update()
        compt -= 3
    return


def datedujour():
    """retourn la date du jour sour forme d'un turple (annee,mois,jour)"""
    dateduj = time.strftime('20%y %m %d', time.localtime()).split()
    # datedujourour
    annee = int(dateduj[0])
    mois = int(dateduj[1])
    jour = int(2)
    return annee, mois, jour


def tempsrestant(anneej, moisj, jourj):
    """retourne le nombre de jours entre la date du jour et le jour j"""
    # Quel jour sommes nous?
    annee, mois, jour = datedujour()
    # calcul nombre de jours jusqu'au jour j
    datedebut = datetime.date(annee, mois, jour)
    datefin = datetime.date(anneej, moisj, jourj)
    nbrjours = datefin - datedebut
    return nbrjours.days


def tempseffectue(anneepremier, moispremier, jourpremier):
    """retourne le nombre de jours entre le début
        du compte à rebour et le jour actuel"""
    # Quel jour sommes nous?
    annee, mois, jour = datedujour()
    # calcul du nombre de jours écoulé
    datepremier = datetime.date(anneepremier, moispremier, jourpremier)
    dateactu = datetime.date(annee, mois, jour)  # Aujourd'hui
    nbrjours = dateactu - datepremier
    return nbrjours.days


def extraits():
    """retourne un extrait choisi au hasard"""
    liste = ["L'effet de la drogue est de supprimer toute logique"
             "dans son comportement.", "Fumer est une chaîne pour la vie"
             "-sauf si vous la brisez ", "C'est la peur qui fait"
             "continuer les gens àfumer .", "L'aspect le plus pathétique"
             "est que la satisfaction qu'un fumeur en retire est le"
             "plaisir de revenir à l'état de paix et de tranquilité de"
             "son corps avant qu'il ne tombe sous l'emprise de sa"
             "drogue ", "Seuls les fumeurs souffrent de symptômes de"
             "manque", "La cigarette ne comble pas un vide , elle le"
             "crée", "Les fumeurs ne fument pas parce que cela leur fait"
             "plaisir, mais parce qu'ils souffrent s'il ne le font pas.",
             "La vie d'un non-fumeur est meilleure et beaucoup"
             "plus agréable", "C'est si bon d'être libéré!", "C'est une"
             " joie incomparable, lorsque l'on ne fume plus, d'être libéré"
             " cet exclavage , de ne plus passer le plus clair de son"
             "temps  à crever d'envie de fumer et le reste àsouhaiter"
             "ne plus jamais avoir à le faire", "Fumer est une réaction"
             "en chaîne , on ne gère pas une dépendance ... On"
             "l'arrête!", "N'oubliez pas : en essayant de réduire votre"
             "consommation , vous vous enfoncerez encore plus dans la"
             "dépendance.", "Combinaison gagnante : arrêter de fumer et"
             "de se morfondre à ce propos! La vie est belle!", "Par"
             "nature, l'homme cherche non à supporter son manque , mais à"
             "le soulager ...", "L'effet de la drogue est de supprimer"
             "toute logique dans son comportement.", "Quoi que vous"
             "fassiez, ne tombez pas dans le piège de vous dire <pas"
             "maintenant, plus tard> : cela finirait par ne plus"
             "devenir une priorité. Décidez maintenant du moment où"
             "vous allez arrêter et attendez le avec impatience", "La"
             "dépendance à une drogue , tend à s'accroître , pas"
             "l'inverse. Si vous pensez que ce sera plus facile"
             "d'arrêter demain , vous rêvez !", "Il n'y a absolument rien"
             "à abandonner ....", "Fumer est l'aliénation à une drogue."
             "Le seul moyen d'y mettre un terme est d'arrêter, et, le"
             "meilleur moment, maintenant.", "La bonne attitude ne"
             "consiste pas à espèrer la victoire, mais à savoir que l'on"
             "a pris une" "décision irrévocable et que c'est gagné.",
             "Savourez la joie d'être libéré decet esclavage, de quitter"
             "cet univers d'idées noires.", "Il est facile d'arrêter de"
             " fumer , mais il est impossible de contrôler sa dépendance",
             "Ne vous faites plus avoir . Décidez une fois pour"
             "toutes que plus jamais vous ne fumerez la moindre"
             "bouffée, quelle qu'en soit la raison", "Souvenez-vous que"
             "vous étiez malheureux lorsque vous fumiez . C'est pour cela"
             "que vous avez arrêté. Réjouissez-vous de plus être"
             "fumeur.", "Tu as toujours voulu t'arrêter , rejouis toi !"]
    return liste[random.randint(0, len(liste)-1)]


def jcraque():
    """module je craque"""
    canvas['bg'] = "white"
    affiche("c'est pas grave, ça va bien ce passer...")

# ############ Initialisation fenetres et boutons ##############
root = tk.Tk()
root.title('La vie est belle')
root.geometry('+10+10')
root.grid()

frameA = tk.Frame(root)
frameA.grid(sticky=tk.NW)  # gauche toute

bouton = tk.Button(frameA, text='Remettre le compteur à 0')
bouton.grid(column=1, row=0)
b_histo = tk.Button(frameA, text='Historique')
b_histo.grid(column=0, row=0)
b_eteint = tk.Button(frameA, text='Éteindre',
                     width=50, command=root.destroy)
# widh détermine la largeur du bouton
b_eteint.grid(column=2, row=0, padx=200)
# padx permet de mettre une marge externe
# au widget b_eteint en pixel (décale le bouton)
b_jourfume = (tk.Button(frameA, text="J'ai craqué", command=jcraque))
b_jourfume.grid(column=3, row=0)
canvas = tk.Canvas(root, width=1400, height=200, bg="pink")
canvas.grid()
# ######### Constantes à modifier selon les besoins  ###
joursrestant = tempsrestant(2019, 4, 25)  # Ceci est le jour j
tempseffectue = tempseffectue(2019, 1, 22)  # Le 1er jour du compte à rebour

# ######### Début du coeur du programme #####
affiche('                   <-------------Bravo, ' + str(tempseffectue) +
        '  jours se sont écoulés. Dans ' +
        str(joursrestant) + ' jours champagne!!')

while True:
    canvas['bg'] = "black"
    extraitsTexte = str(extraits())
    affiche('                '+extraitsTexte, couleurTexte="white")

root.mainloop()
~/mes_scripts jt'écoute :pep8 Newcompte_rebourbis.py 
~/mes_scripts jt'écoute :pylint3 Newcompte_rebourbis.py 
No config file found, using default configuration
************* Module Newcompte_rebourbis
C:  1, 0: Invalid module name "Newcompte_rebourbis" (invalid-name)
C: 19, 0: Invalid argument name "couleurTexte" (invalid-name)
C:129, 0: Invalid constant name "root" (invalid-name)
C:134, 0: Invalid constant name "frameA" (invalid-name)
C:137, 0: Invalid constant name "bouton" (invalid-name)
C:139, 0: Invalid constant name "b_histo" (invalid-name)
C:141, 0: Invalid constant name "b_eteint" (invalid-name)
C:147, 0: Invalid constant name "b_jourfume" (invalid-name)
C:149, 0: Invalid constant name "canvas" (invalid-name)
C:152, 0: Invalid constant name "joursrestant" (invalid-name)
C:153, 0: Invalid constant name "tempseffectue" (invalid-name)
C:162, 4: Invalid constant name "extraitsTexte" (invalid-name)


Report
======
64 statements analysed.

Statistics by type
------------------

+---------+-------+-----------+-----------+------------+---------+
|type     |number |old number |difference |%documented |%badname |
+=========+=======+===========+===========+============+=========+
|module   |1      |1          |=          |100.00      |100.00   |
+---------+-------+-----------+-----------+------------+---------+
|class    |0      |0          |=          |0           |0        |
+---------+-------+-----------+-----------+------------+---------+
|method   |0      |0          |=          |0           |0        |
+---------+-------+-----------+-----------+------------+---------+
|function |6      |6          |=          |100.00      |0.00     |
+---------+-------+-----------+-----------+------------+---------+



Raw metrics
-----------

+----------+-------+------+---------+-----------+
|type      |number |%     |previous |difference |
+==========+=======+======+=========+===========+
|code      |71     |42.51 |71       |=          |
+----------+-------+------+---------+-----------+
|docstring |60     |35.93 |60       |=          |
+----------+-------+------+---------+-----------+
|comment   |15     |8.98  |15       |=          |
+----------+-------+------+---------+-----------+
|empty     |21     |12.57 |26       |-5.00      |
+----------+-------+------+---------+-----------+



Duplication
-----------

+-------------------------+------+---------+-----------+
|                         |now   |previous |difference |
+=========================+======+=========+===========+
|nb duplicated lines      |0     |0        |=          |
+-------------------------+------+---------+-----------+
|percent duplicated lines |0.000 |0.000    |=          |
+-------------------------+------+---------+-----------+



Messages by category
--------------------

+-----------+-------+---------+-----------+
|type       |number |previous |difference |
+===========+=======+=========+===========+
|convention |12     |12       |=          |
+-----------+-------+---------+-----------+
|refactor   |0      |0        |=          |
+-----------+-------+---------+-----------+
|warning    |0      |0        |=          |
+-----------+-------+---------+-----------+
|error      |0      |0        |=          |
+-----------+-------+---------+-----------+



Messages
--------

+-------------+------------+
|message id   |occurrences |
+=============+============+
|invalid-name |12          |
+-------------+------------+



Global evaluation
-----------------
Your code has been rated at 8.12/10 (previous run: 8.12/10, +0.00)

Je ne sais pas si le programme gagne en visibilité mais il est conforme aux préconisations du PEP8.
La convention qui veut que les lignes ne dépassent pas les 80 caractères sera , pour moi, la plus difficile a tenir.
Pour la mise en forme d'une longue liste, la fonction format paragraph de idle est bien utile...

édit: Pour éviter les invalid-name de pylint il faut lancer la commande pylint comme il suit :

pylint3 --reports=n --disable=deprecated-module --const-rgx='[a-z_][a-z0-9_]{2,30}$' machintruc.py 

Explication: https://docs.pylint.org/en/1.6.0/tutorial.html

Dernière modification par Compte supprimé (Le 05/02/2019, à 21:36)

#11 Le 06/02/2019, à 07:37

kholo

Re : [Résolu]Pourquoi mon code n'est pas conforme à pep8/pylint ?

bon,
je vais pouvoir répondre à ton fil !

d'abord le code :
alors ton texte défile toujours à la vitesse d'une F1 sur mon PC et est donc illisible...
en fermant, j'ai ce retour :

Traceback (most recent call last):
  File "fab2.py", line 163, in <module>
    affiche('                '+extraitsTexte, couleurTexte="white")
  File "fab2.py", line 32, in affiche
    canvas.move(item, -3, 0)
  File "/usr/lib/python3.5/tkinter/__init__.py", line 2434, in move
    self.tk.call((self._w, 'move') + args)
_tkinter.TclError: invalid command name ".139797284369968"


------------------
(program exited with code: 1)
Press return to continue

d'ailleurs quand je vois cette ligne, ya un manque d'espace entre + et extraitsTexte

affiche('                '+extraitsTexte, couleurTexte="white")

pour la longueur de tes lignes, comme me dit souvent Watael pour le bash, c'est mieux de séparer le code des données...
pour traduire pour ton script, la fonction "extraits" pourrait être remplacée par une routine qui lit et parse un fichier texte avec ses dictons pour les importer (ce qui simplifierait leur gestion)
NB : si c'est toujours les même, ya un doublon tongue

pour les lignes trop longues, ya divers astuces...
pour le texte, pense à la localisation qui demanderait de factoriser ton texte dans un dico (ou fonction, lambda ou index d'une liste) et remplacerait toutes les phrases par des appels.

pour le reste, par exemple :

    item = canvas.create_text(0, 0, anchor='nw',
                              text=annonce,
                              font=("Helvetica", 100, 'bold'),
                              fill=couleurTexte)

peut passer par divers "triturages" dans une fonction spécifique et dont les arguments seraient dans un dico ou une liste
et c'est là que viennent se poser les contradictions entre la programmation fonctionnelle et les préconisations de la POO.
Je m'explique :
python est fait pour faire de la POO mais n'oblige personne à suivre ce paradigme. Donc, soit tu fais de la POO et pylint ou pep8 te seront utile pour rendre ton code plus pythonique, soit tu fais de la prog fonctionnelle et tu fais comme tu veux tant que tu estimes que ton code est lisible et qu'il pourrait être repris par quelqu'un... voire que ce code n'est pas fait pour être repris.
NB : je me suis un peu énervé hier et j'ai fini par aller faire un tour du côté des librairies de python pour comprendre comment font les autres... et en me disant que certaines devraient être parfaitement conforme. j'ai commencé par une au hasard, puis beautifulsoup, puis future... et bien non, outre que je les trouve imbitable, pylint confirme qu'elles sont gorgées de non conformité.
Mon crédo est : je sais quand je commence à savoir que je ne sais rien.
Après le batch, le VB, le VBA, le C, le java, le python (du temps de 1.3), le bash, le javascript, ... et j'en oublie, j'ai mis des années, et c'est très récent et grâce à Python (et au mooc), que j'arrive enfin à commencer à programmer en POO.
J'ai du sang qui me sort des yeux et des doigts tellement je passe de temps à bosser pour sortir du code propre mais je peux le dire maintenant : Enfin je commence à savoir car je sais que je ne sais rien...
bon code big_smile

PS : j'ai aussi vu passer les fils qui expliquent comment ne pas tenir compte des retours de pylint... ma question est "ça sert à quoi si ce n'est à avoir une meilleure note de résultat voire de ne pas s'encombrer de retours"... autant les parser à grand coup de grep -v !

Dernière modification par kholo (Le 06/02/2019, à 07:41)

Hors ligne

#12 Le 06/02/2019, à 11:18

Compte supprimé

Re : [Résolu]Pourquoi mon code n'est pas conforme à pep8/pylint ?

Salut,

alors ton texte défile toujours à la vitesse d'une F1 sur mon PC et est donc illisible...

ça ne m'étonne pas , la vitesse est réglée sur mon ordi qui est particulièrement lent (AMD E1)..
(ce qui m'interroge sur comment assurer la même vitesse d'affichage sur tous les ordi...? )

J'ai du sang qui me sort des yeux et des doigts tellement je passe de temps à bosser pour sortir du code propre

manque plus que les cheveux en bataille et le teint blafard  tongue .

Hs : J'ai regardé ton code . j'y ai découvert super().__init__() et le module threading. Question : l'utilisation de threading etait il vraiment nécessaire ? Une simple gestion des events n'aurait il pas suffit? ... je vais voir ça

Merci @kholo pour tes échanges

#13 Le 06/02/2019, à 12:43

kholo

Re : [Résolu]Pourquoi mon code n'est pas conforme à pep8/pylint ?

pour les questions...
je suis parti bille en tête à faire ma class... pour le côté graphique, le canvas, que j'ai juste survolé,...
puis je suis arrivé sur la gestion de ce texte défilant...
j'ai pas mal cherché et, pour dire vrai, j'ai fini par trouver la solution seul mais pas pour le côté threading pour lequel j'ai pioché pas mal à droite et à gauche...
je suis d'abord parti de time mais time accapare le programme donc pas glop... (appuie sur les boutons et changement de couleur pas trop possible sans rafistolage)
c'est comme ça que je suis arrivé à threading
et il a fallu que je me fasse violence pour en rester là et ne pas retourner à un simple sleep qui était trèèèèès tentant !
et finalement il est bien là l'enflure !
donc le thread permet de relâcher et continuer le process principal qui est le programme (le GUI) et donner la possibilité de faire des pauses... par exemple...
et donc, je répond à ta question, c'est ce sleep qui permet d'attendre entre deux scroll et donc devrait être identique sur la plupart des machines à partir d'une certaine puissance (je pense même la tienne... je vais tenter ça sur mon rasp2 pour voir !)

HS pour les observations,
le plaisir est partagé wink
je sais que je sais quand je sais expliquer... alors tu fais un parfait testeur ! voire béta testeur

pseudofab a écrit :

manque plus que les cheveux en bataille et le teint blafard

j'ai pas grand chose en cheveux ; mais oui, ils sont en bataille, et j'ai la chance d'être sur Nice... le peu que je sort roll c'est le soleil assuré... heureusement !
... ah, ya mon thunderbird qui couine pour me dire que j'ai un mail du prochain mooc de python qui commence... miam, miam !!! Rhaa lovely !!!!!! RIP Gotlib

Hors ligne