diff --git a/src/ypywidgets/comm.py b/src/ypywidgets/comm.py index b2d1d91..7c8cc04 100644 --- a/src/ypywidgets/comm.py +++ b/src/ypywidgets/comm.py @@ -54,6 +54,8 @@ def __init__( msg = create_sync_message(ydoc) self._comm.send(buffers=[msg]) self._comm.on_msg(self._receive) + ydoc.observe(self._bufferize) + self._updates: list[bytes] | None = [] @property def awareness(self) -> Awareness: @@ -67,15 +69,23 @@ def _receive(self, msg): if reply is not None: self._comm.send(buffers=[reply]) if message[1] == YSyncMessageType.SYNC_STEP2: + assert self._updates is not None + for update in self._updates: + message = create_update_message(update) + self._comm.send(buffers=[message]) + self._updates = None self._ydoc.observe(self._send) case YMessageType.AWARENESS: # Same as pycrdt.websocket.yroom: strip Y message kind, decode body. update = read_message(message[1:]) self._awareness.apply_awareness_update(update, None) + def _bufferize(self, event: TransactionEvent): + if self._updates is not None: + self._updates.append(event.update) + def _send(self, event: TransactionEvent): - update = event.update - message = create_update_message(update) + message = create_update_message(event.update) self._comm.send(buffers=[message]) diff --git a/tests/test_attributes.py b/tests/test_attributes.py index 7e762d5..060b6fb 100644 --- a/tests/test_attributes.py +++ b/tests/test_attributes.py @@ -45,6 +45,7 @@ async def test_create_ydoc(synced_widgets, context): async def test_sync_attribute(widget_factories, synced_widgets, context): async with context: local_widget = await synced_widgets.get_local_widget() + local_widget.foo = "foo3" remote_widget = await synced_widgets.get_remote_widget() with pytest.raises(AttributeError): @@ -53,8 +54,10 @@ async def test_sync_attribute(widget_factories, synced_widgets, context): with pytest.raises(AttributeError): assert remote_widget.wrong_attr2 + await sleep(0.01) + assert remote_widget.foo == "foo3" local_widget.foo = "foo2" - assert remote_widget.foo is None # not synced yet + assert remote_widget.foo == "foo3" # not synced yet await sleep(0.01) # wait for sync assert remote_widget.foo == "foo2"