function modify_document
Modifies a Bokeh document by executing a Python script/module within the document's context, with support for autoreload functionality and error handling.
/tf/active/vicechatdev/patches/server.py
280 - 355
complex
Purpose
This method is part of a Bokeh application handler that loads and executes Python code to populate a Bokeh document. It handles module creation, document context management, autoreload watching, and error display. The function ensures proper cleanup and error reporting when scripts fail, and supports hot-reloading of code during development.
Source Code
def modify_document(self, doc):
from bokeh.io.doc import set_curdoc as bk_set_curdoc
from ..config import config
if config.autoreload:
path = self._runner.path
argv = self._runner._argv
handler = type(self)(filename=path, argv=argv)
self._runner = handler._runner
module = self._runner.new_module()
# If no module was returned it means the code runner has some permanent
# unfixable problem, e.g. the configured source code has a syntax error
if module is None:
return
# One reason modules are stored is to prevent the module
# from being gc'd before the document is. A symptom of a
# gc'd module is that its globals become None. Additionally
# stored modules are used to provide correct paths to
# custom models resolver.
sys.modules[module.__name__] = module
doc.modules._modules.append(module)
try:
old_doc = curdoc()
except Exception:
old_doc=None
bk_set_curdoc(doc)
if config.autoreload:
set_curdoc(doc)
state.onload(autoreload_watcher)
try:
def post_check():
newdoc = curdoc()
# Do not let curdoc track modules when autoreload is enabled
# otherwise it will erroneously complain that there is
# a memory leak
if config.autoreload:
newdoc.modules._modules = []
# script is supposed to edit the doc not replace it
if newdoc is not doc:
raise RuntimeError("%s at '%s' replaced the output document" % (self._origin, self._runner.path))
def handle_exception(handler, e):
from bokeh.application.handlers.handler import handle_exception
from ..pane import HTML
# Clean up
del sys.modules[module.__name__]
if hasattr(doc, 'modules'):
doc.modules._modules.remove(module)
else:
doc._modules.remove(module)
bokeh.application.handlers.code_runner.handle_exception = handle_exception
tb = html.escape(traceback.format_exc())
# Serve error
HTML(
f'<b>{type(e).__name__}</b>: {e}</br><pre style="overflow-y: scroll">{tb}</pre>',
css_classes=['alert', 'alert-danger'], sizing_mode='stretch_width'
).servable()
if config.autoreload:
bokeh.application.handlers.code_runner.handle_exception = handle_exception
with _monkeypatch_io(self._loggers):
with patch_curdoc(doc):
self._runner.run(module, post_check)
finally:
if old_doc!=None:
bk_set_curdoc(old_doc)
Parameters
| Name | Type | Default | Kind |
|---|---|---|---|
self |
- | - | positional_or_keyword |
doc |
- | - | positional_or_keyword |
Parameter Details
self: Instance of the handler class that contains this method. Expected to have attributes: _runner (code runner with path and _argv), _origin (origin identifier), and _loggers (logging configuration).
doc: A Bokeh Document object that will be modified by the executed code. This is the target document where the application's UI components will be added.
Return Value
Returns None implicitly. The function modifies the provided 'doc' parameter in-place by executing code that adds components to it. If the module creation fails (returns None), the function returns early without modifying the document.
Dependencies
bokehparamtornadopanelflask
Required Imports
import sys
import html
import traceback
import bokeh
import bokeh.application.handlers.code_runner
from bokeh.io import curdoc
from bokeh.application.handlers.code import _monkeypatch_io, patch_curdoc
Conditional/Optional Imports
These imports are only needed under specific conditions:
from bokeh.io.doc import set_curdoc as bk_set_curdoc
Condition: Always imported at function start
Required (conditional)from ..config import config
Condition: Always imported at function start to check autoreload settings
Required (conditional)from ..reload import autoreload_watcher
Condition: Only used when config.autoreload is True
Optionalfrom ..state import state
Condition: Only used when config.autoreload is True
Optionalfrom bokeh.application.handlers.handler import handle_exception
Condition: Only imported inside exception handler when errors occur
Optionalfrom ..pane import HTML
Condition: Only imported inside exception handler to display errors
OptionalUsage Example
# This is a method of a handler class, typically used internally by Panel/Bokeh
# Example context where this would be called:
from bokeh.document import Document
from panel.io.handlers import SomeHandler # Hypothetical handler class
# Create a Bokeh document
doc = Document()
# Create handler instance (with required _runner, _origin, _loggers attributes)
handler = SomeHandler(filename='app.py', argv=[])
# Modify the document by executing the script
handler.modify_document(doc)
# The document is now populated with components from app.py
# If autoreload is enabled, changes to app.py will be detected and reloaded
Best Practices
- Ensure config.autoreload is properly set before calling this method to control hot-reload behavior
- The executed script should modify the provided document in-place, not replace it
- Handle exceptions gracefully as the function includes custom error display using HTML panes
- Be aware that modules are stored in sys.modules and doc.modules to prevent garbage collection
- When autoreload is enabled, module tracking is disabled to avoid false memory leak warnings
- The function manages curdoc() context carefully - ensure proper cleanup in calling code
- Error messages are displayed as HTML alerts with full tracebacks when execution fails
- The _runner object must be properly initialized with valid path and argv before calling
Tags
Similar Components
AI-powered semantic similarity - components with related functionality:
-
function init_doc 63.7% similar
-
function unlocked 61.0% similar
-
function autoload_js_script 60.7% similar
-
function set_curdoc 60.2% similar
-
function _eval_panel 59.5% similar