Skip to content

Commit

Permalink
Merge pull request #1444 from ioam/bokeh_app_api
Browse files Browse the repository at this point in the history
Improved BokehRenderer.app API
  • Loading branch information
jlstevens committed May 16, 2017
2 parents 8b68e26 + 460b18e commit fc86317
Showing 1 changed file with 54 additions and 13 deletions.
67 changes: 54 additions & 13 deletions holoviews/plotting/bokeh/renderer.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,20 @@
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
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



Expand Down Expand Up @@ -84,36 +85,74 @@ def __call__(self, obj, fmt=None, doc=None):
elif fmt == 'json':
return self.diff(plot), info


@bothmethod
def get_widget(self_or_cls, plot, widget_type, **kwargs):
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, 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:
return super(BokehRenderer, self_or_cls).get_widget(plot, widget_type, **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):
Expand Down Expand Up @@ -156,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):
"""
Expand Down Expand Up @@ -217,4 +257,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)

0 comments on commit fc86317

Please sign in to comment.