oriolrius.cat

Des del 2000 compartiendo sobre…

Tag: python

Conceptes de Clutter

Reading time: 6 – 9 minutes

Des de fa uns mesos m’he posat a fons amb Clutter, es tracta d’una API més una ABI programada en C per crear interficies d’usuari. Malgrat tractar-se en escència d’una API per crear espais 3D amb objectes 2D, té la capacitat de poder moure els objectes en la coordenada Z. Així doncs, és pot aprofitar la potència d’OpenGL de forma transparent i senzilla i sense haver-se de preocupar de com representar objectes 2D en espais 3D, cosa gens senzilla per un neofit en el món dels gràfics com jo.

Clutter usa el seu propi reactor d’events, però en certs casos pot usar Gobject, Glib i Gtk també. És fàcilment integrable amb DBUS i amb GStreamer. En escència m’ofereix tot el que em cal per un projecte que porto entre mans. Pels que encara no ho tingueu clar, l’interficie gràfica que usa Moblin esta programada amb Clutter com a llibreria gràfica. De fet, és aquest projecte el que li ha donat molta força a Clutter que disposa de 29 programadors a temps complet, dels quals 14 no són d’intel (intel és qui promociona amb més força ‘moblin’).

Bé doncs, aquest impuls que ha patit moblin l’han portat a la versió 0.9.8 que és realment potent i ja gairebé igual que la versió 1.0 que hauria de sortir en breu. Tot i que fins ara Clutter s’ha caracteritzat pel retard en la sortida de les noves versions esperem que aquest cop no sigui així.

Abans d’entrar a definir quins són els elements que té aquesta llibreria, comentar que també disposa de binding de python cosa que pels ‘no-programadors’, com jo, és tota una alegria. També s’ha de dir que a dia d’avui, no hi ha bindings oficials per la branca 0.9 de Clutter que és l’experimental, o futura 1.0. Així doncs, jo només he provat el Clutter fins a la seva versió 0.8, malgrat la segueixo amb lupa la versió 0.9.x; a l’espera de poder començar a fer coses amb ella quan tingui els bindings de python.

Anem al motiu central de l’article, repassar els conceptes que usa Clutter fins a la verió 0.8:

  • Stages: una aplicació de Clutter conté almenys un ‘stage’, aquests contenen actors que són: imatges, rectangles, textos, etc. Un ‘stage’ es comporta de forma semblant a un ‘canvas’ (tapís).
  • Stage Widget: Podem contenir un ‘stage’ dintre d’un objecte finestre de GTK+. En aquests casos es pot usar GTK com a reactor d’events.
  • Actors:  són formes 2D mostrades en un espai 3D. Aquestes formes poden ser; per exemple, formes geomètriques, imatges, textos, etc. Si el que cal és tenir actors tridimencionals en aquest espai el que caldrà és instanciar directament l’API d’OpenGL.  Per mostrar un actor en un ‘stage’ cal fer-ho a través d’un ‘container’.
  • Transformations: es refereix a les transformacions que li podem fer a un ‘actor’ al mostrar-lo:
    • Scaling: aumentar o disminuir la seva mida aparent, no la real.
    • Rotation: es pot rotar sobre els seus eixos X, Y i Z.
    • Clipping: fixar l’objecte sobre el ‘canvas’ això ens permet per exemple, crear una zona d’scrolling al seu intererior.
    • Movement: desplaçar les coordenades de posició de l’objecte.
  • Containers: en si mateix és un tipus especial d’actor, compost per altres actors fills que es posicionen en l’espai respecte la posició del seu contenedor. De fet, si ens hi fixem el propi ‘stage’ és un ‘actor’ de tipus ‘container’. Escencialment hi ha dos tipus de ‘containers’: ClutterContainer i ClutterGroup.
  • Events: la classe ‘actor’ emet una serie de senyals que podem capturar per enllaçar amb funcions, les senyals són:
    • button-press-event: emès quan l’usuari prem el botó del ratolí sobre l’actor.
    • button-release-event: emès quan l’usuari deixa anar el botó del ratolí sobre l’actor.
    • motion-event: quan el ratolí es mou per sobre l’objecte.
    • enter-event: emès a l’entrar sobre la superficie de l’actor.
    • leave-event: emès al sortir de la superficie de l’actor.
  • Timelines: es poden usar per canviar la posició o aparença d’un actor al llarg del temps. Les línies de temps es poden usar soles o amb combinació dels ‘effects’ i els ‘behaviours’. Per cada ‘frame’ que s’ha de dibuixar en el temps s’emet una senyal anomenada ‘new-frame‘, obviament la podem connectar a alguna funció. Al crear una línia de temps hem d’espificar dos paràmetres: la quantitat total de ‘frames’ que tindrà i els ‘frames per segon’ a la que es reproduirà.
  • Score: podem agrupar diverses ‘timelines’ en un ‘score’, això ens permet posar en marxa o parar diverses ‘timelines’ a la vegada.
  • Effects: són una serie de funcions que podem aplicar sobre els actors usant una ‘timeline’ amb l’objectiu de canviar les propietats al llarg del temps, usant un simple càlcul numèric. Sovint aquesta és la forma més simple de crear una animació. És important recordar que els efectes només poden afectar a un actor en una ‘timeline’ i no podem canviar els efectes al llarg del temps, per fer això cal fer-ho amb un ‘behaviour’.
  • Behaviours: tenen la capacitat de canviar una propietat específica d’un actor al llarg del temps aplicant un simple càlcul numèric. A diferència dels ‘effects’ amb els ‘behaviours’ podem controlar més d’un actor a la vegada i canviar els paràmetres dels càlculs que es fan al llarg de la ‘timeline’. Un exemple ben senzill d’aplicació d’això seria que podem fer que la funció que es crides al llarg del temps detecti que s’ha acabat l’efecte aplicat i el faci tornar a començar automàticament, simplement canviant el paràmetre de l’efecte que s’esta aplicant. Els ‘behaviours’ que té Clutter per defecte són:
    • ClutterBehaviourBspline: mou l’actor a través una línia ‘bezier‘.
    • ClutterBehaviourDepth: mou un actor a l’eix Z.
    • ClutterBehaviourEllipse: mou un actor al llarg d’una el·lipse.
    • ClutterBehaviourOpacity: canvia l’opacitat d’un actor.
    • ClutterBehaviourPath: mou un actor al llarg d’un camí definit per una serie de punts.
    • ClutterBehaviourRotate: rotar un actor.
    • ClutterBehaviourScale: canvia la mida aparent d’un actor.

Per fer aquesta referència m’he basat amb la informació de la guia ‘Programming with Clutter‘ escrita per Murray Cumming.

python trick: compartir directori via HTTP

Reading time: 1 – 2 minutes

A vegades estant en la propia LAN, suem tinta per dir-li a un usuari de windows com ho ha de fer per agafar un fitxer d’un directori del nostre linux. Si teniu python instal·lat, normalment totes les distribucions l’instal·len per defecte a més del paquet HTTP. Podeu fer una cosa tan simple com posar al .bashrc:

alias quickweb='python -c "import SimpleHTTPServer;SimpleHTTPServer.test()"'

Ara aneu al directori on voleu compartir els fitxers i escriviu: quickweb. Això obrirà el vostre port 8000 i qualsevol usuari de la xarxa podrà connectar-se amb el navegador a la vostre IP pel port 8000. Allà es pot veure i descarregar els fitxers que hi teniu. Quan volgueu deixar de compartir el directori només cal fer un Control+C i llestos.

Realment una xorrada molt i molt útil, no? si voleu comprovar què esteu compartint ja ho sabeu: http://127.0.0.1:8000. Més senzill impossible.

pop2smtp: POP3 (“recojetodo”) a SMTP amb múltiples destins

Reading time: 2 – 3 minutes

Alguns ISPs ens permeten tenir una compte que reculli tot el correu enviat a un domini, això per exemple es pot usar com a mail-backup del nostre domini. Doncs bé a través de fetchmail és molt senzill re-injectar el correu enmagatzemat a una compte POP3 a un servidor SMTP contra un usuari. El més complicat, és si el correu que hi ha a la compte POP3 pot anar a més d’un destí, com el que deia fa un moment en comptes POP3 tipus ‘recojetodo’ o cul de sac com diuen alguns.

Doncs bé, per això he fet un petit script en python que a partir d’un fitxer BSMTP modifica la companda RCPT TO en funció de la informació de l’etiqueta Envelope to que conté una llista de les comptes d’email destí a qui va dirigit el correu. Així doncs, bàsicament la tasca consisteix en buscar quines comptes d’email apareixen a l’etiqueta comentada i després borrem la comanda RCPT TO i creem tantes comandes d’aquest tipus com faci falta en el seu lloc per enviar copies del correu que volem enviar als seus destins. Aquest nou fitxer BSMTP modificat l’injectem al nostre MTA. Aquest MTA serà l’encarregat de processar aquest correus i entregar-los a les comptes destí.

En el meu cas he decidit fer un petit shell script que s’executa des del crontab cada 10min. Aquest script, Crida a fetchmail per obtenir el fitxer BSMTP amb el correu que hi havia a la compte POP3, després crida l’script de python per modificar el fitxer BSMTP d’entrada tal com he comentat i crea un nou fitxer BSMTP de sortida. Finalment aquest fitxer s’injecta via SMTP cridant un petit script que gràcies al NetCat envia per SMTP el contingut del fitxer BSMTP de sortida.

L’script amb l’estructura de directoris empaquetat en un fitxer: pop2smtp_r1.tar.gz.

Segur que hi ha formes més elegants de resoldre el problema, però la veritat no les he sabut trobar.

Python: Reiniciem el router si no hi ha internet

Reading time: 1 – 2 minutes

Malgrat fa uns dies vaig canviar el meu vell Zyxel per un Cisco 837 a casa, la línia ADSL es continua penjant per motius desconneguts. Ja que quan les dades no circulen ni amunt ni aball les interficies ATM estan aixecades i tot sembla funcionar correctament. Així doncs, no m’ha tocat altre remei que fer-me un petit script amb Python a través del qual cada 5min comprovo si tornen els pings contra un dels servidors de OpenDNS. Si això no és així llavors es connecta contra el router Cisco i el reinicia. Ja que he fet proves baixant i pujant la interficie ATM i no hi ha manera. No se m’ha acudit cap millor idea que llençar un reload.

L’script guarda un fitxer de log a /var/log/online.log i usa el modul pexpect de Python. La resta de coses que usa són moduls que van instal·lats per defecte.

Si a algú li pot fer falta l’script el podeu descarregar: router.py.

Python trick: error Address already in use

Reading time: 1 – 2 minutes

Quan treballem amb sockets en python sovint al publicar un port si matem el procés que publicava el port encara que sigui de forma correcte ens trobem que al llençar-lo de nou, o sigui, a l’intentar publicar altre cop el procés aquest dona error un error que diu algo així com Address already in use. O sigui, que el sistema operatiu es pensa que el port encara esta sent publicat pel procés que ja em matat. Si fem un netstat veiem que el port no hi és, però encanvi fins al cap d’una estoneta (alguns segons o minuts) no hi ha manera de poder usar de nou aquest port.

Doncs bé, un petit truquillo perquè això no passi i el poguem usar a l’instant és fer això després de crear l’objecte de la classe socket:

# creació de l'objecte
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# afegim noves propietats a l'objecte
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)

cleanup-maildir – netejant el maildir

Reading time: 2 – 2 minutes

Avui he trobat aquest article Cleanup Maildir folders (archive/delete old mails) | MDLog:/sysadmin i no he dubtat ni un segon en baixar-me l’script: cleanup-maildir (local) programat en python. De fet, el seu nom ja diu molt del que fa. Bàsicament jo l’uso per netejar el directori Junk. És a dir, allà on rebo les alertes de correus considerats spam, virus, phishing o d’altres malwares. És a dir, he posat l’script al cron i li he dit que el contingut de la carpeta Junk del maildir que tingui més de 15 dies es vagi eliminant. Així no m’he de preocupar d’anar borrant de forma periódica tot el correu mailiciós que ja mai miraré perquè ningú m’ha dit allò tan famós de: “T’he enviat un correu, no ho has vist?” i llavors comences a buscar per la carpeta on hi ha tota la brossa a veure si el troves. Doncs bé, ara només hi haurà 15 dies de brossa.

Realment és un script molt xorra però que el trobo molt útil, ja que té força opcions com per exemple no borrar els correus marcats com a llegits, o com a importants, o crear automàticament subcarpetes on guardar els correus que tenen una antiguitat determinada. Segurament encara em deixo alguna funció però jo diria que la idea queda més que clara.

python: Abyss Webserver start and stop host from CLI

Reading time: 1 – 2 minutes

Petit script en python per iniciar/parar el Abyss Webserver des de la línia de comandes. Només hem de posar la URL d’on es troba la web de la consola de l’Abyss i l’ususari i el password per entrar-hi. Com que esta fet ràpid i corrents, no es suporta el pas de paràmetres per indicar si s’ha d’engegar i/o parar el servei en cada moment. Així que si algú s’anima a afegir-hi les 4 línies de codi que hi falten que me les digui, que jo encara no domino prou el python com per fer-ho en 1s i avui ja estic cansat.

import urllib2

theurl = 'http://127.0.0.1:9999' username = 'theuser' password = 'thepass'
passman = urllib2.HTTPPasswordMgrWithDefaultRealm() passman.add_password(None, theurl, username, password) authhandler = urllib2.HTTPBasicAuthHandler(passman) opener = urllib2.build_opener(authhandler)
data_start = "%2Fhosts%2Fhost%400%2Fstart=Start" data_stop = "%2Fhosts%2Fhost%400%2Fstop=Stop"
data = data_start
request = urllib2.Request(theurl,data) response = opener.open(request)
print response.readlines()

python: Autenticació HTTP de tipus basic-scheme

Reading time: 1 – 2 minutes

Com accedir a un serividor HTTP amb les pàgines protegides amb usuari i password del tipus Basic Authentication Scheme.

import urllib2

theurl = 'http://host:port' username = 'theuser' password = 'thepass'
# this creates a password manager passman = urllib2.HTTPPasswordMgrWithDefaultRealm() # because we have put None at the start it will always use this # username/password combination passman.add_password(None, theurl, username, password) # create the AuthHandler authhandler = urllib2.HTTPBasicAuthHandler(passman) # Return an OpenerDirector instance, which chains the handlers in the # order given Return an OpenerDirector instance, which chains the # handlers in the order given opener = urllib2.build_opener(authhandler) # Install an OpenerDirector instance as the default global opener urllib2.install_opener(opener) # Open the URL url, which can be either a string or a Request object. pagehandle = urllib2.urlopen(theurl) lines = pagehandle.readlines()
for line in lines: print line

L’autentació que usa l’Abyss Webserver per defecte és la del tipus explicada en aquest exemple.

python: Generar passwords d’usuaris per l’Abyss Webserver

Reading time: < 1 minute

L’Abyss Webserver guarda en un fitxer de configuració en format XML els usuaris i passwords. Doncs bé el format en que estan enmagatzemats els passwords en el fitxer XML és:

usercode = nom_usuari + ":" + plaintext_password
encoded_password = md5(base64(usercode))

Doncs bé aquí ve el petit trick de com fer això amb python:

#!/usr/bin/env python
import md5
import base64
import re

def genera_pass_abyss(usercode): b64usercode = base64.encodestring(usercode) b64usercode = re.sub('\n','',b64usercode) hash = md5.new(b64usercode) return hash.hexdigest()
user = 'usuari1' passw = 'password1' usercode = user + ":" + passw print usercode print genera_pass_abyss(usercode)

pyGTK, Glade i SPE (Stani’s Python Editor)

Reading time: 2 – 4 minutes

SPE és l’editor que he començat a usar avui per programar en Python, concretament me l’he instal·lat per la facilitat d’acompletar les comandes especialment per accedir al binding de GKT+ (pyGTK). No és que m’hagi donat per programar en Python però porto un parell de dies liat amb el tema, ahir amb els webservices amb SOAP via SOAPpy i avui amb el pyGTK per tal de modificar una aplicació de compte enrera, concretament Countdown timer.

countdowntimer.png

Bàsicament el primer que he fet és modificar l’aparença de l’aplicació amb el Glade. Aquesta eina ens permet crear i editar GUI de forma senzillíssima. Arrossegant components i assignant mètodes que capturin les senyals dels components de l’aplicació, modificant els atributs dels components, etc. Realment sense tenir-ne ni idea el Glade ens crea un fitxer XML amb l’aparença d’una aplicació realment atractiva i còmode d’usar per l’usuari final.

glade.png

Tornant a l’SPE, doncs no esta malament és força còmode d’usar i té cosetes interessants, com ara la shell de python i un debuger. Però hi he trobat diversos inconvenients que em tenen una mica mosca. L’aplicació es penja moltíssim si usem el seu launcher per provar l’aplicatiu que estem desenvolupament. A més el debuger també es penja només invocar-lo. Suposo que deu ser algún problema de la instal·lació en gentoo.

spe.png

Però com a IDE també li trobo algunes mancances. Suposo que estic massa ben acostumat amb el Zend Studio. El problema esta en que jo voldria disposar d’ajuda en línia quan les opcions d’autocompletat de comandes es llencen així podria saber quina és la funció de GTK o Python que m’interessa en cada moment. Però no només no fa això sinó que la llista de funcions que dona per autocompletar sovint és reduida i no pas la llista completa de funcions suportades per l’objecte.

De fet, he trobat algún altre IDE per Python força interessant, com ara Wing IDE el problema és que és de pagament. Obviament sempre que puc uso vim. Però no vull acabar sent ni un expert de Python, ni de GTK, ni de pyGTK, ni res de tot això només sortir del pas el més ràpid possible amb aquesta necessitat i la veritat no trobo cap IDE que m’ajudi el suficient.