pythonic способ обернуть вызовы xmlrpclib в подобные мультикалы - PullRequest
0 голосов
/ 22 сентября 2010

Я пишу класс, который взаимодействует с вики MoinMoin через xmlrpc (упрощенный код приведен ниже):

class MoinMoin(object):
    token = None

    def __init__(self, url, username=None, password=None):
        self.wiki  = xmlrpclib.ServerProxy(url + '/?action=xmlrpc2')
        if username and password:
            self.token = self.wiki.getAuthToken(username, password)
    # some sample methods:
    def searchPages(self, regexp):
    def getPage(self, page):
    def putPage(self, page):

теперь каждый из моих методов должен вызывать только соответствующий метод xmlrpc, если не задействована аутентификация, или обернуть его в мультикаль, если есть аутентификация. Пример:

def getPage(self, page):
    if not self.token:
        result = self.wiki.getPage(page)
    else:
        mc = xmlrpclib.MultiCall(self.wiki) # build an XML-RPC multicall
        mc.applyAuthToken(self.token)       # call 1
        mc.getPage(page)                    # call 2
        result = mc()[-1]                  # run both, keep result of the latter
    return result

Есть ли более приятный способ сделать это, кроме как повторять эти вещи для каждого метода?

Поскольку мне приходится вызывать произвольные методы, оборачивать их материалом, затем вызывать метод с таким же именем в другом классе, выбирать релевантные результаты и возвращать их, я подозреваю, что решение будет включать мета-классы или подобные эзотерические (для меня) вещи. Мне, вероятно, следует взглянуть на исходники xmlrpclib и посмотреть, как это делается, а затем, возможно, создать подкласс их MultiCall, чтобы добавить мои вещи ...

Но, может быть, я упускаю что-то проще. Лучшее, что я получил, это что-то вроде:

def _getMultiCall(self):
    mc = xmlrpclib.MultiCall(self.wiki)
    if self.token:
        mc.applyAuthToken(self.token)
    return mc
def fooMethod(self, x):
    mc = self._getMultiCall()
    mc.fooMethod(x)
    return mc()[-1]

но он все еще повторяет те же три строки кода для каждого метода, который мне нужно реализовать, просто меняя имя вызываемого метода. Лучше?

1 Ответ

1 голос
/ 22 сентября 2010

Python-функции являются объектами, поэтому их довольно легко можно передать другой функции.

def HandleAuthAndReturnResult(self, method, arg):
    mc = xmlrpclib.MultiCall(self.wiki)
    if self.token:
        mc.applyAuthToken(self.token)
    method(mc, arg)
    return mc()[-1]
def fooMethod(self, x):
    HandleAuthAndReturnResult(xmlrpclib.MultiCall.fooMethod, x)

Может быть и другой способ, но я думаю, что он должен работать.Конечно, часть arg должна быть выровнена с тем, что необходимо для метода, но все ваши методы принимают один аргумент.

Редактировать: я не понял, что MultiCall был прокси-объектом.Даже если реальный вызов метода в конечном итоге и есть в вашем ServerProxy, вы не должны передавать этот объект метода в случае, если MultiCall когда-либо переопределит (определит) его.В этом случае вы можете использовать метод getattribute с именем метода, который вы хотите вызвать, а затем вызвать возвращенный объект функции.Позаботьтесь, чтобы обработать исключение AttributeError.

Методы теперь будут выглядеть так:

def HandleAuthAndReturnResult(self, methodName, arg):
    mc = xmlrpclib.MultiCall(self.wiki)
    if self.token:
        mc.applyAuthToken(self.token)

    try:
        methodToCall = getattr(mc, methodName)
    except AttributeError:
        return None

    methodToCall(arg)
    return mc()[-1]

def fooMethod(self, x):
    HandleAuthAndReturnResult('fooMethod', x)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...