[Zope3-dev] Re: a new zcml directive?

Martijn Faassen faassen at infrae.com
Thu Mar 16 07:07:43 EST 2006


Philipp von Weitershausen wrote:
> Martijn Faassen wrote:
> 
>>I stand by my conclusions on this approach sounding simple in theory,
>>but still being a bit harder than it should be in practice. :)
> 
> I think this is pretty simple:
> 
> def makeAnnotationAdapter(for_, factory, key):
>   @zope.component.adapter(for_)
>   @zope.interface.implementer(IAnnotations)
>   def annotationAdapter(context):
>       annotations = IAnnotations(context)
>       try:
>           return annotations[key]
>       except KeyError:
>           ob = factory()
>           annotations[key] = ob
>           # to please security...
>           zope.app.container.contained.contained(
>               ob, context, 'foobar-whatever')
>           return ob
>   return annotationAdapter
> 
> getFoo = makeAnnotationAdapter(IFoo, Foo, FOO_KEY)
>  
> Perhaps I'm missing something?!?

It's not as simple as your code actually doing to what it needs to do. :)

It doesn't do what it needs to do as we're not aiming to implement 
IAnnotations here, but whatever the factory is implementing. I also 
would like to avoid having to specify for_, as the factory should 
already specify this information.

But it's definitely simpler, if, as you do, know the zope.interface and 
zope.component APIs, and how various things can be used as decorators. I 
hadn't used them yet.

Yesterday I had something that worked if I specified both 'for' and 
'implements' in ZCML; it was pretty close to what you had without the 
decorator bits. I modified it today using your decorator idea and it 
appears to work now:

def factory(factory, name, key):
     @zope.component.adapter(
         list(zope.component.adaptedBy(factory))[0])
     @zope.interface.implementer(
         list(zope.interface.implementedBy(factory))[0])
     def getAnnotation(context):
         annotations = IAnnotations(context)
         try:
             return annotations[key]
         except KeyError:
             result = factory()
             annotations[key] = result
             zope.app.container.contained.contained(
                 result, context, name)
             return result
     # Convention to make adapter introspectable
     # (XXX where is this used? is this necessary at all?)
     getAnnotation.factory = factory
     return getAnnotation

You can use this with the following Python code and ZCML:

class MyAnnotation(Persistent):
     implements(interfaces.IFoo)
     adapts(interfaces.IBaz)

getMyAnnotation = annotation.factory(MyAnnotation, 'my_annotation',
                                     'some_key')

<adapter factory=".module.getMyAnnotation" trusted="yes" />

I hope I can still make the requirement for name and key go away.

In many ways this behaves very similarly to the adapter ZCML directive 
(as I did peek at its implementation :).

I realize I may be in the minority on this particular mailing list, but 
to me the implementation of this code wasn't "pretty simple". If this is 
the way we are going to encourage people to build higher level 
abstractions for definition, we may lose some of them.

Regards,

Martijn


More information about the Zope3-dev mailing list