@ -13,11 +13,12 @@ in the IPython notebook front-end.
# Imports
#-----------------------------------------------------------------------------
from contextlib import contextmanager
import collections
from IPython . core . getipython import get_ipython
from IPython . kernel . comm import Comm
from IPython . config import LoggingConfigurable
from IPython . utils . traitlets import Unicode , Dict , Instance , Bool , List , Tuple , Int
from IPython . utils . traitlets import Unicode , Dict , Instance , Bool , List , Tuple , Int , Set
from IPython . utils . py3compat import string_types
#-----------------------------------------------------------------------------
@ -110,7 +111,8 @@ class Widget(LoggingConfigurable):
return [ name for name in self . traits ( sync = True ) ]
_property_lock = Tuple ( ( None , None ) )
_send_state_lock = Int ( 0 )
_states_to_send = Set ( allow_none = False )
_display_callbacks = Instance ( CallbackDispatcher , ( ) )
_msg_callbacks = Instance ( CallbackDispatcher , ( ) )
@ -174,12 +176,12 @@ class Widget(LoggingConfigurable):
Parameters
- - - - - - - - - -
key : unicode ( optional )
A single property ' s name to sync with the front-end.
key : unicode , or iterable ( optional )
A single property ' s name or iterable of property names to sync with the front-end.
"""
self . _send ( {
" method " : " update " ,
" state " : self . get_state ( )
" state " : self . get_state ( key = key )
} )
def get_state ( self , key = None ) :
@ -187,10 +189,17 @@ class Widget(LoggingConfigurable):
Parameters
- - - - - - - - - -
key : unicode ( optional )
A single property ' s name to get.
key : unicode or iterable ( optional )
A single property ' s name or iterable of property names to get.
"""
keys = self . keys if key is None else [ key ]
if key is None :
keys = self . keys
elif isinstance ( key , string_types ) :
keys = [ key ]
elif isinstance ( key , collections . Iterable ) :
keys = key
else :
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 ' )
@ -255,10 +264,26 @@ class Widget(LoggingConfigurable):
finally :
self . _property_lock = ( None , None )
@contextmanager
def hold_sync ( self ) :
""" Hold syncing any state until the context manager is released """
# We increment a value so that this can be nested. Syncing will happen when
# all levels have been released.
self . _send_state_lock + = 1
try :
yield
finally :
self . _send_state_lock - = 1
if self . _send_state_lock == 0 :
self . send_state ( self . _states_to_send )
self . _states_to_send . clear ( )
def _should_send_property ( self , key , value ) :
""" Check the property lock (property_lock) """
return key != self . _property_lock [ 0 ] or \
value != self . _property_lock [ 1 ]
if self . _send_state_lock > 0 :
self . _states_to_send . add ( key )
return False
return key != self . _property_lock [ 0 ] or value != self . _property_lock [ 1 ]
# Event handlers
@_show_traceback