jupyter-widgets-contrib / ipycanvas

Interactive Canvas in Jupyter
https://ipycanvas.readthedocs.io/en/latest/
BSD 3-Clause "New" or "Revised" License
688 stars 64 forks source link

Not working with ipywidgets_bokeh and Panel #236

Open MarcSkovMadsen opened 2 years ago

MarcSkovMadsen commented 2 years ago

CROSS POST: https://github.com/bokeh/ipywidgets_bokeh/issues/44 CROSS POST: https://github.com/holoviz/panel/issues/3023

Panel: 0.12.6 Bokeh: 2.4.2 ipywidgets_bokeh: 1.2.1 ipycanvas: 0.10.2 ipykernel: 6.6.0

Raises expected a string or ArrayBuffer, got object.

image

# pip install ipycanvas panel ipywidgets_bokeh
import panel as pn
from ipycanvas import Canvas

pn.extension('ipywidgets')

canvas = Canvas(width=200, height=200)

# Cubic curves example
def draw():
    canvas.begin_path()
    canvas.move_to(75, 40)
    canvas.bezier_curve_to(75, 37, 70, 25, 50, 25)
    canvas.bezier_curve_to(20, 25, 20, 62.5, 20, 62.5)
    canvas.bezier_curve_to(20, 80, 40, 102, 75, 120)
    canvas.bezier_curve_to(110, 102, 130, 80, 130, 62.5)
    canvas.bezier_curve_to(130, 62.5, 130, 25, 100, 25)
    canvas.bezier_curve_to(85, 25, 75, 37, 75, 40)
    canvas.fill()
    print("drawn")

pn.state.onload(draw)

pn.panel(canvas, height=200, width=200).servable()
MarcSkovMadsen commented 2 years ago

Additional Context

Panel should work with ipywidgets via ipywidgets_bokeh. See https://panel.holoviz.org/reference/panes/IPyWidget.html#

martinRenou commented 2 years ago

It might be an issue with Bokeh itself. I see the error raises in ipywidgets_bokeh.js, which is not ipycanvas's JavaScript code nor ipywidgets's one.

MarcSkovMadsen commented 2 years ago

We had a similar issue with ipyleaflet. We investigated panel, ipywidgets_bokeh and ipyleaflet. It turned out it was an error in ipyleaflet https://github.com/jupyter-widgets/ipyleaflet/pull/873. So it can be anywhere and I've crossposted with Panel and ipywidgets_bokeh. You where actually involved in solving that one. 😄 Thanks.

martinRenou commented 2 years ago

Ok. Does the error show up also when not trying to draw anything? Are you able to show an empty canvas?

MarcSkovMadsen commented 2 years ago

Yes

# pip install ipycanvas panel ipywidgets_bokeh
import panel as pn
from ipycanvas import Canvas

pn.extension('ipywidgets')

canvas = Canvas(width=200, height=200)

pn.panel(canvas, height=200, width=200).servable()
panel serve script.py --autoreload

image

image

MarcSkovMadsen commented 2 years ago

With Ipyleaflet the below had to be added.

image

Could that be the problem here as well?

martinRenou commented 2 years ago

I don't think so. If the Canvas shows up, then the canvas widget model is less likely to be the problem.

I think it's an issue with binary buffers in custom comm messages in bokeh.

Can you click here? error So we can see in which part of the code it fails?

MarcSkovMadsen commented 2 years ago

image

martinRenou commented 2 years ago

Would you be able to open the debugger at this point and show what e contains?

MarcSkovMadsen commented 2 years ago

This is an example. I don't believe this is the one failing.

image

I will try to debug and share.

martinRenou commented 2 years ago

Maybe a conditional breakpoint would help, with the condition:

!(e instanceof ArrayBuffer)
MarcSkovMadsen commented 2 years ago

It seems its when e is null

image

martinRenou commented 2 years ago

I don't know what this ipywidgets_bokeh message is. Is it some custom messaging logic that Bokeh uses for wrapping all Jupyter messages?

martinRenou commented 2 years ago

It might be worth looking what happens Python side with this ipywidges_bokeh, there might be a reason why the message is null (or None Python side?)

MarcSkovMadsen commented 2 years ago

Probably its some custom messaging logic. But I am not familiar with ipywidgets_bokeh either.

But the source js line is here I believe https://github.com/bokeh/ipywidgets_bokeh/blob/379308211dd81e67eeb792dab2c58d5e98598cc2/ipywidgets_bokeh/src/widget.ts#L73

MarcSkovMadsen commented 2 years ago

I've changed https://github.com/bokeh/ipywidgets_bokeh/blob/379308211dd81e67eeb792dab2c58d5e98598cc2/ipywidgets_bokeh/kernel.py#L44

to

class SessionWebsocket(session.Session):

    def send(self, stream, msg_type, content=None, parent=None, ident=None, buffers=None, track=False, header=None, metadata=None):
        print("\n---------SEND--------------")
        print("stream", stream)
        print("msg_type", msg_type)
        print("content", content)
        print("parent", parent)
        print("header", header)
        print("metadata", metadata)
        msg = self.msg(msg_type, content=content, parent=parent, header=header, metadata=metadata)
        msg['channel'] = stream.channel

        doc = self.document

        # Ensure document message handler is only added once
        try:
            doc.remove_on_message("ipywidgets_bokeh", self.receive)
        except Exception:
            pass
        finally:
            doc.on_message("ipywidgets_bokeh", self.receive)

        packed = self.pack(msg)

        data: Union[bytes, str]
        if buffers is not None and len(buffers) != 0:
            buffers = [packed] + buffers
            nbufs = len(buffers)

            start = 4*(1 + nbufs)
            offsets = [start]

            for buffer in buffers[:-1]:
                start += len(buffer)
                offsets.append(start)

            u32 = lambda n: n.to_bytes(4, "big")
            items = [u32(nbufs)] + [ u32(offset) for offset in offsets ] + buffers
            data = b"".join(items)
        else:
            data = packed.decode("utf-8")
        print("data", data)
        event = MessageSentEvent(doc, "ipywidgets_bokeh", data)
        self._trigger_change(event)

and it then shows

$ panel serve 'tests\script.py' --auto --show

---------SEND--------------
stream <ipywidgets_bokeh.kernel.WebsocketStream object at 0x0000025C9909FF40>
msg_type comm_open
content {'data': {'state': {'_model_module': '@jupyter-widgets/base', '_model_module_version': '1.2.0', '_model_name': 'LayoutModel', '_view_count': None, '_view_module': '@jupyter-widgets/base', '_view_module_version': '1.2.0', '_view_name': 'LayoutView', 'align_content': None, 'align_items': None, 'align_self': None, 'border': None, 'bottom': None, 'display': None, 'flex': None, 'flex_flow': None, 'grid_area': None, 'grid_auto_columns': None, 'grid_auto_flow': None, 'grid_auto_rows': None, 'grid_column': None, 'grid_gap': None, 'grid_row': None, 'grid_template_areas': None, 'grid_template_columns': None, 'grid_template_rows': None, 'height': None, 'justify_content': None, 'justify_items': None, 'left': None, 'margin': None, 'max_height': None, 'max_width': None, 'min_height': None, 'min_width': None, 'object_fit': None, 'object_position': None, 'order': None, 'overflow': None, 'overflow_x': None, 'overflow_y': None, 'padding': None, 'right': None, 'top': None, 'visibility': None, 'width': None}, 'buffer_paths': []}, 'comm_id': 
'1f5969f0fc1a48119290d0dc83806716', 'target_name': 'jupyter.widget', 'target_module': None}
parent {}
header None
metadata {'version': '2.0.0'}
data {"header": {"msg_id": "27462c87-846cc21583fe92c2c8421932_13704_0", "msg_type": "comm_open", "username": "username", "session": "27462c87-846cc21583fe92c2c8421932", "date": "2021-12-20T10:21:42.028109Z", "version": "5.3"}, "msg_id": "27462c87-846cc21583fe92c2c8421932_13704_0", "msg_type": "comm_open", "parent_header": {}, "content": {"data": {"state": {"_model_module": "@jupyter-widgets/base", "_model_module_version": "1.2.0", "_model_name": "LayoutModel", "_view_count": null, "_view_module": "@jupyter-widgets/base", "_view_module_version": "1.2.0", "_view_name": "LayoutView", "align_content": null, "align_items": null, "align_self": null, "border": null, "bottom": null, "display": null, "flex": null, "flex_flow": null, "grid_area": null, "grid_auto_columns": null, "grid_auto_flow": null, "grid_auto_rows": null, "grid_column": null, "grid_gap": null, "grid_row": null, "grid_template_areas": null, "grid_template_columns": null, "grid_template_rows": null, "height": null, "justify_content": null, "justify_items": null, "left": 
null, "margin": null, "max_height": null, "max_width": null, "min_height": null, "min_width": null, "object_fit": null, "object_position": null, "order": null, "overflow": null, "overflow_x": null, "overflow_y": null, "padding": null, "right": null, "top": null, "visibility": null, "width": null}, "buffer_paths": []}, "comm_id": "1f5969f0fc1a48119290d0dc83806716", "target_name": "jupyter.widget", "target_module": null}, "metadata": {"version": "2.0.0"}, "channel": "iopub"}

---------SEND--------------
stream <ipywidgets_bokeh.kernel.WebsocketStream object at 0x0000025C9909FF40>
msg_type comm_open
content {'data': {'state': {'_dom_classes': (), '_model_module': 'ipycanvas', '_model_module_version': '^0.10.2', '_model_name': 'CanvasModel', '_send_client_ready_event': True, '_view_count': None, '_view_module': 'ipycanvas', '_view_module_version': '^0.10.2', '_view_name': 'CanvasView', 'height': 200, 'image_data': None, 'layout': 'IPY_MODEL_1f5969f0fc1a48119290d0dc83806716', 'sync_image_data': False, 'width': 200}, 'buffer_paths': []}, 'comm_id': '6a92a12f2c574fd7a8fd485dc5bb7441', 'target_name': 'jupyter.widget', 'target_module': None}
parent {}
header None
metadata {'version': '2.0.0'}
data {"header": {"msg_id": "27462c87-846cc21583fe92c2c8421932_13704_1", "msg_type": "comm_open", "username": "username", "session": "27462c87-846cc21583fe92c2c8421932", "date": "2021-12-20T10:21:42.036153Z", "version": "5.3"}, "msg_id": "27462c87-846cc21583fe92c2c8421932_13704_1", "msg_type": "comm_open", "parent_header": {}, "content": {"data": {"state": {"_dom_classes": [], "_model_module": "ipycanvas", "_model_module_version": "^0.10.2", "_model_name": "CanvasModel", "_send_client_ready_event": true, "_view_count": null, "_view_module": "ipycanvas", "_view_module_version": "^0.10.2", "_view_name": "CanvasView", "height": 200, "image_data": null, "layout": "IPY_MODEL_1f5969f0fc1a48119290d0dc83806716", "sync_image_data": false, "width": 200}, "buffer_paths": []}, "comm_id": "6a92a12f2c574fd7a8fd485dc5bb7441", "target_name": "jupyter.widget", "target_module": null}, "metadata": {"version": "2.0.0"}, "channel": "iopub"}

---------SEND--------------
stream <ipywidgets_bokeh.kernel.WebsocketStream object at 0x0000025C9909FF40>
msg_type comm_msg
content {'data': {'method': 'custom', 'content': {'shape': (11,), 'dtype': 'uint8'}}, 'comm_id': '6a92a12f2c574fd7a8fd485dc5bb7441'}
parent {}
header None
metadata {}
data b'\x00\x00\x00\x02\x00\x00\x00\x0c\x00\x00\x01\xf8{"header": {"msg_id": "27462c87-846cc21583fe92c2c8421932_13704_2", "msg_type": "comm_msg", "username": "username", "session": "27462c87-846cc21583fe92c2c8421932", "date": "2021-12-20T10:21:42.042142Z", "version": "5.3"}, "msg_id": "27462c87-846cc21583fe92c2c8421932_13704_2", "msg_type": "comm_msg", "parent_header": {}, "content": {"data": {"method": "custom", "content": {"shape": [11], "dtype": "uint8"}}, "comm_id": "6a92a12f2c574fd7a8fd485dc5bb7441"}, "metadata": {}, "channel": "iopub"}[14, [], 0]'

---------SEND--------------
stream <ipywidgets_bokeh.kernel.WebsocketStream object at 0x0000025C9909FF40>
msg_type comm_msg
content {'data': {'method': 'custom', 'content': {'shape': (17,), 'dtype': 'uint8'}}, 'comm_id': '6a92a12f2c574fd7a8fd485dc5bb7441'}
parent {}
header None
metadata {}
data b'\x00\x00\x00\x02\x00\x00\x00\x0c\x00\x00\x01\xf8{"header": {"msg_id": "27462c87-846cc21583fe92c2c8421932_13704_3", "msg_type": "comm_msg", "username": "username", "session": "27462c87-846cc21583fe92c2c8421932", "date": "2021-12-20T10:21:42.046142Z", "version": "5.3"}, "msg_id": "27462c87-846cc21583fe92c2c8421932_13704_3", "msg_type": "comm_msg", "parent_header": {}, "content": {"data": {"method": "custom", "content": {"shape": [17], "dtype": "uint8"}}, "comm_id": "6a92a12f2c574fd7a8fd485dc5bb7441"}, "metadata": {}, "channel": "iopub"}[19, [75, 40], 0]'

---------SEND--------------
stream <ipywidgets_bokeh.kernel.WebsocketStream object at 0x0000025C9909FF40>
msg_type comm_msg
content {'data': {'method': 'custom', 'content': {'shape': (33,), 'dtype': 'uint8'}}, 'comm_id': '6a92a12f2c574fd7a8fd485dc5bb7441'}
parent {}
header None
metadata {}
data b'\x00\x00\x00\x02\x00\x00\x00\x0c\x00\x00\x01\xf8{"header": {"msg_id": "27462c87-846cc21583fe92c2c8421932_13704_4", "msg_type": "comm_msg", "username": "username", "session": "27462c87-846cc21583fe92c2c8421932", "date": "2021-12-20T10:21:42.050142Z", "version": "5.3"}, "msg_id": "27462c87-846cc21583fe92c2c8421932_13704_4", "msg_type": "comm_msg", "parent_header": {}, "content": {"data": {"method": "custom", "content": {"shape": [33], "dtype": "uint8"}}, "comm_id": "6a92a12f2c574fd7a8fd485dc5bb7441"}, "metadata": {}, "channel": "iopub"}[26, [75, 37, 70, 25, 50, 25], 0]'

---------SEND--------------
stream <ipywidgets_bokeh.kernel.WebsocketStream object at 0x0000025C9909FF40>
msg_type comm_msg
content {'data': {'method': 'custom', 'content': {'shape': (37,), 'dtype': 'uint8'}}, 'comm_id': '6a92a12f2c574fd7a8fd485dc5bb7441'}
parent {}
header None
metadata {}
data b'\x00\x00\x00\x02\x00\x00\x00\x0c\x00\x00\x01\xf8{"header": {"msg_id": "27462c87-846cc21583fe92c2c8421932_13704_5", "msg_type": "comm_msg", "username": "username", "session": "27462c87-846cc21583fe92c2c8421932", "date": "2021-12-20T10:21:42.053143Z", "version": "5.3"}, "msg_id": "27462c87-846cc21583fe92c2c8421932_13704_5", "msg_type": "comm_msg", "parent_header": {}, "content": {"data": {"method": "custom", "content": {"shape": [37], "dtype": "uint8"}}, "comm_id": "6a92a12f2c574fd7a8fd485dc5bb7441"}, "metadata": {}, "channel": "iopub"}[26, [20, 25, 20, 62.5, 20, 62.5], 0]'

---------SEND--------------
stream <ipywidgets_bokeh.kernel.WebsocketStream object at 0x0000025C9909FF40>
msg_type comm_msg
content {'data': {'method': 'custom', 'content': {'shape': (35,), 'dtype': 'uint8'}}, 'comm_id': '6a92a12f2c574fd7a8fd485dc5bb7441'}
parent {}
header None
metadata {}
data b'\x00\x00\x00\x02\x00\x00\x00\x0c\x00\x00\x01\xf8{"header": {"msg_id": "27462c87-846cc21583fe92c2c8421932_13704_6", "msg_type": "comm_msg", "username": "username", "session": "27462c87-846cc21583fe92c2c8421932", "date": "2021-12-20T10:21:42.055143Z", "version": "5.3"}, "msg_id": "27462c87-846cc21583fe92c2c8421932_13704_6", "msg_type": "comm_msg", "parent_header": {}, "content": {"data": {"method": "custom", "content": {"shape": [35], "dtype": "uint8"}}, "comm_id": "6a92a12f2c574fd7a8fd485dc5bb7441"}, "metadata": {}, "channel": "iopub"}[26, [20, 80, 40, 102, 75, 120], 0]'

---------SEND--------------
stream <ipywidgets_bokeh.kernel.WebsocketStream object at 0x0000025C9909FF40>
msg_type comm_msg
content {'data': {'method': 'custom', 'content': {'shape': (39,), 'dtype': 'uint8'}}, 'comm_id': '6a92a12f2c574fd7a8fd485dc5bb7441'}
parent {}
header None
metadata {}
data b'\x00\x00\x00\x02\x00\x00\x00\x0c\x00\x00\x01\xf8{"header": {"msg_id": "27462c87-846cc21583fe92c2c8421932_13704_7", "msg_type": "comm_msg", "username": "username", "session": "27462c87-846cc21583fe92c2c8421932", "date": "2021-12-20T10:21:42.060144Z", "version": "5.3"}, "msg_id": "27462c87-846cc21583fe92c2c8421932_13704_7", "msg_type": "comm_msg", "parent_header": {}, "content": {"data": {"method": "custom", "content": {"shape": [39], "dtype": "uint8"}}, "comm_id": "6a92a12f2c574fd7a8fd485dc5bb7441"}, "metadata": {}, "channel": "iopub"}[26, [110, 102, 130, 80, 130, 62.5], 0]'

---------SEND--------------
stream <ipywidgets_bokeh.kernel.WebsocketStream object at 0x0000025C9909FF40>
msg_type comm_msg
content {'data': {'method': 'custom', 'content': {'shape': (38,), 'dtype': 'uint8'}}, 'comm_id': '6a92a12f2c574fd7a8fd485dc5bb7441'}
parent {}
header None
metadata {}
data b'\x00\x00\x00\x02\x00\x00\x00\x0c\x00\x00\x01\xf8{"header": {"msg_id": "27462c87-846cc21583fe92c2c8421932_13704_8", "msg_type": "comm_msg", "username": "username", "session": "27462c87-846cc21583fe92c2c8421932", "date": "2021-12-20T10:21:42.064145Z", "version": "5.3"}, "msg_id": "27462c87-846cc21583fe92c2c8421932_13704_8", "msg_type": "comm_msg", "parent_header": {}, "content": {"data": {"method": "custom", "content": {"shape": [38], "dtype": "uint8"}}, "comm_id": "6a92a12f2c574fd7a8fd485dc5bb7441"}, "metadata": {}, "channel": "iopub"}[26, [130, 62.5, 130, 25, 100, 25], 0]'

---------SEND--------------
stream <ipywidgets_bokeh.kernel.WebsocketStream object at 0x0000025C9909FF40>
msg_type comm_msg
content {'data': {'method': 'custom', 'content': {'shape': (33,), 'dtype': 'uint8'}}, 'comm_id': '6a92a12f2c574fd7a8fd485dc5bb7441'}
parent {}
header None
metadata {}
data b'\x00\x00\x00\x02\x00\x00\x00\x0c\x00\x00\x01\xf8{"header": {"msg_id": "27462c87-846cc21583fe92c2c8421932_13704_9", "msg_type": "comm_msg", "username": "username", "session": "27462c87-846cc21583fe92c2c8421932", "date": "2021-12-20T10:21:42.068146Z", "version": "5.3"}, "msg_id": "27462c87-846cc21583fe92c2c8421932_13704_9", "msg_type": "comm_msg", "parent_header": {}, "content": {"data": {"method": "custom", "content": {"shape": [33], "dtype": "uint8"}}, "comm_id": "6a92a12f2c574fd7a8fd485dc5bb7441"}, "metadata": {}, "channel": "iopub"}[26, [85, 25, 75, 37, 75, 40], 0]'

---------SEND--------------
stream <ipywidgets_bokeh.kernel.WebsocketStream object at 0x0000025C9909FF40>
msg_type comm_msg
content {'data': {'method': 'custom', 'content': {'shape': (20,), 'dtype': 'uint8'}}, 'comm_id': '6a92a12f2c574fd7a8fd485dc5bb7441'}
parent {}
header None
metadata {}
data b'\x00\x00\x00\x02\x00\x00\x00\x0c\x00\x00\x01\xfa{"header": {"msg_id": "27462c87-846cc21583fe92c2c8421932_13704_10", "msg_type": "comm_msg", "username": "username", "session": "27462c87-846cc21583fe92c2c8421932", "date": "2021-12-20T10:21:42.073146Z", "version": "5.3"}, "msg_id": "27462c87-846cc21583fe92c2c8421932_13704_10", "msg_type": "comm_msg", "parent_header": {}, "content": {"data": {"method": "custom", "content": {"shape": [20], "dtype": "uint8"}}, "comm_id": "6a92a12f2c574fd7a8fd485dc5bb7441"}, "metadata": {}, "channel": "iopub"}[18, ["nonzero"], 0]'
drawn
2021-12-20 11:21:42,123 Starting Bokeh server version 2.4.2 (running on Tornado 6.1)
2021-12-20 11:21:42,125 User authentication hooks NOT provided (default user enabled)
2021-12-20 11:21:42,127 Bokeh app running at: http://localhost:5006/script
2021-12-20 11:21:42,127 Starting Bokeh server with process id: 13704

---------SEND--------------
stream <ipywidgets_bokeh.kernel.WebsocketStream object at 0x0000025C9909FF40>
msg_type comm_open
content {'data': {'state': {'_model_module': '@jupyter-widgets/base', '_model_module_version': '1.2.0', '_model_name': 'LayoutModel', '_view_count': None, '_view_module': '@jupyter-widgets/base', '_view_module_version': '1.2.0', '_view_name': 'LayoutView', 'align_content': None, 'align_items': None, 'align_self': None, 'border': None, 'bottom': None, 'display': None, 'flex': None, 'flex_flow': None, 'grid_area': None, 'grid_auto_columns': None, 'grid_auto_flow': None, 'grid_auto_rows': None, 'grid_column': None, 'grid_gap': None, 'grid_row': None, 'grid_template_areas': None, 'grid_template_columns': None, 'grid_template_rows': None, 'height': None, 'justify_content': None, 'justify_items': None, 'left': None, 'margin': None, 'max_height': None, 'max_width': None, 'min_height': None, 'min_width': None, 'object_fit': None, 'object_position': None, 'order': None, 'overflow': None, 'overflow_x': None, 'overflow_y': None, 'padding': None, 'right': None, 'top': None, 'visibility': None, 'width': None}, 'buffer_paths': []}, 'comm_id': 
'6cc9f28254ed44b8aa8a49ccff2202e1', 'target_name': 'jupyter.widget', 'target_module': None}
parent {}
header None
metadata {'version': '2.0.0'}
data {"header": {"msg_id": "27462c87-846cc21583fe92c2c8421932_13704_11", "msg_type": "comm_open", "username": "username", "session": "27462c87-846cc21583fe92c2c8421932", "date": "2021-12-20T10:21:42.395050Z", 
"version": "5.3"}, "msg_id": "27462c87-846cc21583fe92c2c8421932_13704_11", "msg_type": "comm_open", "parent_header": {}, "content": {"data": {"state": {"_model_module": "@jupyter-widgets/base", "_model_module_version": "1.2.0", "_model_name": "LayoutModel", "_view_count": null, "_view_module": "@jupyter-widgets/base", "_view_module_version": "1.2.0", "_view_name": "LayoutView", "align_content": null, "align_items": null, "align_self": null, "border": null, "bottom": null, "display": null, "flex": null, "flex_flow": null, "grid_area": null, "grid_auto_columns": null, "grid_auto_flow": null, "grid_auto_rows": null, "grid_column": null, "grid_gap": null, "grid_row": null, "grid_template_areas": null, "grid_template_columns": null, "grid_template_rows": null, "height": null, "justify_content": null, "justify_items": null, "left": null, "margin": null, "max_height": null, "max_width": null, "min_height": null, "min_width": null, "object_fit": null, "object_position": null, "order": null, "overflow": null, "overflow_x": null, "overflow_y": null, "padding": null, "right": null, "top": null, "visibility": null, "width": null}, "buffer_paths": []}, "comm_id": "6cc9f28254ed44b8aa8a49ccff2202e1", "target_name": "jupyter.widget", "target_module": null}, "metadata": {"version": "2.0.0"}, "channel": "iopub"}

---------SEND--------------
stream <ipywidgets_bokeh.kernel.WebsocketStream object at 0x0000025C9909FF40>
msg_type comm_open
content {'data': {'state': {'_dom_classes': (), '_model_module': 'ipycanvas', '_model_module_version': '^0.10.2', '_model_name': 'CanvasModel', '_send_client_ready_event': True, '_view_count': None, '_view_module': 'ipycanvas', '_view_module_version': '^0.10.2', '_view_name': 'CanvasView', 'height': 200, 'image_data': None, 'layout': 'IPY_MODEL_6cc9f28254ed44b8aa8a49ccff2202e1', 'sync_image_data': False, 'width': 200}, 'buffer_paths': []}, 'comm_id': '4e7e038267584664b625c77f3b861e9d', 'target_name': 'jupyter.widget', 'target_module': None}
parent {}
header None
metadata {'version': '2.0.0'}
data {"header": {"msg_id": "27462c87-846cc21583fe92c2c8421932_13704_12", "msg_type": "comm_open", "username": "username", "session": "27462c87-846cc21583fe92c2c8421932", "date": "2021-12-20T10:21:42.399046Z", 
"version": "5.3"}, "msg_id": "27462c87-846cc21583fe92c2c8421932_13704_12", "msg_type": "comm_open", "parent_header": {}, "content": {"data": {"state": {"_dom_classes": [], "_model_module": "ipycanvas", "_model_module_version": "^0.10.2", "_model_name": "CanvasModel", "_send_client_ready_event": true, "_view_count": null, "_view_module": "ipycanvas", "_view_module_version": "^0.10.2", "_view_name": "CanvasView", "height": 200, "image_data": null, "layout": "IPY_MODEL_6cc9f28254ed44b8aa8a49ccff2202e1", "sync_image_data": false, "width": 200}, "buffer_paths": []}, "comm_id": "4e7e038267584664b625c77f3b861e9d", "target_name": "jupyter.widget", "target_module": null}, "metadata": {"version": "2.0.0"}, "channel": "iopub"}
2021-12-20 11:21:42,651 WebSocket connection opened
2021-12-20 11:21:42,652 ServerConnection created

---------SEND--------------
stream <ipywidgets_bokeh.kernel.WebsocketStream object at 0x0000025C9909FF40>
msg_type status
content {'execution_state': 'busy'}
parent {'header': {'date': datetime.datetime(2021, 12, 20, 10, 21, 42, 730000, tzinfo=tzutc()), 'msg_id': '844de131-2be6-4111-9602-dc851ae47494', 'msg_type': 'comm_msg', 'session': '2ab7dfd6-30ac-43e4-8102-ddbb2fb76c82', 'username': '', 'version': '5.2'}, 'msg_id': '844de131-2be6-4111-9602-dc851ae47494', 'msg_type': 'comm_msg', 'parent_header': {}, 'metadata': {}, 'content': {'comm_id': '4e7e038267584664b625c77f3b861e9d', 'data': {'method': 'custom', 'content': {'event': 'client_ready'}}}, 'buffers': []}
header None
metadata None
data {"header": {"msg_id": "27462c87-846cc21583fe92c2c8421932_13704_13", "msg_type": "status", "username": "username", "session": "27462c87-846cc21583fe92c2c8421932", "date": "2021-12-20T10:21:42.735580Z", "version": "5.3"}, "msg_id": "27462c87-846cc21583fe92c2c8421932_13704_13", "msg_type": "status", "parent_header": {"date": "2021-12-20T10:21:42.730000Z", "msg_id": "844de131-2be6-4111-9602-dc851ae47494", "msg_type": "comm_msg", "session": "2ab7dfd6-30ac-43e4-8102-ddbb2fb76c82", "username": "", "version": "5.2"}, "content": {"execution_state": "busy"}, "metadata": {}, "channel": "iopub"}

---------SEND--------------
stream <ipywidgets_bokeh.kernel.WebsocketStream object at 0x0000025C9909FF40>
msg_type status
content {'execution_state': 'idle'}
parent {'header': {'date': datetime.datetime(2021, 12, 20, 10, 21, 42, 730000, tzinfo=tzutc()), 'msg_id': '844de131-2be6-4111-9602-dc851ae47494', 'msg_type': 'comm_msg', 'session': '2ab7dfd6-30ac-43e4-8102-ddbb2fb76c82', 'username': '', 'version': '5.2'}, 'msg_id': '844de131-2be6-4111-9602-dc851ae47494', 'msg_type': 'comm_msg', 'parent_header': {}, 'metadata': {}, 'content': {'comm_id': '4e7e038267584664b625c77f3b861e9d', 'data': {'method': 'custom', 'content': {'event': 'client_ready'}}}, 'buffers': []}
header None
metadata None
data {"header": {"msg_id": "27462c87-846cc21583fe92c2c8421932_13704_14", "msg_type": "status", "username": "username", "session": "27462c87-846cc21583fe92c2c8421932", "date": "2021-12-20T10:21:42.738727Z", "version": "5.3"}, "msg_id": "27462c87-846cc21583fe92c2c8421932_13704_14", "msg_type": "status", "parent_header": {"date": "2021-12-20T10:21:42.730000Z", "msg_id": "844de131-2be6-4111-9602-dc851ae47494", "msg_type": "comm_msg", "session": "2ab7dfd6-30ac-43e4-8102-ddbb2fb76c82", "username": "", "version": "5.2"}, "content": {"execution_state": "idle"}, "metadata": {}, "channel": "iopub"}
MarcSkovMadsen commented 2 years ago

Refactoring my example to

# pip install ipycanvas panel ipywidgets_bokeh
import panel as pn
from ipycanvas import Canvas

pn.extension('ipywidgets')

canvas = Canvas(width=200, height=200)

# Cubic curves example
button = pn.widgets.Button(name="run")
@pn.depends(button.param.clicks, watch=True)
def draw(clicks):
    print("draw begin")
    canvas.begin_path()
    canvas.move_to(75, 40)
    canvas.bezier_curve_to(75, 37, 70, 25, 50, 25)
    canvas.fill()
    print("draw end")

pn.Column(
    button,
    pn.panel(canvas, height=200, width=200)
).servable()

I can see that the message is not send from that function as it does not print anything if I run the draw function. But the error on client side appears.

https://user-images.githubusercontent.com/42288570/146754367-77e84009-9dff-4954-b2bc-a16b3adee67e.mp4