Magie de la commande find – part 1

30 012012

find est une commande de ouf. je suis loin loin de maîtriser, mais voici quelques unes de mes utilisations favorites :

rechercher un fichier par son nom :

find . -name *.htc -print

rechercher une chaine de charactères dans un fichier :

find . -type f -print | xargs grep -n ma_chaine_a_rechercher

(comparer la vitesse à celle d’un IDE ou d’un gestionnaire de fichiers graphique..)

rechercher des fichiers par taille (utile pour repérer un fichier de log qui part en sucette) :

find . -type f -size +200M -print

rechercher des fichiers modifiés récemment :

find . -mtime -1 -print

ex : prendre les fichiers créés depuis 24h et les archiver dans un tar !

find . -type f -ctime -1 |xargs tar -czvf recent.tar.gz
Publié dans Scripts Shell | Marqué avec , , , | Laisser un commentaire

Validator Custom pour Entités

10 012012

Exemple de validator custom avec une validation de l’âge sur des dates de naissance :

MonBundle/Validator/Majeur.php

namespace Maboite\MonBundle\Validator;

use Symfony\Component\Validator\Constraint;

/**
* @Annotation
*/

class Majeur extends Constraint
{
public $message = 'Vous devez être majeur-e pour jouer.'; //<- le message par défaut
}

MonBundle/Validator/MajeurValidator.php

namespace Maboite\MonBundle\Validator;

use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;

class MajeurValidator extends ConstraintValidator
{
    public function isValid($value, Constraint $constraint)
    {
        $now=new \DateTime("now");
        $diff=$value->diff($now);
       
        // ( le test sur l'année ne suffit pas car diff renvoie une "vraie" différence tenant compte des années bisextiles )
        if ($diff->y == 18) {
            if ($diff->m > 1) return true;
            if (intval($now->format('j')) >= intval($value->format('j'))) return true;
        } else {
        if ($diff->y > 18) {
            return true;
        }
        }
       
        $this->setMessage($constraint->message);
        return false;
       
       
       
    }
}

Dans l’entité concernée on peut utiliser la validation :

MonBundle/Entity/User.php

....
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Bridge\Doctrine\Validator\Constraints as DoctrineAssert;

use Maboite\MonBundle\Validator\Majeur as Majeur;

....

/**
* @var date $datenaissance
*
* @ORM\Column( type="date")
* @Assert\NotBlank(message="Veuillez saisir votre date de naissance.")
* @Majeur(message="Vous devez être majeur-e pour jouer.")
*/

private $datenaissance;

voilà maintenant la contrainte fonctionnera comme les contraintes prédéfinies lors de vos appels à $form->isValid()

Publié dans Symfony | Marqué avec , , , , , , | Laisser un commentaire

Happy 2012

09 012012

By the way… mes voeux de nouvelle année 2012 réalisés sous forme d’animations javascript 1k

Publié dans Javascript | Marqué avec | Laisser un commentaire

Fonctions récursives dans un script shell

05 012012

En cherchant un petit script pour compter des lignes de code dans un dossier, je suis tombé sur la problématique de la récursivité pour parcourir les sous dossiers.
N’étant pas un spécialiste du shell, je ne savais pas qu’on pouvait déclarer des fonctions en shell, donc voici comment faire :

#!/bin/bash

fichierstexte=( html phtml php css js yml );
nbextensions=${#fichierstexte[@]}
nblignes=0
nbfichiers=0

if [ -z "$1" ]
then
    echo "manque argument du dossier"
    exit
fi



recursiveCount() {
    for file in "$1"/*; do
        if [ -f "$file" ]
        then
            extension="${file#*.}"
            for ((i = 0; i < nbextensions; i++)); do
                if [ ${fichierstexte[i]} = $extension ]
                then
                    nb=`wc -l < $file`
                    nblignes=$((nblignes + nb +1))
                    nbfichiers=$((nbfichiers + 1))
                fi
            done

        elif [ -d "$file" ]
        then
            recursiveCount "$file"
        fi
    done
}

recursiveCount $1

echo "nombre de lignes dans $1"
echo "total lignes : $nblignes"
echo "total fichiers : $nbfichiers"

le script produit ce genre de sortie :

julien@julien-desktop:~/Sites$ ./countlines.sh jsproxy/
nombre de lignes dans jsproxy/
total lignes : 8694
total fichiers : 40

à améliorer pour pouvoir passer plus de paramètres comme des dossiers à exclure par exemple.

Publié dans Scripts Shell | Marqué avec , , , , | Laisser un commentaire

Des Chiffres et des Lettres – Timer et ProgressBar

08 062011

Pour créer un timer qui va décompter le temps on va utiliser les threads de Python dans une classe séparée.
On va importer les classes nécessaires et surtout initialiser les threads.

import threading,time,gobject
gobject.threads_init()

La classe qui va gérer le thread comporte 3 paramètres : la barre de progression, le temps, la fonction à apeller quand le timer expire

class MaBarre(threading.Thread):
    def __init__(self, barre, tempstotal,callback):
        super(MaBarre, self).__init__()
        self.barre = barre
        self.tempstotal=tempstotal
        self.callback=callback
        self.quitter=False
        self.on = False
        self.compteur = 0.0

    def update_barre(self, frac):
        if self.on:
            self.barre.set_fraction(frac)
            return False

    def run(self):
        print "run"
        #tant que le thread est actif
        while not self.quitter:
            if self.on: #si le compteur est allumé et non expiré alors
                self.compteur += 0.1
                frac=self.compteur/self.tempstotal
                if frac<=1.0:
                    gobject.idle_add(self.update_barre, frac)
                else:
                    self.lancer_callback()
            time.sleep(0.1)
           

    def stop(self):
        self.quitter=True
    def setOn(self):
        self.on=True
        self.compteur = 0.0
    def setOff(self):
        self.on=False
    def lancer_callback(self):
        self.setOff()
        self.callback()

TODO : pour faire plus propre il faudrait enlever le set_fraction pour regrouper tout ce qui est GUI dans le main thread.

Ensuite, dans la classe principale, il faut :

  • instancier le timer
  • détruire le timer si on quitte

on rajoute donc

self.threadpbar=MaBarre(self.pbar,5.0,self.timeup)
self.threadpbar.start()

dans la fonction main() et

self.threadpbar.stop()

dans la fonction destroy

Le code complet :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
#!/usr/bin/env python
# -*- coding: utf-8 -*-

import pygtk
pygtk.require('2.0')

import string,random
import threading,time,gobject
import gtk

gobject.threads_init()

class MaBarre(threading.Thread):
    def __init__(self, barre, tempstotal,callback):
        super(MaBarre, self).__init__()
        self.barre = barre
        self.tempstotal=tempstotal
        self.callback=callback
        self.quitter=False
        self.on = False
        self.compteur = 0.0

    def update_barre(self, frac):
        if self.on:
            self.barre.set_fraction(frac)
            return False

    def run(self):
        print "run"
        #tant que le thread est actif
        print self.quitter
        while not self.quitter:
            if self.on: #si le compteur est allumé et non expiré alors
                self.compteur += 0.1
                frac=self.compteur/self.tempstotal
                if frac<=1.0:
                    gobject.idle_add(self.update_barre, frac)
                else:
                    self.lancer_callback()
            time.sleep(0.1)
           

    def stop(self):
        self.quitter=True
    def setOn(self):
        print "timer=on"
        self.on=True
        self.compteur = 0.0
    def setOff(self):
        self.on=False
    def lancer_callback(self):
        self.setOff()
        self.callback()

class ChiffresEtLettres:

    def delete_event(self, widget, event, data=None):
        print "delete event occurred"
        return False

    def destroy(self, widget, data=None):
        print "destroy signal occurred"
        self.threadpbar.stop()
        gtk.main_quit()
    def __init__(self):
        print "_init_"
        # création de la fenêtre
        self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
        self.window.set_title("Des Chiffres et des Lettres")
        self.window.connect("delete_event", self.delete_event)
        self.window.connect("destroy", self.destroy)

        self.window.set_border_width(100)

        table=gtk.Table(11,3,False)

        self.window.add(table)    

       
        #labels tirages
        self.lettre=[]
        for i in range(10):
            self.lettre.append(gtk.Label(""))
            table.attach(self.lettre[i], i+1, i+2, 0, 1)

        # bouton nouveau tirage
        button = gtk.Button("Nouveau tirage")
        button.connect("clicked", self.tiragelettres, None)
        table.attach(button, 0, 1, 0, 1)
       
        #progress bar
        self.pbar = gtk.ProgressBar()
        table.attach(self.pbar, 1, 11, 1, 2)

        #tout montrer
        self.window.show_all()
        self.window.show()

    def main(self):
        self.threadpbar=MaBarre(self.pbar,5.0,self.timeup)
        self.threadpbar.start()
        gtk.main()
    def tiragelettres(self, widget, data=None):
        print "Nouveau tirage de lettres"
       
        for i in range(10):
            self.lettre[i].set_text(string.ascii_uppercase[random.randint(0,25)])

        self.demarrertimer()
    def demarrertimer(self):
        print "Demarrage du timer"
        self.threadpbar.setOn()
    def timeup(self):
        print "times up"


if __name__ == "__main__":
    cl = ChiffresEtLettres()
    cl.main()

Ce qui donne ceci :

Le timer se déclenche sur le nouveau tirage, le callback est apellé quand le temps est écoulé.
Prochaine étape : améliorer la qualité des tirages

Publié dans Des Chiffres et des Lettres | Laisser un commentaire

Des Chiffres et des Lettres – premier tirage

08 062011

On va poursuivre le script précédent en connectant le bouton nouveau tirage à un tirage aléatoire de lettres.
Pour cela on va utiliser des labels que l’on remplira par des lettres non accentuées et en majuscules.
On importe random et string :

import string,random

Création des labels :

self.lettre=[]
for i in range(10):
self.lettre.append(gtk.Label(""))
table.attach(self.lettre[i], i+1, i+2, 0, 1)

Remplissage aléatoire :

for i in range(10):
self.lettre[i].set_text(string.ascii_uppercase[random.randint(0,25)])

Code complet :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
#!/usr/bin/env python
# -*- coding: utf-8 -*-

import pygtk
pygtk.require('2.0')
import gtk
import string,random

class ChiffresEtLettres:

    def delete_event(self, widget, event, data=None):
        print "delete event occurred"
        return False

    def destroy(self, widget, data=None):
        print "destroy signal occurred"
        gtk.main_quit()
    def __init__(self):
        print "_init_"
        # création de la fenêtre
        self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
        self.window.set_title("Des Chiffres et des Lettres")
        self.window.connect("delete_event", self.delete_event)
        self.window.connect("destroy", self.destroy)

        self.window.set_border_width(100)

        table=gtk.Table(11,3,False)

        self.window.add(table)    

       
        #labels tirages
        self.lettre=[]
        for i in range(10):
            self.lettre.append(gtk.Label(""))
            table.attach(self.lettre[i], i+1, i+2, 0, 1)

        # bouton nouveau tirage
        button = gtk.Button("Nouveau tirage")
        button.connect("clicked", self.tiragelettres, None)
        table.attach(button, 0, 1, 0, 1)
       
        #tout montrer
        self.window.show_all()
        self.window.show()

    def main(self):
        gtk.main()
    def tiragelettres(self, widget, data=None):
        print "Nouveau tirage de lettres"
       
        for i in range(10):
            self.lettre[i].set_text(string.ascii_uppercase[random.randint(0,25)])


if __name__ == "__main__":
    cl = ChiffresEtLettres()
    cl.main()

Ce qui donne :

On voit que les tirages sont super chauds : trop de X,Y,ou Z, trop de consonnes, on verra comment améliorer ça plus tard. D’abord on va regarder comment créer un timer et le lier à une barre de progression

Publié dans Des Chiffres et des Lettres | Laisser un commentaire

Des Chiffres et des lettres – Hello World

08 062011

Pour ce premier chapitre on va se contenter d’afficher une fenêtre GTK avec bouton et de connecter les différents signaux :

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
#!/usr/bin/env python
# -*- coding: utf-8 -*-

import pygtk
pygtk.require('2.0')
import gtk

class ChiffresEtLettres:

def delete_event(self, widget, event, data=None):
print "delete event occurred"
return False

def destroy(self, widget, data=None):
print "destroy signal occurred"
gtk.main_quit()
def __init__(self):
print "_init_"
# création de la fenêtre
self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
self.window.set_title("Des Chiffres et des Lettres")
self.window.connect("delete_event", self.delete_event)
self.window.connect("destroy", self.destroy)

self.window.set_border_width(100)

table=gtk.Table(11,3,True)
self.window.add(table)

# bouton nouveau tirage
button = gtk.Button("Nouveau tirage")
button.connect("clicked", self.tiragelettres, None)
table.attach(button, 0, 1, 0, 1)

#tout montrer
self.window.show_all()
self.window.show()

def main(self):
gtk.main()
def tiragelettres(self, widget, data=None):
print "Nouveau tirage de lettres"

if __name__ == "__main__":
cl = ChiffresEtLettres()
cl.main()

Ce qui donne :

Etape suivante : Générer un tirage de lettres

Publié dans Des Chiffres et des Lettres | Laisser un commentaire

Des Chiffres et des Lettres – intro

07 062011

Mon but dans cette série d’articles est d’écrire un programme en Pyhon pour m’entraîner aux Chiffres et Lettres, version 10 chiffres, ainsi que pour apprendre Python.

On pourra jouer seul ou a plusieurs en réseau, le programme aura une fonction pour vérifier le mot et si c’est bien le mot le plus long.

Cet exercice va permettre de balayer un large spectre des possibilités de Python.

  1. L’interface graphique
  2. La génération du tirage
  3. Les timers/threads
  4. Amélioration du moteur de tirage
  5. Vérification du tirage
  6. Début d’IHM
  7. Algorithme du Compte est Bon
  8. IHM du Compte est Bon
Publié dans Des Chiffres et des Lettres | Marqué avec , | Laisser un commentaire