Come un altro approccio al sistema di plugin, è possibile controllare il progetto Extend Me .
Ad esempio, definiamo la classe semplice e la sua estensione
# 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 prova ad 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
E mostra ciò che è nascosto dietro la scena:
>>> my_cool_obj.__class__.__bases__
[MyCoolClassExtension1, MyCoolClass]
La libreria extension_me manipola il processo di creazione della classe tramite metaclass, quindi nell'esempio sopra, quando si crea una nuova istanza di MyCoolClass
abbiamo un'istanza di nuova classe che è una sottoclasse di entrambi MyCoolClassExtension
e MyCoolClass
con funzionalità di entrambi, grazie all'eredità multipla di Python
Per un migliore controllo sulla creazione di classi ci sono alcune metaclasse definite in questa libreria:
ExtensibleType
- consente una semplice estensibilità tramite la sottoclasse
ExtensibleByHashType
- simile a ExtensibleType, ma con la possibilità di creare versioni specializzate della classe, consentendo l'estensione globale della classe base e l'estensione delle versioni specializzate della classe
Questa libreria è utilizzata nel progetto proxy OpenERP e sembra funzionare abbastanza bene!
Per un vero esempio di utilizzo, guarda l'estensione '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
qui è un oggetto estensibile. RecordDateTime
è estensione.
Per abilitare l'estensione, basta importare il modulo che contiene la classe di estensione e (nel caso sopra) tutti gli Record
oggetti creati dopo avranno classe di estensione nelle classi di base, avendo così tutte le sue funzionalità.
Il vantaggio principale di questa libreria è che, il codice che gestisce oggetti estensibili, non ha bisogno di conoscere l'estensione e le estensioni potrebbero cambiare tutto in oggetti estensibili.