Update widget serializer/unserializer to allow custom serialization on a trait-by-trait basis.

Serializers/unserializers are given as the trait metadata keys `to_json` and `from_json`.
Jason Grout 12 years ago
parent 7ce5bb8a37
commit 0c72fddaba

@ -195,8 +195,16 @@ class Widget(LoggingConfigurable):
A single property's name to get.
"""
keys = self.keys if key is None else [key]
return {k: self._pack_widgets(getattr(self, k)) for k in keys}
state = {}
for k in keys:
f = self.trait_metadata(k, 'to_json')
value = getattr(self, k)
if f is not None:
state[k] = f(value)
else:
state[k] = self._serialize_trait(value)
return state
def send(self, content):
"""Sends a custom msg to the widget model in the front-end.
@ -280,7 +288,11 @@ class Widget(LoggingConfigurable):
"""Called when a state is received from the front-end."""
for name in self.keys:
if name in sync_data:
value = self._unpack_widgets(sync_data[name])
f = self.trait_metadata(name, 'from_json')
if f is not None:
value = f(sync_data[name])
else:
value = self._unserialize_trait(sync_data[name])
with self._lock_property(name, value):
setattr(self, name, value)
@ -299,31 +311,34 @@ class Widget(LoggingConfigurable):
"""Called when a view has been displayed for this widget instance"""
self._display_callbacks(self, **kwargs)
def _pack_widgets(self, x):
"""Recursively converts all widget instances to model id strings.
def _serialize_trait(self, x):
"""Serialize a trait value to json
Children widgets will be stored and transmitted to the front-end by
their model ids. Return value must be JSON-able."""
Traverse lists/tuples and dicts and serialize their values as well.
Replace any widgets with their model_id
"""
if isinstance(x, dict):
return {k: self._pack_widgets(v) for k, v in x.items()}
return {k: self._serialize_trait(v) for k, v in x.items()}
elif isinstance(x, (list, tuple)):
return [self._pack_widgets(v) for v in x]
return [self._serialize_trait(v) for v in x]
elif isinstance(x, Widget):
return x.model_id
else:
return x # Value must be JSON-able
def _unpack_widgets(self, x):
"""Recursively converts all model id strings to widget instances.
def _unserialize_trait(self, x):
"""Convert json values to objects
Children widgets will be stored and transmitted to the front-end by
their model ids."""
We explicitly support converting valid string widget UUIDs to Widget references.
"""
if isinstance(x, dict):
return {k: self._unpack_widgets(v) for k, v in x.items()}
return {k: self._unserialize_trait(v) for k, v in x.items()}
elif isinstance(x, (list, tuple)):
return [self._unpack_widgets(v) for v in x]
elif isinstance(x, string_types):
return x if x not in Widget.widgets else Widget.widgets[x]
return [self._unserialize_trait(v) for v in x]
elif isinstance(x, string_types) and x in Widget.widgets:
# we want to support having child widgets at any level in a hierarchy
# trusting that a widget UUID will not appear out in the wild
return Widget.widgets[x]
else:
return x

Loading…
Cancel
Save