Skip to content

Instantly share code, notes, and snippets.

@gicmo
Created December 8, 2017 10:32
Show Gist options
  • Save gicmo/4a54e97d63794ae87a3442ad83104d4f to your computer and use it in GitHub Desktop.
Save gicmo/4a54e97d63794ae87a3442ad83104d4f to your computer and use it in GitHub Desktop.
Simple signal class for python
#!/usr/bin/env python3
class Signal(object):
def __init__(self, name):
self.name = name
self.callbacks = set()
def connect(self, callback):
self.callbacks.add(callback)
def disconnect(self, callback):
self.callbacks.remove(callback)
def disconnect_all(self):
self.callbacks = set()
def emit(self, *args, **kwargs):
for cb in self.callbacks:
cb(*args, **kwargs)
def __call__(self, *args, **kwargs):
self.emit(*args, **kwargs)
def __iadd__(self, callback):
self.connect(callback)
def __idel__(self, callback):
self.disconnect(callback)
@staticmethod
def enable(klass):
lst = getattr(klass, 'signals', [])
methods = [m for m in dir(klass) if not m.startswith('__')]
def install(l):
if l is None:
return
if l in methods:
print('WARNING: signal "%s" will overwrite method' % l)
def getter(self):
return self.signals[l]
def setter(self, value):
return self.signals[l]
p = property(getter, setter)
setattr(klass, l, p)
return Signal(l)
klass.signals = {l: install(l) for l in lst}
for m in methods:
method = getattr(klass, m)
name = getattr(method, 'signal', None)
method.signal = install(name)
klass.signals[name] = method.signal
return klass
@staticmethod
def autoemit(name, order='post'):
if order not in ['pre', 'post']:
raise ValueError('invalid order: ' + str(order))
def decorator(f):
def wrapper(self, *args, **kwargs):
signal = f.signal
if not isinstance(signal, Signal):
return f(self, *args, **kwargs)
if order == 'pre':
signal.emit(self)
res = f(self, *args, **kwargs)
if order == 'post':
signal.emit(self)
return res
# will be replaced by the Signal object
# via Signal.enable
wrapper.signal = name
return wrapper
return decorator
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment