Como uma outra abordagem ao sistema de plug-ins, você pode verificar o projeto Estender-me .
Por exemplo, vamos definir classe simples e sua extensão
# 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)
E tente usá-lo:
>>> 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
E mostre o que está oculto nos bastidores:
>>> my_cool_obj.__class__.__bases__
[MyCoolClassExtension1, MyCoolClass]
A biblioteca extend_me manipula o processo de criação de classe por meio de metaclasses, assim no exemplo acima, ao criar uma nova instância, MyCoolClass
obtemos uma instância de nova classe que é subclasse de ambos MyCoolClassExtension
e que MyCoolClass
possui funcionalidade de ambos, graças à herança múltipla do Python
Para melhor controle sobre a criação de classes, existem poucas metaclasses definidas nesta lib:
ExtensibleType
- permite extensibilidade simples subclassificando
ExtensibleByHashType
- semelhante ao ExtensibleType, mas com capacidade de criar versões especializadas de classe, permitindo a extensão global da classe base e a extensão de versões especializadas da classe
Essa lib é usada no OpenERP Proxy Project e parece estar funcionando suficientemente bem!
Para um exemplo real de uso, consulte a extensão 'field_datetime' do OpenERP Proxy :
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
aqui está um objeto extesível. RecordDateTime
é extensão.
Para habilitar a extensão, apenas importe o módulo que contém a classe de extensão e (no caso acima) todos os Record
objetos criados depois dela terão classe de extensão nas classes base, possuindo assim toda a sua funcionalidade.
A principal vantagem dessa biblioteca é que, o código que opera objetos extensíveis, não precisa saber sobre extensão e as extensões podem mudar tudo em objetos extensíveis.