1.1.6.1 Convenience Declarations in Class, Interface and Module Bodies
Description: Convenience Declarations in Class, Interface and Module Bodies
Keywords: ref

###
1.1.6.1 Convenience Declarations in Class, Interface and Module Bodies

Adapters, interfaces, and protocol implementations are usually defined in Python `class` statements. To make it more convenient to make protocol declarations for these classes, the `protocols` package supplies the `advise()` function. This function can make declarations about a class, simply by being called from the body of that class. It can also be called from the body of a module, to make a declaration about the module.

`advise`( | **kw)

  Declare protocol relationships for the containing class or module. All parameters must be supplied as keyword arguments. This function must be called directly from a class or module body, or a `SyntaxError` results at runtime. Different arguments are accepted, according to whether the function is called within a class or module.

  When invoked in the top-level code of a module, this function only accepts the `moduleProvides` keyword argument. When invoked in the body of a class definition, this function accepts any keyword arguments except `moduleProvides`. The complete list of keyword arguments follows. Unless otherwise specified, protocols must support the `IOpenProtocol` interface.

  Note: When used in a class body, this function works by temporarily replacing the `__metaclass__` of the class. If your class sets an explicit `__metaclass__`, it must do so before `advise()` is called, or the protocol declarations will not occur!

Keyword arguments accepted by `advise()`:

instancesProvide = protocols
  A sequence of protocols that instances of the containing class provide, without needing an adapter. Supplying this argument is equivalent to calling `declareImplementation(containing class,protocols)`.

instancesDoNotProvide = protocols
  A sequence of protocols that instances of the containing class do not provide. This is primarily intended for ``rejecting'' protocols provided or supported by base classes of the containing class. Supplying this argument is equivalent to calling `declareImplementation(containing class,instancesDoNotProvide=protocols)`.

asAdapterForTypes = types
  Declare the containing class as an adapter for types, to the protocols listed by the `instancesProvide` argument (which must also be supplied). Supplying this argument is equivalent to calling `declareAdapter(containing class, instancesProvide, forTypes=types)`. (Note that this means the containing class must be an object that provides `IAdapterFactory`; i.e., its constructor should accept being called with a single argument: the object to be adapted.)

asAdapterForProtocols = protocols
  Declare the containing class as an adapter for protocols, to the protocols listed by the `instancesProvide` argument (which must also be supplied). Supplying this argument is equivalent to calling `declareAdapter(containing class, instancesProvide, forProtocols=types)`. (Note that this means the containing class must be an object that provides `IAdapterFactory`; i.e., its constructor should accept being called with a single argument: the object to be adapted.)

factoryMethod = methodName
  New in version 0.9.1. When using `asAdapterForTypes` or `asAdapterForProtocols`, you can also supply a factory method name, using this keyword. The method named must be a class method, and it will be used in place of the class' normal constructor. (Note that this means the named method must be able to be called with a single argument: the object to be adapted.)

protocolExtends = protocols
  Declare that the containing class is a protocol that extends (i.e., implies) the listed protocols. This keyword argument is intended for use inside class statements that themselves define protocols, such as `Interface` subclasses, and that need to ``inherit'' from incompatible protocols. For example, an `Interface` cannot directly subclass a Zope interface, because their metaclasses are incompatible. But using `protocolExtends` works around this:

      import protocols
      from mypackage import ISomeInterface
      from zope.something.interfaces import ISomeZopeInterface

      class IAnotherInterface(ISomeInterface):
          protocols.advise(
              protocolExtends = [ISomeZopeInterface]
          )
          #... etc.

  In the above example, `IAnotherInterface` wants to extend both `ISomeInterface` and `ISomeZopeInterface`, but cannot do so directly because the interfaces are of incompatible types. `protocolExtends` informs the newly created interface that it implies `ISomeZopeInterface`, even though it isn't derived from it.

  Using this keyword argument is equivalent to calling `declareAdapter(NO_ADAPTER_NEEDED, protocols, forProtocols=[containing class])`. Note that this means that the containing class must be an object that supports `IOpenProtocol`, such as an `Interface` subclass.

protocolIsSubsetOf = protocols
  Declare that the containing class is a protocol that is implied (extended) by the listed protocols. This is just like `protocolExtends`, but in the ``opposite direction''. It allows you to declare (in effect) that some other interface is actually a subclass of (extends, implies) this one. See the examples in section 1.1.4 for illustration.

  Using this keyword argument is equivalent to calling `declareAdapter(NO_ADAPTER_NEEDED, [containing class], forProtocols=protocols)`.

equivalentProtocols = protocols
  New in version 0.9.1. Declare that the containing class is a protocol that is equivalent to the listed protocols. That is, the containing protocol both implies, and is implied by, the listed protocols. This is a convenience feature intended mainly to support the use of generated protocols.

  Using this keyword is equivalent to using both the `protocolExtends` and `protocolIsSubsetOf` keywords, with the supplied protocols.

classProvides = protocols
  Declare that the containing class itself provides the specified protocols. Supplying this argument is equivalent to calling `adviseObject(containing class, protocols)`. Note that this means that the containing class may need to support the `IOpenProvider` interface. The `protocols` package supplies default adapters to support `IOpenProvider` for both classic and new-style classes, as long as they do not have custom `__conform__` methods. See section 1.1.6, ``Protocol Declarations for Individual Objects'' for more details.

classDoesNotProvide = protocols
  Declare that the containing class itself does not provide the specified protocols. This is for classes that need to reject inherited class-level `classProvides` declarations. Supplying this argument is equivalent to calling `adviseObject(containing class, doesNotProvide=protocols)`, and the `IOpenProvider` requirements mentioned above for `classProvides` apply here as well.

moduleProvides = protocols
  (module context only)
  A sequence of protocols that the enclosing module provides. Equivalent to `adviseObject(containing module, protocols)`.