From 60553571df11990ae6ca530db1dfe705174be8d6 2014-08-18 17:28:07 From: Jason Grout Date: 2014-08-18 17:28:07 Subject: [PATCH] Make the widget property_lock store the JSON state, not the original object Comparison between arbitrary python objects can get crazy, whereas we really only care about if the JSON state we are syncing is different. So with this change, we store and check against the JSON state. --- diff --git a/IPython/html/widgets/widget.py b/IPython/html/widgets/widget.py index f39c754..98f49d5 100644 --- a/IPython/html/widgets/widget.py +++ b/IPython/html/widgets/widget.py @@ -202,9 +202,7 @@ class Widget(LoggingConfigurable): raise ValueError("key must be a string, an iterable of keys, or None") state = {} for k in keys: - f = self.trait_metadata(k, 'to_json') - if f is None: - f = self._trait_to_json + f = self.trait_metadata(k, 'to_json', self._trait_to_json) value = getattr(self, k) state[k] = f(value) return state @@ -255,6 +253,8 @@ class Widget(LoggingConfigurable): def _lock_property(self, key, value): """Lock a property-value pair. + The value should be the JSON state of the property. + NOTE: This, in addition to the single lock for all state changes, is flawed. In the future we may want to look into buffering state changes back to the front-end.""" @@ -280,7 +280,9 @@ class Widget(LoggingConfigurable): def _should_send_property(self, key, value): """Check the property lock (property_lock)""" - if (key == self._property_lock[0] and value == self._property_lock[1]): + to_json = self.trait_metadata(key, 'to_json', self._trait_to_json) + if (key == self._property_lock[0] + and to_json(value) == self._property_lock[1]): return False elif self._send_state_lock > 0: self._states_to_send.add(key) @@ -311,12 +313,10 @@ class Widget(LoggingConfigurable): """Called when a state is received from the front-end.""" for name in self.keys: if name in sync_data: - f = self.trait_metadata(name, 'from_json') - if f is None: - f = self._trait_from_json - value = f(sync_data[name]) - with self._lock_property(name, value): - setattr(self, name, value) + json_value = sync_data[name] + from_json = self.trait_metadata(name, 'from_json', self._trait_from_json) + with self._lock_property(name, json_value): + setattr(self, name, from_json(json_value)) def _handle_custom_msg(self, content): """Called when a custom msg is received."""