def test_inin_024_port_env_success(dash_duo): app = Dash(__name__) app.layout = html.Div("hi", "out") dash_duo.start_server(app, port="12345") assert dash_duo.server_url == "http://localhost:12345" dash_duo.wait_for_text_to_equal("#out", "hi")
# This Code was written by Ann Marie - a Plotly Forum Moderator from dash import Dash, dcc, html, Input, Output, dash_table, no_update # Dash version >= 2.0.0 import plotly.express as px external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css'] app = Dash(__name__, external_stylesheets=external_stylesheets) df = px.data.gapminder() df["id"] = df.index # print(df.head(15)) dff = df[df.year == 2007] columns = ["country", "continent", "lifeExp", "pop", "gdpPercap"] color = {"lifeExp": "#636EFA", "pop": "#EF553B", "gdpPercap": "#00CC96"} initial_active_cell = { "row": 0, "column": 0, "column_id": "country", "row_id": 0 } app.layout = html.Div([ html.Div([ html.H3("2007 Gap Minder", style={"textAlign": "center"}), dash_table.DataTable( id="table", columns=[{ "name": c, "id": c } for c in columns], data=dff.to_dict("records"),
def test_clsd011_clientside_callback_context_inputs_list(dash_duo): app = Dash(__name__, assets_folder="clientside_assets") app.layout = html.Div([ html.Button("btn0", id="btn0"), html.Button("btn1:0", id={"btn1": 0}), html.Button("btn1:1", id={"btn1": 1}), html.Button("btn1:2", id={"btn1": 2}), html.Div(id="output-clientside", style={"font-family": "monospace"}), ]) app.clientside_callback( ClientsideFunction(namespace="clientside", function_name="inputs_list_to_str"), Output("output-clientside", "children"), [Input("btn0", "n_clicks"), Input({"btn1": ALL}, "n_clicks")], ) class DashView(BaseDashView): dash = app dash_duo.start_server(DashView) dash_duo.wait_for_text_to_equal( "#output-clientside", ('[{"id":"btn0","property":"n_clicks"},' '[{"id":{"btn1":0},"property":"n_clicks"},' '{"id":{"btn1":1},"property":"n_clicks"},' '{"id":{"btn1":2},"property":"n_clicks"}]]'), ) dash_duo.find_element("#btn0").click() dash_duo.wait_for_text_to_equal( "#output-clientside", ('[{"id":"btn0","property":"n_clicks","value":1},' '[{"id":{"btn1":0},"property":"n_clicks"},' '{"id":{"btn1":1},"property":"n_clicks"},' '{"id":{"btn1":2},"property":"n_clicks"}]]'), ) dash_duo.find_element("button[id*='btn1\":0']").click() dash_duo.find_element("button[id*='btn1\":0']").click() dash_duo.wait_for_text_to_equal( "#output-clientside", ('[{"id":"btn0","property":"n_clicks","value":1},' '[{"id":{"btn1":0},"property":"n_clicks","value":2},' '{"id":{"btn1":1},"property":"n_clicks"},' '{"id":{"btn1":2},"property":"n_clicks"}]]'), ) dash_duo.find_element("button[id*='btn1\":2']").click() dash_duo.wait_for_text_to_equal( "#output-clientside", ('[{"id":"btn0","property":"n_clicks","value":1},' '[{"id":{"btn1":0},"property":"n_clicks","value":2},' '{"id":{"btn1":1},"property":"n_clicks"},' '{"id":{"btn1":2},"property":"n_clicks","value":1}]]'), )
# flask run import inspect, os #os.environ["FLASK_APP"] = inspect.getfile(inspect.currentframe()) os.environ[ "OCTAVE_EXECUTABLE"] = "C:\\Octave\\Octave-4.2.2\\bin\\octave-cli.exe" from oct2py import octave from flask import Flask from dash import Dash from dash.dependencies import Input, Output import dash_html_components as html import dash_core_components as dcc flask_app = Flask(__name__) dash_app = Dash(__name__, server=flask_app) filepath = 'C:\\Users\\SEC\\Documents\\Alperia\\HydroptModel\\vsm.mod' octave.eval("load('" + filepath + "', '-mat')") globalData = octave.pull('Data') dash_app.layout = html.Div(id='page-content', children=[dcc.Location(id='url', refresh=False)]) @dash_app.callback(Output('page-content', 'children'), [Input('url', 'pathname')]) def display_page(pathname): return dash_router(pathname)
import os import pandas as pd from flask import Flask from dash import Dash, dcc from flask_sqlalchemy import SQLAlchemy import plotly.graph_objects as go from utils import stancecolormap, stancemap app = Flask(__name__) dashapp = Dash(__name__, server=app, url_base_pathname='/plots/') app.config.from_object(os.environ['APP_SETTINGS']) db = SQLAlchemy(app) custom_font = dict(family="Courier New, monospace", size=14, color="#000000") df = pd.read_pickle('preds.pkl')[:10000] fig = go.Figure( data=[ go.Scatter(x=df['h_pos'][df['actual'] == stance], y=df['v_pos'][df['actual'] == stance], mode='markers', marker_color=stancecolormap.get(stance), opacity=0.6, name=stance) for stance in sorted(stancemap.keys(), reverse=True) ], layout=go.Layout( # title='Stances', margin=go.layout.Margin(l=0, r=0, b=8, t=8), autosize=True, plot_bgcolor="rgba(0, 10, 25, 0.3)",
def Add_Dash(server): """Create a Dash app.""" external_stylesheets = [ '/static/dist/css/styles.css', 'https://fonts.googleapis.com/css?family=Lato', 'https://use.fontawesome.com/releases/v5.8.1/css/all.css' ] external_scripts = [ '/static/dist/js/includes/jquery.min.js', '/static/dist/js/main.js' ] dash_app = Dash(server=server, external_stylesheets=external_stylesheets, external_scripts=external_scripts, routes_pathname_prefix='/followers/') # Override the underlying HTML template dash_app.index_string = html_layout # Add Cassandra Queries and Parameters # Pass this as a dictionary of parameters, hidden in a function x_name = 'timestamp' y_name = 'follower_count' cluster = Cluster(['10.0.0.5', '10.0.0.7', '10.0.0.12', '10.0.0.19']) session = cluster.connect() session.set_keyspace('insight') session.row_factory = lambda x, y: pd.DataFrame(y, columns=x) session.default_fetch_size = 100000 prepared_query_youtube_live = session.prepare( "select timestamp, follower_count from youtube_live " "where streamer=?") prepared_query_twitter_live = session.prepare( "select timestamp, follower_count from twitter_live " "where streamer=?") prepared_query_twitch_live = session.prepare( "select timestamp, follower_count from twitch_live " "where streamer=?") prepared_query_day = session.prepare( "select timestamp, twitch_count, twitter_count, youtube_count, total_count " "from unified_day where streamer=?") prepared_query_hour = session.prepare( "select timestamp, twitch_count, twitter_count, youtube_count, total_count " "from unified_hour where streamer=?") prepared_query_minute = session.prepare( "select timestamp, twitch_count, twitter_count, youtube_count, total_count " "from unified_minute where streamer=?") prepared_query_accounts = session.prepare( "select streamer from insight.accounts;") # Get streamers names, and prepare the dropdown options streamers = session.execute(prepared_query_accounts)._current_rows dropdown_options = [{ 'label': streamer, 'value': streamer } for streamer in streamers.streamer] # Create Dash Layout comprised of Graphs dash_app.layout = html.Div(children=get_followers(dropdown_options), id='dash-container') # Initialize callbacks after our app is loaded # Pass dash_app as a parameter init_callbacks(dash_app, session, x_name, y_name, prepared_query_day, prepared_query_hour, prepared_query_minute, prepared_query_youtube_live, prepared_query_twitter_live, prepared_query_twitch_live) return dash_app.server
def test_rdrh001_request_hooks(dash_duo): app = Dash(__name__) app.index_string = """<!DOCTYPE html> <html> <head> {%metas%} <title>{%title%}</title> {%favicon%} {%css%} </head> <body> <div id="top">Testing custom DashRenderer</div> {%app_entry%} <footer> {%config%} {%scripts%} <script id="_dash-renderer" type"application/json"> const renderer = new DashRenderer({ request_pre: (payload) => { var output = document.getElementById('output-pre') var outputPayload = document.getElementById('output-pre-payload') if(output) { output.innerHTML = 'request_pre changed this text!'; } if(outputPayload) { outputPayload.innerHTML = JSON.stringify(payload); } }, request_post: (payload, response) => { var output = document.getElementById('output-post') var outputPayload = document.getElementById('output-post-payload') var outputResponse = document.getElementById('output-post-response') if(output) { output.innerHTML = 'request_post changed this text!'; } if(outputPayload) { outputPayload.innerHTML = JSON.stringify(payload); } if(outputResponse) { outputResponse.innerHTML = JSON.stringify(response); } } }) </script> </footer> <div id="bottom">With request hooks</div> </body> </html>""" app.layout = html.Div([ dcc.Input(id="input", value="initial value"), html.Div( html.Div([ html.Div(id="output-1"), html.Div(id="output-pre"), html.Div(id="output-pre-payload"), html.Div(id="output-post"), html.Div(id="output-post-payload"), html.Div(id="output-post-response"), ])), ]) @app.callback(Output("output-1", "children"), [Input("input", "value")]) def update_output(value): return value dash_duo.start_server(app) _in = dash_duo.find_element("#input") dash_duo.clear_input(_in) _in.send_keys("fire request hooks") dash_duo.wait_for_text_to_equal("#output-1", "fire request hooks") dash_duo.wait_for_text_to_equal("#output-pre", "request_pre changed this text!") dash_duo.wait_for_text_to_equal("#output-post", "request_post changed this text!") assert json.loads(dash_duo.find_element("#output-pre-payload").text) == { "output": "output-1.children", "outputs": { "id": "output-1", "property": "children" }, "changedPropIds": ["input.value"], "inputs": [{ "id": "input", "property": "value", "value": "fire request hooks" }], } assert json.loads(dash_duo.find_element("#output-post-payload").text) == { "output": "output-1.children", "outputs": { "id": "output-1", "property": "children" }, "changedPropIds": ["input.value"], "inputs": [{ "id": "input", "property": "value", "value": "fire request hooks" }], } assert json.loads(dash_duo.find_element("#output-post-response").text) == { "output-1": { "children": "fire request hooks" } } assert dash_duo.find_element("#top").text == "Testing custom DashRenderer" assert dash_duo.find_element("#bottom").text == "With request hooks" assert dash_duo.get_logs() == []
import dash_html_components as html import dash_core_components as dcc from flask import Flask from dash import Dash from flask_sqlalchemy import SQLAlchemy # initialize flask app APP = Flask(__name__) APP.config["SQLALCHEMY_DATABASE_URI"] = config("DATABASE_URL") # initialize dash, for visualizations DASH = Dash( __name__, server=APP, external_stylesheets=[ "/css/style.css", ], url_base_pathname="/plot/", ) DASH.layout = html.Div( [ dcc.Location(id="url", refresh=False), dcc.Graph(id="main-graph", style={ "height": "100%", "width": "100%" }), ], id="page-content", style={ "height": "100%", "width": "100%"
from dash import Dash from dash.components import * from userguide import app, const dash = Dash(server=app, url_namespace='/{}'.format(const['text-input'])) dash.layout = div( [div(id="app"), hr(), Highlight(id="code", className="python")], className="container") app_template = '''from dash import Dash from dash.components import * {} dash = Dash(__name__) dash.layout = {} {} if __name__ == "__main__": dash.server.run(debug=True) ''' preamble = '''import pandas as pd import pandas_datareader.data as web import datetime as dt import traceback # list of tickers
def test_dada002_external_files_init(dash_duo): js_files = [ "https://www.google-analytics.com/analytics.js", {"src": "https://cdn.polyfill.io/v2/polyfill.min.js"}, { "src": "https://cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.min.js", "integrity": "sha256-43x9r7YRdZpZqTjDT5E0Vfrxn1ajIZLyYWtfAXsargA=", "crossorigin": "anonymous", }, { "src": "https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js", "integrity": "sha256-7/yoZS3548fXSRXqc/xYzjsmuW3sFKzuvOCHd06Pmps=", "crossorigin": "anonymous", }, ] css_files = [ "https://codepen.io/chriddyp/pen/bWLwgP.css", { "href": "https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css", "rel": "stylesheet", "integrity": "sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO", "crossorigin": "anonymous", }, ] app = Dash(__name__, external_scripts=js_files, external_stylesheets=css_files) app.index_string = """<!DOCTYPE html> <html> <head> {%metas%} <title>{%title%}</title> {%css%} </head> <body> <div id="tested"></div> <div id="ramda-test"></div> <button type="button" id="btn">Btn</button> {%app_entry%} <footer> {%config%} {%scripts%} {%renderer%} </footer> </body> </html>""" app.layout = html.Div() dash_duo.start_server(app) js_urls = [x["src"] if isinstance(x, dict) else x for x in js_files] css_urls = [x["href"] if isinstance(x, dict) else x for x in css_files] for fmt, url in itertools.chain( (("//script[@src='{}']", x) for x in js_urls), (("//link[@href='{}']", x) for x in css_urls), ): dash_duo.driver.find_element_by_xpath(fmt.format(url)) assert ( dash_duo.find_element("#btn").value_of_css_property("height") == "18px" ), "Ensure the button style was overloaded by reset (set to 38px in codepen)" # ensure ramda was loaded before the assets so they can use it. assert dash_duo.find_element("#ramda-test").text == "Hello World"
from dash import Dash import dash_core_components as dcc import dash_html_components as html import plotly.express as px import pandas as pd df = px.data.iris() fig = px.scatter(df, x="sepal_width", y="sepal_length", color="species", size='petal_length', hover_data=['petal_width']) #simulates two different dash apps #requests pathname prefix tells the dash renderer where to look and request data #dummy app 1 app1 = Dash(__name__, requests_pathname_prefix='/app1/') app1.layout = html.Div([html.H1('App 1'), dcc.Graph(id='id', figure=fig)]) if __name__ == '__main__': app1.run_server(debug=True)
return content regions = { 'world': {'lat': 0, 'lon': 0, 'zoom': 1}, 'europe': {'lat': 50, 'lon': 0, 'zoom': 3}, 'north_america': {'lat': 40, 'lon': -100, 'zoom': 2}, 'south_america': {'lat': -15, 'lon': -60, 'zoom': 2}, 'africa': {'lat': 0, 'lon': 20, 'zoom': 2}, 'asia': {'lat': 30, 'lon': 100, 'zoom': 2}, 'oceania': {'lat': -10, 'lon': 130, 'zoom': 2}, } app_name = 'Real-time Global Earthquake Data Map' server = Flask(app_name) server.secret_key = os.environ.get('SECRET_KEY', 'default-secret-key') app = Dash(name=app_name, server=server) app.index_string = ''' <!DOCTYPE html> <html> <head> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"> {%metas%} <title>HalcyonAgri Digitization Dashboard | Real-time Global Earthquake Data Map</title> {%favicon%} {%css%} </head> <body> <nav class="navbar navbar-inverse"> <div class="container-fluid"> <div class="navbar-header">
# -*- coding: utf-8 -*- from dash import Dash from flask import Flask, send_from_directory server = Flask(__package__) # load default settings server.config.from_object(f'{__package__}.settings') # load additional settings that will override the defaults in settings.py. eg # $ export SLAPDASH_SETTINGS=/some/path/prod_settings.py server.config.from_envvar('HVODASH_SETTINGS', silent=True) app = Dash( __package__, server=server, # url_base_pathname=server.config['URL_BASE_PATHNAME'] ) # We need to suppress validations as we will be initialising callbacks # that target element IDs that won't yet occur in the layout. app.config.supress_callback_exceptions = True app.config.update({ 'routes_pathname_prefix': '/', 'requests_pathname_prefix': '/dash/' }) @server.route('/favicon.ico') def favicon(): """Serve the favicon"""
def test_inin026_graphs_in_tabs_do_not_share_state(dash_duo): app = Dash(__name__, suppress_callback_exceptions=True) app.layout = html.Div([ dcc.Tabs( id="tabs", children=[ dcc.Tab(label="Tab 1", value="tab1", id="tab1"), dcc.Tab(label="Tab 2", value="tab2", id="tab2"), ], value="tab1", ), # Tab content html.Div(id="tab_content"), ]) tab1_layout = [ html.Div([ dcc.Graph( id="graph1", figure={ "data": [{ "x": [1, 2, 3], "y": [5, 10, 6], "type": "bar" }] }, ) ]), html.Pre(id="graph1_info"), ] tab2_layout = [ html.Div([ dcc.Graph( id="graph2", figure={ "data": [{ "x": [4, 3, 2], "y": [5, 10, 6], "type": "bar" }] }, ) ]), html.Pre(id="graph2_info"), ] @app.callback(Output("graph1_info", "children"), Input("graph1", "clickData")) def display_hover_data(hover_data): return json.dumps(hover_data) @app.callback(Output("graph2_info", "children"), Input("graph2", "clickData")) def display_hover_data_2(hover_data): return json.dumps(hover_data) @app.callback(Output("tab_content", "children"), Input("tabs", "value")) def render_content(tab): return tab2_layout if tab == "tab2" else tab1_layout dash_duo.start_server(app) dash_duo.find_element("#graph1:not(.dash-graph--pending)").click() until(lambda: '"label": 2' in dash_duo.find_element("#graph1_info").text, timeout=3) dash_duo.find_element("#tab2").click() dash_duo.find_element("#graph2:not(.dash-graph--pending)").click() until(lambda: '"label": 3' in dash_duo.find_element("#graph2_info").text, timeout=3)
# Prepare static data to load into application # Realtime data please refer to https://dash.plot.ly/live-updates # Iframe https://community.plot.ly/t/embedding-dash-into-webpage/10645/3 # cavity,clashdiff,hbond,localclash,sbond,sbridge,Mean,SD # CSS external_stylesheets = [ 'https://codepen.io/chriddyp/pen/bWLwgP.css', '/static/main.css' ] # Setting up flask server and dash applications server = flask.Flask(__name__) dash_app1 = Dash(__name__, server=server, url_base_pathname='/leaderboard', external_stylesheets=external_stylesheets) dash_app2 = Dash(__name__, server=server, url_base_pathname='/orderbook', external_stylesheets=external_stylesheets) dash_app1.layout = html.Div(children=[ html.H1(children='Hello Dash'), html.Div(children=''' Dash: A web application framework for Python. '''), dcc.Graph(id='example-graph', figure={ 'data': [ {
url_base_pathname = '/publisher-dash' external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css'] # dash-leaflet uses it external_scripts = ['https://cdnjs.cloudflare.com/ajax/libs/chroma-js/2.1.0/chroma.min.js'] server = Flask(__name__) @server.route('/') def index(): # redirect from `/` to `url_base_pathname` return redirect(f'{url_base_pathname}') @server.route('/<bad_link>') def redirect_to_index(bad_link): # if the user types an invalid link, then it redirects him to `url_base_pathname` return redirect(f'{url_base_pathname}') app = Dash( __name__, server=server, external_stylesheets=external_stylesheets, external_scripts=external_scripts, suppress_callback_exceptions=True, url_base_pathname='{}/'.format(url_base_pathname) )
def test_cbmt011_callbacks_triggered_on_generated_output(dash_duo): app = Dash(__name__, suppress_callback_exceptions=True) call_counts = {"tab1": Value("i", 0), "tab2": Value("i", 0)} app.layout = html.Div([ dcc.Dropdown( id="outer-controls", options=[{ "label": i, "value": i } for i in ["a", "b"]], value="a", ), dcc.RadioItems( options=[ { "label": "Tab 1", "value": 1 }, { "label": "Tab 2", "value": 2 }, ], value=1, id="tabs", ), html.Div(id="tab-output"), ]) @app.callback(Output("tab-output", "children"), Input("tabs", "value")) def display_content(value): return html.Div([html.Div(id="tab-{}-output".format(value))]) @app.callback(Output("tab-1-output", "children"), Input("outer-controls", "value")) def display_tab1_output(value): call_counts["tab1"].value += 1 return 'Selected "{}" in tab 1'.format(value) @app.callback(Output("tab-2-output", "children"), Input("outer-controls", "value")) def display_tab2_output(value): call_counts["tab2"].value += 1 return 'Selected "{}" in tab 2'.format(value) dash_duo.start_server(app) dash_duo.wait_for_text_to_equal("#tab-output", 'Selected "a" in tab 1') dash_duo.wait_for_text_to_equal("#tab-1-output", 'Selected "a" in tab 1') assert call_counts["tab1"].value == 1 assert call_counts["tab2"].value == 0 dash_duo.find_elements('input[type="radio"]')[1].click() dash_duo.wait_for_text_to_equal("#tab-output", 'Selected "a" in tab 2') dash_duo.wait_for_text_to_equal("#tab-2-output", 'Selected "a" in tab 2') assert call_counts["tab1"].value == 1 assert call_counts["tab2"].value == 1 assert not dash_duo.get_logs()
def Add_Dash(server): app = Dash(server=server, url_base_pathname=_URL_BASE) pgdb = create_engine(get_postgres_sqlalchemy_uri()) apply_layout_with_auth(app, layout) @app.callback([ Output('sensitivities-date-dropdown', 'options'), Output('sensitivities-date-dropdown', 'value') ], [Input('account-dropdown', 'value')]) def update_date_dropdowns(account_value): statement = text(""" select distinct model_date from {}.ltv_model_sensitivities order by model_date; """.format(account_value)) with pgdb.connect() as con: rs = con.execute(statement) data = rs.fetchall() data = [{ 'label': datetime.strftime(d[0], "%Y-%m-%d"), 'value': datetime.strftime(d[0], "%Y-%m-%d") } for d in data] default = data[0]['value'] return [data, default] @app.callback([ Output('ltv-metrics-model-type-dropdown', 'options'), Output('ltv-metrics-model-type-dropdown', 'value') ], [Input('account-dropdown', 'value')]) def update_ltv_metrics_model_type_dropdown(account_value): statement = text(""" select distinct model_type from {}.ltv_model_metrics; """.format(account_value)) with pgdb.connect() as con: rs = con.execute(statement) data = rs.fetchall() data = [{'label': d[0], 'value': d[0]} for d in data] print(data) default = data[0]['value'] return [data, default] @app.callback(Output('ltv-metrics-graph', 'figure'), [ Input('account-dropdown', 'value'), Input('ltv-metrics-model-type-dropdown', 'value') ]) def get_ltv_metrics_graph(account_value, model_type): statement = text(""" select * from {}.ltv_model_metrics where model_type='{}' order by model_type, model_date """.format(account_value, model_type)) with pgdb.connect() as con: rs = con.execute(statement) data = rs.fetchall() keys = rs.keys() df = pd.DataFrame(data, columns=keys) df = pd.melt(df, id_vars=['model_date', 'model_type'], value_vars=['precision', 'recall', 'accuracy', 'auc']) df = df.rename(columns={'variable': 'metric'}) fig = px.scatter( df, x='model_date', y='value', color='metric', ) for d in fig.data: d.update(mode='markers+lines') return fig @app.callback(Output('ltv-sensitivities-table', 'data'), [ Input('account-dropdown', 'value'), Input('sensitivities-date-dropdown', 'value') ]) def get_ltv_sensitivities_table(account_value, sensitivity_date): statement = text(""" select category, category_value, category_count, ROUND(sensitivity::numeric, 3) sensitivity, model_type, model_date from {}.ltv_model_sensitivities where model_date = '{}' """.format( account_value, sensitivity_date)) # assume already ordered by batch process with pgdb.connect() as con: rs = con.execute(statement) data = rs.fetchall() keys = rs.keys() df = pd.DataFrame(data, columns=keys) print(df) return df.to_dict(orient='records') return app.server
def test_rdrh003_refresh_jwt(dash_duo): app = Dash(__name__) app.index_string = """<!DOCTYPE html> <html> <head> {%metas%} <title>{%title%}</title> {%favicon%} {%css%} </head> <body> <div>Testing custom DashRenderer</div> {%app_entry%} <footer> {%config%} {%scripts%} <script id="_dash-renderer" type"application/json"> const renderer = new DashRenderer({ request_refresh_jwt: (old_token) => { console.log("refreshing token", old_token); var new_token = "." + (old_token || ""); var output = document.getElementById('output-token') if(output) { output.innerHTML = new_token; } return new_token; } }) </script> </footer> <div>With request hooks</div> </body> </html>""" app.layout = html.Div([ dcc.Input(id="input", value="initial value"), html.Div( html.Div([html.Div(id="output-1"), html.Div(id="output-token")])), ]) @app.callback(Output("output-1", "children"), [Input("input", "value")]) def update_output(value): return value required_jwt_len = 0 # test with an auth layer that requires a JWT with a certain length def protect_route(func): @functools.wraps(func) def wrap(*args, **kwargs): try: if flask.request.method == "OPTIONS": return func(*args, **kwargs) token = ( flask.request.authorization or flask.request.headers.environ.get("HTTP_AUTHORIZATION")) if required_jwt_len and (not token or len(token) != required_jwt_len + len("Bearer ")): # Read the data to prevent bug with base http server. flask.request.get_json(silent=True) flask.abort(401, description="JWT Expired " + str(token)) except HTTPException as e: return e return func(*args, **kwargs) return wrap # wrap all API calls with auth. for name, method in ((x, app.server.view_functions[x]) for x in app.routes if x in app.server.view_functions): app.server.view_functions[name] = protect_route(method) dash_duo.start_server(app) _in = dash_duo.find_element("#input") dash_duo.clear_input(_in) required_jwt_len = 1 _in.send_keys("fired request") dash_duo.wait_for_text_to_equal("#output-1", "fired request") dash_duo.wait_for_text_to_equal("#output-token", ".") required_jwt_len = 2 dash_duo.clear_input(_in) _in.send_keys("fired request again") dash_duo.wait_for_text_to_equal("#output-1", "fired request again") dash_duo.wait_for_text_to_equal("#output-token", "..") assert len(dash_duo.get_logs()) == 2
# Run this app with `python app.py` and # visit http://127.0.0.1:8050/ in your web browser. from dash import Dash, html, dcc import plotly.express as px import pandas as pd import math from dash.dependencies import Input, Output, State app = Dash(__name__) colors = { 'background': '#111111', 'text': '#FFFFFF' } # assume you have a "long-form" data frame # see https://plotly.com/python/px-arguments/ for more options o1 = 0.1 o2 = 0.15 k1 = 0.05 k2 = 0.056 df = pd.DataFrame({ "t": [], "x": [], "y": [], "wav": [] })
import requests from dash import Dash from dash.components import * from userguide import app, const dash = Dash(server=app, url_namespace='') dash.layout = div([ h1('dash'), blockquote(''' dash is a framework for creating interactive web-applications in pure python.'''), h3('quickstart'), Highlight('\n'.join([ '$ pip install dash.ly --upgrade', '$ git clone -b skeleton https://github.com/chriddyp/messin.git', '$ cd messin', '$ pip install -r requirements.txt', '$ cd helloworld', '$ python helloworld.py', ' * Running on http://127.0.0.1:8080/ (Press CTRL+C to quit)']), className="bash"), hr(), div(className="row", content=[
def test_cbsc004_callback_using_unloaded_async_component(dash_duo): app = Dash() app.layout = html.Div( [ dcc.Tabs( [ dcc.Tab("boo!"), dcc.Tab( dash_table.DataTable( id="table", columns=[{"id": "a", "name": "A"}], data=[{"a": "b"}], ) ), ] ), html.Button("Update Input", id="btn"), html.Div("Hello", id="output"), html.Div(id="output2"), ] ) @app.callback( Output("output", "children"), [Input("btn", "n_clicks")], [State("table", "data")], ) def update_out(n_clicks, data): return json.dumps(data) + " - " + str(n_clicks) @app.callback( Output("output2", "children"), [Input("btn", "n_clicks")], [State("table", "derived_viewport_data")], ) def update_out2(n_clicks, data): return json.dumps(data) + " - " + str(n_clicks) dash_duo.start_server(app) dash_duo.wait_for_text_to_equal("#output", '[{"a": "b"}] - None') dash_duo.wait_for_text_to_equal("#output2", "null - None") dash_duo.find_element("#btn").click() dash_duo.wait_for_text_to_equal("#output", '[{"a": "b"}] - 1') dash_duo.wait_for_text_to_equal("#output2", "null - 1") dash_duo.find_element(".tab:not(.tab--selected)").click() dash_duo.wait_for_text_to_equal("#table th", "A") # table props are in state so no change yet dash_duo.wait_for_text_to_equal("#output2", "null - 1") # repeat a few times, since one of the failure modes I saw during dev was # intermittent - but predictably so? for i in range(2, 10): expected = '[{"a": "b"}] - ' + str(i) dash_duo.find_element("#btn").click() dash_duo.wait_for_text_to_equal("#output", expected) # now derived props are available dash_duo.wait_for_text_to_equal("#output2", expected) assert dash_duo.get_logs() == []
def test_cbmt004_chain_with_sliders(MULTI, dash_duo): app = Dash(__name__) app.layout = html.Div( [ html.Button("Button", id="button"), html.Div( [ html.Label(id="label1"), dcc.Slider(id="slider1", min=0, max=10, value=0), ] ), html.Div( [ html.Label(id="label2"), dcc.Slider(id="slider2", min=0, max=10, value=0), ] ), ] ) if MULTI: @app.callback( [Output("slider1", "value"), Output("slider2", "value")], [Input("button", "n_clicks")], ) def update_slider_vals(n): if not n: raise PreventUpdate return n, n else: @app.callback(Output("slider1", "value"), [Input("button", "n_clicks")]) def update_slider1_val(n): if not n: raise PreventUpdate return n @app.callback(Output("slider2", "value"), [Input("button", "n_clicks")]) def update_slider2_val(n): if not n: raise PreventUpdate return n @app.callback(Output("label1", "children"), [Input("slider1", "value")]) def update_slider1_label(val): return "Slider1 value {}".format(val) @app.callback(Output("label2", "children"), [Input("slider2", "value")]) def update_slider2_label(val): return "Slider2 value {}".format(val) dash_duo.start_server(app) dash_duo.wait_for_text_to_equal("#label1", "") dash_duo.wait_for_text_to_equal("#label2", "") dash_duo.find_element("#button").click() dash_duo.wait_for_text_to_equal("#label1", "Slider1 value 1") dash_duo.wait_for_text_to_equal("#label2", "Slider2 value 1") dash_duo.find_element("#button").click() dash_duo.wait_for_text_to_equal("#label1", "Slider1 value 2") dash_duo.wait_for_text_to_equal("#label2", "Slider2 value 2")
def test_cbsc008_wildcard_prop_callbacks(dash_duo): lock = Lock() app = Dash(__name__) app.layout = html.Div( [ dcc.Input(id="input", value="initial value"), html.Div( html.Div( [ 1.5, None, "string", html.Div( id="output-1", **{"data-cb": "initial value", "aria-cb": "initial value"}, ), ] ) ), ] ) input_call_count = Value("i", 0) percy_enabled = Value("b", False) def snapshot(name): percy_enabled.value = os.getenv("PERCY_ENABLE", "") != "" dash_duo.percy_snapshot(name=name) percy_enabled.value = False @app.callback(Output("output-1", "data-cb"), [Input("input", "value")]) def update_data(value): with lock: if not percy_enabled.value: input_call_count.value += 1 return value @app.callback(Output("output-1", "children"), [Input("output-1", "data-cb")]) def update_text(data): return data dash_duo.start_server(app) dash_duo.wait_for_text_to_equal("#output-1", "initial value") snapshot("wildcard-callback-1") input1 = dash_duo.find_element("#input") dash_duo.clear_input(input1) for key in "hello world": with lock: input1.send_keys(key) dash_duo.wait_for_text_to_equal("#output-1", "hello world") snapshot("wildcard-callback-2") # an initial call, one for clearing the input # and one for each hello world character assert input_call_count.value == 2 + len("hello world") assert not dash_duo.get_logs()
def test_rddd001_initial_state(dash_duo): app = Dash(__name__) my_class_attrs = { "id": "p.c.4", "className": "my-class", "title": "tooltip", "style": {"color": "red", "fontSize": 30}, } # fmt:off app.layout = html.Div([ 'Basic string', 3.14, True, None, html.Div('Child div with basic string', **my_class_attrs), html.Div(id='p.c.5'), html.Div([ html.Div('Grandchild div', id='p.c.6.p.c.0'), html.Div([ html.Div('Great grandchild', id='p.c.6.p.c.1.p.c.0'), 3.14159, 'another basic string' ], id='p.c.6.p.c.1'), html.Div([ html.Div( html.Div([ html.Div([ html.Div( id='p.c.6.p.c.2.p.c.0.p.c.p.c.0.p.c.0' ), '', html.Div( id='p.c.6.p.c.2.p.c.0.p.c.p.c.0.p.c.2' ) ], id='p.c.6.p.c.2.p.c.0.p.c.p.c.0') ], id='p.c.6.p.c.2.p.c.0.p.c'), id='p.c.6.p.c.2.p.c.0' ) ], id='p.c.6.p.c.2') ], id='p.c.6') ]) # fmt:on dash_duo.start_server(app) dash_duo.wait_for_text_to_equal(r"#p\.c\.5", "") # Note: this .html file shows there's no undo/redo button by default with open( os.path.join(os.path.dirname(__file__), "initial_state_dash_app_content.html") ) as fp: expected_dom = BeautifulSoup(fp.read().strip(), "lxml") fetched_dom = dash_duo.dash_outerhtml_dom assert ( fetched_dom.decode() == expected_dom.decode() ), "the fetching rendered dom is expected" assert dash_duo.get_logs() == [], "Check that no errors or warnings were displayed" assert dash_duo.driver.execute_script( "return JSON.parse(JSON.stringify(window.store.getState().layout))" ) == json.loads( json.dumps(app.layout, cls=plotly.utils.PlotlyJSONEncoder) ), "the state layout is identical to app.layout" r = requests.get("{}/_dash-dependencies".format(dash_duo.server_url)) assert r.status_code == 200 assert r.json() == [], "no dependencies present in app as no callbacks are defined" paths = dash_duo.redux_state_paths assert paths["objs"] == {} assert paths["strs"] == { abbr: [ int(token) if token in string.digits else token.replace("p", "props").replace("c", "children") for token in abbr.split(".") ] for abbr in ( child.get("id") for child in fetched_dom.find(id="react-entry-point").findChildren(id=True) ) }, "paths should reflect to the component hierarchy" assert not dash_duo.redux_state_is_loading, "no callback => no pendingCallbacks" assert dash_duo.get_logs() == [], "console has no errors"
def test_cbsc014_multiple_properties_update_at_same_time_on_same_component(dash_duo): call_count = Value("i", 0) timestamp_1 = Value("d", -5) timestamp_2 = Value("d", -5) percy_enabled = Value("b") def snapshot(name): percy_enabled.value = os.getenv("PERCY_ENABLE", "") != "" dash_duo.percy_snapshot(name=name) percy_enabled.value = False app = Dash(__name__) app.layout = html.Div( [ html.Div(id="container"), html.Button("Click", id="button-1", n_clicks=0, n_clicks_timestamp=-1), html.Button("Click", id="button-2", n_clicks=0, n_clicks_timestamp=-1), ] ) @app.callback( Output("container", "children"), Input("button-1", "n_clicks"), Input("button-1", "n_clicks_timestamp"), Input("button-2", "n_clicks"), Input("button-2", "n_clicks_timestamp"), ) def update_output(n1, t1, n2, t2): if not percy_enabled.value: call_count.value += 1 timestamp_1.value = t1 timestamp_2.value = t2 return "{}, {}".format(n1, n2) dash_duo.start_server(app) dash_duo.wait_for_text_to_equal("#container", "0, 0") assert timestamp_1.value == -1 assert timestamp_2.value == -1 assert call_count.value == 1 snapshot("Dash button-1 initialization 1") dash_duo.find_element("#button-1").click() dash_duo.wait_for_text_to_equal("#container", "1, 0") assert timestamp_1.value > ((time.time() - (24 * 60 * 60)) * 1000) assert timestamp_2.value == -1 assert call_count.value == 2 snapshot("Dash button-1 click") prev_timestamp_1 = timestamp_1.value dash_duo.find_element("#button-2").click() dash_duo.wait_for_text_to_equal("#container", "1, 1") assert timestamp_1.value == prev_timestamp_1 assert timestamp_2.value > ((time.time() - 24 * 60 * 60) * 1000) assert call_count.value == 3 snapshot("Dash button-2 click") prev_timestamp_2 = timestamp_2.value dash_duo.find_element("#button-2").click() dash_duo.wait_for_text_to_equal("#container", "1, 2") assert timestamp_1.value == prev_timestamp_1 assert timestamp_2.value > prev_timestamp_2 assert timestamp_2.value > timestamp_1.value assert call_count.value == 4 snapshot("Dash button-2 click again")
from flask import Flask from dash import Dash import dash_bootstrap_components as dbc from dashapp.util.show_docs import docs from dashapp.api.yahoo.routes import yahoo from dashapp.api.sel.banks.util.get_env import get_env server = Flask(__name__,template_folder='./templates') # Hide Selenium API for heroku if get_env() not in ["production"]: from dashapp.api.sel.chrome_headless import sel server.register_blueprint(sel) server.register_blueprint(docs) server.register_blueprint(yahoo) # Add auth eventually https://dash.plot.ly/authentication from os import environ # Only used for CI if environ.get('DASH_SUPPRESS') is not None: app = Dash(server=server, suppress_callback_exceptions=True, external_stylesheets=[dbc.themes.BOOTSTRAP]) else: app = Dash(server=server, external_stylesheets=[dbc.themes.BOOTSTRAP])
def test_cbsc002_callbacks_generating_children(dash_duo): """Modify the DOM tree by adding new components in the callbacks.""" # some components don't exist in the initial render app = Dash(__name__, suppress_callback_exceptions=True) app.layout = html.Div( [dcc.Input(id="input", value="initial value"), html.Div(id="output")] ) @app.callback(Output("output", "children"), [Input("input", "value")]) def pad_output(input): return html.Div( [ dcc.Input(id="sub-input-1", value="sub input initial value"), html.Div(id="sub-output-1"), ] ) call_count = Value("i", 0) @app.callback(Output("sub-output-1", "children"), [Input("sub-input-1", "value")]) def update_input(value): call_count.value = call_count.value + 1 return value dash_duo.start_server(app) dash_duo.wait_for_text_to_equal("#sub-output-1", "sub input initial value") assert call_count.value == 1, "called once at initial stage" pad_input, pad_div = dash_duo.dash_innerhtml_dom.select_one( "#output > div" ).contents assert ( pad_input.attrs["value"] == "sub input initial value" and pad_input.attrs["id"] == "sub-input-1" ) assert pad_input.name == "input" assert ( pad_div.text == pad_input.attrs["value"] and pad_div.get("id") == "sub-output-1" ), "the sub-output-1 content reflects to sub-input-1 value" dash_duo.percy_snapshot(name="callback-generating-function-1") paths = dash_duo.redux_state_paths assert paths["objs"] == {} assert paths["strs"] == { "input": ["props", "children", 0], "output": ["props", "children", 1], "sub-input-1": [ "props", "children", 1, "props", "children", "props", "children", 0, ], "sub-output-1": [ "props", "children", 1, "props", "children", "props", "children", 1, ], }, "the paths should include these new output IDs" # editing the input should modify the sub output dash_duo.find_element("#sub-input-1").send_keys("deadbeef") # the total updates is initial one + the text input changes dash_duo.wait_for_text_to_equal( "#sub-output-1", pad_input.attrs["value"] + "deadbeef" ) assert not dash_duo.redux_state_is_loading, "loadingMap is empty" dash_duo.percy_snapshot(name="callback-generating-function-2") assert dash_duo.get_logs() == [], "console is clean"
def test_clsd002_chained_serverside_clientside_callbacks(dash_duo): app = Dash(__name__, assets_folder="clientside_assets") app.layout = html.Div([ html.Label("x"), dcc.Input(id="x", value=3), html.Label("y"), dcc.Input(id="y", value=6), # clientside html.Label("x + y (clientside)"), dcc.Input(id="x-plus-y"), # server-side html.Label("x+y / 2 (serverside)"), dcc.Input(id="x-plus-y-div-2"), # server-side html.Div([ html.Label("Display x, y, x+y/2 (serverside)"), dcc.Textarea(id="display-all-of-the-values"), ]), # clientside html.Label("Mean(x, y, x+y, x+y/2) (clientside)"), dcc.Input(id="mean-of-all-values"), ]) app.clientside_callback( ClientsideFunction("clientside", "add"), Output("x-plus-y", "value"), [Input("x", "value"), Input("y", "value")], ) call_counts = {"divide": Value("i", 0), "display": Value("i", 0)} @app.callback(Output("x-plus-y-div-2", "value"), [Input("x-plus-y", "value")]) def divide_by_two(value): call_counts["divide"].value += 1 return float(value) / 2.0 @app.callback( Output("display-all-of-the-values", "value"), [ Input("x", "value"), Input("y", "value"), Input("x-plus-y", "value"), Input("x-plus-y-div-2", "value"), ], ) def display_all(*args): call_counts["display"].value += 1 return "\n".join([str(a) for a in args]) app.clientside_callback( ClientsideFunction("clientside", "mean"), Output("mean-of-all-values", "value"), [ Input("x", "value"), Input("y", "value"), Input("x-plus-y", "value"), Input("x-plus-y-div-2", "value"), ], ) class DashView(BaseDashView): dash = app dash_duo.start_server(DashView) test_cases = [ ["#x", "3"], ["#y", "6"], ["#x-plus-y", "9"], ["#x-plus-y-div-2", "4.5"], ["#display-all-of-the-values", "3\n6\n9\n4.5"], ["#mean-of-all-values", str((3 + 6 + 9 + 4.5) / 4.0)], ] for selector, expected in test_cases: dash_duo.wait_for_text_to_equal(selector, expected) assert call_counts["display"].value == 1 assert call_counts["divide"].value == 1 x_input = dash_duo.wait_for_element_by_css_selector("#x") x_input.send_keys("1") test_cases = [ ["#x", "31"], ["#y", "6"], ["#x-plus-y", "37"], ["#x-plus-y-div-2", "18.5"], ["#display-all-of-the-values", "31\n6\n37\n18.5"], ["#mean-of-all-values", str((31 + 6 + 37 + 18.5) / 4.0)], ] for selector, expected in test_cases: dash_duo.wait_for_text_to_equal(selector, expected) assert call_counts["display"].value == 2 assert call_counts["divide"].value == 2
dbc.Col([ html.H2("Graph"), dcc.Graph(figure={"data": [{ "x": [1, 2, 3], "y": [1, 4, 9] }]}), ]), ]) ], className="mt-4", ) _layout = html.Div([_navbar, _body]) class DemoLayoutPage: def for_path(self, component): return _layout if __name__ == "__main__": app = Dash( __name__, external_stylesheets=[ "https://stackpath.bootstrapcdn.com/bootstrap/" "4.1.3/css/bootstrap.min.css" ], ) app.layout = _layout app.run_server(port=8888, debug=True)