#-----------------------------------------------------------------------------
# Copyright (c) Anaconda, Inc., and Bokeh Contributors.
# All rights reserved.
#
# The full license is in the file LICENSE.txt, distributed with this software.
#-----------------------------------------------------------------------------
'''
'''
#-----------------------------------------------------------------------------
# Boilerplate
#-----------------------------------------------------------------------------
from __future__ import annotations
import logging # isort:skip
log = logging.getLogger(__name__)
#-----------------------------------------------------------------------------
# Imports
#-----------------------------------------------------------------------------
# Standard library imports
from os.path import abspath, expanduser
from typing import TYPE_CHECKING, Sequence
# External imports
from jinja2 import Template
# Bokeh imports
from ..core.templates import FILE
from ..resources import Resources
from ..settings import settings
from .state import curstate
from .util import default_filename
if TYPE_CHECKING:
from ..core.types import PathLike
from ..models.ui import UIElement
from ..resources import ResourcesLike
from ..themes import Theme
from .state import State
#-----------------------------------------------------------------------------
# Globals and constants
#-----------------------------------------------------------------------------
DEFAULT_TITLE = "Bokeh Plot"
__all__ = (
'save',
)
#-----------------------------------------------------------------------------
# General API
#-----------------------------------------------------------------------------
[docs]
def save(obj: UIElement | Sequence[UIElement], filename: PathLike | None = None, resources: ResourcesLike | None = None,
title: str | None = None, template: Template | str | None = None, state: State | None = None) -> str:
''' Save an HTML file with the data for the current document.
Will fall back to the default output state (or an explicitly provided
:class:`State` object) for ``filename``, ``resources``, or ``title`` if they
are not provided. If the filename is not given and not provided via output state,
it is derived from the script name (e.g. ``/foo/myplot.py`` will create
``/foo/myplot.html``)
Args:
obj (UIElement object) : a Layout (Row/Column), Plot or Widget object to display
filename (PathLike, e.g. str, Path, optional) : filename to save document under (default: None)
If None, use the default state configuration.
resources (Resources or ResourcesMode, optional) : A Resources config to use (default: None)
If None, use the default state configuration, if there is one.
otherwise use ``resources.INLINE``.
title (str, optional) : a title for the HTML document (default: None)
If None, use the default state title value, if there is one.
Otherwise, use "Bokeh Plot"
template (Template, str, optional) : HTML document template (default: FILE)
A Jinja2 Template, see bokeh.core.templates.FILE for the required template
parameters
state (State, optional) :
A :class:`State` object. If None, then the current default
implicit state is used. (default: None).
Returns:
str: the filename where the HTML file is saved.
'''
if state is None:
state = curstate()
theme = state.document.theme
filename, resources, title = _get_save_args(state, filename, resources, title)
_save_helper(obj, filename, resources, title, template, theme)
return abspath(expanduser(filename))
#-----------------------------------------------------------------------------
# Dev API
#-----------------------------------------------------------------------------
#-----------------------------------------------------------------------------
# Private API
#-----------------------------------------------------------------------------
def _get_save_args(state: State, filename: PathLike | None, resources: ResourcesLike | None,
title: str | None) -> tuple[PathLike, Resources, str]:
'''
'''
filename, is_default_filename = _get_save_filename(state, filename)
resources = _get_save_resources(state, resources, is_default_filename)
title = _get_save_title(state, title, is_default_filename)
return filename, resources, title
def _get_save_filename(state: State, filename: PathLike | None) -> tuple[PathLike, bool]:
if filename is not None:
return filename, False
if state.file and not settings.ignore_filename():
return state.file.filename, False
return default_filename("html"), True
def _get_save_resources(state: State, resources: ResourcesLike | None, suppress_warning: bool) -> Resources:
if resources is not None:
if isinstance(resources, Resources):
return resources
else:
return Resources(mode=resources)
if state.file:
return state.file.resources
if not suppress_warning:
from ..util.warnings import warn
warn("save() called but no resources were supplied and output_file(...) was never called, defaulting to resources.CDN")
return Resources(mode=settings.resources())
def _get_save_title(state: State, title: str | None, suppress_warning: bool) -> str:
if title is not None:
return title
if state.file:
return state.file.title
if not suppress_warning:
from ..util.warnings import warn
warn("save() called but no title was supplied and output_file(...) was never called, using default title 'Bokeh Plot'")
return DEFAULT_TITLE
def _save_helper(obj: UIElement | Sequence[UIElement], filename: PathLike, resources: Resources | None,
title: str | None, template: Template | str | None, theme: Theme | None = None) -> None:
'''
'''
from ..embed import file_html
html = file_html(obj, resources=resources, title=title, template=template or FILE, theme=theme)
with open(filename, mode="w", encoding="utf-8") as f:
f.write(html)
#-----------------------------------------------------------------------------
# Code
#-----------------------------------------------------------------------------