#idle_queue.py
import Queue
#Global queue, import it from anywhere, you get the same object instance.
idle_loop = Queue.Queue()
def idle_add(func, *args, **kwargs):
def idle():
func(*args, **kwargs)
return False
idle_loop.put(idle)
#weak_ref.py
import weakref
class _BoundMethodWeakref:
def __init__(self, func):
self.func_name = func.__name__
self.wref = weakref.ref(func.__self__) #__self__ returns the class
def __call__(self):
func_cls = self.wref()
if func_cls is None: #lost reference
return None
else:
func = getattr(func_cls, self.func_name)
return func
def weak_ref(callback):
if hasattr(callback, '__self__') and callback.__self__ is not None: #is a bound method?
return _BoundMethodWeakref(callback)
else:
return weakref.ref(callback)
#event.py
import threading
#import logging
#logger = logging.getLogger(__name__)
import idle_queue
from weak_ref import weak_ref
class Event:
def __init__(self, name):
self.name = name
self.callbacks = []
self.lock = threading.Lock()
def connect(self, callback):
with self.lock:
callback = weak_ref(callback)
self.callbacks.append(callback)
def disconnect(self, callback):
with self.lock:
for index, weakref_callback in enumerate(self.callbacks):
if callback == weakref_callback():
del self.callbacks[index]
break
def emit(self, *args, **kwargs):
with self.lock:
#logger.debug("Event emitted: {}".format(self.name))
for weakref_callback in self.callbacks[:]:
callback = weakref_callback()
if callback is not None:
idle_queue.idle_add(callback, *args, **kwargs)
else: #lost reference
self.callbacks.remove(weakref_callback)
#if not self.callbacks:
#logger.debug("No signals assosiated to: {}".format(self.name))
#events.py
import Event
class _Events:
#add some signals, example:
#do_something = Event('do something') #args: my_arg1, my_arg_list2, my_arg_str3
quit_app = Event('quit app') #args: some_arg
events = _Events()
if __name__ == "__main__":
def quit(some_arg):
print some_arg
sys.exit(0)
events.quit_app.connect(quit) #connect the callback/slot
#events.quit_app.disconnect(quit) #disconnect
something = "goodbye"
events.quit_app.emit(something) #emit the signal
#this should go in your main thread loop if your are using a gui.
#example: http://code.activestate.com/recipes/578299-pyqt-pyside-thread-safe-global-queue-main-loop-int/
callback = idle_loop.get()
callback() #dispatch the event