Panel+Altair on Pyscript

Hello! I’m trying to build a simple panel dashboard where you upload an XML file, parse it, and display an altair plot in a Vega pane. There’s some sensitive data so I can’t show full example, but here’s the gist.

    <script src="https://cdn.jsdelivr.net/npm/vega@5.24.0"></script>
    <script src="https://cdn.jsdelivr.net/npm/vega-lite@5.7.0"></script>
    <script src="https://cdn.jsdelivr.net/npm/vega-embed@6.21.3"></script>
    <script type="text/javascript" src="https://cdn.bokeh.org/bokeh/release/bokeh-2.4.3.js"></script>
    <script type="text/javascript" src="https://cdn.bokeh.org/bokeh/release/bokeh-widgets-2.4.3.min.js"></script>
    <script type="text/javascript" src="https://cdn.bokeh.org/bokeh/release/bokeh-tables-2.4.3.min.js"></script>
    <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/@holoviz/panel@0.14.0/dist/panel.min.js"></script>

            <div class="col mh-50 float-left" id="main" style="border: 1px solid blue">
                <div id="fileinput"></div>
                <div id="output_text" style="background-color: #789"></div>
                <div id="chart"></div>
            </div>

file_input = pn.widgets.FileInput(accept='.xml', width=280)
upload_button = pn.widgets.Button(name='Upload', button_type='primary', width=100)
row = pn.Row(file_input, upload_button, height=80)

chart = pn.panel(vegalite)  # a placeholder graph; previous versions allowed empty pn.Pane.Vega() but not 0.14 (could be wrong)

def process_file(event):
    if file_input.value is not None:
        document.getElementById('output_text').innerHTML = f"<p>{len(file_input.value):,} bytes</p>"
        # parsing and generating `channel_results pandas DF`
        plot = plot_channel_results(channel_results)  # generates Altair plot
        chart.object = plot

upload_button.on_click(process_file)
asyncio.ensure_future(write('fileinput', row))
asyncio.ensure_future(write('chart', chart))

Most of it is working (using 2022.09.1 pyscript). The file is read, the output_text gets populated, and I’m producing a plot and a valid Vega JSON, but the graph won’t get displayed. This console message below shows up. BUT, when I use <py-repl> and ask for chart.object, the altair graph shows up fine.

I don’t know if I’m using the async stuff correctly, or whether something else is going on.

Uncaught PythonError: Traceback (most recent call last):
  File "/lib/python3.10/site-packages/panel/io/pyodide.py", line 183, in jssync
    pydoc.apply_json_patch(json.loads(json_patch), setter='js')
  File "/lib/python3.10/site-packages/bokeh/document/document.py", line 391, in apply_json_patch
    DocumentPatchedEvent.handle_json(self, event_json, references, setter)
  File "/lib/python3.10/site-packages/bokeh/document/events.py", line 259, in handle_json
    handler(doc, event_json, references, setter)
  File "/lib/python3.10/site-packages/bokeh/document/events.py", line 300, in _handle_json
    cb(event_json["msg_data"])
  File "/lib/python3.10/site-packages/bokeh/document/callbacks.py", line 355, in trigger_json_event
    model._trigger_event(event)
  File "/lib/python3.10/site-packages/bokeh/util/callback_manager.py", line 119, in _trigger_event
    self.document.callbacks.notify_event(cast(Model, self), event, invoke)
  File "/lib/python3.10/site-packages/bokeh/document/callbacks.py", line 247, in notify_event
    invoke_with_curdoc(doc, callback_invoker)
  File "/lib/python3.10/site-packages/bokeh/document/callbacks.py", line 408, in invoke_with_curdoc
    return f()
  File "/lib/python3.10/site-packages/bokeh/util/callback_manager.py", line 115, in invoke
    cast(EventCallbackWithEvent, callback)(event)
  File "/lib/python3.10/site-packages/panel/reactive.py", line 426, in _server_event
    self._comm_event(doc, event)
  File "/lib/python3.10/site-packages/panel/reactive.py", line 413, in _comm_event
    state._handle_exception(e)
  File "/lib/python3.10/site-packages/panel/io/state.py", line 408, in _handle_exception
    raise exception
  File "/lib/python3.10/site-packages/panel/reactive.py", line 411, in _comm_event
    self._process_bokeh_event(doc, event)
  File "/lib/python3.10/site-packages/panel/reactive.py", line 348, in _process_bokeh_event
    self._process_event(event)
  File "/lib/python3.10/site-packages/panel/widgets/button.py", line 184, in _process_event
    self.clicks += 1
  File "/lib/python3.10/site-packages/param/parameterized.py", line 367, in _f
    instance_param.__set__(obj, val)
  File "/lib/python3.10/site-packages/param/parameterized.py", line 369, in _f
    return f(self, obj, val)
  File "/lib/python3.10/site-packages/param/__init__.py", line 625, in __set__
    super(Dynamic,self).__set__(obj,val)
  File "/lib/python3.10/site-packages/param/parameterized.py", line 369, in _f
    return f(self, obj, val)
  File "/lib/python3.10/site-packages/param/parameterized.py", line 1252, in __set__
    obj.param._call_watcher(watcher, event)
  File "/lib/python3.10/site-packages/param/parameterized.py", line 2043, in _call_watcher
    self_._execute_watcher(watcher, (event,))
  File "/lib/python3.10/site-packages/param/parameterized.py", line 2025, in _execute_watcher
    watcher.fn(*args, **kwargs)
  File "<exec>", line 235, in process_file
  File "/lib/python3.10/site-packages/param/parameterized.py", line 369, in _f
    return f(self, obj, val)
  File "/lib/python3.10/site-packages/param/parameterized.py", line 1252, in __set__
    obj.param._call_watcher(watcher, event)
  File "/lib/python3.10/site-packages/param/parameterized.py", line 2043, in _call_watcher
    self_._execute_watcher(watcher, (event,))
  File "/lib/python3.10/site-packages/param/parameterized.py", line 2025, in _execute_watcher
    watcher.fn(*args, **kwargs)
  File "/lib/python3.10/site-packages/panel/pane/base.py", line 255, in _update_pane
    cb()
  File "/lib/python3.10/site-packages/panel/pane/base.py", line 194, in _update_object
    self._update(ref, old_model)
  File "/lib/python3.10/site-packages/panel/pane/vega.py", line 312, in _update
    model.update(**props)
  File "/lib/python3.10/site-packages/bokeh/core/has_props.py", line 413, in update
    setattr(self, k, v)
  File "/lib/python3.10/site-packages/bokeh/core/has_props.py", line 230, in __setattr__
    return super().__setattr__(name, value)
  File "/lib/python3.10/site-packages/bokeh/core/property/descriptors.py", line 285, in __set__
    self._set(obj, old, value, setter=setter)
  File "/lib/python3.10/site-packages/bokeh/core/property/descriptors.py", line 559, in _set
    self._trigger(obj, old, value, hint=hint, setter=setter)
  File "/lib/python3.10/site-packages/bokeh/core/property/descriptors.py", line 637, in _trigger
    obj.trigger(self.name, old, value, hint, setter)
  File "/lib/python3.10/site-packages/bokeh/model/model.py", line 567, in trigger
    super().trigger(descriptor.name, old, new, hint=hint, setter=setter)
  File "/lib/python3.10/site-packages/bokeh/util/callback_manager.py", line 194, in trigger
    self.document.callbacks.notify_change(cast(Model, self), attr, old, new, hint, setter, invoke)
  File "/lib/python3.10/site-packages/bokeh/document/callbacks.py", line 236, in notify_change
    self.trigger_on_change(event)
  File "/lib/python3.10/site-packages/bokeh/document/callbacks.py", line 378, in trigger_on_change
    invoke_with_curdoc(doc, invoke_callbacks)
  File "/lib/python3.10/site-packages/bokeh/document/callbacks.py", line 408, in invoke_with_curdoc
    return f()
  File "/lib/python3.10/site-packages/bokeh/document/callbacks.py", line 377, in invoke_callbacks
    cb(event)
  File "/lib/python3.10/site-packages/panel/io/pyodide.py", line 195, in pysync
    jsdoc.apply_json_patch(JSON.parse(json_patch), pyodide.ffi.to_js(buffer_map), setter_id='python')
  File "https://cdn.bokeh.org/bokeh/release/bokeh-2.4.3.js", line 1258, in apply_json_patch
  File "https://cdn.bokeh.org/bokeh/release/bokeh-2.4.3.js", line 2578, in setv
  File "https://cdn.bokeh.org/bokeh/release/bokeh-2.4.3.js", line 2545, in _setv
  File "https://cdn.bokeh.org/bokeh/release/bokeh-2.4.3.js", line 2806, in emit
  File "https://cdn.bokeh.org/bokeh/release/bokeh-2.4.3.js", line 2797, in emit
  File "https://cdn.bokeh.org/bokeh/release/bokeh-2.4.3.js", line 6317, in new_slot
  File "https://cdn.jsdelivr.net/npm/@holoviz/panel@0.14.0/dist/panel.min.js", line 182, in _/connect_signals/<
  File "https://cdn.jsdelivr.net/npm/vega@5.24.0", line 1, in addSignalListener
  File "https://cdn.jsdelivr.net/npm/vega@5.24.0", line 1, in BN
  File "https://cdn.jsdelivr.net/npm/vega@5.24.0", line 1, in u
pyodide.JsException: Error: Unrecognized signal name: "selector001"
    PythonError https://cdn.jsdelivr.net/pyodide/v0.21.2/full/pyodide.asm.js:10
    new_error https://cdn.jsdelivr.net/pyodide/v0.21.2/full/pyodide.asm.js:10
    _pythonexc2js https://cdn.jsdelivr.net/pyodide/v0.21.2/full/pyodide.asm.js:10
    callPyObjectKwargs https://cdn.jsdelivr.net/pyodide/v0.21.2/full/pyodide.asm.js:10
    callPyObject https://cdn.jsdelivr.net/pyodide/v0.21.2/full/pyodide.asm.js:10
    apply https://cdn.jsdelivr.net/pyodide/v0.21.2/full/pyodide.asm.js:10
    apply https://cdn.jsdelivr.net/pyodide/v0.21.2/full/pyodide.asm.js:10
    _trigger_on_change https://cdn.bokeh.org/bokeh/release/bokeh-2.4.3.js:887
    send_event https://cdn.bokeh.org/bokeh/release/bokeh-2.4.3.js:648
    _process_event https://cdn.bokeh.org/bokeh/release/bokeh-2.4.3.js:7893
    trigger https://cdn.bokeh.org/bokeh/release/bokeh-2.4.3.js:654
    trigger_event https://cdn.bokeh.org/bokeh/release/bokeh-2.4.3.js:7898
    click https://cdn.bokeh.org/bokeh/release/bokeh-widgets-2.4.3.min.js:55
    render https://cdn.bokeh.org/bokeh/release/bokeh-widgets-2.4.3.min.js:46
    render https://cdn.bokeh.org/bokeh/release/bokeh-widgets-2.4.3.min.js:46
    render https://cdn.bokeh.org/bokeh/release/bokeh-2.4.3.js:35290
    build https://cdn.bokeh.org/bokeh/release/bokeh-2.4.3.js:35323
    renderTo https://cdn.bokeh.org/bokeh/release/bokeh-2.4.3.js:35317
    render_model https://cdn.bokeh.org/bokeh/release/bokeh-2.4.3.js:43805
    add_document_standalone https://cdn.bokeh.org/bokeh/release/bokeh-2.4.3.js:43819
    _embed_items https://cdn.bokeh.org/bokeh/release/bokeh-2.4.3.js:591
    embed_item https://cdn.bokeh.org/bokeh/release/bokeh-2.4.3.js:566
    hiwire_call_bound https://cdn.jsdelivr.net/pyodide/v0.21.2/full/pyodide.asm.js:10
    method_call_trampoline https://cdn.jsdelivr.net/pyodide/v0.21.2/full/pyodide.asm.js:10
[py](https://cdn.jsdelivr.net/pyodide/v0.21.2/full/pyodide.asm.js)