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_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_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 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)
color="primary", className="mt-4") 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)]
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)