Show More
@@ -13,11 +13,12 b' in the IPython notebook front-end.' | |||||
13 | # Imports |
|
13 | # Imports | |
14 | #----------------------------------------------------------------------------- |
|
14 | #----------------------------------------------------------------------------- | |
15 | from contextlib import contextmanager |
|
15 | from contextlib import contextmanager | |
|
16 | import collections | |||
16 |
|
17 | |||
17 | from IPython.core.getipython import get_ipython |
|
18 | from IPython.core.getipython import get_ipython | |
18 | from IPython.kernel.comm import Comm |
|
19 | from IPython.kernel.comm import Comm | |
19 | from IPython.config import LoggingConfigurable |
|
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 | from IPython.utils.py3compat import string_types |
|
22 | from IPython.utils.py3compat import string_types | |
22 |
|
23 | |||
23 | #----------------------------------------------------------------------------- |
|
24 | #----------------------------------------------------------------------------- | |
@@ -110,7 +111,8 b' class Widget(LoggingConfigurable):' | |||||
110 | return [name for name in self.traits(sync=True)] |
|
111 | return [name for name in self.traits(sync=True)] | |
111 |
|
112 | |||
112 | _property_lock = Tuple((None, None)) |
|
113 | _property_lock = Tuple((None, None)) | |
113 |
|
114 | _send_state_lock = Int(0) | ||
|
115 | _states_to_send = Set(allow_none=False) | |||
114 | _display_callbacks = Instance(CallbackDispatcher, ()) |
|
116 | _display_callbacks = Instance(CallbackDispatcher, ()) | |
115 | _msg_callbacks = Instance(CallbackDispatcher, ()) |
|
117 | _msg_callbacks = Instance(CallbackDispatcher, ()) | |
116 |
|
118 | |||
@@ -174,12 +176,12 b' class Widget(LoggingConfigurable):' | |||||
174 |
|
176 | |||
175 | Parameters |
|
177 | Parameters | |
176 | ---------- |
|
178 | ---------- | |
177 | key : unicode (optional) |
|
179 | key : unicode, or iterable (optional) | |
178 | A single property's name to sync with the front-end. |
|
180 | A single property's name or iterable of property names to sync with the front-end. | |
179 | """ |
|
181 | """ | |
180 | self._send({ |
|
182 | self._send({ | |
181 | "method" : "update", |
|
183 | "method" : "update", | |
182 | "state" : self.get_state() |
|
184 | "state" : self.get_state(key=key) | |
183 | }) |
|
185 | }) | |
184 |
|
186 | |||
185 | def get_state(self, key=None): |
|
187 | def get_state(self, key=None): | |
@@ -187,10 +189,17 b' class Widget(LoggingConfigurable):' | |||||
187 |
|
189 | |||
188 | Parameters |
|
190 | Parameters | |
189 | ---------- |
|
191 | ---------- | |
190 | key : unicode (optional) |
|
192 | key : unicode or iterable (optional) | |
191 | A single property's name to get. |
|
193 | A single property's name or iterable of property names to get. | |
192 | """ |
|
194 | """ | |
193 |
|
|
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 | state = {} |
|
203 | state = {} | |
195 | for k in keys: |
|
204 | for k in keys: | |
196 | f = self.trait_metadata(k, 'to_json') |
|
205 | f = self.trait_metadata(k, 'to_json') | |
@@ -255,10 +264,26 b' class Widget(LoggingConfigurable):' | |||||
255 | finally: |
|
264 | finally: | |
256 | self._property_lock = (None, None) |
|
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 | def _should_send_property(self, key, value): |
|
281 | def _should_send_property(self, key, value): | |
259 | """Check the property lock (property_lock)""" |
|
282 | """Check the property lock (property_lock)""" | |
260 | return key != self._property_lock[0] or \ |
|
283 | if self._send_state_lock > 0: | |
261 | value != self._property_lock[1] |
|
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 | # Event handlers |
|
288 | # Event handlers | |
264 | @_show_traceback |
|
289 | @_show_traceback |
General Comments 0
You need to be logged in to leave comments.
Login now