[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.
Regards,
Martijn
More information about the Grok-dev
mailing list