diff --git a/IPython/html/widgets/widget.py b/IPython/html/widgets/widget.py
index 3ba8f00..9fb2ea9 100644
--- a/IPython/html/widgets/widget.py
+++ b/IPython/html/widgets/widget.py
@@ -14,6 +14,7 @@ in the IPython notebook frontend.
#-----------------------------------------------------------------------------
from copy import copy
from glob import glob
+from contextlib import contextmanager
import uuid
import sys
import os
@@ -30,6 +31,17 @@ from IPython.utils.py3compat import string_types
#-----------------------------------------------------------------------------
# Classes
#-----------------------------------------------------------------------------
+@contextmanager
+def PropertyLock(instance, key, value):
+ instance._property_lock = (key, value)
+ yield
+ del instance._property_lock
+
+def should_send_property(instance, key, value):
+ return not hasattr(instance, _property_lock) or \
+ key != instance._property_lock[0] or \
+ value != instance._property_lock[1]
+
class Widget(LoggingConfigurable):
@@ -58,8 +70,6 @@ class Widget(LoggingConfigurable):
to use to represent the widget.""")
# Private/protected declarations
- # todo: change this to a context manager
- _property_lock = (None, None) # Last updated (key, value) from the front-end. Prevents echo.
_comm = Instance('IPython.kernel.comm.Comm')
def __init__(self, **kwargs):
@@ -114,11 +124,9 @@ class Widget(LoggingConfigurable):
"""Called when a state is recieved from the frontend."""
for name in self.keys:
if name in sync_data:
- try:
- self._property_lock = (name, sync_data[name])
- setattr(self, name, sync_data[name])
- finally:
- self._property_lock = (None, None)
+ value = sync_data[name]
+ with PropertyLock(self, name, value):
+ setattr(self, name, value)
def _handle_custom_msg(self, content):
@@ -145,7 +153,7 @@ class Widget(LoggingConfigurable):
def _handle_property_changed(self, name, old, new):
"""Called when a property has been changed."""
# Make sure this isn't information that the front-end just sent us.
- if self._property_lock[0] != name and self._property_lock[1] != new:
+ if should_send_property(self, name, new):
# Send new state to frontend
self.send_state(key=name)