def test_arg_dependencies(app, test_template, input_form): inputs = input_form( [ dl.Input(dcc.Slider(), label="Slider"), dl.Input(dcc.Dropdown(), label="Dropdown"), ] ) state = dl.State(dcc.Input(), label="State Input") output = dl.Output(dcc.Markdown(), "children", label="Markdown Output") # Build mock function fn = mock_fn_with_return("Hello, world") fn_wrapper = app.callback( output=output, inputs=inputs, state=state, template=test_template )(fn) # call flat version (like dash would) assert fn_wrapper._flat_fn(1, "Option", "Some Text") == ["Hello, world"] # Check how mock function was called args, kwargs = fn.call_args assert args == (1, "Option", "Some Text") assert not kwargs # Check order of dependencies assert_deps_eq(fn_wrapper._flat_input_deps, [a.dependencies() for a in inputs]) assert_deps_eq(fn_wrapper._flat_state_deps, [state.dependencies()]) assert_deps_eq(fn_wrapper._flat_output_deps, [output.dependencies()])
def test_scalar_output_arg_dependencies(app, test_template): inputs = dl.Input(html.Button(), "n_clicks") state = dl.State(dcc.Input()) output = dl.Output(dcc.DatePickerRange(), ("start_date", "end_date")) # Build mock function fn = mock_fn_with_return((datetime.date(2010, 1, 1), datetime.date(2010, 1, 10))) fn_wrapper = app.callback( output=output, inputs=inputs, state=state, template=test_template )(fn) # call flat version (like dash would) assert fn_wrapper._flat_fn(12, "Some Text") == [ datetime.date(2010, 1, 1), datetime.date(2010, 1, 10), ] # Check how mock function was called args, kwargs = fn.call_args assert args == (12, "Some Text") assert not kwargs # Check order of dependencies assert_deps_eq(fn_wrapper._flat_input_deps, [inputs.dependencies()]) assert_deps_eq(fn_wrapper._flat_state_deps, [state.dependencies()]) assert_deps_eq(fn_wrapper._flat_output_deps, list(output.dependencies()))
def test_prevent_initial_callback_passed_through(app, test_template): @app.callback( inputs=[dl.Input(dcc.Slider(min=0, max=10))], template=test_template, prevent_initial_call=False, ) def fn(a, b, c): return a + b + c # False app._callback_list[0]["prevent_initial_call"] is False @app.callback( inputs=[dl.Input(dcc.Slider(min=0, max=10))], template=test_template, prevent_initial_call=True, ) def fn(a, b, c): return a + b + c # True app._callback_list[1]["prevent_initial_call"] is False
def test_state_kwarg_only(app, test_template): state = { "test_input": dl.State(dcc.Input()), "test_slider": dl.Input(dcc.Slider()), } output = {"test_output_markdown": dl.Output(dcc.Markdown(), "children")} # Build mock function fn = mock_fn_with_return({"test_output_markdown": "Hello, world"}) fn_wrapper = app.callback(output=output, state=state, template=test_template)(fn) # call flat version (like dash would) assert fn_wrapper._flat_fn(1, "input string") == ["Hello, world"] # Check how mock function was called args, kwargs = fn.call_args assert kwargs == { "test_slider": 1, "test_input": "input string", } assert not args # Check dependencies # Input input_param_components = test_template.roles["input"] arg_component = input_param_components["test_input"].arg_component arg_props = input_param_components["test_input"].arg_property expected_deps = flat_deps(arg_component, arg_props, "state") assert isinstance(arg_component, dcc.Input) assert arg_props == "value" assert fn_wrapper._flat_state_deps[0] == expected_deps[0] # Slider input_param_components = test_template.roles["input"] arg_component = input_param_components["test_slider"].arg_component arg_props = input_param_components["test_slider"].arg_property expected_deps = flat_deps(arg_component, arg_props, "input") assert isinstance(arg_component, dcc.Slider) assert arg_props == "value" assert fn_wrapper._flat_input_deps[0] == expected_deps[0] # Markdown Output output_param_components = test_template.roles["output"] arg_component = output_param_components["test_output_markdown"].arg_component arg_props = output_param_components["test_output_markdown"].arg_property expected_deps = flat_deps(arg_component, arg_props, "output") assert isinstance(arg_component, dcc.Markdown) assert arg_props == "children" assert fn_wrapper._flat_output_deps[0] == expected_deps[0]
def wrapper(fn): def callback(__n_intervals__, *args, **kwargs): result_key = json.dumps({"args": list(args), "kwargs": kwargs}) progress_key = result_key + "-progress" result = cache.get(result_key) progress = cache.get(progress_key) if result is not None: return dict(result=result, interval_disabled=True) elif progress is not None: return dict( result=html.Progress( value=str(progress[0]), max=str(progress[1]), id=progress_id, style=progress_style, ), interval_disabled=False, ) else: target = make_update_cache(fn, cache, result_key, progress_key) p = Process(target=target, args=args, kwargs=kwargs) p.start() return dict( result=html.Progress(id=progress_id, style=progress_style), interval_disabled=False, ) interval_component = dl.Input( dcc.Interval(interval=interval, id=dl.build_id("interval")), "n_intervals", label=None, ) # Add interval component to inputs all_args = args if isinstance(all_args, dict): all_args = dict(all_args, __n_intervals__=interval_component) else: if not isinstance(all_args, (list, tuple)): all_args = [all_args] all_args = [interval_component] + all_args all_output = dict( result=dl.Output(html.Div(), "children"), interval_disabled=Output(interval_component.id, "disabled"), ) return app.callback(args=all_args, output=all_output, template=template)(callback)
def test_template_layout_generation(app, test_template): inputs = {"test_slider": dx.Input(dcc.Slider(min=0, max=10))} state = {"test_input": dx.State(dcc.Input(value="Initial input"))} output = {"test_output_markdown": dx.Output(dcc.Markdown(), "children")} # Build mock function fn = mock_fn_with_return({"test_output_markdown": "Hello, world"}) fn_wrapper = dx.callback(app, output=output, inputs=inputs, state=state, template=test_template)(fn) # Check dependencies # Slider input_param_components = test_template.roles["input"] arg_component = input_param_components["test_slider"].arg_component arg_props = input_param_components["test_slider"].arg_property assert isinstance(arg_component, dcc.Slider) assert arg_props == "value" expect_input_deps = Input(arg_component.id, "value") assert fn_wrapper._flat_input_deps[0] == expect_input_deps # Input Component as State input_param_components = test_template.roles["input"] arg_component = input_param_components["test_input"].arg_component arg_props = input_param_components["test_input"].arg_property assert isinstance(arg_component, dcc.Input) assert arg_props == "value" expect_input_deps = Input(arg_component.id, "value") assert fn_wrapper._flat_state_deps[0] == expect_input_deps # Markdown Output output_param_components = test_template.roles["output"] arg_component = output_param_components[ "test_output_markdown"].arg_component arg_props = output_param_components["test_output_markdown"].arg_property assert isinstance(arg_component, dcc.Markdown) assert arg_props == "children" expect_output_deps = Input(arg_component.id, "children") assert fn_wrapper._flat_output_deps[0] == expect_output_deps # Check generated layout layout = test_template.layout(app, full=False) check_layout_body(layout, test_template)
) yrs = df.year.unique() range_slider = dcc.RangeSlider( min=yrs[0], max=yrs[-1], step=5, marks={int(i): str(i) for i in [1952, 1962, 1972, 1982, 1992, 2007]}, value=[1982, yrs[-1]], ) # Create interaction between app components ****************************** @app.callback( dl.Input(dropdown, label="Select indicator (y-axis)"), dl.Input(checklist, label="Select continents"), dl.Input(range_slider, label="Select time period"), template=tpl, ) def update_charts(indicator, continents, years): if continents == []: return {} dff = df[df.year.between(years[0], years[1])] dff = dff[dff.continent.isin(continents)] line_fig = px.line( dff, x="year", y=indicator, color="continent",
yrs = df.year.unique() range_slider = dcc.RangeSlider( min=yrs[0], max=yrs[-1], step=5, marks={int(i): str(i) for i in [1952, 1962, 1972, 1982, 1992, 2007]}, value=[1982, yrs[-1]], ) # Create interaction between app components ****************************** @app.callback( inputs=dict( indicator=dl.Input(dropdown, label="Select indicator (y-axis)", component_property="value"), continents=dl.Input(checklist, label="Select continents", component_property="value"), years=dl.Input(range_slider, label="Select time period", component_property="value"), ), output=dict( div_content=tpl.div_output(component_property="children", role="output"), # div_content2=tpl.div_output(component_property="children", role="histogram"), ), template=tpl, )
tooltip={ "placement": "bottom", "always_visible": True }) slider2 = dcc.Slider(min=1, max=10, value=6, tooltip={ "placement": "bottom", "always_visible": True }) @app.callback( # dl.Output(html.Div(), "children"), not needed - this is implied dl.Input(dropdown, label="Function"), dl.Input(textbox, label="Figure Title"), dl.Input(slider, label="Phase"), dl.Input(slider2, label="Amplitude"), Input("themes", "value"), Input("graph_template", "value"), Input("discrete_selected", "children"), Input("checkbox", "value"), template=tpl, ) def callback( fun, figure_title, phase, amplitude, theme,
storage = dcc.Store(id="storage", storage_type="local", data={}) interval = dcc.Interval(id="timer", interval=1000 * 60, n_intervals=0) @app.callback(Output("storage", "data"), Input("timer", "n_intervals")) def store_data(n_time): dataframe = update_wb_data() return dataframe.to_dict("records") @app.callback( args=dict( stored_dataframe=Input("storage", "data"), indct_chosen=dl.State(radio_indicators, label="Select Indicators"), years_chosen=dl.State(years_slider, label="Select Years"), n_clicks=dl.Input(submit_button, "n_clicks", label=""), ), template=tpl, ) def update_graph(n_clicks, stored_dataframe, years_chosen, indct_chosen): dff = pd.DataFrame.from_records(stored_dataframe) if years_chosen[0] != years_chosen[1]: dff = dff[dff.year.between(years_chosen[0], years_chosen[1])] dff = dff.groupby(["iso3c", "country"])[indct_chosen].mean() dff = dff.reset_index() return make_figure(dff, indct_chosen) if years_chosen[0] == years_chosen[1]: dff = dff[dff["year"].isin(years_chosen)] return make_figure(dff, indct_chosen)
import dash_labs as dl import dash_html_components as html import dash app = dash.Dash(__name__, plugins=[dl.plugins.FlexibleCallbacks()]) tpl = dl.templates.DbcCard(title="Simple App", columns=6) @app.callback( dl.Input(html.Button(children="Click Me"), "n_clicks", label="Button to click"), template=tpl, ) def callback(n_clicks): return "Clicked {} times".format(n_clicks) app.layout = tpl.layout(app) if __name__ == "__main__": app.run_server(debug=True)
import dash_labs as dl import dash_html_components as html import dash app = dash.Dash(__name__, plugins=[dl.plugins.FlexibleCallbacks()]) tpl = dl.templates.DbcCard(title="Simple App", columns=4) div = html.Div() button = html.Button(children="Click Me") @app.callback(dl.Output(div, "children"), dl.Input(button, "n_clicks")) def callback(n_clicks): return "Clicked {} times".format(n_clicks) tpl.add_component(button, label="Button to click", role="input") tpl.add_component(div, role="output") app.layout = tpl.layout(app) if __name__ == "__main__": app.run_server(debug=True)
import dash import dash_labs as dl import numpy as np import dash_core_components as dcc import plotly.express as px app = dash.Dash(__name__, plugins=[dl.plugins.FlexibleCallbacks()]) phase_plugin = dl.component_plugins.DynamicLabelPlugin( dl.Input(dcc.Slider(min=1, max=10, value=4), label="Phase: {}")) phase_plugin.install_callback(app) app.layout = phase_plugin.container if __name__ == "__main__": app.run_server(debug=True)
# Load data df = px.data.iris() feature_cols = [col for col in df.columns if "species" not in col] feature_labels = [col.replace("_", " ").title() + " (cm)" for col in feature_cols] feature_options = [ {"label": label, "value": col} for col, label in zip(feature_cols, feature_labels) ] # Build app and template app = dash.Dash(__name__, plugins=[dl.plugins.FlexibleCallbacks()]) tpl = dl.templates.DbcSidebar(title="Iris Dataset") # Use parameterize to create components @app.callback( args=dict( x=dl.Input(dcc.Dropdown(options=feature_options, value="sepal_length")), y=dl.Input(dcc.Dropdown(options=feature_options, value="sepal_width")), ), template=tpl, ) def iris(x, y): return dcc.Graph( figure=px.scatter(df, x=x, y=y, color="species"), ) # Get references to the dropdowns and register a custom callback to prevent the user # from setting x and y to the same variable # Get the dropdown components that were created by parameterize x_component = tpl.roles["input"]["x"].arg_component
def check_component_props_as_groupings( app, input_grouping, state_grouping, output_grouping, template, input_form="list", output_form="list", ): # Compute grouping sizes input_size = grouping_len(input_grouping) state_size = grouping_len(state_grouping) output_size = grouping_len(output_grouping) # Make buttons input_button, input_prop = button_component_prop_for_grouping( input_grouping) state_button, state_prop = button_component_prop_for_grouping( state_grouping) output_button, output_prop = button_component_prop_for_grouping( output_grouping) # Make flat dependencies flat_input_deps = flat_deps(input_button, input_prop, "input") + make_deps( Input, 1) flat_state_deps = flat_deps(state_button, state_prop, "state") flat_output_deps = make_deps(Output, 1) + flat_deps( output_button, output_prop, "output") # Build grouped dependency lists grouped_input_deps = [ dl.Input(input_button, input_prop), flat_input_deps[-1] ] grouped_state_deps = [dl.State(state_button, state_prop)] grouped_output_deps = [ flat_output_deps[0], dl.Output(output_button, output_prop) ] # Build flat input/output values (state is part of input now) flat_input_values = (make_letters(input_size) + ["-"] + make_letters(state_size, upper=True)) flat_output_values = [-1] + list(range(5, output_size + 5)) # Build grouped input/output values (state is part of input) grouped_input_values = [ make_letters_grouping(input_grouping), "-", make_letters_grouping(state_grouping, upper=True), ] grouped_output_values = [ -1, make_numbers_grouping(output_grouping, offset=5) ] # Handle input data forms if input_form == "dict": only_input_keys = make_letters(len(grouped_input_deps), upper=True) grouped_input_deps = { k: v for k, v in zip(only_input_keys, grouped_input_deps) } state_keys = make_letters(len(grouped_state_deps), upper=False) grouped_state_deps = { k: v for k, v in zip(state_keys, grouped_state_deps) } input_value_keys = only_input_keys + state_keys grouped_input_values = { k: v for k, v in zip(input_value_keys, grouped_input_values) } if output_form == "scalar": # Remove first extra scalar value, leave only grouped value as scalar grouped_output_deps = grouped_output_deps[1] grouped_output_values = grouped_output_values[1] flat_output_values = flat_output_values[1:] flat_output_deps = flat_output_deps[1:] elif output_form == "dict": grouped_output_deps = { k: v for k, v in zip(make_letters(len(grouped_output_deps), upper=True), grouped_output_deps) } grouped_output_values = { k: v for k, v in zip( make_letters(len(grouped_output_deps), upper=True), grouped_output_values, ) } # Build mock function with grouped output as return values fn = mock_fn_with_return(grouped_output_values) # Wrap callback with grouped dependency specifications fn_wrapper = dl.callback( app, output=grouped_output_deps, inputs=grouped_input_deps, state=grouped_state_deps, template=template, )(fn) # call flat version (like dash.Dash.callback would) assert fn_wrapper._flat_fn(*flat_input_values) == flat_output_values # Check that mock function was called with expected grouped values args, kwargs = fn.call_args if input_form == "list": assert args == tuple(grouped_input_values) assert not kwargs elif input_form == "dict": assert kwargs == grouped_input_values assert not args # Check order of dependencies assert_deps_eq(fn_wrapper._flat_input_deps, flat_input_deps) assert_deps_eq(fn_wrapper._flat_state_deps, flat_state_deps) assert_deps_eq(fn_wrapper._flat_output_deps, flat_output_deps)
table_plugin = dl.component_plugins.DataTablePlugin( df=df, page_size=10, sort_mode="single", filterable=True, serverside=True, ) dropdown = dcc.Dropdown(options=[{ "label": v, "value": v } for v in ["Male", "Female"]]) @app.callback( args=[dl.Input(dropdown, "value"), table_plugin.args], output=table_plugin.output, ) def callback(gender, plugin_input): if gender: filtered_df = df.query(f"sex == {repr(gender)}") else: filtered_df = df return table_plugin.get_output_values(plugin_input, filtered_df) app.layout = html.Div([dropdown, table_plugin.container]) if __name__ == "__main__": app.run_server(debug=True)
# style_data_conditional=[ # { # 'if': { # 'column_id': 'continent', # }, # 'backgroundColor': 'dodgerblue', # 'color': 'white', # 'textAlign': 'left' # }, # ], ), ) @app.callback( dl.Input(dl_continents, label="Select continents"), dl.Input(dl_indicators, label="Select indicator (y-axis)"), dl.Input(dl_years, label="Select years"), Input("themes", "value"), Input("graph_template", "value"), Input("discrete_selected", "children"), Input("continuous_selected", "children"), Input("checkbox", "value"), output=[ tpl.graph_output(role="Line"), tpl.graph_output(role="Scatter"), tpl.div_output(role="Table"), ], template=tpl, ) def update_line_chart(
y="number_of_likes", color="name", log_y=True, labels={ "number_of_likes": "Likes", "date_time": "Date", "name": "Celebrity", }, ) return dcc.Graph(figure=fig) # Callbacks *************************************************************** @app.callback(dl.Input(dropdown), template=tpl) def update_graph(chosen_value): if len(chosen_value) == 0: raise dash.exceptions.PreventUpdate else: df_filtered = df[df["name"].isin(chosen_value)] return make_graph((df_filtered)) # Layout ****************************************************************** tpl.add_component(twitter_link, role="output", after=0) app.layout = tpl.layout(app) if __name__ == "__main__": app.run_server(debug=True)
@app.callback( Output("interval", "interval"), Output("interval", "disabled"), Input("follow_me_interval", "value"), ) def update_interval(time): disabled = True if time == 0 else False return time, disabled @app.callback( dl.Output(html.Div(), "children"), dl.Output(html.Div(), "children"), dl.Input(options_checklist, label=""), dl.Input(zoom_center, label="Zoom and Center"), dl.Input(geolocation, ("local_date", "timestamp", "position", "position_error"), label=""), prevent_initial_call=True, template=tpl, ) def display_output(checklist, zoom, location_data): date, timestamp, pos, err = location_data if err: return f"Error {err['code']} : {err['message']}", dash.no_update # update message show_address = True if checklist and "address" in checklist else False position = (make_position_card(pos, date, show_address)