Martijn Faassen wrote:

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


Hi,
excuse me, but can someone explain what problem the pattern / workaround is supposed to fix, does it create and return a default annotation value in case an annotation key does not exist? shouldn't the annotation machinery be "fixed" instead to provide getAnnotation(..., default=...) ?

/JM
_______________________________________________
Zope3-dev mailing list
Zope3-dev@zope.org
Unsub: http://mail.zope.org/mailman/options/zope3-dev/archive%40mail-archive.com

Reply via email to