Canonical Voices

What Bitácora de Vuelo talks about

Posts tagged with 'python'

facundo


Estos últimos días se liberaron nuevas versiones de dos proyectos en los que estoy involucrado activamente.

A principio de mes lancé Encuentro 3.1 (como ya sabrán, este programa permite buscar, descargar y ver contenido del Canal Encuentro, Paka Paka, BACUA, Educ.ar y otros).

La versión 3.1 trae los siguientes cambios con respecto a la versión anterior:

  • Vuelve a funcionar luego de los cambios de backend de Encuentro y Conectate
  • Ahora con CTRL-F se va directamente al campo de filtro (gracias Emiliano)
  • Se rehizo el manejo de la lista de episodios: ahora verlos y filtrarlos es muchísimo más rápido
  • Mejoras en el empaquetado, debería funcionar para muchas (todas?) las versiones de Debian/Ubuntu (gracias Adrián Alves). 
  • Varias mejoras al encontrar nuevos episodios de los distintos backends, y correcciones en general. 

Más info y cómo descargarlo, instalarlo, etc, en la página oficial.

Por otro lado, ayer se lanzó fades 3 (un proyecto orientado a desarrolladores Python, en contraposición a Encuentro que está pensado para el usuario final), que desarrollamos principalmente Nico Demarchi y yo.

fades (en inglés: FAst DEpendencies for Scripts) es un sistema que maneja automáticamente los virtualenvs en los casos simples que uno normalmente encuentra al escribir scripts o programas pequeños.  Crea automáticamente un nuevo virtualenv (o reusa uno creado previamente) instalando las dependencias necesarias, y ejecutando el script dentro de ese virtualenv.

¿Qué hay de nuevo en esta release?

  • Podés usar diferentes versiones del intérprete: simplemente pasá --python=python2 o lo que te convenga.
  • Las dependencias pueden especificarse en la linea de comando: no hay necesidad de cambiar el script para una prueba rápida, simplemente especificá la dependencia necesaria con --dependency.
  • Modo interactivo: es la manera más rápida de probar una nueva biblioteca. Sólo hacé fades -d <dependencia> y te abrirá un intérprete interactivo dentro de un venv con esa dependencia.
  • Soporta tomar argumentos desde el shellbang. De esta manera podés crear un script y poner al principio del mismo algo como: #!/usr/bin/env fades -d <dependencia> --python=python2.7
  • Puede parsear requerimientos desde un archivo. No hay necesidad de ningún cambio si ya tenés un archivo requirements.txt: simplemente indicalo con --requirement.
  • Si no se especifica el repo, toma PyPI por defecto, lo que resulta en código más limpio y simple.
  • Tiene una base de datos integrada para conversiones típicas de nombres: de esta manera se puede marcar con fades un "import bs4" incluso si ese no es el nombre del paquete en PyPI.
  • Otros cambios y correcciones menores.

Toda la info, en la página de PyPI del proyecto.

Read more
facundo


Hace un tiempo les hablé de un árbol que hice para sacar prefijos de palabras.

En el laburo estoy estudiando la forma de hacer un autocompletador. Entonces, luego de leer cosas por ahí, decidí probar ese árbol que ya tenía hecho.

Nunca le había tirado tantos datos, pero la verdad es que salió andando de perlas.

Por otro lado, tenía un detalle que necesitaba solucionar: yo quería que la búsqueda de palabras soportara errores en la escritura. O sea, que si uno buscara "maise", encontrara "maizena".

Encontré un paper bastante loco, Efficient Error-tolerant Query Autocompletion, pero que mostraba la forma de soportar errores al buscar palabras completas, no prefijos. Igual, apliqué ideas de ahí, y en un par de días de laburo conseguí lo que quería. Pero, al cargar el millón y medio de registros que tengo que cargar, ¡explotaba por memoria!

Luego de algunas optimizaciones obvias, se me ocurrió lo de deduplicar los subtrees internos. ¿Qué es deduplicar? Deduplicar es la acción por la cual si tengo un objeto A, y luego tengo otro B, que resulta ser igual a A, puedo usar el A directamente en ambos casos, descartando B (libera memoria), y listo.

Deduplicar diccionarios no es un asunto trivial. Tiré el asunto en la lista de PyAr, y en pocas horas logré que todo funcione correctamente. Ahora no sólo no explota, sino que ocupa bastante poca memoria!

    Memory usage after loading the tree: rss: +586 MB  vms: +586 MB
    Time to load the tree: 327190.99 msec
    <WordTree at 3068071276 [tau=1]: 1478347 words 30015540 (2201293) nodes (unique)>

Millón y medio de palabras, 30 millones de nodos (de los cuales 2.2 millones son únicos), ocupando 590 MB de memoria. Nada mal, ¿no? Que tarde 5.5 minutos en armar toda la estructura es un problema, la semana que viene voy a mirar eso bien.

Todo el código, acá.

Read more
facundo


They say that metaclasses make your head explode. They also say that if you're not absolutely sure what are metaclasses, then you don't need them.

And there you go, happily coding through life, jumping and singing in the meadow, until suddenly you get into a dark forest and find the most feared enemy: you realize that some magic needs to be done.


The necessity

Why you may need metaclasses? Let's see this specific case, my particular (real life) experience.

It happened that at work I have a script that verifies the remote scopes service for the Ubuntu Phone, checking that all is nice and crispy.

The test itself is simple, I won't put it here because it's not the point, but it's isolated in a method named _check, that receives the scope name and returns True if all is fine.

So, the first script version did (removed comments and docstrings, for brevity):

    class SuperTestCase(unittest.TestCase):

        def test_all_scopes(self):
            for scope in self._all_scopes:
                resp = self._check(scope)
                self.assertTrue(resp)

The problem with this approach is that all the checks are inside the same test. If one check fails, the rest is not executed (because the test is interrupted there, and fails).

Here I found something very interesting, the (new in Python 3) subTest call:

    class SuperTestCase(unittest.TestCase):

        def test_all_scopes(self):
            for scope in self._all_scopes:
                with self.subTest(scope=scope):
                    resp = self._check(scope)
                    self.assertTrue(resp)

Now, each "sub test" internally is executed independently of the other. So, they all are executed (all checks are done) no matter if one or more fail.

Awesome, right? Well, no.

Why not? Because even if internally everything is handled as independent subtest, from the outside point of view it still is one single test.

This has several consequences. One of those is that the all-inside test takes too long, and you can't know what was going on (note that each of these checks hit the network!), as the test runner just show progress per test (not subtest).

The other inconvenient is that there is not a way to call the script to run only one of those subtests... I can tell it to execute only the all-inside test, but that would mean to execute all the subtests... which, again, takes a lot of time.

So, what I really needed? Something that allows me to express the assertion in one test, but that in reality it were several methods. So, I needed something that, from a single method, reproduce them so the class actually had several ones. This is, write code for a class that Python would find different. This is, metaclasses.


Metaclasses, but easy

Luckily, since a couple of years ago (or more), Python provides a simpler way to achieve the same that could be done with metaclasses. This is: class decorators.

Class decorators, very similar to method decorators, receive the class that is defined below itself, and its response is considered by Python the real definition of the class. If you don't have the concept, you may read a little here about decorators, and a more deep article about decorators and metaclasses here, but it's not mandatory.

So, I wrote the following class decorator (explained below):

    def test_multiplier(klass):
        """Multiply those multipliable tests."""
        for meth_name in (x for x in dir(klass) if x.startswith("test_")):
            meth = getattr(klass, meth_name)
            argspec = inspect.getfullargspec(meth)

            # only get those methods that are to be multiplied
            if len(argspec.args) == 2 and len(argspec.defaults) == 1:
                param_name = argspec.args[1]
                mult_values = argspec.defaults[0]

                # "move" the usefult method to something not automatically executable
                delattr(klass, meth_name)
                new_meth_name = "_multiplied_" + meth_name
                assert not hasattr(klass, new_meth_name)
                setattr(klass, new_meth_name, meth)
                new_meth = getattr(klass, new_meth_name)

                # for each of the given values, create a new method which will call the given method
                # with only a value at the time
                for multv in mult_values:
                    def f(self, multv=multv):
                        return new_meth(self, **{param_name: multv})

                    meth_mult_name = meth_name + "_" + multv.replace(" ", "_")[:30]
                    assert not hasattr(klass, meth_mult_name)
                    setattr(klass, meth_mult_name, f)

        return klass

The basics are: it receives a class, it returns a slightly modified class ;). For each of the methods that starts with "test_", I checked those that had two args (not only 'self'), and that the second argument were named.

So, it would actually get the method defined in the following structure and leave the rest alone:

    @test_multiplier
    class SuperTestCase(unittest.TestCase):

        def test_all_scopes(self, scope=_all_scopes):
            resp = self.checker.hit_search(scope, '')
            self.assertTrue(resp)

For that kind of method, the decorator will move it to something not named "test_*" (so we can call it but it won't be called by automatic test infrastructure), and then create, for each value in the "_scopes" there, a method (with a particular name which doesn't really matter, but needs to be different and is nice to be informative to the user) that calls the original method, passing "scope" with the particular value.

So, for example, let's say that _all_scopes is ['foo', 'bar']. Then, the decorator will rename test_all_scopes to _multiplied_test_all_scopes, and then create two new methods like this::

    def test_all_scopes_foo(self, multv='foo'):
        return self._multiplied_test_all_scopes(scope=multv)

    def test_all_scopes_foo(self, multv='bar'):
        return self._multiplied_test_all_scopes(scope=multv)

The final effect is that the test infrastructure (internally and externally) finds those two methods (not the original one), and calls them. Each one individually, informing progress individually, the user being able to execute them individually, etc.

So, at the end, all gain, no loss, and a fun little piece of Python code :)

Read more
facundo


Algunas, varias y sueltas.

A nivel de proyectos, le estuvimos metiendo bastante con Nico a fades. La verdad es que la versión 2 que sacamos la semana pasada está piolísima... si usás virtualenvs, no dejes de pegarle una mirada.

Otro proyecto con el que estuve es CDPedia... la parte de internacionalización está bastante potable, y eso también me llevó a renovar la página principal que te muestra cuando la abrís, así que puse a tirar una nueva versión de la de español, y luego seguirá una de portugués (¡cada imagen tarda como una semana!).

Hace un rato subí a la página de tutoriales de Python Argentina el Tutorial de Django en español (¡gracias Matías Bordese por el material!). Este tuto antes estaba en un dominio que ahora venció, y nos pareció interesante que esté todo en el mismo lugar, facilita que la gente lo encuentre.

Finalmente, empecé a organizar mi Segundo Curso Abierto de Python. Esta vez lo quiero hacer por la zona de Palermo, o alrededores (la vez pasada fue en microcentro). Todavía no tengo reservado un lugar, y menos fechas establecidas, pero el formato va a ser similar al anterior. Con respecto al sitio, si alguien conoce un buen lugar para alquilar "aulas", me avisa, :)

Read more
facundo

Logging levels


Cuando empecé con el concepto de loguear, me parecía demasiado tener niveles. Con el tiempo y la experiencia me di cuenta que son imprescindibles, :)

En la biblioteca estándar de Python hay un módulo logging que trae varios niveles prefijados. Son estos, con una pequeña anotación de cómo los uso, más un ejemplo de la vida real (tomados de mi programa de Encuentro o de fades).

- CRITICAL: creo que nunca lo usé :)

- ERROR: problemas de todo tipo; cosas que no deberían pasar, y si pasan son un inconveniente; muchas veces el programa no continúa, o continua de forma parcial o limitada, luego de este tipo de linea logueada. En este ejemplo logueo que no se pudo bajar la lista de los backends durante una actualización (también en este caso se le avisa al usuario mediante una ventanita, y el programa sigue, aunque la actualización no se concretó):

    try:
        _, backends_file = yield utils.download(BACKENDS_URL)
    except Exception, e:
        logger.error("Problem when downloading backends: %s", e)
        tell_user("Hubo un PROBLEMA al bajar la lista de backends:", e)
        return

- WARNING: para indicar que sucedió algo que en general no debería pasar; en general no son cosas malas, sino más bien anómalas, y no presentan una situación problemática. En el siguiente ejemplo estoy dejando registro que ignoro la opción 'quiet' que pasó el usuario (porque también pasó la opción 'verbose', que es más importante):

    if verbose and quiet:
        l.warning("Overriding 'quiet' option ('verbose' also requested)")

- INFO: información general del funcionamiento del programa, cosas que son imprescindibles saber y que siempre queremos que sean registradas; en general no involucran gran cantidad de lineas, pero permite seguir el flujo de ejecución del programa desde un nivel alto. Normalmente los programas que se entregan a los usuarios o corren en los servidores están configurados para realmente mandar a disco desde este nivel. En las siguientes dos lineas muestro lo primero que loguea Encuentro al arrancar: con qué versión de Python está siendo ejecutado y qué versión de sí mismo es:

    log.info("Running Python %s on %r", sys.version_info, sys.platform)
    log.info("Encuentro version: %r", version)

- DEBUG: toda la información necesaria para analizar en detalle la ejecución del programa. Puede involucrar grandes cantidades de información, y hasta ser un problema con respecto al uso de disco o afectar la performance, pero en general no se corren los programas en este nivel, sólo durante el desarrollo o en casos de tratar de analizar un problema específico. No es raro, por ejemplo, pedirle al usuario que ejecute el programa con un parámetro especial que configura los logs en este nivel y que trate de reproducir el problema que tuvo, para luego hacer un análisis forense de la situación. En el siguiente ejemplo estoy dejando constancia que fades tuvo que instalar pip a mano en el virtualenv:

    logger.debug("Installing PIP manually in the virtualenv")

Me ha pasado en sistemas muy complejos de necesitar un nivel más abajo que DEBUG para loguear toda aquella información que podría llegar a ser útil para un análisis del comportamiento del programa, pero que normalmente sería un exceso de datos (lo cual complica desde la lectura de los registros hasta el mismo manejo de los archivos). Entonces, usábamos un nivel TRACE, que casi nunca se prendía, para este propósito.

La macana es que el módulo de logging no tiene un nivel TRACE, pero lo creábamos a mano:

    TRACE = 5
    logging.addLevelName('TRACE', TRACE)

Fíjense el 5 ese: es que DEBUG es 10, entonces queda "más abajo". Claro, para que funcione todo, teníamos que usar un Logger custom:

    class Logger(logging.Logger):
        """Logger that support our custom levels."""

        def trace(self, msg, *args, **kwargs):
            """log at TRACE level"""
            if self.isEnabledFor(TRACE):
                self._log(TRACE, msg, args, **kwargs)

Para más información sobre la infrastructura de logging de Python y consejos generales sobre qué, cómo, o cuándo dejar registro de lo que sucede, pueden ver mi charla sobre el tema (estos sons los slides, y en algún momento se publicará acá el video de esta misma charla que dí en la PyCon de Rafaela).

Read more
facundo

PyCon 2014 en Rafaela


Acaba de pasar la sexta PyCon Argentina. Como dice el título, se hizo en Rafaela, provincia de Santa Fe.

Fuimos con Nico Demarchi en auto, salimos el miércoles a la tarde y llegamos una y monedas de la mañana, volvimos el domingo durante el día, arrancando a media mañana. Creo que es el límite de lo que haría en auto... más distancia ya iría en micro o avión.

Yo tenía que llegar el miércoles a la noche porque el jueves abría el día de talleres con Introducción a Python (modo charla extendida, ya que tenía dos horas). El jueves dí dos charlas más: Cómo debuguear en Python, y Cómo los logs me salvaron el alma.Y para cerrar (justo antes de los sorteos y foto grupal), le conté a la gente un poco cómo íbamos con el proyecto de armar la Asociación Civil de PyAr.

Mis charlas salieron bien, aunque la de debugging no me gustó del todo como la había dado (pero luego recibí buen feedback). Para el taller de Intro a Python usé por primera vez a Pysenteishon, un software muy copado y piola para ir pasando los slides desde el teléfono (¡gracias Emiliano por hacerlo!). Y para las charlas del jueves estuve por primera vez descalzo dando la presentación (era algo que quería probar desde hace rato, y aproveché que el escenario del auditorio tenía piso de madera).

Dando la charla en patas

También fuí a muchas charlas, había muchas cosas copadas para ver, y creo que me salté uno o dos timeslots nada más en toda la conferencia. Las keynotes estuvieron bien, pero no me entusiasmaron particularmente. Y todo lo fue lugar y organización estuvo genial, la verdad que se pasaron. Lo mismo con la gente con la que me (re)encontré: es un placer ser parte de una comunidad así.

Yo llevé la cámara... pero la verdad es que colgué sacando fotos. Pero la grosa de Yami sacó un montón, están todas acá. Y una de las últimas que sacó es justamente la grupal, esta que muestro acá:

Foto grupal

Y como siempre que uno no viaja durmiendo o solo, está el efecto de "PyCon extendida". Es que uno viene charlando de mil cosas, de lo más variado, pero también de proyectos, ideas, etc. Con Nico nos venía rondando en la cabeza una idea para facilitar el uso de dependencias en programas Python, estuvimos charlando con gente en la conferencia, nos dieron feedback, la idea fue mutando... y en el viaje de vuelta se nos terminó de ocurrir algo piola, que no debería ser demasiado loco de implementar; ya les traeré la novedad.

¡Pero no sólo un proyecto me traje! (como si tuviera pocos y/o mucho tiempo libre, ¿no?). Tengo ganas de hacer una "maquinita de timelapse" con una Raspi (una cajita que uno puede colgar en cualquier lado y dejarla ahí algunas horas o un par de días y arme un video de esos donde se ve todo rápido, por ejemplo este). El otro proyecto es armar una valija o caja robusta con todo lo necesario en un PyCamp (router, computadora para caché de repositorios, energía, y varios etcéteras), de manera de tener todo listo y de fácil armado, onda llegás y enchufás. Ya veremos cómo se van desarrollando ambos proyectos...

Read more
facundo

Satélites argentinos


Estos días fue lanzado exitosamente el tercer nanosatélite argentino, "Tita" (llamado así en honor a Tita Merello).

Se llaman "nanosatélites" porque, justamente, son mucho más chicos (y baratos) que los satélites "tradicionales". En particular, Tita pesa unos 25 kilos, está equipado con tres antenas y lleva una cámara para tomar fotos y videos en alta definición.

El satélite Tita, siendo instalado en el lanzador

Lo desarrolló la empresa argentina Satellogic, pero no lo lanzamos nosotros al espacio (todavía no tenemos esa capacidad), sino que fue lanzado desde la ciudad rusa de Yasny. Su objetivo es tomar imágenes durante tres años, en colaboración con otros nanosatélites, los ya lanzados Capitán Beto (llamado así obviamente en referencia a la canción de Spinetta) y Manolito (por el personaje de Mafalda), y a otros 15 satélites que Satellogic planea lanzar durante el próximo año.

Pero Tita es diferente a los dos anteriores, que pesaban alrededor de dos kilos. También es un prototipo, y usa las mismas estrategias de diseño y fabricación con componentes de uso comercial (resortes de ferretería, electrónica de teléfonos celulares y computadoras personales), pero este permite tomar imágenes y videos de dos metros de resolución. Esencialmente, la gente de Satellogic está haciendo lo mismo que hace un satélite convencional, pero a un precio entre cien y mil veces menor.

En este video bastante interesante podemos ver a Lino Barañao (Ministro de Ciencia y Tecnología) y Emiliano Kargieman (CEO de Satellogic), contándonos un poco todo esto (y de paso se ven pasos de la construcción, y las oficinas, ¡donde se ve bastante gente de PyAr trabajando!).



Como detalle final, les dejo este audio de Adrián Paenza hablando sobre los satélites (en general) en el programa La Mañana de Victor Hugo Morales.

Read more
facundo


Entre los viajes y las vacaciones, estos meses terminé viendo un montonazo de películas. Encima, no aparecieron muchas peliculas copadas para anotar a futuro.

Por otro lado, no estuve viendo muchas series. Con Moni estamos viendo Battlestar Galactica, y yo tengo varias a punto de arrancar (Black Mirror, Almost Human, Through The Wormhole S03).

Pero, a nivel de películas, sí recuperé bastante terreno, :)

  • Chronicle: -0. Muy bien desarrollado el tema de cómo llevar adelante, explorar, y en algún punto sobrellevar, un superpoder adquirido. El resto de la película no vale.
  • Contagion: -0. Muestra de forma interesante (y ajustado a la realidad, me parece) el proceso social ante una epidemia, y las actuaciones están bien, pero le falta como película, como historia contada, como relato.
  • Dream house: +0. Predecible, predecible, predeci..WHAT? Un giro loco, la historia está buena, las actuaciones también; quiere ser un toque de terror pero blah.
  • El hombre de al lado: -0. Tiene partes interesantes, y Daniel Araoz está genial, pero la historia no llega a evitar el naufragio.
  • Elefante blanco: +0. Una realidad que uno (yo) no conoce; bien crudo como acostumbra Trapero. Darín está bien como siempre. Podría estar mejor la historia.
  • Ender's game: +1. Es una buena adaptación del libro, y la película está buenísima. Sí, el libro está mejor, tiene toda una parte que en la peli ni aparece, y es mucho más profundo... pero todo eso no hace que la peli en sí deje de estar buena.
  • Habitación en Roma: +1. Una película hermosa, cruda, y maravillosa, sobre el "enamoramiento".
  • Haywire: -0. Una película de acción que tiene algunos buenos actores un poco desaprovechados, tiene partes buenas, pero meh, es una más sin nada que la haga valer específicamente.
  • Killer Elite: -0. Al final no es más que una historia (que sí está buena) donde muchos machotes están todo el tiempo midiendo a ver quien tiene la pistola más larga.
  • Margin call: +1. Impecablemente contado la interna humana de un descarrilamiento financiero. Me gusta mucho el punto de vista del trabajador interno de la empresa, me pareció muy veraz. Muy buenas actuaciones.
  • Men in black III: +0. Divertida. Más de lo mismo pero con lo interesante de los saltos temporales y mostrar como era MIB en el pasado :)
  • Mission: Impossible - Ghost protocol: +0. No deja de ser la misma película fantasiosa de siempre, pero esta vez me divertí bastante al verla.
  • Monsters University: +1. Tan buena como la primera, aunque totalmente distinta.
  • No strings attached: -0. Natalie Portman no la llega a rescatar; el tema es trillado, no le dan un giro interesante, y Kutcher, como siempre, resta.
  • Paul: +0. Comedia liviana, nada espectacular, para reirse un rato y disfrutar todas las referencias extraterrestroides.
  • The Avengers: +0. Un poco demasiado violenta, pero en el límite (me hacía acordar a Transformers). Me divirtió. Me gustó los (escasos) planteos filosóficos que tiene, aunque al final siempre el mensaje de "menos mal que tenemos superheroes que nos van a salvar cuando todo esté mal", con el que estoy totalmente opuesto.
  • The King's speech: +1. Fantástica película, con actuaciones soberbias, y una historia muy interesante sobre superación personal.
  • The Ledge: +1. La historia interesante, las actuaciones bien. Muy buenos contrapuntos sobre "la religión". Emotiva. Patrick Wilson mejor de lo que esperaba, y Terrence Howard, como siempre, muy muy bien.
  • The divide: +1. Muy bien hecha. Muestra tan bien las miserias humanas que, aunque no soy impresionable y me banco (casi) cualquier cosa, no la voy a volver a ver.
  • The hobbit: The desolation of Smaug: +1. Segunda parte de la trilogía, sigue estando muy buena. Sorprendente la voz de Smaug (el dragón), ¡es Sherlock! http://www.imdb.com/name/nm1212722/
  • The thing: +1. Es vieja, pero los efectos no están tan mal. Y parece que tiene un montón de lugares comunes... hasta que uno entiende que en esa época no eran comunes! ;)


Las anotadas nuevas:


Finalmente, el conteo de pendientes por fecha:

(Sep-2008)    6
(Ene-2009)   18  12   1   1
(May-2009)   11  10   5
(Oct-2009)   16  15  14
(Mar-2010)   18  18  18  16   4
(Sep-2010)   18  18  18  18  18   9   2   1
(Dic-2010)   13  13  13  12  12  12   5   1
(Abr-2011)   23  23  23  23  23  23  22  17   4
(Ago-2011)       12  12  11  11  11  11  11  11   4
(Ene-2012)           21  21  18  17  17  17  17  11
(Jul-2012)               15  15  15  15  15  15  14
(Nov-2012)                   12  12  11  11  11  11
(Feb-2013)                       19  19  16  15  14
(Jun-2013)                           19  18  16  15
(Sep-2013)                               18  18  18
(Dic-2013)                                   14  14
(Abr-2014)                                        9
Total:      123 121 125 117 113 118 121 125 121 110

Read more
facundo

PyCamp 2014


Se fue otro PyCamp. Como siempre, genial. Lo charlaba con Moni, es notable como el formato del evento no decae año a año, ¡siguen siendo bárbaros!

Eso sí, voy a tratar de innovar en lo que es la descripción del mismo, escaparme de hacer una cronología, y orientar más el relato a las situaciones.


Llegando y saliendo

Los viajes bien. Como el año pasado, me quedé hasta "cerrar el evento", y también como el año pasado, luego de vaciar el lugar, entregar la llave y eso, nos quedamos algunos tomando unas cervezas en el bar del lugar, hasta que íbamos partiendo en función del horario de bondi de cada uno.

La diferencia estuvo en la llegada, ya que este año no tuvimos al Joven Ocupado en la Accesibilidad y Conectividad (JOAC), así que tuvimos que armar toda la infraestructura de red sin saber demasiado. Viajé con Nico Demarchi, así que al llegar nos pusimos con eso... y aunque no es rocket science, tampoco es trivial, y estuvimos como tres horas para dejar todo lindo!

Una Antena Sable Laser


Proyectos

El proyecto mío en el que más trabajé fue Encuentro, en parte en esta biblioteca para parsear SWFs que vengo necesitando, pero también porque para este proyecto se anotaron varias personas... ¡y metieron un montón de laburo! Tres branches de Mica Bressan, dos de Nico y uno de Emiliano Dalla Verde Marcozzi, y creo que hay otro más dando vuelta por ahí.

También trabajé en un proyecto nuevo, que arrancó en este PyCamp. Es WeFree, un proyecto para almacenar colaborativamente claves de redes, de manera de hacer que tu computadora o teléfono se conecte automáticamente en todos los lados posibles. Participé todo el primer día, en el diseño general y luego armé la interfaz gráfica para la compu (no toda, pero sí la base, dejando algo usable).

Algo en lo que también trabajé desde cero, pero que no sé si se puede calificar como proyecto, fue algo así como la "búsqueda del testrunner perfecto", que describí en este post. Con la ayuda de Martín Gaitán atacamos como base a nose, y le fuimos agregando plugins y probándolos. El experimento fue un éxito, logramos todo lo que queríamos, ya voy a poner un post acá explicando bien el detalle.

Hubo un proyecto que llevé pero en el que yo no trabajé, que fue Linkode, pero Seba Alvarez estuvo haciendo cosas copadas con la interfaz, me tiene que mandar el código.

Finalmente, arranqué ayudando a un par de chicos a migrar código a Python 3, pero no hicimos mucho de eso (aunque aprendimos algunos detalles interesantes).

Laburando en Encuentro con Nico, Mica y Emi (que sacó la foto)


Las noches

Sólo tres, porque el último día uno viaja, pero las aprovechamos a full :)... la gente se va a dormir sorprendentemente tarde luego de lo arduo que son los días. Bah, más sorprendente es que muchos al otro día nos levantamos temprano :p

La primer noche jugué a un juego que no conocía, el Munchkin, ¡y gané!. Está bueno el juego, pero es uno de esos que tenés que leer mil cartitas, entonces las primeras diez veces que jugás se hace un poco lento.

El sábado fue la reunión de PyAr, y después charlé con gente y programé algo, no jugué a nada.

La tercer noche fue doble... Munchkin primero (ganó Matías), y luego jugamos al Carrera de Mente. Hacía como 15 años que no jugaba un Carrera de Mente, no me acordaba que fuese tan divertido! Nos reimos mucho.

Carrera de Mente


Notas de color

Este año Alecu no pudo venir... y Diego Sarmentero se le ocurrió la idea de nombrarlo Lider Inspiracional, y mandó a imprimir dos cuadros, uno para tenerlo durante el día, y otro para tenerlo luego de las cenas.

A nivel de "actividades al aire libre", este año volvimos a repetir la caminata del año pasado hasta el río (fuimos un grupito de unos 10), y también hice paddle con Hugo Ruscitti, Emilio Ramirez y Hernán Lozano. ¡Jugamos un montón! Bah, menos de dos horas, pero nos arreglamos para meter dos partidos (cinco sets rápidos).

También hicimos una key signing party, y Juanjo Ciarlante nos charló un poco de seguridad y buenas costumbres.

Todos


Conclusión

Bien simple, lo afirmo una vez más: ¡PyCamp es el mejor evento del año! (todas las fotos acá).

Read more
facundo

Corriendo tests


En la vida del programador hay una tarea que lleva bastante tiempo, y es la de correr tests, ya sean "unit tests" (pruebas unitarias) o "integration tests" (pruebas donde se hacen interactuar subsistemas entre sí).

Es cierto, no todos los proyectos tienen tests, pero deberían. ¡Y son un vicio! Una vez que los probaste, querés pruebas en todos los proyectos. Pero claro, a los tests hay que correrlos, y hay muchas maneras de hacerlo.

La verdad es que la estructura de los tests es siempre la misma (o casi siempre), obviamente hablando de proyectos en Python, pero la forma de correrlos, y especialmente la forma de presentar los resultados, varía mucho de un corredor de tests a otros.

A lo largo de años he probado distintos, y debo decir que ninguno cumple 100% con lo que a mi me gustaría tener en el test runner ideal. Por otro lado, seguramente alguno (como nosetests, por ejemplo), cumpla gran porcentaje de lo que quiero, es cuestión de lograr lo que falta.

Acá está la listita de las cosas que cumpliría mi test runner soñado. Propuse un proyecto en el PyCamp de este mes para laburar en esto (obviamente no escribir algo desde cero, sino lograr el objetivo con el menor esfuerzo posible).

Le puse un número a cada ítem para que sea más fácil referenciar en cualquier discusión:

01. Debería soportar que le pase un directorio (default a '.') y que descubra todo ahí y para abajo:

        $ <testrunner> project/tests/
        $ <testrunner>

02. Debería soportar que le pase un archivo, y que corra sólo los tests de ese archivo:

        $ <testrunner> project/tests/test_stuff.py

03. Debería soportar que le pase "paths de import de Python", y que corra sólo tests de ese paquete, módulo, clase, o lo que corresponda:

        $ <testrunner> project.tests
        $ <testrunner> project.tests.test_stuff
        $ <testrunner> project.tests.test_stuff.StuffTestCase
        $ <testrunner> project.tests.test_stuff.StuffTestCase.test_feature

04. Debería poder pasarle una regex para que corra sólo lo que re.search() encuentra en el path completo del método:

        $ <testrunner> project/tests/ --search feature
            correría:
                test_feature
                test_feature_1
                test_feature_2
            no correría:
                test_crash

        $ <testrunner> project/tests/ --search feature$
            correría:
                test_feature
            no correría:
                test_feature_1
                test_feature_2
                test_crash

05. Debería poder decirle que pare de correr los tests al encontrar el primer error o falla.

06. Debería poder indicarle que mida los tiempos de cada test (y al final que presente un reporte con los N tests que más tardaron).

07. Debería mostrar los resultados usando los nombres de paquete/módulo/clase/método, en una jerarquía de árbol o en la misma linea:

        $ <testrunner> project/tests/test_stuff.py
        project.tests.test_stuff
          StuffTestCase
            test_feature_1                        OK
            test_feature_2                      FAIL
          OtherStuffTestCase
            test_feature_A                        OK

        $ <testrunner> project/tests/test_stuff.py
        OK    project.tests.test_stuff.StuffTestCase.test_feature_1
        FAIL  project.tests.test_stuff.StuffTestCase.test_feature_2
        OK    project.tests.test_stuff.OtherStuffTestCase.test_feature_A

    De cualquier manera, esto no afecta el órden de ejecución de las pruebas (secuencial, aleatoria, etc), sólo es cómo mostrar los resultados.

08. Los OKs deberían ser verdes; ERRORs y FAILs deberían ser rojos.

09. Los OKs/FAILs/ERRORs para cada prueba, en el listado, deberían estar alineados verticalmente.

10. No debería capturar stdout/stderr.

11. En el reporte final (luego del listado que va mostrando al ejecutar todo), debería mostrar el path completo del test que falla (o de los tests que fallan), junto con el (los) errores, de manera que si uno copia y pega ese path, sirva para correr ese único test.

Read more
facundo

Ya tenemos Encuentro 1.1


Como estoy seguro que ya sabrán de memoria, ;), Encuentro es un simple programa que permite buscar, descargar y ver contenido del Canal Encuentro, Paka Paka, BACUA, Educ.ar y otros.

Acabo de liberar la versión 1.1, que principalmente vuelve a permitir que el programa se autentique luego de unos cambios en el backend de Conectate, pero también tiene muchos bugs solucionados a nivel de manejar errores en las descargas, y también mejoras en la interfaz.

¡Es fácil probarlo! Tenemos instaladores para Debian/Ubuntu, para Windows, en Arch sólo hacen yaourt -S encuentro, e incluso, desde cualquier lado, pueden instalarlo desde PyPI (sudo easy_install encuentro) o directamente usando el tarball.

Todos los detalles, como siempre, en la página oficial. ¡Que lo disfruten!

Read more
facundo


Hola!!

Charlando en el viaje a/desde la PyCon de Rosario, surgió la idea de armar un Circo Errante (flying circus, la referencia es obvia) con el objetivo de acercar PyAr a las Universidades de una forma distinta a las actuales.

Hoy por hoy, el principal contacto de PyAr con las Universidades es de gente que arma PyDays en ese ámbito. Esto, normalmente, sucede en las Universidades con carreras afines a la programación. Y el contenido y dinámica de estos PyDays están pensados en función de ese público.

La idea es cambiar eso. Y llegar desde PyAr a Universidades con las cuales normalmente no tenemos mucho contacto. Ejemplo de esto son las carreras de derecho, sociología, matemática, psicología, astronomía, ingenierías no informáticas, etc. Estas son carreras en las que los profesionales podrían hacer un buen uso de Python como herramienta, donde no les interesa tanto  el razonamiento "quiero hacer un programa que haga algo", sino más bien "necesito hacer algo y un programa podría ser una herramienta, aparte del excel y la calculadora que es lo que estoy usando ahora".

Más en detalle, lo que se nos ocurrió es armar una especie de presentación basada en ejemplos de distintas especialidades. O sea, cómo usar Python para solucionar tal problema en astronomía, cómo usarlo para encontrar tal resultado en sociología, o cómo aprovecharlo para mejorar un análisis en ingeniería en alimentos. Una presentación semigenérica, de 30-40 minutos, que sea como la punta de lanza: si les gusta la idea luego se puede mostrar Python más formalmente; en el peor de los casos se quedarán sólo con conocer la herramienta y tener idea de qué se trata, que no está tan mal.  Obviamente, la idea es armar una presentación que todos podamos usar, no que cada uno arme la suya.

Para organizar esto, armé una página en el wiki con (por ahora) tres secciones: una de ejemplos, para ir juntando ejemplos piolas en los cuales basar la presentación, una de ideas para folletería/merchandising (ver más abajo) y otra de gente interesada en dar estas charlas y la "zona de cobertura".

Luego, habría que ir buscando contactos en las Universidades, para poder charlar con alguien que nos dé un aula con un proyector y que organice internamente para que vaya gente a la presentación.

Con respecto a la folletería/merchandising, tenemos que pensar en algo para llevar a estas reuniones: algo que les muestre el uso de la herramienta más allá del lenguaje (ejemplo: no mostrar como se escribe un for, sino lo fácil que es hacer una normalización de un conjunto de datos). Algo que se lleven los asistentes con ellos, para poder verlo más tarde, y tener el contacto con PyAr para poder venir por más info.

¿Qué les parece?

Read more
facundo


Aparecieron muy cerca en el tiempo dos necesidades muy parecidas: hacer certificados de asistencia para PyCon Argentina 2013, y hacer los certificados para mi curso de Python.

Así nació certg, un generador de certificados, que a la vez es simple, versátil, y útil. El proceso para usarlo es simple:

  1. Armás un .SVG (con Inkscape, por ejemplo), poniendole todo el arte que quieras para que el certificado quede lindo. Pero no lo hacés específico a nadie, sino que dejás escrito variables que se van a reemplazar, como {{nombre}} o {{direccion}} o lo que te guste
  2. Armás un archivo de configuración, donde ponés el nombre del .SVG que creaste, qué variable de las que elegiste es única (se usa luego), y luego una lista de grupos de variables, donde a partir de cada grupo se va a generar un certificado.
  3. Ejecutás el programita en Python, pasándole la configuración que armaste. El programita va a leer el .SVG, y por cada grupo en la config, reemplazar esos valores, y generar un certificado (en PDF) usando el nombre unívoco que indicaste.

La verdad, quedó piola: no es dificil de usar, y es lo suficientemente flexible para las distintas necesidades que tuve. Este es como quedó mi certificado de la PyCon:

Fuí a la PyCon!
El proyecto, con ejemplos y todo, acá.

Read more
facundo

PyCon Argentina 2013


Salimos el miércoles tarde (porque yo tenía el curso de Python en el centro), en auto, Julia, Marcos y yo. Llegamos a Rosario, al hostel, a la una y cuarto de la mañana, derechito a dormir. Esperábamos no molestar a Mariano y Claudio, con los que compartíamos habitación, y efectivamente fue así porque ellos todavía no se habían acostado :p.

Al otro día nos levantamos bien tempranito, porque yo tenía que llevar los tutoriales y posavasos para que se repartieran cuando la gente se registraba al evento. Llegamos con tiempo, tanto que luego de entregar los materiales, saludar y etc, nos quedamos tomando mate y desayunando a la vera del rio, durante como media hora...

Y finalmente arrancó la conferencia.  El primer bloque de charlas me gustó entero, y mucho, lo cual hace rato que no me pasaba en una PyCon. Fuí primero a "Recorriendo Nodos con Python" (de Martín Alderete y alguien más que el sitio de PyCon no me deja ver quién es :( ), después a "Aprendizaje automático con scikit-learn" (de Rafa Carrascosa), y finalmente a "Monitoreo de procesos industriales utilizando Python" (de Joac).

Después salimos a almorzar, lo cual es siempre una aventura en este tipo de eventos (imagínense centenares de personas atacando de repente los locales cercanos). Pero teníamos una hora y media, así que no hubo mayor inconveniente que la quemazón generalizada de caras y brazos porque el sol estaba fuerte y nadie se avivó :/.

A la tarde ví una charla que no me gustó tanto, y luego dí Bindings, default mutable arguments, y otros qu... detalles. Luego de eso, algo de pasillo, las lightning talks (bien en general), y luego la plenaria.

La charla plenaria la dió Robert Lefkowitz, sobre "Literacy, Programming, and Open Source", una de las mejores plenarias que vi en la vida. Estuvo genial, sinceramente, tengo ganas de que suban el video a algún lado y agregarle subtítulos en castellano, para que la pueda disfrutar más gente.

Robert, al final de la charla, hizo una invitación general a ir a tomar algo. Pero Emiliano tenía pre-armado unos pescados a la parrilla, así que subimos la apuesta y armamos (previa recolección de dinero) un asado para treinta y pico en un club cercano. Fue una corrida ir a la carnicería, al supermercado por bebidas, pan y etcéteras, y por la casa de Emi para buscar algunos elementos generales, mientras Juan Pablo y Marcos arrancaban con el fuego en el club. Al final se asaron un dorado y un sábalo enormes ambos, más dos bondiolas de cerdo y un pedazote de bife de chorizo. Todo regado con fernet, cerveza, vino, y mucha, mucha charla copada.

La foto grupal

El viernes nos levantamos tarde, tanto que desayunamos en el hostel, y llegamos a la conferencia un rato antes que diera mi segunda charla, Las perlas de Python 3 (¡un estreno!). Luego estuve en un par de charlas, pero la que más me gustó fue la de Alecu, "Juegos electromecánicos con Arduino", tengo muchas ganas de arrancar con algún proyecto de electrónica o electromecánica!

Al final del día vinieron más lightning talks, y la plenaria de Claudo Freire sobre Paralelismo. Luego sorteos, palabras, saludos, y todos los etcéteras del cierre de la conferencia.

Esa noche era la cena "de invitados", donde volvimos a repetir asado (pero esta vez en un restaurant muy bonito), y luego varios nos fuimos a reventar la noche (not really) a una fiesta del CEC.

En fin, pasó otra PyCon Argentina, la cual me gustó mucho mucho. Felicitaciones a todos los que trabajaron para que salga tan lindo todo!  Yo no llevé cámara, pero hay muchas fotos acá, acá, y acá.

Read more
facundo


Porque PyAr no descansa, acabamos de tener la PyCon y ya salimos con el armado del PyCamp del año que viene. Este es un llamado a co-organizadores, locales (o cercanos) a sitios posibles de hacerse el evento.

La idea es hacer el PyCamp del 1 al 4 de Marzo, del 21 al 24 de Marzo, o del 22 al 25 de Marzo.

Yo lo voy a estar coordinando en general, pero la idea es que encontremos el mejor venue posible, buscando de a varios. Es lo mismo que hicimos el año pasado.

¿Cómo es la dinámica? si alguien sabe de un lugar en el que se podría hacer el PyCamp, que vaya o llame y averigüe. Hay que recabar varios datos:

  • Formas de llegar
  • Qué onda el lugar
  • Qué onda las habitaciones
  • Qué onda la comida
  • Tres puntos a favor
  • Tres puntos en contra
  • Disponibilidad
  • Precio

Algo piola para revisar es la página que les acabo de pasar sobre posibles sedes, para tener una idea del tipo de data que hay que juntar. Luego me contactan (por privado) y vamos definiendo todo para dejar el lugar listo para la votación.

¡Gracias! :)

Read more
facundo

Curso de Python confirmado


Estoy muy contento porque el primer Curso Abierto de Python que armé ya está 100% confirmado, :).

El curso es de 18 horas en total, de 19 a 22, los días Miércoles 25 de Septiembre, 2 y 9 de Octubre, saltamos un miércoles, 23 y 30 de Octubre y 6 de Noviembre.

Quedan sólo un par de plazas disponibles, si quieren anotarse tienen todos los datos en la paginita que armé. Una novedad es que ahora también se puede pagar por DineroMail: no me conviene demasiado, pero permite pagar con tarjeta de crédito, RapiPago, PagoFácil, etc., así que supongo que podría ser cómodo para alguien en algunos casos...

Read more
facundo

PyDay en Junín 2013


Este fin de semana se sucedió otro evento en Junín. Organizado por Juan Rodriguez Monti, con la colaboración de varios de los chicos de siempre, y con el apoyo indiscutible de la facultad, armaron otro PyDay que salió muy muy bien.

No estuve en todas las charlas, pero fui a varias; las que más me gustaron fueron la de Alecu "Controlando Python desde Arduino", la de Juanjo Ciarlante "Software Libre en las nubes", y la de Daniel Coletti "Ser emprendedor con Software Libre".

Alecu en su charla

Yo dí una charla nueva, "Emulando paralelismo de forma asincrónica", una charla bastante complicada pero que salió bastante bien. Eso sí, tardé una hora en darla, así que le tengo que pegar una revisada para ajustarla y simplificarla un poco.

Además, fueeeeeeeera de programa, dí un tallercito de "Introducción a Python" el día anterior en la Universidad, pero la asistencia fue muy baja, :(. Por otro lado, estuve jugando un poco al tenis el domingo a la mañana, así que eso compensó, :D.

En fin. Ir a los eventos de Junín siempre está bueno, y los disfruto bastante.

Read more
facundo


Finalmente me decidí, y armé un curso grupal para aquellos que quieren aprender Python, no como parte de un grupo cerrado para una empresa o institución, sino abierto al público en general.

Será un Curso Introductorio a Python, apuntado a aquellos que no saben nada de este lenguaje, o saben algo pero quieren profundizar o formalizar conocimientos.

El nivel es introductorio, lo que significa que se van a ver muchos conceptos del lenguaje de manera profunda, pero no se tocarán temas avanzados ni satélites a lo que es Python en sí, con la intención que el asistente gane sólidos conocimientos que luego le permitan explorar el resto a su gusto.  Se necesita tener conocimientos previos de programación (pero no hace falta ser un programador avanzado).  En detalle, el contenido del curso versará sobre los siguientes ítems:

  • Introducción: ¿Qué es Python?; Primeros pasos; Recursos
  • Tipos de Datos: Haciendo números, y más números; Cadenas de texto; Tuplas y listas; Conjuntos; Diccionarios
  • Controles de flujo: if/elif/else; loops while y for; Excepciones
  • Encapsulando código: Funciones; Clases; Módulos; Espacios de nombres
  • Otros temas: Archivos; Trabajando en Red; Conexión con Bases de Datos

El formato del curso será presencial, en un ambiente "tipo aula" con pizarrón y proyector, pero no basado en filminas, sino totalmente dinámico y adaptativo.  Se hace un foco especial en la interacción profesor-asistente, de forma de ir resolviendo las dudas de todos y lograr un aprendizaje más profundo en el mismo tiempo.  En función de esto también se limita el cupo, con una cantidad máxima de asistentes de alrededor de diez personas.

Como parte del curso se entregará un certificado de asistencia al mismo, basado en una evaluación sobre un proyecto personal o grupal, totalmente a decisión de el/la/los/las participante(s).  Este proyecto se arranca durante el curso, pero puede continuar después del mismo, bajo mi supervisión/tutoría (sin costo extra).  También se entregará documentación de forma digital.  No se necesita asistir al curso con computadoras, pero pueden traer laptops/netbooks si lo desean (van a disponer de conexión a internet via wifi y conexión eléctrica).

El curso es de 18 horas en total (tres horas por clase, un día a la semana, seis semanas), de 19 a 22.  En esta primera oportunidad se hará el curso en un lugar céntrico de la Ciudad de Buenos Aires, los días Miércoles 25 de Septiembre, 2 y 9 de Octubre, saltamos un miércoles, 23 y 30 de Octubre y 6 de Noviembre.

El costo total del curso será de $920; es necesario abonar al menos el 50% para reservar la posición (recuerden que, como indicaba arriba, hay un máximo de lugares disponibles), abonando el saldo restante el primer día de clases.  El curso comienza con un cupo mínimo de 4 alumnos, a confirmar como máximo los primeros días de Septiembre. En el caso de no formarse el grupo, se postergará el inicio o se reintegrará el dinero completo de la seña.

Para reservar, entonces, deberán depositar o transferir el dinero a mi cuenta del banco, para lo cual coordinamos por mail. Si se les complica esta manera de pago, lo charlamos.

Bueno, creo que cubrí la mayoría de los puntos.  Si tienen alguna duda, pueden preguntar por acá, o en privado al mail, sin ningún problema.

Read more
facundo


Bueno, todos los saben, porque no sólo tenemos una página de los proyectos que íbamos a encarar, sino que también armamos un video el último día con todo lo que se hizo durante el PyCamp!




Para completar el ciclo, pueden ver fotos del evento acá, acá, acá y acá.

Read more
facundo

Enjuewemela modo PyAr


No es la primera vez que les comento algo sobre Enjuewemela, mi jueguito similar a los populares Bejeweled o Diamond Mine, que se basa en alinear 3 o más gemas, tanto verticalmente como horizontalmente, intercambiando gemas adyacentes.

Pero quizás este post sea el último que hago sobre el juego. Y es que me aburrí de pulirle detalles, tratar de hacerlo lindo, jugable, divertido... son cosas que llevan mucho tiempo, no tan evidentes al usarlo... y nada, me aburrió.

Para "despedirme", le implementé algo que tenía en mente hace rato y que quería que esté: un "modo Python Argentina", donde en vez de las piezas usuales, hay personajes de juegos hechos por el grupo.

Enjuewemela modo PyAr

Lo consiguen en el lugar de siempre :)

Read more