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
miércoles, mayo 28, 2008
sábado, mayo 24, 2008
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
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.
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.
sábado, mayo 03, 2008
miércoles, abril 30, 2008
sábado, abril 19, 2008
openbox
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:
cuya salida es:
usando el modulo sandbox podemos hacer:
la salida es:
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:
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:
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:
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 ;)
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)
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.
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..
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 :)
* 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..
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:




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.




jueves, enero 24, 2008
Quote (ya perdi la cuenta)
"The key to performance is elegance, not battalions of special cases."
- Jon Bentley and Doug McIlroy
- Jon Bentley and Doug McIlroy
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í:
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í:
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:
la salida fuera:
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:
una función para probar el ejemplo:
que produce la salida:
el código de signals.py es el siguiente:
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
miércoles, enero 16, 2008
Buzzword marketing
por alguna razón derivada de la compra de BEA por parte de Oracle termine leyendo la descripción de dos productos de esta empresa para saber a que se dedican aparte de su J2EE Aplication server, entre a ver dos descripciones:
BEA Tuxedo
BEA aqualogic
se hace casi imposible deducir que es lo que hacen, es una descripción totalmente genérica, retorcida y llena de buzzwords, algunos extractos sublimes, pero los invito a leer la descripción y sin consultar fuentes externas, deducir que hacen estos dos productos.
"Usted necesita una plataforma de infraestructura de aplicaciones probada, fiable y escalable: una plataforma que pueda conectar y autorizar a todo tipo de usuarios, a la vez que integra todas sus aplicaciones y datos corporativos en una solución de e-commerce poderosa, flexible y de punto a punto."
"BEA Tuxedo elimina el tiempo, la complejidad y el riesgo de desarrollar y desplegar esta solución."
"La agilidad de la empresa depende del flujo libre de información, servicios y procesos empresariales por toda la organización"
"La Arquitectura Orientada a Servicios (SOA) ha emergido como la estrategia principal de la TI para perfeccionar la presentación de servicios. SOA toma las funciones empresariales discretas contenidas en aplicaciones empresariales y las organiza en servicios interoperativos y basados en estándares que pueden combinarse y reutilizarse rápidamente en procesos y aplicaciones compuestas."
"La Infraestructura de Servicios, se adhiere a los principios de SOA de servicios de grano grueso, débilmente acoplados y basados en servicios para presentar un contenedor neutral para la lógica empresarial que aísla las complejidades de las tecnologías suyacentes."
me envuelve una docena para llevar?
BEA Tuxedo
BEA aqualogic
se hace casi imposible deducir que es lo que hacen, es una descripción totalmente genérica, retorcida y llena de buzzwords, algunos extractos sublimes, pero los invito a leer la descripción y sin consultar fuentes externas, deducir que hacen estos dos productos.
"Usted necesita una plataforma de infraestructura de aplicaciones probada, fiable y escalable: una plataforma que pueda conectar y autorizar a todo tipo de usuarios, a la vez que integra todas sus aplicaciones y datos corporativos en una solución de e-commerce poderosa, flexible y de punto a punto."
"BEA Tuxedo elimina el tiempo, la complejidad y el riesgo de desarrollar y desplegar esta solución."
"La agilidad de la empresa depende del flujo libre de información, servicios y procesos empresariales por toda la organización"
"La Arquitectura Orientada a Servicios (SOA) ha emergido como la estrategia principal de la TI para perfeccionar la presentación de servicios. SOA toma las funciones empresariales discretas contenidas en aplicaciones empresariales y las organiza en servicios interoperativos y basados en estándares que pueden combinarse y reutilizarse rápidamente en procesos y aplicaciones compuestas."
"La Infraestructura de Servicios, se adhiere a los principios de SOA de servicios de grano grueso, débilmente acoplados y basados en servicios para presentar un contenedor neutral para la lógica empresarial que aísla las complejidades de las tecnologías suyacentes."
me envuelve una docena para llevar?
Suscribirse a:
Entradas (Atom)
Seguidores
Archivo del Blog
-
►
2011
(74)
- ► septiembre (4)
-
►
2010
(111)
- ► septiembre (8)
-
►
2009
(96)
- ► septiembre (3)
-
►
2008
(60)
- ► septiembre (8)
-
►
2007
(64)
- ► septiembre (1)
-
►
2006
(81)
- ► septiembre (1)
