[Chandler-dev] stamping as annotations?

Alec Flett alecf at osafoundation.org
Tue May 16 13:54:12 PDT 2006


Phillip J. Eby wrote:
> I don't think zope.interface will actually buy us anything for 
> stamping, unless I misunderstand what stamping is used for.  Here's 
> what I suggested to Katie that our stamp implementation might look 
> like...  first, there's an abstract base class for all stamps:
>
Fair enough - mostly I personally wanted to make sure that either 
someone took a hard look at zope.interface or someone who knew enough 
about zope.interface took a hard look at our stamping model.

I think the next two things to worry about w.r.t. stamping are 
n-directional relationships and collection membership.

Our current model of stamping makes it really easy to deal with the the 
combined event-ness, the task-ness and the mail-ness of the same item 
item.. i.e. if I have the event-ness of an item (i.e. I'm using the 
startTime attribute) then it is really easy to get to the mail-ness just 
by accessing the toAddress attribute.

 If we move to an attribute-based relationship, then getting from event 
-> task -> mail, or mail -> event -> task or whatever gets more 
complex.. What you describe in the code you presented has this notion 
that there is one primary object that has a bunch of stamps associated 
with it. But what if you've got one of those stamps (i.e. the sort of 
'sub-object') and you need to get to one of the other stamps?

Further, if I stamp some Event as a mail message, and later REMOVE the 
event-ness of it.. what happens to the stamps and the relationships? How 
does the mail item stick around?

This comes up in thinking about collection membership i.e. if you've 
stamped a mail message as an event and a task, then how does the event 
show up in the calendar? is there a 'primary' object (that might be a 
mail message) that shows up, and the calendar has to look through the 
stamps looking for event stamps? Or can we simulate the idea that the 
'event' stamp is in the current collection.

Say we want to check if an item is in a given collection. When we do a 
kind query for Events, we'll get a stamp, but how to we check if one of 
the associated stamps is in that given collection? Anyway, my point is 
that we should figure out how that is going to look from an API 
perspective, because it seems frustrating that we'll have to think about 
this kind of thing all over the codebase.

 I think this is one of the reasons I was thinking about zope.interface 
and adapters - at least on some level it abstracts away the concept of a 
master event and sub-events - if you can just say to any e-mail message 
"adapt yourself into an event" and it doesn't matter who is a sub-object 
of what, and we can figure it out under the hood, then that seems good. 
(And yes we can certainly just make our own API to abstract that away, 
but at least that part looks an awfully lot like zope.interface!)

On the flip side I don't know enough about zope.interface to know if 
there is some way to deal with multiple stamps of a given kind. i.e. if 
I have a mail message and I want to say "give me all the Events that 
this item is stamped with" (as opposed to just one) or "add a new Event 
stamp" - if we couldn't do that, we'd be missing out on one of the key 
reasons we wanted to move away from identity-based stamping...

Alec


> class Stamp(schema.Annotation):
>     schema.kindInfo(annotates=pim.Item)
>
>     # collection of stamp classes for each instance
>     stamp_types = schema.Many(schema.Class)
>
>     @property
>     def stamps(self):
>         for t in self.stamp_types:
>             yield t(self)
>
>     def add(self):
>         self.stamp_types.add(self.__class__)
>
>     def remove(self):
>         self.stamp_types.remove(self.__class__)
>
>
> Now you can make stamp classes like:
>
>     class EventStamp(Stamp):
>         schema.kindInfo(annotates=pim.Item)
>
>         # event attributes here
>
>         # event methods here
>
>
> And then do things like:
>
>      EventStamp(anItem).add()
>
> or:
>      for stamp in Stamp(anItem).stamps:
>          # inspect and do stuff to the stamp object,
>          # or maybe remove it
>
> This can all be done now, without any interface registration or 
> anything like that.  Annotation classes work similarly to adaptation - 
> if you ask for EventStamp(ob) and ob is already an EventStamp, you get 
> an equivalent object.  If it's an item or any annotation of the item, 
> and it's a compatible type, you get an EventStamp adapter object.  In 
> any case, you then have an object with event attributes and methods 
> (and only those attributes and methods).
>
> To answer Grant's question, this does not actually keep Kind 
> composition "under the covers" - it's based purely on the annotation 
> system.  Annotation attributes are normal attributes, so they should 
> be as indexable as anything else.  However, if performance 
> considerations show that storing stamp types as a set (e.g. as shown 
> above) is detrimental then some other way of tracking active stamps is 
> needed.
>



More information about the chandler-dev mailing list