=============================== ÐÑполÑзование ÑееÑÑÑа адапÑеÑов =============================== ÐаннÑй докÑÐ¼ÐµÐ½Ñ ÑодеÑÐ¶Ð¸Ñ Ð½ÐµÐ±Ð¾Ð»ÑÑÑÑ Ð´ÐµÐ¼Ð¾Ð½ÑÑÑаÑÐ¸Ñ Ð¿Ð°ÐºÐµÑа ``zope.interface`` и его ÑееÑÑÑа адапÑеÑов. ÐокÑÐ¼ÐµÐ½Ñ ÑаÑÑÑиÑÑвалÑÑ ÐºÐ°Ðº конкÑеÑнÑй, но более Ñзкий пÑÐ¸Ð¼ÐµÑ Ñого как иÑполÑзоваÑÑ Ð¸Ð½ÑеÑÑейÑÑ Ð¸ адапÑеÑÑ Ð²Ð½Ðµ Zope 3. СнаÑала нам Ð½ÐµÐ¾Ð±Ñ Ð¾Ð´Ð¸Ð¼Ð¾ импоÑÑиÑоваÑÑ Ð¿Ð°ÐºÐµÑ Ð´Ð»Ñ ÑабоÑÑ Ñ Ð¸Ð½ÑеÑÑейÑами:: >>> import zope.interface ТепеÑÑ Ð¼Ñ ÑазÑабоÑаем инÑеÑÑÐµÐ¹Ñ Ð´Ð»Ñ Ð½Ð°Ñего обÑекÑа - пÑоÑÑого Ñайла. ÐÐ°Ñ Ñайл бÑÐ´ÐµÑ ÑодеÑжаÑÑ Ð²Ñего один аÑÑибÑÑ - body, в коÑоÑом ÑакÑиÑеÑки бÑÐ´ÐµÑ ÑÐ¾Ñ Ñанено ÑодеÑжимое Ñайла:: >>> class IFile(zope.interface.Interface): ... ... body = zope.interface.Attribute(u'СодеÑжимое Ñайла.') ... ÐÐ»Ñ ÑÑаÑиÑÑики нам ÑаÑÑо Ð½ÐµÐ¾Ð±Ñ Ð¾Ð´Ð¸Ð¼Ð¾ знаÑÑ ÑÐ°Ð·Ð¼ÐµÑ Ñайла. Ðо бÑло Ð±Ñ Ð½ÐµÑколÑко ÑопоÑно ÑеализовÑваÑÑ Ð¾Ð¿Ñеделение ÑазмеÑа пÑÑмо Ð´Ð»Ñ Ð¾Ð±ÑекÑа Ñайла, Ñ.к. ÑÐ°Ð·Ð¼ÐµÑ Ð±Ð¾Ð»ÑÑе оÑноÑиÑÑÑ Ðº меÑа-даннÑм. Таким обÑазом Ð¼Ñ Ñоздаем еÑе один инÑеÑÑÐµÐ¹Ñ Ð´Ð»Ñ Ð¿ÑедÑÑÐ°Ð²Ð»ÐµÐ½Ð¸Ñ ÑазмеÑа какого-либо обÑекÑа:: >>> class ISize(zope.interface.Interface): ... ... def getSize(): ... 'Return the size of an object.' ... ТепеÑÑ Ð¼Ñ Ð´Ð¾Ð»Ð¶Ð½Ñ ÑоздаÑÑ ÐºÐ»Ð°ÑÑ ÑеализÑÑÑий Ð½Ð°Ñ Ñайл. ÐÐµÐ¾Ð±Ñ Ð¾Ð´Ð¸Ð¼Ð¾ ÑÑо Ð±Ñ Ð½Ð°Ñ Ð¾Ð±ÑÐµÐºÑ Ñ Ñанил инÑоÑмаÑÐ¸Ñ Ð¾ Ñом, ÑÑо он ÑеализÑÐµÑ Ð¸Ð½ÑеÑÑÐµÐ¹Ñ `IFile`. ÐÑ Ñакже Ñоздаем аÑÑибÑÑ Ñ ÑодеÑжимÑм Ñайла по ÑмолÑÐ°Ð½Ð¸Ñ (Ð´Ð»Ñ ÑпÑоÑÐµÐ½Ð¸Ñ Ð½Ð°Ñего пÑимеÑа):: >>> class File(object): ... ... zope.interface.implements(IFile) ... body = 'foo bar' ... ÐалÑÑе Ð¼Ñ Ñоздаем адапÑеÑ, коÑоÑÑй бÑÐ´ÐµÑ Ð¿ÑедоÑÑавлÑÑÑ Ð¸Ð½ÑеÑÑÐµÐ¹Ñ `ISize` полÑÑÐ°Ñ Ð»Ñбой обÑÐµÐºÑ Ð¿ÑедоÑÑавлÑÑÑий инÑеÑÑÐµÐ¹Ñ `IFile`. Ðо ÑоглаÑÐµÐ½Ð¸Ñ Ð¼Ñ Ð¸ÑполÑзÑем аÑÑибÑÑ `__used_for__` Ð´Ð»Ñ ÑÐºÐ°Ð·Ð°Ð½Ð¸Ñ Ð¸Ð½ÑеÑÑейÑа коÑоÑÑй как Ð¼Ñ Ð¾Ð¶Ð¸Ð´Ð°ÐµÐ¼ пÑедоÑÑавлÑÐµÑ Ð°Ð´Ð°Ð¿ÑиÑÑемÑй обÑекÑ, `IFile` в наÑем ÑлÑÑае. Ðа Ñамом деле ÑÑÐ¾Ñ Ð°ÑÑибÑÑ Ð¸ÑполÑзÑеÑÑÑ ÑолÑко Ð´Ð»Ñ Ð´Ð¾ÐºÑменÑиÑованиÑ. Ð ÑлÑÑае еÑли адапÑÐµÑ Ð¸ÑполÑзÑеÑÑÑ Ð´Ð»Ñ Ð½ÐµÑколÑÐºÐ¸Ñ Ð¸Ð½ÑеÑÑейÑов можно ÑказаÑÑ Ð¸Ñ Ð²Ñе в виде коÑÑежа. ÐпÑÑÑ Ð¶Ðµ по ÑоглаÑÐµÐ½Ð¸Ñ ÐºÐ¾Ð½ÑÑÑÑкÑÐ¾Ñ Ð°Ð´Ð°Ð¿ÑеÑа полÑÑÐ°ÐµÑ Ð¾Ð´Ð¸Ð½ аÑгÑÐ¼ÐµÐ½Ñ - context (конÑекÑÑ). РнаÑем ÑлÑÑае конÑекÑÑ - ÑÑо ÑкземплÑÑ `IFile` (обÑекÑ, пÑедоÑÑавлÑÑÑий `IFile`) коÑоÑÑй иÑполÑзÑеÑÑÑ Ð´Ð»Ñ Ð¿Ð¾Ð»ÑÑÐµÐ½Ð¸Ñ Ð¸Ð· него ÑазмеÑа. Так же по ÑоглаÑÐµÐ½Ð¸Ñ ÐºÐ¾Ð½ÑекÑÑ ÑÐ¾Ñ ÑанÑеÑÑÑ Ð° адапÑеÑе в аÑÑибÑÑе Ñ Ð¸Ð¼ÐµÐ½ÐµÐ¼ `context`. Twisted комÑÑниÑи ÑÑÑлаеÑÑÑ Ð½Ð° конÑекÑÑ ÐºÐ°Ðº на обÑÐµÐºÑ `original`. Таким обÑазом можно Ñакже даÑÑ Ð°ÑгÑменÑÑ Ð»Ñбое Ð¿Ð¾Ð´Ñ Ð¾Ð´ÑÑее имÑ, напÑÐ¸Ð¼ÐµÑ `file`:: >>> class FileSize(object): ... ... zope.interface.implements(ISize) ... __used_for__ = IFile ... ... def __init__(self, context): ... self.context = context ... ... def getSize(self): ... return len(self.context.body) ... ТепеÑÑ ÐºÐ¾Ð³Ð´Ð° Ð¼Ñ Ð½Ð°Ð¿Ð¸Ñали Ð½Ð°Ñ Ð°Ð´Ð°Ð¿ÑÐµÑ Ð¼Ñ Ð´Ð¾Ð»Ð¶Ð½Ñ Ð·Ð°ÑегиÑÑÑиÑоваÑÑ ÐµÐ³Ð¾ в ÑееÑÑÑе адапÑеÑов, ÑÑо Ð±Ñ ÐµÐ³Ð¾ можно бÑло запÑоÑиÑÑ ÐºÐ¾Ð³Ð´Ð° он понадобиÑÑÑ. ÐдеÑÑ Ð½ÐµÑ ÐºÐ°ÐºÐ¾Ð³Ð¾-либо глобалÑного ÑееÑÑÑа адапÑеÑов, Ñаким обÑазом Ð¼Ñ Ð´Ð¾Ð»Ð¶Ð½Ñ ÑамоÑÑоÑÑелÑно ÑоздаÑÑ Ð´Ð»Ñ Ð½Ð°Ñего пÑимеÑа ÑееÑÑÑ:: >>> from zope.interface.adapter import AdapterRegistry >>> registry = AdapterRegistry() РееÑÑÑ ÑодеÑÐ¶Ð¸Ñ Ð¾ÑобÑажение Ñого, ÑÑо адапÑÐµÑ ÑеализÑÐµÑ Ð½Ð° оÑнове дÑÑгого инÑеÑÑейÑа коÑоÑÑй пÑедоÑÑавлÑÐµÑ Ð¾Ð±ÑекÑ. ÐоÑÑÐ¾Ð¼Ñ Ð´Ð°Ð»ÑÑе Ð¼Ñ ÑегиÑÑÑиÑÑем адапÑÐµÑ ÐºÐ¾ÑоÑÑй адапÑиÑÑÐµÑ Ð¸Ð½ÑеÑÑÐµÐ¹Ñ `IFile` к инÑеÑÑейÑÑ `ISize`. ÐеÑвÑй аÑгÑÐ¼ÐµÐ½Ñ Ðº меÑÐ¾Ð´Ñ `register()` ÑееÑÑÑа - ÑÑо ÑпиÑок адапÑиÑÑемÑÑ Ð¸Ð½ÑеÑÑейÑов. РнаÑем ÑлÑÑае Ð¼Ñ Ð¸Ð¼ÐµÐµÐ¼ ÑолÑко один адапÑиÑÑемÑй инÑеÑÑÐµÐ¹Ñ - `IFile`. СпиÑок инÑеÑÑейÑов Ð¸Ð¼ÐµÐµÑ ÑмÑÑл Ð´Ð»Ñ Ð¸ÑполÑÐ·Ð¾Ð²Ð°Ð½Ð¸Ñ ÐºÐ¾Ð½ÑепÑии мÑлÑÑи-адапÑеÑов, коÑоÑÑе ÑÑебÑÑÑ Ð½ÐµÑколÑÐºÐ¸Ñ Ð¾ÑигиналÑнÑÑ Ð¾Ð±ÑекÑов Ð´Ð»Ñ Ð°Ð´Ð°Ð¿ÑаÑии к Ð½Ð¾Ð²Ð¾Ð¼Ñ Ð¸Ð½ÑеÑÑейÑÑ. Ð ÑÑой ÑиÑÑаÑии конÑÑÑÑкÑÐ¾Ñ Ð°Ð´Ð°Ð¿ÑеÑа бÑÐ´ÐµÑ ÑÑебоваÑÑ Ð½Ð¾Ð²Ñй аÑгÑÐ¼ÐµÐ½Ñ Ð´Ð»Ñ ÐºÐ°Ð¶Ð´Ð¾Ð³Ð¾ оÑигиналÑного инÑеÑÑейÑа. ÐÑоÑой аÑгÑÐ¼ÐµÐ½Ñ Ð¼ÐµÑода `register()` - ÑÑо инÑеÑÑÐµÐ¹Ñ ÐºÐ¾ÑоÑÑй пÑедоÑÑавлÑÐµÑ Ð°Ð´Ð°Ð¿ÑеÑ, в наÑем ÑлÑÑае `ISize`. ТÑеÑий аÑгÑÐ¼ÐµÐ½Ñ - Ð¸Ð¼Ñ Ð°Ð´Ð°Ð¿ÑеÑа. СейÑÐ°Ñ Ð½Ð°Ð¼ не важно Ð¸Ð¼Ñ Ð°Ð´Ð°Ð¿ÑеÑа и Ð¼Ñ Ð¿ÐµÑедаем его как пÑÑÑÑÑ ÑÑÑокÑ. ÐбÑÑно имена Ð¿Ð¾Ð»ÐµÐ·Ð½Ñ ÐµÑли иÑполÑзÑÑÑÑÑ Ð°Ð´Ð°Ð¿ÑеÑÑ Ð´Ð»Ñ Ð¾Ð´Ð¸Ð½Ð°ÐºÐ¾Ð²Ð¾Ð³Ð¾ набоÑа инÑеÑÑейÑов, но в ÑазлиÑнÑÑ ÑиÑÑаÑиÑÑ . ÐоÑледний аÑгÑÐ¼ÐµÐ½Ñ - ÑÑо клаÑÑ Ð°Ð´Ð°Ð¿ÑеÑа:: >>> registry.register([IFile], ISize, '', FileSize) ТепеÑÑ Ð¼Ñ Ð¼Ð¾Ð¶ÐµÐ¼ иÑполÑзоваÑÑ ÑееÑÑÑ Ð´Ð»Ñ Ð·Ð°Ð¿ÑоÑа адапÑеÑа:: >>> registry.lookup1(IFile, ISize, '') <class '__main__.FileSize'> ÐопÑобÑем более пÑакÑиÑнÑй пÑимеÑ. Создадим ÑкземплÑÑ `File` и Ñоздадим адапÑÐµÑ Ð¸ÑполÑзÑÑÑий запÑÐ¾Ñ ÑееÑÑÑа. ÐаÑем Ð¼Ñ Ñвидим возвÑаÑÐ°ÐµÑ Ð»Ð¸ адапÑÐµÑ ÐºÐ¾ÑÑекÑнÑй ÑÐ°Ð·Ð¼ÐµÑ Ð¿Ñи вÑзове `getSize()`:: >>> file = File() >>> size = registry.lookup1(IFile, ISize, '')(file) >>> size.getSize() 7 Ðа Ñамом деле ÑÑо не оÑÐµÐ½Ñ Ð¿ÑакÑиÑно, Ñ.к. нам нÑжно Ñамим пеÑедаваÑÑ Ð²Ñе аÑгÑменÑÑ Ð¼ÐµÑÐ¾Ð´Ñ Ð·Ð°Ð¿ÑоÑа. СÑÑеÑÑвÑÐµÑ Ð½ÐµÐºÐ¾ÑоÑÑй ÑинÑакÑиÑеÑкий Ð»ÐµÐ´ÐµÐ½ÐµÑ ÐºÐ¾ÑоÑÑй позволÑÐµÑ Ð½Ð°Ð¼ полÑÑиÑÑ ÑкземплÑÑ Ð°Ð´Ð°Ð¿ÑеÑа пÑоÑÑо вÑзвав `ISize(file)`. ЧÑо Ð±Ñ Ð¸ÑполÑзоваÑÑ ÑÑÑ ÑÑнкÑионалÑноÑÑÑ Ð½Ð°Ð¼ понадобиÑÑÑ Ð´Ð¾Ð±Ð°Ð²Ð¸ÑÑ Ð½Ð°Ñ ÑееÑÑÑ Ðº ÑпиÑÐºÑ adapter_hooks, коÑоÑÑй Ð½Ð°Ñ Ð¾Ð´Ð¸ÑÑÑ Ð² модÑле Ñ Ð°Ð´Ð°Ð¿ÑеÑами. ÐÑÐ¾Ñ ÑпиÑок Ñ ÑÐ°Ð½Ð¸Ñ ÐºÐ¾Ð»Ð»ÐµÐºÑÐ¸Ñ Ð²ÑзÑваемÑÑ Ð¾Ð±ÑекÑов коÑоÑÑе вÑзÑваÑÑÑÑ Ð°Ð²ÑомаÑиÑеÑки когда вÑзÑваеÑÑÑ IFoo(obj); Ð¸Ñ Ð¿ÑедназнаÑение - найÑи адапÑеÑÑ ÐºÐ¾ÑоÑÑе ÑеализÑÑÑ Ð¸Ð½ÑеÑÑÐµÐ¹Ñ Ð´Ð»Ñ Ð¾Ð¿Ñеделенного ÑкземплÑÑа конÑекÑÑа. ÐÐµÐ¾Ð±Ñ Ð¾Ð´Ð¸Ð¼Ð¾ ÑеализоваÑÑ ÑÐ²Ð¾Ñ ÑобÑÑвеннÑÑ ÑÑнкÑÐ¸Ñ Ð´Ð»Ñ Ð¿Ð¾Ð¸Ñка адапÑеÑа; даннÑй пÑÐ¸Ð¼ÐµÑ Ð¾Ð¿Ð¸ÑÑÐ²Ð°ÐµÑ Ð¾Ð´Ð½Ñ Ð¸Ð· пÑоÑÑейÑÐ¸Ñ ÑÑнкÑий Ð´Ð»Ñ Ð¸ÑполÑÐ·Ð¾Ð²Ð°Ð½Ð¸Ñ Ñ ÑееÑÑÑом, но Ñакже можно ÑеализоваÑÑ Ð¿Ð¾Ð¸ÑковÑе ÑÑнкÑии коÑоÑÑе, напÑимеÑ, иÑполÑзÑÑÑ ÐºÑÑиÑование, или адапÑеÑÑ ÑÐ¾Ñ ÑанÑемÑе в базе. ФÑнкÑÐ¸Ñ Ð¿Ð¾Ð¸Ñка должна пÑинимаÑÑ Ð¶ÐµÐ»Ð°ÐµÐ¼Ñй на вÑÑ Ð¾Ð´Ðµ инÑеÑÑÐµÐ¹Ñ (в наÑем ÑлÑÑае `ISize`) как пеÑвÑй аÑгÑÐ¼ÐµÐ½Ñ Ð¸ конÑекÑÑ Ð´Ð»Ñ Ð°Ð´Ð°Ð¿ÑаÑии (`file`) как вÑоÑой. ФÑнкÑÐ¸Ñ Ð´Ð¾Ð»Ð¶Ð½Ð° веÑнÑÑÑ Ð°Ð´Ð°Ð¿ÑеÑ, Ñ.е. ÑкземплÑÑ `FileSize`:: >>> def hook(provided, object): ... adapter = registry.lookup1(zope.interface.providedBy(object), ... provided, '') ... return adapter(object) ... ТепеÑÑ Ð¼Ñ Ð¿ÑоÑÑо добавлÑем наÑÑ ÑÑнкÑÐ¸Ñ Ðº ÑпиÑÐºÑ `adapter_hooks`:: >>> from zope.interface.interface import adapter_hooks >>> adapter_hooks.append(hook) Ðак ÑолÑко ÑÑнкÑÐ¸Ñ Ð·Ð°ÑегиÑÑÑиÑована Ð¼Ñ Ð¼Ð¾Ð¶ÐµÐ¼ иÑполÑзоваÑÑ Ð¶ÐµÐ»Ð°ÐµÐ¼Ñй ÑинÑакÑиÑ:: >>> size = ISize(file) >>> size.getSize() 7 ÐоÑле нам нÑжно пÑибÑаÑÑÑÑ Ð·Ð° Ñобой, ÑÑо Ð±Ñ Ð´ÑÑгие полÑÑили ÑиÑÑÑй ÑпиÑок `adaper_hooks` поÑле наÑ:: >>> adapter_hooks.remove(hook) ÐÑо вÑе. ÐдеÑÑ Ð½Ð°Ð¼ÐµÑенно оÑложена диÑкÑÑÑÐ¸Ñ Ð¾Ð± именованнÑÑ Ð¸ мÑлÑÑи-адапÑеÑÐ°Ñ , Ñ.к. даннÑй ÑекÑÑ ÑаÑÑÑиÑан как пÑакÑиÑеÑкое и пÑоÑÑое введение в инÑеÑÑейÑÑ Ð¸ адапÑеÑÑ Zope 3. ÐÐ»Ñ Ð±Ð¾Ð»ÐµÐµ подÑобной инÑоÑмаÑии Ð¸Ð¼ÐµÐµÑ ÑмÑÑл пÑоÑиÑаÑÑ `adapter.txt` из пакеÑа `zope.interface`, ÑÑо Ð±Ñ Ð¿Ð¾Ð»ÑÑиÑÑ Ð±Ð¾Ð»ÐµÐµ ÑоÑмалÑное, ÑпÑавоÑное и полное ÑÑакÑование пакеÑа. Ðнимание: многие жаловалиÑÑ, ÑÑо `adapter.txt` пÑÐ¸Ð²Ð¾Ð´Ð¸Ñ Ð¸Ñ Ð¼Ð¾Ð·Ð³ к ÑаÑÐ¿Ð»Ð°Ð²Ð»ÐµÐ½Ð½Ð¾Ð¼Ñ ÑоÑÑоÑниÑ!