def test_bkwidget_bkplot_links(document, comm): from bokeh.models import Slider bokeh_widget = Slider(value=5, start=1, end=10, step=1e-1) bokeh_fig = figure() scatter = bokeh_fig.scatter([1, 2, 3], [1, 2, 3]) Link(bokeh_widget, scatter, properties={'value': 'glyph.size'}) row = Row(bokeh_fig, bokeh_widget) row.get_root(document, comm=comm) slider = bokeh_widget link_customjs = slider.js_property_callbacks['change:value'][-1] assert link_customjs.args['source'] is slider assert link_customjs.args['target'] is scatter.glyph code = """ var value = source['value']; value = value; value = value; try { var property = target.properties['size']; if (property !== undefined) { property.validate(value); } } catch(err) { console.log('WARNING: Could not set size on target, raised error: ' + err); return; } try { target['size'] = value; } catch(err) { console.log(err) } """ assert link_customjs.code == code
def test_widget_bkplot_link(document, comm): widget = ColorPicker(value='#ff00ff') bokeh_fig = figure() scatter = bokeh_fig.scatter([1, 2, 3], [1, 2, 3]) widget.jslink(scatter.glyph, value='fill_color') row = Row(bokeh_fig, widget) model = row.get_root(document, comm=comm) link_customjs = model.children[1].js_property_callbacks['change:color'][-1] assert link_customjs.args['source'] is model.children[1] assert link_customjs.args['target'] is scatter.glyph assert scatter.glyph.fill_color == '#ff00ff' code = """ var value = source['color']; value = value; value = value; try { var property = target.properties['fill_color']; if (property !== undefined) { property.validate(value); } } catch(err) { console.log('WARNING: Could not set fill_color on target, raised error: ' + err); return; } try { target['fill_color'] = value; } catch(err) { console.log(err) } """ assert link_customjs.code == code
def test_bkwidget_hvplot_links(document, comm): from bokeh.models import Slider bokeh_widget = Slider(value=5, start=1, end=10, step=1e-1) points1 = hv.Points([1, 2, 3]) GenericLink(bokeh_widget, points1, properties={'value': 'glyph.size'}) row = Row(points1, bokeh_widget) model = row.get_root(document, comm=comm) hv_views = row.select(HoloViews) assert len(hv_views) == 1 slider = bokeh_widget scatter = hv_views[0]._plots[model.ref['id']][0].handles['glyph'] link_customjs = slider.js_property_callbacks['change:value'][-1] assert link_customjs.args['source'] is slider assert link_customjs.args['target'] is scatter code = ( "value = source['value'];" "try { property = target.properties['size'];" "if (property !== undefined) { property.validate(value); } }" "catch(err) { console.log('WARNING: Could not set size on target, raised error: ' + err); return; }" "target['size'] = value") assert link_customjs.code == code
def test_holoviews_link_after_adding_item(document, comm): from bokeh.models.tools import RangeTool from holoviews.plotting.links import RangeToolLink c1 = hv.Curve([]) c2 = hv.Curve([]) RangeToolLink(c1, c2) layout = Row(Pane(c1, backend='bokeh')) row = layout.get_root(document, comm=comm) assert len(row.children) == 1 p1, = row.children assert isinstance(p1, Figure) range_tool = row.select_one({'type': RangeTool}) assert range_tool is None layout.append(Pane(c2, backend='bokeh')) _, p2 = row.children assert isinstance(p2, Figure) range_tool = row.select_one({'type': RangeTool}) assert isinstance(range_tool, RangeTool) assert range_tool.x_range == p2.x_range
def test_expand_param_subobject_into_column(document, comm): class Test(param.Parameterized): a = param.Parameter() test = Test(a=Test(name='Nested')) column = Column() test_pane = Pane(test, subobject_layout=column, _temporary=True) layout = Row(test_pane, column) model = layout._get_model(document, comm=comm) toggle = model.children[0].children[2] assert isinstance(toggle, Toggle) # Expand subpane test_pane._widgets['a'][1].active = True assert len(model.children) == 2 subpanel = column.objects[0] row = model.children[1] assert 'instance' in subpanel._callbacks assert isinstance(row, BkColumn) assert len(row.children) == 1 box = row.children[0] assert isinstance(box, BkWidgetBox) assert len(box.children) == 2 div, widget = box.children assert div.text == '<b>Nested</b>' assert isinstance(widget, BkTextInput) # Collapse subpanel test_pane._widgets['a'][1].active = False assert len(row.children) == 0 assert subpanel._callbacks == {}
def test_pnwidget_hvplot_links(document, comm): size_widget = FloatSlider(value=5, start=1, end=10) points1 = hv.Points([1, 2, 3]) size_widget.jslink(points1, value='glyph.size') row = Row(points1, size_widget) model = row.get_root(document, comm=comm) hv_views = row.select(HoloViews) widg_views = row.select(FloatSlider) assert len(hv_views) == 1 assert len(widg_views) == 1 slider = widg_views[0]._models[model.ref['id']][0] scatter = hv_views[0]._plots[model.ref['id']][0].handles['glyph'] link_customjs = slider.js_property_callbacks['change:value'][-1] assert link_customjs.args['source'] is slider assert link_customjs.args['target'] is scatter code = ( "value = source['value'];" "try { property = target.properties['size'];" "if (property !== undefined) { property.validate(value); } }" "catch(err) { console.log('WARNING: Could not set size on target, raised error: ' + err); return; }" "target['size'] = value") assert link_customjs.code == code
def test_template_session_destroy(document, comm): tmplt = Template(template) widget = FloatSlider() row = Row('A', 'B') tmplt.add_panel('A', widget) tmplt.add_panel('B', row) tmplt._init_doc(document, comm, notebook=True) session_context = param.Parameterized() session_context._document = document session_context.id = 'Some ID' assert len(widget._models) == 2 assert len(row._models) == 2 assert len(row[0]._models) == 2 assert len(row[1]._models) == 2 for cb in document.session_destroyed_callbacks: cb(session_context) assert len(widget._models) == 0 assert len(row._models) == 0 assert len(row[0]._models) == 0 assert len(row[1]._models) == 0
def test_server_thread_pool_change_event(threads): button = Button(name='Click') button2 = Button(name='Click') counts = [] def cb(event, count=[0]): count[0] += 1 counts.append(count[0]) time.sleep(0.5) count[0] -= 1 button.on_click(cb) button2.on_click(cb) layout = Row(button, button2) port = 6010 serve(layout, port=port, threaded=True, show=False) # Wait for server to start time.sleep(1) requests.get(f"http://localhost:{port}/") model = list(layout._models.values())[0][0] doc = model.document with set_curdoc(doc): button._server_change(doc, model.ref['id'], None, 'clicks', 0, 1) button2._server_change(doc, model.ref['id'], None, 'clicks', 0, 1) # Wait for callbacks to be scheduled time.sleep(1) # Checks whether Button on_click callback was executed concurrently assert max(counts) == 2
def test_widget_linkable_params(widget): w = widget() controls = w.controls(jslink=True) layout = Row(w, controls) try: CallbackGenerator.error = True layout.get_root() finally: CallbackGenerator.error = False
def test_holoviews_shared_axes_opt_not_linked_axes(document, comm): c1 = hv.Curve([1, 2, 3]) c2 = hv.Curve([1, 2, 3]).opts(shared_axes=False, backend='bokeh') layout = Row(HoloViews(c1, backend='bokeh'), HoloViews(c2, backend='bokeh')) row_model = layout.get_root(document, comm=comm) p1, p2 = row_model.select({'type': Figure}) assert p1.x_range is not p2.x_range assert p1.y_range is not p2.y_range
def test_holoviews_linked_x_axis(document, comm): c1 = hv.Curve([1, 2, 3]) c2 = hv.Curve([1, 2, 3], vdims='y2') layout = Row(HoloViews(c1, backend='bokeh'), HoloViews(c2, backend='bokeh')) row_model = layout.get_root(document, comm=comm) p1, p2 = row_model.select({'type': Figure}) assert p1.x_range is p2.x_range assert p1.y_range is not p2.y_range
def test_pane_linkable_params(pane): p = pane() controls = p.controls(jslink=True) layout = Row(p, controls) try: CallbackGenerator.error = True layout.get_root() except Exception as e: raise e finally: CallbackGenerator.error = False
def test_widget_jscallback_args_model(document, comm): widget = ColorPicker(value='#ff00ff') widget2 = ColorPicker(value='#ff00ff') widget.jscallback(value='some_code', args={'widget': widget2}) model = Row(widget, widget2).get_root(document, comm=comm) customjs = model.children[0].js_property_callbacks['change:color'][-1] assert customjs.args['source'] is model.children[0] assert customjs.args['widget'] is model.children[1] assert customjs.code == "try { some_code } catch(err) { console.log(err) }"
def __init__(self, object=None, **params): super(Annotator, self).__init__(None, **params) self.object = self._process_element(object) self._table_row = Row() self.editor = Tabs(('%s' % param_name(self.name), self._table_row)) self.plot = DynamicMap(Callable(self._get_plot, inputs=[self.object])) self._tables = [] self._init_stream() self._stream.add_subscriber(self._update_object, precedence=0.1) self._selection = Selection1D(source=self.plot) self._update_table() self._update_links() self.param.watch(self._update, self._triggers) self.layout[:] = [self.plot, self.editor]
def test_pane_linkable_params(pane): try: p = pane() except ImportError: pytest.skip("Dependent library could not be imported.") controls = p.controls(jslink=True) layout = Row(p, controls) try: CallbackGenerator.error = True layout.get_root() except Exception as e: raise e finally: CallbackGenerator.error = False
def test_holoviews_linked_axes_merged_ranges(document, comm): c1 = hv.Curve([1, 2, 3]) c2 = hv.Curve([0, 1, 2, 3, 4]) layout = Row(HoloViews(c1, backend='bokeh'), HoloViews(c2, backend='bokeh')) row_model = layout.get_root(document, comm=comm) p1, p2 = row_model.select({'type': Figure}) assert p1.x_range is p2.x_range assert p1.y_range is p2.y_range assert p1.y_range.start == -0.4 assert p1.y_range.end == 4.4
def test_bokeh_figure_jslink(document, comm): fig = figure() pane = Bokeh(fig) t1 = TextInput() pane.jslink(t1, **{'x_range.start': 'value'}) row = Row(pane, t1) model = row.get_root(document, comm) link_customjs = fig.x_range.js_property_callbacks['change:start'][-1] assert link_customjs.args['source'] == fig.x_range assert link_customjs.args['target'] == model.children[1] assert link_customjs.code == """
def layout(self, **kwargs): """ Returns a layout of the widgets and output arranged according to the center and widget location specified in the interactive call. """ widget_box = self.widgets() panel = self.output() loc = self._loc if loc in ('left', 'right'): widgets = Column(VSpacer(), widget_box, VSpacer()) elif loc in ('top', 'bottom'): widgets = Row(HSpacer(), widget_box, HSpacer()) elif loc in ('top_left', 'bottom_left'): widgets = Row(widget_box, HSpacer()) elif loc in ('top_right', 'bottom_right'): widgets = Row(HSpacer(), widget_box) elif loc in ('left_top', 'right_top'): widgets = Column(widget_box, VSpacer()) elif loc in ('left_bottom', 'right_bottom'): widgets = Column(VSpacer(), widget_box) center = self._center if not widgets: if center: components = [HSpacer(), panel, HSpacer()] else: components = [panel] elif center: if loc.startswith('left'): components = [widgets, HSpacer(), panel, HSpacer()] elif loc.startswith('right'): components = [HSpacer(), panel, HSpacer(), widgets] elif loc.startswith('top'): components = [ HSpacer(), Column(widgets, Row(HSpacer(), panel, HSpacer())), HSpacer() ] elif loc.startswith('bottom'): components = [ HSpacer(), Column(Row(HSpacer(), panel, HSpacer()), widgets), HSpacer() ] else: if loc.startswith('left'): components = [widgets, panel] elif loc.startswith('right'): components = [panel, widgets] elif loc.startswith('top'): components = [Column(widgets, panel)] elif loc.startswith('bottom'): components = [Column(panel, widgets)] return Row(*components, **kwargs)
def test_widget_link_bidirectional(document, comm): t1 = TextInput() t2 = TextInput() t1.jslink(t2, value='value', bidirectional=True) row = Row(t1, t2) model = row.get_root(document, comm) tm1, tm2 = model.children link1_customjs = tm1.js_property_callbacks['change:value'][-1] link2_customjs = tm2.js_property_callbacks['change:value'][-1] assert link1_customjs.args['source'] is tm1 assert link2_customjs.args['source'] is tm2 assert link1_customjs.args['target'] is tm2 assert link2_customjs.args['target'] is tm1
def test_template_links_axes(document, comm): tmplt = Template(template) p1 = HoloViews(hv.Curve([1, 2, 3])) p2 = HoloViews(hv.Curve([1, 2, 3])) p3 = HoloViews(hv.Curve([1, 2, 3])) row = Row(p2, p3) tmplt.add_panel('A', p1) tmplt.add_panel('B', row) tmplt._init_doc(document, comm, notebook=True) (_, (m1, _)) = list(p1._models.items())[0] (_, (m2, _)) = list(p2._models.items())[0] (_, (m3, _)) = list(p3._models.items())[0] assert m1.x_range is m2.x_range assert m1.y_range is m2.y_range assert m2.x_range is m3.x_range assert m2.y_range is m3.y_range
def compose(cls, *annotators): """Composes multiple Annotator instances and elements The composed Panel will contain all the elements in the supplied Annotators and Tabs containing all editors. Args: annotators: Annotator objects or elements to compose Returns: A new Panel consisting of the overlaid plots and tables """ layers, tables = [], [] for a in annotators: if isinstance(a, Annotator): layers.append(a.plot) tables += a.tables elif isinstance(a, Element): layers.append(a) return Row(Overlay(layers).collate(), Tabs(*tables))
def test_holoviews_link_across_panes(document, comm): from bokeh.models.tools import RangeTool from holoviews.plotting.links import RangeToolLink c1 = hv.Curve([]) c2 = hv.Curve([]) RangeToolLink(c1, c2) layout = Row(c1, c2) row = layout._get_root(document, comm=comm) assert len(row.children) == 2 p1, p2 = row.children assert isinstance(p1, Figure) assert isinstance(p2, Figure) range_tool = row.select_one({'type': RangeTool}) assert isinstance(range_tool, RangeTool) range_tool.x_range = p2.x_range
def test_link_with_customcode(document, comm): range_widget = RangeSlider(start=0., end=1.) curve = hv.Curve([]) code = """ x_range.start = source.value[0] x_range.end = source.value[1] """ range_widget.jslink(curve, code={'value': code}) row = Row(curve, range_widget) range_widget.value = (0.5, 0.7) model = row.get_root(document, comm=comm) hv_views = row.select(HoloViews) widg_views = row.select(RangeSlider) assert len(hv_views) == 1 assert len(widg_views) == 1 range_slider = widg_views[0]._models[model.ref['id']][0] x_range = hv_views[0]._plots[model.ref['id']][0].handles['x_range'] link_customjs = range_slider.js_property_callbacks['change:value'][-1] assert link_customjs.args['source'] is range_slider assert link_customjs.args['x_range'] is x_range assert link_customjs.code == "try { %s } catch(err) { console.log(err) }" % code
def __init__(self, **params): super(TestClass, self).__init__(**params) self._layout = Row(Param(self.param, parameters=['select']), self.select)
def panel(self): return Row(self.param, self.view)
def __init__(self, object=None, **params): self._vertex_table_row = Row() super(PathAnnotator, self).__init__(object, **params) self.editor.append( ('%s Vertices' % param_name(self.name), self._vertex_table_row))