##// END OF EJS Templates
Update widget serializer/unserializer to allow custom serialization on a trait-by-trait basis....
Jason Grout -
Show More
@@ -195,7 +195,15 b' class Widget(LoggingConfigurable):'
195 A single property's name to get.
195 A single property's name to get.
196 """
196 """
197 keys = self.keys if key is None else [key]
197 keys = self.keys if key is None else [key]
198 return {k: self._pack_widgets(getattr(self, k)) for k in keys}
198 state = {}
199 for k in keys:
200 f = self.trait_metadata(k, 'to_json')
201 value = getattr(self, k)
202 if f is not None:
203 state[k] = f(value)
204 else:
205 state[k] = self._serialize_trait(value)
206 return state
199
207
200 def send(self, content):
208 def send(self, content):
201 """Sends a custom msg to the widget model in the front-end.
209 """Sends a custom msg to the widget model in the front-end.
@@ -280,7 +288,11 b' class Widget(LoggingConfigurable):'
280 """Called when a state is received from the front-end."""
288 """Called when a state is received from the front-end."""
281 for name in self.keys:
289 for name in self.keys:
282 if name in sync_data:
290 if name in sync_data:
283 value = self._unpack_widgets(sync_data[name])
291 f = self.trait_metadata(name, 'from_json')
292 if f is not None:
293 value = f(sync_data[name])
294 else:
295 value = self._unserialize_trait(sync_data[name])
284 with self._lock_property(name, value):
296 with self._lock_property(name, value):
285 setattr(self, name, value)
297 setattr(self, name, value)
286
298
@@ -299,31 +311,34 b' class Widget(LoggingConfigurable):'
299 """Called when a view has been displayed for this widget instance"""
311 """Called when a view has been displayed for this widget instance"""
300 self._display_callbacks(self, **kwargs)
312 self._display_callbacks(self, **kwargs)
301
313
302 def _pack_widgets(self, x):
314 def _serialize_trait(self, x):
303 """Recursively converts all widget instances to model id strings.
315 """Serialize a trait value to json
304
316
305 Children widgets will be stored and transmitted to the front-end by
317 Traverse lists/tuples and dicts and serialize their values as well.
306 their model ids. Return value must be JSON-able."""
318 Replace any widgets with their model_id
319 """
307 if isinstance(x, dict):
320 if isinstance(x, dict):
308 return {k: self._pack_widgets(v) for k, v in x.items()}
321 return {k: self._serialize_trait(v) for k, v in x.items()}
309 elif isinstance(x, (list, tuple)):
322 elif isinstance(x, (list, tuple)):
310 return [self._pack_widgets(v) for v in x]
323 return [self._serialize_trait(v) for v in x]
311 elif isinstance(x, Widget):
324 elif isinstance(x, Widget):
312 return x.model_id
325 return x.model_id
313 else:
326 else:
314 return x # Value must be JSON-able
327 return x # Value must be JSON-able
315
328
316 def _unpack_widgets(self, x):
329 def _unserialize_trait(self, x):
317 """Recursively converts all model id strings to widget instances.
330 """Convert json values to objects
318
331
319 Children widgets will be stored and transmitted to the front-end by
332 We explicitly support converting valid string widget UUIDs to Widget references.
320 their model ids."""
333 """
321 if isinstance(x, dict):
334 if isinstance(x, dict):
322 return {k: self._unpack_widgets(v) for k, v in x.items()}
335 return {k: self._unserialize_trait(v) for k, v in x.items()}
323 elif isinstance(x, (list, tuple)):
336 elif isinstance(x, (list, tuple)):
324 return [self._unpack_widgets(v) for v in x]
337 return [self._unserialize_trait(v) for v in x]
325 elif isinstance(x, string_types):
338 elif isinstance(x, string_types) and x in Widget.widgets:
326 return x if x not in Widget.widgets else Widget.widgets[x]
339 # we want to support having child widgets at any level in a hierarchy
340 # trusting that a widget UUID will not appear out in the wild
341 return Widget.widgets[x]
327 else:
342 else:
328 return x
343 return x
329
344
General Comments 0
You need to be logged in to leave comments. Login now