Как использовать xmlrpc c Zope3
В статье на простом примере дан краткий рассказ об использовании xmlrpc в Zope3.
Как использовать xmlrpc c Zope3:
XMLRPC - протокол вызова удаленных процедур, использующий в качестве транспорта HTTP, а в качестве метода кодирования - вызовы XML. XML-RPC очень простой протокол, определяющий минимум типов данных и команд: его полное описание может поместится на двух листах бумаги. Основная идея, так же как и у большинства RPC систем - прозрачность удаленного вызова. По хорошо написанному коду трудно понять, какая часть кода выполняется локально, а какая удаленно. В питоне xmlrpc поддерживается библиотекой xmlrpclib, входящей в стандартную поставку.
На самом деле это достаточно просто: как обычно, составляется специальный адаптер, который регистрируется как вид для обращения к xmlrpc, к которому потом при помощи модуля libxmlrpc можно обращатся, чтобы выполнять различные операции.
Постановка задачи :
В качестве простой задачи, напишем утилиту, которая будет подключаться к серверу, просматривать рекурсивно его объекты, отбирать из них заданные атрибуты и передавать некоторой программе, результат обработки которой будет загружается обратно. Такая утилита может пригодится для тестирования или для массового редактирования новостей. Пример в этой статье написан на основе программы pd.subversion.notify, которую можно получить на http://pypi.python.org/pypi
Для начала, программа-клиент (это немного проще):
Текст всей программы-клиента включает в себя много обвязки, поэтому здесь приведен сокращенный вариант - только то, что имеет отношение к делу. Для начала функция просмотра дерева объектов:
from xmlrpclib import ServerProxy, Error from urllib import quote,unquote def walk(rpcserver,attributes,klass,interface='zope.interface.Interface') : server = ServerProxy(rpcserver) if not klass or klass == server.klass() : if server.check(interface) : for attr in attributes : yield (rpcserver,server,attr) for item in server.keys() : for x in walk(rpcserver + "/" + item,attributes,klass,interface) : yield x
Немного поясним. Данная функция работает с гипотетическим "интерфейсом" удаленного объекта (в обобщенном смысле слова), который предоставляет функции просмотра и редактирования атрибутов, а также возможность просмотра контейнера (если он контейнер, не контейнер рассматривается как пустой контейнер).
Чтобы в дальнейшем обрабатывать найденные атрибуты, потребуется такой код:
for (path,server,attr) in walk(rpcserver,attributes,klass,interface) : value = server.getattr(interface,attr) fn=tempfile.mktemp() open(fn,"w").write(value) os.system(execute % {"name":fn }) value = open(fn,"r").read() server.setattr(interface,attr,value)
Этот код делает итерацию по найденным коннекторам к объектам, после чего запускает внешнюю программую для их обработки. Мы используем system, а не popen, потому что такие у нас программы :), ваш выбор может быть другим.
Ключевая фраза во всем параграфе выше - это вызов xmlrpclib.ServerProxy(url). Если требуется пароль для доступа к серверу, указывайте url вот так:
http://<ИМЯ>:<ПАРОЛЬ>@<САЙТ>/<ПУТЬ>, например: http://theuser:[email protected]/about
Серверная часть:
Вообще, в смысле компонентной модели, стоило бы для серверной части, для каждого объекта со своими интерфейсами сделать свой адаптер и таким образом все реализовать. В нашем случае мы пока пошли простым путем: реализовали универсальный xmlrpc-вид, который более-менее разбирается с интерфейсами объекта, который он предоставляет.
С точки зрения архитектуры Zope, xmlrpc-вид - это адаптер от пары:
(for_, IXMLRPCRequest)
где for_ - это интерфейс объекта, который обслуживается этим видом.
Получаемый интерфейс:
Interface
Если при регистрации вида использовался параметр interface, то он будет использован только для настройки методов и выдачи прав, а результатом адаптации все равно останется Interface, что, впрочем, также, как и для других видов.
Использование всего этого можно увидеть в :
- zope/app/publisher/xmlrpc
- регистрация и работа директив;
- zope/publisher/xmlrpc.py
- определение xmlrpc запроса и ответа;
Исходный код xmlrpc-вида приведен ниже:
class XMLRPCEdit(object) : def getattr(self,interface,name) : """ Вернуть значение атрибута после адаптирования к указанному интерфейсу """ return getattr(nameToInterface(self.context,interface)(self.context),name) or "" def setattr(self,interface,name,value) : """ Установить значение атрибута после адаптирования к указанному интерфейсу """ setattr(nameToInterface(self.context,interface)(self.context),name,value) notify(ObjectModifiedEvent(self.context)) def keys(self) : """ Вернуть список вложенных объектов """ if IContainer.providedBy(self.context) : return list(IContainer(self.context).keys()) return [] def klass(self) : """ Вернуть название класса """ ob = removeSecurityProxy(self.context) return ob.__class__.__module__ + "." + ob.__class__.__name__ def check(self,interface) : """ Проверить возможность адаптации к интерфейсу """ try : nameToInterface(self.context,interface)(self.context) except TypeError,msg : return False return True __nonzero__ = True
Регистрируется вид следующим образом:
<xmlrpc:view for="*" permission="zope.ManageContent" class=".xmlrpcedit.XMLRPCEdit" methods="getattr setattr keys klass check" />
В атрибуте methods должны быть зарегистрированы все методы, которые будут использовать xmlrpc-клиенты через этот вид. Если имя вида не указано, то для каждого метода будет создан, грубо говоря, свой собственныей вид, поэтому на самом деле образуется сложная смесь методов. Это не очень хорошо, но легко реализуется. Вместо перечисления методов можно, как вариант, указать интерфейс, в котором эти методы описаны.
Заключение:
Основное назначение xmlrpc написание толстых клиентов, взаимодействующих с сервером, чтобы проверить данные на нем или еще что-то в этом роде. В качестве примера сошлемся на две программы, написанные с использованием xmlrpc:
- ng.xmlrpcscan
- программа, на примере которой написана эта статья, и которая реально используется для проверки орфографии;
- pd.subversion.notify
- программа, пересылающая заметки о изменениях сабвершена "куда надо".
Хотелось бы увидеть "толстый" визуальный редактор, действующий через xmlrpc, но пока такого не видно.