Events ====== The Component Architecture provides a way to dispatch events to event handlers. Event handlers are registered as *subscribers* a.k.a. *handlers*. Before we can start we need to import ``zope.component.event`` to make the dispatching effective: .. doctest:: >>> import zope.component.event Consider two event classes: .. doctest:: >>> class Event1(object): ... pass >>> class Event2(Event1): ... pass Now consider two handlers for these event classes: .. doctest:: >>> called = [] >>> import zope.component >>> @zope.component.adapter(Event1) ... def handler1(event): ... called.append(1) >>> @zope.component.adapter(Event2) ... def handler2(event): ... called.append(2) We can register them with the Component Architecture: .. doctest:: >>> zope.component.provideHandler(handler1) >>> zope.component.provideHandler(handler2) Now let's go through the events. We'll see that the handlers have been called accordingly: .. doctest:: >>> from zope.event import notify >>> notify(Event1()) >>> called [1] >>> del called[:] >>> notify(Event2()) >>> called.sort() >>> called [1, 2] Object events ------------- The ``objectEventNotify`` function is a subscriber to dispatch ObjectEvents to interested adapters. First create an object class: .. doctest:: >>> class IUseless(zope.interface.Interface): ... """Useless object""" >>> class UselessObject(object): ... """Useless object""" ... zope.interface.implements(IUseless) Then create an event class: .. doctest:: >>> class IObjectThrownEvent(zope.component.interfaces.IObjectEvent): ... """An object has been thrown away""" >>> class ObjectThrownEvent(zope.component.interfaces.ObjectEvent): ... """An object has been thrown away""" ... zope.interface.implements(IObjectThrownEvent) Create an object and an event: .. doctest:: >>> hammer = UselessObject() >>> event = ObjectThrownEvent(hammer) Then notify the event to the subscribers. Since the subscribers list is empty, nothing happens. .. doctest:: >>> zope.component.event.objectEventNotify(event) Now create an handler for the event: .. doctest:: >>> events = [] >>> def record(*args): #* ... events.append(args) >>> zope.component.provideHandler(record, [IUseless, IObjectThrownEvent]) The event is notified to the subscriber: .. doctest:: >>> zope.component.event.objectEventNotify(event) >>> events == [(hammer, event)] True Following test demonstrates how a subscriber can raise an exception to prevent an action. .. doctest:: >>> zope.component.provideHandler(zope.component.event.objectEventNotify) Let's create a container: .. doctest:: >>> class ToolBox(dict): ... def __delitem__(self, key): ... notify(ObjectThrownEvent(self[key])) ... return super(ToolBox,self).__delitem__(key) >>> container = ToolBox() And put the object into the container: .. doctest:: >>> container['Red Hammer'] = hammer Create an handler function that will raise an error when called: .. doctest:: >>> class Veto(Exception): ... pass >>> def callback(item, event): ... assert(item == event.object) ... raise Veto Register the handler: .. doctest:: >>> zope.component.provideHandler(callback, [IUseless, IObjectThrownEvent]) Then if we try to remove the object, an ObjectThrownEvent is fired: .. doctest:: >>> del container['Red Hammer'] ... # doctest: +NORMALIZE_WHITESPACE Traceback (most recent call last): ... raise Veto Veto