Delegate methods in Python
One thing that's quite useful when you're programming is knowing when a method was called. A naive approach for this would be to add glue code into the method, and have some mechanism to know who wanted to know when the method was called etc.
However a lot of the time the requirements for someone interested in a particular method fall into a few categories, they are:
Before it runs what arguments was it called with.
After it ran what was the return value.
Was there an un-handled exception in the method.
The delegate pattern is a neat approach that can provide a neat answer to these sort of questions. It is heavily used in objective-c, and now in python using mixins and decorators we've got much the same (if not better)!
My solution has two parts:
The DelegateProviderMixin class, that provides methods for adding/removing delegates for all delegatable (is that a word!?) methods, or for specific methods on an instance.
For any method you want to enable delegates on, simply add the @notify_delegates annotation to allow the delegates system to notify delegates before and after any calls to that particular method.
The source is available at https://gist.github.com/tomhennigan/5245713, and here's an example to help get you started using it:
from delegates import DelegateProviderMixin, notify_delegates class Something(DelegateProviderMixin): @notify_delegates def do_something(self): print 'do_something' def do_something_else(self): print 'do_something_else' @notify_delegates def throw_an_exception(self): raise Exception('oh hai') class SomethingDelegate: def on_before_do_something(self, *args, **kwargs): print '- on_before_do_something' def on_after_do_something(self, ret_value, *args, **kwargs): print '- on_after_do_something -args=%r -kwargs=%r -ret_value=%r' % (args, kwargs, ret_value) def on_exception_in_throw_an_exception(self, exception, *args, **kwargs): print ' - on_exception_in_throw_an_exception -args=%r -kwargs=%r -exception=%r' % (args, kwargs, exception) if __name__ == '__main__': thing = Something() delegate = SomethingDelegate() thing.add_delegate(delegate) thing.do_something() thing.do_something_else() thing.throw_an_exception()