diff --git a/lumen/target.py b/lumen/target.py index 701e6c3c..5d7480a8 100644 --- a/lumen/target.py +++ b/lumen/target.py @@ -51,11 +51,18 @@ def __panel__(self): def _construct_layout(self): layout = self.layout if isinstance(layout, list): + view_size = len(self.views) item = pn.Column(sizing_mode='stretch_both') for row_spec in layout: row = pn.Row(sizing_mode='stretch_width') for index in row_spec: if isinstance(index, int): + if index >= view_size: + raise ValueError( + f"Layout specification for '{self.title}' target references " + f"out-of-bounds index ({index}) even though the maximum " + f"available index is {view_size - 1}." + ) view = self.views[index] else: matches = [view for view in self.views if view.name == index] diff --git a/lumen/tests/test_target.py b/lumen/tests/test_target.py index d248c8c0..24c8d675 100644 --- a/lumen/tests/test_target.py +++ b/lumen/tests/test_target.py @@ -2,6 +2,7 @@ import holoviews as hv import numpy as np +import pytest from bokeh.document import Document from panel.io.server import set_curdoc @@ -182,3 +183,40 @@ def test_transform_controls_facetted(set_root): assert np.array_equal(hv_pane1.object['A'], np.array([4, 2, 0])) assert np.array_equal(hv_pane2.object['A'], np.array([3, 1])) + + +@pytest.mark.parametrize( + "layout,error", + [ + ([[0]], None), + ([[0], [1]], ValueError), + ([[0], [1, 2]], ValueError), + ([{"test": 0}], None), + ([{"test1": 0}], KeyError), + ] +) +def test_layout_view(set_root, layout, error): + set_root(str(Path(__file__).parent)) + source = FileSource(tables={'test': 'sources/test.csv'}) + derived = DerivedSource(source=source, transforms=[Astype(dtypes={'B': 'int'})]) + views = { + 'test': { + 'type': 'table', + 'table': 'test', + }, + } + spec = { + 'source': 'test', + 'views': views, + 'layout': layout + } + + doc = Document() + with set_curdoc(doc): + state.sources['test'] = derived + + if error is not None: + with pytest.raises(error): + Target.from_spec(spec, sources={'test': derived}) + else: + Target.from_spec(spec, sources={'test': derived})