hardpy 0.3.0__py3-none-any.whl → 0.4.0__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.
- hardpy/__init__.py +9 -1
- hardpy/hardpy_panel/api.py +15 -0
- hardpy/hardpy_panel/frontend/dist/asset-manifest.json +3 -3
- hardpy/hardpy_panel/frontend/dist/index.html +1 -1
- hardpy/hardpy_panel/frontend/dist/static/js/main.37744128.js +3 -0
- hardpy/hardpy_panel/frontend/dist/static/js/main.37744128.js.map +1 -0
- hardpy/hardpy_panel/runner.py +2 -0
- hardpy/pytest_hardpy/db/const.py +1 -0
- hardpy/pytest_hardpy/db/schema.py +23 -2
- hardpy/pytest_hardpy/plugin.py +4 -0
- hardpy/pytest_hardpy/pytest_call.py +84 -3
- hardpy/pytest_hardpy/pytest_wrapper.py +29 -0
- hardpy/pytest_hardpy/reporter/hook_reporter.py +12 -5
- hardpy/pytest_hardpy/utils/__init__.py +17 -1
- hardpy/pytest_hardpy/utils/config_data.py +5 -1
- hardpy/pytest_hardpy/utils/dialog_box.py +100 -0
- hardpy/pytest_hardpy/utils/exception.py +7 -0
- {hardpy-0.3.0.dist-info → hardpy-0.4.0.dist-info}/METADATA +2 -2
- {hardpy-0.3.0.dist-info → hardpy-0.4.0.dist-info}/RECORD +23 -22
- hardpy/hardpy_panel/frontend/dist/static/js/main.8ef63e9b.js +0 -3
- hardpy/hardpy_panel/frontend/dist/static/js/main.8ef63e9b.js.map +0 -1
- /hardpy/hardpy_panel/frontend/dist/static/js/{main.8ef63e9b.js.LICENSE.txt → main.37744128.js.LICENSE.txt} +0 -0
- {hardpy-0.3.0.dist-info → hardpy-0.4.0.dist-info}/WHEEL +0 -0
- {hardpy-0.3.0.dist-info → hardpy-0.4.0.dist-info}/entry_points.txt +0 -0
- {hardpy-0.3.0.dist-info → hardpy-0.4.0.dist-info}/licenses/LICENSE +0 -0
hardpy/hardpy_panel/runner.py
CHANGED
|
@@ -21,6 +21,8 @@ def run():
|
|
|
21
21
|
parser.add_argument("-dbh", "--db_host", type=str, default=config.db_host, help="database hostname") # noqa: E501
|
|
22
22
|
parser.add_argument("-wh", "--web_host", type=str, default=config.web_host, help="web operator panel hostname") # noqa: E501
|
|
23
23
|
parser.add_argument("-wp", "--web_port", type=str, default=config.web_port, help="web operator panel port") # noqa: E501
|
|
24
|
+
parser.add_argument("-sp", "--sck_port", type=int, default=config.socket_port, help="internal socket port") # noqa: E501
|
|
25
|
+
parser.add_argument("-sa", "--sck_addr", type=int, default=config.socket_port, help="internal socket address") # noqa: E501
|
|
24
26
|
parser.add_argument("path", type=str, nargs='?', help="path to test directory")
|
|
25
27
|
# fmt: on
|
|
26
28
|
|
hardpy/pytest_hardpy/db/const.py
CHANGED
|
@@ -29,12 +29,23 @@ class CaseStateStore(IBaseResult):
|
|
|
29
29
|
"start_time": 1695817188,
|
|
30
30
|
"stop_time": 1695817189,
|
|
31
31
|
"assertion_msg": null,
|
|
32
|
-
"msg": null
|
|
32
|
+
"msg": null,
|
|
33
|
+
"dialog_box": {
|
|
34
|
+
"title_bar": "Example of text input",
|
|
35
|
+
"dialog_text": "Type some text and press the Confirm button",
|
|
36
|
+
"widget": {
|
|
37
|
+
"info": {
|
|
38
|
+
"text": "some text"
|
|
39
|
+
},
|
|
40
|
+
"type": "textinput"
|
|
41
|
+
}
|
|
42
|
+
}
|
|
33
43
|
}
|
|
34
44
|
"""
|
|
35
45
|
|
|
36
46
|
assertion_msg: str | None = None
|
|
37
47
|
msg: dict | None = None
|
|
48
|
+
dialog_box: dict = {}
|
|
38
49
|
|
|
39
50
|
|
|
40
51
|
class CaseRunStore(IBaseResult):
|
|
@@ -175,7 +186,17 @@ class ResultStateStore(IBaseResult):
|
|
|
175
186
|
"start_time": 1695817263,
|
|
176
187
|
"stop_time": 1695817264,
|
|
177
188
|
"assertion_msg": null,
|
|
178
|
-
"msg": null
|
|
189
|
+
"msg": null,
|
|
190
|
+
"dialog_box": {
|
|
191
|
+
"title_bar": "Example of text input",
|
|
192
|
+
"dialog_text": "Type some text and press the Confirm button",
|
|
193
|
+
"widget": {
|
|
194
|
+
"info": {
|
|
195
|
+
"text": "some text"
|
|
196
|
+
},
|
|
197
|
+
"type": "textinput"
|
|
198
|
+
}
|
|
199
|
+
}
|
|
179
200
|
},
|
|
180
201
|
"test_minute_parity": {
|
|
181
202
|
"status": "failed",
|
hardpy/pytest_hardpy/plugin.py
CHANGED
|
@@ -40,6 +40,8 @@ def pytest_addoption(parser: Parser):
|
|
|
40
40
|
parser.addoption("--hardpy-dbp", action="store", default=config_data.db_port, help="database port number") # noqa: E501
|
|
41
41
|
parser.addoption("--hardpy-dbh", action="store", default=config_data.db_host, help="database hostname") # noqa: E501
|
|
42
42
|
parser.addoption("--hardpy-pt", action="store_true", default=False, help="enable pytest-hardpy plugin") # noqa: E501
|
|
43
|
+
parser.addoption("--hardpy-sp", action="store", default=config_data.socket_port, help="internal socket port") # noqa: E501
|
|
44
|
+
parser.addoption("--hardpy-sa", action="store", default=config_data.socket_addr, help="internal socket address") # noqa: E501
|
|
43
45
|
# fmt: on
|
|
44
46
|
|
|
45
47
|
|
|
@@ -77,6 +79,8 @@ class HardpyPlugin(object):
|
|
|
77
79
|
config_data.db_host = config.getoption("--hardpy-dbh")
|
|
78
80
|
config_data.db_pswd = config.getoption("--hardpy-dbpw")
|
|
79
81
|
config_data.db_port = config.getoption("--hardpy-dbp")
|
|
82
|
+
config_data.socket_port = int(config.getoption("--hardpy-sp"))
|
|
83
|
+
config_data.socket_addr = config.getoption("--hardpy-sa")
|
|
80
84
|
|
|
81
85
|
config.addinivalue_line("markers", "case_name")
|
|
82
86
|
config.addinivalue_line("markers", "module_name")
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
# Copyright (c) 2024 Everypin
|
|
2
2
|
# GNU General Public License v3.0 (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
|
|
3
3
|
|
|
4
|
+
import socket
|
|
4
5
|
from os import environ
|
|
5
6
|
from dataclasses import dataclass
|
|
6
|
-
from typing import Optional
|
|
7
|
+
from typing import Optional, Any
|
|
7
8
|
from uuid import uuid4
|
|
8
9
|
|
|
9
10
|
from pycouchdb.exceptions import NotFound
|
|
@@ -14,7 +15,14 @@ from hardpy.pytest_hardpy.db import (
|
|
|
14
15
|
ResultRunStore,
|
|
15
16
|
RunStore,
|
|
16
17
|
)
|
|
17
|
-
from hardpy.pytest_hardpy.utils import
|
|
18
|
+
from hardpy.pytest_hardpy.utils import (
|
|
19
|
+
DuplicateSerialNumberError,
|
|
20
|
+
DuplicateDialogBoxError,
|
|
21
|
+
DialogBox,
|
|
22
|
+
ConfigData,
|
|
23
|
+
generate_dialog_box_dict,
|
|
24
|
+
get_dialog_box_data,
|
|
25
|
+
)
|
|
18
26
|
from hardpy.pytest_hardpy.reporter import RunnerReporter
|
|
19
27
|
|
|
20
28
|
|
|
@@ -184,7 +192,7 @@ def set_run_artifact(data: dict):
|
|
|
184
192
|
|
|
185
193
|
|
|
186
194
|
def set_driver_info(drivers: dict) -> None:
|
|
187
|
-
"""
|
|
195
|
+
"""Add or update drivers data.
|
|
188
196
|
|
|
189
197
|
Driver data is stored in both StateStore and RunStore databases.
|
|
190
198
|
|
|
@@ -203,6 +211,56 @@ def set_driver_info(drivers: dict) -> None:
|
|
|
203
211
|
reporter.update_db_by_doc()
|
|
204
212
|
|
|
205
213
|
|
|
214
|
+
def run_dialog_box(dialog_box_data: DialogBox) -> Any:
|
|
215
|
+
"""Display a dialog box.
|
|
216
|
+
|
|
217
|
+
Args:
|
|
218
|
+
dialog_box_data (DialogBox): Data for creating the dialog box.
|
|
219
|
+
|
|
220
|
+
DialogBox attributes:
|
|
221
|
+
|
|
222
|
+
- dialog_text (str): The text of the dialog box.
|
|
223
|
+
- title_bar (str | None): The title bar of the dialog box.
|
|
224
|
+
If the title_bar field is missing, it is the case name.
|
|
225
|
+
- widget (DialogBoxWidget | None): Widget information.
|
|
226
|
+
|
|
227
|
+
Returns:
|
|
228
|
+
Any: An object containing the user's response.
|
|
229
|
+
|
|
230
|
+
The type of the return value depends on the widget type:
|
|
231
|
+
|
|
232
|
+
- Without widget: None.
|
|
233
|
+
- TEXT_INPUT: str.
|
|
234
|
+
- NUMERIC_INPUT: float.
|
|
235
|
+
|
|
236
|
+
Raises:
|
|
237
|
+
ValueError: If the 'message' argument is empty.
|
|
238
|
+
DuplicateDialogBoxError: If the dialog box is already caused.
|
|
239
|
+
"""
|
|
240
|
+
if not dialog_box_data.dialog_text:
|
|
241
|
+
raise ValueError("The 'dialog_text' argument cannot be empty.")
|
|
242
|
+
|
|
243
|
+
current_test = _get_current_test()
|
|
244
|
+
reporter = RunnerReporter()
|
|
245
|
+
key = reporter.generate_key(
|
|
246
|
+
DF.MODULES,
|
|
247
|
+
current_test.module_id,
|
|
248
|
+
DF.CASES,
|
|
249
|
+
current_test.case_id,
|
|
250
|
+
DF.DIALOG_BOX,
|
|
251
|
+
)
|
|
252
|
+
if reporter.get_field(key):
|
|
253
|
+
raise DuplicateDialogBoxError
|
|
254
|
+
data_dict = generate_dialog_box_dict(dialog_box_data)
|
|
255
|
+
|
|
256
|
+
reporter.set_doc_value(key, data_dict, statestore_only=True)
|
|
257
|
+
reporter.update_db_by_doc()
|
|
258
|
+
|
|
259
|
+
dialog_raw_data = _get_socket_raw_data()
|
|
260
|
+
|
|
261
|
+
return get_dialog_box_data(dialog_raw_data, dialog_box_data.widget)
|
|
262
|
+
|
|
263
|
+
|
|
206
264
|
def _get_current_test() -> CurrentTestInfo:
|
|
207
265
|
current_node = environ.get("PYTEST_CURRENT_TEST")
|
|
208
266
|
|
|
@@ -224,3 +282,26 @@ def _get_current_test() -> CurrentTestInfo:
|
|
|
224
282
|
case_id = case_with_stage[:case_id_end_index]
|
|
225
283
|
|
|
226
284
|
return CurrentTestInfo(module_id=module_id, case_id=case_id)
|
|
285
|
+
|
|
286
|
+
|
|
287
|
+
def _get_socket_raw_data() -> str:
|
|
288
|
+
# create socket connection
|
|
289
|
+
server = socket.socket()
|
|
290
|
+
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
|
291
|
+
config_data = ConfigData()
|
|
292
|
+
try:
|
|
293
|
+
server.bind((config_data.socket_addr, config_data.socket_port))
|
|
294
|
+
except socket.error as exc:
|
|
295
|
+
raise RuntimeError(f"Error creating socket: {exc}")
|
|
296
|
+
server.listen(1)
|
|
297
|
+
client, _ = server.accept()
|
|
298
|
+
|
|
299
|
+
# receive data
|
|
300
|
+
max_input_data_len = 1024
|
|
301
|
+
socket_data = client.recv(max_input_data_len).decode("utf-8")
|
|
302
|
+
|
|
303
|
+
# close connection
|
|
304
|
+
client.close()
|
|
305
|
+
server.close()
|
|
306
|
+
|
|
307
|
+
return socket_data
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
import sys
|
|
5
5
|
import signal
|
|
6
6
|
import subprocess
|
|
7
|
+
from socket import socket
|
|
7
8
|
from platform import system
|
|
8
9
|
|
|
9
10
|
from hardpy.pytest_hardpy.utils.config_data import ConfigData
|
|
@@ -46,6 +47,10 @@ class PyTestWrapper(object):
|
|
|
46
47
|
self.config.db_user,
|
|
47
48
|
"--hardpy-dbpw",
|
|
48
49
|
self.config.db_pswd,
|
|
50
|
+
"--hardpy-sp",
|
|
51
|
+
str(self.config.socket_port),
|
|
52
|
+
"--hardpy-sa",
|
|
53
|
+
self.config.socket_addr,
|
|
49
54
|
"--hardpy-pt",
|
|
50
55
|
],
|
|
51
56
|
cwd=self.config.tests_dir.absolute(),
|
|
@@ -64,6 +69,10 @@ class PyTestWrapper(object):
|
|
|
64
69
|
self.config.db_user,
|
|
65
70
|
"--hardpy-dbpw",
|
|
66
71
|
self.config.db_pswd,
|
|
72
|
+
"--hardpy-sp",
|
|
73
|
+
str(self.config.socket_port),
|
|
74
|
+
"--hardpy-sa",
|
|
75
|
+
self.config.socket_addr,
|
|
67
76
|
"--hardpy-pt",
|
|
68
77
|
],
|
|
69
78
|
cwd=self.config.tests_dir.absolute(),
|
|
@@ -115,6 +124,26 @@ class PyTestWrapper(object):
|
|
|
115
124
|
)
|
|
116
125
|
return True
|
|
117
126
|
|
|
127
|
+
def confirm_dialog_box(self, dialog_box_output: str):
|
|
128
|
+
"""Set dialog box data to pytest subprocess.
|
|
129
|
+
|
|
130
|
+
Args:
|
|
131
|
+
dialog_box_output (str): dialog box output data
|
|
132
|
+
|
|
133
|
+
Returns:
|
|
134
|
+
bool: True if dialog box was confirmed, else False
|
|
135
|
+
"""
|
|
136
|
+
config_data = ConfigData()
|
|
137
|
+
|
|
138
|
+
try:
|
|
139
|
+
client = socket()
|
|
140
|
+
client.connect((config_data.socket_addr, config_data.socket_port))
|
|
141
|
+
client.sendall(dialog_box_output.encode("utf-8"))
|
|
142
|
+
client.close()
|
|
143
|
+
except Exception:
|
|
144
|
+
return False
|
|
145
|
+
return True
|
|
146
|
+
|
|
118
147
|
def is_running(self) -> bool | None:
|
|
119
148
|
"""Check if pytest is running."""
|
|
120
149
|
return self._proc and self._proc.poll() is None
|
|
@@ -90,8 +90,8 @@ class HookReporter(BaseReporter):
|
|
|
90
90
|
item_statestore = self._statestore.get_field(key)
|
|
91
91
|
item_runstore = self._runstore.get_field(key)
|
|
92
92
|
|
|
93
|
-
self._init_case(item_statestore, node_info)
|
|
94
|
-
self._init_case(item_runstore, node_info,
|
|
93
|
+
self._init_case(item_statestore, node_info, is_only_statestore=True)
|
|
94
|
+
self._init_case(item_runstore, node_info, is_only_runstore=True)
|
|
95
95
|
|
|
96
96
|
self.set_doc_value(key, item_statestore, statestore_only=True)
|
|
97
97
|
self.set_doc_value(key, item_runstore, runstore_only=True)
|
|
@@ -176,7 +176,11 @@ class HookReporter(BaseReporter):
|
|
|
176
176
|
self.set_doc_value(key, int(time()))
|
|
177
177
|
|
|
178
178
|
def _init_case(
|
|
179
|
-
self,
|
|
179
|
+
self,
|
|
180
|
+
item: dict,
|
|
181
|
+
node_info: NodeInfo,
|
|
182
|
+
is_only_runstore: bool = False,
|
|
183
|
+
is_only_statestore: bool = False,
|
|
180
184
|
):
|
|
181
185
|
module_default = { # noqa: WPS204
|
|
182
186
|
DF.STATUS: TestStatus.READY,
|
|
@@ -195,7 +199,7 @@ class HookReporter(BaseReporter):
|
|
|
195
199
|
}
|
|
196
200
|
|
|
197
201
|
if item.get(node_info.module_id) is None: # noqa: WPS204
|
|
198
|
-
if
|
|
202
|
+
if is_only_runstore:
|
|
199
203
|
module_default[DF.ARTIFACT] = {}
|
|
200
204
|
item[node_info.module_id] = module_default # noqa: WPS204
|
|
201
205
|
else:
|
|
@@ -205,8 +209,11 @@ class HookReporter(BaseReporter):
|
|
|
205
209
|
item[node_info.module_id][DF.STOP_TIME] = None
|
|
206
210
|
item[node_info.module_id][DF.NAME] = self._get_module_name(node_info)
|
|
207
211
|
|
|
208
|
-
if
|
|
212
|
+
if is_only_runstore:
|
|
209
213
|
case_default[DF.ARTIFACT] = {}
|
|
214
|
+
|
|
215
|
+
if is_only_statestore:
|
|
216
|
+
case_default[DF.DIALOG_BOX] = {}
|
|
210
217
|
item[node_info.module_id][DF.CASES][node_info.case_id] = case_default
|
|
211
218
|
|
|
212
219
|
def _remove_outdate_node(
|
|
@@ -6,7 +6,17 @@ from hardpy.pytest_hardpy.utils.progress_calculator import ProgressCalculator
|
|
|
6
6
|
from hardpy.pytest_hardpy.utils.const import TestStatus, RunStatus
|
|
7
7
|
from hardpy.pytest_hardpy.utils.singleton import Singleton
|
|
8
8
|
from hardpy.pytest_hardpy.utils.config_data import ConfigData
|
|
9
|
-
from hardpy.pytest_hardpy.utils.exception import
|
|
9
|
+
from hardpy.pytest_hardpy.utils.exception import (
|
|
10
|
+
DuplicateSerialNumberError,
|
|
11
|
+
DuplicateDialogBoxError,
|
|
12
|
+
)
|
|
13
|
+
from hardpy.pytest_hardpy.utils.dialog_box import (
|
|
14
|
+
DialogBox,
|
|
15
|
+
DialogBoxWidget,
|
|
16
|
+
DialogBoxWidgetType,
|
|
17
|
+
generate_dialog_box_dict,
|
|
18
|
+
get_dialog_box_data,
|
|
19
|
+
)
|
|
10
20
|
|
|
11
21
|
__all__ = [
|
|
12
22
|
"NodeInfo",
|
|
@@ -16,4 +26,10 @@ __all__ = [
|
|
|
16
26
|
"Singleton",
|
|
17
27
|
"ConfigData",
|
|
18
28
|
"DuplicateSerialNumberError",
|
|
29
|
+
"DuplicateDialogBoxError",
|
|
30
|
+
"DialogBox",
|
|
31
|
+
"DialogBoxWidget",
|
|
32
|
+
"DialogBoxWidgetType",
|
|
33
|
+
"generate_dialog_box_dict",
|
|
34
|
+
"get_dialog_box_data",
|
|
19
35
|
]
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
# Copyright (c) 2024 Everypin
|
|
2
2
|
# GNU General Public License v3.0 (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
|
|
3
3
|
|
|
4
|
-
from
|
|
4
|
+
from socket import gethostname
|
|
5
5
|
from pathlib import Path
|
|
6
6
|
|
|
7
|
+
from hardpy.pytest_hardpy.utils.singleton import Singleton
|
|
8
|
+
|
|
7
9
|
|
|
8
10
|
class ConfigData(Singleton):
|
|
9
11
|
"""Web connection data storage."""
|
|
@@ -17,6 +19,8 @@ class ConfigData(Singleton):
|
|
|
17
19
|
self.web_host: str = "0.0.0.0"
|
|
18
20
|
self.web_port: int = 8000
|
|
19
21
|
self.tests_dir = Path.cwd()
|
|
22
|
+
self.socket_port: int = 6525
|
|
23
|
+
self.socket_addr: str = gethostname()
|
|
20
24
|
self._initialized = True
|
|
21
25
|
|
|
22
26
|
@property
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
# Copyright (c) 2024 Everypin
|
|
2
|
+
# GNU General Public License v3.0 (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
|
|
3
|
+
|
|
4
|
+
from enum import Enum
|
|
5
|
+
from dataclasses import dataclass
|
|
6
|
+
from typing import Any
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class DialogBoxWidgetType(Enum):
|
|
10
|
+
"""Dialog box widget type."""
|
|
11
|
+
|
|
12
|
+
RADIOBUTTON = "radiobutton"
|
|
13
|
+
CHECKBOX = "checkbox"
|
|
14
|
+
TEXT_INPUT = "textinput"
|
|
15
|
+
NUMERIC_INPUT = "numericinput"
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
@dataclass
|
|
19
|
+
class DialogBoxWidget:
|
|
20
|
+
"""Dialog box widget.
|
|
21
|
+
|
|
22
|
+
Args:
|
|
23
|
+
type (DialogBoxWidgetType): widget type
|
|
24
|
+
info (dict | None): widget info
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
type: DialogBoxWidgetType
|
|
28
|
+
info: dict | None = None
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
@dataclass
|
|
32
|
+
class DialogBox:
|
|
33
|
+
"""Dialog box data.
|
|
34
|
+
|
|
35
|
+
Args:
|
|
36
|
+
dialog_text (str): dialog text
|
|
37
|
+
title_bar (str | None): title bar
|
|
38
|
+
widget (DialogBoxWidget | None): widget info
|
|
39
|
+
"""
|
|
40
|
+
|
|
41
|
+
dialog_text: str
|
|
42
|
+
title_bar: str | None = None
|
|
43
|
+
widget: DialogBoxWidget | None = None
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def generate_dialog_box_dict(dialog_box_data: DialogBox) -> dict:
|
|
47
|
+
"""Generate dialog box dictionary.
|
|
48
|
+
|
|
49
|
+
Args:
|
|
50
|
+
dialog_box_data (DialogBox): dialog box data
|
|
51
|
+
|
|
52
|
+
Returns:
|
|
53
|
+
dict: dialog box dictionary
|
|
54
|
+
"""
|
|
55
|
+
if dialog_box_data.widget is None:
|
|
56
|
+
data_dict = {
|
|
57
|
+
"title_bar": dialog_box_data.title_bar,
|
|
58
|
+
"dialog_text": dialog_box_data.dialog_text,
|
|
59
|
+
"widget": None,
|
|
60
|
+
}
|
|
61
|
+
else:
|
|
62
|
+
data_dict = {
|
|
63
|
+
"title_bar": dialog_box_data.title_bar,
|
|
64
|
+
"dialog_text": dialog_box_data.dialog_text,
|
|
65
|
+
"widget": {
|
|
66
|
+
"info": dialog_box_data.widget.info,
|
|
67
|
+
"type": dialog_box_data.widget.type.value,
|
|
68
|
+
},
|
|
69
|
+
}
|
|
70
|
+
return data_dict
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def get_dialog_box_data(
|
|
74
|
+
input_data: str, widget: DialogBoxWidget | None
|
|
75
|
+
) -> Any:
|
|
76
|
+
"""Get the dialog box data in the correct format.
|
|
77
|
+
|
|
78
|
+
Args:
|
|
79
|
+
input_data (str): input string
|
|
80
|
+
widget (DialogBoxWidget | None): widget info
|
|
81
|
+
|
|
82
|
+
Returns:
|
|
83
|
+
Any: Dialog box data in the correct format
|
|
84
|
+
"""
|
|
85
|
+
if widget is None:
|
|
86
|
+
return None
|
|
87
|
+
|
|
88
|
+
if widget.type is None:
|
|
89
|
+
raise ValueError("Widget type is `None`, but widget data is not empty")
|
|
90
|
+
|
|
91
|
+
match widget.type:
|
|
92
|
+
case DialogBoxWidgetType.NUMERIC_INPUT:
|
|
93
|
+
try:
|
|
94
|
+
return float(input_data)
|
|
95
|
+
except ValueError:
|
|
96
|
+
return None
|
|
97
|
+
case DialogBoxWidgetType.TEXT_INPUT:
|
|
98
|
+
return input_data
|
|
99
|
+
case _:
|
|
100
|
+
return None
|
|
@@ -14,3 +14,10 @@ class DuplicateSerialNumberError(HardpyError):
|
|
|
14
14
|
|
|
15
15
|
def __init__(self):
|
|
16
16
|
super().__init__(self.__doc__) # type: ignore
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class DuplicateDialogBoxError(HardpyError):
|
|
20
|
+
"""The dialog box has already been determined."""
|
|
21
|
+
|
|
22
|
+
def __init__(self):
|
|
23
|
+
super().__init__(self.__doc__) # type: ignore
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: hardpy
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.4.0
|
|
4
4
|
Summary: HardPy library for device testing
|
|
5
5
|
Project-URL: repository, https://github.com/everypindevices/hardpy
|
|
6
6
|
Author: Everypin
|
|
@@ -62,7 +62,7 @@ HardPy is a python library for creating a test bench for devices.
|
|
|
62
62
|
HardPy allows you to:
|
|
63
63
|
|
|
64
64
|
* Create test benches for devices using [pytest](https://docs.pytest.org/);
|
|
65
|
-
* Use a browser to view,
|
|
65
|
+
* Use a browser to view, start, stop, and interact with tests;
|
|
66
66
|
* Store test results in the [CouchDB](https://couchdb.apache.org/) database.
|
|
67
67
|
|
|
68
68
|
## To Install
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
hardpy/__init__.py,sha256=
|
|
1
|
+
hardpy/__init__.py,sha256=kn64nKBEVYJMYJedvIV2sQqR1ucoes_LeO7gemwO7oA,1043
|
|
2
2
|
hardpy/hardpy_panel/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
3
|
-
hardpy/hardpy_panel/api.py,sha256=
|
|
4
|
-
hardpy/hardpy_panel/runner.py,sha256=
|
|
5
|
-
hardpy/hardpy_panel/frontend/dist/asset-manifest.json,sha256=
|
|
3
|
+
hardpy/hardpy_panel/api.py,sha256=zm24Spyhl7bqqJTcfyIydajq0_mqrAaxzac53V-Y_-Q,1979
|
|
4
|
+
hardpy/hardpy_panel/runner.py,sha256=lJFVFAbh-y6utBKW7pEqlbAPgS1PLGTP3s-YRE52Sq4,2121
|
|
5
|
+
hardpy/hardpy_panel/frontend/dist/asset-manifest.json,sha256=dknw2XV7tgYq_ciUOwtYAon3pURFH1LNSEpgbcCDehw,2824
|
|
6
6
|
hardpy/hardpy_panel/frontend/dist/favicon.ico,sha256=sgIk5PKUKEKBDpkSrc8dJgjpObp0iF82Mec0GpfKId4,15406
|
|
7
|
-
hardpy/hardpy_panel/frontend/dist/index.html,sha256=
|
|
7
|
+
hardpy/hardpy_panel/frontend/dist/index.html,sha256=RLLhIgyucL-mXa6EWwU9_ZH6QFgyUhFAfKuyZ6cVYc0,656
|
|
8
8
|
hardpy/hardpy_panel/frontend/dist/logo512.png,sha256=-fIMbqX7PYUpheK4kX1C1erRTe_hHZwFQYDLrAbhFRU,34188
|
|
9
9
|
hardpy/hardpy_panel/frontend/dist/manifest.json,sha256=PfmJlN2JMJtHS6OnhU4b4X5wPQC_yRBdjesjoirObSA,502
|
|
10
10
|
hardpy/hardpy_panel/frontend/dist/static/css/main.e8a862f1.css,sha256=gNl6kGMBhtswNrUU6X2S6uosRU7xhxqI_p9gsEtBUqE,318244
|
|
@@ -21,9 +21,9 @@ hardpy/hardpy_panel/frontend/dist/static/js/blueprint-icons-all-paths.f63155c9.c
|
|
|
21
21
|
hardpy/hardpy_panel/frontend/dist/static/js/blueprint-icons-all-paths.f63155c9.chunk.js.map,sha256=p1xKHRK4AZutkZsQHiWSNU61tYp7I3iUuyLLm3eqkHQ,2833
|
|
22
22
|
hardpy/hardpy_panel/frontend/dist/static/js/blueprint-icons-split-paths-by-size-loader.52a072d3.chunk.js,sha256=Jl5xm_jQ9IXKhCagHHvnIhwYXb379Q5FFBiqPoKdUIE,605
|
|
23
23
|
hardpy/hardpy_panel/frontend/dist/static/js/blueprint-icons-split-paths-by-size-loader.52a072d3.chunk.js.map,sha256=amJiG2QaJMRR9Y2M0C2soOqd75xdQHhsVKjwrDSIIT0,2224
|
|
24
|
-
hardpy/hardpy_panel/frontend/dist/static/js/main.
|
|
25
|
-
hardpy/hardpy_panel/frontend/dist/static/js/main.
|
|
26
|
-
hardpy/hardpy_panel/frontend/dist/static/js/main.
|
|
24
|
+
hardpy/hardpy_panel/frontend/dist/static/js/main.37744128.js,sha256=ssTeNO5sKL6UzOS2wHRWcbOjD8pp951j5cVNEGMd3Gs,1050817
|
|
25
|
+
hardpy/hardpy_panel/frontend/dist/static/js/main.37744128.js.LICENSE.txt,sha256=ForPNukClWMEP3pF9LMYoU-ve-LsyCH-rYU8eLki_FY,2315
|
|
26
|
+
hardpy/hardpy_panel/frontend/dist/static/js/main.37744128.js.map,sha256=6jCBcnbF5mXljOi7LGADG-lE2NN1oWTo5h5dGdNMBS8,5247867
|
|
27
27
|
hardpy/hardpy_panel/frontend/dist/static/media/blueprint-icons-16.520846c6beb41df528c8.eot,sha256=PTCTrQYNHX2hIPUaYWtOKrI30-iQGXt_EGxq6JCXie0,117628
|
|
28
28
|
hardpy/hardpy_panel/frontend/dist/static/media/blueprint-icons-16.5c52b39c697f2323ce8b.svg,sha256=lDCQy06aS-9bmhwuFOUs-EdcR8MP2wqwAwky5oamtkQ,509417
|
|
29
29
|
hardpy/hardpy_panel/frontend/dist/static/media/blueprint-icons-16.84db1772f4bfb529f64f.woff,sha256=edyqQN0nw4dNBs1pgr7pQB7nJhhR6T_YfklFcG_fHj0,53344
|
|
@@ -36,20 +36,20 @@ hardpy/hardpy_panel/frontend/dist/static/media/blueprint-icons-20.afbadb627d43b7
|
|
|
36
36
|
hardpy/hardpy_panel/frontend/dist/static/media/blueprint-icons-20.e857f5a5132b8bfa71a1.woff,sha256=mQZTxE1PyyAL16VWuASOvXlZFwuI4aCPvbrhfgpdIdU,55356
|
|
37
37
|
hardpy/hardpy_panel/frontend/dist/static/media/logo_smol.5b16f92447a4a9e80331.png,sha256=E4K7drvhJCg9HcTpRihOXZhVJVBZ7-W97Se-3tDb46o,14485
|
|
38
38
|
hardpy/pytest_hardpy/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
39
|
-
hardpy/pytest_hardpy/plugin.py,sha256=
|
|
40
|
-
hardpy/pytest_hardpy/pytest_call.py,sha256=
|
|
41
|
-
hardpy/pytest_hardpy/pytest_wrapper.py,sha256=
|
|
39
|
+
hardpy/pytest_hardpy/plugin.py,sha256=JjVFuAiea5sP_G1kQ1LJKJf2pZ6iWKqJuasu5mU4rWY,11369
|
|
40
|
+
hardpy/pytest_hardpy/pytest_call.py,sha256=ds3Xofm_gbqCVvM99qFonp8l6dbI2UDQ8URqn3A1TWc,8449
|
|
41
|
+
hardpy/pytest_hardpy/pytest_wrapper.py,sha256=18kCuS-TVXcXC2QiMsrbc5gHjv48tIMv0F3xAJCdi_U,4508
|
|
42
42
|
hardpy/pytest_hardpy/db/__init__.py,sha256=MxDufncz0zgRAxrndvPXXW4NrU7rRP7MzIrR7S5Cwwo,558
|
|
43
43
|
hardpy/pytest_hardpy/db/base_connector.py,sha256=7KUgPY-GmAo8MFN4OFpG5y3WH1xjohRnpeQ1gxQF1tg,751
|
|
44
44
|
hardpy/pytest_hardpy/db/base_server.py,sha256=uBnq5zGkzEIq_EGzLw0C8kfDEDvQyN52Y6L41KKL9FQ,397
|
|
45
45
|
hardpy/pytest_hardpy/db/base_store.py,sha256=DiYaBOwufEOdtDpo9dUb3ZaZ7-c1FInAWjLpUXSEFHA,2668
|
|
46
|
-
hardpy/pytest_hardpy/db/const.py,sha256=
|
|
46
|
+
hardpy/pytest_hardpy/db/const.py,sha256=b4Hq0gaT8SF5YBg21EIHoF3RMMHD3nRJBpvGmvVYQn0,648
|
|
47
47
|
hardpy/pytest_hardpy/db/runstore.py,sha256=50amoTIO7OTqd5Ks1_7uTzqjCldLpTapkxbIQOgj1sQ,1023
|
|
48
|
-
hardpy/pytest_hardpy/db/schema.py,sha256=
|
|
48
|
+
hardpy/pytest_hardpy/db/schema.py,sha256=AAf1qXEge0Bd2xwwx4A2DBOtUkbE36DTpbsOPczPUZ4,7529
|
|
49
49
|
hardpy/pytest_hardpy/db/statestore.py,sha256=1BUfA4oqG4vx7z5v_uUYi_Un6YA769JeuShxDicrl9Q,636
|
|
50
50
|
hardpy/pytest_hardpy/reporter/__init__.py,sha256=RONapygH3c_FyXokAlyCVJXGV2cV_jCYDxLymvvA1uE,322
|
|
51
51
|
hardpy/pytest_hardpy/reporter/base.py,sha256=M-lwli64ty9FW8HlGEpUyoFsZv48tyNgzPjCWVUrATY,1941
|
|
52
|
-
hardpy/pytest_hardpy/reporter/hook_reporter.py,sha256=
|
|
52
|
+
hardpy/pytest_hardpy/reporter/hook_reporter.py,sha256=kZ3jx--ne9l3a27TmVdZCPBoqy53EuHYg2fHDGuJNes,10068
|
|
53
53
|
hardpy/pytest_hardpy/reporter/runner_reporter.py,sha256=NXkBIoERqmLI-GYtHavmOWC5t6NIpcAE-NECrUKIAJs,827
|
|
54
54
|
hardpy/pytest_hardpy/result/__init__.py,sha256=NMeCGx3yh8ds9VpaUpuNFDxbwgYFq3e-o7W6rYIv8uI,346
|
|
55
55
|
hardpy/pytest_hardpy/result/couchdb_config.py,sha256=QZryfA2QoHIjzbVT3OAD76DCNppCghtRWdZMZ5v7KhY,611
|
|
@@ -57,15 +57,16 @@ hardpy/pytest_hardpy/result/report_loader/__init__.py,sha256=FuHuD6IFZyaKj0yu5ur
|
|
|
57
57
|
hardpy/pytest_hardpy/result/report_loader/couchdb_loader.py,sha256=1BGncK1NnwYJanm5TYETjMkqR7tmrUfGK8Sgnp2JZC8,2203
|
|
58
58
|
hardpy/pytest_hardpy/result/report_reader/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
59
59
|
hardpy/pytest_hardpy/result/report_reader/couchdb_reader.py,sha256=WqetspIsQzu3iJ_HGo3XNkx4iXj6RC9o_SaRqyT-c-c,5634
|
|
60
|
-
hardpy/pytest_hardpy/utils/__init__.py,sha256=
|
|
61
|
-
hardpy/pytest_hardpy/utils/config_data.py,sha256=
|
|
60
|
+
hardpy/pytest_hardpy/utils/__init__.py,sha256=nG06N4aT95i7RU-xIzFu18nbz4Jtg-5kJlBtodg8kes,1049
|
|
61
|
+
hardpy/pytest_hardpy/utils/config_data.py,sha256=953nSUndqfiqk6oVMb7GYA4RYCFPIKkPpSthXgKtKKY,1113
|
|
62
62
|
hardpy/pytest_hardpy/utils/const.py,sha256=rjW1Rzhe2vCr8GeQqeN_pafepGDYhjhY4u1VfTOVI6U,625
|
|
63
|
-
hardpy/pytest_hardpy/utils/
|
|
63
|
+
hardpy/pytest_hardpy/utils/dialog_box.py,sha256=TC2kNFOmvu0-Z84aT-sV3IW50Ii5pucoxmIYN-7_csY,2460
|
|
64
|
+
hardpy/pytest_hardpy/utils/exception.py,sha256=VRBYs8zL7r2L1VTe_G336HYpjNdJ_ajwyxioFFhERUk,637
|
|
64
65
|
hardpy/pytest_hardpy/utils/node_info.py,sha256=VnEbhKBNAL5xpuFtJTCg90TmkjkFCQA59F5W2RcOlx4,3157
|
|
65
66
|
hardpy/pytest_hardpy/utils/progress_calculator.py,sha256=r0qb3p6_yDIyLeCshF3Ceo5pCzd3BoTahL4rCD2oMNw,1041
|
|
66
67
|
hardpy/pytest_hardpy/utils/singleton.py,sha256=C8cgRDydnG2b5dcN1LCLw4aM-AUMAvJc1W39mTkNWlQ,614
|
|
67
|
-
hardpy-0.
|
|
68
|
-
hardpy-0.
|
|
69
|
-
hardpy-0.
|
|
70
|
-
hardpy-0.
|
|
71
|
-
hardpy-0.
|
|
68
|
+
hardpy-0.4.0.dist-info/METADATA,sha256=Zy37donDAM87tsAVl6m8Qk7BYIPLf5J-ctoxrTpJowo,4113
|
|
69
|
+
hardpy-0.4.0.dist-info/WHEEL,sha256=TJPnKdtrSue7xZ_AVGkp9YXcvDrobsjBds1du3Nx6dc,87
|
|
70
|
+
hardpy-0.4.0.dist-info/entry_points.txt,sha256=q73g5GfznSUpjkayi0SV4uaAtrf7D-7rmDoWoEZmZe0,120
|
|
71
|
+
hardpy-0.4.0.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
|
|
72
|
+
hardpy-0.4.0.dist-info/RECORD,,
|