viernes, diciembre 26, 2008

Haganme un favor

Cuando estén con migo ponganme en una situación en la que pueda decir touche de manera adecuada.

Siempre quise parecer inteligente diciendo esa palabra

Book meme

Ningún Test lo es. - Sueñan los androides con ovejas eléctricas? Philip K. Dick
link: http://fitoria.net/2008/11/13/book-meme/
  • Agarra el libro mas cercano
  • Abrelo en la pagina 56.
  • Encuentra la quinta oración.
  • Postealo junto con estas instrucciones
  • No vayas por tu libro favorito solo agarra el que este MAS CERCA
  • Poner la url del site donde leíste el meme

lunes, diciembre 22, 2008

Xml -> dict -> objetos

En este ejemplo se muestra como convertir un string a una estructura de diccionarios y listas anidadas usando expat, tambien se proveen dos clases que permiten manipular el resultado como si fueran objetos.

primero el codigo

import xml.parsers.expat

class XmlParser(object):
'''a class that parses a xml string an generates a nested
dict/list structure
'''

def __init__(self, text):
'''constructor'''
self.parser = xml.parsers.expat.ParserCreate()
self.parser.buffer_text = True

self.result = None
self.stack = []
self.current = None

self.parser.StartElementHandler = self.start_element
self.parser.EndElementHandler = self.end_element
self.parser.CharacterDataHandler = self.char_data
self.parser.Parse(text)

def start_element(self, name, attrs):
'''Start xml element handler'''
if self.current != None:
self.stack.append(self.current)

self.current = {}

for (key, value) in attrs.iteritems():
self.current[str(key)] = value

self.current['tag'] = name
self.current['childs'] = []

def end_element(self, name):
'''End xml element handler'''
if len(self.stack):
current = self.stack.pop()
current['childs'].append(self.current)
self.current = current
else:
self.result = self.current

def char_data(self, data):
'''Char xml element handler.
buffer_text is enabled, so this is the whole text element'''
self.current['childs'].append(data)

class DictObj(dict):
'''a class that allows to access a dict as an object
'''

def __init__(self, kwargs):
'''constructor'''
dict.__init__(self, kwargs)

def __getattribute__(self, name):
if name in self:
obj = self[name]

if type(obj) == dict:
return DictObj(obj)
elif type(obj) == list:
return ListObj(obj)

return obj
else:
return None

class ListObj(list):
'''a class that allows to access dicts inside a list as objects
'''

def __init__(self, args):
'''constructor'''
list.__init__(self, args)

def __getitem__(self, index):
if index > len(self):
raise IndexError('list index out of range')

obj = list.__getitem__(self, index)

if type(obj) == dict:
return DictObj(obj)
elif type(obj) == list:
return ListObj(obj)

return obj

def __iter__(self):
'''iterate over the list'''

count = 0

while count < len(self):
yield self[count]
count += 1

def raw_string(dct_):
'''return a string containing just the string parts removing all the
xml stuff'''

def helper(dct):
result = []

for child in dct.childs:
if type(child) == str or type(child) == unicode:
result.append(str(child))
else:
result = result + helper(child)

return result

return ''.join(helper(dct_))



Simplemente creamos un objeto de tipo XmlParser pasandole el string y obtenemos el resultado parseado en la variable result. Si no queremos andar preguntado si las llaves existen antes de accederlas para evitar excepciones podemos usar la clase DictObj que nos permite acceder a las llaves como si fueran atributos, las variables que no existan como llaves contendran None. Aca va un ejemplo en la consola interactiva


>>> import XmlParser
>>> p = XmlParser.XmlParser('google test foo !!')
>>> r = p.result
>>> d = XmlParser.DictObj(r)
>>> d
{'childs': [{'childs': [u'go', {'childs': [u'o'], 'tag': u's'}, u'gle'], 'href': u'google.com', 'tag': u'a'}, u' ', {'childs': [u'test'], 'tag': u'i'}, u' ', {'childs': [], 'src': u'foo.png', 'alt': u'foo', 'tag': u'img'}, u' ', {'childs': [u'!'], 'tag': u'u'}, {'childs': [u'!'], 'tag': u's'}], 'tag': u'span'}
>>> d.childs
[{'childs': [u'go', {'childs': [u'o'], 'tag': u's'}, u'gle'], 'href': u'google.com', 'tag': u'a'}, u' ', {'childs': [u'test'], 'tag': u'i'}, u' ', {'childs': [], 'src': u'foo.png', 'alt': u'foo', 'tag': u'img'}, u' ', {'childs': [u'!'], 'tag': u'u'}, {'childs': [u'!'], 'tag': u's'}]
>>> d.childs[0]
{'childs': [u'go', {'childs': [u'o'], 'tag': u's'}, u'gle'], 'href': u'google.com', 'tag': u'a'}
>>> d.childs[0].tag
u'a'
>>> d.childs[0].childs[0]
u'go'
>>> d.childs[0].childs[1].tag
u's'

jueves, diciembre 18, 2008

Metacrap

buen articulo (explica por que nunca use los tags de blogger :P)

http://www.well.com/~doctorow/metacrap.htm

sábado, diciembre 13, 2008

sobre startups

este articulo confirma algunas cosas que tenia en mente y que no sabia si era yo nomas :D

http://www.paulgraham.com/divergence.html

quotes para los fiacosos

The reason startups no longer depend so much on VCs is one that everyone in the startup business knows by now: it has gotten much cheaper to start a startup. There are four main reasons: Moore's law has made hardware cheap; open source has made software free; the web has made marketing and distribution free; and more powerful programming languages mean development teams can be smaller. These changes have pushed the cost of starting a startup down into the noise.

Once you cross the threshold of profitability, however low, your runway becomes infinite. It's a qualitative change, like the stars turning into lines and disappearing when the Enterprise accelerates to warp speed. Once you're profitable you don't need investors' money. And because Internet startups have become so cheap to run, the threshold of profitability can be trivially low. Which means many Internet startups don't need VC-scale investments anymore.

jueves, diciembre 04, 2008

import antigravity

problema: queres pasarle uno o mas archivos a una persona, solo queres que vea archivos de una carpeta determinada y poner apache o samba no tiene sentido para vos.

solucion en una linea de python:

__import__('BaseHTTPServer').HTTPServer(('', 8000), __import__('SimpleHTTPServer').SimpleHTTPRequestHandler).serve_forever()


si lo queres correr desde la consola (te publica el directorio donde corriste el comando):

python -c "__import__('BaseHTTPServer').HTTPServer(('', 8000), __import__('SimpleHTTPServer').SimpleHTTPRequestHandler).serve_forever()"


vamos a admitirlo, es un poco perlish, asi que vamos a ponerlo mas limpio:

import BaseHTTPServer
import SimpleHTTPServer

server = BaseHTTPServer.HTTPServer(('', 8000), SimpleHTTPServer.SimpleHTTPRequestHandler)
server.serve_forever()



PD: al final lo pasamos en pendrive porque eran 899MB pero cuando haces algo asi en python es con el unico fin de levantarte minas, ej:

*se aproxima a la mujer objetivo en bar, boliche o similar*
- ayer le tenia que pasar un archivo a un amigo y no tenia como
*hace gesto de desinteresada*
- sabes que hice?
*no responde*
*mira para otro lado*
- escribi un servidor web en 4 lineas de python
*lo mira*
*comienza a besarlo apasionadamente*

;)

sábado, noviembre 29, 2008

Workaround

este post es un placeholder, cuando quieras sharear una url que no tenes en tus links podes ir al feed de mi blog (obviamente lo tenes en los feeds :P) y shareas este post con un comentario con la url que te parecio interesante.

Esto hasta que google reader me permita sharear urls arbitrarias sin tener que estar suscripto a su feed.

Si el post te parece muy largo puedo crear uno sin toda esta explicacion, pero esta bueno que tu share tenga la explicacion de porque estas shareando un post tan pedorro con una url que no tiene nada que ver :D

Si tildas este post como "keep unread" en reader no vas a tener que tener "all items" en mi blog, sino que solo vas a poder ver los nuevos ;)

a su servicio,
wariano

miércoles, noviembre 26, 2008

How Software Companies Die

"Programming is the Great Game. It consumes you, body and soul. When you're caught up in it, nothing else matters. When you emerge into daylight, you might well discover that you're a hundred pounds overweight, your underwear is older than the average first grader, and judging from the number of pizza boxes lying around, it must be spring already. But you don't care, because your program runs, and the code is fast and clever and tight. You won. "

http://www.zoion.com/~erlkonig/writings/programmer-beekeeping.html

martes, noviembre 18, 2008

vimrc

set nocompatible
set smartcase
set incsearch
set hlsearch
set bs=indent,eol,start
set ts=4
set sts=4
set sw=4
set et
set tw=75
set ai
set smartindent
set smarttab
set syntax

# estas 3 son para gvim en windows

colorscheme desert
set guioptions-=T
set guifont=Consolas:h14

lo dejo para que cada vez que tenga un vim al frente tenga las settings que uso siempre en algún lado, si le sirve a alguien bien :D

martes, noviembre 11, 2008

lunes, octubre 27, 2008

minirants

1) a mi que me da verguenza cuando emesene se congela por unos segundos, la verguenza que deben pasar los de outlook que se congela todo el tiempo :P

2) aguante la opcion -c de wget

jueves, octubre 16, 2008

migrar access a postgres

aca hay un pequeño script que hice para migrar de access a postgres, tuve que hacer algunos trucos para que ande bien. si a alguien le sirve...
import os
import commands

archivo = "archivo.mdb"

tables = commands.getoutput("mdb-tables -S %s" % (archivo,))
os.popen("rm carga.sql")
os.popen("rm schema.sql")

os.popen("mdb-schema -S %s postgres| sed 's/Postgres_Unknown 0x0c/Text/' | grep \"\-\-\" -v | grep \"^DROP TABLE\" -v | sed 's/Bool/Int8/' > schema.sql" \
% (archivo,))

for table in tables.split():
cmd = \
# si tenes el postgres con locales que te pide insertar la fecha con un
# formato no ISO (MDY) correr la siguiente linea antes de los inserts
# SET DateStyle TO 'MDY';
"mdb-export -I -S %s %s | sed -e 's/)$/)\;/' | sed -e s/\\\"/\\'/g >> carga.sql"
if not table.startswith('MSys'):
os.popen(cmd % (archivo, table))

domingo, octubre 12, 2008

cosas locas de java

en una clase tengo dos atributos privados, los cuales solo son modificados por un método. Hasta ahí todo bien.
El problema es que para poder serializar esa clase a json y para poder guardarla en Hibernate tienen que ser beans (osea esos atributos tienen que tener getter y setters) por lo cual me rompe todo el bendito encapsulamiento, ya que cualquiera manipulando un objeto puede romper la consistencia y relacion de los dos atributos usando el set de uno (no, no puedo deducir que hacer con el otro en base al valor de uno).

Cosas que pasan.

PD: puede que haya una forma de arreglarlo, yo no la se.

jueves, octubre 02, 2008

Quote

And do you have any advice for up-and-coming programmers? I think it’s important to try to master the different paradigms of programs that are out there. The obvious object oriented programming is hopefully something that you will be taught in school. Hopefully school will also teach you functional programming, if not, that is a good thing to go look at.

Go look at dynamic languages and meta-programming: those are really interesting concepts. Once you get an understanding of these different kinds of programming and the philosophies that underlie them, you can get a much more coherent picture of what’s going on and the different styles of programming that might be more appropriate for you with what you’re doing right now.

Anyone programming today should check out functional programming and meta-programming as they are very important trends going forward.

del creador de C#

lunes, septiembre 29, 2008

Quote de pyar

by juanjo conti

>> Esto quiere decir que ya podrán competir programadores de C# y java.
>>
>
> Los amigos no dejan que los amigos programen en Java.

viernes, septiembre 26, 2008

Yahoo test

desde hoy voy a usar yahoo como mi buscador por defecto en firefox en todas mis maquinas.
En una semana aprox les comento los resultados.

miércoles, septiembre 10, 2008

ultimo tweet (?)

@LHC: No, YOU suck!

si lo lees mañana va a ser un chiste totalmente pasado de moda.

para cuando el proximo meme con ribetes cientificos?

viernes, septiembre 05, 2008

tiernizzzz ^^

Frente a todos los estereotipos, los aficionados al "heavy metal" son personas tiernas, según un estudio divulgado hoy en el Reino Unido que analiza los vínculos entre los gustos musicales y los rasgos de la personalidad.

De acuerdo con la investigación, tanto los amantes del jazz como los de la música clásica tienen una alta autoestima y son gente creativa, pero mientras los primeros se caracterizan por su sociabilidad, los segundos son personas introvertidas.

yo escucho jazz, musica clasica y metal de todo tipo, que demonios soy?

http://criticadigital.com/index.php?secc=nota&nid=10338

martes, septiembre 02, 2008

tweets teledirigidos

@fibertel: gracias por ponerme de mal humor el domingo, metete tus mensajes de bienvenida windows only que bloquean el acceso a donde mas te plasca
@jquery: (hasta ahora) gracias
@255.255.255.255: tengo router inhalambrico, las lan parties son cosa del pasado, wlan parties FTW

jueves, agosto 14, 2008

ciclo de desarrollo web

2 horas escribiendo el css
8 horas tratando de hacerlo andar en IE7*

* con busquedas desesperadas del tipo "ie7 css hack", "ie7 broken box model" etc..

miércoles, agosto 06, 2008

self.quote()

algo que acabo de decir autoquoteado a pedido de nassty.

anti-patterns de la vida: quemar un libro, talar un arbol y escribir un framework de php

domingo, agosto 03, 2008

me encantan las amenazas

si contara la cantidad de veces que me tendría que haber muerto por cadenas de mails no reenviadas, seria el ser humano mas muerto de la historia, pero este mail se paso.

el bajo nivel de redacción en el primer slide, algo así como "pepe de california envío este mail a 13 personas en 13 minutos y su vida cambio, ahora es millonario, jose de nueva york no lo envío y su gato le disparo 13 veces".

y la subliminalidad de la amenaza para que lo mandes es genial

realmente me gustaría saber quien inicia estas cadenas..



también admiro la incapacidad de usar herramientas de edición gráfica, en el slide anterior el fantasma metido en la foto, da pena.

si me muero en 13 días, esto va a ser el meme mas grande de la historia.

sábado, agosto 02, 2008

run forest run

rfr es un proyectito que empecé una noche, retome antes de ayer y termine ayer, la razón de su existencia es que en mi actual desktop (openbox+fbpanel) me faltaba un lanzador con historial y autocompleción, necesitaba algo simple, minimalista, como mi desktop.

Y como se dice por ahí del soft libre, si no existe, hacelo, así que eso hice y con la intención de rememorar mis 1337 skillz (léase programación en C), programe run forest run (rfr para el comando).

como una imagen vale mas que 1000 tweets, aca van los screenshots mostrando (en el orden que se le cante a blogger), el launcher, autocompletando y mostrando el historial.




la ultima version con un binario compilado para linux de 32 bits esta aca

www.marianoguerra.com.ar/rfr.tar.gz

licencia? GPL 3 :P

jueves, julio 31, 2008

Frases sobre programacion

aclaro que los quotes que pongo sobre programacion son solo eso, quotes, no quiere decir que este 100% de acuerdo con todos, pero que si los pongo es porque al menos me hicieron reir.

C combines all the power of assembly language with all the ease of use of assembly language.

-- unknown

I'd just like to take this moment to point out that C has all the expressive power of two dixie cups and a string.

-- Jamie Zawinski, in the source code for xkeycaps

There is a point in your life when you realize that you have written enough destructors, and have spent enough time tracking down a memory leak, and you have spend enough time tracking down memory corruption, and you have spent enough time using low-level insecure functions, and you have implemented way too many linked lists.

-- Miguel de Icaza

Greenspun's Tenth Rule of Programming: "Any sufficiently complicated C or Fortran program contains an ad-hoc, informally-specified bug-ridden slow implementation of half of Common Lisp."

-- Philip Greenspun

Your superior intellect is no match for our puny weapons.

-- unknown, via Aaron Stern


C++

C++ : an octopus made by nailing extra legs onto a dog.

-- off smalltalk.org

Think of C++ as an object-oriented assembly language.

-- off the guile Scheme mailing list

C makes it easy to shoot yourself in the foot. C++ makes it harder, but when you do, you blow your whole leg off.

-- Bjarne Stroustrup

Programming in C++ is premature optimization.

-- off comp.lang.python

The abstraction level of both C# and Java is mediocre; it's much better than C, somewhat weaker (!) than C++, and not nearly as good as languages that support both object-oriented and functional programming (such as Lisp and Ocaml). Therefore, I find programming in these languages to be pretty boring and tedious. Many of the scalability features in these languages are not, strictly speaking, part of the languages at all but of the environment(s) built up around the languages. For instance, the support for components, versioning, packaging and documentation generation are all features of the environments. I hope we will soon start to see these kinds of meta-features in better languages than Java or C#.

Python: executable pseudocode. Perl: executable line noise.

-- off comp.lang.python

Common Lisp and Scheme

Most people are just too damn dumb to recognise how great Lisp is.

-- off slashdot

[Lisp] is the only computer language that is beautiful.

-- Neal Stephenson

The journey of a thousand miles begins with an open parenthesis.

-- Rainer Joswig

Will write code that writes code that writes code for food.

-- Martin Rodgers

Those who do not understand lisp are doomed to re-implement it.

-- attributed to Erik Naggum, off comp.lang.lisp


One of the consequences of all these features is that it is extremely easy to implement new programming paradigms within the Lisp language. For instance, you can implement a full object-oriented system (or several different incompatible OO systems) within the Lisp language itself. For this reason, Lisp is sometimes referred to as a "language laboratory". Because of this, Lisp programmers often write their programs bottom-up by effectively writing a new program-specific language for the application and then writing the application in that language. Paul Graham's book On Lisp discusses this approach in great detail. Lisp is also an incredibly dynamic and flexible language; code can be compiled on the fly and modules can be re-loaded as needed. Despite this, Lisp compilers exist that are very efficient and can routinely produce code that is only (say) 1.5 times slower than optimized C code.


todos sacados de aca:

http://www.cs.caltech.edu/~mvanier/hacking/rants/scalable_computer_programming_languages.html


nota mental, leerlo de nuevo mas lento :P

sábado, julio 12, 2008

Prism howto (flash plugin y sacar statusbar)

para instalar el plugion flash en linux hay que copiar libflashplayer.so a ~/.mozilla/plugins (si la carpeta plugins no existe, hay que crearla)

para sacar el status bar, hay que editar el archivo webrunner.xul que se encuentra en prism/chrome/webrunner.jar

hay que comentar desde la linea que empieza con "<statusbar id="statusbar">" hasta "</statusbar>" sacando los comentarios internos en caso de existir (en la 0.9 hay uno)

es mas un recordatorio que algo util para alguien, pero por si alguien lo googlea...

jueves, julio 10, 2008

9 de julio

estudio y ...





hasta ahi todo mas o menos bien (excepto los temas de las conversaciones)

ahora..



:)

Update, esta puede ser mas interesante ;)



update, plugin flash :D

domingo, junio 29, 2008

Hibernate, HSQLDB y SQLERROR

esto es un mensaje por si alguien googlea el problema, la solución es:

no nombre campos con el nombre "end"

listo, ahi fue una hora de mi vida por no poner nombres mas descriptivos a los errores..

miércoles, junio 25, 2008

Bjarne Stroustrup quote

Do you have any advice for up-and-coming programmers?

Know the foundations of computer science: algorithms, machine architectures, data structures, etc. Don't just blindly copy techniques from application to application. Know what you are doing, that it works, and why it works. Don't think you know what the industry will be in five years time or what you'll be doing then, so gather a portfolio of general and useful skills. Try to write better, more principled code. Work to make "programming" more of a professional activity and less of a low-level "hacking" activity (programming is also a craft, but not just a craft). Learn from the classics in the field and the better advanced textbooks; don't be satisfied with the easily digested "how to" guides and online documentation - it's shallow.

lunes, junio 23, 2008

compiling

cuando lei esta historieta me rei, pero ahora que principalmente programo en lenguajes compilados, me doy cuenta que es verdad..


que manera de checkear los feeds mientras se compila...

lunes, junio 16, 2008

touchscreens en pcs...

veo un vídeo de windows 7, lo único que prometen hasta ahora es el soporte de touch screen y detección de múltiples dedos. Muy bonito, pero me pongo a pensar.

repasé lo que hago en un día normal con mi computadora, y no puedo encontrar una sola cosa que sea mejor o mas fácil hacer tocando la pantalla. Por favor, no salgan con que no tengo visión, y que con el tiempo surgiran usos, reconosco que en los celulares es muy útil, ya que la interacción es muy básica (pocas opciones, pocos botones, interacción básica), pero no comprendo que me puede ayudar o ayudar a una persona normal el uso de touch screens, a modo de ejercicio cito algunas de ellas:

* programar, redactar texto y todo lo relacionado con texto, no sirve (de la misma forma que no sirve la detección de voz, que esta en vista y nadie usa)
* navegar por internet, mas que seguir links, cosa que es mas fácil con el mouse
* administrar el sistema en general

si alguien salta con dibujar, que muestran el paint ahi, la forma natural de interacción con las herramientas de dibujo por parte de los profesionales es.... con un LAPIZ no con los dedos, y eso se hace sobre superficies fijas que ya existen y que se usan.

no me imagino una persona trabajando 8 horas por dia con los brazos levantados, ni tampoco me imagino una persona 8 horas mirando para abajo con una pantalla ubicada en la mesa.
Tampoco me imagino una persona limpiando la pantalla cada cinco minutos, o levantandola porque le pego con el dedo muy fuerte.

llamenme exceptico, pero la interacción por voz y por contacto con las manos creo que tiene un nicho muy reducido y que no me parece que sea usado como el "buque insignia" de windows 7.

Todo esto a menos que se cambie por completo el paradigma de ventanas para el diseño de interfacez graficas, lo que si permitiria el uso de esta tecnologia. Me quedo esperando que alguien salga con un paradigma mejor con el actual.

jueves, junio 12, 2008

to:microsoft

  1. hace que vista responda mejor a cualquier evento
  2. hace que vista borre y copie archivos mas rápido que windows 3.1
  3. hace que vista no confunda no poder borrar un archivo por que esta siendo usado con que no lo puedo borrar porque requiero privilegios de administrador (y que después de pedirme los privilegios falle)
  4. hace que la porquería de cmd sepa que si le pongo un path relativo y aprieto tab me trate de autocompletar en *ese* directorio y no en el que estoy
  5. hace que el buscador de porquería ese encuentre un archivo cuando le escribo el nombre completo y se que existe
  6. hace que tenga acceso a los ejecutables y no tenga que escribir toda la ruta
  7. hace que cuando vuelve de suspender ande internet (bue, eso de suspender es una porquería en todos lados)
y un largo etc.

miércoles, mayo 28, 2008

Sobre lenguajes estaticos y dinamicos

En los últimos dos meses he estado desarrollando un software en C# junto a otras 6 personas y he notado una cosa:

Se pasa mucho tiempo debugueando y traceando excepciones que (obviamente) saltan en tiempo de ejecución.

mi primera opinión sobre eso fue que era una forma de desarrollar de mis compañeros, ya que yo programo en python y no se ni como se debuguea, seguir excepciones obviamente si lo he hecho pero supuse que era algo que solo pasaba en lenguajes dinámico, pero no, también pasa en los lenguajes estáticos.
En un proyecto de 7 personas y con mucho código no escrito por uno, no se suelen controlar todas las excepciones que pasan, y esto no es de este grupo, uno normalmente no maneja todas las excepciones que pueden llegar a saltar en todo momento en el código. Esto hace que una gran parte de los errores del programa (escrito en un lenguaje inherentemente estático) sean detectados en tiempo de ejecución y no de compilación, los otros errores mas comúnmente encontrados son:

* errores en nombres de variables
* problemas de tipos en declaraciones
* referencias a nulo por no inicializar una variable

de esos tres, el primero es el único que sucede en python y que en C# lo detecta el compilador (aunque en python lo detecta pylint ;)).
El segundo en python no existe ya que no se declaran tipos (gracias al bendito ducktyping) y el tercero casi no aparece ya que las variables se declaran cuando se inicializan, así que si no es nuestra costrumbre andar usando None en todos lados (cosa que no hago mas que en parámetros de métodos para variables mutables) este problema desaparece.

A donde quiero llegar con esto?

A que el ser un lenguaje estático no me trae ninguna ventaja como desarrollador, ya que me enfrento a la misma incertidumbre en tiempo de ejecución a que errores no detectados durante la compilación surjan (y que son muchos).

Para terminar, aquí java se merece una mención ya que nos obliga a tratar una excepción o mencionar que es "Throweada" así que SI sabemos que excepciones pueden surgir durante el desarrollo, mientras que en .NET solo podemos saberlo mirando la documentación (cosa que el 99% del tiempo no hacemos).

Resumen, aguanten los lenguajes dinámicos :P

sábado, mayo 17, 2008

bash history meme

mariano@mousehouse:~$ history | awk '{print $2}' | sort | uniq -c | sort -rn | head
83 python
64 cd
52 sh
51 ls
49 svn
30 sudo
30 ncmpc
28 vim
11 rm

lunes, mayo 12, 2008

clamo por la cabeza de...

...el que decidio hacer que el plastiquito de la tapa de pepsi sea dificultoso de sacar.

firma: presidente del club de fans de masticadores de plastiquito de la tapa de pepsi (ASDF por sus siglas en polaco), somos pocos, pero tampoco somos buenos.

miércoles, abril 30, 2008

sábado, abril 19, 2008

openbox

me pase a openbox, muy bonito y liviano, aca va screenshot


(el panel es pypanel)

y como soy un artista, les dejo una de mis obras culmines (?)

martes, abril 08, 2008

metawtf

jugando un poco con metaclases y decoradores para hacer los plugins de emesene mas seguros.

el problema que intento resolver es el siguiente.

dada una función o un método que pueden llegar a fallar:

def function(a, b):
return a / b

class Object(object):
def __init__(self, num):
self.num = num

def method(self, a, b):
'''return a / b * self.num'''
return a / b * self.num

print "function(1, 2) = ", function(1, 2)
print "Object(10).method(1, 2) = ", Object(10).method(1, 2)

print "trying function(1, 0)"
try:
function(1, 0)
except ZeroDivisionError, error:
print error

print "trying Object(10).method(1, 0)"
try:
Object(10).method(1, 0)
except ZeroDivisionError, error:
print error


cuya salida es:


function(1, 2) = 0
Object(10).method(1, 2) = 0
trying function(1, 0)
integer division or modulo by zero
trying Object(10).method(1, 0)
integer division or modulo by zero


usando el modulo sandbox podemos hacer:

import sandbox

def callback(function, exception_type, exception):
print "exception raised by %s: %s" % (function, exception)

@sandbox.sandbox(callback, Exception)
def safe_function(a, b):
return a / b

class SafeObject(object):
__metaclass__ = sandbox.meta_decorator(sandbox.sandbox,
callback, Exception)

def __init__(self, num):
self.num = num

def method(self, a, b):
'''return a / b * self.num'''
return a / b * self.num

print "safe_function(1, 2) = ", safe_function(1, 2)
print "SafeObject(10).method(1, 2) = ", SafeObject(10).method(1, 2)

print "trying safe_function(1, 0)"
try:
safe_function(1, 0)
except ZeroDivisionError, error:
print error

print "trying SafeObject(10).method(1, 0)"
try:
SafeObject(10).method(1, 0)
except ZeroDivisionError, error:
print error


la salida es:


safe_function(1, 2) = 0
SafeObject(10).method(1, 2) = 0
trying safe_function(1, 0)
exception raised by safe_function: integer division or modulo by zero
trying SafeObject(10).method(1, 0)
exception raised by method: integer division or modulo by zero


la salida es la salida del callback

otra cosa turbia que se puede hacer, es decorar metodos de objetos, no de clases, aca hay un ejemplo:

obj = Object(10)
sandbox.decorate_object(obj, sandbox.sandbox, callback,
ZeroDivisionError)

print "trying obj.method(1, 0)"
obj.method(1, 0)


notese que decora el objeto, no es que lo copia y devuelve uno similar o algo asi.

lo que hace es decorar un objeto del tipo Objeto (que no es seguro).
la salida:


trying obj.method(1, 0)
exception raised by method: integer division or modulo by zero


para que sirve todo esto? basicamente para asegurarme de que los plugins que cargo no emitan excepciones, y que si lo hacen, un metodo que yo defina decida que hacer con ese plugin (pararlo, reportar el error, seguir o preguntarle al usuario que desea hacer con el mismo).
Todo esto sin requerir que el usuario escriba una linea extra de codigo (lo cual no suelen hacer de todas formas, mientras el plugin les funcione a ellos :P)

el modulo permite crear metaclases que decoren con cualquier decorador que reciba una cantidad arbitraria de parametros, no solo el decorador de sandobox, lo mismo con decorate_object, por lo que pueden ser usados para decorar cualquier cosa con cualquier decorador.

para los curiosos que quieren ver el codigo, aca esta:

import types
import inspect
import functools

class sandbox(object):
'''decorator that will catch the exceptions of type
exception_type and call the callback passing the function, the
exception type and the exception object as parameters'''

def __init__(self, callback, exception_type=Exception):
self.callback = callback
self.exception_type= exception_type

def __call__(self, function):
@functools.wraps(function)
def wrapper(*args, **kwds):
try:
return function(*args, **kwds)
except self.exception_type, exception:
self.callback(function, self.exception_type, exception)

return wrapper

# wtf?
def meta_decorator(decorator, *args, **kwds):
'''return a metaclass that used on a class will decorate
all the methods of the *class* with the decorator
passing args and kwds to the decorator'''

class MetaDecorator(type):
def __init__(cls, name, bases, dct):
type.__init__(cls, name, bases, dct)
methods = [x for x in dct if isinstance(dct[x],
types.FunctionType)]

dec = decorator(*args, **kwds)

for method in methods:
setattr(cls, method, dec(getattr(cls, method)))

return MetaDecorator

class MethodSandbox(object):
'''wrap a method with the sandbox decorator and return a callable
object that is almost identical to the method'''

def __init__(self, method, callback, exception_type=Exception):
functools.update_wrapper(self, method)
self.method = method
self.callback = callback
self.exception_type = exception_type

def __call__(self, *args, **kwds):
try:
return self.method(*args, **kwds)
except self.exception_type, exception:
self.callback(self.method, self.exception_type, exception)

def decorate_object(obj, decorator, *args, **kwds):
'''wrap all the obj methods with the sandbox decorator,
and calling the callback parameter when an exception is raised
it decorates all the methods on an *object*'''
dec = decorator(*args, **kwds)

[setattr(obj, method, dec(getattr(obj, method)))\
for method in dir(obj) if inspect.ismethod(getattr(obj, method))]

martes, marzo 25, 2008

nicevte 0.1 :P

en el post anterior les comente de evilvte, bueno, hice un minifork para arreglar un bug (cuando cerraba dejaba el proceso corriendo), agregue el boton cerrar a cada tab, agregue scroll cuando los tabs son mas largos que la ventana, tabs reordenables y tabs que se expanden hasta ocupar toda la pantalla.

que le falta? que el boton de cerrar no haga el tab tan largo.

screenshot obligado :P


copia esto de aca abajo en una terminal:

wget http://marianoguerra.com.ar/nicevte-0.1.tar.gz && tar -xzf nicevte-0.1.tar.gz && cd nicevte-0.1 && ./configure && make && sudo make install && evilvte

lo baja lo desempaca, lo configura, lo compila, lo instala y lo corre, eso es user friendlyness :P

PD: si, el binario se sigue llamando evilvte, cosas de la vida ;)

lunes, marzo 24, 2008

user friendlyness

an VTE based super lightweight terminal emulator

evilvte is a terminal emulator. It supports almost everything VTE provides.
It also supports tabs, tabbar autohide, and switch encoding at runtime.
Configuration is via editing source code and recompilation.

http://www.calno.com/evilvte/

fuera de eso, esta genial, liviana, levanta al instante, buen reemplazo de xterm con lo que se le extraña en xterm de gnome-terminal (tabs y colores como la gente)

viernes, febrero 29, 2008

otra vez lavoz.com.ar

titulo: Robots asesinos
nota al pie de la imagen: ROBOTS. En realidad, son pequeños tanques operados a control remoto por soldados

eso si que es periodismo serio.

le recomiendo otros titulares

enfermedad mortal incurable se exparse por el mundo
bah, en realidad es la gripe

hombre mueve objetos con la mente
mmmh, digamos que lo mueve con un hilo y no te das cuenta

boca goleo a river 6 a 0
no, en realidad jugo con estudiantes y empataron.

martes, febrero 19, 2008

Bordes redondeados en fluxbox

me negaba a empezar a estudiar sin bordes redondeados en fluxbox (?), por desgracia los muchachos de ubuntu lo compilan sin soporte para bordes redondeados asi que lo tuve que hacer yo.

la receta:

wget http://surfnet.dl.sourceforge.net/sourceforge/fluxbox/fluxbox-1.0.0.tar.gz
tar -xvzf fluxbox-1.0.0.tar.gz
cd fluxbox-1.0.0/
sudo aptitude install libimlib2-dev xlibs-dev libxft-dev libxpm-dev
./configure --enable-imlib2 --enable-nls --enable-xft --enable-xpm --enable-shape --enable-render
make
sudo make install
vim /home/mariano/.fluxbox/startup # cambiar /usr/bin/fluxbox por /usr/local/bin/fluxbox

y listo..

lunes, febrero 11, 2008

Porque me gusta el software libre

* Quiero subir mis albums a picasa
* Picasa no soporta subir cantidades de fotos a albums en linux
* Busco un proyecto que lo haga
* No lo encuentro
* Busco como hacerlo y lo hago
* Funciona
* Quiero agregarle soporte para Thumbails
* Busco algun proyecto que haga eso
* Encuentro uno
* Le mando mi codigo
* Lo agrega a su proyecto

Ya tengo visor de imagenes multiplataforma para administrar mi album web de picasa.



El proyecto (http://www.kiyut.com/products/ekspos/index.html) es un visor de imagenes multiplataforma escrito en java, ahora soporta seleccionar fotos y subirlas a tu album web de picasa, su licencia es BSD, por lo cual tuve que cambiar la licencia de mi codigo.

si tienen el mismo problema que yo, ya esta solucionado :)

sábado, febrero 02, 2008

como hacer algo simple de la manera complicada

class Kiace(object):
pass

kiace = Kiace()

for (num, l) in enumerate("kiace"):
setattr(kiace, l, (num, l))

l = [getattr(kiace, name) for name in dir(kiace) if not name.startswith('_')]
l.sort(cmp = lambda x, y: x[0] - y[0])

print ''.join([x[1] for x in l])


basicamente imprime kiace creando un objeto vacio, le agrega atributos, despues obtiene los atributos y los ordena para imprimir kiace

(?)

en realidad es una excusa para probar el resaltado de sintaxis HTML que nos proveen los muchachos de dpaste.com ;)

lunes, enero 28, 2008

No me quedo atras!

como se puede leer en http://www.cesarius.net/desarrollador-de-amarok-se-tatua-el-logo-en-el-brazo/ el desarrollador de amarok se tatuó el logo de su proyecto en el brazo, tuza (mi nuevo asistente de marketing para america latina) me mando una propuesta para que evalúe, se las pongo acá a ver que les parece:

lavoz.com.ar informacion confiable? al instante

titulo del articulo (por si lo cambian)

El fraude a Société Générale alcanzó los 50 millones de euros

titulo de clarin

Francia: Société Générale admitió que el fraude llegó a alcanzar los 50.000 millones de euros

primer párrafo de la nota en lavoz.com.ar

El presunto autor del fraude multimillonario contra Société Générale, uno de los mayores bancos de Francia, compró activos por un valor que alcanzó los 50.000 millones de euros

se les olvidaron unos ceros..

viernes, enero 25, 2008

Instalar solaris [Done]

Siempre quise probar solaris, y hoy llego el CD que había pedido hace unas semanas, así que no pude evitar gastar mi escaso tiempo en instalarlo, acá van una serie de observaciones y screenshots.

Observaciones:
  • Bootea en modo texto: no es para quejarse, un usuario que quiere ver eye candy no va a instalar solaris, pero mi examen es compararlo con ubuntu así que voy a notar las diferencias.
  • 768 MB de RAM para la instalación gráfica: no se si es bueno o malo, pero me obligo a ponerle los 512 MB que tenia por ahí :)
  • Aunque eleji la instalación gráfica el teclado se configura en una interfaz en ncurses.
  • En la seleccion de particiones, no puedo cambiar el tipo de partición a solaris si hay dos particiones del mismo tipo (WTF?).
  • Durante la instalación no hay información detallada sobre que esta haciendo, mas que un mensaje de "Instalando Solaris".
  • La consola de debug, que esta media escondida, es una consola en motif (feo), que no autocompleta y tiene el delete configurado raro.
  • La instalación demora casi 3 horas.
  • Grub se instalo sin detectarme ubuntu, ahora lo único que puedo bootear es solaris.
  • Cuando seleccionas reiniciar o apagar en cualquier lado, se demora mas de un minuto en hacerlo y no da ninguna información de que en realidad esta haciendo lo que le pediste (tanto en la instalación como en el uso del escritorio)
  • No tiene documentación offline, asume que tu red es dhcp y no te deja configurarla en ningún momento durante la instalación. Cuando booteas y vas a Administración -> Redes te dice que no se puede mostrar porque esta habilitado no se que cosa y que para usarla la tenes que deshabilitar (te dice que leas el man para deshabilitarlo).
  • No tengo sonido (aunque para ser una notebook, detecto todo el resto del hardware bastante bien)
  • La consola de root no es bash :S
  • CDE es horrible! (uso gnome 2.18)
  • A diferencia de MS, Sun si usa su lenguaje (Java) para sus aplicaciones.
  • tiene svn, python 2.4.4 y pygtk instalado.
  • emesene funciona una pinturita :P.
  • El look&feel es bastante bonito.
Bueno, basta de observaciones y a los screenshots! :P






jueves, enero 24, 2008

miércoles, enero 23, 2008

Decoradores, introspeccion y señales

Jugando un poco con decoradores y el modulo inspect por primera vez, se me ocurrió intentar reemplazar alguna funcionalidad de gobject.

La funcionalidad que implemente primero, que es bastante útil, es la de notificar a un objeto cuando un atributo de otro objeto cambia, por ejemplo, es útil para la lista de usuarios saber cuando el atributo "status" de un contacto cambia.
Lo que quería, era que las clases "notificadoras" y las clases "notificables" no tuvieran tanto código feo de manejo de eventos, para eso, decidí ver si los decoradores eran la solución, parece ser que si.

ejemplo, una clase "TestObject" tiene un atributo llamado "attribute" con las properties de get/set.
Eel código seria así:


class TestObject(object):
'''a class that have a property called attribute'''

def __init__(self, attribute):
'''class contructor'''
self._attribute = attribute

def set_attribute(self, attribute):
'''set the value of self._attribute'''
self._attribute = attribute

def get_attribute(self):
'''return the value of attribute'''
return self._attribute

attribute = property(fget=get_attribute, fset=set_attribute)


si, ya se que el property en ese caso es al pedo, pero va a ser requerido mas adelante, así que lo pongo :D.

ahora, una clase que desea ser notificada cuando el atributo "attribute" de la clase "TestObject" cambia.
El código seria mas o menos así:


class TestNotificable(object):
'''a class that is notified when an attribute on other object changes'''

def __init__(self):
'''class constructor'''
pass

def on_property_changed(self, obj, attr_name, method_name,
old_value, new_value):
'''method called when an attribute is changed
on an object that we are attached to
'''
print("%s: %s changed in %s(%s).%s from %s to %s" % \
(str(id(self)), attr_name, obj.__class__.__name__,
str(id(obj)), method_name, repr(old_value),
repr(new_value)))



no hay mucha magia, solo lo que necesitamos, un atributo y un método el cual es llamado cuando este atributo cambia

imaginen que haciendo:


obj = TestObject(5)
notificable = TestNotificable()
obj.attach(notificable)
obj.attribute = 10


la salida fuera:


3084746540: attribute changed in TestObject(3084722988).set_attribute from 5 to 10


estaría bueno, pero cuantas lineas habría que agregar a cada clase para eso?
si mis cálculos no fallan, 2 lineas a TestObject y ninguna a TestNotificable.

el código de las clases seria:


import signals

class TestNotificable(signals.Notificable):
'''a class that implements the notificable interface'''

def __init__(self):
'''class constructor'''
pass

def on_property_changed(self, obj, attr_name, method_name,
old_value, new_value):
'''method called when a method with the
@notify_change decorator from a signal.Object is called
'''
print "%s: %s changed in %s(%s).%s from %s to %s" % \
(str(id(self)), attr_name, obj.__class__.__name__,
str(id(obj)), method_name, repr(old_value),
repr(new_value))

class TestObject(signals.Object):
'''a class that have a property that notify when it's changed'''

def __init__(self, attribute):
'''class contructor'''
signals.Object.__init__(self)
self._attribute = attribute

@signals.notify_change
def set_attribute(self, attribute):
'''set the value of self._attribute'''
self._attribute = attribute

def get_attribute(self):
'''return the value of attribute'''
return self._attribute

attribute = property(fget=get_attribute, fset=set_attribute)


una función para probar el ejemplo:


def test():
'''test the implementation of signals'''
obj = TestObject(5)

notificable = TestNotificable()
obj.attach(notificable)

obj.attribute = 10

notificable1 = TestNotificable()
obj.attach(notificable1)

print("")
obj.attribute = None
print("")

notificable2 = TestNotificable()
obj.attach(notificable2)

try:
obj.attach("")
print("[EE] doesn't catch not notificables being attached")
except TypeError:
print("catch not notificables being attached")

notificable = None

if len(obj.notificables) == 2:
print("clean the list if a reference is removed")
else:
print("[EE] doesn't clean the list if a reference is removed")

print("")
obj.attribute = True

obj.deattach(notificable2)
print("\nshould show 1 notification\n")
obj.attribute = []

notificable1 = None

if len(obj.notificables) == 0:
print("clean the list if a reference is removed")
else:
print("[EE] doesn't clean the list if a reference is removed")

obj.attribute = "shouldn't be shown"

if __name__ == '__main__':
test()


que produce la salida:


3083871212: attribute changed in TestObject(3083871244).set_attribute from 5 to 10

3083871212: attribute changed in TestObject(3083871244).set_attribute from 10 to None
3083221740: attribute changed in TestObject(3083871244).set_attribute from 10 to None

catch not notificables being attached
clean the list if a reference is removed

3083221740: attribute changed in TestObject(3083871244).set_attribute from None to True
3083222572: attribute changed in TestObject(3083871244).set_attribute from None to True

should show 1 notification

3083221740: attribute changed in TestObject(3083871244).set_attribute from True to []
clean the list if a reference is removed


el código de signals.py es el siguiente:


import weakref
import inspect

'''a module that implement classes and methods to do signals on a pythonic
way
'''

class Object(object):
'''a class that represent an object that can call other objects
to notify about a changed property, must be used with the
@notify_change decorator, the classes that want to register
to receive notifications over property changes must inherit from
the Notificable interface
'''

def __init__(self):
'''class constructor'''
# a list of weakrefs
self.notificables = []

def notify_property_change(self, attr_name, method_name,
old_value, new_value):
'''call the on_property_changed of all the objects on the list
'''
# uncomment the code below to have a nice debug of the changes
# made to the properties on the objects that inherit from this
# class
#print("%s: %s changed in %s(%s).%s from %s to %s" % \
# (str(id(self)), attr_name, obj.__class__.__name__,
# str(id(obj)), method_name, repr(old_value),
# repr(new_value)))

for notificable in self.notificables:
notificable.on_property_changed(self, attr_name, method_name,
old_value, new_value)

def attach(self, notificable):
'''attach an object that implement the Notificable interface,
add a weakref so it's deleted when the other reference to the
object are 0
'''

if Notificable not in notificable.__class__.mro():
raise TypeError("the object must implement Notificable")

self.notificables.append(weakref.proxy(notificable,
self.__clean_refs))

def deattach(self, notificable):
'''remove the notificable obect from the list, if it exists'''
proxy = weakref.proxy(notificable)

if proxy in self.notificables:
self.notificables.remove(proxy)

def __clean_refs(self, reference):
'''remove the reference from the list, since it's going to be
cleaned by the garbage collector
'''

self.notificables.remove(reference)

class Notificable(object):
'''Interface that define the methods to be implemented to be able
to register to an signals.Object to receive notifications when
a method with the @notify_change decorator is called
'''

def on_property_changed(self, obj, attr_name, method_name,
old_value, new_value):
'''method called when a method with the
@notify_change decorator from a signal.Object is called
'''
pass

def notify_change(method):
'''decorator that add the ability to a setter/fset property to
notify other objects when an attribute of the object is modified
'''

def new_method(*args):
'''the function that decorates the class method, basically it
run the setter and then try to notify the objects about the
change, the setter is runned first since it may raise an
exception, and we dont want to notify over a change that
wasn't made
'''

arguments = inspect.getargspec(method)[0]

if Object not in args[0].__class__.mro():
raise TypeError("object doesn't inherit from signals.Object")

if len(arguments) != 2:
raise ValueError("method should receive two arguments")

self_object = args[0]
name = arguments[1]
method_name = method.__name__
old_value = getattr(self_object, name)
new_value = args[1]

return_value = method(*args)
self_object.notify_property_change(name, method_name,
old_value, new_value)

return return_value

return new_method

Seguidores

Archivo del Blog