##// END OF EJS Templates
fixed None for type/sender
Barry Wark -
Show More
@@ -20,6 +20,12 b' class NotificationCenter(object):'
20 20 """Synchronous notification center"""
21 21 def __init__(self):
22 22 super(NotificationCenter, self).__init__()
23 self._init_observers()
24
25
26 def _init_observers(self):
27 """Initialize observer storage"""
28
23 29 self.registeredTypes = set() #set of types that are observed
24 30 self.registeredSenders = set() #set of senders that are observed
25 31 self.observers = {} #map (type,sender) => callback (callable)
@@ -41,20 +47,34 b' class NotificationCenter(object):'
41 47 type and sender.")
42 48
43 49 # If there are no registered observers for the type/sender pair
44 if((theType not in self.registeredTypes) or
45 (sender not in self.registeredSenders)):
50 if((theType not in self.registeredTypes and None not in self.registeredTypes) or
51 (sender not in self.registeredSenders and None not in self.registeredSenders)):
52 print theType,sender,self.registeredTypes,self.registeredSenders
46 53 return
47 54
48 keys = ((theType,sender), (None, sender), (theType, None), (None,None))
49 observers = set()
55 for o in self._observers_for_notification(theType, sender):
56 o(theType, sender, args=kwargs)
57
58
59 def _observers_for_notification(self, theType, sender):
60 """Find all registered observers that should recieve notification"""
61
62 keys = (
63 (theType,sender),
64 (theType, None),
65 (None, sender),
66 (None,None)
67 )
68
69
70 obs = set()
50 71 for k in keys:
51 observers.update(self.observers.get(k, set()))
72 obs.update(self.observers.get(k, set()))
52 73
53 for o in observers:
54 o(theType, sender, args=kwargs)
74 return obs
55 75
56 76
57 def add_observer(self, observerCallback, theType, sender):
77 def add_observer(self, callback, theType, sender):
58 78 """Add an observer callback to this notification center.
59 79
60 80 The given callback will be called upon posting of notifications of
@@ -75,10 +95,15 b' class NotificationCenter(object):'
75 95 The notification sender. If None, all notifications of theType
76 96 will be posted.
77 97 """
78 assert(observerCallback != None)
98 assert(callback != None)
79 99 self.registeredTypes.add(theType)
80 100 self.registeredSenders.add(sender)
81 self.observers.setdefault((theType,sender), set()).add(observerCallback)
101 self.observers.setdefault((theType,sender), set()).add(callback)
102
103 def remove_all_observers(self):
104 """Removes all observers from this notification center"""
105
106 self._init_observers()
82 107
83 108
84 109
@@ -15,8 +15,9 b' __docformat__ = "restructuredtext en"'
15 15 # Imports
16 16 #-----------------------------------------------------------------------------
17 17
18 from IPython.kernel.core.notification import NotificationCenter,\
19 sharedCenter
18 import unittest
19 import IPython.kernel.core.notification as notification
20 from nose.tools import timed
20 21
21 22 #
22 23 # Supporting test classes
@@ -24,13 +25,14 b' from IPython.kernel.core.notification import NotificationCenter,\\'
24 25
25 26 class Observer(object):
26 27 """docstring for Observer"""
27 def __init__(self, expectedType, expectedSender, **kwargs):
28 def __init__(self, expectedType, expectedSender,
29 center=notification.sharedCenter, **kwargs):
28 30 super(Observer, self).__init__()
29 31 self.expectedType = expectedType
30 32 self.expectedSender = expectedSender
31 33 self.expectedKwArgs = kwargs
32 34 self.recieved = False
33 sharedCenter.add_observer(self.callback,
35 center.add_observer(self.callback,
34 36 self.expectedType,
35 37 self.expectedSender)
36 38
@@ -38,8 +40,10 b' class Observer(object):'
38 40 def callback(self, theType, sender, args={}):
39 41 """callback"""
40 42
41 assert(theType == self.expectedType)
42 assert(sender == self.expectedSender)
43 assert(theType == self.expectedType or
44 self.expectedType == None)
45 assert(sender == self.expectedSender or
46 self.expectedSender == None)
43 47 assert(args == self.expectedKwArgs)
44 48 self.recieved = True
45 49
@@ -49,6 +53,11 b' class Observer(object):'
49 53
50 54 assert(self.recieved)
51 55
56 def reset(self):
57 """reset"""
58
59 self.recieved = False
60
52 61
53 62
54 63 class Notifier(object):
@@ -58,7 +67,7 b' class Notifier(object):'
58 67 self.theType = theType
59 68 self.kwargs = kwargs
60 69
61 def post(self, center=sharedCenter):
70 def post(self, center=notification.sharedCenter):
62 71 """fire"""
63 72
64 73 center.post_notification(self.theType, self,
@@ -69,8 +78,13 b' class Notifier(object):'
69 78 # Test Cases
70 79 #
71 80
81 class NotificationTests(unittest.TestCase):
82 """docstring for NotificationTests"""
83
84 def tearDown(self):
85 notification.sharedCenter.remove_all_observers()
72 86
73 def test_notification_delivered():
87 def test_notification_delivered(self):
74 88 """Test that notifications are delivered"""
75 89 expectedType = 'EXPECTED_TYPE'
76 90 sender = Notifier(expectedType)
@@ -81,7 +95,7 b' def test_notification_delivered():'
81 95 observer.verify()
82 96
83 97
84 def test_type_specificity():
98 def test_type_specificity(self):
85 99 """Test that observers are registered by type"""
86 100
87 101 expectedType = 1
@@ -96,7 +110,7 b' def test_type_specificity():'
96 110 observer.verify()
97 111
98 112
99 def test_sender_specificity():
113 def test_sender_specificity(self):
100 114 """Test that observers are registered by sender"""
101 115
102 116 expectedType = "EXPECTED_TYPE"
@@ -110,9 +124,56 b' def test_sender_specificity():'
110 124 observer.verify()
111 125
112 126
113 def test_complexity_with_no_observers():
127 def test_remove_all_observers(self):
128 """White-box test for remove_all_observers"""
129
130 for i in xrange(10):
131 Observer('TYPE', None, center=notification.sharedCenter)
132
133 self.assert_(len(notification.sharedCenter.observers[('TYPE',None)]) >= 10,
134 "observers registered")
135
136 notification.sharedCenter.remove_all_observers()
137
138 self.assert_(len(notification.sharedCenter.observers) == 0, "observers removed")
139
140
141 def test_any_sender(self):
142 """test_any_sender"""
143
144 expectedType = "EXPECTED_TYPE"
145 sender1 = Notifier(expectedType)
146 sender2 = Notifier(expectedType)
147 observer = Observer(expectedType, None)
148
149
150 sender1.post()
151 observer.verify()
152
153 observer.reset()
154 sender2.post()
155 observer.verify()
156
157
158 @timed(.01)
159 def test_post_performance(self):
160 """Test that post_notification, even with many registered irrelevant
161 observers is fast"""
162
163 for i in xrange(10):
164 Observer("UNRELATED_TYPE", None)
165
166 o = Observer('EXPECTED_TYPE', None)
167
168 notification.sharedCenter.post_notification('EXPECTED_TYPE', self)
169
170 o.verify()
171
172
173 def test_complexity_with_no_observers(self):
114 174 """Test that the notification center's algorithmic complexity is O(1)
115 175 with no registered observers (for the given notification type)
116 176 """
117 177
118 assert(False) #I'm not sure how to test this yet
178 self.fail("I'm not sure how to test this.")
179
General Comments 0
You need to be logged in to leave comments. Login now