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

Implement Template.save #1224

Merged
merged 2 commits into from
Apr 3, 2020
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
58 changes: 45 additions & 13 deletions panel/io/save.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@

from six import string_types

import bokeh

from bokeh.document.document import Document
from bokeh.embed import file_html
from bokeh.io.export import export_png
Expand All @@ -23,8 +25,7 @@
# Private API
#---------------------------------------------------------------------


def save_png(model, filename):
def save_png(model, filename, template=None, template_variables=None):
"""
Saves a bokeh model to png

Expand All @@ -34,13 +35,33 @@ def save_png(model, filename):
Model to save to png
filename: str
Filename to save to
template:
template file, as used by bokeh.file_html. If None will use bokeh defaults
template_variables:
template_variables file dict, as used by bokeh.file_html
"""
from bokeh.io.webdriver import webdriver_control
if not state.webdriver:
state.webdriver = webdriver_control.create()

webdriver = state.webdriver
export_png(model, filename=filename, webdriver=webdriver)

try:
if template:
def get_layout_html(obj, resources, width, height):
return file_html(
obj, resources, title="", template=template,
template_variables=template_variables,
suppress_callback_warning=True, _always_new=True
)
old_layout_fn = bokeh.io.export.get_layout_html
bokeh.io.export.get_layout_html = get_layout_html
export_png(model, filename=filename, webdriver=webdriver)
except Exception:
raise
finally:
if template:
bokeh.io.export.get_layout_html = old_layout_fn


#---------------------------------------------------------------------
Expand Down Expand Up @@ -86,27 +107,38 @@ def save(panel, filename, title=None, resources=None, template=None,
Whether to report progress
"""
from ..pane import PaneBase
from ..template import Template

if isinstance(panel, PaneBase) and len(panel.layout) > 1:
panel = panel.layout

as_png = isinstance(filename, string_types) and filename.endswith('png')

doc = Document()
if isinstance(panel, Document):
doc = panel
else:
doc = Document()

comm = Comm()
with config.set(embed=embed):
model = panel.get_root(doc, comm)
if embed:
embed_state(
panel, model, doc, max_states, max_opts, embed_json,
json_prefix, save_path, load_path, progress
)
if isinstance(panel, Document):
model = panel
elif isinstance(panel, Template):
panel._init_doc(doc, title=title)
model = doc
else:
add_to_doc(model, doc, True)
model = panel.get_root(doc, comm)
if embed:
embed_state(
panel, model, doc, max_states, max_opts, embed_json,
json_prefix, save_path, load_path, progress
)
else:
add_to_doc(model, doc, True)

if as_png:
save_png(model, filename=filename)
return
return save_png(model, filename=filename, template=template,
template_variables=template_variables)
elif isinstance(filename, string_types) and not filename.endswith('.html'):
filename = filename + '.html'

Expand Down
59 changes: 59 additions & 0 deletions panel/template.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
from .config import config, panel_extension
from .io.model import add_to_doc
from .io.notebook import render_template
from .io.save import save
from .io.state import state
from .layout import Column
from .models.comm_manager import CommManager
Expand Down Expand Up @@ -67,7 +68,10 @@ class Template(param.Parameterized, ServableMixin):
def __init__(self, template=None, items=None, nb_template=None, **params):
super(Template, self).__init__(**params)
if isinstance(template, string_types):
self._code = template
template = _Template(template)
else:
self._code = None
self.template = template
if isinstance(nb_template, string_types):
nb_template = _Template(nb_template)
Expand Down Expand Up @@ -244,3 +248,58 @@ def server_doc(self, doc=None, title=None):
The Bokeh document the panel was attached to
"""
return self._init_doc(doc, title=title)

def save(self, filename, title=None, resources=None, embed=False,
max_states=1000, max_opts=3, embed_json=False,
json_prefix='', save_path='./', load_path=None):
"""
Saves Panel objects to file.

Arguments
---------
filename: string or file-like object
Filename to save the plot to
title: string
Optional title for the plot
resources: bokeh resources
One of the valid bokeh.resources (e.g. CDN or INLINE)
embed: bool
Whether the state space should be embedded in the saved file.
max_states: int
The maximum number of states to embed
max_opts: int
The maximum number of states for a single widget
embed_json: boolean (default=True)
Whether to export the data to json files
json_prefix: str (default='')
Prefix for the auto-generated json directory
save_path: str (default='./')
The path to save json files to
load_path: str (default=None)
The path or URL the json files will be loaded from.
"""
if embed:
raise ValueError("Embedding is not yet supported on Template.")
return save(self, filename, title, resources, self.template,
self._render_variables, embed, max_states, max_opts,
embed_json, json_prefix, save_path, load_path)

def select(self, selector=None):
"""
Iterates over the Template and any potential children in the
applying the Selector.

Arguments
---------
selector: type or callable or None
The selector allows selecting a subset of Viewables by
declaring a type or callable function to filter by.

Returns
-------
viewables: list(Viewable)
"""
objects = []
for obj, _ in self._render_items.values():
objects += obj.select(selector)
return objects