zope.component icon indicating copy to clipboard operation
zope.component copied to clipboard

not easy to get the superAdapter or next most specific adapter when overriding an adapter.

Open djay opened this issue 4 years ago • 2 comments

There are times you want to override an adapter but use the fundtionality of the whatever else was registered that you overrode. This code allows you to do that. It would be very handy if this was added as a feature to zope.component, perhaps in a more efficient way?

def superAdapter(specific_interface, adapter, objects, name=u""):
    """ find the next most specific adapter """

    #  We are adjusting view object class to provide IForm rather than IEasyFormForm or IGroup to make
    #  one of the objects less specific. This allows us to find anotehr adapter other than our one. This allows us to
    #  find any custom adapters for any fields that we have overridden
    new_obj = []
    found = False
    for obj in objects:
        interfaces = list(providedBy(obj).interfaces())
        try:
            index = interfaces.index(specific_interface)
            found = True
        except ValueError:
            pass
        else:
            super_inferface = interfaces[index + 1]

            @implementer(super_inferface)
            class Wrapper(object):
                def __init__(self, view):
                    self.__view__ = view

                def __getattr__(self, item):
                    return getattr(self.__view__, item)

            obj = Wrapper(obj)  # Make one class less specific
        new_obj.append(obj)
    if not found:
        return None

    provides = providedBy(adapter).declared[0]

    return queryMultiAdapter(new_obj, provides, name=name)

djay avatar May 21 '20 09:05 djay