@@ -512,34 +512,47 @@ def send_state(self, key=None):
512
512
A single property's name or iterable of property names to sync with the front-end.
513
513
"""
514
514
state = self .get_state (key = key )
515
- if len (state ) > 0 :
516
- if JUPYTER_WIDGETS_ECHO :
517
- echo_state = {}
518
- if self ._updated_attrs_from_frontend :
519
- for attr in self ._updated_attrs_from_frontend :
520
- echo_state [attr ] = state [attr ]
521
- del state [attr ]
522
- self ._updated_attrs_from_frontend = None
523
- state , buffer_paths , buffers = _remove_buffers (state )
524
- echo_state , echo_buffer_paths , echo_buffers = _remove_buffers (echo_state )
525
- msg = {'method' : 'update' , 'state' : state , 'buffer_paths' : buffer_paths }
526
- if echo_state or echo_buffer_paths :
527
- msg ['echo_state' ] = echo_state
528
- msg ['echo_buffer_paths' ] = echo_buffer_paths
529
- buffers += echo_buffers
530
- self ._send (msg , buffers = buffers )
531
- return
532
-
533
- # TODO: _property_lock is our understanding of what the frontend thinks values are
534
- # TODO: it is based on what we've sent the frontend
535
- if self ._property_lock : # we need to keep this dict up to date with the front-end values
536
- for name , value in state .items ():
537
- if name in self ._property_lock :
538
- self ._property_lock [name ] = value
539
- state , buffer_paths , buffers = _remove_buffers (state )
540
- msg = {'method' : 'update' , 'state' : state , 'buffer_paths' : buffer_paths }
541
- self ._send (msg , buffers = buffers )
515
+ if len (state ) == 0 :
516
+ return
542
517
518
+ # For any values that are currently locked (i.e., we are not echoing,
519
+ # and we are currently processing an update for), we need to update our
520
+ # notion of what the frontend value is.
521
+
522
+ # TODO: does this handle the case where we get an update from the
523
+ # frontend, in the middle of this we update the value *and send it*, and
524
+ # then at the end we have to evaluate whether to send an echo message.
525
+ # We need to send an echo message at some point so the originator can unblock
526
+ # other echo messages, and we don't want to send the same data twice. So probably
527
+ # the first time we send an update for an attribute back, we need to send it as an
528
+ # echo, and record that we've already sent it. So perhaps we just need to keep
529
+ # track of what echos we need to send, and we send at the end whatever echos still
530
+ # need to be sent.
531
+
532
+ # Sending echos at the end may send updates out of order, i.e., we may send
533
+ # some updates in the middle, then send echos at the end. perhaps we should immediately
534
+ # send echos just as we start processing the message?
535
+ if self ._property_lock :
536
+ for name , value in state .items ():
537
+ if name in self ._property_lock :
538
+ self ._property_lock [name ] = value
539
+
540
+
541
+ echo_state = {}
542
+ if self ._updated_attrs_from_frontend :
543
+ for attr in self ._updated_attrs_from_frontend :
544
+ echo_state [attr ] = state [attr ]
545
+ del state [attr ]
546
+ self ._updated_attrs_from_frontend = None
547
+ state , buffer_paths , buffers = _remove_buffers (state )
548
+ echo_state , echo_buffer_paths , echo_buffers = _remove_buffers (echo_state )
549
+ msg = {'method' : 'update' , 'state' : state , 'buffer_paths' : buffer_paths }
550
+ if echo_state or echo_buffer_paths :
551
+ msg ['echo_state' ] = echo_state
552
+ msg ['echo_buffer_paths' ] = echo_buffer_paths
553
+ buffers += echo_buffers
554
+ self ._send (msg , buffers = buffers )
555
+ return
543
556
544
557
def get_state (self , key = None , drop_defaults = False ):
545
558
"""Gets the widget state, or a piece of it.
0 commit comments