Package Pyblio :: Module Callback
[hide private]
[frames] | no frames]

Source Code for Module Pyblio.Callback

  1  """ 
  2  A generic callback mechanism. 
  3   
  4  Classes that wish to emit events inherit from L{Publisher}. Interested 
  5  clients call the L{Publisher.register} method on the object. The 
  6  publisher then calls L{Publisher.emit} to emit the event.""" 
  7   
  8  import weakref 
  9   
 10   
11 -class WeakError (Exception):
12 """ Invoked when a function call is performed on a destroyed method """ 13 pass
14 15
16 -class WeakMethodBound :
17 18 """ A weak reference on a bound method """ 19
20 - def __init__ (self, f):
21 # Keep a hard reference on the function itself 22 self.f = f.im_func 23 self.c = weakref.ref(f.im_self) 24 return
25 26
27 - def __call__ (self , *arg):
28 o = self.c() 29 30 if o is None: 31 raise WeakError, 'Method called on dead object' 32 33 return apply (self.f, (o,) + arg)
34
35 - def same(self, fn):
36 try: 37 rf = fn.im_func 38 except AttributeError: 39 return False 40 41 return self.f is rf and self.c() is fn.im_self
42 43
44 -class WeakMethodFree:
45 """ A weak reference on an unbound method """
46 - def __init__ (self, f):
47 self.f = weakref.ref(f) 48 return
49
50 - def __call__ (self, *arg):
51 o = self.f() 52 if o is None : 53 raise WeakError , 'Function no longer exist' 54 return apply(o, arg)
55
56 - def same(self, fn):
57 return self.f() is fn
58 59
60 -def weakmethod (f):
61 62 try: f.im_func 63 64 except AttributeError: 65 return WeakMethodFree(f) 66 67 return WeakMethodBound(f)
68 69
70 -class Publisher(object):
71 72 """ Base class for objects that wish to emit signals to registered 73 clients.""" 74 75
76 - def __init__ (self):
77 """ Intialize the publisher """ 78 79 self.__observers = {} 80 return
81 82
83 - def emit(self, signal, *args):
84 """ Call this method to emit a signal. Registered client will 85 have their callbacks automatically invoked, with the specified 86 arguments """ 87 88 try: 89 queue = self.__observers[signal] 90 except KeyError: 91 return 92 93 for data in queue[:]: 94 cb, bound = data 95 try: 96 apply(cb, args + bound) 97 except WeakError: 98 queue.remove(data) 99 continue 100 return
101 102
103 - def register(self, signal, callback, *args):
104 105 """ Clients interested in a given signal must register with 106 this method. The optional args are passed as the last 107 arguments (after the emit arguments) to the callback. """ 108 109 queue = self.__observers.setdefault(signal, []) 110 queue.append((weakmethod(callback), args)) 111 return
112
113 - def unregister(self, signal, callback):
114 """ Stop notifying events for the specified signal/callback 115 pair.""" 116 117 queue = self.__observers.get(signal,[]) 118 119 for data in queue[:]: 120 cb, bound = data 121 122 if cb.same(callback): 123 queue.remove(data) 124 125 return
126