Skip to content

Commit c1fce7c

Browse files
committed
WIP: handle update_display_data
1 parent 07ecd3b commit c1fce7c

File tree

4 files changed

+42
-12
lines changed

4 files changed

+42
-12
lines changed

jupyter_server_documents/kernels/kernel_client.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,7 @@ async def handle_document_related_message(self, msg: t.List[bytes]) -> t.Optiona
223223
parent_msg_data = self.message_cache.get(parent_msg_id)
224224
cell_id = parent_msg_data.get('cell_id')
225225

226+
self.log.info(f"msg_type: {dmsg["msg_type"]}")
226227
# Handle different message types using pattern matching
227228
match dmsg["msg_type"]:
228229
case "kernel_info_reply":
@@ -265,6 +266,7 @@ async def handle_document_related_message(self, msg: t.List[bytes]) -> t.Optiona
265266
if cell_id:
266267
# Extract execution count and update each collaborative room's notebook
267268
content = self.session.unpack(dmsg["content"])
269+
self.log.info(f"dsmg content: {content}")
268270
execution_count = content["execution_count"]
269271
for yroom in self._yrooms:
270272
notebook = await yroom.get_jupyter_ydoc()
@@ -273,12 +275,13 @@ async def handle_document_related_message(self, msg: t.List[bytes]) -> t.Optiona
273275
target_cell["execution_count"] = execution_count
274276
break
275277

276-
case "stream" | "display_data" | "execute_result" | "error":
278+
case "stream" | "display_data" | "execute_result" | "error" | "update_display_data":
277279
if cell_id:
278280
# Process specific output messages through an optional processor
279281
if self.output_processor and cell_id:
280282
cell_id = parent_msg_data.get('cell_id')
281283
content = self.session.unpack(dmsg["content"])
284+
self.log.info(f"dsmg content: {content}")
282285
dmsg = self.output_processor.process_output(dmsg['msg_type'], cell_id, content)
283286
# Suppress forwarding of processed messages by returning None
284287
return None

jupyter_server_documents/outputs/manager.py

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
class OutputsManager(LoggingConfigurable):
1515
_last_output_index = Dict(default_value={})
1616
_stream_count = Dict(default_value={})
17+
_output_index_by_display_id = Dict(default_value={})
1718

1819
outputs_path = Instance(PurePath, help="The local runtime dir")
1920
stream_limit = Int(default_value=10, config=True, allow_none=True)
@@ -34,6 +35,10 @@ def _build_path(self, file_id, cell_id=None, output_index=None):
3435
path = path / f"{output_index}.output"
3536
return path
3637

38+
def get_output_index(self, display_id: str):
39+
"""Returns output index for a cell by display_id"""
40+
return self._output_index_by_display_id.get(display_id)
41+
3742
def get_output(self, file_id, cell_id, output_index):
3843
"""Get an output by file_id, cell_id, and output_index."""
3944
path = self._build_path(file_id, cell_id, output_index)
@@ -102,23 +107,34 @@ def get_stream(self, file_id, cell_id):
102107
with open(path, "r", encoding="utf-8") as f:
103108
output = f.read()
104109
return output
105-
106-
def write(self, file_id, cell_id, output):
110+
111+
def write(self, file_id, cell_id, output, display_id=None):
107112
"""Write a new output for file_id and cell_id.
108113
109114
Returns a placeholder output (pycrdt.Map) or None if no placeholder
110115
output should be written to the ydoc.
111116
"""
112-
placeholder = self.write_output(file_id, cell_id, output)
117+
placeholder = self.write_output(file_id, cell_id, output, display_id)
113118
if output["output_type"] == "stream" and self.stream_limit is not None:
114119
placeholder = self.write_stream(file_id, cell_id, output, placeholder)
115120
return placeholder
116121

117-
def write_output(self, file_id, cell_id, output):
122+
def write_output(self, file_id, cell_id, output, display_id=None):
123+
print(f"display_id:{display_id} passed into write_output")
118124
self._ensure_path(file_id, cell_id)
119125
last_index = self._last_output_index.get(cell_id, -1)
120-
index = last_index + 1
121-
self._last_output_index[cell_id] = index
126+
if display_id:
127+
index = self._output_index_by_display_id.get(display_id)
128+
print(f"Found index: {index} for display_id {display_id}")
129+
if index is None:
130+
index = last_index + 1
131+
self._last_output_index[cell_id] = index
132+
self._output_index_by_display_id[display_id] = index
133+
print(f"Generated new index: {index} for display_id: {display_id}")
134+
else:
135+
index = last_index + 1
136+
self._last_output_index[cell_id] = index
137+
122138
path = self._build_path(file_id, cell_id, index)
123139
data = json.dumps(output, ensure_ascii=False)
124140
with open(path, "w", encoding="utf-8") as f:
@@ -165,6 +181,10 @@ def clear(self, file_id, cell_id=None):
165181
del self._stream_count[cell_id]
166182
except KeyError:
167183
pass
184+
try:
185+
del self._last_output_index[cell_id]
186+
except KeyError:
187+
pass
168188
path = self._build_path(file_id, cell_id)
169189
try:
170190
shutil.rmtree(path)

jupyter_server_documents/outputs/output_processor.py

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -106,10 +106,13 @@ async def output_task(self, msg_type, cell_id, content):
106106
return
107107
self._file_id = file_id
108108

109+
display_id = content.get("transient", {}).get("display_id")
110+
self.log.info(f"display_id: {display_id} found in content")
111+
output_index = self.outputs_manager.get_output_index(display_id) if display_id else None
109112
# Convert from the message spec to the nbformat output structure
110-
if self.use_outputs_service:
113+
if self.use_outputs_service:
111114
output = self.transform_output(msg_type, content, ydoc=False)
112-
output = self.outputs_manager.write(file_id, cell_id, output)
115+
output = self.outputs_manager.write(file_id, cell_id, output, display_id)
113116
else:
114117
output = self.transform_output(msg_type, content, ydoc=True)
115118

@@ -125,8 +128,11 @@ async def output_task(self, msg_type, cell_id, content):
125128
# Write the outputs to the ydoc cell.
126129
_, target_cell = notebook.find_cell(cell_id)
127130
if target_cell is not None and output is not None:
128-
target_cell["outputs"].append(output)
129-
self.log.info(f"Write output to ydoc: {path} {cell_id} {output}")
131+
if output_index:
132+
target_cell["outputs"][output_index] = output
133+
else:
134+
target_cell["outputs"].append(output)
135+
self.log.info(f"Wrote output to ydoc: {path} {cell_id} {output}")
130136

131137

132138
def transform_output(self, msg_type, content, ydoc=False):
@@ -141,7 +147,7 @@ def transform_output(self, msg_type, content, ydoc=False):
141147
"text": content["text"],
142148
"name": content["name"]
143149
})
144-
elif msg_type == "display_data":
150+
elif msg_type == "display_data" or msg_type == "update_display_data":
145151
output = factory({
146152
"output_type": "display_data",
147153
"data": content["data"],

src/notebook-factory/notebook-factory.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ const DIRTY_CLASS = 'jp-mod-dirty';
3838
}
3939

4040
if (change.outputsChange) {
41+
console.trace(change.outputsChange);
4142
globalModelDBMutex(() => {
4243
let retain = 0;
4344
for (const outputsChange of change.outputsChange!) {

0 commit comments

Comments
 (0)