Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ensure that bokeh plot refresh has the Document lock #3621

Merged
merged 2 commits into from
Apr 26, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions holoviews/plotting/bokeh/plot.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import numpy as np
import param

from bokeh.io import curdoc
from bokeh.layouts import gridplot
from bokeh.models import (ColumnDataSource, Column, Row, Div)
from bokeh.models.widgets import Panel, Tabs
Expand Down Expand Up @@ -175,6 +176,12 @@ def _construct_callbacks(self):
cbs.append(cb(self, cb_streams, source))
return cbs

def refresh(self, **kwargs):
if self.renderer.mode == 'server' and curdoc() is not self.document:
# If we do not have the Document lock, schedule refresh as callback
self.document.add_next_tick_callback(self.refresh)
else:
super(BokehPlot, self).refresh(**kwargs)

def push(self):
"""
Expand Down
8 changes: 8 additions & 0 deletions holoviews/tests/plotting/bokeh/testcallbacks.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

try:
from bokeh.events import Tap
from bokeh.io.doc import set_curdoc
from bokeh.models import Range1d, Plot, ColumnDataSource, Selection, PolyEditTool
from holoviews.plotting.bokeh.callbacks import (
Callback, PointDrawCallback, PolyDrawCallback, PolyEditCallback,
Expand Down Expand Up @@ -49,6 +50,7 @@ def test_stream_callback(self):
dmap = DynamicMap(lambda x, y: Points([(x, y)]), kdims=[], streams=[PointerXY()])
plot = bokeh_server_renderer.get_plot(dmap)
bokeh_server_renderer(plot)
set_curdoc(plot.document)
plot.callbacks[0].on_msg({"x": 0.3, "y": 0.2})
data = plot.handles['source'].data
self.assertEqual(data['x'], np.array([0.3]))
Expand All @@ -58,6 +60,7 @@ def test_point_stream_callback_clip(self):
dmap = DynamicMap(lambda x, y: Points([(x, y)]), kdims=[], streams=[PointerXY()])
plot = bokeh_server_renderer.get_plot(dmap)
bokeh_server_renderer(plot)
set_curdoc(plot.document)
plot.callbacks[0].on_msg({"x": -0.3, "y": 1.2})
data = plot.handles['source'].data
self.assertEqual(data['x'], np.array([0]))
Expand All @@ -68,6 +71,7 @@ def test_stream_callback_on_clone(self):
stream = PointerXY(source=points)
plot = bokeh_server_renderer.get_plot(points.clone())
bokeh_server_renderer(plot)
set_curdoc(plot.document)
plot.callbacks[0].on_msg({"x": 0.8, "y": 0.3})
self.assertEqual(stream.x, 0.8)
self.assertEqual(stream.y, 0.3)
Expand All @@ -83,6 +87,7 @@ def test_stream_callback_with_ids(self):
dmap = DynamicMap(lambda x, y: Points([(x, y)]), kdims=[], streams=[PointerXY()])
plot = bokeh_server_renderer.get_plot(dmap)
bokeh_server_renderer(plot)
set_curdoc(plot.document)
model = plot.state
plot.callbacks[0].on_msg({"x": {'id': model.ref['id'], 'value': 0.5},
"y": {'id': model.ref['id'], 'value': 0.4}})
Expand All @@ -98,6 +103,7 @@ def history_callback(x, history=deque(maxlen=10)):
dmap = DynamicMap(history_callback, kdims=[], streams=[stream])
plot = bokeh_server_renderer.get_plot(dmap)
bokeh_server_renderer(plot)
set_curdoc(plot.document)
for i in range(20):
stream.event(x=i)
data = plot.handles['source'].data
Expand Down Expand Up @@ -137,6 +143,7 @@ def test_pointer_x_datetime_out_of_bounds(self):
points = Points([(dt.datetime(2017, 1, 1), 1), (dt.datetime(2017, 1, 3), 3)])
PointerX(source=points)
plot = bokeh_server_renderer.get_plot(points)
set_curdoc(plot.document)
callback = plot.callbacks[0]
self.assertIsInstance(callback, PointerXCallback)
msg = callback._process_msg({'x': 1000})
Expand All @@ -148,6 +155,7 @@ def test_tap_datetime_out_of_bounds(self):
points = Points([(dt.datetime(2017, 1, 1), 1), (dt.datetime(2017, 1, 3), 3)])
SingleTap(source=points)
plot = bokeh_server_renderer.get_plot(points)
set_curdoc(plot.document)
callback = plot.callbacks[0]
self.assertIsInstance(callback, TapCallback)
msg = callback._process_msg({'x': 1000, 'y': 2})
Expand Down