Adapters and the order of calling

for example, in plone.outputfilters are filters defined as adapters with an order attribute. Can someone tell me the place where the order is observed. To me it sounds like a method ‘getAdpaterByOrder’ in the Zope universe. Does something like this exist?

That’s an interesting question! In Plone (and Zope), adapters are typically invoked based on the order attribute, which determines the sequence in which they are applied. While there isn’t a specific method called getAdapterByOrder that I’m aware of, the order in which adapters are executed is often handled implicitly by the framework. Specifically, in Plone, the order attribute is used in places like plone.outputfilters, which controls the sequence in which filters or adapters are applied.

If you want to inspect or modify the order, you may need to check the specific context where the adapters are registered, as the framework will typically use the order to determine their application sequence.

Does this mean that my adapter only needs an ‘order’ attribute, regardless of the characteristics of the rest of the adapter, to control the execution order (apart from the context)?

Yes, exactly, The order attribute is what controls the execution sequence of the adapter. As long as the adapter is registered in the correct context, the order will dictate when it gets executed compared to others. You don’t need to worry too much about the other details of the adapter unless they affect how it works in that context.

So, the order should be enough to control the flow, and the context will determine where it applies.

Sorry, I may be wrong, but, do you use AI tools to generate answers, @alikhere? If, no, I am really sorry for asking. If yes, please be so kind and mention the use of AI tools.

3 Likes

No need to apologize, and I don’t use AI tools to generate my answers. I base my responses on my own understanding and experience with the topic.
it’s possible that my understanding of topic may be incorrect, so please feel free to correct me if needed. I’m always open to learning and improving.

I do not know the answer but I would begin my search using the following search terms:

"zope adapters interface resolution order"

Report back what you find.

The order-Attribute is just a handy way to circumvent the idea of how Zope decides, which adapters comes first when calling methods like getAdapter(s).

For your concrete case, let's look into the code:

In plone.outputfilters.transform.html_to_plone_outputfilters_html.py you have snippet like this:

@implementer(ITransform)
class html_to_plone_outputfilters_html:
    def convert(self, orig, data, **kwargs):
        context = kwargs.get("context")
        request = getattr(getSite(), "REQUEST", None)
        filters = [f for _, f in getAdapters((context, request), IFilter)]

        res = apply_filters(filters, orig)
        data.setData(res)
        return data

and apply_filters is defined as this:

def apply_filters(filters, data):
    filters = sorted(filters, key=lambda x: x.order)
    for filter in filters:
        if filter.is_enabled():
            res = filter(data)
            if res is not None:
                data = res
    return data

As you can see, we retrieve just all the adapters and manually sort them by their order-attribute. That's it. If you wish to have precedence, define another one that comes with a higher order.

BTW: This method is also used in all the ITransform adapters like Diazo (plone.app.theming.transform) as super early transform with order 8850 and Caching (plone.caching.mutator) with order 12000.

If you wish to know more about how Zope's adapter lookup works, you can probably look into Zope's documentation. As a rule over the thumb, the "more specific" adapter aka the adapter registered for the more specific interface/class is the one that usually wins.

That's why adapters registered for a marker interface usually wins, against adapters for the generic zope.Interface.

5 Likes

That was the point, that i searched. Thanks for hint.

Thanks for the clarification , It’s cool how the order attribute handles the adapter sequence. Have you ever run into a situation where the order wasn’t enough, and you had to get more specific with the adapters? Just curious to hear your take on it!

In extensions to @pgg answer, here are some specific code pieces on how the adapter registry works

the adapter storage is a list (https://github.com/zopefoundation/zope.interface/blob/90a4801441a9dc3e29a160918d3f70c68a8574c5/src/zope/interface/adapter.py#L150)

Which means that the order is given by the order adapters are registered. In Plone mostly via ZCML into a global registry (You can have local adapter registries as well). So the order ZCML files are getting loaded defines the order of the adapters.

As mentioned by @pgg as well, the only "order" that is implemented into the registry is that, more specific adapters (via inheritance) are usually returned instead of more generic adapters. See: https://github.com/zopefoundation/zope.interface/blob/90a4801441a9dc3e29a160918d3f70c68a8574c5/src/zope/interface/adapter.py#L993-L1014

2 Likes

Yes i know the normal adapter registration process in zope, thanks. for me only the ordering via "order attribute" like in plone.outputfilters was interesting. @pgg give me the very helpful hint.

1 Like