##// END OF EJS Templates
Add a new context manager, Widget.hold_sync(), which holds any syncing until the manager exits...
Jason Grout -
Show More
@@ -13,11 +13,12 b' in the IPython notebook front-end.'
13 13 # Imports
14 14 #-----------------------------------------------------------------------------
15 15 from contextlib import contextmanager
16 import collections
16 17
17 18 from IPython.core.getipython import get_ipython
18 19 from IPython.kernel.comm import Comm
19 20 from IPython.config import LoggingConfigurable
20 from IPython.utils.traitlets import Unicode, Dict, Instance, Bool, List, Tuple, Int
21 from IPython.utils.traitlets import Unicode, Dict, Instance, Bool, List, Tuple, Int, Set
21 22 from IPython.utils.py3compat import string_types
22 23
23 24 #-----------------------------------------------------------------------------
@@ -110,7 +111,8 b' class Widget(LoggingConfigurable):'
110 111 return [name for name in self.traits(sync=True)]
111 112
112 113 _property_lock = Tuple((None, None))
113
114 _send_state_lock = Int(0)
115 _states_to_send = Set(allow_none=False)
114 116 _display_callbacks = Instance(CallbackDispatcher, ())
115 117 _msg_callbacks = Instance(CallbackDispatcher, ())
116 118
@@ -174,12 +176,12 b' class Widget(LoggingConfigurable):'
174 176
175 177 Parameters
176 178 ----------
177 key : unicode (optional)
178 A single property's name to sync with the front-end.
179 key : unicode, or iterable (optional)
180 A single property's name or iterable of property names to sync with the front-end.
179 181 """
180 182 self._send({
181 183 "method" : "update",
182 "state" : self.get_state()
184 "state" : self.get_state(key=key)
183 185 })
184 186
185 187 def get_state(self, key=None):
@@ -187,10 +189,17 b' class Widget(LoggingConfigurable):'
187 189
188 190 Parameters
189 191 ----------
190 key : unicode (optional)
191 A single property's name to get.
192 key : unicode or iterable (optional)
193 A single property's name or iterable of property names to get.
192 194 """
193 keys = self.keys if key is None else [key]
195 if key is None:
196 keys = self.keys
197 elif isinstance(key, string_types):
198 keys = [key]
199 elif isinstance(key, collections.Iterable):
200 keys = key
201 else:
202 raise ValueError("key must be a string, an iterable of keys, or None")
194 203 state = {}
195 204 for k in keys:
196 205 f = self.trait_metadata(k, 'to_json')
@@ -255,10 +264,26 b' class Widget(LoggingConfigurable):'
255 264 finally:
256 265 self._property_lock = (None, None)
257 266
267 @contextmanager
268 def hold_sync(self):
269 """Hold syncing any state until the context manager is released"""
270 # We increment a value so that this can be nested. Syncing will happen when
271 # all levels have been released.
272 self._send_state_lock += 1
273 try:
274 yield
275 finally:
276 self._send_state_lock -=1
277 if self._send_state_lock == 0:
278 self.send_state(self._states_to_send)
279 self._states_to_send.clear()
280
258 281 def _should_send_property(self, key, value):
259 282 """Check the property lock (property_lock)"""
260 return key != self._property_lock[0] or \
261 value != self._property_lock[1]
283 if self._send_state_lock > 0:
284 self._states_to_send.add(key)
285 return False
286 return key != self._property_lock[0] or value != self._property_lock[1]
262 287
263 288 # Event handlers
264 289 @_show_traceback
General Comments 0
You need to be logged in to leave comments. Login now