Bokeh Server.If the number of legends is more than 25, I get AttributeError: Trying to access 'items' attribute on an empty 'splattable' list

I have my_app.py. If the number of legends is more than 25, I get  AttributeError: Trying to access 'items' attribute on an empty 'splattable' list.

Is there any way to fix the error? I need to display more than 50 legends.

import numpy as np
import holoviews as hv
from bokeh.io import curdoc
from bokeh.layouts import layout
from bokeh.models import HoverTool

hv.extension('bokeh')
renderer = hv.renderer('bokeh').instance(mode='server')
frequencies = [0.1*i for i in range(1,26)] #set numbers of legends. Change 26 to 27 for get error

def sine_curve(phase, freq):
    xvals = [0.1* i for i in range(100)]
    return hv.Curve((xvals, [np.sin(phase+freq*x) for x in xvals]))

def callback1(label):
    print(f'Curve {label} is turn off')
    
def callback2(label):
    print(f'Curve {label} is turn on')
    

curve_dict = {f:sine_curve(0,f) for f in frequencies}

def find_and_attach_to_legend(legend, label):
    for i in legend.items:#if the number of legends is more than 25, I get  AttributeError: Trying to access 'items' attribute on an empty 'splattable' list
        if i.label['value'] == label:
            if legend.click_policy == 'hide':
                attr = 'visible'
                invert = False
            elif legend.click_policy == 'mute':
                attr = 'muted'
                invert = True
            else:
                raise RuntimeError('Unhandled click_policy value', legend.click_policy)

            def on_visible_change(attr, old, new):
                if invert:
                    new = not new
                if new:
                    callback2(label)
                else:
                    callback1(label)

            i.renderers[0].on_change(attr, on_visible_change)
            break

ndoverlay = hv.NdOverlay(curve_dict, kdims='frequency')
doc=curdoc()
hvplot = renderer.get_plot(ndoverlay, doc)
plot=hvplot.state
plot.height=600
plot.width=600
plot.legend.label_width=100
plot.legend.glyph_width=25
for freq in frequencies:
    find_and_attach_to_legend(plot.legend, str(freq))
doc.add_root(plot)

Please provide more of the stack trace.

You hit this issue: NdOverlay legend fails · Issue #3647 · holoviz/holoviews · GitHub

As a workaround, just use renderer.get_plot(ndoverlay, doc, legend_limit=100) or something like that.

3 Likes

Thanks for tracking down @p-himik I was scratching my head trying to think of any issue this could be in Bokeh proper.

File “c:\users\pc\appdata\local\programs\python\python37-32\test_boken\barchart\lib\site-packages\bokeh\application\handlers\code_runner.py”, line 179, in run
exec(self._code, module.dict)
File “C:\Users\pc\AppData\Local\Programs\Python\Python37-32\test_boken\barchart\my_app_1.py”, line 58, in
find_and_attach_to_legend(plot.legend, str(freq))
File “C:\Users\pc\AppData\Local\Programs\Python\Python37-32\test_boken\barchart\my_app_1.py”, line 26, in find_and_attach_to_legend
for i in legend.items:
File “c:\users\pc\appdata\local\programs\python\python37-32\test_boken\barchart\lib\site-packages\bokeh\models\plots.py”, line 744, in getattribute
raise AttributeError(“Trying to access %r attribute on an empty ‘splattable’ list” % attr)
AttributeError: Trying to access ‘items’ attribute on an empty ‘splattable’ list

Thank you very mutch.It works.