Personal tools
You are here: Home Статьи Разные мелкие заметки Как работает SiteManager что бы обеспечить доступ к локальным утилитам
Document Actions

Как работает SiteManager что бы обеспечить доступ к локальным утилитам

by cray last modified 2006-12-13 23:00

Как работает SiteManager что бы обеспечить доступ к локальным утилитам

Забавно устроен Zope. Есть глобальный SiteManager, есть куча локальных SiteManager-ов. Естественно, ряд запросов должен обрабатываться локальным SiteManager. В теории (т.е. если посмотреть написанные коды), что бы получить его, нужно дернуть что-то типа getSiteManager(), у которого есть специальный аргумент context.

Тем не менее, по неясным для меня причинам, такой способ не используется. getSiteManager() (см. zope.component._api) сделан hookable (это такой способ "законно" делать то, что когда-то в Zope2 называлось "Monkey Patch", подробности см. в zope.hookable), и фактически не используется. Так как в zope.app.component.hooks перекрывается забавным getSiteManager, который обрабатывает свой единственный аргумент несколько иначе.

Итак, если аргумент равняется None (т.е. фактически не указан), то вместо того, что бы вернуть глобальный SiteManager, возвращается содержимое siteinfo.sm, которая определена, как понимаете, там же, в zope.app.component.hooks.

Переменная siteinfo это экземпляр класса SiteInfo, который является подклассом zope.thread.local. А вот zope.thread.local это такая забавная штука, которая позволяет иметь в треде локальные (в рамках треда) переменные: вы просто порождаете класс от zope.thread.local и можете пользоваться его атрибутами как локальными переменными треда. Соответственно, атрибут sm содержит SiteManager и инициализируется глобальным SiteManager'ом. Вроде бы пока ничего не изменилось - вызов getSiteManager() по-прежнему возвращает глобальный SiteManager.

А теперь заглянем в zope.app.component.site :), в котором определена замечательная функция threadSiteSubscriber, которая в zope.app.component.configure прописана как обработчик события zope.app.publication.interfaces.IBeforeTraverseEvent при траверсе SiteManager (точнее, объекта с интерфейсом ISite). Назначение этого хендлера - прописать в siteinfo.sm пройденный SiteManager. Именно поэтому siteinfo.sm всегда содержит последний пройденный SiteManager, и именно поэтому вызов getSiteManager() (без аргументов) возвращает __последний_пройденный__ SiteManager.

Зачем так сделано - не до конца понимаю. Ну, видимо, так сложилось.

Сухой остаток отсюда, на самом деле не SiteManager:

zope.thread.local
работа с локальными переменными треда, я против таких методов :), но хорошо, что такая возможность есть.
zope.hookable
стандартный способ перегружать ключевые функции Zope.

А SiteManager и связанные с ним реестры находятся сейчас в состоянии интенсивного переписывания, и в конце концов не так уж важно, как там они работают сейчас.


Powered by Plone CMS, the Open Source Content Management System