В качестве одного из подходов к системе плагинов, вы можете выбрать Расширить проект .
Например, давайте определим простой класс и его расширение
# 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)
И попробуйте использовать это:
>>> 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
И покажи, что скрыто за сценой:
>>> my_cool_obj.__class__.__bases__
[MyCoolClassExtension1, MyCoolClass]
exte_me библиотека управляет процессом создания класса с помощью метаклассов, таким образом, в примере выше, при создании нового экземпляра MyCoolClass
мы получили экземпляр нового класса, который является подклассом MyCoolClassExtension
и MyCoolClass
, имеющих функциональность обоих из них, благодаря множественному наследованию Python 1020 *
Для лучшего контроля над созданием классов в этой библиотеке определено несколько метаклассов:
ExtensibleType
- допускает простую расширяемость путем подкласса
ExtensibleByHashType
- похоже на ExtensibleType, но обладает способностью
создавать специализированные версии класса, позволяющие глобальное расширение
базового класса и расширение специализированных версий класса
Эта библиотека используется в OpenERP Proxy Project и, кажется, работает достаточно хорошо!
Для реального примера использования, посмотрите в Расширение 'OpenERP Proxy' field_datetime ':
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
здесь это расширяемый объект. RecordDateTime
это расширение.
Чтобы включить расширение, просто импортируйте модуль, который содержит класс расширения, и (в случае выше) все объекты Record
, созданные после него, будут иметь класс расширения в базовых классах, таким образом, имея всю его функциональность.
Основным преимуществом этой библиотеки является то, что код, который управляет расширяемыми объектами, не должен знать о расширении, и расширения могут изменить все в расширяемых объектах.