def test_gene002_arbitrary_resources(dash_duo): app = Dash(__name__) app.layout = Div([Button(id="btn"), Div(id="container")]) @app.callback(Output("container", "children"), [Input("btn", "n_clicks")]) def update_container(n_clicks): if n_clicks is None: raise PreventUpdate return StyledComponent(id="styled", value="Styled", style={"font-family": "godfather"}) dash_duo.start_server(app) assert (dash_duo.driver.execute_script( "return document.fonts.check('1em godfather')") is False) dash_duo.wait_for_element("#btn").click() assert dash_duo.wait_for_element("#styled").text == "Styled" WebDriverWait(dash_duo.driver, 10).until( lambda _: dash_duo.driver.execute_script( "return document.fonts.check('1em godfather')") is True, ) dash_duo.percy_snapshot(name="gene002-arbitrary-resource")
def test_szng004_on_focus(test, props, data_fn): app = dash.Dash(__name__) baseProps1 = get_props(data_fn=data_fn) baseProps2 = get_props(data_fn=data_fn) baseProps1.update(dict(**props, id="table1")) baseProps2.update(dict(**props, id="table2")) app.layout = Div( [ DataTable(**baseProps1), DataTable(**baseProps2), ] ) test.start_server(app) table2 = test.table("table2") for i in range(len(baseProps1.get("columns"))): table2.cell(0, i).click() t1 = test.driver.find_element_by_css_selector("#table1") t2 = test.driver.find_element_by_css_selector("#table2") cells_are_same_width(t1, t1) cells_are_same_width(t1, t2) assert test.get_log_errors() == []
def get_app(): app = dash.Dash(__name__) columns = [{"name": i, "id": i} for i in ["a", "b"]] data = [dict(a=1, b=2), dict(a=11, b=22)] app.layout = Div( [ Button(id="clear-table", children=["Clear table"]), DataTable(id="table", columns=columns, data=data), ] ) @app.callback( [Output("table", "data"), Output("table", "columns")], [Input("clear-table", "n_clicks")], ) def clear_table(n_clicks): if n_clicks is None: raise PreventUpdate nonlocal columns, data return (data, columns) if n_clicks % 2 == 0 else (None, None) return app
def szng003_on_prop_change_impl( test, fixed_columns, fixed_rows, merge_duplicate_headers, callback_props ): props = {**base_props, **fixed_columns, **fixed_rows, **merge_duplicate_headers} table = DataTable(**props, id="table") app = dash.Dash(__name__) app.layout = Div([Button(id="btn", children=["Update"]), table]) @app.callback( [Output("table", key) for key in callback_props.keys()], [Input("btn", "n_clicks")], prevent_initial_call=True, ) def callback(n_clicks): return [callback_props.get(key) for key in callback_props.keys()] test.start_server(app) target = test.driver.find_element_by_css_selector("#table") cells_are_same_width(target, target) test.driver.find_element_by_css_selector("#btn").click() cells_are_same_width(target, target) assert test.get_log_errors() == []
def test_gene001_simple_callback(dash_duo): app = Dash(__name__) app.layout = Div( [ # Note: `value` is not part of the explicit function signature # for MyStandardComponent, due to --max-props 2 in its build command # but this verifies that it still works. MyStandardComponent(id="standard", value="Standard"), MyNestedComponent(id="nested", value="Nested"), TypeScriptComponent(id="typescript", required_string="TypeScript"), TypeScriptClassComponent(id="typescript-class", required_string="TypeScriptClass"), StandardComponent(id="ts-standard", children="jsx"), ], id="outer", ) dash_duo.start_server(app) assert dash_duo.wait_for_element("#standard").text == "Standard" assert dash_duo.wait_for_element("#nested").text == "Nested" assert dash_duo.wait_for_element("#typescript").text == "TypeScript" assert dash_duo.wait_for_element( "#typescript-class").text == "TypeScriptClass" assert dash_duo.wait_for_element("#ts-standard").text == "jsx" expected_html = ( '<div id="standard">Standard</div>' '<div id="nested">Nested</div>' '<div id="typescript">TypeScript</div>' '<div class="typescript-class-component" id="typescript-class">TypeScriptClass</div>' '<div id="ts-standard">jsx</div>') assert dash_duo.find_element("#outer").get_property( "innerHTML") == expected_html
def update_table(n) -> Div: """ """ MQTT_CLIENT.loop() compute_machines = [] if GPU_STATS: df = to_overall_gpu_process_df(copy.deepcopy(GPU_STATS)) else: df = DataFrame(["No data"], columns=("data", )) compute_machines.append( DataTable( id="gpu-table-0", columns=[{ "name": i, "id": i } for i in df.columns], data=df.to_dict("records"), page_size=ALL_CONSTANTS.TABLE_PAGE_SIZE, # style_as_list_view=True, style_data_conditional=[{ "if": { "row_index": "odd" }, "backgroundColor": "rgb(248, 248, 248)" }], style_header={ "backgroundColor": "rgb(230, 230, 230)", "fontWeight": "bold", }, )) return Div(compute_machines)
def test_gene001_simple_callback(dash_duo): app = Dash(__name__) app.layout = Div([ # Note: `value` is not part of the explicit function signature # for MyStandardComponent, due to --max-props 2 in its build command # but this verifies that it still works. MyStandardComponent(id="standard", value="Standard"), MyNestedComponent(id="nested", value="Nested"), TypeScriptComponent(id="typescript", required_string="TypeScript"), TypeScriptClassComponent(id="typescript-class", required_string="TypeScriptClass"), StandardComponent(id="ts-standard", children="jsx"), ]) dash_duo.start_server(app) assert dash_duo.wait_for_element("#standard").text == "Standard" assert dash_duo.wait_for_element("#nested").text == "Nested" assert dash_duo.wait_for_element("#typescript").text == "TypeScript" assert dash_duo.wait_for_element( "#typescript-class").text == "TypeScriptClass" assert dash_duo.wait_for_element("#ts-standard").text == "jsx" dash_duo.percy_snapshot(name="gene001-simple-callback")
def test_szng002_percentages_result_in_same_widths(test): _fixed_columns = [dict(headers=True, data=1), dict(headers=True)] _fixed_rows = [dict(headers=True, data=1), dict(headers=True)] _merge_duplicate_headers = [True, False] variations = [] i = 0 for fixed_columns in _fixed_columns: for fixed_rows in _fixed_rows: for merge_duplicate_headers in _merge_duplicate_headers: variations.append({ **base_props, "fixed_columns": fixed_columns, "fixed_rows": fixed_rows, "merge_duplicate_headers": merge_duplicate_headers, "id": "table{}".format(i), }) i = i + 1 tables = [DataTable(**variation) for variation in variations] app = dash.Dash(__name__) app.layout = Div(tables) test.start_server(app) cells_are_same_width(test, "#table0", "#table0") for i in range(1, len(variations)): cells_are_same_width(test, "#table0", "#table{}".format(i)) assert test.get_log_errors() == []
def update_graph(n) -> Div: """ """ global GPU_STATS global KEEP_ALIVE compute_machines = [] if GPU_STATS: compute_machines.extend( per_machine_per_device_pie_charts(copy.deepcopy(GPU_STATS), KEEP_ALIVE)) return Div(compute_machines)
def test_gene001_simple_callback(dash_duo): app = Dash(__name__) app.layout = Div([ MyStandardComponent(id="standard", value="Standard"), MyNestedComponent(id="nested", value="Nested"), ]) dash_duo.start_server(app) assert dash_duo.wait_for_element("#standard").text == "Standard" assert dash_duo.wait_for_element("#nested").text == "Nested" dash_duo.percy_snapshot(name="gene001-simple-callback")
def test_ddvi001_fixed_table(dash_duo): app = Dash(__name__) app.layout = Div([ Dropdown( id="dropdown", options=[ { "label": "New York City", "value": "NYC" }, { "label": "Montreal", "value": "MTL" }, { "label": "San Francisco", "value": "SF" }, ], value="NYC", ), DataTable( id="table", columns=[{ "name": x, "id": x, "selectable": True } for x in ["a", "b", "c"]], editable=True, row_deletable=True, fixed_rows=dict(headers=True), fixed_columns=dict(headers=True), data=[{ "a": "a" + str(x), "b": "b" + str(x), "c": "c" + str(x) } for x in range(0, 20)], ), ]) dash_duo.start_server(app) dash_duo.find_element("#dropdown").click() dash_duo.wait_for_element("#dropdown .Select-menu-outer") dash_duo.percy_snapshot( "dcc.Dropdown dropdown overlaps table fixed rows/columns") assert dash_duo.get_logs() == []
def get_app(props=dict(), special=False, clear=False): app = dash.Dash(__name__) baseProps = get_props(rows=200) if special: for c in baseProps.get("columns"): if c["id"] == "bbb": c["id"] = "b+bb" elif c["id"] == "ccc": c["id"] = "c cc" elif c["id"] == "ddd": c["id"] = "d:dd" elif c["id"] == "eee": c["id"] = "e-ee" elif c["id"] == "fff": c["id"] = "f_ff" elif c["id"] == "ggg": c["id"] = "g.gg" for i in range(len(baseProps["data"])): d = baseProps["data"][i] d["b+bb"] = d["bbb"] d["c cc"] = d["ccc"] d["d:dd"] = d["ddd"] d["e-ee"] = d["eee"] d["f_ff"] = d["fff"] d["g.gg"] = d["ggg"] baseProps.update(dict(filter_action="native")) baseProps.update(props) if clear: app.layout = Div([ DataTable(**baseProps), Button(id="btn", children=["Clear filters"]) ]) @app.callback(Output("table", "filter_query"), Input("btn", "n_clicks")) def get_filter(n_clicks): return "" else: app.layout = DataTable(**baseProps) return app
def get_app(props=dict()): app = dash.Dash(__name__) baseProps = dict( columns=[dict(name=i, id=i, selectable=True) for i in rawDf.columns], data=df, editable=True, filter_action="native", fixed_columns={"headers": True}, fixed_rows={"headers": True}, page_action="native", row_deletable=True, row_selectable=True, sort_action="native", ) baseProps.update(props) app.layout = Div([DataTable(**baseProps), DataTable(**baseProps)]) return app
def per_machine_per_device_pie_charts(gpu_stats: Mapping, keep_alive: Sequence[Number]): """ """ compute_machines = [] for machine_name, machine in gpu_stats.items(): machine_devices = [] devices = machine["devices"] for i, d in enumerate(devices): used = d["used"] // MB_DIVISOR total = d["total"] // MB_DIVISOR used_ratio = used / total used_ratio = [used_ratio] + [1.0 - used_ratio] hover_text = [f"used:{used:.0f}mb", f"free:{total - used:.0f}mb"] machine_devices.append( Div( [ Graph( id=f"gpu_stats_{machine_name}{i}", figure={ "data": [ graph_objs.Pie( values=used_ratio, text=hover_text, name="used ratio", hole=0.4, ) ], "layout": graph_objs.Layout( title=f"{d['name']} cuda_idx:{d['id']}", showlegend=False, hovermode="closest", ), }, style={ "width": "100%", }, ) ], className="col", )) compute_machines.append( Div( [ H3( f"{machine_name}: {keep_alive[machine_name]} sec ago", className="text-monospace", style={"text-decoration": "underline"}, ), Div([*machine_devices], className="row"), ], style={ "text-align": "center", "width": "100%", }, )) return compute_machines
def test_szng001_widths_on_style_change(test): base_props = dict( data=[ {"a": 85, "b": 601, "c": 891}, {"a": 967, "b": 189, "c": 514}, {"a": 398, "b": 262, "c": 743}, {"a": 89, "b": 560, "c": 582}, {"a": 809, "b": 591, "c": 511}, ], columns=[ {"id": "a", "name": "A"}, {"id": "b", "name": "B"}, {"id": "c", "name": "C"}, ], style_data={ "width": 100, "minWidth": 100, "maxWidth": 100, "border": "1px solid blue", }, row_selectable="single", row_deletable=True, ) styles = [ dict( style_table=dict( width=500, minWidth=500, maxWidth=500, paddingBottom=10, display="none" ) ), dict(style_table=dict(width=500, minWidth=500, maxWidth=500, paddingBottom=10)), dict(style_table=dict(width=750, minWidth=750, maxWidth=750, paddingBottom=10)), dict( style_table=dict( width=750, minWidth=750, maxWidth=750, paddingBottom=10, display="none" ) ), dict(style_table=dict(width=350, minWidth=350, maxWidth=350, paddingBottom=10)), ] fixes = [ dict(), dict(fixed_columns=dict(headers=True)), dict(fixed_rows=dict(headers=True)), dict(fixed_columns=dict(headers=True), fixed_rows=dict(headers=True)), dict(fixed_columns=dict(headers=True, data=1)), dict(fixed_rows=dict(headers=True, data=1)), dict( fixed_columns=dict(headers=True, data=1), fixed_rows=dict(headers=True, data=1), ), ] variations = [] style = styles[0] i = 0 for fix in fixes: variations.append({**style, **fix, **base_props, "id": "table{}".format(i)}) i = i + 1 variations_range = range(0, len(variations)) tables = [DataTable(**variation) for variation in variations] app = dash.Dash(__name__) app.layout = Div( children=[ Button(id="btn", children="Click me"), Div( [ DataTable( **base_props, id="table{}".format(width), style_table=dict( width=width, minWidth=width, maxWidth=width, paddingBottom=10, ) ) for width in [350, 500, 750] ] ), Div(tables), ] ) @app.callback( [Output("table{}".format(i), "style_table") for i in variations_range], [Input("btn", "n_clicks")], prevent_initial_call=True, ) def update_styles(n_clicks): if n_clicks < len(styles): style_table = styles[n_clicks]["style_table"] return [style_table for i in variations_range] else: raise PreventUpdate test.start_server(app) for style in styles: display = style.get("style_table", dict()).get("display") width = style.get("style_table", dict()).get("width") target = ( test.driver.find_element_by_css_selector("#table{}".format(width)) if display != "none" else None ) for variation in variations: table = test.driver.find_element_by_css_selector( "#{}".format(variation["id"]) ) if target is None: assert table is not None assert ( test.driver.execute_script( "return getComputedStyle(document.querySelector('#{} .dash-spreadsheet-container')).display".format( variation["id"] ) ) == "none" ) else: cells_are_same_width(target, table) test.driver.find_element_by_css_selector("#btn").click() assert test.get_log_errors() == []
import pytest from dash import Output from dash.html import Div from dash.exceptions import InvalidCallbackReturnValue from dash._validate import fail_callback_output @pytest.mark.parametrize( "val", [ {0}, [{1}, 1], [1, {2}], Div({3}), Div([{4}]), Div(style={5}), Div([1, {6}]), Div([1, Div({7})]), [Div({8}), 1], [1, Div({9})], [Div(Div({10}))], [Div(Div({11})), 1], [1, Div(Div({12}))], { "a": {13} }, Div(style={"a": {14}}), Div(style=[{15}]), [1, Div(style=[{16}])], ],