robotframework-dashboard 1.3.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- robotframework_dashboard/__init__.py +0 -0
- robotframework_dashboard/abstractdb.py +60 -0
- robotframework_dashboard/arguments.py +459 -0
- robotframework_dashboard/css/styling.css +431 -0
- robotframework_dashboard/dashboard.py +126 -0
- robotframework_dashboard/database.py +371 -0
- robotframework_dashboard/dependencies/bootstrap.css +6 -0
- robotframework_dashboard/dependencies/bootstrap.js +7 -0
- robotframework_dashboard/dependencies/chart.js +20 -0
- robotframework_dashboard/dependencies/chartjs-adapter-date-fns.js +7 -0
- robotframework_dashboard/dependencies/chartjs-chart-boxplot.js +2 -0
- robotframework_dashboard/dependencies/chartjs-chart-matrix.js +8 -0
- robotframework_dashboard/dependencies/chartjs-plugin-datalabels.js +7 -0
- robotframework_dashboard/dependencies/datatables.css +18 -0
- robotframework_dashboard/dependencies/datatables.js +25 -0
- robotframework_dashboard/dependencies/gridstack.css +1 -0
- robotframework_dashboard/dependencies/gridstack.js +9 -0
- robotframework_dashboard/dependencies/pako.js +2 -0
- robotframework_dashboard/dependencies.py +222 -0
- robotframework_dashboard/js/admin_page/admin_api.js +218 -0
- robotframework_dashboard/js/admin_page/admin_common.js +26 -0
- robotframework_dashboard/js/admin_page/admin_eventlisteners.js +102 -0
- robotframework_dashboard/js/admin_page/admin_information.js +128 -0
- robotframework_dashboard/js/admin_page/admin_main.js +20 -0
- robotframework_dashboard/js/admin_page/admin_theme.js +129 -0
- robotframework_dashboard/js/common.js +169 -0
- robotframework_dashboard/js/database.js +18 -0
- robotframework_dashboard/js/eventlisteners.js +675 -0
- robotframework_dashboard/js/filter.js +662 -0
- robotframework_dashboard/js/graph_creation/all.js +107 -0
- robotframework_dashboard/js/graph_creation/compare.js +77 -0
- robotframework_dashboard/js/graph_creation/keyword.js +360 -0
- robotframework_dashboard/js/graph_creation/overview.js +589 -0
- robotframework_dashboard/js/graph_creation/run.js +154 -0
- robotframework_dashboard/js/graph_creation/suite.js +338 -0
- robotframework_dashboard/js/graph_creation/tables.js +188 -0
- robotframework_dashboard/js/graph_creation/test.js +475 -0
- robotframework_dashboard/js/graph_data/donut.js +289 -0
- robotframework_dashboard/js/graph_data/duration.js +188 -0
- robotframework_dashboard/js/graph_data/duration_deviation.js +50 -0
- robotframework_dashboard/js/graph_data/failed.js +118 -0
- robotframework_dashboard/js/graph_data/flaky.js +155 -0
- robotframework_dashboard/js/graph_data/graph_config.js +332 -0
- robotframework_dashboard/js/graph_data/heatmap.js +62 -0
- robotframework_dashboard/js/graph_data/helpers.js +111 -0
- robotframework_dashboard/js/graph_data/messages.js +116 -0
- robotframework_dashboard/js/graph_data/statistics.js +219 -0
- robotframework_dashboard/js/graph_data/stats.js +43 -0
- robotframework_dashboard/js/graph_data/time_consuming.js +201 -0
- robotframework_dashboard/js/information.js +105 -0
- robotframework_dashboard/js/layout.js +451 -0
- robotframework_dashboard/js/localstorage.js +221 -0
- robotframework_dashboard/js/log.js +122 -0
- robotframework_dashboard/js/main.js +26 -0
- robotframework_dashboard/js/menu.js +252 -0
- robotframework_dashboard/js/theme.js +215 -0
- robotframework_dashboard/js/variables/chartconfig.js +88 -0
- robotframework_dashboard/js/variables/data.js +35 -0
- robotframework_dashboard/js/variables/globals.js +74 -0
- robotframework_dashboard/js/variables/graphmetadata.js +940 -0
- robotframework_dashboard/js/variables/graphs.js +69 -0
- robotframework_dashboard/js/variables/information.js +271 -0
- robotframework_dashboard/js/variables/settings.js +85 -0
- robotframework_dashboard/js/variables/svg.js +116 -0
- robotframework_dashboard/licenses/THIRD_PARTY_LICENSES.txt +250 -0
- robotframework_dashboard/main.py +88 -0
- robotframework_dashboard/processors.py +304 -0
- robotframework_dashboard/queries.py +45 -0
- robotframework_dashboard/robotdashboard.py +245 -0
- robotframework_dashboard/server.py +593 -0
- robotframework_dashboard/templates/admin.html +350 -0
- robotframework_dashboard/templates/dashboard.html +713 -0
- robotframework_dashboard/version.py +1 -0
- robotframework_dashboard-1.3.1.dist-info/METADATA +101 -0
- robotframework_dashboard-1.3.1.dist-info/RECORD +79 -0
- robotframework_dashboard-1.3.1.dist-info/WHEEL +5 -0
- robotframework_dashboard-1.3.1.dist-info/entry_points.txt +2 -0
- robotframework_dashboard-1.3.1.dist-info/licenses/LICENSE +21 -0
- robotframework_dashboard-1.3.1.dist-info/top_level.txt +1 -0
|
File without changes
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
from abc import ABC, abstractmethod
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
|
|
4
|
+
class AbstractDatabaseProcessor(ABC):
|
|
5
|
+
|
|
6
|
+
def __init_subclass__(cls, **kwargs):
|
|
7
|
+
"""Function to validate that the custom dabataseclass is named 'DatabaseProcessor' correctly"""
|
|
8
|
+
super().__init_subclass__(**kwargs)
|
|
9
|
+
if cls.__name__ != "DatabaseProcessor":
|
|
10
|
+
raise TypeError(f"The custom databaseclass classname must be 'DatabaseProcessor', not '{cls.__name__}'")
|
|
11
|
+
|
|
12
|
+
@abstractmethod
|
|
13
|
+
def __init__(self, database_path: Path) -> None:
|
|
14
|
+
"""Mandatory: This function should handle the creation of the tables if required
|
|
15
|
+
The use of the database_path variable might not be required but you should still keep it as an argument!
|
|
16
|
+
"""
|
|
17
|
+
pass
|
|
18
|
+
|
|
19
|
+
@abstractmethod
|
|
20
|
+
def open_database(self) -> None:
|
|
21
|
+
"""Mandatory: This function should handle the connection to the database and set it for other functions to use"""
|
|
22
|
+
pass
|
|
23
|
+
|
|
24
|
+
@abstractmethod
|
|
25
|
+
def close_database(self) -> None:
|
|
26
|
+
"""Mandatory: This function is called to close the connection to the database"""
|
|
27
|
+
pass
|
|
28
|
+
|
|
29
|
+
@abstractmethod
|
|
30
|
+
def run_start_exists(self, run_start: str) -> bool:
|
|
31
|
+
"""Mandatory: This function is called to check if the output is already present in the database, this is done to save time on needless reprocessing.
|
|
32
|
+
If you want a very simple implementation without complex logic you can simply "return False". This will work but will reprocess needlessly.
|
|
33
|
+
"""
|
|
34
|
+
pass
|
|
35
|
+
|
|
36
|
+
@abstractmethod
|
|
37
|
+
def insert_output_data(
|
|
38
|
+
self, output_data: dict, tags: list, run_alias: str, path: Path, project_version: str
|
|
39
|
+
) -> None:
|
|
40
|
+
"""Mandatory: This function inserts the data of an output file into the database"""
|
|
41
|
+
pass
|
|
42
|
+
|
|
43
|
+
@abstractmethod
|
|
44
|
+
def get_data(self) -> dict:
|
|
45
|
+
"""Mandatory: This function gets all the data in the database"""
|
|
46
|
+
pass
|
|
47
|
+
|
|
48
|
+
@abstractmethod
|
|
49
|
+
def list_runs(self) -> None:
|
|
50
|
+
"""Mandatory: This function gets all available runs and prints them to the console"""
|
|
51
|
+
pass
|
|
52
|
+
|
|
53
|
+
@abstractmethod
|
|
54
|
+
def remove_runs(self, remove_runs: list) -> None:
|
|
55
|
+
"""Mandatory: This function removes all provided runs and all their corresponding data"""
|
|
56
|
+
pass
|
|
57
|
+
|
|
58
|
+
def update_output_path(self, log_path: str) -> None:
|
|
59
|
+
"""Optional: Function to update the output_path using the log path that the server has used"""
|
|
60
|
+
raise NotImplementedError("update_output_path is not implemented in the custom databaseclass, but is only required when using the server!")
|
|
@@ -0,0 +1,459 @@
|
|
|
1
|
+
import argparse
|
|
2
|
+
from datetime import datetime
|
|
3
|
+
from sys import exit
|
|
4
|
+
from re import split
|
|
5
|
+
from os import getcwd
|
|
6
|
+
from os.path import join, exists
|
|
7
|
+
from .version import __version__
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class dotdict(dict):
|
|
11
|
+
"""dot.notation access to dictionary attributes"""
|
|
12
|
+
|
|
13
|
+
__getattr__ = dict.get
|
|
14
|
+
__setattr__ = dict.__setitem__
|
|
15
|
+
__delattr__ = dict.__delitem__
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class ArgumentParser:
|
|
19
|
+
"""Parse the input arguments that can be provided to robotdashboard
|
|
20
|
+
Only get_arguments is called, all other functions are helper functions"""
|
|
21
|
+
|
|
22
|
+
def get_arguments(self):
|
|
23
|
+
"""The function that handles the complete parsing process"""
|
|
24
|
+
try:
|
|
25
|
+
arguments = self._parse_arguments()
|
|
26
|
+
arguments = self._process_arguments(arguments)
|
|
27
|
+
except Exception as error:
|
|
28
|
+
print(
|
|
29
|
+
f" ERROR: There was an issue during the parsing of the provided arguments"
|
|
30
|
+
)
|
|
31
|
+
print(f" {error}")
|
|
32
|
+
exit(0)
|
|
33
|
+
return arguments
|
|
34
|
+
|
|
35
|
+
def _normalize_bool(self, value, arg_name):
|
|
36
|
+
"""
|
|
37
|
+
Checks the boolean value and returns the correct boolean or exits with error
|
|
38
|
+
"""
|
|
39
|
+
v = str(value).lower()
|
|
40
|
+
if v == "true":
|
|
41
|
+
return True
|
|
42
|
+
elif v == "false":
|
|
43
|
+
return False
|
|
44
|
+
else:
|
|
45
|
+
print(
|
|
46
|
+
f" ERROR: The provided value: '{value}' for --{arg_name} is invalid\n"
|
|
47
|
+
f" Please provide True, False, or leave empty for the reverse boolean of the default\n"
|
|
48
|
+
f" See the --h / --help for more information and usage examples"
|
|
49
|
+
)
|
|
50
|
+
exit(0)
|
|
51
|
+
|
|
52
|
+
def _parse_arguments(self):
|
|
53
|
+
"""Parses the actual arguments"""
|
|
54
|
+
parser = argparse.ArgumentParser(
|
|
55
|
+
add_help=False,
|
|
56
|
+
formatter_class=argparse.RawTextHelpFormatter,
|
|
57
|
+
epilog="For full documentation, visit: https://timdegroot1996.github.io/robotframework-dashboard/",
|
|
58
|
+
)
|
|
59
|
+
parser.add_argument(
|
|
60
|
+
"-v",
|
|
61
|
+
"--version",
|
|
62
|
+
action="store_true",
|
|
63
|
+
dest="version",
|
|
64
|
+
help="Display application version information.\n",
|
|
65
|
+
)
|
|
66
|
+
parser.add_argument(
|
|
67
|
+
"-h",
|
|
68
|
+
"--help",
|
|
69
|
+
help="Provide additional information.\n",
|
|
70
|
+
action="help",
|
|
71
|
+
default=argparse.SUPPRESS,
|
|
72
|
+
)
|
|
73
|
+
parser.add_argument(
|
|
74
|
+
"-o",
|
|
75
|
+
"--outputpath",
|
|
76
|
+
help=(
|
|
77
|
+
"`path` Specifies one or more paths to output.xml.\n"
|
|
78
|
+
"Usage behavior:\n"
|
|
79
|
+
" • Multiple XML files: repeat '-o' for each file\n"
|
|
80
|
+
" • Accepts files or paths to files\n"
|
|
81
|
+
" • Optional tags can be provided by appending ':tag1:tag2' to the path\n"
|
|
82
|
+
"Examples:\n"
|
|
83
|
+
" • '-o path/to/output1.xml' -> add one output\n"
|
|
84
|
+
" • '-o output2.xml:dev:nightly -o output3.xml:prod' -> add two outputs with tags\n"
|
|
85
|
+
),
|
|
86
|
+
action="append",
|
|
87
|
+
nargs="*",
|
|
88
|
+
default=None,
|
|
89
|
+
)
|
|
90
|
+
parser.add_argument(
|
|
91
|
+
"-f",
|
|
92
|
+
"--outputfolderpath",
|
|
93
|
+
help=(
|
|
94
|
+
"`path` Specifies a directory path scanned recursively for *output*.xml files.\n"
|
|
95
|
+
"Usage behavior:\n"
|
|
96
|
+
" • Provide a folder path\n"
|
|
97
|
+
" • All matching *output*.xml files in all subfolders will be included\n"
|
|
98
|
+
" • Optional tags can be provided by appending ':tag1:tag2' to the path\n"
|
|
99
|
+
"Examples:\n"
|
|
100
|
+
" • '-f results/' -> scan folder for output files\n"
|
|
101
|
+
" • '-f results/' -f path/to/more_results/:prod:regression -> multiple folders with tags\n"
|
|
102
|
+
),
|
|
103
|
+
action="append",
|
|
104
|
+
nargs="*",
|
|
105
|
+
default=None,
|
|
106
|
+
)
|
|
107
|
+
parser.add_argument(
|
|
108
|
+
"--projectversion",
|
|
109
|
+
help=(
|
|
110
|
+
"`string` specifies project version associated with runs\n"
|
|
111
|
+
"Usage behaviour:\n"
|
|
112
|
+
" • Provide text to set a project version for the supplied runs\n"
|
|
113
|
+
"Examples:\n"
|
|
114
|
+
" . '--projectversion=1.1'\n"
|
|
115
|
+
" . '--projectversion=1.1'\n"
|
|
116
|
+
),
|
|
117
|
+
dest="project_version",
|
|
118
|
+
type=str,
|
|
119
|
+
default=None,
|
|
120
|
+
)
|
|
121
|
+
parser.add_argument(
|
|
122
|
+
"-r",
|
|
123
|
+
"--removeruns",
|
|
124
|
+
help=(
|
|
125
|
+
"`string` Specifies indexes, run_starts, aliases or tags to remove from the database.\n"
|
|
126
|
+
"Usage behavior:\n"
|
|
127
|
+
" • Multiple values separated by commas (,)\n"
|
|
128
|
+
" • Must specify data types: index, run_start, alias or tag\n"
|
|
129
|
+
" • Ranges supported using ':' and lists using ';'\n"
|
|
130
|
+
"Examples:\n"
|
|
131
|
+
" • '-r index=0,index=1:4;9,index=10' -> remove index 0, 1, 2, 3, 9, 10\n"
|
|
132
|
+
" • '-r run_start=2024-07-30 15:27:20.184407,index=20' -> remove specified run and index 20\n"
|
|
133
|
+
" • '-r alias=some_alias,tag=prod,tag=dev' -> remove all runs with alias some_alias or tag prod or dev\n"
|
|
134
|
+
),
|
|
135
|
+
action="append",
|
|
136
|
+
nargs="*",
|
|
137
|
+
default=None,
|
|
138
|
+
)
|
|
139
|
+
parser.add_argument(
|
|
140
|
+
"-d",
|
|
141
|
+
"--databasepath",
|
|
142
|
+
help=(
|
|
143
|
+
"`path` Specifies the path to the database file.\n"
|
|
144
|
+
"Usage behavior:\n"
|
|
145
|
+
" • Default value: robot_results.db\n"
|
|
146
|
+
" • Provide a custom .db file to use instead of the default\n"
|
|
147
|
+
"Examples:\n"
|
|
148
|
+
" • '-d path/to/myresults.db'\n"
|
|
149
|
+
),
|
|
150
|
+
default="robot_results.db",
|
|
151
|
+
)
|
|
152
|
+
parser.add_argument(
|
|
153
|
+
"-n",
|
|
154
|
+
"--namedashboard",
|
|
155
|
+
help=(
|
|
156
|
+
"`string` Specifies a custom HTML dashboard file name.\n"
|
|
157
|
+
"Usage behavior:\n"
|
|
158
|
+
" • Default value: robot_dashboard_yyyymmdd-hhssmm.html\n"
|
|
159
|
+
" • Provide a filename to override\n"
|
|
160
|
+
"Examples:\n"
|
|
161
|
+
" • '-n dashboard.html'\n"
|
|
162
|
+
),
|
|
163
|
+
default="",
|
|
164
|
+
)
|
|
165
|
+
parser.add_argument(
|
|
166
|
+
"-j",
|
|
167
|
+
"--jsonconfig",
|
|
168
|
+
help=(
|
|
169
|
+
"`path` Specifies a path to a dashboard JSON configuration.\n"
|
|
170
|
+
"Usage behavior:\n"
|
|
171
|
+
" • Default value: None\n"
|
|
172
|
+
" • File is used as the initial configuration if no config exists yet in user localstorage\n"
|
|
173
|
+
"Examples:\n"
|
|
174
|
+
" • '-j settings.json'\n"
|
|
175
|
+
),
|
|
176
|
+
default=None,
|
|
177
|
+
)
|
|
178
|
+
parser.add_argument(
|
|
179
|
+
"-t",
|
|
180
|
+
"--dashboardtitle",
|
|
181
|
+
help=(
|
|
182
|
+
"`string` Specifies the dashboard HTML title.\n"
|
|
183
|
+
"Usage behavior:\n"
|
|
184
|
+
" • Default value: Robot Framework Dashboard - yyyy-mm-dd hh:mm:ss\n"
|
|
185
|
+
" • Provide text to set a custom title\n"
|
|
186
|
+
"Examples:\n"
|
|
187
|
+
" • '-t My_Test_Dashboard'\n"
|
|
188
|
+
),
|
|
189
|
+
default="",
|
|
190
|
+
)
|
|
191
|
+
parser.add_argument(
|
|
192
|
+
"-m",
|
|
193
|
+
"--messageconfig",
|
|
194
|
+
help=(
|
|
195
|
+
"`path` Specifies a config file containing message templates.\n"
|
|
196
|
+
"Usage behavior:\n"
|
|
197
|
+
" • Default value: None\n"
|
|
198
|
+
" • File should contain lines with placeholders like ${value}\n"
|
|
199
|
+
"Examples:\n"
|
|
200
|
+
" • 'The test has failed on date: ${date}' -> example line in messages.txt\n"
|
|
201
|
+
" • 'Expected ${x} but received: ${y}' -> example line in messages.txt\n"
|
|
202
|
+
" • '-m messages.txt'\n"
|
|
203
|
+
),
|
|
204
|
+
default=None,
|
|
205
|
+
)
|
|
206
|
+
parser.add_argument(
|
|
207
|
+
"-q",
|
|
208
|
+
"--quantity",
|
|
209
|
+
help=(
|
|
210
|
+
"`integer` Specifies the number of runs shown on initial dashboard load.\n"
|
|
211
|
+
"Usage behavior:\n"
|
|
212
|
+
" • Default value: 20\n"
|
|
213
|
+
" • Provide an integer to override, the higher this number the slower initial load\n"
|
|
214
|
+
"Examples:\n"
|
|
215
|
+
" • '-q 25'\n"
|
|
216
|
+
),
|
|
217
|
+
default=None,
|
|
218
|
+
)
|
|
219
|
+
parser.add_argument(
|
|
220
|
+
"-u",
|
|
221
|
+
"--uselogs",
|
|
222
|
+
help=(
|
|
223
|
+
"`boolean` Enables clickable graphs linking to log.html.\n"
|
|
224
|
+
"Usage behavior:\n"
|
|
225
|
+
" • Default value: False\n"
|
|
226
|
+
" • Using '--uselogs' with no value -> True (reverse default)\n"
|
|
227
|
+
" • Using '--uselogs true' -> True\n"
|
|
228
|
+
" • Using '--uselogs false' -> False\n"
|
|
229
|
+
),
|
|
230
|
+
nargs="?",
|
|
231
|
+
const=True,
|
|
232
|
+
default=False,
|
|
233
|
+
)
|
|
234
|
+
|
|
235
|
+
parser.add_argument(
|
|
236
|
+
"-g",
|
|
237
|
+
"--generatedashboard",
|
|
238
|
+
help=(
|
|
239
|
+
"`boolean` Whether to generate the HTML dashboard.\n"
|
|
240
|
+
"Usage behavior:\n"
|
|
241
|
+
" • Default value: True\n"
|
|
242
|
+
" • Using '--generatedashboard' with no value -> False (reverse default)\n"
|
|
243
|
+
" • Using '--generatedashboard true' -> True\n"
|
|
244
|
+
" • Using '--generatedashboard false' -> False\n"
|
|
245
|
+
),
|
|
246
|
+
nargs="?",
|
|
247
|
+
const=False,
|
|
248
|
+
default=True,
|
|
249
|
+
)
|
|
250
|
+
|
|
251
|
+
parser.add_argument(
|
|
252
|
+
"-l",
|
|
253
|
+
"--listruns",
|
|
254
|
+
help=(
|
|
255
|
+
"`boolean` Whether runs should be listed in the dashboard.\n"
|
|
256
|
+
"Usage behavior:\n"
|
|
257
|
+
" • Default value: True\n"
|
|
258
|
+
" • Using '--listruns' with no value -> False (reverse default)\n"
|
|
259
|
+
" • Using '--listruns true' -> True\n"
|
|
260
|
+
" • Using '--listruns false' -> False\n"
|
|
261
|
+
),
|
|
262
|
+
nargs="?",
|
|
263
|
+
const=False,
|
|
264
|
+
default=True,
|
|
265
|
+
)
|
|
266
|
+
|
|
267
|
+
parser.add_argument(
|
|
268
|
+
"--offlinedependencies",
|
|
269
|
+
help=(
|
|
270
|
+
"`boolean` Use locally embedded JS/CSS instead of CDN.\n"
|
|
271
|
+
"Usage behavior:\n"
|
|
272
|
+
" • Default value: False\n"
|
|
273
|
+
" • Using '--offlinedependencies' with no value -> True (reverse default)\n"
|
|
274
|
+
" • Using '--offlinedependencies true' -> True\n"
|
|
275
|
+
" • Using '--offlinedependencies false' -> False\n"
|
|
276
|
+
),
|
|
277
|
+
nargs="?",
|
|
278
|
+
const=True,
|
|
279
|
+
default=False,
|
|
280
|
+
)
|
|
281
|
+
|
|
282
|
+
parser.add_argument(
|
|
283
|
+
"-c",
|
|
284
|
+
"--databaseclass",
|
|
285
|
+
help=(
|
|
286
|
+
"`path` Specifies a custom database class to override SQLite.\n"
|
|
287
|
+
"Usage behavior:\n"
|
|
288
|
+
" • Default value: None (built-in SQLite engine)\n"
|
|
289
|
+
" • Provide a .py file implementing a compatible database handler\n"
|
|
290
|
+
" • Detailed instructions can be found in the docs (url at the bottom of the help)\n"
|
|
291
|
+
"Examples:\n"
|
|
292
|
+
" • '-c customdb.py'\n"
|
|
293
|
+
),
|
|
294
|
+
default=None,
|
|
295
|
+
)
|
|
296
|
+
|
|
297
|
+
parser.add_argument(
|
|
298
|
+
"-s",
|
|
299
|
+
"--server",
|
|
300
|
+
nargs="?", # Makes the argument optional
|
|
301
|
+
const="default", # Value to use if the flag is given without an argument
|
|
302
|
+
help=(
|
|
303
|
+
"Starts the dashboard webserver.\n"
|
|
304
|
+
"Usage behavior:\n"
|
|
305
|
+
" • Default value: None (no webserver)\n"
|
|
306
|
+
" • Provide 'default[:username:password]'\n"
|
|
307
|
+
" • Or provide 'host:port[:username:password]'\n"
|
|
308
|
+
" • Detailed instructions can be found in the docs (url at the bottom of the help)\n"
|
|
309
|
+
"Examples:\n"
|
|
310
|
+
" • '--server' -> results in default behavior\n"
|
|
311
|
+
" • '--server default' -> default behaviour\n"
|
|
312
|
+
" • '--server 0.0.0.0:8080' -> custom host/port\n"
|
|
313
|
+
" • '--server 0.0.0.0:8080:admin:secret' -> custom host/port and admin username/password\n"
|
|
314
|
+
),
|
|
315
|
+
)
|
|
316
|
+
return parser.parse_args()
|
|
317
|
+
|
|
318
|
+
def _process_arguments(self, arguments):
|
|
319
|
+
"""handles the version execution"""
|
|
320
|
+
if arguments.version:
|
|
321
|
+
print(__version__)
|
|
322
|
+
exit(0)
|
|
323
|
+
|
|
324
|
+
# handles possible tags on all provided --outputpath
|
|
325
|
+
outputs = None
|
|
326
|
+
if arguments.outputpath:
|
|
327
|
+
outputs = []
|
|
328
|
+
for output in arguments.outputpath:
|
|
329
|
+
splitted = split(r":(?!(\/|\\))", output[0])
|
|
330
|
+
while None in splitted:
|
|
331
|
+
splitted.remove(
|
|
332
|
+
None
|
|
333
|
+
) # None values are found by re.split because of the 2 conditions
|
|
334
|
+
path = splitted[0]
|
|
335
|
+
tags = splitted[1:]
|
|
336
|
+
outputs.append([path, tags])
|
|
337
|
+
|
|
338
|
+
# handles possible tags on all provided --outputfolderpath
|
|
339
|
+
outputfolderpaths = None
|
|
340
|
+
if arguments.outputfolderpath:
|
|
341
|
+
outputfolderpaths = []
|
|
342
|
+
for folder in arguments.outputfolderpath:
|
|
343
|
+
splitted = split(r":(?!(\/|\\))", folder[0])
|
|
344
|
+
while None in splitted:
|
|
345
|
+
splitted.remove(
|
|
346
|
+
None
|
|
347
|
+
) # None values are found by re.split because of the 2 conditions
|
|
348
|
+
path = splitted[0]
|
|
349
|
+
tags = splitted[1:]
|
|
350
|
+
outputfolderpaths.append([path, tags])
|
|
351
|
+
|
|
352
|
+
# handles the processing of --removeruns
|
|
353
|
+
remove_runs = None
|
|
354
|
+
if arguments.removeruns:
|
|
355
|
+
remove_runs = []
|
|
356
|
+
for runs in arguments.removeruns:
|
|
357
|
+
parts = str(runs[0]).split(",")
|
|
358
|
+
for part in parts:
|
|
359
|
+
remove_runs.append(part)
|
|
360
|
+
|
|
361
|
+
# handles the boolean handling of relevant arguments
|
|
362
|
+
generate_dashboard = self._normalize_bool(arguments.generatedashboard, "generatedashboard")
|
|
363
|
+
list_runs = self._normalize_bool(arguments.listruns, "listruns")
|
|
364
|
+
offline_dependencies = self._normalize_bool(arguments.offlinedependencies, "offlinedependencies")
|
|
365
|
+
use_logs = self._normalize_bool(arguments.uselogs, "uselogs")
|
|
366
|
+
|
|
367
|
+
# generates the datetime used in the file dashboard name and the html title
|
|
368
|
+
generation_datetime = datetime.now()
|
|
369
|
+
|
|
370
|
+
# handles the custom test message handling
|
|
371
|
+
message_config = []
|
|
372
|
+
if arguments.messageconfig:
|
|
373
|
+
with open(arguments.messageconfig) as file:
|
|
374
|
+
for line in file:
|
|
375
|
+
message_config.append(line.strip())
|
|
376
|
+
|
|
377
|
+
# handles the json config
|
|
378
|
+
json_config = []
|
|
379
|
+
if arguments.jsonconfig:
|
|
380
|
+
with open(arguments.jsonconfig) as file:
|
|
381
|
+
json_config = file.read()
|
|
382
|
+
|
|
383
|
+
# handles the custom dashboard name
|
|
384
|
+
if arguments.namedashboard == "":
|
|
385
|
+
dashboard_name = (
|
|
386
|
+
f"robot_dashboard_{generation_datetime.strftime('%Y%m%d-%H%M%S')}.html"
|
|
387
|
+
)
|
|
388
|
+
elif not arguments.namedashboard.endswith(".html"):
|
|
389
|
+
dashboard_name = f"{arguments.namedashboard}.html"
|
|
390
|
+
else:
|
|
391
|
+
dashboard_name = arguments.namedashboard
|
|
392
|
+
|
|
393
|
+
# handles the databaseclass implementation and provides the complete path to the module
|
|
394
|
+
database_class = None
|
|
395
|
+
if arguments.databaseclass:
|
|
396
|
+
database_class = join(getcwd(), arguments.databaseclass).replace(
|
|
397
|
+
"\\.\\", "\\"
|
|
398
|
+
)
|
|
399
|
+
if not exists(database_class):
|
|
400
|
+
raise Exception(
|
|
401
|
+
f" ERROR: the provided database class did not exist in the expected path: {database_class}"
|
|
402
|
+
)
|
|
403
|
+
|
|
404
|
+
# handles the server argument
|
|
405
|
+
server_host = "127.0.0.1"
|
|
406
|
+
server_port = 8543
|
|
407
|
+
server_user = ""
|
|
408
|
+
server_pass = ""
|
|
409
|
+
if arguments.server:
|
|
410
|
+
start_server = True
|
|
411
|
+
parts = arguments.server.split(":")
|
|
412
|
+
|
|
413
|
+
if parts[0] == "default":
|
|
414
|
+
# e.g. default[:username:password]
|
|
415
|
+
if len(parts) == 3:
|
|
416
|
+
server_user = parts[1]
|
|
417
|
+
server_pass = parts[2]
|
|
418
|
+
else:
|
|
419
|
+
# e.g. host:port or host:port:username:password
|
|
420
|
+
server_host = parts[0]
|
|
421
|
+
server_port = int(parts[1])
|
|
422
|
+
if len(parts) == 4:
|
|
423
|
+
server_user = parts[2]
|
|
424
|
+
server_pass = parts[3]
|
|
425
|
+
else:
|
|
426
|
+
start_server = False
|
|
427
|
+
|
|
428
|
+
# handles the quantity argument
|
|
429
|
+
quantity = arguments.quantity
|
|
430
|
+
if quantity == None:
|
|
431
|
+
quantity = 20
|
|
432
|
+
else:
|
|
433
|
+
int(quantity)
|
|
434
|
+
|
|
435
|
+
# return all provided arguments
|
|
436
|
+
provided_args = {
|
|
437
|
+
"outputs": outputs,
|
|
438
|
+
"output_folder_paths": outputfolderpaths,
|
|
439
|
+
"database_path": arguments.databasepath,
|
|
440
|
+
"generate_dashboard": generate_dashboard,
|
|
441
|
+
"dashboard_name": dashboard_name,
|
|
442
|
+
"generation_datetime": generation_datetime,
|
|
443
|
+
"list_runs": list_runs,
|
|
444
|
+
"remove_runs": remove_runs,
|
|
445
|
+
"dashboard_title": arguments.dashboardtitle,
|
|
446
|
+
"database_class": database_class,
|
|
447
|
+
"start_server": start_server,
|
|
448
|
+
"server_host": server_host,
|
|
449
|
+
"server_port": server_port,
|
|
450
|
+
"server_user": server_user,
|
|
451
|
+
"server_pass": server_pass,
|
|
452
|
+
"json_config": json_config,
|
|
453
|
+
"message_config": message_config,
|
|
454
|
+
"quantity": quantity,
|
|
455
|
+
"use_logs": use_logs,
|
|
456
|
+
"offline_dependencies": offline_dependencies,
|
|
457
|
+
"project_version": arguments.project_version,
|
|
458
|
+
}
|
|
459
|
+
return dotdict(provided_args)
|