Package emma :: Module events
[hide private]
[frames] | no frames]

Source Code for Module emma.events

  1  """ 
  2  Event support for emma 
  3   
  4  The events are addressed by L{Event} class, with the event name, interface and 
  5  identifier of the L{interface} related to it. Any complement can be scubcribed 
  6  and trigger any event. 
  7   
  8  @copyright: (c) 2011 hackmeeting U{http://sindominio.net/hackmeeting} 
  9  @author: Ruben Pollan 
 10  @organization: hackmeeting U{http://sindominio.net/hackmeeting} 
 11  @contact: meskio@sindominio.net 
 12  @license: 
 13    This program is free software; you can redistribute it and/or 
 14    modify it under the terms of the Do What The Fuck You Want To 
 15    Public License, Version 2, as published by Sam Hocevar. See 
 16    U{http://sam.zoy.org/projects/COPYING.WTFPL} for more details. 
 17  """ 
 18   
 19  import thread 
 20  import itertools 
 21  import logging 
 22   
 23   
24 -class Event:
25 """ 26 Event addressing class 27 28 It holds the event name, interface and identifier of the event. You can 29 access to each of them from the object once instanciated: 30 31 >>> myEvent = Event(event="foo", identifier="bar") 32 >>> myEvent.event 33 'foo' 34 >>> myEvent.interface 35 >>> myEvent.identifier 36 'bar' 37 """
38 - def __init__(self, event=None, interface=None, identifier=None):
39 """ 40 Define the event 41 42 Set the event name, interface and identifier, none of them is required. 43 Any of the three elements empty will mean that the event subscription 44 will get all the events with the element or elements defined. 45 46 @type event: string 47 @param event: name of the event 48 @type interface: string 49 @param interface: interface producer or receiver of the event 50 @type identifier: string 51 @param identifier: the identifier string of the interface 52 """ 53 self.event = event 54 self.interface = interface 55 self.identifier = identifier
56
57 - def __cmp__(self, event):
58 return cmp(self.elements(), event.elements())
59
60 - def __hash__(self):
61 return self.elements().__hash__()
62
63 - def elements(self):
64 """ 65 Get the elements of the event 66 67 @returns: (event, interface, identifier) 68 """ 69 return (self.event, self.interface, self.identifier)
70
71 - def all_events(self):
72 """ 73 Get all the events that will be trigger with it 74 75 @returns: [all the combinations of None and elements of the event] 76 @attention: this method is meant to be use only inside L{emma.events} 77 """ 78 event_tuples = itertools.product((self.event, None), \ 79 (self.interface, None), \ 80 (self.identifier, None)) 81 events = set([Event(x, y, z) for x, y, z in event_tuples]) 82 return events
83 84 85 _events = {} 86 _events_lock = thread.allocate_lock() 87 88
89 -def _get_handlers(event):
90 handlers = [] 91 for e in event.all_events(): 92 if e in _events: 93 handlers += _events[e] 94 return handlers
95 96
97 -def trigger(event, data):
98 """ 99 Trigger an event on background 100 101 Execute in a new thread each handler L{subscribe}d to the event. 102 103 @type event: L{Event} 104 @param event: event to be triggered, it must have all the elements 105 @type data: undefined 106 @param data: the information passed by the event, each event will define 107 it's data structure 108 @warning: event can not have any None value 109 """ 110 handlers = _get_handlers(event) 111 112 for handler in handlers: 113 thread.start_new_thread(handler, (event, data))
114 115
116 -def run_event(event, data):
117 """ 118 Run an event waiting for it's result 119 120 Execute each handler L{subscribe}d to the event secuentially getting back 121 the return value of each handler. 122 123 @type event: L{Event} 124 @param event: event to be triggered, it must have all the elements 125 @type data: undefined 126 @param data: the information passed by the event, each event will define 127 it's data structure 128 @returns: [return value of each event handler] 129 @warning: event can not have any None value 130 """ 131 handlers = _get_handlers(event) 132 133 res = [] 134 for handler in handlers: 135 res.append(handler(event, data)) 136 return res
137 138
139 -def subscribe(event, handler):
140 """ 141 Subscribe to an event 142 143 Set a function to be call if an event is produced. The event can have some 144 (or all) elements undefined, so it was call by any event with the defined 145 elements equals to the subscribed event. 146 147 @type event: L{Event} 148 @param event: event to be triggered 149 @type handler: fun(event, data) 150 @param handler: function to call if the event is trigger 151 """ 152 with _events_lock: 153 if event not in _events: 154 _events[event] = [handler] 155 else: 156 _events[event].append(handler)
157 158
159 -def unsubscribe(event, handler):
160 """ 161 Unsubscribe from an event 162 163 @type event: L{Event} 164 @param event: event used for subscription 165 @type handler: fun(event, data) 166 @param handler: the function used for subscription 167 @warning: it is not properly tested might have bugs 168 """ 169 with _events_lock: 170 if event in _events: 171 _events[event].remove(handler) 172 else: 173 log_str = _("[core] can't unsubscribe identifier," \ 174 " it was not subscribed") 175 logging.warning(log_str)
176