import asyncio import json import pyodide import os from js import JSON import param from bokeh import __version__ from bokeh.document import Document from bokeh.embed.util import standalone_docs_json from bokeh.protocol.messages.patch_doc import process_document_events from . import resources resources.RESOURCE_MODE = 'CDN' os.environ['BOKEH_RESOURCES'] = 'cdn' def async_execute(func): event_loop = asyncio.get_running_loop() if event_loop.is_running(): event_loop.call_soon(func) else: event_loop.run_until_complete(func()) return param.parameterized.async_executor = async_execute def serve(*args, **kwargs): """ Stub to replace Tornado based serve function. """ raise RuntimeError('Cannot serve application in pyodide context.') def _doc_json(model, target): doc = Document() model.server_doc(doc=doc) model = doc.roots[0] docs_json = standalone_docs_json([model]) doc_json = list(docs_json.values())[0] root_id = doc_json['roots']['root_ids'][0] return doc, json.dumps(dict( target_id = target, root_id = root_id, doc = doc_json, version = __version__, )) def _link_docs(pydoc, jsdoc): def jssync(event): if (getattr(event, 'setter_id', None) is not None): return events = [event] json_patch = jsdoc.create_json_patch_string(pyodide.to_js(events)) pydoc.apply_json_patch(json.loads(json_patch)) jsdoc.on_change(pyodide.create_proxy(jssync), pyodide.to_js(False)) def pysync(event): json_patch, buffers = process_document_events([event], use_buffers=True) buffer_map = {} for (ref, buffer) in buffers: buffer_map[ref['id']] = buffer jsdoc.apply_json_patch(JSON.parse(json_patch), pyodide.to_js(buffer_map), setter_id='js') pydoc.on_change(pysync) async def show(obj, target): """ Renders the object into a DOM node specified by the target. Arguments --------- obj: Viewable Object to render into the DOM node target: str Target ID of the DOM node to render the object into. """ from js import Bokeh from ..pane import panel as as_panel obj = as_panel(obj) pydoc, model_json = _doc_json(obj, target) views = await Bokeh.embed.embed_item(JSON.parse(model_json)) jsdoc = views[0].model.document _link_docs(pydoc, jsdoc)