Reading time: < 1 minute
He montat un generador de codis QR al servidor de casa i que és usable des d'internet. Si a algú li fa falta és tan senzill d'usar com:
Abans de parlar de CouchDB, si no heu sentit a parlar mai de les bases de dades NoSQL, és important que sapigueu que no són bases de dades ralacionals, ni orientades a objectes. Sinó que es basen en un paradigme diferet, són orientades a documents.
Doncs bé, CouchDB és un projecte de la fundació Apache i és OpenSource, és clar. Algunes de les seves característiques són:
RESTful API
schema-less document store (document=JSON format w/binary support like attachments)
multi-version-concurrency-control model
user-defined query structured as map/reduce (javascript, python, C, etc)
incremental index update mechanism
multi-master replication
easily distributable
update validation
programat amb erlang
web based basic admin features
binding for python, C, .NET, PHP, Ruby, etc.
pros: retrieve information, cons: insert data
Actualment estic estudiant si usar aquest producte en un dels projectes que estic treballant. De fet, encara no tinc clar si aplica al 100% a les necessitats que tinc en el projecte però a priori s’ajusta prou bé. Perquè no penseu que això és una raresa que no coneix ningú informar-vos que Ubuntu One usa couchDB com a backend, pels que no conegueu el servei jo el vaig descobrir gràcies a l’article d’Ars Technica: Code tutorial: make your application sync with Ubuntu One.
Inicialment volia fer un manual de les funcions bàsiques de CouchDB però degut al munt de documentació que he trobat he pensat que era una tonteria re-inventar la roda, així doncs a continuació faré una ressenya de les fonts d’informació que he usat per coneixer aquesta base de dades:
CouchDB Implementation: descripció molt detallada i no massa extensa de com funciona per dintre aquest sistema de BBDD especialment dedicada al Pau. Destaco aquest paràgraf:
CouchDB is a “document-oriented” database where document is a JSON string (with an optional binary attachment). The underlying structure is composed of a “storage” as well as multiple “view indexes”. The “storage” is used to store the documents and the “view indexes” is used for query processing.
Abans d’acabar comentar que personalmentel que més m’ha costat d’entendre de tot plegat és el tema map/reduce especialment la part de reduce, ja que no acabava de veure al 100% com funcionava i quina finalitat tenia. Potser l’error més gran que he comès és intentar buscar un paral·lelísme directe entre SQL i NoSQL. Sota el meu punt de vista no són tecnologies substitutories, més aviat complementaries ja que cada una s’ajusta a un tipus de solucions diferents. Per tant, abans que res recomano que confronteu la vostre problemàtica amb cada un dels paradigmes: orientat a objectes, bbdd relacionals i orientat a documents.
A vegades quan estem fent un programa ens interessa que el nostre codi pugui ser extés sense haver de tocar la seva estructra, fins hi tot el que ens pot interessar és que aquest codi sigui extés en algunes ocasions i en d’altres no. Un altre requeriment que podem tenir també seria que qui l’extengui no siguem nosaltres. Sovint tot això i molt més s’acostuma a fer amb el que anomenem Plug-ins, per cert, sempre m’ha fet molta gràcia la traducció al català de la paraula: ‘afegitons’.
Doncs bé, com que jo de programació no hi entenc gaire li vaig demanar al Pau que m’ajudés a entendre els models de plug-ins que implementaven alguns programes fets amb Python, ja que m’ineressava integrar aquesta funcionalitat en una serie de codis que estic desenvolupament. En aquest post intentaré explicar com funciona el paradigma dels plug-ins que usa Trac.
Primer de tot cal tenir en compte que Trac usa un patró de desplegament d’objectes anomenat Singleton, o sigui que totes les instàncies d’un objecte es refereixes a la mateixa instància. De fet, no sé dir fins a quin punt és necessari que el codi segueixi aquest patró per usar el sistema de plug-ins; tot i que jo diria que almenys les parts del codi que vulguin ser exteses pel model de plug-ins de Trac l’han de seguir.
Els plug-ins de Trac tenen les següents característiques:
Un Plug-in és un component que extent la funcionalitat d’un altre component
Un Plug-in pot extendre un altre Plug-in
Per tal d’incorporar la filosofia que té Trac per suportar Plug-ins al nostre codi cal importar el component ‘trac.core’, d’aquest component usarem el següent:
trac.core.Interface (classe) s’usa per definir quin és el contracte que hauran de seguir els plug-ins.
trac.core.ExtensionPoint (funció) quan volem que un component sigui extés usarà aquesta funció per recuperar les implementacions del contracte. Deifineix els punts de hook que té el nostre codi.
trac.core.implements (funció) quan un component usa aquesta funció és per implementar un contracte, o sigui, que els plug-ins que es construeixin l’han d’usar.
Abans de seguir explicaré que s’enten per contracte. Un contracte és en escència una classe de tipus interficie (python no té aquest model com a tal) que defineix quins mètodes (o altres classes) poden ser extesos dins el component original. O sigui, que cal no només definir quin és el contracte que s’ofereix sinó també documentar-lo el millor possible, explicant quines són les entrades i sortides que s’esperen de cada un dels mètodes/classes.
Perquè tot plegat s’entengui millor el Pau em va posar el següent exemple:
Imaginem que tenim una classe del tipus DNI que implementa una base de dades de DNIs, on té un metode que ens permet entrar DNIs a la base de dades:
el que fa és carregar els plug-ins que extenen la funcionalitat del codi original. A més cal que ens fixem que el paràmetre que usa la funció és la classe que defineix el contracte sobre el que es fan els plug-ins:
Com es pot veure el contracte només defineix un mètode: ‘check’ que ha de tenir un paràmetre d’entrada i espera un valor boleà de sortida.
Cal fixar-se en que la classe DNI cada vegada que afegeixi un element a la base de dades (en aquest cas una simple llista), cridarà a tots els plug-ins que compleixin el contracte per l’ordre en que s’han instanciat (s’han importat al codi original) mitjançant el següent codi.
fordni_checkinself.dni_checks:ifdni_check.check(dni) is False:print"El dni %s sembla no ser correcte"% ( dni )return
Un exemple de plug-in sobre el codi anterior i que compleix el contracte especificat podria ser aquest:
Es pot veure com la classe és una instància de ‘trac.core.Component’ (model Singleton) i implementa la interfice ‘dni.IDNIInput’. A nivell funcional el que es fa és ben simple, comprovem que sigui una cadena de texte i que tingui una mida de 9 caràcters, si això es dona retorna un ‘True’ o sinó un ‘False’.
Un exemple de com quedaria el codi principal seria:
importtrac.coreclassIDNIInput(trac.core.Interface):defcheck(nom):""" Es cridada cada cop que s'entra un nou dni"""classDNI(trac.core.Component):dni_checks = trac.core.ExtensionPoint(IDNIInput)def__init__(self):self._dnis = []defadd(self,dni):assertnotdniinself._dnis,"DNI ja existeix"fordni_checkinself.dni_checks:ifdni_check.check(dni) isFalse:print"El dni %s sembla no ser correcte" % ( dni )returnself._dnis.append(dni)defllista(self):printself._dnis
A aquestes altures ja s’han carregat dos plug-ins que treballen un després de l’altre i s’ha pogut apreciar la simplicitat i potència del model. Obviament es poden trobar coses a faltar com per exemple algún element que defineixi el llistat de plug-ins disponibles i que permeti alterar l’ordre en que aquests s’executen però això ja s’hauria de desenvolupar a part.
Espero haver-ho descrit de forma entenedora i sent el més fidel possible a les explicacions del Pau, al que he d’agrair-li l’esforç i dedicació per explicar-me aquest model de Plug-ins de Python.
Aquestes últimes vacances a madeira he aprofitat per utitlizar una eina que fins ara incorporaven els mòbils que tenia però que fins ara que m’he passat a Android no m’he decidit a expremer, estic parlant d’htc footprints. És una eina que a partir d’un simple formulari permet registrar llocs emblemàtics, bonics, interessants, curiosos o que simplement volem recordar. Aquest formulari guarda coses com una fotografia del lloc, un títol, la posició del GPS, la direcció, pots afegir-hi comentaris de text i fins hi tot de veu; potser hem deixo algún detallet del que pots afegir-hi per cada entrada a footprints però escencialment això és tot el que fa. Obviament el bo del tema és que gràcies a les tecnologies que incorpora el telèfon omplir el formulari és ben senzill, ja que la foto, posició del GPS o gravació de veu es fan amb simples clics, com sempre el més molest és escriure text.
L’interessant del tema és que després això es pot exportar a un fitxer .kmz (tot el contingut del footprints) o un fitxer .kml (només una entrada del footprints). El .kmz conté en escència un paquet amb un fitxer kml i els arxius externs del footprints, per exemple, les fotografies o l’audio. Pel que fa al format del fitxer .kml es tracta d’un fitxer XML amb el contingut del formulari que he comentat anteriorment. Aquests fitxers són directament importables al Google Earth i a moltes altres eines de la saga de Google. Però el que a mi m’interessa comentar en aquest article és la llibereria libkml, també de google, la que vaig usar per parsejar el fitxer kmz de les vacances a Madeira.
A través d’un simple codi amb python vaig generar el codi en format dokuwiki necessari per montar-me l’esquelet de la web de les vacances a Madeira. De fet, el codi no esta gens polit i esta extret d’snippets d’exemple que he trobat per la web, però pel que jo volia era més que suficient. Al final del post hi teniu un enllaç.
Fa dies que en aquesta línia dono voltes a la idea de montar-me un servei que després de fer una entrada al footprints amb el mòbil enviï automàticament el fitxer .kmz/.kml per email a una direcció reservada que parsegi el correu i que automàticament doni d’alta aquest contingut a alguna de les seccions d’oriolrius.cat, de fet, encara no tinc clar si la millor idea és injectar-ho com a post o com a entrada del wiki, el que si que tinc clar és que això després s’haurà de referenciar al meu lifestream perquè així quedi constància de llocs interessants que coneixo i que sempre que vols recordar ja has oblidat. Si algú té idees de com millorar aquesta idea, ja ho sap, que m’avisi.
Sovint faig molts scripts de sistema usant python com a llenguatge de programació, doncs bé, sobretot quan aquests scripts s’han de llençar usant el ‘crontab’ va molt bé tenir un bon ‘log’ per saber com van les coses. Així doncs, la setmana passada vaig decidir posar-me a fons amb el tema ‘logging’ de python i ara la forma de fer ‘logs’ que uso per defecte en els meus scripts és:
Després d’importar la llibreria de ‘logging’ es recuperar el fitxer de configuració on estan definits els paràmetres de ‘logging’. Un cop carregat, descomento una o les dues línies que hi ha a continuació en funció de si vull logs per pantalla o només contra un fitxer. La última línia només indica fins a quin nivell de depuració he de fer mostrar logs.
A més vaig trobar un petit script, que carrega una GUI per generar les configuracions dels fitxers de configuració dels ‘logs’, realment útil i simple d’usar:
Aquesta GUI l’he trobada al paquet: logging-0.4.9.6.tar.gz concretament al directori ‘tests’. Si no voleu buscar tant també podeu descarregar-lo directament: logconf.py.
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.
La idea que es persegueix al usar múltiples esquemes en un sol projecte és la de poder usar múltiples bases de dades en un sol projecte. La idea sembla molt senzilla, però a través de la documentació oficial del projecte Symfony la veritat és que no he sabut trobar la solució. En l’explicació per portar a terme aquesta funcionalitat hem referiré tota l’estona als fitxers .yml i no als .xml equivalents, però suposo que la idea és totalment exportable.
Es tracta de deixar d’usar el fitxer schemal.yml i passar a usar diferents fitxers anomentats nomarbitrari_schema.yml, si encomptes d’un nom voleu usar un número tampoc hi ha problemes per fer-ho, per exemple, 1_schema.yml i successius.
Pel que fa al contingut d’aquests fitxers és el de sempre, tot i que jo ús recomanaria usar petites ajudes com aquesta:
Aquest nombasededades l’usarem després per especificar les dades de connexió al fitxer databases.yml, però potser el més interessant és fixar-se en el paràmetre package que ens permet que tot el model de dades quedi guardat dins de lib/model/nombasedades. O sigui, que tot queda molt més ben organitzat i fàcil d’accedir.
Cal que vigileu si dues bases de dades tenen dues taules que s’anomenen igual, ja que si això passa llavors hi haurà un conflicte en els models de dades que es generen, perquè aquestes tindran el mateix nom. Això és fàcilment solucionable simplement a l’schema heu de dir-li que el nom de la classe que representa les dades d’aquella taula de la base de dades és un nom diferent al de la taula, o sigui, el nom escollit per defecte.
Pel que fa al fitxer databases.yml el seu contingut és el de sempre, simplement cal que penseu que cal descriure la connexió de cada una de les bases de dades que heu anat declarant als diferents fitxers d’schema.yml, un exemple:
Per fi he trobat un plugin de highlighting que m’agrada, l’he trobat avui a través del blog del François Zaninotto. Llàstima que el plugin és força antic, no hi ha actualitzacions des de l’any 2006. Quan l’he instal·lat al WordPress 2.5.1 m’ha donat un problema amb els permisos malgrat estava com a administrador. Així doncs en un moment li he fet un workaround, o sigui, com que el blog només l’uso jo ara mateix i no uso els usuaris m’he saltat la validació que fa de si tinc permisos. D’aquesta manera l’he pogut configurar com pertoca.
Per si algú vol fer el mateix, al fitxer syntax_hilite.php li he comentat les línies que podem veure a continuació:
[php num=268]<br>//function for the Admin GUI<br>function igSynHilite_GUI() {<br>global $user_level, $igWpVersion;<br>get_currentuserinfo();<br>//if user is not an admin equalling/above level 8, then don't give any GUI<br>/*<br>if ($user_level < 8) { ?><br><div class="wrap"><br><h2>iG:Syntax Hiliter(v<!--?php print(IG_VERSION);?-->) Configuration</h2><br><!--?php _e("<br><br><div style="color:#770000;">You are not a <strong>LEVEL 8</strong> or above USER &<br ?--> hence you cannot configure <strong>iG:Syntax Hiliter</strong>. If you are a <strong>LEVEL 8</strong> or above USER,<br>then please Logout & Login again.<br><br></div><br>"); ?><br><br><?php return; } */if(!empty($_POST['igsh_plainTxt'])){[/php]
A més, els directoris que crea el fitxer .zip de la pàgina del plugin no són compatibles amb el WordPress 2.5.1. O sigui, que adjunto un .tar.gz amb els fitxers que he posat a BLOG_HOME/wp-content/plugins.
Aquest matí l’Alfredo m’ha informat que reddit ha obert el seu codi. Doncs bé després de mirar-me cada un dels components que ha explicat que esta usant m’ha faltat temps per passar-me per cada una de les pàgines web de les aplicacions per mirar-me a veure què tal. A continuació ús faig una llista del que més destaco, obviament són les aplicacions més inusuals i menys conegudes.
HAProxy: és un aplicatiu molt semblant al Pound, la seva finalitat es balacejar les peticions HTTP entre diferents servidors. Malgrat són aplicacions similars Pound i HAProxy poden treballar de forma combinada. Diguem que HAProxy esta molt més orientat a grans infraestructures i Pound és per entorns de carrega mitjana. El bo és que podem usar HAProxy i darrera usar Pound per fer redireccions més refinades en funció da la URL o certs paràmetres de les HTTP headers. També és diferencien bàsicament amb el tractament que fan dels paquets HTTPs, la qual també convida a treballar amb les dues eines a la vegada. Ja que podriem montar un sistema per escalar peticions HTTPs de forma segura i simple.
Slony-l:és un sistema de replicació master-slave que suporta treballar en cascada i amb failover. A més esta pensat per treballar amb bases de dades grans. Bàsicament usat pel PostgreSQL que usa reddit, això els permet tenir molts servidors de bases de dades de lectura que són les peticions que bàsicament tenen a la base de dades.
Pylons: es tracta d’un framework MVC que usa Python, és realment lleuger i combina idees del món Ruby, Python i Perl. Potser una de les coses que més sobte és que els projectes de Pylons no requereixe servidor web sinó es vol, ja que ells mateixos ja n’implementen un amb Python, a més de tenir un instal·lador del projecte que creem només pel sol fet de crear el projecte. Si ja controleu algún tipus d’MVC i esteu una mica familiaritzats amb la sintaxis de Python podeu veure l’screencast: Special Edition Screencast: Pylons with Tesla. Amb aquest screencast ús podreu fer una molt bona idea de com funciona aquest MVC i de la seva potència. S’ha de reconeixer que promet molt no ús perdeu el sistema de debug, realment m’ha agradat moltíssim pensava que el debug de Symfony era bo, però aquest encara el supera.
Slor: es tracta d’un servidor d’indexació d’informació web implementat sobre Tomcat i que ofereix serveis de consulta via JSON i d’altres sistemes webservice que simplifiquen moltíssim la seva integració amb d’altres arquitectures. A més disposa d’una llista de funcionalitats molt atractives.
Daemontools: una eina realment senzilla i potent, bàsicament només serveix per llençar processos com a dimonis o directament dimonis en si mateixos. El bo és que controla aquests dimonis per si aquests cauen tornar-los a aixecar. La veritat és que malgrat ser una mica més gran diria que és millor monit. Tot i que s’ha de dir que es triga molt mé montar monit que no pas daemontools i com que la gent de reddit ja usen Ganglia com a sistema de monitorització no s’han complicat amb el monit.
S’ha de reconeixer que han fet molt bones eleccions aquesta colla, a més s’ha demostrat que són realment escalables i que la seva disponibilitat és envejable. Un bon exemple de com fer les coses bé i senzilles des del principi. La gent de twitter en podrien prendre bona nota. Si ús fa il·lusió un dia d’aquests ús explicaré les meves idees de com fer que twitter sigui molt escalable i no s’enfosi amb els 2M d’usuaris que té diariament, la qual cosa no em sembla cap exageració amb un bon disseny darrera segur que en Pau pateix molt més amb els seus milions de megues a indexar diarimant.