Skip to content

[BUG] DeserializationError when trying to change a DataTable's columns with CustomJS #11422

@charlesbluca

Description

@charlesbluca

ALL software version info (bokeh, python, notebook, OS, browser, any other relevant packages)

  • Bokeh 2.3.2
  • Python 3.8.10

Description of expected behavior and the observed behavior

I am trying to use a CheckboxButtonGroup widget to toggle the visibility of columns in a DataTable. My approach to this is to use some CustomJS that adds or removes columns from the table in question upon clicking the button. This works fine, and the table responds as expected. However, I get serialization errors in console every time I click the button.

For context, this issue came up while working on dask/distributed#4614.

Complete, minimal, self-contained example code that reproduces the issue

# example.py

from datetime import date
from random import randint

from bokeh.io import show
from bokeh.layouts import column
from bokeh.models import (
        ColumnDataSource,
        DataTable,
        DateFormatter,
        TableColumn,
        CheckboxButtonGroup,
        CustomJS
    )
from bokeh.plotting import curdoc

data = dict(
        dates=[date(2014, 3, i+1) for i in range(10)],
        downloads=[randint(0, 100) for i in range(10)],
    )
source = ColumnDataSource(data)

columns = [
        TableColumn(field="dates", title="Date", formatter=DateFormatter()),
        TableColumn(field="downloads", title="Downloads"),
    ]
data_table = DataTable(source=source, columns=columns, width=400, height=280)

column_choice = CheckboxButtonGroup(
    labels=[
        "Date",
        "Downloads"
    ],
    active=[0, 1],
)
column_choice.js_on_click(
    CustomJS(
        args=dict(
            table=data_table, columns=columns
        ),
        code="""
            var visible_columns = []
            for (var i = 0; i < this.active.length; i++) {
                visible_columns.push(columns[this.active[i]])
            }
            table.columns = visible_columns;
        """,
    )
)

curdoc().add_root(column(column_choice, data_table))
$ bokeh serve --show example.py

Stack traceback and/or browser JavaScript console output

On button click:

bokeh.server.protocol_handler - ERROR - error handling message
 message: Message 'PATCH-DOC' content: {'events': [{'kind': 'ModelChanged', 'model': {'id': '1371'}, 'attr': 'columns', 'new': [{'id': '1345'}, {'id': '1346'}, {'id': '1347'}, {'id': '1348'}, {'id': '1349'}, {'id': '1350'}, {'id': '1351'}, {'id': '1352'}]}], 'references': []} 
 error: DeserializationError("Instance(TableColumn) failed to deserialize reference to {'id': '1345'}")
Traceback (most recent call last):
  File "/home/charlesbluca/miniconda3/envs/dask-distributed/lib/python3.8/site-packages/bokeh/server/protocol_handler.py", line 90, in handle
    work = await handler(message, connection)
  File "/home/charlesbluca/miniconda3/envs/dask-distributed/lib/python3.8/site-packages/bokeh/server/session.py", line 67, in _needs_document_lock_wrapper
    result = func(self, *args, **kwargs)
  File "/home/charlesbluca/miniconda3/envs/dask-distributed/lib/python3.8/site-packages/bokeh/server/session.py", line 261, in _handle_patch
    message.apply_to_document(self.document, self)
  File "/home/charlesbluca/miniconda3/envs/dask-distributed/lib/python3.8/site-packages/bokeh/protocol/messages/patch_doc.py", line 100, in apply_to_document
    doc._with_self_as_curdoc(lambda: doc.apply_json_patch(self.content, setter))
  File "/home/charlesbluca/miniconda3/envs/dask-distributed/lib/python3.8/site-packages/bokeh/document/document.py", line 1198, in _with_self_as_curdoc
    return f()
  File "/home/charlesbluca/miniconda3/envs/dask-distributed/lib/python3.8/site-packages/bokeh/protocol/messages/patch_doc.py", line 100, in <lambda>
    doc._with_self_as_curdoc(lambda: doc.apply_json_patch(self.content, setter))
  File "/home/charlesbluca/miniconda3/envs/dask-distributed/lib/python3.8/site-packages/bokeh/document/document.py", line 411, in apply_json_patch
    patched_obj.set_from_json(attr, value, models=references, setter=setter)
  File "/home/charlesbluca/miniconda3/envs/dask-distributed/lib/python3.8/site-packages/bokeh/core/has_props.py", line 412, in set_from_json
    descriptor.set_from_json(self, json, models, setter)
  File "/home/charlesbluca/miniconda3/envs/dask-distributed/lib/python3.8/site-packages/bokeh/core/property/descriptors.py", line 623, in set_from_json
    return super().set_from_json(obj, self.property.from_json(json, models), models, setter)
  File "/home/charlesbluca/miniconda3/envs/dask-distributed/lib/python3.8/site-packages/bokeh/core/property/container.py", line 70, in from_json
    return self._new_instance([ self.item_type.from_json(item, models) for item in json ])
  File "/home/charlesbluca/miniconda3/envs/dask-distributed/lib/python3.8/site-packages/bokeh/core/property/container.py", line 70, in <listcomp>
    return self._new_instance([ self.item_type.from_json(item, models) for item in json ])
  File "/home/charlesbluca/miniconda3/envs/dask-distributed/lib/python3.8/site-packages/bokeh/core/property/instance.py", line 93, in from_json
    raise DeserializationError(f"{self} failed to deserialize reference to {json}")
bokeh.core.property.bases.DeserializationError: Instance(TableColumn) failed to deserialize reference to {'id': '1345'}

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions