Event

This module provides an event framework that is composed of the following classes:

                                            |
Generator1 <----+                           |
                 \ gets             puts    |    gets
Generator2 <----+------- Dispatcher ----> Queue <---- Processor
                 /                          |
Generator3 <----+                           |
                                  Thread 1  |  Thread 2

The EventDispatcher is at the center of the framework. When the EventDispatcher is created, it starts another thread to handle the processing of Events. These Events are passed between the two threads via an event queue. Events are generated by EventGenerators which are polled on a periodic basis by the EventDispatcher.

When an EventGenerator is polled, all accumulated Events are returned to the EventDispatcher, which then places the Events on the event queue so that the EventProcessor may eventually process the Event using the EventHandler that wass specified as part of the Event. This package includes two simple EventHandlers (print and exec) as well as a handler that is capable of chaining other handlers together. It is called a ChainEventHandler.

It should be noted that the EventDispatcher sleeps for a small configurable interval (1s be default) before polling for new Events. This avoids excessive CPU utilization.

Sample use of this API is as follows:

dispatcher = EventDispatcher()
try:
   dispatcher.error_handler(PrintEventHandler())
   dispatcher.add_event_generator(EventGenerator())
   dispatcher.add_event_generator(EventGenerator())
   dispatcher.start()
   while 1:
       sleep(1)
except:
   dispatcher.stop()

The loop in the above code is not related to the previous mention of a configurable time. Instead, this loop is used to enable a user to cleanly hit Ctrl-C to stop the application via a KeyboardInterrupt.

class EventDispatcher(Thread):

The EventDispatcher is the controlling entity of this event framework. EventGenerators register themselves with an EventDispatcher, which then repeatedly polls all registered generators for new Events. Events are placed on the event queue for the EventProcessor to consume and process. The dispatcher manages the injection of events into the queue.

The polling of the EventGenerators is done via a simple busy loop that has a small sleep interval to avoid excessive CPU consumption (it should be noted that event processing is not affected as it runs in its own thread).

__init__(poll_interval=1):
Constructor that creates the queue and starts up an EventProcessor to handle Events.
stop():
Stops the event dispatcher after all pending Events have been processed.
run():
The main busy loop that continually polls EventGenerators for new events and dispatching those events onto the event queue for consumption by the EventProcessor which runs in a different thread. This method should not be called directly as it is invoked when the EventDispatcher is started.
error_handler(error_handler):
Specifies a handler to be used when the processing of an event fails. By default, errors are ignored unless a handler is provided. Errors generated by this handler are silently ignored.
add_event_generator(event_generator):
Adds an EventGenerator from which events are generated.
class EventGenerator(object):

The EventGenerator is a source of Events in this event framework. Each generator is registered with an EventDispatcher which repeatedly queries all registered generators for new events. All events are placed on the event queue which the EventProcessor consumes and processes (via the Event's EventHandler).

get_events():
Gets all pending events that have occurred since the last time this method was invoked. If no events have occurred, an empty list must be returned.
stop():
Stop the event generation and cleanly shutdown all resources currently in use by the EventGenerator (open files, sockets, etc).
class EventProcessor(Thread):

Consumes events placed on the event queue and invokes an Event's handler to process the event.

__init__(event_queue):
Constructor that specifies the event queue from which events will arrive.
run():
The run loop for the processor. It runs in its own thread. This method should not be called directly as it is started automatically when the EventProcessor is started.
stop():
Stop event processing immediately and terminate thread.
dispatch_event():

Dispatches an event off of the queue and invokes the handler to process the event. This method blocks until the handler has completed processing. If an error occurs while processing the event, the configured error handler is dispatched, otherwise, errors are silently discarded. Furthermore, if an error occurs while processing the error handler, it is also ignored.

When an error does occur, a new event is generated. This new event sends a tuple for the data field of the Event object. The first item in the tuple is the exception that was thrown, and the second item is the original event that caused the exception to be thrown. This data may be used to troubleshoot the error.

class Event(object):

Event represents an event that has occurred. An event contains a reference to the object that generated the event, a handler, and arbitrary data to be used by the handler when processing the event. Each event is also tagged with a timestamp. The EventProcessor will consume Events.

__init__(originator, handler, data):
Constructor that specifies the originator of the event, the event handler that should be used to process this event, and arbitrary data that can be used by the event handler when processing.
__str__():
Generate a string representation of this event.
class EventHandler(object):

EventHandlers process Events upon consumption from the EventProcessor. The handler is expected to adhere to this interface. Either subclass EventHandler and provide your own implementation of 'process_event', or create a class that implements the method.

It is strongly recommended that a handler can accept strings as arguments to methods that set properties in addition to the native type of the property. This will enable a handler to be created by various rule builder systems (guis, config files, etc).

process_event(event):
Processes the specified event. This method must be overridden or you must define an object that implementst this method. Furthermore, a non-false value should be returned to indicate success.
__str__():
Return a string representation of the EventHandler and possibly any of its properties.
class ChainEventHandler(EventHandler):

ChainEventHandler is used to chain multiple EventHandlers. This enables a single event to be processed by more than one EventHandler. The chain is executed until an EventHandler returns false at which point the chain execution is stopped.

__init__(*handlers):
Contructor that specifies a number of EventHandlers that should be chained together and executed when the chain is processed.
process_event(event):
Processes the event using the chain of handlers that were specified in the constructor. Each handler is expected to return a non-false value; otherwise, the processing of the chain terminates. This can be used for short-circuit the event processing.
__str__():
Returns a string representation of the events that participate in this chain.
class ExecEventHandler(EventHandler):

ExecEventHandler is used internally to pass commands between the LogEncapsulator and the EventProcessor. The event object that is passed is not processed. Instead, the soure specified in the constructor is exec()'d. Currently, this is used to shutdown the EventProcessor gracefully when the LogEncapsulator is shutdown.

__init__(command):
Constructor that specifies the command to execute.
process_event(event):
Processes the event by executing the python source.
class PrintEventHandler(EventHandler):

PrintEventHandler prints Events to a file object (stdout by default). Is is the default EventHandler for the LogEncapsulator.

__init__(file=stdout):
Constructor that specifies the file events should be printed.
process_event(event):
Prints the event to the file object specified in the cstror.