def BokehApplication(applications, server, prefix="/", template_variables={}): prefix = "/" + prefix.strip("/") + "/" if prefix else "/" extra = {"prefix": prefix, **template_variables} funcs = {k: functools.partial(v, server, extra) for k, v in applications.items()} apps = {k: Application(FunctionHandler(v)) for k, v in funcs.items()} kwargs = dask.config.get("distributed.scheduler.dashboard.bokeh-application").copy() extra_websocket_origins = create_hosts_allowlist( kwargs.pop("allow_websocket_origin"), server.http_server.port ) return BokehTornado( apps, prefix=prefix, use_index=False, extra_websocket_origins=extra_websocket_origins, **kwargs, )
def test_request_server_info(self): application = Application() with ManagedServerLoop(application) as server: session = ClientSession(session_id='test_request_server_info', websocket_url=ws_url(server), io_loop=server.io_loop) session.connect() assert session.connected assert session.document is None info = session.request_server_info() from bokeh import __version__ assert info['version_info']['bokeh'] == __version__ assert info['version_info']['server'] == __version__ session.close() session.loop_until_closed(suppress_warning=True) assert not session.connected
def __spawn_server(self): bslg = logging.getLogger('bokeh.server.util') bsll = bslg.getEffectiveLevel() bslg.setLevel(logging.ERROR) self._server_info['application'] = app = Application( FunctionHandler(self.__entry_point)) app.add(BokehSessionHandler()) self._server_info['server'] = srv = Server( {'/': app}, io_loop=IOLoop.instance(), port=0, allow_websocket_origin=['*']) self._server_info['server_id'] = srv_id = uuid4().hex curstate().uuid_to_server[srv_id] = srv srv_addr = srv.address if srv.address else socket.gethostbyname( socket.gethostname()) self._server_info['server_url'] = 'http://{}:{}/'.format( srv_addr, srv.port) srv.start() bslg.setLevel(bsll)
def test_request_server_info(self, ManagedServerLoop: MSL) -> None: application = Application() with ManagedServerLoop(application) as server: session = ClientSession(session_id=ID("test_request_server_info"), websocket_url=ws_url(server), io_loop=server.io_loop) session.connect() assert session.connected assert session.document is None info = session.request_server_info() from bokeh import __version__ assert info['version_info']['bokeh'] == __version__ assert info['version_info']['server'] == __version__ session.close() session._loop_until_closed() assert not session.connected
async def test__use_provided_session_autoload_token(ManagedServerLoop) -> None: application = Application() with ManagedServerLoop(application) as server: sessions = server.get_sessions('/') assert 0 == len(sessions) expected = 'foo' expected_token = generate_jwt_token(expected) response = await http_get( server.io_loop, autoload_url(server) + "&bokeh-token=" + expected_token) js = response.body token = extract_token_from_json(js) assert expected_token == token sessionid = get_session_id(token) assert expected == sessionid sessions = server.get_sessions('/') assert 1 == len(sessions) assert expected == sessions[0].id
def launch_server(): context = zmq.Context() origins = ["localhost:{}".format(5006)] apps = {'/': Application(FunctionHandler(partial(make_document, context)))} server = Server(apps, port=5006) server.start() print('Opening Bokeh application on:') for entry in origins: print('\thttp://{}/'.format(entry)) try: server.io_loop.start() except KeyboardInterrupt: print("terminating") server.io_loop.stop()
def main(): curDir = os.path.dirname(__file__) plotData = pd.read_csv(os.path.join(curDir, 'test.csv')) """Launch the server and connect to it. """ global x_values, y_values x_values = plotData['Area'].values y_values = plotData['% of F'].values print("Preparing a bokeh application.") io_loop = IOLoop.current() bokeh_app = Application(FunctionHandler( modify_doc)) server = Server({"/": bokeh_app}, io_loop=io_loop) server.start() print("Opening Bokeh application on http://localhost:5006/") io_loop.add_callback(server.show, "/") io_loop.start()
def test_websocket_origins(): application = Application() with ManagedServerLoop(application) as server: assert server._tornado.websocket_origins == set(["localhost:5006"]) # OK this is a bit of a confusing mess. The user-facing arg for server is # "allow_websocket_origin" which gets converted to "extra_websocket_origins" # for BokehTornado, which is exposed as a property "websocket_origins"... with ManagedServerLoop(application, allow_websocket_origin=["foo"]) as server: assert server._tornado.websocket_origins == set(["foo:80"]) with ManagedServerLoop(application, allow_websocket_origin=["foo:8080"]) as server: assert server._tornado.websocket_origins == set(["foo:8080"]) with ManagedServerLoop(application, allow_websocket_origin=["foo:8080", "bar"]) as server: assert server._tornado.websocket_origins == set(["foo:8080", "bar:80"])
def test_host_whitelist_failure(self): application = Application() # failure bad host with ManagedServerLoop(application, host=["bad_host"]) as server: session = ClientSession(websocket_url=ws_url(server), io_loop = server.io_loop) session.connect() assert not session.connected session.close() session.loop_until_closed() with ManagedServerLoop(application, host=["bad_host:5006"]) as server: session = ClientSession(websocket_url=ws_url(server), io_loop = server.io_loop) session.connect() assert not session.connected session.close() session.loop_until_closed() # failure good host, bad port with ManagedServerLoop(application, host=["localhost:80"]) as server: session = ClientSession(websocket_url=ws_url(server), io_loop = server.io_loop) session.connect() assert not session.connected session.close() session.loop_until_closed() # failure good host, bad default port with ManagedServerLoop(application, host=["localhost"]) as server: session = ClientSession(websocket_url=ws_url(server), io_loop = server.io_loop) session.connect() assert not session.connected session.close() session.loop_until_closed() # failure with custom port with ManagedServerLoop(application, port=8080, host=["localhost:8081"]) as server: session = ClientSession(websocket_url=ws_url(server), io_loop = server.io_loop) session.connect() assert not session.connected session.close() session.loop_until_closed()
def test_host_whitelist_success(self): application = Application() # succeed no host value with defaults with ManagedServerLoop(application, host=None) as server: session = ClientSession(websocket_url=ws_url(server), io_loop=server.io_loop) session.connect() assert session.connected session.close() session.loop_until_closed() # succeed no host value with port with ManagedServerLoop(application, port=8080, host=None) as server: session = ClientSession(websocket_url=ws_url(server), io_loop=server.io_loop) session.connect() assert session.connected session.close() session.loop_until_closed() # succeed matching host value with ManagedServerLoop(application, port=8080, host=["localhost:8080"]) as server: session = ClientSession(websocket_url=ws_url(server), io_loop=server.io_loop) session.connect() assert session.connected session.close() session.loop_until_closed() # succeed matching host value one of multiple with ManagedServerLoop(application, port=8080, host=["bad_host", "localhost:8080"]) as server: session = ClientSession(websocket_url=ws_url(server), io_loop=server.io_loop) session.connect() assert session.connected session.close() session.loop_until_closed()
def run_server(queue, start_signal, port, db_options): """ Setup and run a server creating und continuously updating a dashboard. The main building of the dashboard is done in run_dashboard. Here this function is only turned into an Application and run in a server. Args: queue (Queue): queue to which originally the parameters DataFrame is supplied and to which later the updated parameter Series will be supplied. start_signal (Queue): empty queue. The minimization starts once it stops being empty. port (int): port at which to display the dashboard. db_options (dict): dictionary with options. see ``run_dashboard`` for details. """ db_options = _process_db_options(db_options) asyncio.set_event_loop(asyncio.new_event_loop()) apps = { "/": Application( FunctionHandler( partial( run_dashboard, queue=queue, db_options=db_options, start_signal=start_signal, ))) } server = _setup_server(apps, port) server._loop.start() server.start()
def start(self): def plotter(doc): # Base data x = [item['x'] for item in self.data] y = [item['y'] for item in self.data] ds = ColumnDataSource(data=dict(x=x, y=y)) def update_plot(): new = {} if len(self.data): new = { 'x': [self.data[-1]['x']], 'y': [self.data[-1]['y']] } last = {} if len(ds.data['x']): last = {'x': [ds.data['x'][-1]], 'y': [ds.data['y'][-1]]} if new != last: print('Displaying new data') ds.stream(new) p = figure(plot_width=1200, plot_height=400) p.line('x', 'y', color="firebrick", line_width=2, source=ds) doc.add_periodic_callback(update_plot, 1000) doc.add_root(p) io_loop = IOLoop.current() bokeh_app = Application(FunctionHandler(plotter)) server = Server({'/': bokeh_app}, io_loop=io_loop, host="*") server.start() print('Opening Bokeh application on http://localhost:5006/') io_loop.add_callback(server.show, '/') io_loop.start()
def main(): # parse command line arguments args = parse_args() # set the logger log = logging.getLogger("dashmd") log.setLevel(loglevel.get(args.log)) log.debug(f"Set log level to '{args.log}'") os.environ['BOKEH_PY_LOG_LEVEL'] = dashmd_loglevel_to_bokeh.get(args.log) os.environ['BOKEH_LOG_LEVEL'] = dashmd_loglevel_to_bokeh.get(args.log) log.debug( f"Set Bokeh log level to '{dashmd_loglevel_to_bokeh.get(args.log)}'") # start the server try: log.debug("Preparing the Bokeh server") # create tornado IO loop io_loop = IOLoop.current() # force bokeh to load resources from CDN (quick fix, not working with bokeh 1.4.0) os.environ['BOKEH_RESOURCES'] = 'cdn' # create app app_dir = os.path.dirname(os.path.realpath(__file__)) bokeh_app = Application( DirectoryHandler(filename=app_dir, argv=[args.default_dir, args.update, args.port])) # create server server = Server( {'/': bokeh_app}, io_loop=io_loop, port=args.port, num_procs=1, allow_websocket_origin=[f'localhost:{args.port}'], ) except OSError: log.error( f"[ERROR] Port {args.port} is already in use. Please specify a different one by using the --port flag." ) sys.exit(1) server.start() log.info(f"Opening DashMD on http://localhost:{args.port}") server.io_loop.add_callback(server.show, "/") server.io_loop.start()
def _try_start_web_server(self): static_path = os.path.join(os.path.dirname(__file__), 'static') handlers = dict() for p, h in _bokeh_apps.items(): handlers[p] = Application( FunctionHandler(functools.partial(h, self._scheduler_ip))) handler_kwargs = {'scheduler_ip': self._scheduler_ip} extra_patterns = [('/static/(.*)', BokehStaticFileHandler, { 'path': static_path })] for p, h in _web_handlers.items(): extra_patterns.append((p, h, handler_kwargs)) retrial = 5 while retrial: try: if self._port is None: use_port = get_next_port() else: use_port = self._port self._server = Server( handlers, allow_websocket_origin=['*'], address=self._host, port=use_port, extra_patterns=extra_patterns, http_server_kwargs={'max_buffer_size': 2**32}, ) self._server.start() self._port = use_port logger.info('Mars UI started at %s:%d', self._host, self._port) break except OSError: if self._port is not None: raise retrial -= 1 if retrial == 0: raise
def test_host_whitelist_success(self): application = Application() # succeed no host value with defaults with ManagedServerLoop(application, host=None) as server: self.check_http_ok_socket_ok(server) # succeed no host value with port with ManagedServerLoop(application, port=8080, host=None) as server: self.check_http_ok_socket_ok(server) # succeed matching host value with ManagedServerLoop(application, port=8080, host=["localhost:8080"]) as server: self.check_http_ok_socket_ok(server) # succeed matching host value one of multiple with ManagedServerLoop(application, port=8080, host=["bad_host", "localhost:8080"]) as server: self.check_http_ok_socket_ok(server)
def _run_server(fnc_make_document, iplot=True, notebook_url="localhost:8889", port=80, ioloop=None): """Runs a Bokeh webserver application. Documents will be created using fnc_make_document""" handler = FunctionHandler(fnc_make_document) app = Application(handler) if iplot and 'ipykernel' in sys.modules: show(app, notebook_url=notebook_url) else: apps = {'/': app} print(f"Open your browser here: http://localhost:{port}") server = Server(apps, port=port, io_loop=ioloop) if ioloop is None: server.run_until_shutdown() else: server.start() ioloop.start()
def finalize(self): """Finalize the link. :returns: status code of finalization :rtype: StatusCode """ # --- any code to finalize the link follows here from bokeh.server.server import Server from bokeh.application import Application from bokeh.application.handlers.function import FunctionHandler apps = {"/": Application(FunctionHandler(self._doc_factory))} server = Server(applications=apps, port=5000) server.io_loop.add_callback(server.show, "/") try: server.io_loop.start() except KeyboardInterrupt: return StatusCode.Success
def test_launch_server_with_complex_plot(self): dmap = DynamicMap(lambda x_range, y_range: Curve([]), streams=[RangeXY()]) overlay = dmap * HLine(0) static = Polygons([]) * Path([]) * Curve([]) layout = overlay + static launched = [] def modify_doc(doc): bokeh_renderer(layout, doc=doc) launched.append(True) server.stop() handler = FunctionHandler(modify_doc) app = Application(handler) server = Server({'/': app}, port=0) server.start() url = "http://localhost:" + str(server.port) + "/" pull_session(session_id='Test', url=url, io_loop=server.io_loop) self.assertTrue(len(launched) == 1)
def build_single_handler_application(path, argv=None): ''' Return a Bokeh application built using a single handler for a file or directory. Args: path (str) : path to a file or directory for creating a Bokeh application. argv (seq[str], optional) : command line arguments to pass to the application handler Returns: Application Raises: RuntimeError ''' argv = argv or [] path = os.path.abspath(path) if os.path.isdir(path): handler = DirectoryHandler(filename=path, argv=argv) else: if path.endswith(".ipynb"): handler = NotebookHandler(filename=path, argv=argv) elif path.endswith(".py"): if path.endswith("main.py"): warnings.warn(DIRSTYLE_MAIN_WARNING) handler = ScriptHandler(filename=path, argv=argv) else: raise ValueError( "Expected a '.py' script or '.ipynb' notebook, got: '%s'" % path) if handler.failed: raise RuntimeError("Error loading %s:\n\n%s\n%s " % (path, handler.error, handler.error_detail)) application = Application(handler) return application
def test_io_push_to_server(self): from bokeh.io import output_server, push, curdoc, reset_output application = Application() with ManagedServerLoop(application) as server: reset_output() doc = curdoc() doc.clear() client_root = SomeModelInTestClientServer(foo=42) session_id = 'test_io_push_to_server' output_server(session_id=session_id, url=("http://localhost:%d/" % server.port)) doc.add_root(client_root) push(io_loop=server.io_loop) server_session = server.get_session('/', session_id) print(repr(server_session.document.roots)) assert len(server_session.document.roots) == 1 server_root = next(iter(server_session.document.roots)) assert client_root.foo == 42 assert server_root.foo == 42 # Now modify the client document and push client_root.foo = 57 push(io_loop=server.io_loop) server_root = next(iter(server_session.document.roots)) assert server_root.foo == 57 # Remove a root and push doc.remove_root(client_root) push(io_loop=server.io_loop) assert len(server_session.document.roots) == 0 # Clean up global IO state reset_output()
def _run_server(fnc_make_document, notebook_url='localhost:8889', iplot=True, ioloop=None, address='localhost', port=8889, autostart=False): ''' Runs a Bokeh webserver application. Documents will be created using fnc_make_document ''' handler = FunctionHandler(fnc_make_document) app = Application(handler) ipython = iplot and 'ipykernel' in sys.modules if ipython: try: get_ipython except: ipython = False if ipython: show(app, notebook_url=notebook_url) # noqa else: apps = {'/': app} if autostart: print(f'Browser is launching at: http://localhost:{port}') view(f'http://localhost:{port}') else: print(f'Open browser at: http://localhost:{port}') server = Server(apps, port=port, allow_websocket_origin=[address], io_loop=ioloop) if ioloop is None: server.run_until_shutdown() else: server.start() ioloop.start()
def show(self, notebook_url=None, port=0, remake_layout=False, verbose=False): """ Show the app in a jupyter notebook. Parameters ---------- notebook_url : str, optional The URL of the notebook. Will be determined automatically if not specified. port : int, default 0 The port over which the app will be served. Chosen randomly if set to 0. remake_layout : bool, default False If True, call ``make_layout`` even when the layout has already been created. Note that any changes made by ``modify_figures`` will be omitted. verbose : bool, default False If True, create the document once again outside of show_app in order to show errors. """ if notebook_url is None: notebook_url = get_notebook_url() output_notebook(hide_banner=True) if verbose: self.make_layout() Application(FunctionHandler(self._modify_doc)).create_document() if self.layout is None or remake_layout or verbose: self.make_layout() show(self._modify_doc, None, notebook_url=notebook_url, port=port)
def test_websocket_origins(ManagedServerLoop, unused_tcp_port) -> None: application = Application() with ManagedServerLoop(application, port=unused_tcp_port) as server: assert server._tornado.websocket_origins == { "localhost:%s" % unused_tcp_port } # OK this is a bit of a confusing mess. The user-facing arg for server is # "allow_websocket_origin" which gets converted to "extra_websocket_origins" # for BokehTornado, which is exposed as a property "websocket_origins"... with ManagedServerLoop(application, allow_websocket_origin=["foo"]) as server: assert server._tornado.websocket_origins == {"foo:80"} with ManagedServerLoop(application, allow_websocket_origin=["foo:8080"]) as server: assert server._tornado.websocket_origins == {"foo:8080"} with ManagedServerLoop(application, allow_websocket_origin=["foo:8080", "bar"]) as server: assert server._tornado.websocket_origins == {"foo:8080", "bar:80"}
def figure(ip, directory, model) -> None: """Start bokeh server with the file passed.""" # pylint: disable=import-outside-toplevel from bokeh.server.server import Server from bokeh.application import Application from bokeh.application.handlers.function import FunctionHandler from .figures.interactive_config import make_document # pylint: enable=import-outside-toplevel if isinstance(ip, str): ip = (ip,) if directory: directory = Path(directory) make_document = partial(make_document, directory=directory, models=model) apps = {"/": Application(FunctionHandler(make_document))} server = Server(apps, allow_websocket_origin=list(ip)) server.run_until_shutdown() logger.info("Bokeh server terminated.")
def start_bokeh_server(): """ Create and start a bokeh server with a series of applications. """ # Declare the absolute path to the demo application. demo_path = os.path.abspath("project/server/bokeh_apps/bokehDemo") # Declare the dictionary of applications to launch. apps = { '/bokehDemo': Application(DirectoryHandler(filename=demo_path)), } # Instantiate the Bokeh server. # Allow connections from the Flask application. server = Server( applications=apps, allow_websocket_origin=["127.0.0.1:5000"], # port=5006 ) server.start() server.io_loop.start()
def test_host_whitelist_failure(self): application = Application() # failure bad host with ManagedServerLoop(application, host=["bad_host"]) as server: self.check_http_blocked_socket_blocked(server) with ManagedServerLoop(application, host=["bad_host:5006"]) as server: self.check_http_blocked_socket_blocked(server) # failure good host, bad port with ManagedServerLoop(application, host=["localhost:80"]) as server: self.check_http_blocked_socket_blocked(server) # failure good host, bad default port with ManagedServerLoop(application, host=["localhost"]) as server: self.check_http_blocked_socket_blocked(server) # failure with custom port with ManagedServerLoop(application, port=8080, host=["localhost:8081"]) as server: self.check_http_blocked_socket_blocked(server)
def test__ioloop_not_forcibly_stopped(): # Issue #5494 application = Application() loop = IOLoop() loop.make_current() server = Server(application, ioloop=loop) server.start() result = [] def f(): server.unlisten() server.stop() # If server.stop() were to stop the Tornado IO loop, # g() wouldn't be called and `result` would remain empty. loop.add_timeout(timedelta(seconds=0.01), g) def g(): result.append(None) loop.stop() loop.add_callback(f) loop.start() assert result == [None]
def add_app(self, uri, makefn): """ Adds an app to the server the app is a standard :class:`bokeh.application.application.Application` that is created by passing either an arbitrary makefunction (see :class:`bokeh.application.handlers.function.FunctionHandler`), or a :class:`BokehDash` object (which implements the same make function as the make_doc method). Args: uri: The URI to serve the app on (e.g. '/dash', or '/' or ...) makefn: The app to add (can be either a BokehDash app, or an arbitrary user-define app maker function. If you are implementing arbitrary app-maker ensure it follows the format required by :class:`bokeh.application.handlers.function.FunctionHandler` Returns: """ if isinstance(makefn, BokehDash): makefn = makefn.make_doc elif not callable(makefn): raise Error("App must either be of type BokehDash (i.e. with a make_doc method), or a callable") self._apps[uri] = Application(FunctionHandler(makefn))
def run_server( cell_stack, input_data, port=5000, markers=None, default_cell_marker=None, server_kwargs={}, ): print(server_kwargs) apps = { "/": Application( FunctionHandler( partial( prepare_server, cell_stack=cell_stack, input_data=input_data, cell_markers=markers, default_cell_marker=default_cell_marker, ))) } server = Server(apps, port=port, **server_kwargs) server.run_until_shutdown()
def test_default_resources(ManagedServerLoop) -> None: application = Application() with ManagedServerLoop(application) as server: r = server._tornado.resources() assert r.mode == "server" assert r.root_url == "" assert r.path_versioner == StaticHandler.append_version with ManagedServerLoop(application, prefix="/foo/") as server: r = server._tornado.resources() assert r.mode == "server" assert r.root_url == "/foo/" assert r.path_versioner == StaticHandler.append_version with ManagedServerLoop(application, prefix="foo/") as server: r = server._tornado.resources() assert r.mode == "server" assert r.root_url == "/foo/" assert r.path_versioner == StaticHandler.append_version with ManagedServerLoop(application, prefix="foo") as server: r = server._tornado.resources() assert r.mode == "server" assert r.root_url == "/foo/" assert r.path_versioner == StaticHandler.append_version with ManagedServerLoop(application, prefix="/foo") as server: r = server._tornado.resources() assert r.mode == "server" assert r.root_url == "/foo/" assert r.path_versioner == StaticHandler.append_version with ManagedServerLoop(application, prefix="/foo/bar") as server: r = server._tornado.resources() assert r.mode == "server" assert r.root_url == "/foo/bar/" assert r.path_versioner == StaticHandler.append_version