Apr 21

dues versions de python en un host

Reading time: < 1 minute A vegades cal fer algún invent extrany amb el python, com per exemple, el haver de tenir dues versions instal·lades. Sovint la nostre distribució ja portarà una versió del mateix i a més moltes eines de les distribucions acostumen a anar lligades a aquesta versió que millor no malmetre. Cookbook d'ordres per instal·lar un python 2.6.5 a més del 2.4.3 que ja portava el host:

cd /var/tmp
wget http://python.org/ftp/python/2.6.5/Python-2.6.5.tar.bz2
tar xvfj Python-2.6.5.tar.bz2
cd Python-2.6.5
./configure –prefix=/usr
make
make altinstall

si ara fem:

# python -V
Python 2.4.3
# python2.4 -V
Python 2.4.3
# python2.6 -V
Python 2.6.5

Apr 16

long polling amb jquery+jsonp+couchdb (cross domain suportat)

Reading time: 6 – 9 minutes

Porto mesos somiant amb fer la prova de concepte que explico en aquest article, intentaré descriure en que consisteix però ja aviso que la cosa és un pèl complicadilla.

Funcionalitats requerides:

  • long polling: l’objectiu és rebre els canvis d’una base de dades de couchdb en temps real sense haver d’anar preguntant si hi ha canvis, sinó que aquest s’envien cada vegada que es donen de forma automàtica.
  • A través de jQuery el que vull és actualitzar una pàgina web de forma asíncrona, de forma que els nous resultats que vagin entrant a la BBDD es vagin mostrant en temps real a la pantalla.
  • JSONP, és una tècnica que ens permet rebre la sortida JSON de CouchDB i després cridar una funció de callback de JavaScript. El problema és que la funció jQuery.getJSON() original de jQuery té algunes mancances que gràcies a el plugin jQuery-JSONP podem solucionar, aquestes són: (copy/paste de la web del plugin)
    • error recovery in case of network failure or ill-formed JSON responses,
    • precise control over callback naming and how it is transmitted in the URL,
    • multiple requests with the same callback name running concurrently,
    • two caching mechanisms (browser-based and page based),
    • the possibility to manually abort the request just like any other AJAX request,
    • a timeout mechanism.
  • CouchDB és una base de dades NoSQL basada en documents que és capaç d’emetre una senyal (trigger) cada vegada que el contingut d’una base de dades canvia. Per més informació sobre el tema es pot consultar a: CouchDB: The Definitive Guide al capítol Change Notifications.
  • Cross-domain: quan es llença una petició XmlHttpRequest (la base del AJAX) amb JavaScript tenim la limitació de només poder-ho fer sobre el domini que serveix la pàgina web, cap altre port ni subdomini. Obviament tampoc un altre host. Per saltar-se aquesta restricción és quan cal recorrer a JSONP.

La prova de concepte ha estat crear una base de dades anomenada: notifcations on es guarden documents que són notificacions a mostrar a la pàgina web.

Després he programat la següent web:

<html>
<head>
<script type="text/javascript" src="jquery-1.4.2.min.js"></script>
<script type="text/javascript" src="jquery.jsonp-1.1.4.js"></script>
<script type="text/javascript">
function longpoll(since) {
    var url = "http://IP_COUCHDB_SERVER:5984/notifications/_changes?include_docs=true&feed=longpoll&since="+since+"&callback=?";
    console.log("since="+since);
    $.jsonp({
        "url":url,
        "success":function(data) {
            //console.log(data);
            since=data.last_seq;
            try {
                console.log(data.results[0].doc.msg);
            } catch(err) {
                console.log("error:"+err);
            };
            longpoll(since);
        },
        "error":function(msg) {
            //console.log(msg);
            console.log('capturat error');
        }
    });
};

var url = "http://IP_COUCHDB_SERVER:5984/notifications?callback=?";
$.jsonp({
    "url":url,
    "success":function(data) {
        //console.log(data);
        longpoll(data.update_seq);
    },
    "error":function(msg) {
        console.log(msg);
    }
});
</script>
</head>
<body>
cos
</body>
</html>

El codi és força simple de seguir, primer de tot es carreguen les llibreries: jQuery 1.4.2 i jquery-jsonp 1.1.4, ambdues necessaries per cridar el métode $.jsonp que és el que realment farà la feina.

A continuació es declara la funció longpoll que té com a paràmetre el númeral que indica quin ha estat el últim canvi a la base de dades. Aquest s’utiliza per construir la petició que es fa a CouchDB:

var url = "http://IP_COUCHDB_SERVER:5984/notifications/_changes?include_docs=true&feed=longpoll&since="+since+"&callback=?";

La URL el que fa és demanar el següent:

  • els canvis (_changes)
  • incloent els documents que han canviat (include_docs=true)
  • tracta la petició com a long polling (feed=longpoll)
  • mostra els canvis des de la versió X (since=X)
  • quan enviis els canvis fes una crida a la funció de callback definida aquí (callback=?)
    • ‘?’ és substituit per jquery-jsonp per la funció anomenada ‘C’, aquest nom es pot canviar usant paràmetres en la declaració de $.jsonp() que ve a continuació

Els missatges de l’estil ‘console.log()‘ són per tenir un seguiment del que va passant a la consola de javascript del navegador.

$.jsonp() té força paràmetres possibles definits a la API, però en aquesta prova de concepte només uso ‘url’, ‘success’ i ‘error’. El primer esta clar que és, els altres dos són les funcions a cridar quan l’acció va bé o malament respectivament. Dins de la funció posem el codi referent a les accions que volem fer, per exemple, actualitzar la pàgina actual. Com que això només és una prova de concepte el que faig és mostrar missatges per consola i llestos. La part més important és fixar-se que quan la cosa ha anat bé es fa una crida a ella mateix de forma que la cosa no acabi mai. De fet quan hi ha un error es podria també fer una crida a si mateix perquè no pares de provar de llençar la petició un i altre cop, però el que he fet per provar eś que es notifiqui a la consola de javascript i prou.

Fora de la funció longpoll el que es fa és una petició JSONP per saber quina és l’últim número de seqüència de la base de dades, paràmetre necessari per entrar per primera vegada a la funció recursiva de longpoll.

Conclusions

Pot semblar tot una mica enravassat però diria que he simplificat el problema moltíssim, ja que fins ara havia estat teoritzant moltíssim sobre el tema. Fins que ahir i abans d’ahir vaig haver de posar-me a provar-ho a la pràctica per saber exactament com es podia implementar. Sota el meu punt de vista ha quedat tot força net i entenedor.

Pels que sou programadors de webs habitualment haureu tingut necessitats semblants així doncs espero que ús pugui ser tan útil com a mi, de fet, fa unes setmanes que estic treballant amb Tiny Core Linux montant un Quiet PC sobre una DOM de 512MB per usar-la de sistema de monitorització de les meves xarxes i les d’alguns clients, espero que d’aquí uns mesos pugui donar-vos més informació del projecte.

Mar 01

Les últimes setmanes en fotografies

Reading time: 8 – 12 minutes

Com sembla que és una tònica en la meva vida tot corre molt, tot va molt ràpid i sempre hem passen mil i una coses. Qualsevol diria que normalment treballo des de casa, potser és gràcies a internet que hem permet mourem molt i aprofitar al màxim les sortides. Així doncs, per posar-me al dia he decidit re-editar un post que vaig fer l’any 2007: Fotografies dels últims dos dies. En aquest cas potser parlem de més de dues setmanes però la idea és la mateixa: buidar la targeta del mòbil i anotar coses curioses o no tan curioses al blog.

Des del 24 de gener continuo sense el meu portàtil, o sigui, que ja porto més d’un mes de patiments i esperes. De fet, gràcies a uns companys de LanA2 vaig poder-lo disfrutar garibé una setmana només netejant-lo ben net, però finalment va tornar a morir amb el mateix problema que el primer dia:

Malgrat alguna gent ha tingut la sort de que Dell li ha reparat el problema gratuitament, a d’altres com ara jo no hem tingut tanta sort. Així doncs, per eBay he demanat una placa base nova i encara estic a l’espera de rebre-la. Així podré recuperar el Dell m1330 que tan bon rendiment m’ha donat aquests quasi 3 anys.

Per altre banda, he demanat un Dell Studio 13 que fa més d’1mes que espero que Dell es digni a entregar-me, de fet, avui havia de rebre’l però segons l’estat de la comanda això no serà fins la setmana que ve, cosa que ja hem costa de creure quan han incomplert més de 3 vegades la data d’entrega.

Dell Studio XPS13

A nivell tècnic podriem dir que és l’evolució del m1330. Amb 8GB de RAM, 500GB d’HD i algunes millores en el lector de targetes flash a més d’una gràfica més potent, etc. Però el que realment m’ha fet comprar-ne un de nou no és tan el hardware sinó una garantia de 3 anys del dia després perquè no torni a estar com ara.
Canviant de tema, fa unes setmanes vaig ser al Mobile World Congress (MWC’10) de Barcelona, on vaig aprofitar per retrobar-me amb molts amics, no només durant la fira sinó durant tot el dia. Fins hi tot vaig retrobar-me amb el Fernando que després d’uns anys a Dublin a decidit establir-se a Barcelona. Pel que fa a la fira si no hi heu pogut anar, més enllà de mirar-vos mil fotografies i videos dels mòbils i d’altres cosetes que hi van presentar ús recomano llegir: 20 key trends at Mobile World Congress 2010 (1-10, 11-20).

Aquest any l’entrada va ser gentilesa de Google i més concretament de l’Ernest, que no només ens va aconseguir aquest passe als amiguetes sinó també una entrada a la conferència de desenvolupadors d’Android que es feia a la fira. La sorpresa que ens tenien preparats l’Ernest i la gent de Google és el regal d’un Nexus One al final de la xerrada.

Google Nexus One

Sobre el telèfon comentar que és un Android i com a tal tampoc es diferència tan del HTC Hero que ja tenia, això si quan sortim del sistema operatiu per mirar-nos el telèfon és impressionant el ràpid que arriba a funcionar la CPU d’1GHz i els més de 500MB de RAM. Tot el que feia amb la Hero ara mateix vola amb el Nexus One i quan dic vola vull dir que vola, estic impressionat. Per cert, el meu més gran descobriment dels últims dies a nivell d’aplicacions és una aplicació que es diu WebSharing i que permet compartir tot el mèdia que tinc al meu telèfon via Wi-Fi a través d’una interficie web senzillíssima d’usar i molt potent.

Aquesta setmana passada també ha estat molt especial perquè movilpoint ha venut la seva primera unitat de la nova gama de productes. Després de molts mesos de feina s’ha reorientat totalment la companyia i de forma oficiosa ja puc informar que els nous productes de l’empresa seran totalment hardware, o sigui, que ja no farem software. Són productes totalment ecològics, molt econòmics i fets a mida de cada client a través d’una configuració via web. La gama de producte esta totalment orientada a fires i events, espero poder-vos presentar la nova web ben aviat.

Mentretant podeu veure com estem treballant amb els nous punts d’informació:

i també donar un cop d’ull a la primera unitat instalada a casa d’un client:

Finalment aquest cap de setmana he estat a la DrupalCamp 2010 que es feia al Citilab de Cornellà; després de fer campana al phpWorkShop d’aquest any he passat a coneixer una mica més a fons a la gent i la tecnologia de Drupal. En general he sortit amb molt bon gust de boca de tot plegat, unes xerrades amb un bon nivell tècnic, una organització molt ben portada i una col·lecció de geeks més gran i fidel del que m’imaginava, això si, molt de Mac suelto 😉

Parlant de temes tècnics potser el que més m’ha agradat és SCRUM, que com cap metodologia de projectes és perfecte però si que aporta certs elements d’XP (eXtreme Programming) que sempre he trobat molt interessants. Potser la decepció més gran Open Atrium, no sé perquè m’esperava alguna cosa molt més potent. Per cert, alguna gent com en @quimet i en @linobertrand m’han preguntat què montava jo encomptes d’Open Atrium i això ho vaig respondre a un podcast que vaig fer el maig del 2008: Podcast 1×07: gestió de projectes. Per altre banda, des de llavors també he treballat amb Redmine i el recomano moltíssim, ja que esta molt ben integrat i malgrat esta fet amb RubyOnRails del que no en sé res de res, he de reconeixer que és una solució molt ben pensada i ben feta.

Abans d’acabar algunes fotos de la DrupalCamp 2010:

Feb 24

Microfeed – feeds via DBUS

Reading time: 2 – 2 minutes

Avui he descobert microfeed, es tracta d’una implementació d’arquitectura client-servidor que permet accedir a diferents fonts d’informació d’internet publicades via feeds. Potser el que més gràcia m’ha fet és que si volem usar aquesta llibreria per programar, per exemple, una GUI que permeti gestionar aquestes dades l’accés es fa a través de DBUS. És a dir, per un costat microfeed recull les dades de les seves fonts originals (twitter, facebook, identi.ca, etc) i la GUI es comunica amb la llibreria via DBUS. De fet, el que realment m’ha fet gràcia és que això és el que fa Telepathy però encomptes de fer-ho contra feeds ho fa contra jabber/XMPP, MSN, IRC, SIP, etc.

Una forma molt visual d’entendre que fa microfeed és amb aquest esquema:

microfeed_architecture

En principi la única GUI que he trobat que usa aquest backend és Mauku que és una aplicació pensada per Maemo.

Amb el primer cop d’ull a la llibreria no he arribat a trobar com ho fa per rebre els feeds dels llocs com twitter i facebook, imagino que ho farà via polling. Seria interessant saber si també ho pot fer per PubSub. Ja que segons l’esquema només tinc la sensació que el PubSub s’usa via DBUS. Si algún dia em poso a treballar amb la llibreria espero aclararir-ho.

/wp-includes/js/tinymce/themes/advanced/skins/wp_theme/content.css

Feb 12

eines per XMPP

This entry is part 4 of 4 in the series xmpp

Reading time: 2 – 3 minutes

A continuació adjunto una petita descripció d’algunes eines per comunicar-se amb una xarxa XMPP que poden ser molt útils:

Idavoll

Implementació del XEP-0060, o sigui, d’un servei de publish-subscribe (PubSub) esta escrit amb Python i Twisted. Bàsicament el que permet és que sobre un servidor XMPP estàndard hi podem connectar un servei basat en PubSub, o sigui, que nosaltres publiquem una serie d’informació que un seguit de clients consulten perquè hi estan subscrits. És un mètode basat en events (no-polling) molt adient per disfondre certs tipus d’informació.

Switchboard

A vegades programem shell scripts que necessiten enviar el seu resultat a la xarxa XMPP, per exemple, imagineu que volem comunicar la caiguda d’un servei a través de GTalk, doncs aquest toolkit ens simplifica moltíssim aquesta tasca. Esta programat en ruby i a part de poder-se usar des de la CLI també podem integrar-ho com a llibreria dins d’un codi en ruby.

XMPP Poetry CLI tools

El seu nom ja ho diu tot, són una col·lecció d’eines que via CLI ens permeten interactuar amb una xarxa XMPP, algunes de les seves funcions són:

  • disco: recull informació sobre serveis
  • pubsub-config: crea, configura i llança queries contra serveis pub-sub

Aquestes eines estan escrites amb Python, Twisted i Wokkel.

XMPPPHP

Llibreria de PHP5 amb suport de:

  • XMPP 1.0 (pot connectar a: GTalk, LJTalk, jabber.org, etc)
  • Suporta TLS
  • Processa diversos formats XML

Sembla força senzill d’usar, per exemple, programar un bot és tan fàcil com això:

<?php
include("xmpp.php");
$conn = new XMPP('talk.google.com', 5222, 'user', 'password', 'xmpphp', 'gmail.com', $printlog=True, $loglevel=LOGGING_INFO);
$conn->connect();
while(!$conn->disconnected) {
    $payloads = $conn->processUntil(array('message', 'presence', 'end_stream', 'session_start'));
    foreach($payloads as $event) {
        $pl = $event[1];
        switch($event[0]) {
            case 'message':
                print "---------------------------------------------------------------------------------\n";
                print "Message from: {$pl['from']}\n";
                if($pl['subject']) print "Subject: {$pl['subject']}\n";
                print $pl['body'] . "\n";
                print "---------------------------------------------------------------------------------\n";
                $conn->message($pl['from'], $body="Thanks for sending me \"{$pl['body']}\".", $type=$pl['type']);
                if($pl['body'] == 'quit') $conn->disconnect();
                if($pl['body'] == 'break') $conn->send("");
            break;
            case 'presence':
                print "Presence: {$pl['from']} [{$pl['show']}] {$pl['status']}\n";
            break;
            case 'session_start':
                $conn->presence($status="Cheese!");
            break;
        }
    }
}
?>

Jan 14

CouchDB: bases de dades NoSQL

Reading time: 4 – 6 minutes

couchdb logo

couchdb logo

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.

  • Serie d’articles del blog RVZ: una pequeña introducción I, II, III y IV.
  • Llibre: CouchDB: The Definitive Guide, consultable online en format HTML.
  • CouchDB.es, sobre CouchDB y NoSQL.

Enllaços orientats a les consultes:

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.

Oct 24

Python: afegir suport de plug-ins al nostre codi

Reading time: 6 – 9 minutes

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:

class DNI(trac.core.Component):
  dni_checks = trac.core.ExtensionPoint(IDNIInput)
  def __init__(self):
     self._dnis = []
  def add(self, dni):
     assert not dni in self._dnis, "DNI ja existeix"for dni_check in self.dni_checks:
     if dni_check.check(dni) is False:
       print "El dni %s  sembla no ser correcte" % ( dni )
       return
    self._dnis.append(dni)
  def llista(self):
    print self._dnis

Cal fixar-se que la línia:

dni_checks = trac.core.ExtensionPoint(IDNIInput)

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:

class IDNIInput(trac.core.Interface):
  def check(dni):
    """ Es cridada cada cop que s'entra un nou dni, espera que es retorni un valor boleà"""

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.

for dni_check in self.dni_checks:
  if dni_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:

import trac.core
import dni
class ValidDNI(trac.core.Component):
  trac.core.implements(dni.IDNIInput)
  def check(self, dni):
    if type(dni) is not type("str"):
      return False
    if len(dni) != 9:
      return False
    return True

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:

import trac.core                                                           

class IDNIInput(trac.core.Interface):
  def check(nom):
    """ Es cridada cada cop que s'entra un nou dni"""
class DNI(trac.core.Component):
  dni_checks = trac.core.ExtensionPoint(IDNIInput)
  def __init__(self):
    self._dnis = []
  def add(self, dni):
    assert not dni in self._dnis, "DNI ja existeix"
    for dni_check in self.dni_checks:
      if dni_check.check(dni) is False:
        print "El dni %s  sembla no ser correcte" % ( dni )
        return
    self._dnis.append(dni)
  def llista(self):
    print self._dnis

Exemples d’ús:

>>> import trac.core
>>> from dni import DNI
>>>
>>> dni_bd = DNI(comp_mgr)
>>> dni_bd.add("38135009C")
>>> dni_bd.add("38135009")
>>> dni_bd.llista()
['38135009C', '38135009']

# importem el plug-in check_dni
>>> import check_dni
>>> dni_bd.add("11111111")
El dni 11111111  sembla no ser correcte
>>> dni_bd.add("11111111A")
>>> dni_bd.llista()
['38135009C', '38135009', '11111111A']

Definim el codi ‘log_dni’ que serà un altre plug-in:

import trac.core
import dni
class LogDNI(trac.core.Component):
  trac.core.implements(dni.IDNIInput)
  def check(self, dni):
    print "Nou dni entrat %s" % (dni)

Seguim amb l’exemple anterior:

# importem ara el plug-in 'log_dni'
>>> import log_dni
>>> dni_bd.add("22222222B")
Nou dni entrat 22222222B

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.

Sep 26

Fitxers kmz/kml i htc footprints

Reading time: 3 – 5 minutes

footprintAquestes ú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.

schema fitxer kml

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.

Referències:

NOTA: el codi del dokuwiki usa el plugin de google maps.

Aug 06

pkg-config: controlant les llibreries que tenim instal·lades

Reading time: < 1 minute pkg-config és una eina que ens ajuda quan hem de compilar aplicacions i llibreries. Permet descobrir les opcions que s’han d’afegir al compilador.

Alguns exemples ràpids de coses que podem fer:

# descobrir llista de llibreries que tenim instal·lades:
pkg-config --list-all
# cflags per una lliberia concreta
pkg-config nom_llibreria --cflags
# llibreries a incloure al compilador per una llibreria concreta
pkg-config nom_llibreria --libs