[Zope3-dev] Questions about Interface.Implements

Steve Alexander steve@cat-box.net
Fri, 08 Nov 2002 12:06:50 +0000


Hi Jim,

In the process of writing his tools for documentation, Kapil has found 
some problems with the functions in Interface.Implements.

I'd like to spend a little time fixing these up, and writing some unit 
tests to exercise them some more. I have some questions though:

1: visitImplements has a docstring that says:

"This does not, and should not, visit superinterfaces."

Does this mean that the following is correct?

class I1(Interface): pass
class I2(I1): pass

l = []
visitImplements(I2, None, l.append)

# l == [I2]



2: Does visitImplements accurately describe the valid contents of an 
__implements__ ?

Here's my interpretation:

The implements attribute:

   An implements attribute of an object O is O.__implements__, unless
   isinstance(O, ClassTypes), in which case it is O.__class_implements__.

Value of the implements attribute:

   An implements attribute may be of one of the following types:

   * an Interface (that is, a class derived from Interface.Interface)

   * a string

   * the special value CLASS_INTERFACES

   * a tuple containing any of the things mentioned in these four
     bullet-points


You can find the interfaces given by an implements attribute thus:

   obj = the object that has the implements attribute
   ia = the implements attribute

   def simple_flatten(x):
       if x is an interface:
           return [x]

       if x is a string:
           return simple_flatten(
               someFunctionThatReturnsAnInterfaceForAString(x)
               )

       if x is a tuple:
           l = []
           for i in x:
               l += simple_flatten(x)
           return l

       if x is CLASS_INTERFACES:
           if obj has a __class__ attribute:
               return simple_flatten(
                   getImplementsOfInstances(obj.__class__)
                   )
           else:
               return []

       # if there has been no return statement so far...
       raise BadImplements

   interfaces_given_by_implements_attribute = simple_flatten(ia)

Notes:

   Although a string can act as an interface, a unicode cannot.

   Strings are not considered interfaces in themselves. They are
   keys to allow a real interface to be looked up. This interface
   can be anything you'd put in an implements attribute.


3: flattenInterfaces

   The flattenInterfaces function is supposed to work like the
   simple_flatten pseudocode above, except that we also need to
   consider the bases for each interface we come across.

       if x is an interface:
           return [x] + simple_flatten(x.getBases())

   There is an option to remove duplicates from the results of
   calling simple_flatten before returning this as the
   results of flattenInterfaces.

   This removal of duplicates should work similarly to Python2.2's
   method resolution order for new-style classes.


4: Proposed work

   * Improve the unit tests to thoroughly exercise the different
     possibilities for an implements attribute

   * Improve the unit tests to cover both flattenInterfaces and
     visitImplements

   * Refactor flattenInterfaces and visitImplements to share the
     same code for walking an implements attribute, taking into
     account that only flattenInterfaces uses getBases.


--
Steve Alexander