Software: Apache/2.2.16 (Debian). PHP/5.3.3-7+squeeze19 uname -a: Linux mail.tri-specialutilitydistrict.com 2.6.32-5-amd64 #1 SMP Tue May 13 16:34:35 UTC uid=33(www-data) gid=33(www-data) groups=33(www-data) Safe-mode: OFF (not secure) /usr/lib/python2.6/dist-packages/zope/interface/ drwxr-xr-x |
Viewing file: Select action/file-type: =============================== Рспользование реестра адаптеров =============================== Данный документ содержит небольшую демонстрацию пакета ``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` РїСЂРёРІРѕРґРёС‚ РёС… РјРѕР·Рі Рє расплавленному состоянию! |
:: Command execute :: | |
--[ c99shell v. 2.0 [PHP 7 Update] [25.02.2019] maintained by KaizenLouie | C99Shell Github | Generation time: 0.0138 ]-- |