From 80d98e37586fc30caf35f53bf5d22da7e0ca7df0 Mon Sep 17 00:00:00 2001
From: Philipp Rudiger
Date: Tue, 16 May 2017 11:42:37 +0100
Subject: [PATCH 1/3] Set notebook type when loading bokeh extension
---
holoviews/plotting/bokeh/renderer.py | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/holoviews/plotting/bokeh/renderer.py b/holoviews/plotting/bokeh/renderer.py
index 4a443ffa7f..87393a4959 100644
--- a/holoviews/plotting/bokeh/renderer.py
+++ b/holoviews/plotting/bokeh/renderer.py
@@ -19,7 +19,7 @@
from ..plot import GenericElementPlot
from ..renderer import Renderer, MIME_TYPES
from .widgets import BokehScrubberWidget, BokehSelectionWidget, BokehServerWidgets
-from .util import compute_static_patch, serialize_json, attach_periodic
+from .util import compute_static_patch, serialize_json, attach_periodic, bokeh_version
@@ -217,4 +217,5 @@ def load_nb(cls, inline=True):
"""
Loads the bokeh notebook resources.
"""
- load_notebook(hide_banner=True, resources=INLINE if inline else CDN)
+ kwargs = {'notebook_type': 'jupyter'} if bokeh_version > '0.12.5' else {}
+ load_notebook(hide_banner=True, resources=INLINE if inline else CDN, **kwargs)
From c121eca525629960df49f277f16a2d8ca7044083 Mon Sep 17 00:00:00 2001
From: Philipp Rudiger
Date: Tue, 16 May 2017 11:43:27 +0100
Subject: [PATCH 2/3] Added doc argument to BokehRenderer.get_plot
---
holoviews/plotting/bokeh/renderer.py | 18 ++++++++++++++++--
1 file changed, 16 insertions(+), 2 deletions(-)
diff --git a/holoviews/plotting/bokeh/renderer.py b/holoviews/plotting/bokeh/renderer.py
index 87393a4959..388428b9dd 100644
--- a/holoviews/plotting/bokeh/renderer.py
+++ b/holoviews/plotting/bokeh/renderer.py
@@ -84,10 +84,24 @@ def __call__(self, obj, fmt=None, doc=None):
elif fmt == 'json':
return self.diff(plot), info
+
+ @bothmethod
+ def get_plot(self_or_cls, obj, doc=None, renderer=None):
+ """
+ Given a HoloViews Viewable return a corresponding plot instance.
+ Allows supplying a document attach the plot to, useful when
+ combining the bokeh model with another plot.
+ """
+ plot = super(BokehRenderer, self_or_cls).get_plot(obj, renderer)
+ if doc is not None:
+ plot.document = doc
+ return plot
+
+
@bothmethod
- def get_widget(self_or_cls, plot, widget_type, **kwargs):
+ def get_widget(self_or_cls, plot, widget_type, doc=None, **kwargs):
if not isinstance(plot, Plot):
- plot = self_or_cls.get_plot(plot)
+ plot = self_or_cls.get_plot(plot, doc)
if self_or_cls.mode == 'server':
return BokehServerWidgets(plot, renderer=self_or_cls.instance(), **kwargs)
else:
From 460b18ef6a879056175fccc40aafe49aaef74a57 Mon Sep 17 00:00:00 2001
From: Philipp Rudiger
Date: Tue, 16 May 2017 11:44:06 +0100
Subject: [PATCH 3/3] Added options to BokehRenderer.app
---
holoviews/plotting/bokeh/renderer.py | 44 ++++++++++++++++++++++------
1 file changed, 35 insertions(+), 9 deletions(-)
diff --git a/holoviews/plotting/bokeh/renderer.py b/holoviews/plotting/bokeh/renderer.py
index 388428b9dd..12f6439dcf 100644
--- a/holoviews/plotting/bokeh/renderer.py
+++ b/holoviews/plotting/bokeh/renderer.py
@@ -7,12 +7,13 @@
from bokeh.application import Application
from bokeh.charts import Chart
from bokeh.document import Document
-from bokeh.embed import notebook_div
-from bokeh.io import load_notebook, curdoc, show
+from bokeh.embed import notebook_div, autoload_server
+from bokeh.io import load_notebook, curdoc, show as bkshow
from bokeh.models import (Row, Column, Plot, Model, ToolbarBox,
WidgetBox, Div, DataTable, Tabs)
from bokeh.plotting import Figure
from bokeh.resources import CDN, INLINE
+from bokeh.server.server import Server
from ...core import Store, HoloMap
from ..comms import JupyterComm, Comm
@@ -109,25 +110,49 @@ def get_widget(self_or_cls, plot, widget_type, doc=None, **kwargs):
@bothmethod
- def app(self_or_cls, plot, notebook=False):
+ def app(self_or_cls, plot, show=False, new_window=False):
"""
Creates a bokeh app from a HoloViews object or plot. By
default simply uses attaches plot to bokeh's curdoc and
- returns the Document, if notebook option is supplied creates
- an Application instance, displays it and returns it.
+ returns the Document, if show option is supplied creates
+ an Application instance and displays it either in a browser
+ window or inline if notebook extension has been loaded.
+ Using the new_window option the app may be displayed in a
+ new browser tab once the notebook extension has been loaded.
"""
renderer = self_or_cls.instance(mode='server')
- if not notebook:
+ # If show=False and not in noteboook context return document
+ if not show and not self_or_cls.notebook_context:
doc, _ = renderer(plot)
return doc
def modify_doc(doc):
renderer(plot, doc=doc)
-
handler = FunctionHandler(modify_doc)
app = Application(handler)
- show(app)
- return app
+
+ if not show:
+ # If not showing and in notebook context return app
+ return app
+ elif self_or_cls.notebook_context and not new_window:
+ # If in notebook, show=True and no new window requested
+ # display app inline
+ return bkshow(app)
+
+ # If app shown outside notebook or new_window requested
+ # start server and open in new browser tab
+ from tornado.ioloop import IOLoop
+ loop = IOLoop.current()
+ server = Server({'/': app}, port=0, loop=loop)
+ def show_callback():
+ server.show('/')
+ server.io_loop.add_callback(show_callback)
+ server.start()
+ try:
+ loop.start()
+ except RuntimeError:
+ pass
+ return server
def server_doc(self, plot, doc=None):
@@ -170,6 +195,7 @@ def diff(self, plot, serialize=True):
processed = self._apply_post_render_hooks(patch, plot, 'json')
return serialize_json(processed) if serialize else processed
+
@classmethod
def plot_options(cls, obj, percent_size):
"""