Create an proxy that forwards methods to a group of observers
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | def ObserverProxy(method_names):
class Proxy:
def __init__(self):
self._observers = []
def add_observer(self, observer):
self._observers.append(observer)
def remove_observer(self, observer):
self._observers.remove(observer)
def create_method_proxy(method_name):
def method_proxy(self, *args, **kwargs):
for observer in self._observers:
getattr(observer, method_name)(*args, **kwargs)
return method_proxy
for method_name in method_names:
setattr(Proxy, method_name, create_method_proxy(method_name))
return Proxy()
if __name__ == "__main__":
# usage example
output_proxy = ObserverProxy(["write", "close"])
import sys
output_proxy.add_observer(sys.stdout)
output_proxy.add_observer(sys.stderr)
output_proxy.add_observer(file("somefile", "w"))
print >>output_proxy, "This goes to all observers"
output_proxy.close()
|
I found myself repeatedly creating proxying observers for different purposes, for example in unittest test suites where I wanted multiple result objects, so I made this recipe.
http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/52289 is a similar recipe with an advantage - it doesn't require defining the interface in advance.
Tags: ui
Nice closure application, but you should also mention similar / related recipes ... ... for ex.:
http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/107027
http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/52289
Thanks, I wasn't aware of them. The second recipe, http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/52289, is really cool - it seems to wrap each method when called, so it's unnecessary to predefine the interface. There are a lot of new instances created, on each call, but hey, no need to optimize prematurely :)
The first recipe is conceptually different in that the proxy doesn't provide the same interface, so it can't be plugged in.
Another complement. I didn't think of it the first time, but there are also parallels with my events recipe at http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/410686
It fasciliates mapping compatible protocols (methods of same signature) onto each other, independent of their name, for ex.: