Customizing For

Sometimes the output of zope.interface.providedBy() is not what you want the high-level dynamic subscription APIs to use. This can be customized by providing an adapter for the object to nti.webhooks.interfaces.IWebhookResourceDiscriminator.

Example

Previously in Dynamic Webhook Subscriptions, we saw how employees.Employee got a very specific registration. Let’s add an adapter and see it get a different registration.

First, we create the normal configuration.

>>> from zope.configuration import xmlconfig
>>> conf_context = xmlconfig.string("""
... <configure
...     xmlns="http://namespaces.zope.org/zope"
...     xmlns:webhooks="http://nextthought.com/ntp/webhooks"
...     >
...   <include package="nti.webhooks" />
...   <include package="nti.webhooks" file="subscribers_promiscuous.zcml" />
...   <include package="nti.site" />
...   <include package="zope.traversing" />
... </configure>
... """)

Next, we create and provide an adapter. When called, it returns the specific class instead of its set of provided interfaces. Typically, an adapter will return one specific interface, but it can return anything that can be passed to zope.interface.interfaces.IComponentRegistry.registerAdapter() as part of the required parameter.

>>> from zope.interface import implementer
>>> from zope.component import adapter
>>> from zope.component import provideAdapter
>>> from employees import Employee
>>> from nti.webhooks.interfaces import IWebhookResourceDiscriminator
>>> @implementer(IWebhookResourceDiscriminator)
... @adapter(Employee)
... class EmployeeDiscriminator(object):
...     def __init__(self, context):
...         self.context = context
...     def __call__(self):
...         return type(self.context)
>>> provideAdapter(EmployeeDiscriminator)

Now, when we use the high-level API, we find a more specific for value:

>>> from nti.webhooks.api import subscribe_to_resource
>>> bob = Employee()
>>> subscription = subscribe_to_resource(bob, 'https://example.com/some/path')
>>> subscription.for_
<class 'employees.Employee'>