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

Improved BokehRenderer.app API #1444

Merged
merged 3 commits into from
May 16, 2017
Merged
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
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)