Il mio codice Python è scritto bene?

10 novembre 2009

Chiedilo a pep8.py ;)

Per chi non lo sapesse, la PEP 8 è una specifica di Python che indica come si dovrebbe scrivere il codice (definisce come deve essere l’indentazione ecc.).
Questo programma verifica se il codice scritto è conforme alla PEP 8 :)

Link: http://github.com/jcrocholl/pep8/raw/master/pep8.py

frafra Python ,

Scaricare l’ultima versione di un certo programma

10 novembre 2009

Vi è mai capitato di dover (o voler) scaricare l’ultima versione di uno o più programmi? O sapere semplicemente se è stato rilasciato un aggiornamento?
Bene, a Frafra queste cose capitano, soprattutto quando si parla di sorgenti, compilazione, e compagnia cantante :)

Ho creato un programma Python (>= 3.x, testato su 3.1.1), che risolve automaticamente questo problema, con l’uso di un parser e di un crawler :) Sono cento linee giuste giuste, parzialmente commentate, con tanto di licenza (questa volta metto il file per intero, perché in primo luogo ho raggiunto un numero di linee tondo tondo, e in secondo luogo perché la prima linea è molto importante).

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
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# takeit.py
#
# Copyright 2009 Francesco Frassinelli <fraph24@gmail.com>
#
#     This program is free software: you can redistribute it and/or modify
#     it under the terms of the GNU General Public License as published by
#     the Free Software Foundation, either version 3 of the License, or
#     (at your option) any later version.
#    
#     This program is distributed in the hope that it will be useful,
#     but WITHOUT ANY WARRANTY; without even the implied warranty of
#     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
#     GNU General Public License for more details.
#    
#     You should have received a copy of the GNU General Public License
#     along with this program. If not, see <http://www.gnu.org/licenses/>.
 
""" This program shows you the latest version of a source package """
 
### HTMLParser patched version, see: http://bugs.python.org/issue755660
# $ cp /usr/local/lib/python3.1/html/parser.py HTMLParser.py
# $ wget http://bugs.python.org/file13041/htmlparser_error.diff
# $ patch -p0 HTMLParser.py < htmlparser_error.diff
import HTMLParser
import re, sys, urllib.request
 
servers = {
    "gnu":"http://ftp.gnu.org/gnu/",
    "linux":"http://ftp.kernel.org/pub/linux/",
    "vim":"http://ftp.vim.org/pub/vim/unix/",
} # List of available servers: add yours and report test them
 
class Parser(HTMLParser.HTMLParser):
    def __init__(self, page, callback):
        super(Parser, self).__init__()
        self.callback = callback
        self.page = page # Current page
    def handle_starttag(self, tag, attrs):
        if tag == "a":
            attrs = dict(attrs)
            if "href" in attrs:
                self.callback(self.page, attrs["href"])
    def error(self, message):
        pass # Overwriting default function, in order to skip any error
 
class Crawler:
    def __init__(self):
        self.source = re.compile(r"""^
            (.+?)-                  # package name
            ([\d\.-]+)              # version
            \.(tar\.bz2|tar\.gz)    # compression
            $""", re.VERBOSE) # VERBOSE is for multiline commented regex
        self.packages = dict()
    def inspect(self, page):
        print("I'm in:", page) # If there're errors, report it *always*
        with urllib.request.urlopen(page) as data:
            parser = Parser(page, self.callback)
            parser.feed(data.read().decode("utf_8", "ignore"))
            parser.close()
    def item(self, page, link):
        if self.source.match(link):
            res = self.source.search(link)
            package, version, compression = res.groups()
            if package == "0": # Should we use re.match("^\d+$", package)?
                return # Not properly detected: regex could be wrong
            if package not in self.packages:
                self.packages[package] = list()
            self.packages[package].append((version, page + link))
    def callback(self, page, link):
        # Special link / Backwards link / External link or absolute path
        useless = "?" in link or ".." in link or link.count("/") > 1
        if not useless:
            if link.endswith("/"):
                self.inspect(page + link) # Directory: recursive function
            else:
                self.item(page, link) # File: analize its name
    def results(self):
        for package, version in sorted(self.packages.items()):
            version, url = sorted(version, reverse = True)[0]
            yield package, version, url # Just to iterate it
 
def mycrawler(base, directory = ""):
    crawler = Crawler()
    crawler.inspect(base + directory)
    for package, version, url in crawler.results():
        print() # Newline ("\n")
        print("Name:", package)
        print(" -> Version:", version)
        print(" -> URL:", url)
 
if __name__ == "__main__":
    args = len(sys.argv)
    base      = (servers[sys.argv[1]],) if args > 1 else servers.values()
    directory = set(sys.argv[2:])       if args > 2 else ("",)
    for server in base:
        for page in directory:
            mycrawler(server, page)

frafra Linux, Python , ,

Gioco della vita di Conway: da Python a C

7 novembre 2009

Vi ricordate il post sul gioco della vita di Conway (life)? Avevo scritto un algoritmo che oltre a implementare questo giochino (vedi Gioco della vita di Conway), ricercasse, con un bruteforce, tutte le figure che si ripetevano. Ora l’ho riscritto in C, supportando come parametri anche shift e step (sono un metodo grezzo per permettere un balance tra cpu/pc lanciando processi con parametri diversi) e un metodo economico (ma stupido) per il calcolo delle figure successive (vedere la variabile dirty e la nota n. 1). Quest’ultima caratteristica rende l’algoritmo intrinsecamente più veloce rispetto a quello che avevo scritto in Python, per cui le prestazioni sono sfasate (penso che questo trucco possa rendere il codice cinque volte più veloce mediamente, ma devo ancora studiare meglio gli effetti).

Tenendo conto di questo, il rapporto tra il programma in C, il programma Python convertito in C++ con Shedskin, la versione che usa Psyco, e la versione “classica”, è: (approssimativamente) 1:10:70:300. Ripeto: devo ancora applicare l’algoritmo nuovo in Python, e pare che gli ultimi tre dati si possano dividere per cinque circa, portando la versione Shedskin nello stesso ordine di grandezza della versione in C (questo sottolinea la validità del progetto), mentre la versione Pythonica sarebbe meno di due ordini di grandezza più lenta.

Il codice è questo :) Non lo commenterò passo passo, in quanto mi pare molto leggibile e simile a quello della versione in Python. Oltretutto, è già lungo di suo, quindi eviterei di riprendere inutilmente pezzi di codice per commentare la loro funzione :D Ho tolto la licenza… Tenete conto che, ovviamente, è sotto GPLv3:

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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
#include <stdio.h>
#include <stdlib.h>
 
void clean(int *p, int dim) {
    int c; for (c=0; c<=dim; c++, p++) *p = 0;
}
 
void clone(int *from, int *to, int dim) {
    int c; for (c=0; c<=dim; c++) to[c] = from[c];
}
 
int compare(int *from, int *to, int dim) {
    int c;
    for (c=0; c<=dim; c++) { if (*to != *from) return 0; from++; to++; }
    return 1;
}
 
int main(int argc, char *argv[]) {
    if ((argc != 3) && (argc != 5)) {
        printf("Usage: %s [rows] [columns] [shift] [step]\n", argv[0]);
        return 1;
    }
    const int rows = atoi(argv[1]);
    const int columns = atoi(argv[2]);
    const int dim = rows*columns;
 
    int shift = 0;
    int step = 1;
    if (argc == 5) {
        shift = atoi(argv[3]);
        step = atoi(argv[4]);
    }
    if (shift >= step) {
        printf("shift/step are invalid.\n");
        return 2;
    }
 
    int clean_stage[dim];  int *clean_p = &clean_stage[0];
    clean(clean_p, dim);
 
    int alpha_stage[dim];  int *alpha_p = &alpha_stage[0];
    clean(alpha_p, dim);
    int beta_stage[dim];   int *beta_p = &beta_stage[0]; 
    clean(beta_p, dim);
    int first_stage[dim];  int *first_p = &first_stage[0];
    clean(first_p, dim);
 
    int i;
 
    int dirty;
 
    int p = dim-1;
    int r, sum, row, column, row_p, row_n;
    r = 0;
    while (1) {
        p = dim-1;
        while (first_stage[p] == 1) p--;
        first_stage[p] = 1;
        for (p++; p<dim; p++) first_stage[p] = 0;
        if (r%step != shift) {
            r++;
            continue;
        } else r = 0;
        clone(first_p, alpha_p, dim);
        dirty = 0;
        while (dirty != 18) { /* [1] Nota a fine programma... */
            for (i=0; i<dim; i++) {
                row = i/columns;
                column = i%columns;
                if (row == 0) {
                    row_n = i+columns;
                    if (column == 0) sum =\
                        alpha_stage[i+1] +\
                        alpha_stage[row_n] +\
                        alpha_stage[row_n+1];
                    else if (column < columns-1) sum =\
                        alpha_stage[i-1] +\
                        alpha_stage[i+1] +\
                        alpha_stage[row_n-1] +\
                        alpha_stage[row_n] +\
                        alpha_stage[row_n+1];
                    else sum = \
                        alpha_stage[i-1] +\
                        alpha_stage[row_n-1] +\
                        alpha_stage[row_n];
                } else if (row < rows-1) {
                    row_p = i-columns;
                    row_n = i+columns;
                    if (column == 0) sum =\
                        alpha_stage[row_p] +\
                        alpha_stage[row_p+1] +\
                        alpha_stage[i+1] +\
                        alpha_stage[row_n] +\
                        alpha_stage[row_n+1];
                    else if (column < columns-1) sum =\
                        alpha_stage[row_p-1] +\
                        alpha_stage[row_p] +\
                        alpha_stage[row_p+1] +\
                        alpha_stage[i-1] +\
                        alpha_stage[i+1] +\
                        alpha_stage[row_n-1] +\
                        alpha_stage[row_n] +\
                        alpha_stage[row_n+1];
                    else sum =\
                        alpha_stage[row_p-1] +\
                        alpha_stage[row_p] +\
                        alpha_stage[i-1] +\
                        alpha_stage[row_n-1] +\
                        alpha_stage[row_n];
                } else {
                    row_p = i-columns;
                    if (column == 0) sum =\
                        alpha_stage[row_p] +\
                        alpha_stage[row_p+1] +\
                        alpha_stage[i+1];
                    else if (column < columns-1) sum =\
                        alpha_stage[row_p-1] +\
                        alpha_stage[row_p] +\
                        alpha_stage[row_p+1] +\
                        alpha_stage[i-1] +\
                        alpha_stage[i+1];
                    else sum =\
                        alpha_stage[row_p-1] +\
                        alpha_stage[row_p] +\
                        alpha_stage[i-1];
                }
 
                beta_stage[i] = 0;
                switch (sum) {
                    case 2: beta_stage[i] = alpha_stage[i]; break;
                    case 3: beta_stage[i] = 1;
                }
            }
            if (compare(beta_p, first_p, dim)) {
                for (i=0; i<dim-1; i++) printf("%d ", first_stage[i]);
                printf("%d\n", first_stage[dim-1]);
                break;
            }
            if (compare(alpha_p, beta_p, dim)) break;
            clone(beta_p, alpha_p, dim);
 
            dirty++;
        }
    if (compare(first_p, clean_p, dim)) break;
    }
    return 0;
}
 
/* Nota [1]:
  Per non comparare sempre lo stage corrente con quelli precedenti,
  ho creato una modalità "stupida" di computazione. Il valore 18
  indica che non è necessario calcolare ulteriori stages se non si è
  ancora usciti dal ciclo, in quanto pare che non ci siano figure nel
  primo stadio, che si ripetano dopo il 18esimo stadio. */

P.S. Ho trovato una implementazione di questo giochino, molto carina, (senza bruteforce ovviamente) nella directory di Python 3.1.1 (ma penso si trovi anche in versioni precedenti) che usa curses, sotto Python-3.1.1/Demo/curses/life.py :)

frafra C/C++, Python , ,

Paldo: una distribuzione interessante

7 novembre 2009

E’ da un po’ di mesi che provo questa distribuzione poco nota. Le peculiarità?

  1. In un cdrom sono contenuti tutti i programmi che ci si aspetterebbe, inclusi Openoffice, Gimp e Inkscape
  2. Software aggiornatissimo
  3. Veloce e leggera, ma non gli manca nulla (avvia anche cups e openssh al boot)
  4. Gnome-centrica
  5. Comodissima per compilare: il sistema di gestione dei pacchetti permette di scegliere se installare il binario o il sorgente, che verrà automaticamente compilato. Inoltre, è già inclusa una suite di programmi atti alla compilazione e allo sviluppo, oltre agli headers file di tutti i programmi (non c’è la divisione tra pacchetti -dev e non)

Pochi giorni fa, è stata rilasciata la versione 1.20. Non è stata ancora annunciata sul sito, ma è possibile scaricarla sotto la pagina di download.

Ho testato questa versione sul mio nuovo portatile (Asus UL30), e sono rimasto piacevolmente colpito :) Inoltre ho scritto un post sul forum di paldo dove mostro i problemi riscontrati, cosa si può migliorare, e un paio di workaround (utili quelli per utilizzare qemu in accoppiata con kvm e quello per creare una pennetta usb con paldo live, processo riutilizzabile per altre distribuzioni).

Il link è: Paldo forum – Topic 673

Il sito della distribuzione è: Paldo.org

frafra Guide, News

Condividere una connessione

12 settembre 2009
little tux

Il guardiano del router e compagna :)

Proprio ieri sono stato privato della mia linea ADSL casalinga (sto traslocando). In un primo momento, sono stato preso dal panico, pensando a un malfunzionamento del router (basato su Linux, ha sempre funzionato benissimo). Nonostante nella mia testa iniziasse a girovagare l’idea che mi avessero staccato la linea, per i primi 30 minuti il mio cervello non accettava il fatto, come quando viene a mancare un animale domestico al quale si è affezionati e nonostante ciò gli si riempie la ciotola di pappa :) Dopo qualche reboot dei miei tre scatolotti necessari per far funzionare la mia rete (un modem ethernet, un router 4 porte wifi, e uno switch 8 porte), ho guardato il “guardiano del router” (un piccolo pinguino di peluche che tiene lontani gli spiriti cattivi dalla mia connessione), e gli ho detto: “mi dispiace, per un po’ ti toccherà fare il disoccupato…”.

Detto ciò, ho passato un po’ di tempo a sistemare i miei programmini Python, e a pubblicare su github un po’ di codice (vedasi github.com/frafra, dove ho pubblicato anche una interessante applicazione PyQT4+Twisted per la chat), utilizzando il pc di un amico :) Questo mio amico (nonché vicino di casa), ha acconsentito a condividere temporaneamente la sua connessione wifi. E qui inizia il divertimento :)

Obiettivo: dare internet alla lan, utilizzando una rete wifi

Sostanzialmente, abbiamo bisogno di un pc che da una parte si connetta dalla rete wireless, e dall’altra condivida la propria connessione. Per fare ciò sul pc dotato sia di scheda wireless sia di scheda ethernet dobbiamo:

  1. Connetterci alla rete (soluzione più semplice: networkmanager)
  2. ifconfig eth0 192.168.100.1 up
    (ho scelto 192.168.100.1 perché così sono sicuro che non si tratti di una rete già in uso)
  3. echo 1 > /proc/sys/net/ipv4/ip_forward
  4. iptables -t nat -A POSTROUTING -o wlan0 -j MASQUERADE
    (dove eth0 è l’inferfaccia di rete e wlan0 quella wifi)
  5. Installare dnsmasq
  6. Editare /etc/dnsmasq.conf, mettendo:
    domain-needed
    bogus-priv
    interface=eth0
    dhcp-range=192.168.100.2,192.168.100.100,12h
  7. Avviare il demone dnsmasq
    (spesso basta dare /etc/init.d/dnsmasq start o /etc/rc.d/dnsmasq start)

Tutti questi comandi devono essere avviati come superutente (quindi o aggiungendo sudo davanti a ogni comando, o digitando su [invio] prima di iniziare la procedura). Dagli altri computer ora potete connettervi come se fosse presente un normale router nella rete locale (quindi con networkmanger, o lanciando un dhclient/dhcpcd eth0), e il gioco è fatto ;) Per collegare più dispositivi alla rete del mio portatile, ho collegato i vari computer (incluso il portatile) allo switch. Nulla di più facile :D

<a href=
Ecco che, grazie alle mie doti nell’arte figurativa (eeeh!) e a inkscape, ho creato una mappa della rete, prima e dopo :)

P.S. Ehi, ho appena fatto 19 anni, sto invecchiando :D Domani si parte per l’avventura chiamata “università” ;)

frafra Frafra, Guide, Linux , ,

Con Kolivas è tornato!

4 settembre 2009

L’anestesista più chiacchierato nel mondo del software libero è tornato a due anni di distanza, dopo l’abbandono dello sviluppo del suo set di patch al kernel Linux (chi non si ricorda il patchset -ck?).

Per ora non pare sia interessato alla mainline di Linux, però ha già rilasciato del codice interessante. Cosa avrà mai sviluppato? Uno scheduler ovviamente :) Perché? Perché Linux è migliorato molto sotto questo aspetto, ma lo scheduler attuale, stando alle parole del nostro eroe, è adatto principalmente per macchine con molti processori, e passa molto tempo calcolando come bilanciare il carico. Kolivas ha fatto uno scheduler che, al contrario, va meglio sui normali computer, meglio se con un paio di cpu :)

Ecco il covo! ck.kolivas.org/patches/bfs/

frafra Linux, News , ,

Tesina multimediale in PyQT4/XHTML/CSS

3 settembre 2009

Ecco che,  come promesso, ho pubblicato la mia tesina multimediale, scritta (e programmata) per la mia maturità.

Attualmente la struttura è funzionante, ma mancano alcune grosse correzioni che ho apportato il 10 luglio (la prima versione che ho appena pubblicato risale al 9 luglio). Le apporterò al più presto (grazie alla copia cartacea della tesina, dato che la versione definitiva che ho portato all’orale s’è volatilizzata).

La cosa interessante di questa tesina multimediale consiste nel fatto che è stata creata con le seguenti caratteristiche:

  • Il programma per visualizzare i contenuti è scritto in Python
  • La libreria grafica utilizzata è QT (>= 2.5) che, grazie a un widget particolare, permette di renderizzare le pagine web con webkit
  • I contenuti sono stati scritti in XHTML/CSS (validati dal correttore del W3C)

Questo mi ha permesso di portare una tesina diversa dal solito, che ha interessato i professori, al posto della noiosissima e poco efficace presentazione Powerpoint. Inoltre, avendola fatta in xhtml/css, l’ho potuta (con un semplice browser) salvare in pdf e stamparla, ottenendo così anche una versione cartacea).

L’ho caricata su github, all’indirizzo: github.com/frafra/Tesina-Frafra/tree

Potete scaricarla premendo su download (e scaricandola sottoforma di archivio compresso), oppure clonando il repository git. Tutto il codice è commentato.

frafra Frafra, Python , ,

Nemmeno un editor nano può tanto…

28 agosto 2009

E ora che “L’estate sta finendooo…”, ci si prepara a lottare contro la vita quotidiana… In particolare Frafra ha appena finito di sistemare il suo Aspire One (che monta una Archlinux con sopra KDE svn con tanto di desktop semantico funzionante).

Della serie “ma Frafra non ha nulla di meglio da fare?”, ecco a voi un simpatico screenshot, che narra di una breve discussione a tre, tra me, dolphin e konsole:

Notare la scritta nel riquadro del terminale… La finestra è troppo piccola per nano :D

frafra Cavolate, Frafra , ,

Un nuovo amico: Sheevaplug

5 agosto 2009
sheevaplug

sheevaplug

Eccomi :) In compagnia di Sheeva Plug, il mio nuovo server arrivato dall’America l’altro ieri, con le seguenti caratteristiche:

Processore ARM Kirkwood 1.2 Ghz
Memoria 512 mb DDR2
NAND  512 mb (con Ubuntu Jaunty modificata, con filesystem jffs2 compresso)
Presa USB generica, USB da utilizzare come tty, lettore SD, presa ethernet.
Dimensioni simili a quelle di un alimentatore.
Consumo intorno ai 5 watt ora.

Non male vero? Con la spedizione, il cambio, e la dogana è venuto 130€ circa. Non è un amore? :D

Attualmente sono riuscito a ricreare un debootstrap una Debian Lennyminimale con un kernel 2.6.30 ottimizzato per arm-kirkwood su una pennetta usb, e ad effettuare il boot da essa. Il boot loader è un po’ incasinato. Presto farò una guida completa e testata sul come mettere una bella Debian Lenny al posto di Ubuntu Jaunty (niente in contrario, ma dopo un upgrade ho dovuto resettare la password di root modificando i parametri di boot, dato che il login dava sempre errore).

Penso che ognuno dovrebbe adottare un piccolo kiwi (l’ho chiamato così, per una assonanza improbabile con l’architettura del processore… “kirky” sembrava più un mostriciattolo o un aspirapolvere) :D

frafra Gingilli ,

Test d’ingresso e lan party notturno

16 giugno 2009

tankb2…E così, il nostro intrepido studente Frafra, passò con successo il test di ammissione a ingegneria informatica del Politecnico di Milano :) E dato che attualmente è abbastanza libero (in fondo, ha “solo” la maturità), ha organizzato un lan party durato dalle ore 21.00 alle ore 6.30 del mattino successivo, nel quale lui e tre suoi amici, si sono ammazzati al mitico bzflag :D Frafra ottenne sempre il miglior punteggio personale, ma vinse solo una volta su tre, anche se una partità finì sul punteggio di 19-20. La serata è proseguita con intermezzi di Fifa ‘09 e di Call of duty 4 in full hd. Risultato? Un successo :)

Appena finirò la maturità faremo un altra serata di questo tipo, ma con qualche persona in più, e metterò l’invito per partecipare anche su questo blog, nel caso qualcuno voglia giocare un po’ da casa sua :) Se invece volete organizzare qualcosa a casa vostra, vi elenco gli ingredienti che hanno reso il nostro lan party unico, fatto solo di sano divertimento ;)

Ecco la lista delle cose necessarie:

  1. Un numero di amici superiore a tre (preferibilmente dispari, in modo che le squadre risultino essere composte da un numero uguale di partecipanti) disposti a passare tutta la notte al pc
  2. Una quantità sufficiente di liquerizia (in bastoncini, pastiglie, cubetti), di caffé, e di stuzzichini
  3. Un numero sufficente di pc (rigorosamente con Linux, altrimenti il partecipante partirà con un punteggio di -5 a bzflag)
  4. Un router con uno switch (per l’occasione, mi sono dotato di uno switch ethernet 8 porte)
  5. Un numero di persone sane mentalmente (aka genitori) presenti in casa pari a zero (altrimenti portate del cloroformio)

Ecco la lista delle cose che NON sono necessarie:

  1. Una camera grande (la mia stanza è piccola, un partecipante era seduto perfino per terra col portatile sopra il mio letto)
  2. Un computer megagigaultra-veloce (ogni informatico sa che non è l’hardware che fa il monaco… aspetta, ma era così il detto? xD)
  3. Delle ragazze (è dimostrato scientificamente che il lag di un computer in una lan è direttamente proporzionale al numero di esseri femminili presenti nel raggio di 100m)

Detto questo… Divertitevi! Mentre io torno a lavorare sulla mia tesina “multimediale” programmata in Python/Qt4.5 e xhtml/css xD (poi vi mostrerò il codice sorgente e il risultato ottenuto, a lavoro ultimato)

frafra Frafra ,