I have been using a GUI library that allows you to connect signals to signal handlers using a connect function, for example:
widget.connect(signal, callback)
Means that the function callback will be run whenever the signal is fired from the widget. In an attempt to make my code nicer, and remove a series of connect calls from my constructor, I decided to use a decorator, which works well:
def callback(widget, signal)
def decorate(f):
widget.connect(signal, f)
return f
return decorate
...
@callback(widget, signal)
def do_something():
...
This works excellently until I needed to do this in a class – the function is decorated before it is bound to the class, meaning the callback function given doesn’t get the instance of the class that owns it, making it useless. Is there a way to get this to work?
A relatively simple solution to this is possible. We begin by using the decorator to mark the function. When instances are constructed, we search for these marks and register the callbacks.
More specifically, the mark and recapture pattern works by using the decorator to mark the function before it is bound, and then find it amongst the bound methods of the instance in the constructor.
First we use a decorator to do the marking (we use a set to allow for multiple marks on one method):
Then we use the inspect module to find the bound versions of the marked functions, and connect them:
__func__is the name of the original, unbound function. This allows us to access the marks that we applied earlier, facilitating our recapture.We can then simply create our class and decorate our functions, remembering to connect our callbacks in the constructor:
This allows us to connect the bound methods with a decorator.
Edit: I have published a tiny library on github that does this for you – it’s called recap.