Where events provide a way to extend functionality of existing components, annotations provide a seamless way to extend the data stored (in ZoDB) with instances of components.

For example, a zope.security.interfaces.IPrincipal interface provides an id, a title and a description.  It may be that you would like to add some additional account based information such as firstname, surname and email address:

from zope.security.interfaces import IPrincipal
from zope.interface import Interface, Attribute

class IAccount(Interface):
    firstname = Attribute("First Name")
    surname = Attribute("Surname")
    email  = Attribute("Enail")

class Principal(grok.Model)
    grok.implements(IPrincipal)
    ...

class Account(grok.Annotation):
    grok.implements(IAccount)
    firstname = ''
    surname = ''
    email = ''


joe = Principal()
account = Account(joe)
account.firstname = "Joseph"
...

In the above example, joe is an instance of a Principal, and so has an id, title and description.  We create an instance of an Account, passing joejoe is adapted and extended with the attributes from IAccount, namely a firstname, surname and email.

This way the original IPrincipal interface does not have to be altered every time an particular application has some specific data it needs to add for a user.  A generic and pluggable authentication library can now be built to provide an IPrincipal, and used by various applications, each with their own differing requirements for user data storage.  

If the ZoDB is used for storage, annotations are automatically stored with objects in the object database.

Grok 4 Noobs

Extending existing objects with Annotations