pythonpython-3.xzopezope.interfacezope3

Error when try to register implementer of zope.interface


I have next class:

@implementer(ISocial)
class SocialVKSelenium:
    pass

And when I add it to zope registry:

gsm = getGlobalSiteManager()
gsm.registerAdapter(SocialVKSelenium)

I got: TypeError: The adapter factory doesn't have a __component_adapts__ attribute and no required specifications were specified

When I add there adapter(IOther), the registration works as expected, but without is not. Why does it happens?


Solution

  • You need to provide a context, either on the class, or to the registry.

    I suspect that you are not communicating the entirety of your problem set -- an adapter is a component that adapts an object of a specified interface, and provides another. Your example fails to specify what the context being adapted is, that is, what kind of object is adapted on construction of your adapter object by its class?

    For example, this works fine:

    from zope.interface import Interface, implements
    from zope.component import getGlobalSiteManager, adapts
    
    
    class IWeight(Interface):
        pass
    
    
    class IVolume(Interface):
        pass
    
    class WeightToVolume(object):
        implements(IVolume)
        adapts(IWeight)
        #...
    
    
    gsm = getGlobalSiteManager()
    gsm.registerAdapter(WeightToVolume)
    

    While you can use the decorator (implementer/adapter) syntax for this, by convention, use of implements/adapts are preferred for adapter factories that are classes, not functions.

    At the very minimum if your adapter does not declare what it adapts on the class or factory function itself, you will need to tell the registry. In the broadest case, this might look like:

    gsm.registerAdapter(MyAdapterClassHere, required=(Interface,))
    

    Of course, this example above is an adapter that claims to adapt any context, which is not recommended unless you know why you need that.