##// END OF EJS Templates
fixed None for type/sender
Barry Wark -
Show More
@@ -20,6 +20,12 b' class NotificationCenter(object):'
20 """Synchronous notification center"""
20 """Synchronous notification center"""
21 def __init__(self):
21 def __init__(self):
22 super(NotificationCenter, self).__init__()
22 super(NotificationCenter, self).__init__()
23 self._init_observers()
24
25
26 def _init_observers(self):
27 """Initialize observer storage"""
28
23 self.registeredTypes = set() #set of types that are observed
29 self.registeredTypes = set() #set of types that are observed
24 self.registeredSenders = set() #set of senders that are observed
30 self.registeredSenders = set() #set of senders that are observed
25 self.observers = {} #map (type,sender) => callback (callable)
31 self.observers = {} #map (type,sender) => callback (callable)
@@ -41,20 +47,34 b' class NotificationCenter(object):'
41 type and sender.")
47 type and sender.")
42
48
43 # If there are no registered observers for the type/sender pair
49 # If there are no registered observers for the type/sender pair
44 if((theType not in self.registeredTypes) or
50 if((theType not in self.registeredTypes and None not in self.registeredTypes) or
45 (sender not in self.registeredSenders)):
51 (sender not in self.registeredSenders and None not in self.registeredSenders)):
52 print theType,sender,self.registeredTypes,self.registeredSenders
46 return
53 return
47
54
48 keys = ((theType,sender), (None, sender), (theType, None), (None,None))
55 for o in self._observers_for_notification(theType, sender):
49 observers = set()
50 for k in keys:
51 observers.update(self.observers.get(k, set()))
52
53 for o in observers:
54 o(theType, sender, args=kwargs)
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 """Add an observer callback to this notification center.
78 """Add an observer callback to this notification center.
59
79
60 The given callback will be called upon posting of notifications of
80 The given callback will be called upon posting of notifications of
@@ -75,10 +95,15 b' class NotificationCenter(object):'
75 The notification sender. If None, all notifications of theType
95 The notification sender. If None, all notifications of theType
76 will be posted.
96 will be posted.
77 """
97 """
78 assert(observerCallback != None)
98 assert(callback != None)
79 self.registeredTypes.add(theType)
99 self.registeredTypes.add(theType)
80 self.registeredSenders.add(sender)
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 # Imports
15 # Imports
16 #-----------------------------------------------------------------------------
16 #-----------------------------------------------------------------------------
17
17
18 from IPython.kernel.core.notification import NotificationCenter,\
18 import unittest
19 sharedCenter
19 import IPython.kernel.core.notification as notification
20 from nose.tools import timed
20
21
21 #
22 #
22 # Supporting test classes
23 # Supporting test classes
@@ -24,22 +25,25 b' from IPython.kernel.core.notification import NotificationCenter,\\'
24
25
25 class Observer(object):
26 class Observer(object):
26 """docstring for Observer"""
27 """docstring for Observer"""
27 def __init__(self, expectedType, expectedSender, **kwargs):
28 def __init__(self, expectedType, expectedSender,
29 center=notification.sharedCenter, **kwargs):
28 super(Observer, self).__init__()
30 super(Observer, self).__init__()
29 self.expectedType = expectedType
31 self.expectedType = expectedType
30 self.expectedSender = expectedSender
32 self.expectedSender = expectedSender
31 self.expectedKwArgs = kwargs
33 self.expectedKwArgs = kwargs
32 self.recieved = False
34 self.recieved = False
33 sharedCenter.add_observer(self.callback,
35 center.add_observer(self.callback,
34 self.expectedType,
36 self.expectedType,
35 self.expectedSender)
37 self.expectedSender)
36
38
37
39
38 def callback(self, theType, sender, args={}):
40 def callback(self, theType, sender, args={}):
39 """callback"""
41 """callback"""
40
42
41 assert(theType == self.expectedType)
43 assert(theType == self.expectedType or
42 assert(sender == self.expectedSender)
44 self.expectedType == None)
45 assert(sender == self.expectedSender or
46 self.expectedSender == None)
43 assert(args == self.expectedKwArgs)
47 assert(args == self.expectedKwArgs)
44 self.recieved = True
48 self.recieved = True
45
49
@@ -49,6 +53,11 b' class Observer(object):'
49
53
50 assert(self.recieved)
54 assert(self.recieved)
51
55
56 def reset(self):
57 """reset"""
58
59 self.recieved = False
60
52
61
53
62
54 class Notifier(object):
63 class Notifier(object):
@@ -58,7 +67,7 b' class Notifier(object):'
58 self.theType = theType
67 self.theType = theType
59 self.kwargs = kwargs
68 self.kwargs = kwargs
60
69
61 def post(self, center=sharedCenter):
70 def post(self, center=notification.sharedCenter):
62 """fire"""
71 """fire"""
63
72
64 center.post_notification(self.theType, self,
73 center.post_notification(self.theType, self,
@@ -69,50 +78,102 b' class Notifier(object):'
69 # Test Cases
78 # Test Cases
70 #
79 #
71
80
72
81 class NotificationTests(unittest.TestCase):
73 def test_notification_delivered():
82 """docstring for NotificationTests"""
74 """Test that notifications are delivered"""
75 expectedType = 'EXPECTED_TYPE'
76 sender = Notifier(expectedType)
77 observer = Observer(expectedType, sender)
78
83
79 sender.post()
84 def tearDown(self):
85 notification.sharedCenter.remove_all_observers()
80
86
81 observer.verify()
87 def test_notification_delivered(self):
82
88 """Test that notifications are delivered"""
83
89 expectedType = 'EXPECTED_TYPE'
84 def test_type_specificity():
90 sender = Notifier(expectedType)
85 """Test that observers are registered by type"""
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()
98 def test_type_specificity(self):
94 unexpectedSender.post()
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()
107 sender.post()
97
108 unexpectedSender.post()
98
99 def test_sender_specificity():
100 """Test that observers are registered by sender"""
101
109
102 expectedType = "EXPECTED_TYPE"
110 observer.verify()
103 sender1 = Notifier(expectedType)
104 sender2 = Notifier(expectedType)
105 observer = Observer(expectedType, sender1)
106
111
107 sender1.post()
108 sender2.post()
109
112
110 observer.verify()
113 def test_sender_specificity(self):
111
114 """Test that observers are registered by sender"""
112
115
113 def test_complexity_with_no_observers():
116 expectedType = "EXPECTED_TYPE"
114 """Test that the notification center's algorithmic complexity is O(1)
117 sender1 = Notifier(expectedType)
115 with no registered observers (for the given notification type)
118 sender2 = Notifier(expectedType)
116 """
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