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.append(module) old_doc = curdoc() bk_set_curdoc(doc) old_io = self._monkeypatch_io() if config.autoreload: set_curdoc(doc) state.onload(autoreload_watcher) try: def post_check(): newdoc = curdoc() # 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__] 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 self._runner.run(module, post_check) finally: self._unmonkeypatch_io(old_io) bk_set_curdoc(old_doc)
def modify_document(self, doc): from bokeh.io.doc import set_curdoc as bk_set_curdoc from ..config import config logger.info(LOG_SESSION_LAUNCHING, id(doc)) 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) old_doc = curdoc() bk_set_curdoc(doc) if config.autoreload: set_curdoc(doc) state.onload(autoreload_watcher) sessions = [] 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 state._launching.append(doc) with _monkeypatch_io(self._loggers): with patch_curdoc(doc): with profile_ctx(config.profiler) as sessions: self._runner.run(module, post_check) def _log_session_destroyed(session_context): logger.info(LOG_SESSION_DESTROYED, id(doc)) doc.on_session_destroyed(_log_session_destroyed) finally: state._launching.remove(doc) if config.profiler: try: path = doc.session_context.request.path state._profiles[(path, config.profiler)] += sessions state.param.trigger('_profiles') except Exception: pass bk_set_curdoc(old_doc)