Skip to content

Commit aedee7b

Browse files
feat: support IPython clear_output for output widget (#212)
1 parent 6005f96 commit aedee7b

File tree

3 files changed

+53
-3
lines changed

3 files changed

+53
-3
lines changed

solara/server/patch.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,9 @@ def hook(msg):
269269
if msg["msg_type"] == "display_data":
270270
self.outputs += ({"output_type": "display_data", "data": msg["content"]["data"], "metadata": msg["content"]["metadata"]},)
271271
return None
272+
if msg["msg_type"] == "clear_output":
273+
self.outputs = ()
274+
return None
272275
return msg
273276

274277
get_ipython().display_pub.register_hook(hook)

solara/server/shell.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -119,11 +119,15 @@ def clear_output(self, wait=False):
119119
"""
120120
content = dict(wait=wait)
121121
self._flush_streams()
122+
msg = self.session.msg("clear_output", json_clean(content), parent=self.parent_header)
123+
for hook in self._hooks:
124+
msg = hook(msg)
125+
if msg is None:
126+
return
127+
122128
self.session.send(
123129
self.pub_socket,
124-
"clear_output",
125-
content,
126-
parent=self.parent_header,
130+
msg,
127131
ident=self.topic,
128132
)
129133

tests/unit/output_widget_test.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
from unittest.mock import Mock
2+
3+
import IPython.display
4+
import ipywidgets as widgets
5+
6+
from solara.server import app, kernel
7+
8+
9+
def test_interactive_shell(no_app_context):
10+
ws1 = Mock()
11+
ws2 = Mock()
12+
kernel1 = kernel.Kernel()
13+
kernel2 = kernel.Kernel()
14+
kernel1.session.websockets.add(ws1)
15+
kernel2.session.websockets.add(ws2)
16+
context1 = app.AppContext(id="1", kernel=kernel1)
17+
context2 = app.AppContext(id="2", kernel=kernel2)
18+
19+
with context1:
20+
output1 = widgets.Output()
21+
with output1:
22+
IPython.display.display("test1")
23+
assert output1.outputs[0]["data"]["text/plain"] == "'test1'"
24+
assert ws1.send.call_count == 3 # create 2 widgets (layout and output) and update data
25+
assert ws2.send.call_count == 0
26+
with context2:
27+
output2 = widgets.Output()
28+
with output2:
29+
IPython.display.display("test2")
30+
assert output2.outputs[0]["data"]["text/plain"] == "'test2'"
31+
assert ws1.send.call_count == 3
32+
assert ws2.send.call_count == 3
33+
34+
context1.close()
35+
context2.close()
36+
37+
38+
def test_clear_output():
39+
output1 = widgets.Output()
40+
with output1:
41+
IPython.display.display("test1")
42+
IPython.display.clear_output()
43+
assert len(output1.outputs) == 0

0 commit comments

Comments
 (0)