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

2006-03-17 Thread Martijn Faassen

Martijn Faassen wrote:
[snip Jim helping me]
Okay, that's one step closer to support for this in the annotation 
package, thanks!


I've checked this in last night. There's a README.txt in 
zope.app.annotation now too that explains its usage.


Regards,

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



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

2006-03-16 Thread Martijn Faassen

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
___
Zope3-dev mailing list
Zope3-dev@zope.org
Unsub: http://mail.zope.org/mailman/options/zope3-dev/archive%40mail-archive.com



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

2006-03-16 Thread Jean-Marc Orliaguet

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



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

2006-03-16 Thread Martijn Faassen

Jean-Marc Orliaguet wrote:
[snip]


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=...) ?


I thought I described it in my initial post.

I was looking for a way to register annotations for objects (and create 
them if they aren't there yet) without having to write fairly long bits 
of code for each annotation factory.


I just want to be able to say:

myannotation = IFoo(obj)

where IFoo is the interface of an annotation of the obj. The only place 
I worry about it being an annotation is in the registration code. No 
need to import anything else from that package. Whether it needs to 
create a new annotation or get an existing one is an implementation detail.


Regards,

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



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

2006-03-16 Thread Jean-Marc Orliaguet

Martijn Faassen wrote:


Jean-Marc Orliaguet wrote:
[snip]



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=...) ?



I thought I described it in my initial post.

I was looking for a way to register annotations for objects (and 
create them if they aren't there yet) without having to write fairly 
long bits of code for each annotation factory.


I just want to be able to say:

myannotation = IFoo(obj)

where IFoo is the interface of an annotation of the obj. The only 
place I worry about it being an annotation is in the registration 
code. No need to import anything else from that package. Whether it 
needs to create a new annotation or get an existing one is an 
implementation detail.


Regards,

Martijn



OK, basically you mean that the 'annotations' given in your original 
post should implement a 'setdefault' method?


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



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

2006-03-16 Thread Martijn Faassen

Jean-Marc Orliaguet wrote:
[snip]
OK, basically you mean that the 'annotations' given in your original 
post should implement a 'setdefault' method?


I don't see how that would help - you'd still end up writing a factory 
that uses the setdefault, right?


I don't want to keep repeating factory code each time I want to do this, 
including factory code that calls IAnnotations(), uses setdefault() or 
anything else. I just want to say, I want to make an adapter that uses 
this standardized factory code. How the factory code does this is not 
very interesting, it's just that I don't want to keep writing it over 
and over.


Regards,

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



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

2006-03-16 Thread Jean-Marc Orliaguet

Martijn Faassen wrote:


Jean-Marc Orliaguet wrote:
[snip]

OK, basically you mean that the 'annotations' given in your original 
post should implement a 'setdefault' method?



I don't see how that would help - you'd still end up writing a factory 
that uses the setdefault, right?


I don't want to keep repeating factory code each time I want to do 
this, including factory code that calls IAnnotations(), uses 
setdefault() or anything else. I just want to say, I want to make an 
adapter that uses this standardized factory code. How the factory code 
does this is not very interesting, it's just that I don't want to keep 
writing it over and over.


Regards,

Martijn



OK, you could pass the interface of the factory to the getter method and 
let it create the object based on this information. That wouldn't be 
exactly like setdefault(), but at least the factory code would be in the 
called method, not in the caller.


If I remember correctly the pattern I'm using (which I still think is 
OK) is to register a factory as a global utility and look up the factory 
by its interface.


so for instance to create a style or type IStyle, I register:

 cpsskins:setting
 name=style
 schema=.style.IStyle
 factory=.style.StyleFactory
 /

with:

def setting(_context, name=u'', schema=None, factory=None):
...
   provideUtility(factory, IFactory, name)

then the annotation getter can contain a 'factory = getUtility(IFactory, 
name)'


regards
/JM

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



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

2006-03-15 Thread Martijn Faassen

Jim Fulton wrote:

Philipp von Weitershausen wrote:


Marius Gedminas wrote:


I'd prefer

   from zope.annotation.adapter import AnnotationAdapter

   getFoo = AnnotationAdapter(for_=IBar,
  interface=IFoo,
  factory=Foo,
  key=FOO_KEY)
   # I suppose the key could be optional; you could use a dotted
   # interface name by default

and then the ordinary

   zope:adapter factory=.foo.getFoo /




+10
 
Likewise.


I just tried to write AnnotationAdapter. Unfortunately, I haven't gotten 
very far yet, as it turns out I need to understand the internals of the 
implementation of the zope:adapter ZCML statement.


zope:adapter has a bunch of automation to look for the interface of 
something and what it adapts on the factory. This works if the factory 
is the class itself, but in this case, the factory is a class which has 
instances which can provide an instance of the annotation class when called.


So, I need to come up with trickery so that instances of 
AnnotationAdapter return the 'for_' argument when asked for by 
zope.interface.implementedBy() and the 'factory' argument when called 
with component.adaptedBy(). Since the instances of AnnotationAdapter are 
actually not doing any adaptation or implementing any of the interface, 
but are actually just providing a factory, it seems like this trickery 
would amount to actually lying.


This is hairy enough for me to give up for now.

Unless I'm missing something, I conclude that implementing 
AnnotationAdapter is currently at least as difficult as just 
implementing a new directive. The other conclusion is that figuring out 
what is happening in case something goes wrong is also at least as hard 
to understand as the innards of a directive, due to the trickery 
necessary to make it work.


Using zope:adapter.. with an explicit 'for' and 'provides' would avoid 
the problem, but this seems to be going against the suggestions given in 
this thread.


Regards,

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



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

2006-03-15 Thread Jim Fulton

Martijn Faassen wrote:
...
I just tried to write AnnotationAdapter. Unfortunately, I haven't gotten 
very far yet, as it turns out I need to understand the internals of the 
implementation of the zope:adapter ZCML statement.


No, you don't.

zope:adapter has a bunch of automation to look for the interface of 
something and what it adapts on the factory. This works if the factory 
is the class itself, but in this case, the factory is a class which has 
instances which can provide an instance of the annotation class when 
called.


This may not be documented as well as it should be, but not for lack of
trying.

1. You can always provide the interface provided by an adapter
   when you register it.

2. If a factory declares that it implements a single interface,
   then you can omit the interface when registering the adapter.

   If a factory is a class, it typically declares that it implements
   an interface via the implements call in the class statement.

   If a factory is not a class, and if it allows attributes to be
   set on it, then the interface.implementor function can be used to make
   declarations for it.  This is documeted in zope/interfaces/README.txt
   and zope/component/README.txt.

Jim



--
Jim Fulton   mailto:[EMAIL PROTECTED]   Python Powered!
CTO  (540) 361-1714http://www.python.org
Zope Corporation http://www.zope.com   http://www.zope.org
___
Zope3-dev mailing list
Zope3-dev@zope.org
Unsub: http://mail.zope.org/mailman/options/zope3-dev/archive%40mail-archive.com



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

2006-03-15 Thread Martijn Faassen

Jim Fulton wrote:

Martijn Faassen wrote:
...

I just tried to write AnnotationAdapter. Unfortunately, I haven't 
gotten very far yet, as it turns out I need to understand the 
internals of the implementation of the zope:adapter ZCML statement.


No, you don't.

zope:adapter has a bunch of automation to look for the interface of 
something and what it adapts on the factory. This works if the factory 
is the class itself, but in this case, the factory is a class which 
has instances which can provide an instance of the annotation class 
when called.


This may not be documented as well as it should be, but not for lack of
trying.

1. You can always provide the interface provided by an adapter
   when you register it.


I realize this, but I was trying to implement the example as suggested, 
also because it's clear that the tendency is away from specifying 'for' 
and 'implements' in ZCML. I know I wouldn't have a problem if I use 
'for' and 'implements' in ZCML.



2. If a factory declares that it implements a single interface,
   then you can omit the interface when registering the adapter.

   If a factory is a class, it typically declares that it implements
   an interface via the implements call in the class statement.


Well, I found this out by reading the code in zope.app.component.


   If a factory is not a class, and if it allows attributes to be
   set on it, then the interface.implementor function can be used to make
   declarations for it.  This is documeted in zope/interfaces/README.txt
   and zope/component/README.txt.


This is one bit I was missing, thanks.

Unfortunately I read in zope/interface/README.txt that the 'implementer' 
function cannot be used for classes yet, so this will change the design 
somewhat (I was using __call__, looks like I'll have to exploit lexical 
scoping and generate a function on the fly).


Using implements() on the class seems like lying, as the class is just 
implementing a factory, not the functionality itself. Besides, I'd have 
to change the class each time it gets called (it's using implementedBy 
to check).


Then that leaves convincing 'adaptedBy()'. One hack is to write the 
'for_' argument that's passed to the AnnotationAdapter() constructor 
directly to an attribute called __component_adapts__. I don't think I 
can use 'adapts()' on a lexically scoped function...


I stand by my conclusions on this approach sounding simple in theory, 
but still being a bit harder than it should be in practice. :)


Regards,

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



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

2006-03-15 Thread Jim Fulton

Martijn Faassen wrote:

Jim Fulton wrote:


...

   If a factory is not a class, and if it allows attributes to be
   set on it, then the interface.implementor function can be used to make
   declarations for it.  This is documeted in zope/interfaces/README.txt
   and zope/component/README.txt.



This is one bit I was missing, thanks.

Unfortunately I read in zope/interface/README.txt that the 'implementer' 
function cannot be used for classes yet, so this will change the design 
somewhat (I was using __call__, looks like I'll have to exploit lexical 
scoping and generate a function on the fly).


No.  You can use it on an instance of the class.  You want something
like:

  class FactoryFactory:

  def __init__(self):
  # initialize a new factory
  ...
  implementer(self, someinterfacethatmyinstancesimplement)

Jim

--
Jim Fulton   mailto:[EMAIL PROTECTED]   Python Powered!
CTO  (540) 361-1714http://www.python.org
Zope Corporation http://www.zope.com   http://www.zope.org
___
Zope3-dev mailing list
Zope3-dev@zope.org
Unsub: http://mail.zope.org/mailman/options/zope3-dev/archive%40mail-archive.com



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

2006-03-15 Thread Martijn Faassen

Jim Fulton wrote:

Martijn Faassen wrote:


Jim Fulton wrote:



This is one bit I was missing, thanks.

Unfortunately I read in zope/interface/README.txt that the 
'implementer' function cannot be used for classes yet, so this will 
change the design somewhat (I was using __call__, looks like I'll have 
to exploit lexical scoping and generate a function on the fly).



No.  You can use it on an instance of the class.  You want something
like:

  class FactoryFactory:

  def __init__(self):
  # initialize a new factory
  ...
  implementer(self, someinterfacethatmyinstancesimplement)


I'm stupid. Right!

Then this and the __component_adapts__ hack should be enough to make it 
work (still an unpleasant hack, that). With that I suspect I should even 
be able to steal the implementedBy and the adaptedBy from the annotation 
itself, which would mean I'd only need to spell it out there.


Thanks again!

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



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

2006-03-15 Thread Jim Fulton

Martijn Faassen wrote:
...

Then this and the __component_adapts__ hack should be enough to make it 
work (still an unpleasant hack, that).


Huh?  Use adapter.

   class FactoryFactory:

   def __init__(self):
   # initialize a new factory
   ...
   implementer(self, someinterfacethatmyinstancesimplement)
   zope.component.adapter(theinterfacemyinstancesadapt)

Jim

--
Jim Fulton   mailto:[EMAIL PROTECTED]   Python Powered!
CTO  (540) 361-1714http://www.python.org
Zope Corporation http://www.zope.com   http://www.zope.org
___
Zope3-dev mailing list
Zope3-dev@zope.org
Unsub: http://mail.zope.org/mailman/options/zope3-dev/archive%40mail-archive.com



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

2006-03-15 Thread Martijn Faassen

Jim Fulton wrote:

Martijn Faassen wrote:
...

Then this and the __component_adapts__ hack should be enough to make 
it work (still an unpleasant hack, that).



Huh?  Use adapter.

   class FactoryFactory:

   def __init__(self):
   # initialize a new factory
   ...
   implementer(self, someinterfacethatmyinstancesimplement)
   zope.component.adapter(theinterfacemyinstancesadapt)


Another one that I couldn't find but is indeed there, sorry. It's right 
there in the zope.component README.txt with an example:


 def personJob(person):
... return getattr(person, 'job', None)
 personJob = interface.implementer(IJob)(personJob)
 personJob = component.adapter(IPerson)(personJob)

Okay, that's one step closer to support for this in the annotation 
package, thanks!


In the new world for ZCML, ZCML as a language falls apart in a 
minimalistic XML language, and some support code (such as 
zope.app.annotation.AnnotationFactory) to help it do more advanced things.


One remaining benefit of higher-level ZCML is that it gets picked up by 
apidoc and thus can be discovered fairly easily by developers as part of 
the configuration story. While AnnotationFactory is doing definition and 
is in Python code in the new world for ZCML, this act of definition is 
closely associated with the act of registering it in ZCML.


It would be nice if we somehow retained discoverability for APIs that 
are meant to work with ZCML - it's obvious from this subthread that it 
takes some idiots^H^H^H^H^H^Hpeople a while to pick up an API... We'd 
like people working with annotations to be able to find out that we have 
this available. Perhaps a README.txt in the annotation package is enough 
for now, though. Perhaps we can think of other ways to help make this 
discoverable...


Regards,

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



Dissecting NamedTemplate (was Re: [Zope3-dev] Re: a new zcml directive?)

2006-03-15 Thread Jeff Shell
Another long post, where below I take apart
zope.formlib.namedtemplate, hoping it can be used as a source of
insight into how to provide flexible extensibility (like in this
example AnnotationsAdapter concept) without needing
yet-another-ZCML-directive.

On 3/15/06, Martijn Faassen [EMAIL PROTECTED] wrote:
 Jim Fulton wrote:
  This may not be documented as well as it should be, but not for lack of
  trying.
 
  1. You can always provide the interface provided by an adapter
 when you register it.

 I realize this, but I was trying to implement the example as suggested,
 also because it's clear that the tendency is away from specifying 'for'
 and 'implements' in ZCML. I know I wouldn't have a problem if I use
 'for' and 'implements' in ZCML.

I don't think there's anything wrong with specifying 'for' and
'implements' in ZCML. It serves a couple of purposes:

1. It is where you can override \ augment an existing configuration.
2. It's where you can specify those arguments for objects and situations
   that aren't easy to specify in Python.

I prefer to see 'implements' and 'adapts' in Python code as much as
possible, but there are certainly situations where specifying it in
ZCML is fine. It's also allowable to provide those arguments in
zope.component.provideAdapter / zapi.provideAdapter.

  2. If a factory declares that it implements a single interface,
 then you can omit the interface when registering the adapter.
 
 If a factory is a class, it typically declares that it implements
 an interface via the implements call in the class statement.

 Well, I found this out by reading the code in zope.app.component.

 If a factory is not a class, and if it allows attributes to be
 set on it, then the interface.implementor function can be used to make
 declarations for it.  This is documeted in zope/interfaces/README.txt
 and zope/component/README.txt.

 This is one bit I was missing, thanks.

 Unfortunately I read in zope/interface/README.txt that the 'implementer'
 function cannot be used for classes yet, so this will change the design
 somewhat (I was using __call__, looks like I'll have to exploit lexical
 scoping and generate a function on the fly).

 Using implements() on the class seems like lying, as the class is just
 implementing a factory, not the functionality itself. Besides, I'd have
 to change the class each time it gets called (it's using implementedBy
 to check).

When you say 'implements() on the class', do you mean::

class FooAdapter(...):
implements(IFoo)

I believe that the interfaces documentation says that this statement
means 'instances of this class provide the IFoo interface'.
zope.interface.classProvides is what you use to make declarations
about the class itself.

class FooAdapter(...):
implements(IFoo)
classProvides(IFooFactory)

 Then that leaves convincing 'adaptedBy()'. One hack is to write the
 'for_' argument that's passed to the AnnotationAdapter() constructor
 directly to an attribute called __component_adapts__. I don't think I
 can use 'adapts()' on a lexically scoped function...

 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 feel the same way. I may have missed some obvious piece of
documentation. Or maybe it's just not an obvious piece of
documentation. But there do seem to be certain rules about what can
register as an adapter. I believe this is why so many of the browser:
directives generate new classes dynamically.

There's a good possibility that you may be over-complicating the
situation. Since I haven't tried implementing my suggestion myself (it
was mostly wishful thinking on what I'd prefer to see), I can't say
for sure. But NamedTemplates in formlib seem to be doing something
similar... I think.

In zope/formlib/form.py::

class Action(...)
implements(interfaces.IAction)
...
render = namedtemplate.NamedTemplate('render')

@namedtemplate.implementation(interfaces.IAction)
def render_submit_button(self):
if not self.available():
return ''
...

In zope/formlib/configure.zcml::

adapter factory=.form.render_submit_button name=render /

The implementation of named templates (zope/formlib/namedtemplate.py)
looks rather small. It uses zope.interface.implementer and
zope.component.adapts. It's probably a good example of  something.
It's taken me a little while to figure it out from staring at it, but
I think I finally get it now. I'll document my interpretation of it.
Anyone's free to correct me if I'm wrong. I think this may help in
providing ways of keeping the number of ZCML directives down.

Looking at ``render = namedtemplate.NamedTemplate('render')``. That
creates an instance of this class::

class NamedTemplate(object):

def __init__(self, name):
self.__name__ = name

def __get__(self, instance, type=None):

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

2006-03-15 Thread Jeff Shell
On 3/15/06, Martijn Faassen [EMAIL PROTECTED] wrote:
 In the new world for ZCML, ZCML as a language falls apart in a
 minimalistic XML language, and some support code (such as
 zope.app.annotation.AnnotationFactory) to help it do more advanced things.

That's what I'd like to see! :)

 One remaining benefit of higher-level ZCML is that it gets picked up by
 apidoc and thus can be discovered fairly easily by developers as part of
 the configuration story. While AnnotationFactory is doing definition and
 is in Python code in the new world for ZCML, this act of definition is
 closely associated with the act of registering it in ZCML.

I agree with that benefit of higher-level ZCML. But I've found in
practice that documentation is still terse and sparse. That alone is
what has had me digging into the code to try to figure out ok, what
does that mean?

name - TextLine (default = None)
Name
Adapters can have names.

This attribute allows you to specify the name for this adapter.

So, yay for documentation. That bit's good. But things like this could
really really benefit from some examples. Especially on core things
like adapter, whose 'locate', 'permission', and 'trusted' properties
and their impact on each other are a bit tricky to figure out.

But Python code and interfaces get picked up by apidoc too. Well, most
of them (schema fields have gone missing in action.. I think a search
will turn them up, but they can't be browsed to directly).

One of the biggest downsides of higher-level ZCML to me is that it
feels totally disconnected from Python. The documentation, as it
stands now, generally documents the fields. But it doesn't go into
what's being done behind the scenes, or why I should be using
directive X, or how to use the results of directive X. The other
downside is that higher level ZCML needs the ZCML 'runtime' in order
to work.

Besides, AnnotationFactory isn't just associated with registering
something in ZCML. It can be associated with registering something
with::

zope.component.provideAdapter(...)

I know that the adapter directive does a bit more than just provide an
adapter. But the point is that it could be used outside of ZCML.

 It would be nice if we somehow retained discoverability for APIs that
 are meant to work with ZCML - it's obvious from this subthread that it
 takes some idiots^H^H^H^H^H^Hpeople a while to pick up an API... We'd
 like people working with annotations to be able to find out that we have
 this available. Perhaps a README.txt in the annotation package is enough
 for now, though. Perhaps we can think of other ways to help make this
 discoverable...

I don't know the status of the static-apidoc tool, but maybe that
could help in some ways...

By having http://api.rubyonrails.com/ , not only is there a great
online API reference, but it's (of course) searchable by the search
engine of choice. Hopefully there will be a day when a search for
'zope annotations' will have the API reference and a couple of darn
good recipes/articles/tips as the first set of results. I know it's
been helpful to see a reference to something in Rails and google
``rails validates_presence_of`` and usually get to the api reference
first. (Not that I'm leaving Zope for Rails, but I have been toying
with it a bit, I admit).

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



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

2006-03-15 Thread Philipp von Weitershausen
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?!?

Philipp



This message was sent using IMP, the Internet Messaging Program.
___
Zope3-dev mailing list
Zope3-dev@zope.org
Unsub: http://mail.zope.org/mailman/options/zope3-dev/archive%40mail-archive.com



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

2006-03-14 Thread Jim Fulton

Philipp von Weitershausen wrote:

Marius Gedminas wrote:


I'd prefer

   from zope.annotation.adapter import AnnotationAdapter

   getFoo = AnnotationAdapter(for_=IBar,
  interface=IFoo,
  factory=Foo,
  key=FOO_KEY)
   # I suppose the key could be optional; you could use a dotted
   # interface name by default

and then the ordinary

   zope:adapter factory=.foo.getFoo /



+10


Likewise.

Jim

--
Jim Fulton   mailto:[EMAIL PROTECTED]   Python Powered!
CTO  (540) 361-1714http://www.python.org
Zope Corporation http://www.zope.com   http://www.zope.org
___
Zope3-dev mailing list
Zope3-dev@zope.org
Unsub: http://mail.zope.org/mailman/options/zope3-dev/archive%40mail-archive.com



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

2006-03-10 Thread Shane Hathaway
Rocky Burt wrote:
 On Fri, 2006-10-03 at 17:17 -0700, Jeff Shell wrote:
 But I beg you not to add to the ZCML pile because you had to copy and
 paste 12 lines of Python code.  snip...
 
 I haven't personally formed an opinion on where this sort of thing
 should go, but copying and pasting 12 lines of python code is totally
 unacceptable for *any* reason.

Oops, there goes another can of worms.  This is a controversial issue
and not specific to Zope or Python, so let us please not discuss it here.

Shane

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