Question

Consider a class like the following:

from zope.interface import implementer

@implementer(IMessage)
class Foo:

  @classmethod
  def parse(Klass, msg):
  """
  Parses `msg` into an instance of :class:`Foo`.

  :returns obj -- An instance of :class:`Foo`.
  """

How would I specify the class method in the Zope interface IMessage?

Using the @classmethod decorator in Zope interfaces results in

zope.interface.exceptions.InvalidInterface: Concrete attribute, parse
Was it helpful?

Solution

Zope interfaces don't care about class methods; they only specify what API a specific interface must implement. Note that you specify methods without the self parameter, for example. This way, you can implement an interface any way you like, including using regular functions in a module!

If the implementation chooses to make that callable a classmethod is entirely outside of the scope of interfaces. Interfaces only care about what API you'd use when you access interface providers; if an instance has a callable then the end-user shouldn't need to care if that is a class method.

If the class method should be available on the class directly, then that's the interface the class must provide; lets call it the factory interface here:

class IMessageFactory(Interface):
     def __call__():
         """Produce an IMessage provider"""

     def parse(msg):
         """Parses `msg` into a IMessage provider"""


class IMessage(Interface):
     """A message interface"""

     # Optional, show the class method here too
     def parse(msg):
         """Parses `msg` into a IFoo provider"""

Your Foo class directly provides IMessageFactory, and implements the IMessage interface (so that it's instances provide it).

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top