Quote (ya perdi la cuenta)
"The key to performance is elegance, not battalions of special cases."
- Jon Bentley and Doug McIlroy
This is my blog, more about me at marianoguerra.github.io
🦋 @marianoguerra.org 🐘 @marianoguerra@hachyderm.io 🐦 @warianoguerra
"The key to performance is elegance, not battalions of special cases."
- Jon Bentley and Doug McIlroy
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)
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)))
obj = TestObject(5)
notificable = TestNotificable()
obj.attach(notificable)
obj.attribute = 10
3084746540: attribute changed in TestObject(3084722988).set_attribute from 5 to 10
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)
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()
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
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
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?
leyendo clarin, veo esta noticia: http://www.clarin.com/diario/2008/01/10/um/m-01582119.htm
A titulo "Saquean una casa de Caballito mientras sus dueños estaban de viaje".
Esta noticia me hizo pensar dos cosas:
los invito a leer mi post en el blog de emesene sobre la censura en msn
http://emesene.org/blog/2007/12/15/pwned11oneeleven/
este codigo es una partecita de una libreria para manejar VESA en DOS que escribi hace 5 años, esta parte me encanta, porque esa lib esta toda escrita para hacer todo independiente de la resolucion, los bits por pixel y los bancos del modo (una cosa que es una porqueria:
esta parte:
void Video::putPixel( word x , word y , byte red , byte green , byte blue )
{
word color = ( ( word )( red & ( ( 1
color |= ( ( word )( green & ( ( 1
color |= ( ( word )( blue & ( ( 1
long addr = (long)y * vbeModeInfoBlock.BytesPerScanLine + x * (vbeModeInfoBlock.BitsPerPixel >> 3);
setBank((int)(addr >> 16));
*(videoMemory + (addr & 0xFFFF)) = (char)color;
*(videoMemory + (addr & 0xFFFF) + 1 ) = (char)(color >> 8);
}
que seria de este blog si no me dedicara sistemáticamente a robarle contenido a un grande.
seria la misma porquería, pero bueno...
acá van algunas perlitas:
experimento 1 Colectivos
experimento 2 Taxis
experimento 3 Canteros
experimento 4 Vendedores
mi notebook se esta convirtiendo lentamente en un centro de desarrollo, ya tiene:
* pastebin
* viewvc
* Apache/2.2.4 (Ubuntu) mod_python/3.3.1 Python/2.5.1 PHP/5.2.3-1ubuntu6.2
* mysql
* postgres
iba a instalar mediawiki, pero pensé que hay una solución interesante que también pensaba instalar que ya tiene wiki, así que pensé en instalar trac, se me ocurrió ver si servía administrar la vida con trac.
* tickets como un TODO personal y laboral
* wiki para ir escribiendo cosas que luego se convertirán en trabajos, posts, documentaciones variadas
* integración con svn para ver en que andan mis desarrollos locales
* no se me ocurre nada mas por ahora... (ideas?)
sudo trac-admin /var/mariano-trac initenv
Project Name [My Project]> Vida de Mariano
Database connection string [sqlite:db/trac.db]>
Repository type [svn]>
Path to repository [/path/to/repos]> /svnroot
Templates directory [/usr/share/trac/templates]>
sudo vim /var/mariano-trac/conf/trac.ini
chwon www-data.www-data /var/mariano-trac
sudo vim /var/mariano-trac/conf/trac.ini
sudo htpasswd -c -m /etc/apache2/trac.htpasswd mariano
New password:
Re-type new password:
Adding password for user mariano
sudo vim /etc/apache2/sites-available/trac
cat /etc/apache2/sites-available/trac
<virtualhost>
ServerName trac.localhost
SetHandler mod_python
PythonHandler trac.web.modpython_frontend
PythonOption TracEnv /var/mariano-trac
</virtualhost>
<location>
AuthType Basic
AuthName "vida de marianoguerra"
AuthUserFile /etc/apache2/trac.htpasswd
Require valid-user
</location>
sudo a2ensite trac
sudo /etc/init.d/apache2 force-reload