Juanjo Conti: Audio de la entrevista en Recreo Diario sobre mi artículo sobre el escrutinio en las elecciones Santa Fe 2015

   Publicado:

Luego de publicar el post Jugando con los datos del escrutinio provisorio me contactaron de radio Continental Santa Fe para participar del programa Recreo Diario contando lo que hice.

Luego de mi entrevista siguió una con Pepito Cybrian y Cecilia Milone. Me saqué una foto con ellos y la usé para ilustrar el audio.

Facundo Batista: Releases por dos: Encuentro y fades

   Publicado:


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.

Juanjo Conti: Jugando con los datos del escrutinio provisorio

   Publicado:

Anoche estuve jugando un poco con los datos (publicados) del escrutinio provisorio de las elecciones a gobernador en la provincia de Santa Fe.

La misma noche de las elecciones, cuando los resultados provisorios no lo favorecieron, Miguel del Sel y los partidarios del PRO en general empezaron a instalar una sospecha de fraude. No tardaron en hacerse eco en las redes sociales distinto tipo de usuarios: obsecuentes, tira bombas, paranoicos, ingenuos.

En distintos medios, Del Sel mostró como “prueba” del fraude errores producidos al realizar la carga manual de datos durante el escrutinio provisorio, es decir durante el proceso humano de mirar una planilla completada a mano e ingresar (tipeando) los valores en el sistema.

De los tipos de errores, voy a tomar uno, el primero que mostró (1, 2): el candidato figura con 0 votos en el sitio web, pero en la planilla tiene X votos.

Mi objetivo es ver cuantas veces se da este error y como afecta a los distintos candidatos.

Programé un pequeño script que hace lo siguiente:

  1. Baja el archivo XML con los datos de la categoría Gobernador correspondiente a cada mesa.
  2. Lee los archivos XML para obtener, para cada mesa, la cantidad de votos de los 3 partidos dominantes.
  3. Encuentra las mesas en las que cada partido tiene 0 votos.
    1. Si en una mesa los 3 candidatos tienen 0 votos, se asume que se trata de una mesa con telegrama desestimado.

Luego revisé los archivos PDF de los telegramas de estas mesas. Arribé a lo siguiente:

Partido Nº de mesa Votos
PRO 1725 0
PRO 270 73
PRO 5351 0 *
Total votos faltantes PRO 73
FPV 1478 0
FPV 7591 0
FPV 5545 0
FPV 4912 0
FPV 7601 0
FPV 1845 0
FPV 4950 0
FPV 4729 85
FPV 6555 0
FPV 6333 0 *
Total votos faltantes FPV 85
FPCS 6852 0 *
FPCS 1478 0
FPCS 134 0
FPCS 7591 0
FPCS 5485 82
FPCS 4501 75
FPCS 6555 0
FPCS 1845 0
Total votos faltantes FPCS 157
* la casilla estaba en blanco en el telegrama

Se pueden analizar otros tipos de errores en la carga, pero con uno me alcanza para demostrar mi punto: esto no es prueba ni de fraude ni del accionar de un cracker, solo errores humanos distribuidos uniformemente.

Es decir, este tipo de error ocurrió una vez para el PRO (a quien se le deben contabilizar 73 votos más), una vez para el FPV (a quien se le deben contabilizar 85 votos más) y 2 veces para el FPCS (a quien se le deben contabilizar 157 votos más).

Los datos y las herramientas están disponibles para periodistas y entusiastas que quieran seguir explorando el espectro de los votos mientras el tribunal sigue contando.

Finalmente, como esto se puso muy serio, cierro con un poco de humor, uno de los mejores Eameos:

MI-DA-CHIActualización: audio disponible.

 

Juanjo Conti: Video de mi charla Ruby para programadores Python

   Publicado:

Hoy encontré que los organizadores de PyConAr 2014 habían subido el video de mi charla Ruby para programadores Python. Se que subir todos los videos de una conferencia lleva tiempo y es mucho trabajo. Muchas gracias!

Marcos Dione: ayrton-0.4.4

   Publicado:

I forgot to mention: I did a couple of ayrton releases, one more than a month ago and another a couple of days ago. One thing to notice is that even when 0.4.4 introduces an incompatible change (source() is no more), I didn't bump the minor or major version, as the level of usage is practically null. Here's the combined changelog:

  • source() is out. use python's import system.
  • Support executing foo.py().
  • Let commands handle SIGPIE and SIGINT. Python does funky things to them.
  • for line in foo(): ... forces Capture'ing the output.
  • Fix remote() a little. The API stills sucks.
  • Fix remote() tests.

Get it on github or pypi!


python ayrton

Facundo Batista: Búsqueda por prefijos tolerante a errores

   Publicado:


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á.

Mariano Draghi (cHagHi): Rearrancando...

   Publicado:
Restart, human!

Restart, human! por Anders Sandberg

Nueva casa, nueva tecnología, nuevo formato. Todo es nuevo. Menos el contenido, que está abandonado hace casi un año. Y que ya venía semi abandonado antes de eso.

Ya ni los ¿clásicos? posts sobre los viajes estoy haciendo. Hay por lo menos dos que no están acá. Y es una pena. Esto nunca fue muy popular, ni tuvo muchos lectores, pero siempre fue un buen ejercicio esto de escribir, y más de una vez fue interesante en lo personal volver para atrás y releer algunas cosas. Y eso que he escrito cada pelotudez... :p Pero nada, las pelotudeces también son interesantes. Es interesante ver como uno cambia, o como el mundo cambia, y contrastar lo que pensaba, sentía o vivía mi "yo" de hace X tiempo con mi "yo" actual.

Y cada tanto, cada muy tanto, hasta llegué a escribir algo que le sirvió a alguien. Y eso también está bueno.

¿Y por qué dejé de hacerlo? No se muy bien, pero en general siento que la culpa es de Facebook y Twitter. Es mucho más fácil escribir una gilada de 140 caracteres en Twitter o un par de párrafos en Facebook que ponerlo en un blog.


Para motivarme un poco, porque uno ante todo es nerd (?), decidí demoler el blog anterior y armarlo otra vez. Estoy usando Nikola, mascota de Roberto Alsina, que resulta que además de recomendar muy buenos libros, desarrolla muy buenos generadores de sitios estáticos ;-) (¡gracias Roberto!)

La principal ventaja para mi de haber migrado a Nikola es que ahora el contenido del blog está en archivos de texto, en un formato que es legible por un humano incluso sin la magia que lo transforma en páginas web.

La segunda ventaja es que está desarrollado en Python, que es un lenguaje de programación que me gusta hasta el infinito y más allá más que PHP (que es lo que usa WordPress), y que me resulta mucho más fácil de entender cuando necesito tocar algo, o agregar funcionalidad, o hacer modificaciones.

La tercer ventaja es que Nikola es minimalista. No tiene las decenas de características que tiene WordPress, ni sus miles y miles de plugins. Tiene lo que necesito. Es más simple. Y cuando uno no necesita la complejidad extra, "simple es mejor que complejo" [*].

Migrar de WordPress a Nikola es algo que es más o menos automático en un 75%, pero si sos obse como yo y realmente querés emprolijar las cosas, requiere luego una serie de ajustes que dependen de cuan horrible sea el formato heredado de WordPress. Para algunos de esos ajustes fui haciendo reemplazos semi-automáticos con distintas herramientas, para otros tuve que ir a mano (y para esos casos, que no fueron taaaaantos, agradecí no haber estado escribiendo con más frecuencia :p). En todo este proceso me vino de 10 la experiencia previa de Humitos.

Todavía tengo cosas que ajustar, como los tags y categorías, o hacer que el sitio tenga un look un poco menos genérico. Y otro gran tema es encontrar un mecanismo cómodo para poder publicar desde el celu/tablet, o una compu desde la que no tenga acceso al servidor. Esto es medio una desventaja común a todos los generadores de sitios estáticos. Hay varias opciones, pero todas requieren algún trabajillo extra, todas tienen algún pero, y va a requerir un poco más de tiempo evaluar que es lo que más me conviene.

Pero la base está...


Para terminar el revoleo, el blog no está más alojado en un hosting compartido. Me llevé todo a un VPS. Y eso también es toda una novedad, y en parte un desafío, porque tengo que administrar absolutamente todo yo. Es un arma de doble filo: puedo hacer lo que quiera en el servidor, y por lo tanto también puedo romper todo. Y tengo que tener un ojo puesto en todo lo que sea configuración, actualizaciones, seguridad, etc.

Al pasar a un VPS hay una cosa que estaba seguro que no quería administrar: las cuentas de correo de mi dominio. Administrar un servidor de correo propio es, para mi, "ligas mayores" (para hacerlo razonablemente bien), así que tuve que encontrar una solución, preferentemente gratuita. En una época la respuesta obvia a esto era Google Apps, pero no es más gratis. Por recomendación de Roberto (que además de recomendar buenos libros, y de desarrollar buenos generadores de sitios estáticos, hace buenas recomendaciones de servicios en la nube), el correo de mi dominio quedó en Zoho, que ofrece un plan gratuito que me alcanza y sobra.

Y acá estamos. Todo nuevito. Ahora solo falta escribir...


[*]El Zen de Python

Martín Gaitán: Curso de Python para ñoños

   Publicado:

¡Los cupos irán a sorteo! Anotate. Si no entrás para en esta edición, quedás anotado para la próxima que será muy pronto.

La demanda nos desbordó. En menos de 2 dias tenemos inscriptos para llenar dos veces el laboratorio que tenemos disponible! Algunos ya están averiguando la disponibilidad del Estadio Kempes para hacer el próximo.

Como recién hoy (martes 7 de abril) se realizó la difusión oficial desde FaMAF, la decisión de los organizadores es permitir la inscripción de todos los interesados y hacer un sorteo de las 25 plazas aranceladas y otro para las 15 plazas gratuitas reservadas para estudiantes de grado de FaMAF.

La justificación de un sorteo en vez de tomar el orden de inscripción la dió el Dr. Nicolás Wolovick, que junto al Dr. Pedro Pury fueron los gestores para que el curso se oficializara, con un argumento democráticamente ñoño:

Estar conectado 24/7 por 3G, recibir el tweet, e inscribirse, no es justo, es una condición de posibilidad que no todos tienen. La distribución uniforme es la que mayor entropía tiene :)

Si estás interesado, es importante que te inscribas a través del formulario. Así tendremos una lista bien grande de "argumentos" para reeditar el curso lo más pronto posible.

Otra posibilidad es que averigües hagas lobby en tu empresa o laboratorio sobre la posibilidad de realizar el curso in house y, si tienen interés, lo charlamos.


/images/Newsletter4-Banner_20120705_12-44-50-800.jpg

A partir del 29 de abril voy a dar el curso Introducción a Python para ciencias e ingenierías en la Facultad de Matemática, Astronomía y Física (FaMAF) de la Universidad Nacional de Córdoba.

Este curso es una versión revisada y extendida del que dí en la ScipyCon Argentina 2014 y durará 8 clases de 2hs cada una. Será los miércoles de 18hs a 20hs en el laboratorio de computación de la facultad. No hace falta contar con equipo propio y el único pre-requisito es tener nociones básicas de programación en cualquier lenguaje.

El costo del curso es $400. Hay becas para estudiantes de grado de FaMAF.

Acá está el formulario de pre-inscripción (LOS CUPOS IRAN A SORTEO).

El curso está reconocido como Curso de Extensión de FaMAF (Res. HCD 107/2015) y se entregarán certificados oficiales a quienes completen asistencia y participación.

Atención Los cupos son muy limitados!

Introducción

En las últimas décadas la computación se ha convertido en un pilar de la ingeniería y la investigación científica. En la mayoría de las áreas, el trabajo computacional es un complemento fundamental de la experimentación tradicional y de la teoría, y cada vez más publicaciones involucran cálculos numéricos, simulaciones y modelado computacional.

Frecuentemente, la tarea de los profesionales involucra el uso de aplicaciones específicas que requieren un gran trabajo de procesamiento de los datos de entrada y un post-procesamiento de los resultados utilizando otras herramientas.

Otras veces se desarrolla software ad hoc en lenguajes de programación tradicionales en la ciencia como Fortran, muy limitados para el pre-procesamiento y la visualización de datos y cuyo desarrollo se torna improductivo por los tiempos inherentes al ciclo de edición, compilación, ejecución y depuración.

Existen nuevos entornos y lenguajes de programación que permiten un flujo de trabajo dinámico e interactivo, mucho más armónico y útil en el contexto de la "experimentación computacional". Un entorno interactivo permite a los científicos e ingenieros manipular datos, probar algoritmos y visualizar resultados de una manera integrada y versátil, sin limitaciones impuestas por una interfaz de usuario ni la laboriosa y frágil tarea de hacer interactuar distintos sistemas.

Este curso brindará una introducción al lenguaje de programación Python y a las herramientas fundamentales del "ecosistema científico" (IPython, Numpy, Matplotlib, Scipy, Sympy, entre otros) que conforman un entorno de programación interactivo de vanguardia, simple, libre, gratuito y multiplataforma.

Sobre el docente

Martín Gaitán es Ingeniero en Computación por la Universidad Nacional de Córdoba (2011). Socio fundador de Phasety, emprendimiento incubado en la UNC que desarrolla software de simulación especializado para la industria del petróleo y el gas. Pythonista desde hace casi una década, es especialista en el framework web Django y cree entender las necesidades del software científico. Es frecuente orador en eventos de software libre. Hincha de Boca y fundamentalista del locro. Más información en su blog.

Programa

Clase 1:
Instalación de entorno para Python en Windows/Linux. Modos de usar Python. Anaconda. Introducción a Ipython Notebook Tipos de datos: enteros, floats, complejos, strings. Estructuras de datos: listas, tuplas, diccionarios, conjuntos. Packing, indexing, slicing, etc. Conceptos de mutabilidad/inmutabilidad, secuencia, iterador Control de flujo: if, for, while, manejo de excepciones.
Clase 2:
Funciones: definición, argumentos posicionales y nominales. Sentencia yield. Funciones incorporadas: zip, range, enumerate, etc. Manejo de I/O: lectura y escritura de archivos.
Clase 3:
Estructura de proyectos: módulos, paquetes, importación. Paseo por la biblioteca estandar: math, CSV, json, pickle Conceptos básicos de programacion orientada a objetos. Introduccion a Matplotlib y Numpy.
Clase 4:
Numpy: introducción al objeto Array. Slicing extendido, métodos y funciones importantes, importación de datos. Aplicación de Numpy en algebra lineal. Resolución de sistemas de ecuaciones lineales. Matplotlib: generación de gráficos cartesianos continuos, puntos, histogramas.
Clase 5:
Vectorización de funciones con Numpy. Matplotlib avanzado: API orientada a objetos. Manipulación del formato y apariencia. Gráficos 3D, otros tipos de gráficos 2D. Introducción a Scipy: algoritmos para estadística, interpolación, regresión lineal, integración, etc.
Clase 6:
Python como "lenguaje pegamento". Integración con Fortran a través de F2Py. Herramienta "fortran-magic". Paso de argumentos escalares, arrays, output implícito, manipulación de signatura. Introducción a otras herramientas de optimización: Cython y Numba.
Clase 7:
Sympy: Python para matemática simbólica.
Clase 8:
Otras herramientas del "ecosistema científico" de Python. Entornos virtuales. Instalación de otros paquetes. Widgets de IPython Notebook. Exportación de documentos.

Facundo Batista: Metaclasses in Python, the easy way (a real life example)

   Publicado:


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 :)

Facundo Batista: Novedades pythónicas: fades, CDPedia, Django y curso

   Publicado:


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, :)

Share