Почему мой MultiAdapter не может зарегистрироваться?

В настоящее время я экспериментирую с ZCA, и я столкнулся с небольшой заминкой. Сценарий ниже определяет IFuncttion интерфейс, который используется для создания функциональных объектов, которые могут быть связаны (например, монады).

В этом примере я пытаюсь создать простую монаду писателя в качестве адаптера, но getMultiAdapter поднимает ComponentLookupError, Почему это?

from zope import component, interface


class IFunction(interface.Interface):
    name = interface.Attribute('Name of the function object')

    def __call__(*args, **kw):
        """Call the function"""


class Function(object):
    name = ''
    interface.implements(IFunction)

    def __call__(self, *args, **kw):
        return self.run(*args, **kw)

    def run(self, *args, **kw):
        raise NotImplementedError


class MWriter(object):
    component.adapts(IFunction, IFunction)
    interface.implements(IFunction)

    def __init__(self, prv, nxt):
        self.prev, self.next = prv, nxt

    def bind(self, x, log=None):
        log = log or []
        result, line = self.prev(x)
        log.append(line)
        return self.next(result, log)

    def __call__(self, *args, **kw):
        return self.bind(*args, **kw)


class AddOne(Function):
    name = 'addone'

    def run(self, x):
        return x + 1


class MulTwo(Function):
    name = 'multwo'

    def run(self, x):
        return x * 2

component.provideAdapter(MWriter)
print component.getMultiAdapter((AddOne(), MulTwo()), MWriter)(11, [])

1 ответ

Решение

Вы не должны передавать адаптер, на который хотите посмотреть component.getMultiAdapter(), Второй аргумент этой функции - это имя, используемое для именованных адаптеров, но ваша регистрация не использовала имя.

Просто удалите этот второй аргумент:

>>> component.getMultiAdapter((AddOne(), MulTwo()))
<__main__.MWriter object at 0x1072516d0>

К сожалению звоню MWriter() по-прежнему не удается, потому что вы ожидаете self.prev() вернуть кортеж:

result, line = self.prev(x)

но AddOne() возвращает только одно целое число:

class AddOne(Function):
    name = 'addone'

    def run(self, x):
        return x + 1

так что вы получите исключение:

>>> component.getMultiAdapter((AddOne(), MulTwo()))(11)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<string>", line 37, in __call__
  File "<string>", line 32, in bind
TypeError: 'int' object is not iterable

Возможно, вы хотели друг Function() вернуть имя и результат:

class Function(object):
    name = ''
    interface.implements(IFunction)

    def __call__(self, *args, **kw):
        return self.run(*args, **kw), self.name

    def run(self, *args, **kw):
        raise NotImplementedError

но потом звоню self.next() не удается, потому что он не принимает дополнительные log аргумент передан.

Другие вопросы по тегам