[Grok-dev] Re: Annotations adapters and interface inheritance

Martijn Faassen faassen at startifact.com
Wed May 7 18:06:26 EDT 2008

Hi there,

Douglas Cerna wrote:

I spent a few minutes trying to understand what you're asking, but I'm 
not sure I get it yet.

[snip code]

> If I use the form in a IPublicationContainer, everything works as expected. However, if I use it in a IMediaContainer I get this:
> (Pdb) changes
> {<InterfaceClass roco.interfaces.IDateable>: ['date'], <InterfaceClass roco..interfaces.IMedia>: ['duration'], <InterfaceClass roco.interfaces.IResource>: ['data']}

So far this looks reasonable, right? It looks for the most specific 
adapters that these fields exist for. If it did not, you couldn't 
implement an adapter to IDateable directly and expect things to work.

> (Pdb) IMedia(resource)
> <roco.Media object at 0xb5f8e62c>
> (Pdb) IMedia(resource).date
> *** AttributeError: 'Media' object has no attribute 'date'

Right, so you're trying to get the value again from the annotation you 
expect, but you don't see it.

> And when I adapt the object to IDateable I get this:
> (Pdb) IDateable(resource)
> <roco.Publication object at 0xb5f8e66c>

which is then likely the reason, right?

> I know applyData adapts the context to the requested form interfaces. But, why is it 
 > adapting IResource to IDateable using the Publication adapter > 
instead of the Media adapter? It works if I provide a IResource -> 
IDateable adapter, though.

Hm, here we are in obscure rules of the component architecture land, 
something I don't have straight in my head itself. It's clear that the 
most specific adaptation, if you provide it, works.

You are giving the system two choices to get IDateable: either through 
Media or through Publication. The system cannot give a conflict, as you 
want to be able to provide two adapters from the same interface to a 
different interface. But this means that you can do an ambiguous adapter 
lookup you ask for an IDateable (which two adapters provide by 
extension), and given the two equal candidates (your Media and 
Publication annotations) it evidently just picks one.

You could try around with zope.component.getAdapters() to see which 
adapters are listed from IResource to IDateable.

All this inspired me to start reading zope.interface.adapter (both the 
.txt and the .py), but I can't read it well enough yet to know what the 
rule here would be. Perhaps it's simply left undefined which adapter 
you'll get in the end. The system is after all doing what you ask it to. 
  The use of annotations, which involve storage, complicate matters here.

One of the ways I can think of to try to resolve this issue is to try to 
register a local adapter for the media container and the resource 
container, different for each container. Of course Grok doesn't have any 
support for registering local adapters yet...

Instead of going with an annotation model here, I would suggest 
investigating using factories instead. You'd have a factory for a Media 
object and a Publication object, for instance simply by having two such 
classes. The IResourceContainer interface could contain a method to 
actually get the appropriate factory, and implementions of 
IMediaContainer and IPublicationContainer would have to implement this. 
This would take the place of the logic to distinguish between the two 
you've now placed in your form. Since the instances you create will then 
automatically supply the right interfaces for you, applyData should do 
the right thing.



More information about the Grok-dev mailing list