<commit_before>''' This module provides functions for embedding Bokeh plots in various
different ways.

There are a number of different combinations of options when embedding
Bokeh plots. The data for the plot can be contained in the document,
or on a Bokeh server, or in a sidecar JavaScript file. Likewise, BokehJS
may be inlined in the document, or loaded from CDN or a Bokeh server.

The functions in ``bokeh.embed`` provide functionality to embed in all
these different cases.

'''

from __future__ import absolute_import

from warnings import warn
import uuid

from .protocol import serialize_json
from .resources import Resources
from .templates import (
    AUTOLOAD, AUTOLOAD_SERVER, AUTOLOAD_STATIC, FILE,
    NOTEBOOK_DIV, PLOT_DIV, PLOT_JS, PLOT_SCRIPT, RESOURCES
)
from .util.string import encode_utf8


def _wrap_in_function(code):
    # Indent and wrap Bokeh function def around
    code = "\n".join([ "    " + line for line in code.split("\n") ])
    return 'Bokeh.$(function() {\n%s\n});' % code


def components(plot_objects, resources=None):
    ''' Return HTML components to embed a Bokeh plot.

    The data for the plot is stored directly in the returned HTML.

    .. note:: The returned components assume that BokehJS resources
              are **already loaded**.

    Args:
        plot_objects (PlotObject|list|dict|tuple) : Will return script
        and div element to render if PlotObject, or correlating structures
        of script/div combinations
        resources : Deprecated argument
    Returns:
        (script, div[s]): UTF-8 encoded
    '''

    from .plot_object import PlotObject
    from collections import Sequence
    from six import string_types
    if isinstance(plot_objects, PlotObject):
        plot_objects = [plot_objects]
    if resources is not None:
        warn('Because the ``resources`` argument is no longer needed, '
             'is it deprecated and will be removed in'
             'a future version.', DeprecationWarning, stacklevel=2)
    all_models = []
    plots = []
    if isinstance(plot_objects, Sequence) and all(isinstance(x, PlotObject) for x in plot_objects):
        divs = []
        for idx, plot_object in enumerate(plot_objects):
            elementid = str(uuid.uuid4())
            _append_plot(all_models, plots, plot_object, elementid)
            divs = _append_div(elementid, divs)
        if len(divs) == 1:
            divs = divs[0]
        else:
            divs = tuple(divs)
        return _component_pair(all_models, plots, divs)
    elif isinstance(plot_objects, dict) and all(isinstance(x, string_types) for x in plot_objects.keys()) and all(isinstance(x, PlotObject) for x in plot_objects.values()):
        divs = {}
        for key in plot_objects.keys():
            elementid = str(uuid.uuid4())
            _append_plot(all_models, plots, plot_objects[key], elementid)
            divs = _append_div(elementid, divs, key)
        return _component_pair(all_models, plots, divs)
    else:
        raise ValueError('Input must be a PlotObject, a Sequence of PlotObjects, or a mapping of string to PlotObjects')

def _component_pair(all_models, plots, divs):
    js = PLOT_JS.render(
        all_models = serialize_json(all_models),
        plots = plots
    )
    script = PLOT_SCRIPT.render(
        plot_js = _wrap_in_function(js),
    )
    return encode_utf8(script), divs

def _append_plot(all_models, plots, plot_object, elementid):
    ref = plot_object.ref
    all_models.extend(plot_object.dump())
    plots.append({
        'modelid': ref["id"],
        'elementid': '#' + elementid,
        'modeltype': ref["type"]
    })

def _append_div(elementid, divs=None, key=None):
    div = PLOT_DIV.render(
        elementid = elementid
    )
    if isinstance(divs, list):
        divs.append(encode_utf8(div))
        return divs
    elif isinstance(divs, dict):
        divs[key] = encode_utf8(div)
        return divs
    else:
        return encode_utf8(div)

def notebook_div(plot_object):
    ''' Return HTML for a div that will display a Bokeh plot in an
    IPython Notebook

    The data for the plot is stored directly in the returned HTML.

    Args:
        plot_object (PlotObject) : Bokeh object to render
            typically a Plot or PlotContext

    Returns:
        div : UTF-8 encoded HTML text

    .. note:: Assumes ``bokeh.load_notebook()`` or the equivalent has
              already been executed.

    '''
    ref = plot_object.ref
    elementid = str(uuid.uuid4())

    js = PLOT_JS.render(
        elementid = elementid,
        modelid = ref["id"],
        modeltype = ref["type"],
        all_models = serialize_json(plot_object.dump()),
    )
    script = PLOT_SCRIPT.render(
        plot_js = _wrap_in_function(js),
    )
    div = PLOT_DIV.render(elementid=elementid)
    html = NOTEBOOK_DIV.render(
        plot_script = script,
        plot_div = div,
    )
    return encode_utf8(html)


def file_html(plot_object, resources, title, template=FILE):
    ''' Return an HTML document that embeds a Bokeh plot.

    The data for the plot is stored directly in the returned HTML.

    Args:
        plot_object (PlotObject) : Bokeh object to render
            typically a Plot or PlotContext
        resources (Resources) : a resource configuration for BokehJS assets
        title (str) : a title for the HTML document ``<title>`` tags
        template (Template, optional) : HTML document template (default: FILE)
            A Jinja2 Template, see bokeh.templates.FILE for the required
            template parameters

    Returns:
        html : standalone HTML document with embedded plot

    '''
    from .plot_object import PlotObject
    if not isinstance(plot_object, PlotObject):
        raise ValueError('plot_object must be a single PlotObject')

    plot_resources = RESOURCES.render(
        js_raw = resources.js_raw,
        css_raw = resources.css_raw,
        js_files = resources.js_files,<commit_msg>Added Document support alongside PlotObject<commit_after>''' This module provides functions for embedding Bokeh plots in various
different ways.

There are a number of different combinations of options when embedding
Bokeh plots. The data for the plot can be contained in the document,
or on a Bokeh server, or in a sidecar JavaScript file. Likewise, BokehJS
may be inlined in the document, or loaded from CDN or a Bokeh server.

The functions in ``bokeh.embed`` provide functionality to embed in all
these different cases.

'''

from __future__ import absolute_import

from warnings import warn
import uuid

from .protocol import serialize_json
from .resources import Resources
from .templates import (
    AUTOLOAD, AUTOLOAD_SERVER, AUTOLOAD_STATIC, FILE,
    NOTEBOOK_DIV, PLOT_DIV, PLOT_JS, PLOT_SCRIPT, RESOURCES
)
from .util.string import encode_utf8


def _wrap_in_function(code):
    # Indent and wrap Bokeh function def around
    code = "\n".join([ "    " + line for line in code.split("\n") ])
    return 'Bokeh.$(function() {\n%s\n});' % code


def components(plot_objects, resources=None):
    ''' Return HTML components to embed a Bokeh plot.

    The data for the plot is stored directly in the returned HTML.

    .. note:: The returned components assume that BokehJS resources
              are **already loaded**.

    Args:
        plot_objects (PlotObject|list|dict|tuple) : Will return script
        and div element to render if PlotObject, or correlating structures
        of script/div combinations
        resources : Deprecated argument
    Returns:
        (script, div[s]): UTF-8 encoded
    '''

    from .plot_object import PlotObject
    from .document import Document
    from collections import Sequence
    from six import string_types
    if isinstance(plot_objects, (PlotObject, Document)):
        plot_objects = [plot_objects]
    if resources is not None:
        warn('Because the ``resources`` argument is no longer needed, '
             'is it deprecated and will be removed in'
             'a future version.', DeprecationWarning, stacklevel=2)
    all_models = []
    plots = []
    if isinstance(plot_objects, Sequence) and all(isinstance(x, (PlotObject, Document)) for x in plot_objects):
        divs = []
        for idx, plot_object in enumerate(plot_objects):
            elementid = str(uuid.uuid4())
            _append_plot(all_models, plots, plot_object, elementid)
            divs = _append_div(elementid, divs)
        if len(divs) == 1:
            divs = divs[0]
        else:
            divs = tuple(divs)
        return _component_pair(all_models, plots, divs)
    elif isinstance(plot_objects, dict) and all(isinstance(x, string_types) for x in plot_objects.keys()) and all(isinstance(x, (PlotObject, Document)) for x in plot_objects.values()):
        divs = {}
        for key in plot_objects.keys():
            elementid = str(uuid.uuid4())
            _append_plot(all_models, plots, plot_objects[key], elementid)
            divs = _append_div(elementid, divs, key)
        return _component_pair(all_models, plots, divs)
    else:
        raise ValueError('Input must be a PlotObject, a Sequence of PlotObjects, or a mapping of string to PlotObjects')

def _component_pair(all_models, plots, divs):
    js = PLOT_JS.render(
        all_models = serialize_json(all_models),
        plots = plots
    )
    script = PLOT_SCRIPT.render(
        plot_js = _wrap_in_function(js),
    )
    return encode_utf8(script), divs

def _append_plot(all_models, plots, plot_object, elementid):
    ref = plot_object.ref
    all_models.extend(plot_object.dump())
    plots.append({
        'modelid': ref["id"],
        'elementid': '#' + elementid,
        'modeltype': ref["type"]
    })

def _append_div(elementid, divs=None, key=None):
    div = PLOT_DIV.render(
        elementid = elementid
    )
    if isinstance(divs, list):
        divs.append(encode_utf8(div))
        return divs
    elif isinstance(divs, dict):
        divs[key] = encode_utf8(div)
        return divs
    else:
        return encode_utf8(div)

def notebook_div(plot_object):
    ''' Return HTML for a div that will display a Bokeh plot in an
    IPython Notebook

    The data for the plot is stored directly in the returned HTML.

    Args:
        plot_object (PlotObject) : Bokeh object to render
            typically a Plot or PlotContext

    Returns:
        div : UTF-8 encoded HTML text

    .. note:: Assumes ``bokeh.load_notebook()`` or the equivalent has
              already been executed.

    '''
    ref = plot_object.ref
    elementid = str(uuid.uuid4())

    js = PLOT_JS.render(
        elementid = elementid,
        modelid = ref["id"],
        modeltype = ref["type"],
        all_models = serialize_json(plot_object.dump()),
    )
    script = PLOT_SCRIPT.render(
        plot_js = _wrap_in_function(js),
    )
    div = PLOT_DIV.render(elementid=elementid)
    html = NOTEBOOK_DIV.render(
        plot_script = script,
        plot_div = div,
    )
    return encode_utf8(html)


def file_html(plot_object, resources, title, template=FILE):
    ''' Return an HTML document that embeds a Bokeh plot.

    The data for the plot is stored directly in the returned HTML.

    Args:
        plot_object (PlotObject) : Bokeh object to render
            typically a Plot or PlotContext
        resources (Resources) : a resource configuration for BokehJS assets
        title (str) : a title for the HTML document ``<title>`` tags
        template (Template, optional) : HTML document template (default: FILE)
            A Jinja2 Template, see bokeh.templates.FILE for the required
            template parameters

    Returns:
        html : standalone HTML document with embedded plot

    '''
    from .plot_object import PlotObject
    from .document import Document
    if not isinstance(plot_object, (PlotObject, Document)):
        raise ValueError('plot_object must be a single PlotObject')

    plot_resources = RESOURCES.render(
        js_raw = resources.js_raw,
        css_raw = resources.css_raw,
        js_files = resources.js_files,
{'fraction_non_alphanumeric': 0.08385813722240637, 'fraction_numerical': 0.002485913158766987, 'mean_word_length': 2.849760765550239, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6222578', 'n_tokens_mistral': 3564, 'n_tokens_neox': 3447, 'n_words': 1163}