Como otro enfoque para el sistema de complementos, puede marcar el proyecto Extenderme .
Por ejemplo, definamos una clase simple y su extensión
# Define base class for extensions (mount point)
class MyCoolClass(Extensible):
my_attr_1 = 25
def my_method1(self, arg1):
print('Hello, %s' % arg1)
# Define extension, which implements some aditional logic
# or modifies existing logic of base class (MyCoolClass)
# Also any extension class maby be placed in any module You like,
# It just needs to be imported at start of app
class MyCoolClassExtension1(MyCoolClass):
def my_method1(self, arg1):
super(MyCoolClassExtension1, self).my_method1(arg1.upper())
def my_method2(self, arg1):
print("Good by, %s" % arg1)
Y trata de usarlo:
>>> my_cool_obj = MyCoolClass()
>>> print(my_cool_obj.my_attr_1)
25
>>> my_cool_obj.my_method1('World')
Hello, WORLD
>>> my_cool_obj.my_method2('World')
Good by, World
Y muestra lo que se esconde detrás de la escena:
>>> my_cool_obj.__class__.__bases__
[MyCoolClassExtension1, MyCoolClass]
La biblioteca extend_me manipula el proceso de creación de clases a través de metaclases, por lo tanto, en el ejemplo anterior, cuando creamos una nueva instancia de MyCoolClass
tenemos una nueva clase que es subclase de ambos MyCoolClassExtension
y que MyCoolClass
tiene funcionalidad de ambos, gracias a la herencia múltiple de Python
Para un mejor control sobre la creación de clases, hay pocas metaclases definidas en esta biblioteca:
ExtensibleType
- permite una extensibilidad simple mediante subclases
ExtensibleByHashType
- similar a ExtensibleType, pero con capacidad para construir versiones especializadas de clase, permitiendo la extensión global de la clase base y la extensión de versiones especializadas de clase
¡Esta lib se usa en OpenERP Proxy Project y parece estar funcionando lo suficientemente bien!
Para un ejemplo real de uso, busque en la extensión 'field_datetime' del proxy OpenERP :
from ..orm.record import Record
import datetime
class RecordDateTime(Record):
""" Provides auto conversion of datetime fields from
string got from server to comparable datetime objects
"""
def _get_field(self, ftype, name):
res = super(RecordDateTime, self)._get_field(ftype, name)
if res and ftype == 'date':
return datetime.datetime.strptime(res, '%Y-%m-%d').date()
elif res and ftype == 'datetime':
return datetime.datetime.strptime(res, '%Y-%m-%d %H:%M:%S')
return res
Record
Aquí hay un objeto extensible. RecordDateTime
Es extensión.
Para habilitar la extensión, solo importe el módulo que contiene la clase de extensión y (en el caso anterior) todos los Record
objetos creados después de que tenga la clase de extensión en las clases base, teniendo así toda su funcionalidad.
La principal ventaja de esta biblioteca es que, el código que opera objetos extensibles, no necesita saber acerca de la extensión y las extensiones podrían cambiar todo en objetos extensibles.