martes, 26 de mayo de 2009

Adios Blogger, adios...

Bueno, este es el último post de mi blog en esta dirección. A partir de ahora, me mudo a un dominio propio, con un sistema bastante más robusto, lindo y con muchas más características: Wordpress.

El nuevo sitio es: http://blog.marcelofernandez.info

Este post cuenta un poquito más: http://blog.marcelofernandez.info/2009/05/hola-mundo/

Básicamente dejo Blogger porque tiene muy pocas features, y me cansé de esperar que implementen cosas como colorización de código fuente, editor mejorado (donde escribo tiene unas 15 líneas de alto más o menos), mejores diseños, posibilidad de plugins, etc.

No hace falta actualizar el feed RSS, al utilizar FeedBurner el switch lo hago yo. :-)

Bueno, nos vemos en el nuevo site!

Saludos
Marcelo

domingo, 24 de mayo de 2009

PostgreSQL Conference 2009

Gracias a este post del sitio de PostgreSQL en español, me entero que terminó la conferencia anual de la comunidad de PostgreSQL, llamada PGCon 2009. Obviamente, la nueva versión que está al caer (8.4) acaparó todo un track completo, así que acá está la lista de charlas para ver de qué se trató.

Particularmente, a mí me interesó mirar los slides de:

  • Introducing Windowing functions: Es una nueva e importante característica de PostgreSQL 8.4, el soporte de consultas con varios niveles de aggregates, no sólo el primero con la cláusula GROUP BY, sino que también se pueden subdividir estos grupos (llamados Windows) y ejecutar funciones dentro de cada subrango. Muy interesante.
  • No More Waiting: La clásica y necesaria charla sobre las nuevas cosas de PostgreSQL 8.4.
  • SkyTools3: Replication (Londiste3): Si hay algo que se le puede "recriminar" a PostgreSQL es la falta de replicación built-in (está prometido para la 8.5, tough). Sin embargo, hay muchas herramientas extra para hacerlo, y Londiste es una de ellas (desarrollada por la gente de Skype, que usa PostgreSQL para todo).
En fin, PostgreSQL es una base de datos muy robusta y confiable, la vengo utilizando profesionalmente y nunca me dejó de a pie. Tiene una excelente documentación, una licencia extremadamente libre (BSD), casi todas las características de las grandes, y un muy buen soporte en la lista de PostgreSQL en español.

Saludos
Marcelo

sábado, 2 de mayo de 2009

Renderizando PDFs en Python con Poppler

Buenas... hoy voy a mostrar una forma de renderizar archivos PDF dentro de nuestras aplicaciones y desde Python, para casi cualquier plataforma con la estemos trabajando.

Introducción
Si bien cuando se arma una aplicación de escritorio se suele "llamar" a un software externo (Acrobat Reader, Fox-It, Evince, etc.) para que muestre el contenido de un archivo PDF, generalmente queda "feo"; nuestro programa pierde la interacción y el control de lo que el usuario hace con el mismo, implica superponer un programa arriba del otro, etc. Esto suele producir una experiencia dificultosa para el usuario de nuestro querido programa, y como corresponde, los programadores nos ponemos tristes. :-(

Como una alternativa tenemos, en plataformas Windows, y estando el Acrobat Reader instalado previamente, la posibilidad de embeber en nuestro programa el mismo como un control ActiveX (hay otras alternativas) pero en el resto de las plataformas este problema no tenía solución (que yo conociera, al menos), ni siquiera algo más "liviano". El resultado de embeber todo el Acrobat Reader es más o menos lo que hacen los navegadores web cuando tienen el plugin de Adobe instalado y hacemos click en un link a un archivo PDF de la web:

(Después de 1 minuto, y si el usuario no cerró la ventana, aparece esto)

Hace unos días, en la lista de usuarios de las bibliotecas wxPython preguntaron si se podía renderizar un PDF dentro de una ventana del mismo programa, pero sobre Linux, y buscando la solución me encontré con un binding Python para Poppler.

Solución: Poppler-Python sobre Cairo
Veamos, Poppler es una biblioteca de código abierto desarrollada en C con el objetivo de renderizar (es decir, interpretar y dibujar) archivos PDF, siendo la evolución del viejo Xpdf. Es una pieza de software imprescindible en el escritorio de cualquier Sistema Operativo Libre, ya que es un trabajo bárbaro el que hace, y además es la piedra fundamental de programas como Evince y Okular (más allá de que el PDF es un formato de archivo universal). Y lo mejor es que dibuja sobre cualquier contexto de dibujo de Cairo, así que donde haya Cairo y compilador de C, puede estar Poppler*.

Hasta acá, bien, Poppler se puede utilizar desde C (como lo hace Evince, el visor de PDFs de Gnome). Pero 'ete aquí que me encontré con estos bindings de Poppler para Python, y si bien el ejemplo que éstos incluyen utiliza PyGTK, en realidad, sólo necesita de un Canvas Cairo (GTK dibuja mucho sobre Cairo y provee mecanismos para que el desarrollador lo utilice también); es el mismo Cairo que incluye wxPython a partir de la versión 2.8.9.0 (aunque se puede utilizar con ctypes desde versiones anteriores a la 2.8.9).

Un poco de Código
En fin, voy a tratar de explicarlo mejor, esta es la manera de renderizar un PDF dentro de una aplicación PyGTK. Voy a pegar acá abajo lo relevante:
def __init__(self):
[...]
self.document = poppler.document_new_from_file (uri, None)
self.n_pages = self.document.get_n_pages()
self.current_page = self.document.get_page(0)
self.scale = 1
self.width, self.height = self.current_page.get_size()
[...]
self.dwg = gtk.DrawingArea()
self.dwg.set_size_request(int(self.width), int(self.height))
self.dwg.connect("expose-event", self.on_expose)

[...]

def on_expose(self, widget, event):
cr = widget.window.cairo_create()
cr.set_source_rgb(1, 1, 1)

if self.scale != 1:
cr.scale(self.scale, self.scale)

cr.rectangle(0, 0, self.width, self.height)
cr.fill()
self.current_page.render(cr)
Como se puede ver, Poppler-Python se encarga de cargar el archivo, devolver la cantidad de páginas, etc., mientras que con GTK creamos el contexto de dibujo Cairo, y todo lo que hacemos es decirle a Poppler "dibujá acá, en este contexto Cairo".

Entonces me puse a jugar con wxPython para hacer lo mismo, !y funciona!

Acá está el ejemplo:
#!/usr/bin/env python
import wx
import wx.lib.wxcairo
import sys
import poppler

class MyFrame(wx.Frame):

def __init__(self):
wx.Frame.__init__(self, None, -1, "Cairo Test", size=(500,400))
self.Bind(wx.EVT_PAINT, self.OnPaint)
uri = "file://" + sys.argv[1]
self.document = poppler.document_new_from_file (uri, None)
self.n_pages = self.document.get_n_pages()

self.current_page = self.document.get_page(0)
self.scale = 1
self.width, self.height = self.current_page.get_size()
self.SetSize((self.width, self.height))

def OnPaint(self, event):
dc = wx.PaintDC(self)
cr = wx.lib.wxcairo.ContextFromDC(dc)
cr.set_source_rgb(1, 1, 1)

if self.scale != 1:
cr.scale(self.scale, self.scale)

cr.rectangle(0, 0, self.width, self.height)
cr.fill()
self.current_page.render(cr)

if __name__=="__main__":
app = wx.App()
f = MyFrame()
f.Show()
app.MainLoop()
Y acá está la captura de pantalla obligada, luego de ejecutar "python ejemplo.py /path/al/archivo.pdf" (click para agrandar):

De esta manera, es posible utilizar Python, Poppler y wxPython (o PyGTK) para mostrar y manejar el contenido de un archivo PDF dentro de nuestra aplicación y en casi cualquier plataforma, sin recurrir a componentes de terceros. :-)

Consideraciones:
Bueno, quisiera comentar que poppler-python parece ser un proyecto "joven", ya que todavía sólo está incluido en los repositorios de Ubuntu 9.04 en adelante. Con lo cual, en caso de utilizarlo en otras distribuciones y/o plataformas, hay que hacer un checkout desde sus repositorios y compilarlo; sus únicas dependencias son pycairo y poppler (0.10.x o posterior). Es muy sencillo hacerlo (el típico ./configure, make y make install), y no tuve ningún problema, utilizando Ubuntu 8.10.

En caso de querer utilizar Poppler-Python sobre el Cairo que incluye wxPython, lo mejor es utilizar una versión 2.8.9.x o superior de wxPython (ya con eso es suficiente, porque incluye Cairo en el paquete). Ubuntu 9.04 trae wxPython 2.8.9.1, Poppler 0.10.x y Poppler-Python en los repositorios, así que con un único apt-get ya tenemos todo lo necesario para hacer andar el ejemplo de arriba.

En mi caso, para probarlo en Ubuntu 8.10, tuve que compilar poppler desde los fuentes (traía la versión 0.8.x) y después compilar python-poppler, por un lado. Por el otro, para utilizar Cairo sobre wxPython 2.8.8.0 (el que viene en Ubuntu 8.10), llamé a Cairo con ctypes, como dice acá, y me quedó este ejemplo. Este procedimiento sería similar para cualquier otra distribución con versiones viejas de Poppler y/o de wxPython. Para la distribución de nuestro software todo se simplifica, ya que se puede usar tranquilamente Py2Exe, cx_Freeze o PyInstaller, por nombrar algunos. Pero eso es tema de otro post ;-)

* Poppler denomina Frontend a las diferentes APIs que tiene para ser utilizado, entre ellas QT4 (base de KDE) y Glib (GTK principalmente, base de Gnome). Y tiene como backend (es decir, necesita para dibujar) no sólo a Cairo, sino que también puede dibujar sobre Splash (ignoro qué es, y Google no me devuelve nada relevante).

Bueno, espero que al menos le sirva a alguien, que lo aprovechen y lo mejoren!

Saludos
Marcelo

martes, 28 de abril de 2009

Charla sobre Virtualización - Slides

Estos slides los estuve preparando para dar una charla sobre virtualización en el último FLISOL en la UNLu. No se dio (¡era mucha gente para atender instalando máquinas! :-D), pero las subo acá por un lado, y por el otro no va a faltar la oportunidad en darla. Es más, estamos pensando seriamente en hacer algún "pequeño evento" en la UNLu no muy lejano para juntar charlas...

En fin, los slides en cuestión, están disponibles aquí formato OpenOffice, y aquí en formato PDF.

Si encuentran algún typo, error, omisión o se les ocurre alguna mejora, ¡bienvenida sea!

Saludos
Marcelo