1 # Copyright (c) 2022 Cisco and/or its affiliates.
2 # Licensed under the Apache License, Version 2.0 (the "License");
3 # you may not use this file except in compliance with the License.
4 # You may obtain a copy of the License at:
6 # http://www.apache.org/licenses/LICENSE-2.0
8 # Unless required by applicable law or agreed to in writing, software
9 # distributed under the License is distributed on an "AS IS" BASIS,
10 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 # See the License for the specific language governing permissions and
12 # limitations under the License.
14 """Plotly Dash HTML layout override.
19 import dash_bootstrap_components as dbc
21 from flask import Flask
24 from dash import callback_context, no_update, ALL
25 from dash import Input, Output, State
26 from yaml import load, FullLoader, YAMLError
27 from copy import deepcopy
28 from ast import literal_eval
30 from ..utils.constants import Constants as C
31 from ..utils.utils import show_tooltip, label, sync_checklists, list_tests, \
33 from ..utils.url_processing import url_decode
34 from ..data.data import Data
35 from .graphs import graph_iterative, table_comparison, get_short_version
39 """The layout of the dash app and the callbacks.
42 def __init__(self, app: Flask, releases: list, html_layout_file: str,
43 graph_layout_file: str, data_spec_file: str, tooltip_file: str) -> None:
45 - save the input parameters,
46 - read and pre-process the data,
47 - prepare data for the control panel,
48 - read HTML layout file,
49 - read tooltips from the tooltip file.
51 :param app: Flask application running the dash application.
52 :param releases: Lis of releases to be displayed.
53 :param html_layout_file: Path and name of the file specifying the HTML
54 layout of the dash application.
55 :param graph_layout_file: Path and name of the file with layout of
57 :param data_spec_file: Path and name of the file specifying the data to
58 be read from parquets for this application.
59 :param tooltip_file: Path and name of the yaml file specifying the
63 :type html_layout_file: str
64 :type graph_layout_file: str
65 :type data_spec_file: str
66 :type tooltip_file: str
71 self.releases = releases
72 self._html_layout_file = html_layout_file
73 self._graph_layout_file = graph_layout_file
74 self._data_spec_file = data_spec_file
75 self._tooltip_file = tooltip_file
78 self._data = pd.DataFrame()
80 data_mrr = Data(self._data_spec_file, True).\
81 read_iterative_mrr(release=rls.replace("csit", "rls"))
82 data_mrr["release"] = rls
83 data_ndrpdr = Data(self._data_spec_file, True).\
84 read_iterative_ndrpdr(release=rls.replace("csit", "rls"))
85 data_ndrpdr["release"] = rls
86 self._data = pd.concat(
87 [self._data, data_mrr, data_ndrpdr], ignore_index=True)
89 # Get structure of tests:
91 cols = ["job", "test_id", "test_type", "dut_version", "release"]
92 for _, row in self._data[cols].drop_duplicates().iterrows():
94 ttype = row["test_type"]
95 lst_job = row["job"].split("-")
97 d_ver = get_short_version(row["dut_version"], dut)
98 tbed = "-".join(lst_job[-2:])
99 lst_test_id = row["test_id"].split(".")
103 area = "-".join(lst_test_id[3:-2])
104 suite = lst_test_id[-2].replace("2n1l-", "").replace("1n1l-", "").\
106 test = lst_test_id[-1]
107 nic = suite.split("-")[0]
108 for drv in C.DRIVERS:
110 driver = drv.replace("-", "_")
111 test = test.replace(f"{drv}-", "")
115 infra = "-".join((tbed, nic, driver))
116 lst_test = test.split("-")
117 framesize = lst_test[0]
118 core = lst_test[1] if lst_test[1] else "8C"
119 test = "-".join(lst_test[2: -1])
121 if tbs.get(rls, None) is None:
123 if tbs[rls].get(dut, None) is None:
124 tbs[rls][dut] = dict()
125 if tbs[rls][dut].get(d_ver, None) is None:
126 tbs[rls][dut][d_ver] = dict()
127 if tbs[rls][dut][d_ver].get(infra, None) is None:
128 tbs[rls][dut][d_ver][infra] = dict()
129 if tbs[rls][dut][d_ver][infra].get(area, None) is None:
130 tbs[rls][dut][d_ver][infra][area] = dict()
131 if tbs[rls][dut][d_ver][infra][area].get(test, None) is None:
132 tbs[rls][dut][d_ver][infra][area][test] = dict()
133 tbs[rls][dut][d_ver][infra][area][test]["core"] = list()
134 tbs[rls][dut][d_ver][infra][area][test]["frame-size"] = list()
135 tbs[rls][dut][d_ver][infra][area][test]["test-type"] = list()
136 if core.upper() not in \
137 tbs[rls][dut][d_ver][infra][area][test]["core"]:
138 tbs[rls][dut][d_ver][infra][area][test]["core"].append(
140 if framesize.upper() not in \
141 tbs[rls][dut][d_ver][infra][area][test]["frame-size"]:
142 tbs[rls][dut][d_ver][infra][area][test]["frame-size"].append(
146 tbs[rls][dut][d_ver][infra][area][test]["test-type"]:
147 tbs[rls][dut][d_ver][infra][area][test]["test-type"].append(
149 elif ttype == "ndrpdr":
151 tbs[rls][dut][d_ver][infra][area][test]["test-type"]:
152 tbs[rls][dut][d_ver][infra][area][test]["test-type"].extend(
157 self._html_layout = ""
158 self._graph_layout = None
159 self._tooltips = dict()
162 with open(self._html_layout_file, "r") as file_read:
163 self._html_layout = file_read.read()
164 except IOError as err:
166 f"Not possible to open the file {self._html_layout_file}\n{err}"
170 with open(self._graph_layout_file, "r") as file_read:
171 self._graph_layout = load(file_read, Loader=FullLoader)
172 except IOError as err:
174 f"Not possible to open the file {self._graph_layout_file}\n"
177 except YAMLError as err:
179 f"An error occurred while parsing the specification file "
180 f"{self._graph_layout_file}\n{err}"
184 with open(self._tooltip_file, "r") as file_read:
185 self._tooltips = load(file_read, Loader=FullLoader)
186 except IOError as err:
188 f"Not possible to open the file {self._tooltip_file}\n{err}"
190 except YAMLError as err:
192 f"An error occurred while parsing the specification file "
193 f"{self._tooltip_file}\n{err}"
197 if self._app is not None and hasattr(self, 'callbacks'):
198 self.callbacks(self._app)
201 def html_layout(self):
202 return self._html_layout
206 return self._spec_tbs
214 return self._graph_layout
216 def add_content(self):
217 """Top level method which generated the web page.
220 - Store for user input data,
222 - Main area with control panel and ploting area.
224 If no HTML layout is provided, an error message is displayed instead.
226 :returns: The HTML div with the whole page.
230 if self.html_layout and self.spec_tbs:
244 id="offcanvas-metadata",
245 title="Throughput And Latency",
249 dbc.Row(id="metadata-tput-lat"),
250 dbc.Row(id="metadata-hdrh-graph"),
258 dcc.Store(id="selected-tests"),
259 dcc.Store(id="control-panel"),
260 dcc.Location(id="url", refresh=False),
261 self._add_ctrl_col(),
262 self._add_plotting_col(),
280 def _add_navbar(self):
281 """Add nav element with navigation panel. It is placed on the top.
283 :returns: Navigation bar.
284 :rtype: dbc.NavbarSimple
286 return dbc.NavbarSimple(
287 id="navbarsimple-main",
291 "Iterative Test Runs",
300 brand_external_link=True,
305 def _add_ctrl_col(self) -> dbc.Col:
306 """Add column with controls. It is placed on the left side.
308 :returns: Column with the control panel.
314 self._add_ctrl_panel(),
318 def _add_plotting_col(self) -> dbc.Col:
319 """Add column with plots and tables. It is placed on the right side.
321 :returns: Column with tables.
325 id="col-plotting-area",
330 class_name="g-0 p-2",
333 dbc.Row( # Throughput
335 class_name="g-0 p-2",
336 children=[C.PLACEHOLDER, ]
343 class_name="g-0 p-2",
344 children=[C.PLACEHOLDER, ]
352 class_name="g-0 p-2",
353 children=[C.PLACEHOLDER, ]
356 id="row-btn-download",
357 class_name="g-0 p-2",
358 children=[C.PLACEHOLDER, ]
366 def _add_ctrl_panel(self) -> dbc.Row:
367 """Add control panel.
369 :returns: Control panel.
374 class_name="g-0 p-2",
382 children=show_tooltip(self._tooltips,
383 "help-release", "CSIT Release")
387 placeholder=("Select a Release..."),
390 {"label": k, "value": k} \
391 for k in self.spec_tbs.keys()
393 key=lambda d: d["label"]
408 children=show_tooltip(self._tooltips,
414 "Select a Device under Test..."
429 children=show_tooltip(self._tooltips,
430 "help-dut-ver", "DUT Version")
435 "Select a Version of "
436 "Device under Test..."
451 children=show_tooltip(self._tooltips,
452 "help-infra", "Infra")
457 "Select a Physical Test Bed "
473 children=show_tooltip(self._tooltips,
478 placeholder="Select an Area...",
493 children=show_tooltip(self._tooltips,
498 placeholder="Select a Test...",
508 id="row-ctrl-framesize",
512 children=show_tooltip(self._tooltips,
513 "help-framesize", "Frame Size"),
519 id="cl-ctrl-framesize-all",
520 options=C.CL_ALL_DISABLED,
530 id="cl-ctrl-framesize",
543 children=show_tooltip(self._tooltips,
544 "help-cores", "Number of Cores"),
550 id="cl-ctrl-core-all",
551 options=C.CL_ALL_DISABLED,
570 id="row-ctrl-testtype",
574 children=show_tooltip(self._tooltips,
575 "help-ttype", "Test Type"),
581 id="cl-ctrl-testtype-all",
582 options=C.CL_ALL_DISABLED,
592 id="cl-ctrl-testtype",
601 id="row-ctrl-normalize",
605 children=show_tooltip(self._tooltips,
606 "help-normalize", "Normalize"),
612 id="cl-ctrl-normalize",
614 "value": "normalize",
616 "Normalize results to CPU"
629 class_name="gy-1 p-0",
635 children="Add Selected",
645 id="row-card-sel-tests",
647 style=C.STYLE_DISABLED,
654 class_name="overflow-auto",
658 style={"max-height": "20em"},
663 id="row-btns-sel-tests",
664 style=C.STYLE_DISABLED,
671 children="Remove Selected",
672 class_name="w-100 me-1",
677 id="btn-sel-remove-all",
678 children="Remove All",
679 class_name="w-100 me-1",
692 """A class representing the control panel.
695 def __init__(self, panel: dict) -> None:
696 """Initialisation of the control pannel by default values. If
697 particular values are provided (parameter "panel") they are set
700 :param panel: Custom values to be set to the control panel.
701 :param default: Default values to be set to the control panel.
706 # Defines also the order of keys
708 "dd-rls-value": str(),
709 "dd-dut-options": list(),
710 "dd-dut-disabled": True,
711 "dd-dut-value": str(),
712 "dd-dutver-options": list(),
713 "dd-dutver-disabled": True,
714 "dd-dutver-value": str(),
715 "dd-phy-options": list(),
716 "dd-phy-disabled": True,
717 "dd-phy-value": str(),
718 "dd-area-options": list(),
719 "dd-area-disabled": True,
720 "dd-area-value": str(),
721 "dd-test-options": list(),
722 "dd-test-disabled": True,
723 "dd-test-value": str(),
724 "cl-core-options": list(),
725 "cl-core-value": list(),
726 "cl-core-all-value": list(),
727 "cl-core-all-options": C.CL_ALL_DISABLED,
728 "cl-framesize-options": list(),
729 "cl-framesize-value": list(),
730 "cl-framesize-all-value": list(),
731 "cl-framesize-all-options": C.CL_ALL_DISABLED,
732 "cl-testtype-options": list(),
733 "cl-testtype-value": list(),
734 "cl-testtype-all-value": list(),
735 "cl-testtype-all-options": C.CL_ALL_DISABLED,
736 "btn-add-disabled": True,
737 "cl-normalize-value": list(),
738 "cl-selected-options": list()
741 self._panel = deepcopy(self._defaults)
743 for key in self._defaults:
744 self._panel[key] = panel[key]
747 def defaults(self) -> dict:
748 return self._defaults
751 def panel(self) -> dict:
754 def set(self, kwargs: dict) -> None:
755 """Set the values of the Control panel.
757 :param kwargs: key - value pairs to be set.
759 :raises KeyError: If the key in kwargs is not present in the Control
762 for key, val in kwargs.items():
763 if key in self._panel:
764 self._panel[key] = val
766 raise KeyError(f"The key {key} is not defined.")
768 def get(self, key: str) -> any:
769 """Returns the value of a key from the Control panel.
771 :param key: The key which value should be returned.
773 :returns: The value of the key.
775 :raises KeyError: If the key in kwargs is not present in the Control
778 return self._panel[key]
780 def values(self) -> tuple:
781 """Returns the values from the Control panel as a list.
783 :returns: The values from the Control panel.
786 return tuple(self._panel.values())
788 def callbacks(self, app):
789 """Callbacks for the whole application.
791 :param app: The application.
795 def _generate_plotting_area(figs: tuple, table: pd.DataFrame,
797 """Generate the plotting area with all its content.
799 :param figs: Figures to be placed in the plotting area.
800 :param table: A table to be placed in the plotting area bellow the
802 :param utl: The URL to be placed in the plotting area bellow the
804 :type figs: tuple of plotly.graph_objects.Figure
805 :type table: pandas.DataFrame
807 :returns: tuple of elements to be shown in the plotting area.
809 (dcc.Graph, dcc.Graph, dbc.Table, list(dbc.Col, dbc.Col))
812 (fig_tput, fig_lat) = figs
814 row_fig_tput = C.PLACEHOLDER
815 row_fig_lat = C.PLACEHOLDER
816 row_table = C.PLACEHOLDER
817 row_btn_dwnld = C.PLACEHOLDER
822 id={"type": "graph", "index": "tput"},
830 dcc.Loading(children=[
832 id="btn-download-data",
833 children=show_tooltip(self._tooltips,
834 "help-download", "Download Data"),
838 dcc.Download(id="download-data")
850 children=show_tooltip(self._tooltips,
851 "help-url", "URL", "input-url")
868 id={"type": "graph", "index": "lat"},
874 dbc.Table.from_dataframe(
876 id={"type": "table", "index": "compare"},
883 return row_fig_tput, row_fig_lat, row_table, row_btn_dwnld
886 Output("control-panel", "data"), # Store
887 Output("selected-tests", "data"), # Store
888 Output("row-graph-tput", "children"),
889 Output("row-graph-lat", "children"),
890 Output("row-table", "children"),
891 Output("row-btn-download", "children"),
892 Output("row-card-sel-tests", "style"),
893 Output("row-btns-sel-tests", "style"),
894 Output("dd-ctrl-rls", "value"),
895 Output("dd-ctrl-dut", "options"),
896 Output("dd-ctrl-dut", "disabled"),
897 Output("dd-ctrl-dut", "value"),
898 Output("dd-ctrl-dutver", "options"),
899 Output("dd-ctrl-dutver", "disabled"),
900 Output("dd-ctrl-dutver", "value"),
901 Output("dd-ctrl-phy", "options"),
902 Output("dd-ctrl-phy", "disabled"),
903 Output("dd-ctrl-phy", "value"),
904 Output("dd-ctrl-area", "options"),
905 Output("dd-ctrl-area", "disabled"),
906 Output("dd-ctrl-area", "value"),
907 Output("dd-ctrl-test", "options"),
908 Output("dd-ctrl-test", "disabled"),
909 Output("dd-ctrl-test", "value"),
910 Output("cl-ctrl-core", "options"),
911 Output("cl-ctrl-core", "value"),
912 Output("cl-ctrl-core-all", "value"),
913 Output("cl-ctrl-core-all", "options"),
914 Output("cl-ctrl-framesize", "options"),
915 Output("cl-ctrl-framesize", "value"),
916 Output("cl-ctrl-framesize-all", "value"),
917 Output("cl-ctrl-framesize-all", "options"),
918 Output("cl-ctrl-testtype", "options"),
919 Output("cl-ctrl-testtype", "value"),
920 Output("cl-ctrl-testtype-all", "value"),
921 Output("cl-ctrl-testtype-all", "options"),
922 Output("btn-ctrl-add", "disabled"),
923 Output("cl-ctrl-normalize", "value"),
924 Output("cl-selected", "options"), # User selection
925 State("control-panel", "data"), # Store
926 State("selected-tests", "data"), # Store
927 State("cl-selected", "value"), # User selection
928 Input("dd-ctrl-rls", "value"),
929 Input("dd-ctrl-dut", "value"),
930 Input("dd-ctrl-dutver", "value"),
931 Input("dd-ctrl-phy", "value"),
932 Input("dd-ctrl-area", "value"),
933 Input("dd-ctrl-test", "value"),
934 Input("cl-ctrl-core", "value"),
935 Input("cl-ctrl-core-all", "value"),
936 Input("cl-ctrl-framesize", "value"),
937 Input("cl-ctrl-framesize-all", "value"),
938 Input("cl-ctrl-testtype", "value"),
939 Input("cl-ctrl-testtype-all", "value"),
940 Input("cl-ctrl-normalize", "value"),
941 Input("btn-ctrl-add", "n_clicks"),
942 Input("btn-sel-remove", "n_clicks"),
943 Input("btn-sel-remove-all", "n_clicks"),
946 def _update_ctrl_panel(cp_data: dict, store_sel: list, list_sel: list,
947 dd_rls: str, dd_dut: str, dd_dutver: str, dd_phy: str, dd_area: str,
948 dd_test: str, cl_core: list, cl_core_all: list, cl_framesize: list,
949 cl_framesize_all: list, cl_testtype: list, cl_testtype_all: list,
950 cl_normalize: list, btn_add: int, btn_remove: int,
951 btn_remove_all: int, href: str) -> tuple:
952 """Update the application when the event is detected.
954 :param cp_data: Current status of the control panel stored in
956 :param store_sel: List of tests selected by user stored in the
958 :param list_sel: List of tests selected by the user shown in the
960 :param dd_rls: Input - Releases.
961 :param dd_dut: Input - DUTs.
962 :param dd_dutver: Input - Version of DUT.
963 :param dd_phy: Input - topo- arch-nic-driver.
964 :param dd_area: Input - Tested area.
965 :param dd_test: Input - Test.
966 :param cl_core: Input - Number of cores.
967 :param cl_core_all: Input - All numbers of cores.
968 :param cl_framesize: Input - Frame sizes.
969 :param cl_framesize_all: Input - All frame sizes.
970 :param cl_testtype: Input - Test type (NDR, PDR, MRR).
971 :param cl_testtype_all: Input - All test types.
972 :param cl_normalize: Input - Normalize the results.
973 :param btn_add: Input - Button "Add Selected" tests.
974 :param btn_remove: Input - Button "Remove selected" tests.
975 :param btn_remove_all: Input - Button "Remove All" tests.
976 :param href: Input - The URL provided by the browser.
978 :type store_sel: list
987 :type cl_core_all: list
988 :type cl_framesize: list
989 :type cl_framesize_all: list
990 :type cl_testtype: list
991 :type cl_testtype_all: list
992 :type cl_normalize: list
994 :type btn_remove: int
995 :type btn_remove_all: int
997 :returns: New values for web page elements.
1001 ctrl_panel = self.ControlPanel(cp_data)
1004 parsed_url = url_decode(href)
1006 row_fig_tput = no_update
1007 row_fig_lat = no_update
1008 row_table = no_update
1009 row_btn_dwnld = no_update
1010 row_card_sel_tests = no_update
1011 row_btns_sel_tests = no_update
1013 trigger_id = callback_context.triggered[0]["prop_id"].split(".")[0]
1015 if trigger_id == "dd-ctrl-rls":
1017 rls = self.spec_tbs[dd_rls]
1019 [{"label": v, "value": v} for v in rls.keys()],
1020 key=lambda d: d["label"]
1027 "dd-rls-value": dd_rls,
1028 "dd-dut-value": str(),
1029 "dd-dut-options": options,
1030 "dd-dut-disabled": disabled,
1031 "dd-dutver-value": str(),
1032 "dd-dutver-options": list(),
1033 "dd-dutver-disabled": True,
1034 "dd-phy-value": str(),
1035 "dd-phy-options": list(),
1036 "dd-phy-disabled": True,
1037 "dd-area-value": str(),
1038 "dd-area-options": list(),
1039 "dd-area-disabled": True,
1040 "dd-test-value": str(),
1041 "dd-test-options": list(),
1042 "dd-test-disabled": True,
1043 "cl-core-options": list(),
1044 "cl-core-value": list(),
1045 "cl-core-all-value": list(),
1046 "cl-core-all-options": C.CL_ALL_DISABLED,
1047 "cl-framesize-options": list(),
1048 "cl-framesize-value": list(),
1049 "cl-framesize-all-value": list(),
1050 "cl-framesize-all-options": C.CL_ALL_DISABLED,
1051 "cl-testtype-options": list(),
1052 "cl-testtype-value": list(),
1053 "cl-testtype-all-value": list(),
1054 "cl-testtype-all-options": C.CL_ALL_DISABLED
1056 elif trigger_id == "dd-ctrl-dut":
1058 rls = ctrl_panel.get("dd-rls-value")
1059 dut = self.spec_tbs[rls][dd_dut]
1061 [{"label": v, "value": v} for v in dut.keys()],
1062 key=lambda d: d["label"]
1069 "dd-dut-value": dd_dut,
1070 "dd-dutver-value": str(),
1071 "dd-dutver-options": options,
1072 "dd-dutver-disabled": disabled,
1073 "dd-phy-value": str(),
1074 "dd-phy-options": list(),
1075 "dd-phy-disabled": True,
1076 "dd-area-value": str(),
1077 "dd-area-options": list(),
1078 "dd-area-disabled": True,
1079 "dd-test-value": str(),
1080 "dd-test-options": list(),
1081 "dd-test-disabled": True,
1082 "cl-core-options": list(),
1083 "cl-core-value": list(),
1084 "cl-core-all-value": list(),
1085 "cl-core-all-options": C.CL_ALL_DISABLED,
1086 "cl-framesize-options": list(),
1087 "cl-framesize-value": list(),
1088 "cl-framesize-all-value": list(),
1089 "cl-framesize-all-options": C.CL_ALL_DISABLED,
1090 "cl-testtype-options": list(),
1091 "cl-testtype-value": list(),
1092 "cl-testtype-all-value": list(),
1093 "cl-testtype-all-options": C.CL_ALL_DISABLED
1095 elif trigger_id == "dd-ctrl-dutver":
1097 rls = ctrl_panel.get("dd-rls-value")
1098 dut = ctrl_panel.get("dd-dut-value")
1099 dutver = self.spec_tbs[rls][dut][dd_dutver]
1101 [{"label": v, "value": v} for v in dutver.keys()],
1102 key=lambda d: d["label"]
1109 "dd-dutver-value": dd_dutver,
1110 "dd-phy-value": str(),
1111 "dd-phy-options": options,
1112 "dd-phy-disabled": disabled,
1113 "dd-area-value": str(),
1114 "dd-area-options": list(),
1115 "dd-area-disabled": True,
1116 "dd-test-value": str(),
1117 "dd-test-options": list(),
1118 "dd-test-disabled": True,
1119 "cl-core-options": list(),
1120 "cl-core-value": list(),
1121 "cl-core-all-value": list(),
1122 "cl-core-all-options": C.CL_ALL_DISABLED,
1123 "cl-framesize-options": list(),
1124 "cl-framesize-value": list(),
1125 "cl-framesize-all-value": list(),
1126 "cl-framesize-all-options": C.CL_ALL_DISABLED,
1127 "cl-testtype-options": list(),
1128 "cl-testtype-value": list(),
1129 "cl-testtype-all-value": list(),
1130 "cl-testtype-all-options": C.CL_ALL_DISABLED
1132 elif trigger_id == "dd-ctrl-phy":
1134 rls = ctrl_panel.get("dd-rls-value")
1135 dut = ctrl_panel.get("dd-dut-value")
1136 dutver = ctrl_panel.get("dd-dutver-value")
1137 phy = self.spec_tbs[rls][dut][dutver][dd_phy]
1139 [{"label": label(v), "value": v} for v in phy.keys()],
1140 key=lambda d: d["label"]
1147 "dd-phy-value": dd_phy,
1148 "dd-area-value": str(),
1149 "dd-area-options": options,
1150 "dd-area-disabled": disabled,
1151 "dd-test-value": str(),
1152 "dd-test-options": list(),
1153 "dd-test-disabled": True,
1154 "cl-core-options": list(),
1155 "cl-core-value": list(),
1156 "cl-core-all-value": list(),
1157 "cl-core-all-options": C.CL_ALL_DISABLED,
1158 "cl-framesize-options": list(),
1159 "cl-framesize-value": list(),
1160 "cl-framesize-all-value": list(),
1161 "cl-framesize-all-options": C.CL_ALL_DISABLED,
1162 "cl-testtype-options": list(),
1163 "cl-testtype-value": list(),
1164 "cl-testtype-all-value": list(),
1165 "cl-testtype-all-options": C.CL_ALL_DISABLED
1167 elif trigger_id == "dd-ctrl-area":
1169 rls = ctrl_panel.get("dd-rls-value")
1170 dut = ctrl_panel.get("dd-dut-value")
1171 dutver = ctrl_panel.get("dd-dutver-value")
1172 phy = ctrl_panel.get("dd-phy-value")
1173 area = self.spec_tbs[rls][dut][dutver][phy][dd_area]
1175 [{"label": v, "value": v} for v in area.keys()],
1176 key=lambda d: d["label"]
1183 "dd-area-value": dd_area,
1184 "dd-test-value": str(),
1185 "dd-test-options": options,
1186 "dd-test-disabled": disabled,
1187 "cl-core-options": list(),
1188 "cl-core-value": list(),
1189 "cl-core-all-value": list(),
1190 "cl-core-all-options": C.CL_ALL_DISABLED,
1191 "cl-framesize-options": list(),
1192 "cl-framesize-value": list(),
1193 "cl-framesize-all-value": list(),
1194 "cl-framesize-all-options": C.CL_ALL_DISABLED,
1195 "cl-testtype-options": list(),
1196 "cl-testtype-value": list(),
1197 "cl-testtype-all-value": list(),
1198 "cl-testtype-all-options": C.CL_ALL_DISABLED
1200 elif trigger_id == "dd-ctrl-test":
1201 rls = ctrl_panel.get("dd-rls-value")
1202 dut = ctrl_panel.get("dd-dut-value")
1203 dutver = ctrl_panel.get("dd-dutver-value")
1204 phy = ctrl_panel.get("dd-phy-value")
1205 area = ctrl_panel.get("dd-area-value")
1206 test = self.spec_tbs[rls][dut][dutver][phy][area][dd_test]
1207 if dut and phy and area and dd_test:
1209 "dd-test-value": dd_test,
1210 "cl-core-options": [{"label": v, "value": v}
1211 for v in sorted(test["core"])],
1212 "cl-core-value": list(),
1213 "cl-core-all-value": list(),
1214 "cl-core-all-options": C.CL_ALL_ENABLED,
1215 "cl-framesize-options": [{"label": v, "value": v}
1216 for v in sorted(test["frame-size"])],
1217 "cl-framesize-value": list(),
1218 "cl-framesize-all-value": list(),
1219 "cl-framesize-all-options": C.CL_ALL_ENABLED,
1220 "cl-testtype-options": [{"label": v, "value": v}
1221 for v in sorted(test["test-type"])],
1222 "cl-testtype-value": list(),
1223 "cl-testtype-all-value": list(),
1224 "cl-testtype-all-options": C.CL_ALL_ENABLED,
1226 elif trigger_id == "cl-ctrl-core":
1227 val_sel, val_all = sync_checklists(
1228 options=ctrl_panel.get("cl-core-options"),
1234 "cl-core-value": val_sel,
1235 "cl-core-all-value": val_all,
1237 elif trigger_id == "cl-ctrl-core-all":
1238 val_sel, val_all = sync_checklists(
1239 options = ctrl_panel.get("cl-core-options"),
1245 "cl-core-value": val_sel,
1246 "cl-core-all-value": val_all,
1248 elif trigger_id == "cl-ctrl-framesize":
1249 val_sel, val_all = sync_checklists(
1250 options = ctrl_panel.get("cl-framesize-options"),
1256 "cl-framesize-value": val_sel,
1257 "cl-framesize-all-value": val_all,
1259 elif trigger_id == "cl-ctrl-framesize-all":
1260 val_sel, val_all = sync_checklists(
1261 options = ctrl_panel.get("cl-framesize-options"),
1263 all=cl_framesize_all,
1267 "cl-framesize-value": val_sel,
1268 "cl-framesize-all-value": val_all,
1270 elif trigger_id == "cl-ctrl-testtype":
1271 val_sel, val_all = sync_checklists(
1272 options = ctrl_panel.get("cl-testtype-options"),
1278 "cl-testtype-value": val_sel,
1279 "cl-testtype-all-value": val_all,
1281 elif trigger_id == "cl-ctrl-testtype-all":
1282 val_sel, val_all = sync_checklists(
1283 options = ctrl_panel.get("cl-testtype-options"),
1285 all=cl_testtype_all,
1289 "cl-testtype-value": val_sel,
1290 "cl-testtype-all-value": val_all,
1292 elif trigger_id == "btn-ctrl-add":
1294 rls = ctrl_panel.get("dd-rls-value")
1295 dut = ctrl_panel.get("dd-dut-value")
1296 dutver = ctrl_panel.get("dd-dutver-value")
1297 phy = ctrl_panel.get("dd-phy-value")
1298 area = ctrl_panel.get("dd-area-value")
1299 test = ctrl_panel.get("dd-test-value")
1300 cores = ctrl_panel.get("cl-core-value")
1301 framesizes = ctrl_panel.get("cl-framesize-value")
1302 testtypes = ctrl_panel.get("cl-testtype-value")
1303 # Add selected test to the list of tests in store:
1304 if all((rls, dut, dutver, phy, area, test, cores, framesizes,
1306 if store_sel is None:
1309 for framesize in framesizes:
1310 for ttype in testtypes:
1313 tid = "-".join((rls, dut, dutver,
1314 phy.replace('af_xdp', 'af-xdp'), area,
1315 framesize.lower(), core.lower(), test,
1317 if tid not in [itm["id"] for itm in store_sel]:
1326 "framesize": framesize.lower(),
1327 "core": core.lower(),
1328 "testtype": ttype.lower()
1330 store_sel = sorted(store_sel, key=lambda d: d["id"])
1331 row_card_sel_tests = C.STYLE_ENABLED
1332 row_btns_sel_tests = C.STYLE_ENABLED
1333 if C.CLEAR_ALL_INPUTS:
1334 ctrl_panel.set(ctrl_panel.defaults)
1336 "cl-selected-options": list_tests(store_sel)
1338 elif trigger_id == "btn-sel-remove-all":
1340 row_fig_tput = C.PLACEHOLDER
1341 row_fig_lat = C.PLACEHOLDER
1342 row_table = C.PLACEHOLDER
1343 row_btn_dwnld = C.PLACEHOLDER
1344 row_card_sel_tests = C.STYLE_DISABLED
1345 row_btns_sel_tests = C.STYLE_DISABLED
1347 ctrl_panel.set({"cl-selected-options": list()})
1348 elif trigger_id == "btn-sel-remove":
1351 new_store_sel = list()
1352 for item in store_sel:
1353 if item["id"] not in list_sel:
1354 new_store_sel.append(item)
1355 store_sel = new_store_sel
1356 elif trigger_id == "url":
1357 # TODO: Add verification
1358 url_params = parsed_url["params"]
1360 store_sel = literal_eval(
1361 url_params.get("store_sel", list())[0])
1363 row_card_sel_tests = C.STYLE_ENABLED
1364 row_btns_sel_tests = C.STYLE_ENABLED
1366 if trigger_id in ("btn-ctrl-add", "url", "btn-sel-remove",
1367 "cl-ctrl-normalize"):
1369 row_fig_tput, row_fig_lat, row_table, row_btn_dwnld = \
1370 _generate_plotting_area(
1372 self.data, store_sel, self.layout,
1376 self.data, store_sel, bool(cl_normalize)
1378 gen_new_url(parsed_url, {"store_sel": store_sel})
1381 "cl-selected-options": list_tests(store_sel)
1384 row_fig_tput = C.PLACEHOLDER
1385 row_fig_lat = C.PLACEHOLDER
1386 row_table = C.PLACEHOLDER
1387 row_btn_dwnld = C.PLACEHOLDER
1388 row_card_sel_tests = C.STYLE_DISABLED
1389 row_btns_sel_tests = C.STYLE_DISABLED
1391 ctrl_panel.set({"cl-selected-options": list()})
1393 if ctrl_panel.get("cl-core-value") and \
1394 ctrl_panel.get("cl-framesize-value") and \
1395 ctrl_panel.get("cl-testtype-value"):
1400 "btn-add-disabled": disabled,
1401 "cl-normalize-value": cl_normalize
1405 ctrl_panel.panel, store_sel,
1406 row_fig_tput, row_fig_lat, row_table, row_btn_dwnld,
1407 row_card_sel_tests, row_btns_sel_tests
1409 ret_val.extend(ctrl_panel.values())