Roberto Alsina: rst2pdf 0.13 released!
I've just uploaded the 0.13 version of rst2pdf, a tool to convert reStructured text to PDF using Reportlab to http://rst2pdf.googlecode.com
rst2pdf supports the full reSt syntax, works as a sphinx extension, and has many extras like limited support for TeX-less math, SVG images, embedding fragments from PDF documents, True Type font embedding, and much more.
This is a major version, and has lots of improvements over 0.12.3, including but not limited to:
Facundo Batista: PyCamp 2010
Viernes
En realidad llegamos a Veronica el jueves. Viajamos a la tarde/noche con Alecu, Ricardo y Joac, para llegar, cenar, acostarnos, y levantarnos temprano para armar lo que era energía e internet.
El plan estuvo muy bien, nos levantamos casi a las ocho, desayunamos, y empezamos a armar todo... para cuando empezó a llegar la gente, ya teníamos todo andando.
La mañana estuvo tranquila, charlando de cosas varias mientras iban llegando los participantes, y recién luego de comer arrancamos con la organización del schedule para todos los días:

El primer tema me interesaba (tower defense); no para programarlo, sino para participar en la charla inicial. Las ideas estuvieron muy bien, veamos como evoluciona.
También participé de la segunda sesión (hacer un server XMPP en Twisted), pero llegamos a la conclusión que no tiene sentido ponernos a hacer todo ese trabajo, porque para las funcionalidades locas que quisieramos implementar, es suficiente con hacer un cliente o un componente (y ya hay soporte para eso en Twisted).
Luego me pegué un regio baño, y llegó la hora de la cena. Y con el fin de la comida, pasamos a la parte de juegos.
Como siempre, se armaron distintos grupos jugando a distintas cosas. Yo jugué al Settlers of Catan con Perrito, Robert, y Luciano. Un rato después de que terminamos de jugar (y de que nos habíamos terminado el Legui), llegó Moni con Felipe, que venían de Buenos Aires en el auto de John, así que fuimos a terminar de armar las cosas en la habitación y a dormir, que eran como las dos de la mañana.
Sábado
Por suerte no arrancamos temprano, ya que el desayuno es a las nueve de la mañana, así que me levanté ocho y media, y a las nueve estábamos desayunando con la familia.
Durante la mañana no hice nada específico, más que nada charlas, cargué muchos bugs de Enjuewemela, y le eché algo de laburo a Typus Pocus: nos fuimos de Google Code, ahora estamos en Launchpad, y empecé a darle forma para poder utilizarlo de ejemplo en la clase de empaquetamiento de Luciano (ver más abajo).
A las 13 almorzamos, y luego jugamos a la pelota como media hora (sí, ¡deporte!). Cortamos a las 14 porque arrancaba la sesión de Lalita. Nos juntamos obviamente al aire libre (estabamos la mitad transpirados por el fúbol), y charlamos cosas para hacerle. Me anoté un bug doble (o dos bugs muy parecidos, como quieran), pero antes de empezar a hacer eso me fui a bañar.

Cuando salí encontré que ya había empezado la charla de cocos2d, y me metí para la charla/discusión sobre qué era y cual es el futuro (llegamos a la conclusión de que lo que habría que hacerle a la biblioteca es: mejor manejo de sonido, implementar colisiones, mejor documentación, y bugfixing en general).
La noche pintaba tranqui, porque no habíamos podido armar el fogón entonces no sabíamos que íbamos a hacer con la reunión de PyAr. Pero al final la hicimos, repartimos merchandising que Nati y Matías habían traido de USA, repartimos tutoriales impresos para que lleven a las Universidades, hablamos del PyCon en Argentina pasado y futuro, del recién terminado PyCon USA, de Python y la evolución del lenguaje, de cómo estaba Python en Argentina a nivel laboral, etc. Muchos temas. Y terminó derivando en charlas políticas muy interesantes.
A eso de las dos y media de la mañana, luego de charlar en varios grupos y con ya demasiado vino en sangre, me fuí a dormir.
Domingo
El domingo arranqué con un poco de resaca, pero llegué bien a desayunar.
Durante la mañana estuve trabajando en Typus Pocus, para que esté listo para la clase de la tarde de Luciano Bello sobre empaquetar proyectos para Debian. Esa clase fue muy útil, y recorrimos casi todos los pasos para que se pueda meter el juego en esa distro de Linux (todavía faltan sacarle unos warnings de lintian, ya anunciaré aquí como evoluciona eso).
Luego se hizo un pequeño Bug Day de Python, en la cual muchos chicos aprendieron cómo trabajar en el proyecto de Python en sí, y cómo buscar bugs y proponer soluciones, y hasta se corrigieron un par de cosas!
Durante la tarde, también, se realizó el primer Torneo Universal de Ping Pong Durante Un PyCamp (o más fácil: TUPPDUPC). Yo perdí en cuartos a manos de (o "a paletas de") el que sería el campeón, Nico Echaniz:

Estuvimos también charlando un rato largo sobre el modelo del juego que construiremos durante el próximo PyWeek (el juego más grande del mundo, ¡ya les contaré cómo participar!).
Finalmente, volví a trabajar en la laptop, en el bug doble de Lalita que había comenzado a resolver el día anterior. Y estando ahí trabajando, al lado de Riq, no se bien cómo surgió pero me terminó explicando cómo se usaban matrices para resolver los cambios a imágenes (redimensionarlas, rotarlas, desplazarlas, etc.; lean esto que lo explica bien).
Lunes
Durante la mañana del último día logré corregir los bugs que venía trabajando de Lalita, antes de comer me puse a trabajar en un juego que estoy armando, Enjuewemela, un juego loco con un montón de gemas que tienden a desaparecer siguiendo extrañamente acciones del usuario.
Luego del almuerzo tuvimos una charla entre todos sobre el PyCamp mismo: cómo había sido, que cosas estuvieron mal, cuales bien, qué deberíamos corregir, y hasta terminamos tirando la idea de hacer un segundo PyCamp a continuación de PyCon Argentina 2010, en Córdoba.
Luego de esta charla seguí trabajando en Enjuewemela, hasta que se acabó el tiempo.
Ahí empecé a ordenar todo lo mío y a limpiar un poco los lugares donde habíamos trabajado, armé el auto, y emprendimos el regreso.

Así terminó el tercer PyCamp en Argentina, uno de los eventos de programación más interesantes que conozco, y uno de los que más cumplen a la hora de aprender y divertirse. Todas las fotos, aquí.
Mariano Guerra: nuevo intento de viejo proyecto
queres probar algo nuevo? tenes algun lugar para recomendar? ayudame a cargar datos http://pleinu.appspot.com (consejos/quejas bienvenidas)
esta vez empieza desde lo basico y se arma con tu feedback
para los nionios como yo, esta hecho en python sobre appengine usando tubes*
* http://a-series-of-tubes.appspot.com/ y http://github.com/marianoguerra/tubes
Roberto Alsina: Cómo encontrar un programador que sepa programar.
Si todavía no leíste Why Can't Programmers.. Program? de Jeff Atwood andá, leélo y volvé.
¿Ya te asustaste? No lo hagas, el problema es el proceso de contratación.
Sí, hay montones de personas que se presentan para trabajos de programador y no saben programar. Eso es normal.
Está relacionado con una cosa que escribió Joel Spolsky (extrañamente, socio de Atwood en stackoverflow.com).
Suponéte que querés contratar a alguien en el top 1% de los programadores.
Tenés 100 postulantes, de ellos 99 no pueden programar. 1 puede, y lo contratás.
Después la empresa de al lado necesita lo mismo. Tienen 100 postulantes, 99 no pueden programar... ¡y 80 son los mismos que la otra compañía rechazó!
Así que no, contratar al mejor de 100 no es la manera de tener un programador "top 1%", es simplemente tu intuición estadística que te hace equivocar.
No querés contratar a alguien en el top 1% de los postulantes, querés uno en el top 1% de programadores. Diferentes universos.
Estas dos cosas son los dos lados de la misma moneda. 99% de los postulantes son inútiles, por eso son postulantes, porque no pueden conseguir trabajo y no tienen trabajo porque son inútiles como programadores.
Juzgar a los programadores por el standard de los postulantes que se presentan es como juzgar la calidad de un restaurante lamiendo su tacho de basura.
Ahora, habiendo entendido esto, ¿cómo se encuentra un programador que pueda programar?
¡Fácil! ¡Buscás uno que tenga programas para mostrarte!
Nunca contrataría a un programador que no me pueda mostrar código. Tiene que tener un problema porque los programadores programan.
Es lo que hacemos. ¿Si no lo hacemos que somos? ¿Teóricos?
Veamos algunas objeciones obvias:
Programó para su trabajo anterior y no lo puede mostrar.
Ok, lohizo. ¿Qué más escribió? ¿Algo open source? ¿fragmentos en un blog? ¿Respuestas en stackoverflow?
¿Nada? ¿No escribió nada sin cobrar? No es el que quiero. Si sólo programa por dinero no tiene pasión por la programación, o no lo disfruta. Probablemente no es muy bueno tampoco.
Está terminando la universidad, todavía no escribió mucho.
¿Porqué? ¿Qué está esperando? ¿Qué lo detiene? Lleva años estudiando como programar! ¿Qué hizo con el conocimiento que fué adquiriendo? ¿Lo guarda para cuando cumpla 25? ¿No practicó su arte? No es el programador que buscamos.
Pero conseguir alguien que te muestre código no es suficiente por supuesto. También tiene que ser buen código, si estás seriamente tratando de contratar programadores excelentes.
Así que aquí hay unos criterios extra:
Y después está lo obvio, referencias, entrevistas, ejercicios, pero esos son filtros secundarios, lo importante es que pueda programar, y mostrarte su código es la forma de hacerlo.
Andrés Gattinoni: Python: Ver dominios de Apache que más transferencia consumen
Hace un rato publiqué un post con un script para ver qué dominios de Apache consumen mayor transferencia. El script en BASH toma unos 7 segundos en procesar 750 archivos de uno de mis servidores. Ahora hice una versión en Python, para la que me dieron algunos consejos los chicos de PyAr, y toma aproximadamente 4 segundos en procesar los mismos archivos. Aquí les dejo el código:
Parses all the files in a directory
treating them as access_log files
and outputs the list of files sorted
by transfered megabytes. Useful for
identifying heavy users.
Usage:
./access_log_parser.py <base_dir>
base_dir = directory where the access_log files are
"
def main (args):
"""Main
Main function of the script.
This is where the magic happens.
It takes the script arguments
and returns an exit code.
"""
# Parameter checking
if len(args) < 2:
print "Usage: %s <base_dir>" % args[0]
return 1
if os.path.isdir(args[1]):
base_dir = args[1]
else:
print "%s is not a directory" % args[1]
return 2
# Init vars
t1 = time.time()
mbyte = 1048576.0
domains = []
# Start processing files
for item in os.listdir(args[1]):
path = os.path.join(base_dir, item)
if os.path.isfile(path) and \
os.path.getsize(path) > 0:
bytes = 0
init_date = None
data = None
# Process file lines
for line in open(path, ‘r’):
data = line.split(" ")
if init_date is None:
init_date = data[3][1:]
try:
bytes += long(data[9])
except ValueError:
pass
domains.append({‘domain’: item, \
‘mbytes’: bytes / mbyte, \
‘init_date’: init_date, \
‘end_date’: data[3][1:] })
# Print out sorted information
for domain in sorted(domains, key=itemgetter(‘mbytes’)):
print "%.2f MB | From: %s | To: %s | %s" % \
(domain[‘mbytes’], \
domain[‘init_date’], \
domain[‘end_date’], \
domain[‘domain’])
print "Generated in %d seconds" % (time.time() – t1)
return 0
if __name__ == "__main__":
sys.exit(main(sys.argv))
Para ejecutarlo:
./access_log_parser.py /tmp/domain_logs ... 544.30 MB | From: 10/Mar/2010:02:48:33 | To: 10/Mar/2010:18:13:25 | dominio1.com.ar.log 602.34 MB | From: 10/Mar/2010:00:23:09 | To: 10/Mar/2010:23:39:45 | dominio2.com.ar.log 944.03 MB | From: 10/Mar/2010:00:49:35 | To: 10/Mar/2010:23:39:57 | dominio3.com.ar.log Generated in 3 seconds
Quizás te interese:
Marcos Vanetta: Tutorial de Bazaar
Hace algunas semanas hable sobre Bazaar [1] en este post. Lo he probado durante algún tiempo y me ha parecido muy simple! por supuesto, yo trabajo solo y casi nunca tengo conflictos con… migo mismo, pero en fin. Aquí presento un pequeño tutorial al respecto:

Primero básico e imprescindible: Iniciar un proyecto. Podemos empezar uno nosotros mismos o clonar uno de algún repositorio. (Es decir copiarnos el de alguien para modificarlo nosotros).
1) Creamos nosotros un nuevo proyecto
mkdir proyecto_nuevo
cd proyecto_nuevo
bzr init
2) hacemos branch de un proyecto:
bzr branch lp:lalita
Configuramos nuestro repositorio: Principalmente, se seleccionan que archivos no queremos formen parte del repositorio: archivos propios del IDE, configuraciones exclusivas de nuestro sistemas, la base de datos que estemos usando, backups del sistema, *.pyc, etc. Si bien ya hay un archivo que se encarga de esto en Bazaar, también podemos crear el nuestro .bzrignore. Ojo! debe estar dentro de un commit (ver más adelante)
*.o
*~
*.tmp
*.py[co]
bzr ignore
bzr ignore –old-default-rules
Listo! ya podemos empezar a trabajar en nuestro proyecto. Una vez que tengamos algunos cambios y estemos seguros de que funcionan deberíamos hacer commit. En el caso de que hayamos creado o borrado algunos archivos a drede antes deberíamos avisarle a Bazaar:
bzr add nombre_del_archivo
bzr add . #agregamos todos los archivos nuevos
bzr remove nombre_del_archivo
bzr commit -m “esto es un commit”
bzr commit -m “solo comiteamos un archivo” file_name
bzr commit –author “Patricio Rey “
Revisemos como vamos:
bzr status # nos dice si hicimos cambios desde el último commit
bzr diff # nos muestra todos los cambios desde el último commit
bzr diff file.py #exclusivo para un archivo
bzr diff –diff-options –side-by-side foo.py #a probar!
bzr log # nos muestra un historial de commits
bzr log foo.py # el historial de un solo archivo
bzr cat -r X file #la versión X del archivo file
bzr viz # Herramienta gráfica!
¡Errores! Supongamos que hemos hecho algunos cambios y … no nos gusta ninguno. Podemos hacer un:
bzr revert # y eliminar los cambios hasta el último commit
bzr revert archivo # elimina los cambios de un archivo
bzr uncommit # elimina el último commit
bzr uncommit -r -3 # vuelve 3 commits para atrás
A veces, tenemos una versión funcional, pero le queremos agregar algunas opciones nuevas. A riesgo de no “romper” el programa que ya está andando, lo que hacemos es crear un branch y luego, cuando nos aseguramos que las nueva features funcionan genial, hacemos un merge entre las dos versiones:
#no ubicamos un directorio antes en el árbol:
pwd -> /home/malev/code/lalita
cd..
bzr branch lalita nuevo_branch
# jugamos en nuevo_branch y cuando nos convence
# en el directorio de lalita hacemos
pwd -> /home/malev/code/lalita
bzr merge ../nuevo_branch
# y si no hay conflictos, YA ESTÁ!
Preparando un release! Esta opción nos permite copiar todos los archivos y directorios de un branch y empaquetarlos en un archivo o directorio. También es posible taggear o etiquetar un conjunto de archivos con un número de versión.
bzr export ../releases/my-stuff-1.5.tar.gz
bzr tag version-1-5
bzr diff -r tag:version-1-5
bzr tag 2.0-beta-4 –delete #si nos confundimos![]()
Todo este tutorial ha sido extraído de [2]. Aunque también recibí ayuda de Facu, Dermi y Gonzalo, todos del canal de IRC de PyAr [3]
También existe una aplicación visual [4], pero todavía no descubrí como instalarla ![]()
Y por último, he encontrado otro tutorial en español que parece interesante aquí en [5]
[1] http://bazaar.canonical.com
[2] http://doc.bazaar.canonical.com
[3] http://python.org.ar
[4] http://doc.bazaar.canonical.com/explorer/en/visual-tour-gnome.html
[5] http://palangano.com.ar/tag/bazaar/
Juan Pedro Fisanotti: Pycamp 2010, día 3
Resumen de hoy :)
A la mañana me quedé medio dormido, jeje, porque anoche nos habíamos quedado hasta las 4 a.m.
A la siesta participé en un mini-cursito de empaquetado de aplicaciones Python para Debian. La verdad que era más complejo de lo que esperaba, pero nada que un programador no pueda hacer. Conclusión: tengo que aprender setuptools
Más tarde participé en el Bug Day de Python: cada uno elegía algún bug de Python y trataba de mandar un parche con la corrección. No pude hacer ningún parche, pero aprendí un poco viendo código de cómo está hecho Python, lo que estuvo bueno.
Y ahora a la noche, después de comer empanadas y panqueques, vuelvo a programar un poco el juego que empezamos el sábado.
Saludos!!
update!: me acabo de enganchar en una reunión de otro juego que se va a desarrollar para una competencia, veremos que onda :)
Juan Pedro Fisanotti: PyCamp 2010, día 2
Ayer no postee porque no tuve tiempo en todo el día, así que posteo ahora el resumen. Supongo que esta noche volveré a postear con el resumen de hoy
Lo más interesante de ayer fue el sprint de Django. Sprint = gente que se junta a programar, Django = framework para hacer desarrollo web usando Python, el mejor que probé hasta ahora. O sea, los que querían se juntaron para sobre todo corregir bugs en Django, para la versión nueva que va a salir dentro de unos días. Sinceramente fui más que nada para ver y aprender, porque pensaba que estaba a un nivel en el que yo no podía aportar mucho. Pero para mi sorpresa, terminamos corrigiendo un bug de Django juntos con Javi :). Mi granito de arena para Django, así devuelvo algo de todo lo que me está sirviendo.
Por la tarde me enganché en el momento de cocos2d (el framework para juegos que nació en un PyCamp anterior, que estamos usando para el juego que empezamos el sábado). Me enganché medio tarde, pero estuvo bueno, me ayudó a entenderlo mejor.
Finalmente, a la noche tuvimos el "fogón", pero sin fuego porque no se consiguió leña. Se empezó hablando de los temas más comunitarios, objetivos, realidad de Python en Argentina, etc. Se habló también de PyCon Atlanta 2010 y PyCon Argentina 2010. Y después se terminó hablando de política, sociedad, valores, ideologías, etc. Discusiones acaloradas pero muy interesantes. Algo parecido a los threads de PyAr, jajaja.
Hoy viene siendo interesante también, pero esta noche hago el resumen. Saludos!
Juan Pedro Fisanotti: PyCamp 2010, día 1
No voy a hacer un post muy completo, eso lo dejo para cuando vuelva. Pero cada día voy a postear un breve resumen de como pasé/pasamos el día.
El viaje fue largo... salí de Rafaela el jueves a las 11 de la noche, y recién llegamos al lugar hoy a las 13, justo para la comida :).
El lugar muy bueno. Todavía no pude recorrer mucho, pero tiene hasta para hacer cayack (o como se escriba, jeje).
Está todo super organizado el tema de wifi, hay cables y antenas atadas con cinta por las paredes, jeje. Y por suerte no se necesitó usar mi router (hubiese sido para renegar nomás).
Lo primero que se hizo a la tarde fué presentar todos los proyectos, y anotar cuántos interesados había en cada uno. A partir de eso se organizó un cronograma, armado como para favorecer la participación el los proyectos más votados. Pero todos los proyectos quedaron en el cronograma, y cada uno elije en cuáles participar y cuáles no :).
De hoy, el proyecto en el que más participé y me interesó fue el de desarrollo de un juego de tipo "Tower Defense", usando la librería para juegos en Python COCOS2D. Es una librería que se había empezado a desarrollar en un PyCamp anterior, jeje.
La verdad que tenía miedo de no poder aportar mucho, pero en un rato nomás ya estaba a tono y codeando para modificar la lógica de disparo de las torres :D.
Y ahora, a la noche, algunos seguimos codeando, mientras otros están con juegos de mesa, o más relajados.
La gente hasta ahora genial!
Marcos Vanetta: Decimal, la evolución de los floats
Desde Python 2.4 se nos ha unido un módulo con un nuevo tipo de datos: Decimal, que permite manejar las matemáticas de punto flotante con algunas ventajas respecto a float:
El módulo se centra en 3 conceptos: el número decimal, el contexto aritmético y las señales.
Número decimal: inmutable, tiene un signo, coeficientes y un exponente. No trunca ceros a la derecha y posee los valores especiales: infinito, – infinito y NaN (no es un número). También diferencia entre -0 y +0.
El contexto aritmético es el ambiente donde se especifica la precisión, las reglas de redondeo, los límites en los exponentes, banderas que indican los resultados de las operaciones y “trampas” que permiten que ciertas señales sean tratadas como excepciones. La opciones de redondeo incluyen: ROUND_CEILING, ROUND_DOWN, ROUND_FLOOR, ROUND_HALF_DOWN, ROUND_HALF_EVEN, ROUND_HALF_UP, ROUND_UP, and ROUND_05UP.
Las señales son un conjunto de condiciones que surgen durante el proceso de cálculo. Y dependiendo de las necesidades de la aplicación, pueden ser ignoradas, consideradas información o tratadas como excepciones. Las señales en el módulo decimal son: Clamped, InvalidOperation, DivisionByZero, Inexact, Rounded, Subnormal, Overflow, and Underflow.
Para cada señal hay una flag (bandera) y una trap (trampa¿?). Cuando se encuentra una señal, la flag se pone a uno, luego si la habilitador de la trap está puesto en uno, entonces se envía una excepción (exception). Las flags quedan en uno, por lo que es necesario reiniciarlas antes de monitorear el cálculo.
Probando:
1 2 3 4 | from decimal import * getcontext() # Context(prec=28, rounding=ROUND_HALF_EVEN, Emin=-999999999, Emax=999999999, capitals=1, flags=[], traps=[Overflow, DivisionByZero, InvalidOperation]) getcontext().prec = 7 # Set a new precision |
Los objetos decimal se instancian a partir de integers, string o tuplas. Para convertir una desde un float primero es recomendable convertilo primero a string.
Ya se, este post parece una traducción de [1] y medio que lo es, pero lo hice para obligarme a leer toda la documentación
También les dejo un tutorial más que interesante en [2].
El contra de decimal: No se pueden realizar operaciones entre números Decimal y floats. Antes los floats deben ser convertidos a string y luego a decimal. Bastante molesto cuando cargamos constantes, o algunos valores numéricos de una ecuación. Seguro hay alguna forma de hacer esto simple, pero todavía no la he encontrado ![]()
[1] http://docs.python.org/library/decimal.html
[2] http://broadcast.oreilly.com/2009/08/pymotw-decimal—fixed-and-flo.html
Administración y hosting cortesía de Net Managers SRL
Tema por Andrés Antista
Banner por Joaquín Sorianello