There are more than one way to do it

April 19th, 2009

I wrote a method the other day. It was not a particularly difficult method and before writing it, it didn’t seem like a challenge. When I finished it, it looked quite good and simple but there was something that keep my eyes focused on a point instead of enjoying the method as a whole. Something similar as when you buy a shiny beatiful monitor, you plug it in and you discover it has a dead pixel. No matter how bright and fast your monitor is, that rotten pixel is ruining your experience.

Let me show you my broken pixel.

But before I’ll give you a small explanation of what the method does. Its class has a list of collectors, where each collector is a callable that return a generator of photos . The method collect the photos of all collectors until a maximum is reached, then it return the photos using an auxiliar method that does its own job postprocesing the list of photos.

Example carrusel

Example carrusel

Here is my initial version:


    def collect_photos1(self, destination):
        n_photos_collected = 0
        for collector in self.collectors:
            for photo_info in collector(destination):
                self.add_photo(photo_info)
                n_photos_collected += 1
                if n_photos_collected > self.max:
                    return self.get_photos()

        return self.get_photos()

As you can see, no rocket science so far. It’s just a nested for loop that iterates over all the photos until we get as many as we want. The rotten pixel is the return self.get_photos() line. It is bad because it’s duplicated, one in the finished condition and one at the end of the method. There are two problems with that duplication:

  • The first one is a practical problem. What if, in the future, the get_photos aux method need to receive a parameter. We need to update the call to that method, but as we have two calls there is a chance that we forget to update one of them. If we had only one the error probability of an update would be lower.
  • The second problem is a theorical one. We are using a nested for loop to iterate over a list of lists of photos but we do not know in advance how long those lists are and how many loop body we are going to iterate.

My second version is basically the same as the first but instead of duplicating the return self.get_photos line we are duplicating the break condition. Now, if we add a parameter to the get_photos method we will have to update just one call. But if we want to add another condition to stop collecting photos we will have to update two if statements. In other words, this version is pretty much the same.


    def collect_photos2(self, destination):
        n_photos_collected = 0
        for collector in self.collectors:
            for photo_info in collector(destination):
                self.add_photo(photo_info)
                n_photos_collected += 1
                if n_photos_collected > self.max:
                    break
            if n_photos_collected > self.max:
                break

        return self.get_photos()

Then I tried to convert the for loops into while loops since basic computer science tell us that a while loop is the choice to make when the number of iterations is unknown. So this version does not have the previous two problems and it’s easier to maintain. Nevertheless, it introduces another problem: it’s harder to read and to understand.


    def collect_photos3(self, destination):
        n_photos_collected = 0
        need_more_photos = True
        collectors_iterator = iter(self.collectors)
        while need_more_photos and collectors_iterator.has_next():
            collector = collectors_iterator.next()

            photos_iterator = collector(destination)
            while need_more_photos and photos_iterator.has_next():
                photo_info = photos_iterator.next()
                self.add_photo(photo_info)
                n_photos_collected += 1

                if n_photos_collected > self.max:
                    need_more_photos = False

        return self.get_photos()

Version 4 is a crazy one. It tries to simulate to goto statement in Python. Everybody will tell you the goto statement is evil and well, most of the times, it is. But sometimes it has no good replacement like this one where we want to stop two nested loops with a statement. Too bad Python does not have a goto statement :(


    def collect_photos4(self, destination):
        n_photos_collected = 0
        try:
            for collector in self.collectors:
                for photo_info in collector(destination):
                    self.add_photo(photo_info)
                    n_photos_collected += 1
                    if n_photos_collected > self.max:
                        raise TypeError('goto')

        except TypeError:
            pass

        return self.get_photos()

Now, what if we separate the two problems this method is trying to solve: iterating over the photos and adding to our result set. Doing so we can write a simple generator that gives us a photo at a time and then a while loop that check there are more photos in this generator and we actually want them. I like this version more than any of the previous one but still, the while loop is not very readable.


    def collect_photos5(self, destination):
        def photos_fetcher():
            for collector in self.collectors:
                for photo in collector(destination):
                    yield photo

        n_photos_collected = 0
        photos_iterator = photos_fetcher()
        while n_photos_collected < self.max and photos_iterator.has_next():
            photo_info = photos_iterator.next()
            self.add_photo(photo_info)
            n_photos_collected += 1

        return self.get_photos()

And then, the last version. I decided to add the stop condition logic into the generator and as it is a nested function I can put a return statement to exit from the two nested loops. Then the main loop can be a for loop without the boilerplate management code that the while loop needed.


    def collect_photos6(self, destination):
        def photos_fetcher(max_photos):
            n_photos_collected = 0
            for collector in self.collectors:
                for photo in collector(destination):
                    if n_photos_collected > max_photos:
                        return
                    yield photo
                    n_photos_collected += 1

        for photo_info in photos_fetcher(self.max):
            self.add_photo(photo_info)

        return self.get_photos()

What version do you like most?

Mapping inheritance to a RDBMS with storm. Autoproxy version

January 27th, 2009

We saw in the Proxy version that some types of queries were not possible using the lazr.delegates package. We solved that problem using Storm’s Proxy objects but we lost easyness in the process.

This time we will try to combine both aproaches to get the best of both worlds.

The interface definitions do not change:

    >>> from zope.interface import Interface, Attribute
    >>> class IPerson(Interface):
    ...     name = Attribute("Name")
    ...
    >>> class ISecretAgent(IPerson):
    ...     passcode = Attribute("Passcode")
    ...
    >>> class ITeacher(IPerson):
    ...     school = Attribute("School")

Neither the Person class:

    >>> from zope.interface import implements
    >>> from zope.interface.verify import verifyClass
    >>> from lazr.delegates import delegates
    >>> from storm.locals import Store, Storm, Unicode, Int, Proxy, Reference
    >>> class Person(Storm):
    ...     implements(IPerson)
    ...
    ...     __storm_table__ = "person"
    ...
    ...     id = Int(allow_none=False, primary=True)
    ...     name = Unicode()
    ...     person_type = Int(allow_none=False)
    ...     _person = None
    ...
    ...     def __init__(self, store, name, person_class, **kwargs):
    ...         self.name = name
    ...         self.person_type = person_class.person_type
    ...         store.add(self)
    ...         self._person = person_class(self, **kwargs)
    ...
    ...     @property
    ...     def person(self):
    ...         if self._person is None:
    ...             assert self.id is not None
    ...             person_class = BasePerson.get_class(self.person_type)
    ...             self._person = Store.of(self).get(person_class, self.id)
    ...         return self._person
    ...
    >>> verifyClass(IPerson, Person)
    True

Now, the real magic is in the metaclass. We use it not only to register our subclasses (so the Person.person property can find them) but to automatically store the attributes we needed to set manually in our previous version: the person_id and person attributes and a proxy object for each Person attribute. It’s like we are reimplementing inheritance in Python but not really :-)

    >>> from storm.properties import PropertyPublisherMeta
    >>> class PersonType(PropertyPublisherMeta):
    ...     def __init__(self, name, bases, dict):
    ...         if hasattr(self, '__storm_table__'):
    ...             # this need to be done before calling the superclass
    ...             # otherwise Storm will cry about not having a primary key
    ...             self.person_id = Int(allow_none=False, primary=True)
    ...
    ...         super(PersonType, self).__init__(name, bases, dict)
    ...
    ...         if not hasattr(self, '_person_types_registry'):
    ...             self._person_types_registry = {}
    ...         elif hasattr(self, '__storm_table__'):
    ...             key = len(self._person_types_registry)
    ...             self._person_types_registry[key] = self
    ...             self.person_type = key
    ...
    ...             self.person = Reference(self.person_id, Person.id)
    ...             self._add_proxy_properties()
    ...
    ...     def _add_proxy_properties(self):
    ...         for name in IPerson:
    ...             if not hasattr(self, name):
    ...                 remote_attr = getattr(Person, name)
    ...                 setattr(self, name, Proxy(self.person, remote_attr))
    ...
    ...     def get_class(self, person_type):
    ...         return self._person_types_registry[person_type]

Not our BasePerson is really simple

    >>> class BasePerson(Storm):
    ...     __metaclass__ = PersonType
    ...
    ...     def __init__(self, person):
    ...         self.person = person

And so are the subclasses. No repetition, so it is less prone to mistakes :-)

    >>> class SecretAgent(BasePerson):
    ...     implements(ISecretAgent)
    ...
    ...     __storm_table__ = "secret_agent"
    ...     passcode = Unicode()
    ...
    ...     def __init__(self, person, passcode=None):
    ...         super(SecretAgent, self).__init__(person)
    ...         self.passcode = passcode
    ...
    >>> verifyClass(ISecretAgent, SecretAgent)
    True
    >>> class Teacher(BasePerson):
    ...     implements(ITeacher)
    ...
    ...     __storm_table__ = "teacher"
    ...     school = Unicode()
    ...
    ...     def __init__(self, person, school=None):
    ...         super(Teacher, self).__init__(person)
    ...         self.school = school
    ...
    >>> verifyClass(ITeacher, Teacher)
    True

Let’s make sure our queries work as expected:

    >>> from storm.locals import create_database
    >>> database = create_database("sqlite:")
    >>> store = Store(database)
    >>> result = store.execute("""
    ...     CREATE TABLE person (
    ...         id INTEGER PRIMARY KEY,
    ...         person_type INTEGER NOT NULL,
    ...         name TEXT NOT NULL)
    ... """)
    >>> result = store.execute("""
    ...     CREATE TABLE secret_agent (
    ...         person_id INTEGER PRIMARY KEY,
    ...         passcode TEXT)
    ... """)
    >>> result = store.execute("""
    ...     CREATE TABLE teacher (
    ...         person_id INTEGER PRIMARY KEY,
    ...         school TEXT)
    ... """)
    ...
    >>> secret_agent = Person(store, u"James Bond",
    ...                        SecretAgent, passcode=u"007")
    >>> ISecretAgent.providedBy(secret_agent.person)
    True
    >>> teacher = Person(store, u"Albus Dumbledore",
    ...                  Teacher, school=u"Hogwarts")
    >>> ITeacher.providedBy(teacher.person)
    True
    >>> store.commit()
    >>> del secret_agent
    >>> del teacher
    >>> store.rollback()
    >>> secret_agent = store.find(SecretAgent).one()
    >>> secret_agent.name, secret_agent.passcode
    (u'James Bond', u'007')
    >>> teacher = store.find(Teacher).one()
    >>> teacher.name, teacher.school
    (u'Albus Dumbledore', u'Hogwarts')
    >>> secret_agent = store.find(SecretAgent, SecretAgent.name==u'James Bond').one()
    >>> secret_agent.passcode
    u'007'
    >>> teacher = store.find(Teacher, Teacher.school==u'Hogwarts').one()
    >>> teacher.name
    u'Albus Dumbledore'

So we made it by using a metaclass that automatically generate a bunch of attributes.

Mapping inheritance to a RDBMS with storm. Proxy version

January 23rd, 2009

One problem that we had in the first version of our inheritance by composition pattern was that we could not make storm queries using the subclasses. In other words, the following would return None::

    secret_agent = store.find(SecretAgent, SecretAgent.name==u'James Bond').one()

The reason is that the expresion SecretAgent.name would resolve to a Passthrough lazr.delegates object that Storm does not know how to handle.

This time we will try to fix this problem using a manually generated version of our classes using storm’s Proxy objects.

The interface definitions do not change:

    >>> from zope.interface import Interface, Attribute
    >>> class IPerson(Interface):
    ...     name = Attribute("Name")
    ...
    >>> class ISecretAgent(IPerson):
    ...     passcode = Attribute("Passcode")
    ...
    >>> class ITeacher(IPerson):
    ...     school = Attribute("School")

Neither the Person class:

    >>> from zope.interface import implements
    >>> from zope.interface.verify import verifyClass
    >>> from lazr.delegates import delegates
    >>> from storm.locals import Store, Storm, Unicode, Int, Proxy, Reference
    >>> class Person(Storm):
    ...     implements(IPerson)
    ...
    ...     __storm_table__ = "person"
    ...
    ...     id = Int(allow_none=False, primary=True)
    ...     name = Unicode()
    ...     person_type = Int(allow_none=False)
    ...     _person = None
    ...
    ...     def __init__(self, store, name, person_class, **kwargs):
    ...         self.name = name
    ...         self.person_type = person_class.person_type
    ...         store.add(self)
    ...         self._person = person_class(self, **kwargs)
    ...
    ...     @property
    ...     def person(self):
    ...         if self._person is None:
    ...             assert self.id is not None
    ...             person_class = BasePerson.get_class(self.person_type)
    ...             self._person = Store.of(self).get(person_class, self.id)
    ...         return self._person
    >>> verifyClass(IPerson, Person)
    True

Neither our custom metaclass:

    >>> from storm.properties import PropertyPublisherMeta
    >>> class PersonType(PropertyPublisherMeta):
    ...     def __init__(self, name, bases, dict):
    ...         super(PersonType, self).__init__(name, bases, dict)
    ...         if not hasattr(self, '_person_types_registry'):
    ...             self._person_types_registry = {}
    ...         elif hasattr(self, '__storm_table__'):
    ...             key = len(self._person_types_registry)
    ...             self._person_types_registry[key] = self
    ...             self.person_type = key
    ...
    ...     def get_class(self, person_type):
    ...         return self._person_types_registry[person_type]

Here start the changes. Our BasePerson class does not have the delegates call and does not define the person_id attribute and person reference.

    >>> class BasePerson(Storm):
    ...     __metaclass__ = PersonType
    ...
    ...     def __init__(self, person):
    ...         self.person = person

Instead we define the person_id and person reference in each subclass and also we define each attribute of the Person base class as a proxy to the related attribute of the person reference.

    >>> class SecretAgent(BasePerson):
    ...     implements(ISecretAgent)
    ...
    ...     __storm_table__ = "secret_agent"
    ...     passcode = Unicode()
    ...     person_id = Int(allow_none=False, primary=True)
    ...     person = Reference(person_id, Person.id)
    ...     name = Proxy(person, Person.name)
    ...
    ...     def __init__(self, person, passcode=None):
    ...         super(SecretAgent, self).__init__(person)
    ...         self.passcode = passcode
    >>> verifyClass(ISecretAgent, SecretAgent)
    True

We do it again for the Teacher class:

    >>> class Teacher(BasePerson):
    ...     implements(ITeacher)
    ...
    ...     __storm_table__ = "teacher"
    ...     school = Unicode()
    ...     person_id = Int(allow_none=False, primary=True)
    ...     person = Reference(person_id, Person.id)
    ...     name = Proxy(person, Person.name)
    ...
    ...     def __init__(self, person, school=None):
    ...         super(Teacher, self).__init__(person)
    ...         self.school = school
    >>> verifyClass(ITeacher, Teacher)
    True

Time to test the database storage:

    >>> from storm.locals import create_database
    >>> database = create_database("sqlite:")
    >>> store = Store(database)
    >>> result = store.execute("""
    ...     CREATE TABLE person (
    ...         id INTEGER PRIMARY KEY,
    ...         person_type INTEGER NOT NULL,
    ...         name TEXT NOT NULL)
    ... """)
    >>> result = store.execute("""
    ...     CREATE TABLE secret_agent (
    ...         person_id INTEGER PRIMARY KEY,
    ...         passcode TEXT)
    ... """)
    >>> result = store.execute("""
    ...     CREATE TABLE teacher (
    ...         person_id INTEGER PRIMARY KEY,
    ...         school TEXT)
    ... """)
    >>> secret_agent = Person(store, u"James Bond",
    ...                        SecretAgent, passcode=u"007")
    >>> ISecretAgent.providedBy(secret_agent.person)
    True
    >>> teacher = Person(store, u"Albus Dumbledore",
    ...                  Teacher, school=u"Hogwarts")
    >>> ITeacher.providedBy(teacher.person)
    True
    >>> store.commit()

And what’s more important, all this changes should make possible to do the query with the subclass:

    >>> del secret_agent
    >>> del teacher
    >>> store.rollback()
    >>> secret_agent = store.find(SecretAgent).one()
    >>> secret_agent.name, secret_agent.passcode
    (u'James Bond', u'007')
    >>> teacher = store.find(Teacher).one()
    >>> teacher.name, teacher.school
    (u'Albus Dumbledore', u'Hogwarts')
    >>> secret_agent = store.find(SecretAgent, SecretAgent.name==u'James Bond').one()
    >>> secret_agent.passcode
    u'007'

We have improved the power of the pattern but now it is much more verbose to write each subclass since we need to repeat a lot of things. Note that we can not move the definition of the person_id and person attributes to the BasePerson aux class because Storm will tell us that it lacks the __storm_table__ attribute. In other words: storm does not allow attributes in abstract classes.

Mapping inheritance to a RDBMS with storm and lazr.delegates

January 18th, 2009

When using a ORM one of the most common problems is how to map your beautiful
application class inheritance to the database. The specific scenario I’m going
to describe is when you have an abstract base class with some fields and you
want to store those fields in a database table. Then all of its subclasses will
have their own table and to get the data of an instance you will need to make
a join between the base table and the subclass table.

One pattern to accomplish this is the infoheritance pattern described in the
Storm documentation. I’ll show you here a slightly modified version of this
pattern that uses the package lazr.delegates to make the user code easier by
hiding the fact that we are using composition to model inheritance.

So let’s start with some interface definition showing our model hierarchy:

    >>> from zope.interface import Interface, Attribute
    >>> class IPerson(Interface):
    ...     name = Attribute("Name")
    ...
    >>> class ISecretAgent(IPerson):
    ...     passcode = Attribute("Passcode")
    ...
    >>> class ITeacher(IPerson):
    ...     school = Attribute("School")

No rocket science so far. Let’s write now the implementation of the
IPerson interface. This will be our abstract base class. Pay special
attention to the person property which dynamically retrieve the subclass
instance by using composition.

    >>> from zope.interface import implements
    >>> from zope.interface.verify import verifyClass
    >>> from lazr.delegates import delegates
    >>> from storm.locals import Store, Storm, Unicode, Int, Reference
    >>> class Person(Storm):
    ...     implements(IPerson)
    ...
    ...     __storm_table__ = "person"
    ...
    ...     id = Int(allow_none=False, primary=True)
    ...     name = Unicode()
    ...     person_type = Int(allow_none=False)
    ...     _person = None
    ...
    ...     def __init__(self, store, name, person_class, **kwargs):
    ...         self.name = name
    ...         self.person_type = person_class.person_type
    ...         store.add(self)
    ...         self._person = person_class(self, **kwargs)
    ...
    ...     @property
    ...     def person(self):
    ...         if self._person is None:
    ...             assert self.id is not None
    ...             person_class = BasePerson.get_class(self.person_type)
    ...             self._person = Store.of(self).get(person_class, self.id)
    ...         return self._person
    >>> verifyClass(IPerson, Person)
    True

We will also use a custom metaclass (based on Storm metaclass) so it will
automatically register our subclasses. This is necessary for the dynamic
person property of the Person class where we map integer (stored in the
database) to classes (stored in the source code).

    >>> from storm.properties import PropertyPublisherMeta
    >>> class PersonType(PropertyPublisherMeta):
    ...     def __init__(self, name, bases, dict):
    ...         super(PersonType, self).__init__(name, bases, dict)
    ...         if not hasattr(self, '_person_types_registry'):
    ...             self._person_types_registry = {}
    ...         elif hasattr(self, '__storm_table__'):
    ...             key = len(self._person_types_registry)
    ...             self._person_types_registry[key] = self
    ...             self.person_type = key
    ...
    ...     def get_class(self, person_type):
    ...         return self._person_types_registry[person_type]

Now we define a convenience base class for our subclasses. Remember that
the subclasses don’t really inherit from the Person class because we
are using composition. This is where the lazr.delegates.delegates function
comes to rescue. By saying that we delegate the implementation of the
IPerson interface to the ‘person’ attribute, the instances of these subclasses
will look like they really are subclasses of Person, not just from BasePerson.

    >>> class BasePerson(Storm):
    ...     __metaclass__ = PersonType
    ...     delegates(IPerson, "person")
    ...
    ...     person_id = Int(allow_none=False, primary=True)
    ...     person = Reference(person_id, "Person.id")
    ...
    ...     def __init__(self, person):
    ...         self.person = person
    ...
    >>> class SecretAgent(BasePerson):
    ...     implements(ISecretAgent)
    ...
    ...     __storm_table__ = "secret_agent"
    ...     passcode = Unicode()
    ...
    ...     def __init__(self, person, passcode=None):
    ...         super(SecretAgent, self).__init__(person)
    ...         self.passcode = passcode

Here is the magic: we have an interface hierarchy and a different
hierarchy for the classes implementing them. But it’s all transparent
and our classes implement the full hierarchy:

    >>> verifyClass(ISecretAgent, SecretAgent)
    True
    >>> class Teacher(BasePerson):
    ...     implements(ITeacher)
    ...
    ...     __storm_table__ = "teacher"
    ...     school = Unicode()
    ...
    ...     def __init__(self, person, school=None):
    ...         super(Teacher, self).__init__(person)
    ...         self.school = school
    ...
    >>> verifyClass(ITeacher, Teacher)
    True

Now let’s try storing the objects in the database. We will use a
sqlite in memory database for this example.

    >>> from storm.locals import create_database
    >>> database = create_database("sqlite:")
    >>> store = Store(database)
    >>> result = store.execute("""
    ...     CREATE TABLE person (
    ...         id INTEGER PRIMARY KEY,
    ...         person_type INTEGER NOT NULL,
    ...         name TEXT NOT NULL)
    ... """)
    >>> result = store.execute("""
    ...     CREATE TABLE secret_agent (
    ...         person_id INTEGER PRIMARY KEY,
    ...         passcode TEXT)
    ... """)
    >>> result = store.execute("""
    ...     CREATE TABLE teacher (
    ...         person_id INTEGER PRIMARY KEY,
    ...         school TEXT)
    ... """)
    >>> secret_agent = Person(store, u"James Bond",
    ...                        SecretAgent, passcode=u"007")
    >>> ISecretAgent.providedBy(secret_agent.person)
    True
    >>> teacher = Person(store, u"Albus Dumbledore",
    ...                  Teacher, school=u"Hogwarts")
    >>> ITeacher.providedBy(teacher.person)
    True
    >>> store.commit()

The objects are now saved in the database. Let’s destroy them and
retrieve them back using some queries:

    >>> del secret_agent
    >>> del teacher
    >>> store.rollback()
    >>> secret_agent = store.find(SecretAgent).one()
    >>> secret_agent.name, secret_agent.passcode
    (u'James Bond', u'007')
    >>> teacher = store.find(Teacher).one()
    >>> teacher.name, teacher.school
    (u'Albus Dumbledore', u'Hogwarts')

The great thing is that we can write teacher.name without having to
write teacher.person.name (which also works by the way) effectively
hiding the implementation detail of composition.

Just one final note: Bear in mind that you should not have very deep
hierarchies or you may get a lot of JOINs and a slow application.

You can download a couple of files to test this on your own computer. You just need storm 0.14 and lazr.delegates 1.0, both of which can be installed with easy_install:

Conexión a internet desde un móvil Nokia 6234 con Simyo

December 14th, 2008

Tras un par de intentos fallidos de conectarme a Internet desde mi móvil con mi nuevo proveedor he conseguido que funcione.

Nokia 6234

Nokia 6234

A continuación escribo las opciones que he tenido que configurar en el móvil para conseguirlo. Espero que la nomenclatura se entienda.

Configuración: Configuración: Ajustes config. personal: Opciones: Añadir nuevo: Internet

  Nombre de cuenta: Internet Simyo
  Página de inicio: http://www.google.com
  Nombre de usuario:
  Contraseña:
  Usar pto. acceso preferido: No
  Conf. de punto de acceso:

    Proxy: Activado
    Dirección de proxy: 217.18.32.181
    Puerto de proxy: 8080
    Portador de datos: Paquetes de datos
    Configuración portador:

      Pto. acceso paquts. datos: gprs-service.com
      Tipo de red: IPv4
      Tipo de autentificación: Normal
      Nombre de usuario:
      Contraseña: 

Internet: Configuración: Ajustes de configuración:

  Configuración: Configuración personal
  Cuenta: Internet Simyo
  Mostrar ventana terminal: No

Para el que esté pensando que eso de internet desde un móvil normalito no tiene mucho sentido pues sí y no. Está claro que cualquier parecido entre navegar con un ordenador y un móvil como el mío es pura coincidencia, pero eso no quiere decir que la posibilidad de ver tu correo en Gmail desde tu móvil no sea útil o también, la posibilidad de sincronizar tus contactos entre el móvil, el ordenador, tu cuenta google, etc. usando servicios como scheduleworld.com

Las tarifas de mi proveedor las podeis consultar en su web y la verdad es que me parecen bastante razonables. Por ahora estoy contento con Simyo no sólo por que me resulta más barato que mi anterior proveedor, si no porque es infinitamente más transparente y claro que los demás y al menos tienes la sensación de que estás pagando por lo que usas, no por lo que ellos quieren.

El siguiente paso ha sido conectar mi Nokia N800 al teléfono vía Bluetooth y usar la conexión a internet del teléfono para navegar desde el otro cacharro. Esto ya se va pareciendo mucho más a navegar a la vieja usanza gracias a la pantalla de 800 pixeles de ancho que tiene el N800.

Nokia N800

Nokia N800

Si mi portátil tuviera Bluetooth, también podría conectarme a internet desde cualquier sitio, pero fui tan listo al comprarlo que desactive esa opción pensando que nunca la usaría. Ahora puedo pedir esa ampliación e instalarla yo mismo o comprar un pequeño dongle usb y hacer lo mismo.

Encoding videos for the Nokia N800

November 23rd, 2008

Quick command reminder about how to encode videos for watching them in the Nokia N800:

mencoder Fringe-S01E06.avi -o Fringe-S01E06-n800.avi -oac mp3lame -lavcopts acodec=libmp3lame:abitrate=96 -ovc lavc -lavcopts vcodec=mpeg4:autoaspect:vbitrate=600:vpass=1:turbo -vf scale=400:240 -ffourcc DIVX -idx

Update: add these options to embed subtitles:

-sub Fringe-S01E06.srt -subcp latin5 -subfont-text-scale 4

You will need a subfont.ttf font file in ~/.mplayer/

Viajes y cambios

September 13th, 2008

Este mes de Agosto Ana y yo fuimos a Londres. Ana nunca había estado antes y aunque yo había estado en algunas ocasiones, Londres es de esas ciudades en las que es totalmente imposible aburrirse o decir “es que ya he visto todo lo que había que ver”. Así que nos metimos en EasyJet un Lunes por la mañana y aparecimos en Gatwick poco rato después. Vaya tela el Gatwick Express: sesenta y tantas libras por dos billetes ida y vuelta.

Loren delante de las Casas del Parlamento

Nota para posibles visitantes a Londres: im-pres-cin-di-ble la Oyster card para viajar por el metro. Sale muchísimo más barata que ir a pagando a pelo y luego está el efecto molón de ir pasando la cartera por los lectores de tarjetas sin necesidad de sacar la tarjeta. Al final le cogimos el truco y parecíamos londinenses, bueno eso de cuello para abajo, de cuello para arriba era muy difícil ocultar que en realidad somos de londonelzaidin ya que la cara de empanaos y turistas la llevamos a todas partes. Igual que Dos Flores.

Anita en el momento británico

De las cosas que vimos, que no fueron pocas (a Ana incluso se le rompieron los zapatos de tanto andar) nos quedamos sin duda con el museo de Historia Natural. Impresionante tanto el continente como el contenido. No tan popular como la Tate o el Museo Británico pero para flipaos de los bichos como nosotros igual o más interesante.

Tripu y Loren

Mención especial de nuestro viaje fue el encuentro con nuestro más querido Tripulante, que hizo de anfitrión excepcional y nos enseño todo el Soho (el barrio) mostrándonos tanto los sitios más típicos como algunos restaurantes con las tres bes. Un día toco italiano y otro día griego. Muy mediterráneo, sí, pero mejor no preguntéis por la comida inglesa: es casi inexistente si la buscas en restaurantes y por algo será.

Se acaba la diversión

En fín, un viaje muy típico pero también muy recomendable. Si aún no has estado en Londres, no tienes excusa ahora que está a tiro de piedra con compañias low cost. Más fotos en el Flickr de Ana.

También han sido mis vacaciones más largas desde que empecé en Sicem haya por el 2003. Quince días de vacaciones y quince en paro. El lunes empiezo en Yaco y la verdad, tengo bastantes ganas de empezar y cambiar un poco de aires.

Uploading files to wordpress and SELinux problems

July 24th, 2008

If you use Fedora and Wordpress and you get this error while trying to upload an image to your post:

The uploaded file could not be moved to /usr/share/wordpress/wp-content

All you need to do is labeling your uploads directory with the httpd_sys_content_t type:

[root@nyarlathotep wp-content]# pwd
/usr/share/wordpress/wp-content

[root@nyarlathotep wp-content]# chcon -t httpd_sys_content_t uploads/ -R

I hope this is useful for somebody else.

Google Maps a pie

July 23rd, 2008

Desde hace poco Google Maps permite calcular recorridos a pie. Siempre lo ha hecho en coche pero lo nuevo es que ahora calcula los recorridos a pie si así se lo decimos. De esta forma no tiene en cuenta el sentido de circulación de las calles y simplemente calcula el camino más corto entre dos puntos. ¿O no?

Además, también te calcula el tiempo estimado a pie, algo bastante útil para ciudades que no son la tuya y en la que no te haces una idea de la escala del mapa.

He hecho la prueba en el recorrido que hago desde mi casa a la Alhambra todos los martes y los jueves para ir a trabajar y me he quedado un poco sorprendido de los resultados obtenidos:

Este es el camino que me calcula Google:

Ruta de Google

Y este el que hago yo:

Ruta que hago yo

Como podeis ver en la ruta de Google se tardan 42 minutos, mientras que en la mía, se tardan 41 minutos. Algunos detalles curiosos:

  • La ruta es de desde A (mi casa) a B (el trabajo). Si la calculamos desde B a A, el tiempo es de 37 minutos ya que el camino es cuesta abajo en este último caso.
  • Realmente yo tardo unos 30 minutos cuesta arriba y unos 25 cuesta abajo, pero como me pica la curiosidad, mañana me pienso cronometrar.
  • El único motivo que se me ocurre por el que Google no me haya dado mi ruta (se tarda menos) es porque mi ruta tiene más recorrido con una cuesta más pronunciada. Si esto fuera así es para fliparlo. El difunto Dijkstra estaría orgulloso.

Actualización: Hoy me he cronometrado en el trayecto A->B y he tardado 28 minutos. Parece que ando más rápido de lo que estima Google Maps.

Y ya van 5

July 4th, 2008

Escribo este post desde la última charla de la quinta Guadec Hispana. Quién lo diría desde aquel primer encuentro en Almendralejo, pero lo cierto es que hemos pasado ya por La Coruña, Vilanova, Granada y Fuenlabrada. Afortunadamente yo he tenido la suerte de asistir a todas ellas y ya es casi una cita obligada para mí. Más aún cuando sólo he podido ir a la Guadec internacional una vez.

Han sido dos días muy agradables viendo a viejos conocidos como Germán, los Carlos, Álvaro, Palomo, Daniel, Claudio, Roberto, Domingo y muchos otros que posiblemente olvide.

Al igual que GCubo, el grupo de personas de GNOME-Hispano es ya un grupo de amigos primero y de desarrolladores/usuarios de GNOME después. Tristemente, y al igual que GCubo otra vez, cada vez se ven menos caras nuevas. Aquí en la Guadec se ha hablado de esto y se han intentado buscar causas y soluciones sin llegar a un acuerdo concreto.

Al final, para mí no deja de ser un par de días muy agradables en un ambiente distendido y divertido en los que siempre aprendes cosas nuevas pero sobre todo mantienes el contacto con un puñado de personas que vienen todos los años porque les apasiona esto del software libre. Como a mí.

Algunas caras de esta Guadec-es