Imported Upstream version 3.2.2
[debian/gnuradio] / gr-wxgui / src / python / pubsub.py
1 #!/usr/bin/env python
2 #
3 # Copyright 2008 Free Software Foundation, Inc.
4 #
5 # This file is part of GNU Radio
6 #
7 # GNU Radio is free software; you can redistribute it and/or modify
8 # it under the terms of the GNU General Public License as published by
9 # the Free Software Foundation; either version 3, or (at your option)
10 # any later version.
11 #
12 # GNU Radio is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 # GNU General Public License for more details.
16 #
17 # You should have received a copy of the GNU General Public License
18 # along with GNU Radio; see the file COPYING.  If not, write to
19 # the Free Software Foundation, Inc., 51 Franklin Street,
20 # Boston, MA 02110-1301, USA.
21 #
22
23 """
24 Abstract GNU Radio publisher/subscriber interface
25
26 This is a proof of concept implementation, will likely change significantly.
27 """
28
29 class pubsub(dict):
30     def __init__(self):
31         self._publishers = { }
32         self._subscribers = { }
33         self._proxies = { }
34
35     def __missing__(self, key, value=None):
36         dict.__setitem__(self, key, value)
37         self._publishers[key] = None
38         self._subscribers[key] = []
39         self._proxies[key] = None
40
41     def __setitem__(self, key, val):
42         if not self.has_key(key):
43             self.__missing__(key, val)
44         elif self._proxies[key] is not None:
45             (p, pkey) = self._proxies[key]
46             p[pkey] = val
47         else:
48             dict.__setitem__(self, key, val)
49         for sub in self._subscribers[key]:
50             # Note this means subscribers will get called in the thread
51             # context of the 'set' caller.
52             sub(val)
53
54     def __getitem__(self, key):
55         if not self.has_key(key): self.__missing__(key)
56         if self._proxies[key] is not None:
57             (p, pkey) = self._proxies[key]
58             return p[pkey]
59         elif self._publishers[key] is not None:
60             return self._publishers[key]()
61         else:
62             return dict.__getitem__(self, key)
63
64     def publish(self, key, publisher):
65         if not self.has_key(key): self.__missing__(key)
66         if self._proxies[key] is not None:
67             (p, pkey) = self._proxies[key]
68             p.publish(pkey, publisher)
69         else:
70             self._publishers[key] = publisher
71
72     def subscribe(self, key, subscriber):
73         if not self.has_key(key): self.__missing__(key)
74         if self._proxies[key] is not None:
75             (p, pkey) = self._proxies[key]
76             p.subscribe(pkey, subscriber)
77         else:
78             self._subscribers[key].append(subscriber)
79
80     def unpublish(self, key):
81         if self._proxies[key] is not None:
82             (p, pkey) = self._proxies[key]
83             p.unpublish(pkey)
84         else:
85             self._publishers[key] = None
86
87     def unsubscribe(self, key, subscriber):
88         if self._proxies[key] is not None:
89             (p, pkey) = self._proxies[key]
90             p.unsubscribe(pkey, subscriber)
91         else:
92             self._subscribers[key].remove(subscriber)
93
94     def proxy(self, key, p, pkey=None):
95         if not self.has_key(key): self.__missing__(key)
96         if pkey is None: pkey = key
97         self._proxies[key] = (p, pkey)
98
99     def unproxy(self, key):
100         self._proxies[key] = None
101
102 # Test code
103 if __name__ == "__main__":
104     import sys
105     o = pubsub()
106
107     # Non-existent key gets auto-created with None value
108     print "Auto-created key 'foo' value:", o['foo']
109
110     # Add some subscribers
111     # First is a bare function
112     def print_len(x):
113         print "len=%i" % (len(x), )
114     o.subscribe('foo', print_len)
115
116     # The second is a class member function
117     class subber(object):
118         def __init__(self, param):
119             self._param = param
120         def printer(self, x):
121             print self._param, `x`
122     s = subber('param')
123     o.subscribe('foo', s.printer)
124
125     # The third is a lambda function
126     o.subscribe('foo', lambda x: sys.stdout.write('val='+`x`+'\n'))
127
128     # Update key 'foo', will notify subscribers
129     print "Updating 'foo' with three subscribers:"
130     o['foo'] = 'bar';
131
132     # Remove first subscriber
133     o.unsubscribe('foo', print_len)
134
135     # Update now will only trigger second and third subscriber
136     print "Updating 'foo' after removing a subscriber:"
137     o['foo'] = 'bar2';
138
139     # Publish a key as a function, in this case, a lambda function
140     o.publish('baz', lambda : 42)
141     print "Published value of 'baz':", o['baz']
142
143     # Unpublish the key
144     o.unpublish('baz')
145
146     # This will return None, as there is no publisher
147     print "Value of 'baz' with no publisher:", o['baz']
148
149     # Set 'baz' key, it gets cached
150     o['baz'] = 'bazzz'
151
152     # Now will return cached value, since no provider
153     print "Cached value of 'baz' after being set:", o['baz']