Skip to content

Commit d77c894

Browse files
committed
Refactored
1 parent 9eb78f6 commit d77c894

File tree

2 files changed

+40
-35
lines changed

2 files changed

+40
-35
lines changed

jupyter_server_documents/kernels/kernel_client.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -105,12 +105,12 @@ def handle_incoming_message(self, channel_name: str, msg: list[bytes]):
105105
msg_id = header["msg_id"]
106106
metadata = self.session.unpack(msg[2])
107107
cell_id = metadata.get("cellId")
108-
# Clear output processor if this cell already has
109-
# an existing request.
108+
109+
# Clear cell outputs if cell is re-executedq
110110
if cell_id:
111111
existing = self.message_cache.get(cell_id=cell_id)
112112
if existing and existing['msg_id'] != msg_id:
113-
self.output_processor.clear(cell_id)
113+
self.output_processor.clear_cell_outputs(cell_id)
114114

115115
self.message_cache.add({
116116
"msg_id": msg_id,

jupyter_server_documents/outputs/output_processor.py

Lines changed: 37 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
class OutputProcessor(LoggingConfigurable):
1010

1111
_file_id = Unicode(default_value=None, allow_none=True)
12-
_clear_output_cells = Dict(default_value={})
12+
_pending_clear_output_cells = Dict(default_value={})
1313

1414
use_outputs_service = Bool(
1515
default_value=True,
@@ -47,48 +47,54 @@ def yroom_manager(self):
4747
"""A shortcut for the jupyter server ydoc manager."""
4848
return self.settings["yroom_manager"]
4949

50-
51-
async def get_notebook_ydoc(self, file_id):
50+
async def get_jupyter_ydoc(self, file_id):
5251
room_id = f"json:notebook:{file_id}"
5352
room = self.yroom_manager.get_room(room_id)
5453
if room is None:
5554
self.log.error(f"YRoom not found: {room_id}")
5655
return
57-
notebook = await room.get_jupyter_ydoc()
56+
ydoc = await room.get_jupyter_ydoc()
5857

59-
return notebook
58+
return ydoc
6059

61-
async def clear_cell_outputs(self, cell_id, room_id):
60+
async def _clear_ydoc_outputs(self, cell_id):
6261
"""Clears the outputs of a cell in ydoc"""
63-
room = self.yroom_manager.get_room(room_id)
64-
if room is None:
65-
self.log.error(f"YRoom not found: {room_id}")
62+
63+
if not self._file_id:
6664
return
67-
notebook = await room.get_jupyter_ydoc()
68-
self.log.info(f"Notebook: {notebook}")
69-
65+
66+
notebook = self.get_jupyter_ydoc(self._file_id)
7067
cell_index, target_cell = notebook.find_cell(cell_id)
7168
if target_cell is not None:
7269
target_cell["outputs"].clear()
73-
self.log.info(f"Cleared outputs for ydoc: {room_id} {cell_index}")
70+
self.log.info(f"Cleared outputs for {self._file_id=}, {cell_index=}")
7471

75-
def clear(self, cell_id):
76-
"""Clear all outputs for a given cell Id."""
72+
def clear_cell_outputs(self, cell_id) -> asyncio.Task | None:
73+
"""
74+
Clears all outputs for a cell on disk and in ydoc. Returns an
75+
`asyncio.Task` that clears outputs for the cell in ydoc. Callers
76+
should wait for this task to complete, if they expect to update
77+
the ydoc.
78+
79+
```
80+
clear_output_task = clear("cellid")
81+
await clear_outputs_task
82+
```
83+
"""
7784

78-
task = None
85+
clear_outputs_task = None
7986

8087
if self._file_id is not None:
8188
if self.use_outputs_service:
82-
room_id = f"json:notebook:{self._file_id}"
83-
task = asyncio.create_task(self.clear_cell_outputs(cell_id, room_id))
89+
clear_outputs_task = asyncio.create_task(
90+
self._clear_ydoc_outputs(cell_id)
91+
)
8492
self.outputs_manager.clear(file_id=self._file_id, cell_id=cell_id)
8593

86-
# Remove any pending delayed clear for this cell
87-
self._clear_output_cells.pop(cell_id, None)
94+
self._pending_clear_output_cells.pop(cell_id, None)
8895

89-
return task
96+
return clear_outputs_task
9097

91-
# Outgoing messages
9298
def process_output(self, msg_type: str, cell_id: str, content: dict):
9399
"""Process outgoing messages from the kernel.
94100
@@ -109,20 +115,19 @@ async def output_task(self, msg_type, cell_id, content):
109115
"""A coroutine to handle output messages."""
110116

111117
if msg_type == "clear_output":
112-
if not content.get("wait", False):
113-
# Clear immediately
114-
self.clear(cell_id)
118+
wait = content.get("wait", False)
119+
if not wait:
120+
self.clear_cell_outputs(cell_id)
115121
else:
116-
# Mark for delayed clear, overriding any previous pending clear
117-
self._clear_output_cells[cell_id] = True
122+
self._pending_clear_output_cells[cell_id] = True
118123

119124
return
120125

121-
# Check for delayed clear before processing output
122-
if cell_id in self._clear_output_cells and msg_type != "clear_output":
123-
clear_task = self.clear(cell_id)
124-
if clear_task is not None:
125-
await clear_task
126+
# Check for pending clear_output before processing output
127+
if cell_id in self._pending_clear_output_cells and (
128+
clear_task := self.clear_cell_outputs(cell_id)
129+
):
130+
await clear_task
126131

127132
try:
128133
# TODO: The session manager may have multiple notebooks connected to the kernel

0 commit comments

Comments
 (0)