Masticando fotos

Estoy en vías de actualizar mi cámara de fotos. Los por qué, y cual es la cámara que quiero serán materia de otro post (¡suspenso!), ya que la decisión no fue fácil, y tiene varias aristas. Y además es una excusa para hacer otro post y hacer de cuenta que tengo un blog y escribo regularmente (?)

Pero una de las primeras cuestiones con las que me topé, es que si pretendía ganar en “profesionalismo” de la cámara, iba a tener que sacrificar zoom. Mi cámara actual, una Canon PowerShot S5 IS, entra en la categoría bridge/prosumer, pero a su vez, super zoom. Tiene un zoom de 12X (sí, OK, hoy no es tanto para una super zoom, pero cuando la compré, era una barbaridad).

Y resulta que las cámaras compactas más pro, como las “PowerShot G” de Canon o las “Coolpix P” de Nikon, tienen bastante menos zoom. Y las cámaras reflex vienen con un lente estándar con mucho menos zoom, y si bien se le puede poner el lente zoom que uno quiera, hay que considerar dos cosas: el precio del lente, y que un lente de más de 300mm (o incluso menos) para una reflex es un Señor Lente (en tamaño y peso), no muy “trekking friendly”. Y lo mismo que aplica a las reflex aplica a las nuevas mirrorless / EVIL / micro four thirds / etc.

Así que de entrada quedó claro que si iba por una compacta pro (no super zoom) o por una reflex, iba a sacrificar longitud focal.

Inmediatamente me surgieron un montón de preguntas: ¿cuánto uso el zoom de mi cámara? ¿qué porcentaje de fotos saco con un zoom óptico mayor a 5X? ¿qué valor tienen para mi las fotos que saqué con un zoom grande, tipo 10X, 12X? ¿son fotos buenísimas que no querría haberme perdido por nada del mundo?

Algunas de esas preguntas eran complicadas de responder con certeza, pero básicamente decidí asumir el riesgo y seguir mi investigación sobre cámaras bajándole la prioridad al tema zoom. Tenía la impresión subjetiva de que no era un tema tan importante.

En algún momento, ya ni recuerdo como, porque en las últimas semanas he leído una cantidad escandalosa de reviews, opiniones, blog posts, etc., etc. sobre cámaras, caí en este interesante artículo: Photo Statistics: Aggregating EXIF data to see how I shoot photos. Y eso me abrió el camino a encontrar una respuesta certera a mis preguntas/dudas sobre como aprovecho la longitud focal del lente de mi cámara actual. Resulta que…

  • … las fotos más importantes / interesantes las tengo subidas a Flickr.
  • … Flickr expone los datos EXIF de las fotos (a menos que los ocultes, cosa que yo no hago).
  • … Flickr tiene una API que permite acceder por software a la información de las fotos, sin necesidad de tener que mirarlas una por una en la web
  • … Python es un lenguaje de programación hermoso y divertido, que últimamente tengo medio olvidado, y en el que es realmente muy fácil escribir un programita que acceda a mi cuenta de Flickr, y recupere la metadata EXIF de todas mis fotos, los mastique, me de las respuestas que busco, y encima me las grafique.
  • … hace rato que busco alguna excusa para volver a escribir algo simple en Python, para recordarme a mi mismo que programar puede ser muy divertido cuando no tenés que lidiar con problemas boludos de clientes idiotas y/o hardware lento y/o restricciones de Microsoft :)

Así que puse manos a la obra, y en un par de horas tenía 80 líneas de Python que resolvían el tema de bajar los datos de Flickr. Considerando que hacía rato que no escribía nada en Python desde cero, y que no conocía las bibliotecas que necesité usar (principalmente, FlickrAPI, aunque alguna vez, en otra vida, usé ese código como base para armar un Remember The Milk API), me di por satisfecho.

Dejé el script corriendo un largo rato (bajar la info de todas las fotos no es muy rápido, y encima el script no tiene absolutamente ninguna optimización, y tampoco estoy seguro de estar usando la API de Flickr eficientemente y no estar haciendo requests al pedo), y terminé con toda la data que necesitaba en formato JSON.

El resto fue fácil: levantar esa data, y empezar a obtener las respuestas que necesitaba (usando Python también, ¡obvio!). Y hoy estuve jugando un rato con matplotlib y haciendo algunos dibujitos con la data.

Pasen y vean que lindas tolderías:

(gráfico de Apertura vs Longitud Focal)

Apertura vs Longitud Focal

Conclusiones sobre fotografía

No uso mucho el zoom. De un total de 1800 fotos en Flickr tomadas con la S5 IS, solo un 17% están tomadas con un zoom mayor a 5X. Y si bien porcentualmente 17% es bastante, una rápida mirada por varias de esas fotos me confirma que no son obras maestras. Las únicas fotos en las que el zoom 12X garpó y mucho, fueron en un par de fotos de la luna. Así que a lo sumo tendré que sacrificar el fotografiar la luna.

Esto es consistente con el tipo de fotos que saco: paisajes, macros, algún que otro retrato. Todas situaciones en las que el zoom se usa poco y nada. Las longitudes focales largas están normalmente asociadas con “action shots”, deportes, y fotografía de “vida salvaje”, y es un tipo de fotografía que no practico, o porque no es mi tema, o porque si bien me alcanzaría el zoom, mi cámara está limitada en otros aspectos que también son clave en esas situaciones: una buena velocidad de disparo, una buena velocidad en obtener foco, buena calidad de imagen con ISOs altos, por ejemplo.

En resumen: creo que podría vivir con un zoom moderado.

Conclusiones sobre programación

Programar en Python es fácil y divertido. Esto ya lo sabía, pero se me estaba olvidando.

Programar para resolver algo que te interesa resolver a vos es mucho más interesante que programar para resolver algo que a otro le interesa que le resuelvas. Otra cuestión que debería tener más presente, aunque parezca una verdad de perogrullo.

Programar concentrándote en resolver tu problema, y no en convencer a un compilador de que estás resolviendo el problema de la manera correcta (i.e., programar con tipado dinámico vs programar con tipado estático) permite llegar al resultado mucho más rápido, y podés ocuparte de las refinaciones después. Otra perogrullada y van…

No voy a publicar el código porque los tres o cuatro scripts que hice son un asco y me da vergüenza. Tal vez invierta algo de tiempo en convertirlos en algo que califique de “programa”, y no de revoleo-de-sentencias-de-python, y los suba a algún lado. En algún momento. Pero no se si vale la pena. Anyway, si estás interesado en conocer más detalles sobre algo de todo esto, preguntá, y vemos…

PyCon Argentina 2009

Y pasó PyCon Argentina 2009. La primera conferencia de Python en el mundo en español. Y junto con esto, se cumplen 5 años de vida de PyAr. ¡Cuánta nostalgia! (y como pasa el tiempo…)

La conferencia estuvo EXCELENTE, empezando por el material de registración, siguiendo por la organización general, el lugar, la coordinación, las charlas, la versión impresa del tutorial en español, las keynotes de Jacob Kaplan-Moss y Collin Winter, y toda la cosa social que hubo alrededor.

Realmente, felicitaciones a todos los organizadores y colaboradores. Es la primera vez que PyAr se cargaba algo así al hombro, y salió muy bien. Parece que el año que viene habrá PyConAr otra vez, y será en Córdoba. Trataremos de estar :)

Para mi esta PyCon marcó un punto de inflexión. Este año medio me desconecté de PyAr, y por añadidura de la organización de PyCon. El viernes y el sábado la verdad me arrepentí. Ni yo no entiendo muy bien las razones por las cuales me alejé, hay muchas… y ninguna. Pero una de las tantas que puedo esbozar, es que sentí que no estaba pudiendo participar de ninguna manera más que asistiendo a las reuniones y hacer de "opinólogo". Como toda comunidad con participación voluntaria, se sigue esto de que "cada uno se rasca donde le pica", y a mi hacía rato que no me picaba nada concreto de Python, y tampoco me interesaba ayudar a rascar la picazón de nadie. Y me sentía cada vez más inútil. Y en algún momento sentí que era mejor dar un paso al costado, al menos por un tiempo. Hubo (hay) más razones, pero de nuevo, esa es una bastante concreta, y una que tuvo peso.

En retrospectiva, me doy cuenta que después de haber estado en PyAr desde los inicios, el haberme alejado JUSTO cuando se estaba organizando PyCon la verdad no fue una buena idea… porque ahí justamente había MUCHO para hacer, mucho en que ayudar y colaborar, mucho para organizar. Y me hubiera gustado sentirme un poco más parte de todo eso, en lugar de mirarlo de afuera. Y ojo: Mirarlo de afuera estuvo *buenísimo*, porque la conferencia estuvo buenísima. Pero si había una oportunidad de hacer algo concreto era la primera PyConAr, y me auto-excluí. Ufa. En fin… cosas que uno aprende.

Pero nada… lo pasado pisado. Disfruté de una muy buena conferencia, aprendí sobre varias cosas interesantes que están sucediendo en Python en este momento, y creo que lo más importante, es que aprendí (o recordé, o reafirmé) que lo más valioso que tiene PyAr es PyAr-la-gente, y que soy un boludo si por no reconciliarme con las cosas de PyAr que no me gustan, me pierdo todo el resto.

¡Feliz cumple PyAr! Por muchos PyConAr más…

 

IronPython pyc

Estuve investigando el supuesto camino de pre-compilar módulos para ver si lograba resolver los problemas de performance que mencioné hace unos días.

Resulta que la punta del iceberg estaba escondida en el pack de ejemplos de IronPython, que se descarga aparte. En ese paquete está, entre otras cosas, el famoso pyc.py, parte de cuyo README nos cuenta:

This sample demonstrates the use of the Python Hosting APIs to compile Python files into .NET executables.  The behavior of the generated files is actually quite similar to that of CPython files with the ".pyc" file extension.

Bueno, ni tanto. El script de ejemplo solo es un programita de consola para compilar en bloque una serie de módulos, y generar un assembly. Básicamente, es una interfaz al nuevo método CompileModules del CLR, y hay una explicación bastante detallada de como funciona todo esto acá.

A menos que me esté perdiendo de algo, sinceramente no entiendo de donde sacan que el funcionamiento de todo esto es "similar al de los archivos CPython de extensión .pyc".

Veamos por que:

  • Explícitamente tengo que compilar los módulos. En CPython, esto es transparente.
  • Explícitamente tengo que indicar cual es el módulo que actuará como "entry point". En CPython, esto no es necesario.
  • Si compilo varios módulos, termino con un único assembly con todo. En CPython, cada .py genera su propio .pyc.
  • Pero lo más importante: Para usar el módulo compilado, tengo que cambiar los fuentes que lo consumen (importan). En CPython, el uso de los .pyc por parte del intérprete es completamente transparente.

El último punto es re-importante, y es la diferencia más grave. En CPython, si tengo un módulo foo, en el archivo foo.py, lo importo así:

import foo

… y resulta que si ese módulo está pre-compilado en foo.pyc, es lo mismo. Para mí no cambia nada. El intérprete agarra el .pyc. Y es más: El intérprete se ocupa de determinar si el .py cambió (es decir, si el .pyc ya no es válido).

En IronPython, al usar la compilación de módulos, y asumiendo que ya me haya tomado el trabajo de generar foo.dll (lo que me están vendiendo como "equivalente a un .pyc", para usar el assembly tengo que hacer esto:

clr.AddReference("foo.dll")
import foo

Y eso tiene varios problemas:

  • El código dejó de ser compatible con CPython (por el uso de clr)
  • Si alguien borra el assembly, el código pincha
  • Si foo.py sufre algún cambio, y nadie lo recompila, sigo levantando la foo.dll con el código viejo, y capaz ni me entero

Todo es más o menos workarroundeable: Podría tener un módulo clr "dummy" que no haga nada en CPython, podría meter el AddReference en un try/catch, podría crearme un modulito genérico que generalice toda esta magia, e incluso se ocupe de verificar si el assembly debe ser recompilado… pero no es el punto. Esto NO es lo mismo que un .pyc.

Anyway, estuve jugando con el esquema. Aplicarlo a algo como Cheetah es muy complejo, porque está compuesto por muchísimos módulos. ¿Cuáles compilo? ¿Todos? ¿Algunos? ¿Genero un solo assembly? ¿Genero un assembly por cada módulo? ¿Cuál es la diferencia? La documentación oficial sobre todo lo que tenga que ver con la compilación estática de scripts es sumamente escasa, por no decir inexistente.

Lamentablemente, no llegué a ningún resultado útil. Si compilo Cheetah, igual sigue tardando una bocha en importarse, y lo que es peor: ¡Después no anda! Se importa aparentemente ok (tardando…), pero luego al usarlo empiezan a producirse errores extraños, inesperados.

También noté que si compilo un programa de consola, tengo problemas por ejemplo con sys.argv. En la versión compilada, pierdo los parámetros (sys.argv es siempre ['']).

Conclusión: El esquema de compilación estática no es transparente, no funciona igual que los .pyc de CPython, es más engorroso de usar, obliga a cambiar el código fuente, no acelera la importación, e introduce side-effects y errores inesperados.

Me parece que el equipo de desarrollo de IronPython debería volver a leer el Zen de Python…

Mientras tanto, este esquema a nosotros no nos sirve. No solo no nos resuelve la performance, sino que nos obliga a armar toda una magia para implementarlo, y encima, después funciona a medias, o directamente no funciona.

Probando IronPython 2

Hace un tiempo vengo haciendo diversas pruebas con IronPython 2, principalmente por sus mejoras en compatibilidad con CPython, y sus mejores opciones de integración con VS (en particular VS 2008).

A partir de aquel experimento que alguna vez comenté, en el laburo decidimos usar Cheetah e IronPython como núcleo de nuestro generador de código. Hace un tiempo había empezado a experimentar con IronPython 2, y me dí contra la pared cuando descubrí que Cheetah (en su momento el único template engine que encontré que andaba con IronPython) ya no funcionaba del todo bien, y que además, era *lentísimo*. Oportunamente reporté esto en CodePlex, pero básicamente parecía haber quedado en el olvido.

Los problemas de Cheetah en el peor de los casos podían salvarse con un par de workarounds, pero implicaba tocar bastante código de nuestro lado, y además caer en cosas no recomendadas por la doc de Cheetah. Así que no era lindo. Pero además, lo de la performance era… intolerable. Simplemente intolerable.

Así que seguimos usando IPy 1.1.

En los últimos días me hice de algo de tiempo para probar IPy 2.0.1, la última release estable de IronPython. Y me encontré con 2 gratas sorpresas:

  • Cheetah funciona otra vez as expected;
  • parte de los problemas de performance están resueltos;

Eso último, parcialmente: Lo que encontré es que usando IPy 2.0.1, el generador de código funciona perfecto, y descontando la inicialización de Cheetah, incluso es por lo menos un 30% más rápido que IPy 1.1. ¿Lo malo? La inicialización de Cheetah es PATETICAMENTE lenta.

¿A qué le llamo "inicializar Cheetah"? A un simple

from Cheetah.Template import Template

Eso en CPython es instantáneo. En IPy 1.1 tarda segundos (más de 5", y a veces hasta 10"), y en IPy 2.0.1 tarda el triple que en IPy 1.1 Frown

¿Es un problema de Cheetah? No. Es un issue conocido en IronPython que los module imports son lentísimos, y que a veces muchas de las mejoras de performance de IronPython sobre CPython a nivel runtime se pierden porque de pronto en medio de tu código tenés un inocente import que se lleva el 80% del tiempo de ejecución. Una reverenda cagada. Mal.

IPy 1.1 tenía una opción SaveAssemblies que permitía guardar las DLL que generaba el intérprete. Eso ayudaba un poco, aunque no mucho en el caso de los imports. El tema es que esa opción no existe más en IPy 2.x. Supuestamente, para IPy 2.x se estuvo trabajando en una precompilación similar a la de CPython (algo parecido a la generación de .pyc), y por más que el tema está mencionado en las release notes y todo, no logro encontrar como cuerno se activa y/o usa y/o implementa eso. De todos modos no tengo muchas esperanzas, porque leí en varios lugares que de nuevo, en el caso de los imports, esta precompilación no aporta mucho, pero en nuestro caso algo es algo, y me gustaría probarlo.

Dear lazy web, does anybody know how to test the "precompile" feature of IronPython 2.x?

 

8JRSL

Y así pasaron las 8vas. Jornadas Regionales de Software Libre.

Para mi fueron las primeras, gracias a que fueron en Buenos Aires, y las viví como una "CaFeConf on steroids" :p
Lamentablemente son muchos días hábiles (3), y es complicado coordinar en el laburo la oportunidad de ir todos los días, quizás no por el contenido (al fin y al cabo, en el trabajo varias de nuestras core-tools son software libre), pero sí por el tiempo. Es muy difícil "desaparecer" 3 días. En años anteriores, a la complejidad extra de que las jornadas eran en alguna otra provincia, se sumó que coincidieron con la implementación de algún proyecto. Este año, estamos teniendo (¡por suerte!) un mediados-de-agosto tranquilo, y pude organizar las cosas para asisitir a las charlas que más me interesaban.

También mi participación esta vez fue meramente como expectador (comparando con CaFeConf 2006 y 2007). No es que otros años haya organizado nada… pero al menos, participaba más activamente del stand de PyAr, y de la presencia de PyAr en el evento, al menos aportando ideas. Esta vez, ni eso. Quizás tiene un poco que ver con que PyAr ya lleva varios años participando en estas cosas… y todo sale más de taquito.

Anyway, hay ciertas cosas que deberíamos aprender a distribuir mejor. Por ejemplo, para el pobre de Facu, la "carga" de ser una de las estrellas de PyAr, una de las personas más consultadas, organizar y dar dos charlas, asistir a Raymond Hettinger, coordinar afuera ayuda de la PSF, conseguir libros de O’Reilly para sortear, organizar el sorteo, organizar el concurso de diseño, proceso de selección, confección, y posterior venta de las remeras, y darse el lujo de además colaborar con la organización general de las 8JRSL… es *MUCHO*. Ojo, no dudo que lo disfruta, lo hace por que le gusta, y que mucha otra gente colabora con él en muchas cosas… pero el punto es que PyAr creció mucho, sigue creciendo, y no se… me queda una crítica mínimo a mi mismo por no involucrarme más (de hecho al contrario, estoy menos involucrado de lo que estaba hace un par de años), y tomar la posta para por ejemplo dar una mano con las remeras, que consume un montón de tiempo. Si bien hay cosas en las que es más complicado colaborar (ejemplo, lo de O’Reilly es mucho mejor / más fácil si lo coordina Facu como mimbro de la PSF, que si lo hace un "don nadie"), hay muchas otras cosas para hacer.

El stand de PyAr funcionó re-bien (¡como siempre!), y también se repitió la historia de que en general, los stands de "la comunidad" funcionan mucho mejor que los formales y aburridos stands de las empresas que van solo a venderse.

De las charlas que fui, me quedo con las de Raymond Hettinger; aprendí *un montón* de cositas interesantes de Python. En particular, el tutorial sobre descriptores fue bastante mind-blowing para mí, y terminó gustándome más que la charla sobre core containers.

¿Qué más? Tuvimos nuestra reunión de PyAr, la 31… creo, con record absoluto de gente, de la cual tengo pendiente redactar la minuta. Gracias a toda la gente que vino a Capital Federeal para participar de las jornadas, fue también una reunión realmente "federal", con presencia de gente de varios lugares.

¡Me gané un libro! ¡Sí! Nunca me gano NADA en ningún sorteo… así que fue completamente inesperado. Y qué libro… Programming Python, de Mark Lutz. Unas 1500 páginas. Una Biblia. Gracias PyAr, gracias O’Reilly, y gracias Facu por organizarlo.

No saqué fotos. Eventualmente iré posteando links a las fotos que publiquen otros miembros de PyAr.

IronPython con baterías incluídas

¡Bien! La beta4 de IronPython 2.0 va a incluir la librería estándar de Python. En el laburo estamos usando bastante IronPython para algunas herramientas internas. Y siempre me molestó que por un lado hacían un laburo realmente MUY BUENO en brindar un runtime de Python perfectamente integrado con .NET, y por el otro… le sacaban las baterías (para los no iniciados: solemos decir que "Python viene con las baterías incluídas", por lo amplia, útil y poderosa que es la librería estándar que uno obtiene out-of-the-box cuando lo instala).

La realidad es que no van a incluir TODA la stdlib; hay cosas que hoy por hoy ya se sabe que no funcionan (mayormente, módulos que en todo o en parte están implementados en C, y para los cuales no se hizo ningún wrapper "managed" del lado de .NET). Pero es algo.

Otro punto positivo: IronPython 2.0 va a salir con una licencia dual: La licencia MS-PL de Microsoft, que cubre IronPython, y la Python Software Foundation License, cubriendo la stdlib. Esto es todo un hito: MS acepta, y reconoce, la licencia de la PSF. Según comentan en otro blog, hasta hubo abogados de por medio para poder dar este paso. Bien por la PSF, bien por el software libre, y bien MS.

IronPython 2.0 va a ser compatible con Python 2.5, lo cual agregará varios chiches por sobre 1.1, y probablemente habilitará a que funcionen algunos módulos de terceros que hoy por hoy no funcionan.

Aún tengo pendiente probar todo esto; en particular, quiero aprovechar estas últimas betas para verificar que nuestras herramientas funcionen correctamente con el nuevo runtime.

(gracias Facu por pasarme la data)

 

Extendiendo Trac

En el trabajo ya hace bastante tiempo estamos usando Trac, con bastante éxito. Tiene sus limitaciones, ya que manejamos muchos proyectos, y sobretodo para la gente que tiene que coordinar más de un proyecto, se vuelve muy tediosa la falta de una "vista consolidada" que permita consultar y administrar al conjunto de proyectos como un todo. Por ejemplo, responder la pregunta "¿cuántos tickets tiene asignados fulano en TODOS los proyectos en los que está?" es complicado.

Esa parte la resolvió Diego exportando cada N tiempo cada una de las bases de datos SQLite de cada proyecto a una base de datos dentro de SQLServer, y ahora se están desarrollando varios reportes usando las herramientas estándares de la consultora. La desventaja es que la información es un snapshot (i.e., no tenemos la info en tiempo real, actualizada al instante), la enorme ventaja es que estamos pudiendo explotar la info de Trac de una manera mucho más rica, a la vez que nos permite una integración mucho más fuerte con nuestras otras herramientas. En cuanto a esta parte del dilema (consolidación de la información), la pata que está faltando es interactuar con Trac, es decir, no solo consultar la info, sino por ejemplo hacer operaciones masivas, del estilo seleccionar N tickets de X proyectos que cumplen tal criteria y cerrarlos. Diego está experimentando con una especie de RPC casero haciendo POSTs a Trac, yo tengo pendiente instalar en un entorno de prueba el XmlRpcPlugin y ver si nos da alguna ventaja.

Otro problema que teníamos era la consistencia entre proyectos en cuanto a "Prioridades", "Tipos de tickets", "Severidades", etc., etc., más cuestiones como definir que componentes por defecto están activos, que usuarios tienen que permisos, etc. Eso lo resolvimos haciendo un wrapper alrededor de TracAdmin. Pero no "trac-admin" el comando, sino TracAdmin a nivel de componente. Este wrapper puede usarse por línea de comandos o como un servicio web (que invocamos por ejemplo desde una página de creación de proyectos), y "sabe" hacer un initenv usando todos nuestros defaults: borra las cosas que no necesitamos, agrega las que sí, setea defaults y permisos, etc. Así cualquiera puede inicializar un nuevo proyecto en Trac con total confianza de no olvidarse ningún paso, y de que va a cumplir con nuestro estándar interno. Y el 99% de las cosas que hace este wrapper están definidas en un archivo externo de configuración, con lo cual es simple modificar / extender lo que hace.

Sacando esos dos grandes temas, aún tenemos pendientes varios detalles mas finitos, varios de los cuales son candidatos a o bien encontrar un plug-in en Trac Hacks que nos de la funcionalidad requerida, o implementar nuestro propio plug-in. Uno de esos temas tiene que ver con que Trac 0.10 no maneja workflows, la versión 0.11 se sigue demorando… y demoraaaaaaando, y estábamos necesitando empezar a validar ciertas cosas, en particular, de consistencia de valores de algunos campos al cerrar un ticket. Así que con un poco de expermientación del finde, más un ratito hoy en el trabajo para afinar detalles, me largué a escribir mi primer plugin para Trac.

Es realmente MUY fácil. La mayor parte del tiempo la invertí investigando de cual de tooooooooodos los puntos de extensión que expone Trac tenía que colgarme para hacer lo que yo quería. Una vez descubierto eso, fue muy sencillo. Quería validar el ticket al grabar cambios. La interfaz a implementar resultó ser ITicketManipulator. Macheteandome un poco en el código SpamFilterPlugin, y leyendo la MUY buena doc de Trac, el resto fue coser y cantar.

No publico el código completo porque está muy pegado a lo que hacemos internamente en el trabajo, pero en esencia, el core del plug-in es algo así:

from trac.core import *from trac.ticket import ITicketManipulator, TicketSystemclass RechazarTicket(TracError):  """Excepcion a generar si el ticket es inválido."""class MiValidator(Component):  implements(ITicketManipulator)  # Métodos de ITicketManipulator  def prepare_ticket(self, req, ticket, fields, actions):    pass  def validate_ticket(self, req, ticket):    if 'preview' in req.args:      # Si es un preview, y no estamos grabando, no validamos nada      return []    if ticket['status'] != 'closed':      if ticket['version'] in ('XXX', 'YYY'):        raise RechazarTicket('La versión %s solo es válida si el ticket está cerrado.' % ticket['version'])      # El ticket aún no está cerrado: No validamos nada más      return []    # Recuperamos todos los campos que NO son de texto    fields = [f['name'] for f in              TicketSystem(self.env).get_ticket_fields()              if f['type'] not in ('textarea', 'text')]    for field in fields:      # Acá implemento las validaciones que quiera...      # "field" tiene el nombre del campo (ej., "version", "status", etc.)      # puedo acceder al valor haciendo      #    ticket[field]      # y puedo ver el valor anterior (para ver si se está modificando) haciendo      #    ticket._old[field]      # Si alguna de mis validaciones custom no se cumple, se hace un      # raise de RechazarTicket... y listo.    return []

Como ven, muy fácil. Ahora entiendo un poco más por qué en Trac Hacks hay TANTAS cosas… es que realmente es simple extender Trac. Ahora que rompimos el hielo con este primer plugin… probablemente se vengan más a futuro.

 

CDC UNLUX 2007 – Conectando Puntos

El sábado se realizó el Ciclo de Charlas UNLUX 2007, "Conectando Puntos", organizado por el Grupo de Usuarios de Software Libre de la Universidad Nacional de Luján (UNLUX para los amigos :p)

Evento que tuvo el "honor" de ser auspiciado por PyAr. ¿Será un honor? Jeje… hablando en serio, el honor fue nuestro, y marca un hito. Esperemos que en adelante podamos seguir auspiciando estos eventos.

Otro punto que hace especial a este ciclo de charlas es que fue generado desde adentro de una universidad, y eso es fantástico. Las universidades tendrían que tener un contacto MUCHO más grande con el software libre del que tienen… por una cuestión de soberanía y autonomía, por una cuestión de flexibilidad a la hora de adaptar el software a sus necesidades, por una cuestión pedagógica, especialmente en carreras de informática, dada por la posibilidad de de ver y modificar el código fuente, y como si todo eso fuera poco, por una cuestión económica.

Este fue el primer ciclo de charlas organizado por el UNLUX, y fue todo un éxito. Mucha más gente de la que esperábamos (el puntapié inicial de estas cosas no siempre tiene la convocatoria que uno quisiera), y la organización estuvo muy prolija. Hasta los chicos tuvieron que capear un corte de luz general de varias horas en toda la universidad.

Hubo una gran cantidad de charlas, de diversos temas. Obviamente, Python estuvo ahí, como corresponde :)

Luego del cierre de las charlas, gran parte de los organizadores, disertantes, un grupo de PyAr y algunos otros asistentes nos fuimos a festejar, cenar y pasar un rato agradable a una pizzería.

Facundo escribió un review bastante detallado del evento en este post.

Por último, si quieren fotos… las mías están en este álbum. Los chicos de UNLUX también publicaron fotos en su site, en el álbum CDC -> 2007 :: Conectando puntos. Y Facundo subió más fotos acá.

 

CaFeConf 2007

Y así pasaron las Sextas Conferencias Abiertas de Software Libre y GNU/Linux.

Al igual que el año pasado, Python fue el lenguaje con más presencia en las conferencias, tanto en charlas, como en "comunidad". Esto es un logro de todo PyAr, pero creo que merece ser destacado el esfuerzo de Alecu, Dani, Dave, Lucio y Facu generando contenido, y el de los chicos de Santa Fe y Córdoba, siempre presentes. Como siempre, y a pesar de los reparos que yo en lo personal tengo al respecto, pyWeek vende. Y tener dos OLPC (gracias Educ.ar!) en el stand para mostrar, fue como tener un tarro de miel a un metro de un hormiguero… :)

Otro "debut" de este año fue la cartelera de trabajo, organizada por Alecu: http://python.com.ar/trabajos. Además de su contrapartida web, estuvo "físicamente" en forma de un gran afiche junto a nuestro stand, y todo el tiempo ví gente tomando nota.

Hubo muchas menos charlas que el año pasado, y creo que eso es un plus. Como comentábamos con los chicos de Lanux anoche, eso ayudó a subir el nivel: Hubo mucha menos superposición de contenidos, y más gente en cada charla. No si es esto fue casual o la gente de CaFeLUG específicamente buscó este efecto… pero es para tomar nota.

De las charlas a las que asistí, me quedo en especial con dos:

  • "Python más rápido que C", por Lucio Torre y Facundo Batista. Una muy entretenida e ilustrativa charla para mostrar que sí, que a veces Python es (bueno, casi…) más rápido que C, y que otras tantas, C es más rápido pero, ¿vale la pena el esfuerzo? Habían generado mucha espectativa con su charla, el título de entrada fue un gancho de marketing fenomenal. Y salieron muy bien parados de la prueba. Felicitaciones.
  • "Caperucita en el Bosque", por Enrique Chaparro, de la Fundación Vía Libre. Excelente. Sumamente ocurrente, en cuanto a usar el cuento de caperucita roja como analogía e hilo conductor de la charla. Muy amena. Y muy ilustrativa. Esta fue la "Key note", la única charla plenaria. Espero que se haya grabado… traten de buscarla, bájenla y véanla. Vale la pena.

El cierre de CaFeConf quedó una vez más a cargo de Leito Monk, y al igual que el año pasado, estuvo absolutamente desopilante. NADIE, absolutamente NADIE se esperaba verlo entrar al escenario disfrazado de pingüino, y gritando "developers! developers! developers!" La organización de todo el evento estuvo muy bien, realmente la muchachada de CaFeLUG labura un montón para esto… y se nota. Gracias!

El único punto "flaco", al igual que el año pasado, fue el lugar: UADE no es el mejor ámbito para estas conferencias. Los cacheos de seguridad, LENTOS y BUROCRATICOS son sumamente molestos. Así y todo, desapareció una laptop. Y algo me dice que UADE va a mirar seguramente para otro lado (ojalá que no… but I'm not holding my breath…). Pero bueno, por ahora, es lo que hay. 

En cuanto al aspecto puramente social y pythonico, la noche del viernes nos fuimos a tomar unas cervezas por San Telmo. La excusa oficial fue festejar los buenos resultados de los grupos argentinos en la última edición de pyWeek… y terminó siendo una pseudo-reunión de PyAr. Luego de pasar un rato en una coqueta parrilla de San Telmo de la cual no recuerdo el nombre (ni lo quiero recordar…), en la que solo tomamos unas cervezas, terminamos en la pizzería Tío Felipe, en Balcarce y San Lorenzo. BUENISIMO. La pasamos genial. Y como siempre, los lugares más tradicionales, más "de barrio", son los mejores. Si alguien de Tío Felipe lee esto: Sigan así. No se dejen aggiornar por la movida "transformemos San Telmo en un lugar solo apto para europeos con euros". Ojo, no tengo NADA en contra del turismo europeo… solo de los comerciantes inescrupulosos argentinos que arman una mentira cara para vender a los turistas, que NO tiene nada que ver con la escencia de uno de los barrios más antiguos y tradicionales de Bs. As., y hacen que solo puedas salir a comer afuera por la zona si a), te creés la mentira y b) estás dispuesto a pagar por un servicio que no lo vale.

La noche del sábado, un pequeñísimo grupo de PyAr (Dave, Alecu y yo) acompañamos a los chicos de Lanux a tomar algo… oooootra vez, una muy buena cervezeada con picada y pizza, en el local de Zapi de Independencia y Perú.

Fotos, fotos y más fotos.

 

Cómo tener una consola de IronPython decente en Linux

IronPython, como buena implementación de Python, provee una consola interactiva.

Tiene un gran problema: En linux, anda MUY mal. Al menos en Ubuntu, desde gnome-terminal, suckea. Mucho. Pero que mucho. En Windows, anda un poquitín mejor. Por ejemplo, uno puede apretar backspace y sucede esa cosa mágica de borrar el caracter a la izquierda del cursor y todo!!! En linux, por default, ni eso.

Este finde estuve por primera vez en varios meses usando en serio IronPython, y si bien los ajustes finales de este mini-proyecto los terminé sobre .NET en Windows, arranqué trabajando con Mono en Linux. Y trabajar con Python con una consola que NO funciona, es desesperante. Me cansé de googlear buscando soluciones… y no encontré nada. Mi última búsqueda fue "ironpython console on linux sucks". Y para mi sorpresa, no arrojó resultados significativos. Porque IT REALLY SUCKS! Al toque empecé con mis teorías conspirativas, en la línea "claro, ahora que es un proyecto de Microsoft, no nos importa como anda en Linux". Pero no tenía sentido… porque debería haber una legión de usuarios de Linux/Mono descontentos. Y si Google no los encontraba, ¿dónde estaban? No cerraba. Evidentemente *yo* estaba haciendo algo mal.

Y ahí fue cuando entre tantas vueltas, descubrí que la consola de IronPython se puede iniciar con una serie de opciones… y al toque 3 llamaron poderosamente mi atención:

 -X:AutoIndent        Automatically insert indentation -X:ColorfulConsole   Enable ColorfulConsole -X:TabCompletion     Enable TabCompletion mode

Si bien a priori no tenían que ver con mi problema (que es un manejo absolutamente BROKEN de las secuencias de escape, movimiento del cursor y demás), decidí probar. Y para mi sorpresa… no solo gané color, tab-completion (bastante similar a la que ofrece iPython) y auto-indent… sino que con esas opciones se resuelven los demás problemas!!! Fantástico. No se cual de las 3 hace la magia (sinceramente no lo probé… se los dejo como tarea para el hogar) pero sospecho que la opción salvadora debe ser -X:ColorfulConsole, que para manejar el color debe usar otra librería para interactuar con la consola.

Así que ahora tengo en mi .bash_aliases lo siguiente:

alias ipy='ipy -X:AutoIndent -X:ColorfulConsole -X:TabCompletion'

… de manera que cuando ejecuto 'ipy' (el intérprete de IronPython), lo hago con las opciones correctas. Y me pregunto por qué mierda esas opciones no están activas por default, y/o por qué Ubuntu no las activa por default. Porque la diferencia es ABISMAL.

Bonus-track: Esas opciones son también útiles en Windows.