##// 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()
50 for k in keys:
51 observers.update(self.observers.get(k, set()))
52
53 for o in observers:
55 for o in self._observers_for_notification(theType, sender):
54 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"""
55 61
62 keys = (
63 (theType,sender),
64 (theType, None),
65 (None, sender),
66 (None,None)
67 )
68
69
70 obs = set()
71 for k in keys:
72 obs.update(self.observers.get(k, set()))
73
74 return obs
56 75
57 def add_observer(self, observerCallback, theType, sender):
76
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,22 +25,25 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,
34 self.expectedType,
35 self.expectedSender)
35 center.add_observer(self.callback,
36 self.expectedType,
37 self.expectedSender)
36 38
37 39
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,50 +78,102 b' class Notifier(object):'
69 78 # Test Cases
70 79 #
71 80
72
73 def test_notification_delivered():
74 """Test that notifications are delivered"""
75 expectedType = 'EXPECTED_TYPE'
76 sender = Notifier(expectedType)
77 observer = Observer(expectedType, sender)
81 class NotificationTests(unittest.TestCase):
82 """docstring for NotificationTests"""
78 83
79 sender.post()
84 def tearDown(self):
85 notification.sharedCenter.remove_all_observers()
80 86
81 observer.verify()
82
83
84 def test_type_specificity():
85 """Test that observers are registered by type"""
87 def test_notification_delivered(self):
88 """Test that notifications are delivered"""
89 expectedType = 'EXPECTED_TYPE'
90 sender = Notifier(expectedType)
91 observer = Observer(expectedType, sender)
92
93 sender.post()
94
95 observer.verify()
86 96
87 expectedType = 1
88 unexpectedType = "UNEXPECTED_TYPE"
89 sender = Notifier(expectedType)
90 unexpectedSender = Notifier(unexpectedType)
91 observer = Observer(expectedType, sender)
92 97
93 sender.post()
94 unexpectedSender.post()
98 def test_type_specificity(self):
99 """Test that observers are registered by type"""
100
101 expectedType = 1
102 unexpectedType = "UNEXPECTED_TYPE"
103 sender = Notifier(expectedType)
104 unexpectedSender = Notifier(unexpectedType)
105 observer = Observer(expectedType, sender)
95 106
96 observer.verify()
97
98
99 def test_sender_specificity():
100 """Test that observers are registered by sender"""
107 sender.post()
108 unexpectedSender.post()
101 109
102 expectedType = "EXPECTED_TYPE"
103 sender1 = Notifier(expectedType)
104 sender2 = Notifier(expectedType)
105 observer = Observer(expectedType, sender1)
110 observer.verify()
106 111
107 sender1.post()
108 sender2.post()
109 112
110 observer.verify()
111
112
113 def test_complexity_with_no_observers():
114 """Test that the notification center's algorithmic complexity is O(1)
115 with no registered observers (for the given notification type)
116 """
113 def test_sender_specificity(self):
114 """Test that observers are registered by sender"""
115
116 expectedType = "EXPECTED_TYPE"
117 sender1 = Notifier(expectedType)
118 sender2 = Notifier(expectedType)
119 observer = Observer(expectedType, sender1)
120
121 sender1.post()
122 sender2.post()
123
124 observer.verify()
125
126
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):
174 """Test that the notification center's algorithmic complexity is O(1)
175 with no registered observers (for the given notification type)
176 """
177
178 self.fail("I'm not sure how to test this.")
117 179
118 assert(False) #I'm not sure how to test this yet
General Comments 0
You need to be logged in to leave comments. Login now