hardpy 0.13.0__py3-none-any.whl → 0.15.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.
Files changed (38) hide show
  1. hardpy/__init__.py +45 -10
  2. hardpy/cli/cli.py +32 -28
  3. hardpy/common/config.py +5 -4
  4. hardpy/common/stand_cloud/connector.py +2 -2
  5. hardpy/hardpy_panel/api.py +13 -3
  6. hardpy/hardpy_panel/frontend/dist/assets/{allPaths-Cg7WZDXy.js → allPaths-CV5wjLMB.js} +1 -1
  7. hardpy/hardpy_panel/frontend/dist/assets/{allPathsLoader-C79wUwqR.js → allPathsLoader-JIzW_pSb.js} +2 -2
  8. hardpy/hardpy_panel/frontend/dist/assets/browser-ponyfill-CccdstaD.js +2 -0
  9. hardpy/hardpy_panel/frontend/dist/assets/index-6RIgWzcZ.js +790 -0
  10. hardpy/hardpy_panel/frontend/dist/assets/{splitPathsBySizeLoader-hWuLTMwD.js → splitPathsBySizeLoader-DkZadBcn.js} +1 -1
  11. hardpy/hardpy_panel/frontend/dist/index.html +1 -1
  12. hardpy/hardpy_panel/frontend/dist/locales/de/translation.json +60 -0
  13. hardpy/hardpy_panel/frontend/dist/locales/en/translation.json +60 -0
  14. hardpy/hardpy_panel/frontend/dist/locales/es/translation.json +60 -0
  15. hardpy/hardpy_panel/frontend/dist/locales/fr/translation.json +60 -0
  16. hardpy/hardpy_panel/frontend/dist/locales/ja/translation.json +60 -0
  17. hardpy/hardpy_panel/frontend/dist/locales/ru/translation.json +60 -0
  18. hardpy/hardpy_panel/frontend/dist/locales/zh/translation.json +60 -0
  19. hardpy/pytest_hardpy/db/base_store.py +23 -0
  20. hardpy/pytest_hardpy/db/const.py +40 -19
  21. hardpy/pytest_hardpy/db/schema/v1.py +140 -326
  22. hardpy/pytest_hardpy/plugin.py +32 -1
  23. hardpy/pytest_hardpy/pytest_call.py +331 -22
  24. hardpy/pytest_hardpy/pytest_wrapper.py +25 -34
  25. hardpy/pytest_hardpy/reporter/hook_reporter.py +53 -2
  26. hardpy/pytest_hardpy/result/report_loader/stand_cloud_loader.py +8 -2
  27. hardpy/pytest_hardpy/result/report_reader/couchdb_reader.py +1 -5
  28. hardpy/pytest_hardpy/utils/__init__.py +25 -11
  29. hardpy/pytest_hardpy/utils/const.py +72 -0
  30. hardpy/pytest_hardpy/utils/exception.py +7 -32
  31. hardpy/pytest_hardpy/utils/node_info.py +55 -1
  32. hardpy/pytest_hardpy/utils/stand_type.py +198 -0
  33. {hardpy-0.13.0.dist-info → hardpy-0.15.0.dist-info}/METADATA +2 -1
  34. {hardpy-0.13.0.dist-info → hardpy-0.15.0.dist-info}/RECORD +37 -28
  35. hardpy/hardpy_panel/frontend/dist/assets/index-De5CJ3kt.js +0 -790
  36. {hardpy-0.13.0.dist-info → hardpy-0.15.0.dist-info}/WHEEL +0 -0
  37. {hardpy-0.13.0.dist-info → hardpy-0.15.0.dist-info}/entry_points.txt +0 -0
  38. {hardpy-0.13.0.dist-info → hardpy-0.15.0.dist-info}/licenses/LICENSE +0 -0
@@ -2,7 +2,13 @@
2
2
  # GNU General Public License v3.0 (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
3
3
 
4
4
  from hardpy.pytest_hardpy.utils.connection_data import ConnectionData
5
- from hardpy.pytest_hardpy.utils.const import TestStatus
5
+ from hardpy.pytest_hardpy.utils.const import (
6
+ ChartType,
7
+ ComparisonOperation,
8
+ Group,
9
+ MeasurementType,
10
+ TestStatus,
11
+ )
6
12
  from hardpy.pytest_hardpy.utils.dialog_box import (
7
13
  BaseWidget,
8
14
  CheckboxWidget,
@@ -16,11 +22,7 @@ from hardpy.pytest_hardpy.utils.dialog_box import (
16
22
  TextInputWidget,
17
23
  )
18
24
  from hardpy.pytest_hardpy.utils.exception import (
19
- DuplicatePartNumberError,
20
- DuplicateSerialNumberError,
21
- DuplicateTestStandLocationError,
22
- DuplicateTestStandNameError,
23
- DuplicateTestStandNumberError,
25
+ DuplicateParameterError,
24
26
  ImageError,
25
27
  TestStandNumberError,
26
28
  WidgetInfoError,
@@ -29,27 +31,39 @@ from hardpy.pytest_hardpy.utils.machineid import machine_id
29
31
  from hardpy.pytest_hardpy.utils.node_info import NodeInfo
30
32
  from hardpy.pytest_hardpy.utils.progress_calculator import ProgressCalculator
31
33
  from hardpy.pytest_hardpy.utils.singleton import SingletonMeta
34
+ from hardpy.pytest_hardpy.utils.stand_type import (
35
+ Chart,
36
+ Instrument,
37
+ NumericMeasurement,
38
+ StringMeasurement,
39
+ SubUnit,
40
+ )
32
41
 
33
42
  __all__ = [
34
43
  "BaseWidget",
44
+ "Chart",
45
+ "ChartType",
35
46
  "CheckboxWidget",
47
+ "ComparisonOperation",
36
48
  "ConnectionData",
37
49
  "DialogBox",
38
- "DuplicatePartNumberError",
39
- "DuplicateSerialNumberError",
40
- "DuplicateTestStandLocationError",
41
- "DuplicateTestStandNameError",
42
- "DuplicateTestStandNumberError",
50
+ "DuplicateParameterError",
51
+ "Group",
43
52
  "HTMLComponent",
44
53
  "ImageComponent",
45
54
  "ImageError",
55
+ "Instrument",
56
+ "MeasurementType",
46
57
  "MultistepWidget",
47
58
  "NodeInfo",
48
59
  "NumericInputWidget",
60
+ "NumericMeasurement",
49
61
  "ProgressCalculator",
50
62
  "RadiobuttonWidget",
51
63
  "SingletonMeta",
52
64
  "StepWidget",
65
+ "StringMeasurement",
66
+ "SubUnit",
53
67
  "TestStandNumberError",
54
68
  "TestStatus",
55
69
  "TextInputWidget",
@@ -17,3 +17,75 @@ class TestStatus(str, Enum):
17
17
  RUN = "run"
18
18
  READY = "ready"
19
19
  STOPPED = "stopped"
20
+
21
+
22
+ class Group(str, Enum):
23
+ """Test group."""
24
+
25
+ SETUP = "setup"
26
+ MAIN = "main"
27
+ TEARDOWN = "teardown"
28
+
29
+
30
+ class MeasurementType(str, Enum):
31
+ """Measurement type."""
32
+
33
+ NUMERIC = "numeric"
34
+ """Numeric measurement"""
35
+
36
+ STRING = "string"
37
+ """String measurement"""
38
+
39
+
40
+ class ComparisonOperation(str, Enum):
41
+ """Comparison operator."""
42
+
43
+ EQ = "eq"
44
+ """Equal"""
45
+
46
+ NE = "ne"
47
+ """Not equal"""
48
+
49
+ GT = "gt"
50
+ """Greater than"""
51
+
52
+ GE = "ge"
53
+ """Greater or equal"""
54
+
55
+ LT = "lt"
56
+ """Less than"""
57
+
58
+ LE = "le"
59
+ """Less or equal"""
60
+
61
+ GTLT = "gtlt"
62
+ """Greater than lower limit, less than upper limit"""
63
+
64
+ GELE = "gele"
65
+ """Greater or equal than lower limit, less or equal than upper limit"""
66
+
67
+ GELT = "gelt"
68
+ """Greater or equal than lower limit, less than upper limit"""
69
+
70
+ GTLE = "gtle"
71
+ """Greater than lower limit, less or equal than upper limit"""
72
+
73
+ LTGT = "ltgt"
74
+ """Less than lower limit or greater than upper limit"""
75
+
76
+ LEGE = "lege"
77
+ """Less or equal than lower limit or greater or equal than upper limit"""
78
+
79
+ LEGT = "legt"
80
+ """Less or equal than lower limit or greater than upper limit"""
81
+
82
+ LTGE = "ltge"
83
+ """Less than lower limit or greater or equal than upper limit"""
84
+
85
+ class ChartType(str, Enum):
86
+ """Chart type."""
87
+
88
+ LINE = "line"
89
+ LINE_LOG_X = "line_log_x"
90
+ LINE_LOG_Y = "line_log_y"
91
+ LOG_X_Y = "log_x_y"
@@ -2,6 +2,9 @@
2
2
  # GNU General Public License v3.0 (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
3
3
 
4
4
 
5
+ from typing import Any
6
+
7
+
5
8
  class HardpyError(Exception):
6
9
  """Base HardPy exception."""
7
10
 
@@ -9,39 +12,11 @@ class HardpyError(Exception):
9
12
  super().__init__(f"HardPy error: {msg}")
10
13
 
11
14
 
12
- class DuplicateSerialNumberError(HardpyError):
13
- """The serial number has already been determined."""
14
-
15
- def __init__(self) -> None:
16
- super().__init__(self.__doc__) # type: ignore
17
-
18
-
19
- class DuplicatePartNumberError(HardpyError):
20
- """The part number has already been determined."""
21
-
22
- def __init__(self) -> None:
23
- super().__init__(self.__doc__) # type: ignore
24
-
25
-
26
- class DuplicateTestStandNameError(HardpyError):
27
- """The test stand name has already been determined."""
15
+ class DuplicateParameterError(HardpyError):
16
+ """A parameter has already been defined."""
28
17
 
29
- def __init__(self) -> None:
30
- super().__init__(self.__doc__) # type: ignore
31
-
32
-
33
- class DuplicateTestStandLocationError(HardpyError):
34
- """The test stand location has already been determined."""
35
-
36
- def __init__(self) -> None:
37
- super().__init__(self.__doc__) # type: ignore
38
-
39
-
40
- class DuplicateTestStandNumberError(HardpyError):
41
- """The test stand number has already been determined."""
42
-
43
- def __init__(self) -> None:
44
- super().__init__(self.__doc__) # type: ignore
18
+ def __init__(self, param_name: Any) -> None: # noqa: ANN401
19
+ super().__init__(f"Parameter {param_name} is already defined")
45
20
 
46
21
 
47
22
  class TestStandNumberError(HardpyError):
@@ -7,6 +7,8 @@ from logging import getLogger
7
7
  from pathlib import Path
8
8
  from typing import TYPE_CHECKING, NamedTuple
9
9
 
10
+ from hardpy.pytest_hardpy.utils.const import Group
11
+
10
12
  if TYPE_CHECKING:
11
13
  from pytest import Item, Mark
12
14
 
@@ -45,6 +47,9 @@ class NodeInfo:
45
47
 
46
48
  self._critical = self._get_critical(item.own_markers + item.parent.own_markers)
47
49
 
50
+ self._module_group = self._get_group(item.parent.own_markers, "module_group")
51
+ self._case_group = self._get_group(item.own_markers, "case_group")
52
+
48
53
  self._module_id = Path(item.parent.nodeid).stem # type: ignore
49
54
  self._case_id = item.name
50
55
 
@@ -111,6 +116,24 @@ class NodeInfo:
111
116
  """
112
117
  return self._critical
113
118
 
119
+ @property
120
+ def module_group(self) -> Group:
121
+ """Get module group.
122
+
123
+ Returns:
124
+ Group: module group
125
+ """
126
+ return self._module_group
127
+
128
+ @property
129
+ def case_group(self) -> Group:
130
+ """Get case group.
131
+
132
+ Returns:
133
+ Group: case group
134
+ """
135
+ return self._case_group
136
+
114
137
  def _get_human_name(self, markers: list[Mark], marker_name: str) -> str:
115
138
  """Get human name from markers.
116
139
 
@@ -143,7 +166,8 @@ class NodeInfo:
143
166
  return names
144
167
 
145
168
  def _get_dependency_info(
146
- self, markers: list[Mark],
169
+ self,
170
+ markers: list[Mark],
147
171
  ) -> list[TestDependencyInfo] | None:
148
172
  """Extract and parse dependency information.
149
173
 
@@ -197,3 +221,33 @@ class NodeInfo:
197
221
  bool: True if test or module is critical, False otherwise
198
222
  """
199
223
  return any(marker.name == "critical" for marker in markers)
224
+
225
+ def _get_group(
226
+ self,
227
+ markers: list[Mark],
228
+ marker_name: str,
229
+ ) -> Group:
230
+ """Get group from markers or use default.
231
+
232
+ Args:
233
+ markers (list[Mark]): item markers list
234
+ marker_name (str): marker name
235
+ Returns:
236
+ Group: group from marker or default (Group.MAIN)
237
+ """
238
+ for marker in markers:
239
+ if marker.name == marker_name and marker.args:
240
+ arg = marker.args[0]
241
+
242
+ if isinstance(arg, Group):
243
+ return arg
244
+ if isinstance(arg, str):
245
+ valid_groups = {group.value for group in Group}
246
+ if arg not in valid_groups:
247
+ msg = f"Invalid group '{arg}'. Valid groups are: {', '.join(valid_groups)}" # noqa: E501
248
+ raise ValueError(msg)
249
+ return Group(arg)
250
+ msg = f"Group marker argument must be either string or Group enum, got {type(arg)}" # noqa: E501
251
+ raise ValueError(msg)
252
+
253
+ return Group.MAIN
@@ -0,0 +1,198 @@
1
+ # Copyright (c) 2025 Everypin
2
+ # GNU General Public License v3.0 (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt)
3
+
4
+ from __future__ import annotations
5
+
6
+ from pydantic import model_validator
7
+
8
+ from hardpy.pytest_hardpy.db.schema.v1 import (
9
+ Chart as ChartModel,
10
+ Instrument as InstrumentModel,
11
+ NumericMeasurement as NumericMeasurementModel,
12
+ StringMeasurement as StringMeasurementModel,
13
+ SubUnit as SubUnitModel,
14
+ )
15
+ from hardpy.pytest_hardpy.utils.const import ComparisonOperation as CompOp
16
+
17
+
18
+ class Instrument(InstrumentModel):
19
+ """Test stand instrument (equipment)."""
20
+
21
+
22
+ class SubUnit(SubUnitModel):
23
+ """Sub unit of DUT."""
24
+
25
+
26
+ class NumericMeasurement(NumericMeasurementModel):
27
+ """Represents a numeric measurement with value and comparison operation.
28
+
29
+ Args:
30
+ value (int | float): The value of the measurement.
31
+ name (str | None): The name of the measurement.
32
+ unit (str | None): The unit of the measurement.
33
+ operation (CompOp | None): The comparison operation to apply.
34
+ comparison_value (int | float | None): The value to compare against.
35
+ lower_limit (int | float | None): The lower limit for range operations.
36
+ upper_limit (int | float | None): The upper limit for range operations.
37
+ """
38
+
39
+ @model_validator(mode="after")
40
+ def validate_operation_requirements(self) -> NumericMeasurement:
41
+ """Validate field requirements based on selected operation."""
42
+ if (
43
+ self.operation
44
+ in (CompOp.EQ, CompOp.NE, CompOp.GT, CompOp.LT, CompOp.GE, CompOp.LE)
45
+ and self.comparison_value is None
46
+ ):
47
+ msg = f"Comparison_value required for {self.operation} operation"
48
+ raise ValueError(msg)
49
+
50
+ if self.operation in (
51
+ CompOp.GTLT,
52
+ CompOp.GELE,
53
+ CompOp.GELT,
54
+ CompOp.GTLE,
55
+ CompOp.LTGT,
56
+ CompOp.LEGE,
57
+ CompOp.LEGT,
58
+ CompOp.LTGE,
59
+ ) and (self.lower_limit is None or self.upper_limit is None):
60
+ msg = "lower_limit and upper_limit required for range operations"
61
+ raise ValueError(msg)
62
+
63
+ if self.operation:
64
+ self.result = self._check_condition()
65
+
66
+ return self
67
+
68
+ def _check_condition(self) -> bool: # noqa: C901,PLR0912
69
+ """Evaluate the measurement based on the selected operation."""
70
+ res = False
71
+ match self.operation:
72
+ case CompOp.EQ:
73
+ res = self.value == self.comparison_value
74
+ case CompOp.NE:
75
+ res = self.value != self.comparison_value
76
+ case CompOp.GT:
77
+ res = self.value > self.comparison_value
78
+ case CompOp.LT:
79
+ res = self.value < self.comparison_value
80
+ case CompOp.GE:
81
+ res = self.value >= self.comparison_value
82
+ case CompOp.LE:
83
+ res = self.value <= self.comparison_value
84
+ case CompOp.GTLT:
85
+ res = self.value > self.lower_limit and self.value < self.upper_limit
86
+ case CompOp.GELE:
87
+ res = self.value >= self.lower_limit and self.value <= self.upper_limit
88
+ case CompOp.GELT:
89
+ res = self.value >= self.lower_limit and self.value < self.upper_limit
90
+ case CompOp.GTLE:
91
+ res = self.value > self.lower_limit and self.value <= self.upper_limit
92
+ case CompOp.LTGT:
93
+ res = self.value < self.lower_limit or self.value > self.upper_limit
94
+ case CompOp.LEGE:
95
+ res = self.value <= self.lower_limit or self.value >= self.upper_limit
96
+ case CompOp.LEGT:
97
+ res = self.value <= self.lower_limit or self.value > self.upper_limit
98
+ case CompOp.LTGE:
99
+ res = self.value < self.lower_limit or self.value >= self.upper_limit
100
+ return res
101
+
102
+
103
+ class StringMeasurement(StringMeasurementModel):
104
+ """Represents a string measurement with value and comparison operation.
105
+
106
+ Args:
107
+ value (str): The value of the measurement.
108
+ name (str | None): The name of the measurement.
109
+ operation (CompOp | None): The comparison operation to apply.
110
+ comparison_value (str | None): The value to compare against.
111
+ """
112
+
113
+ @model_validator(mode="after")
114
+ def validate_operation_requirements(self) -> StringMeasurement:
115
+ """Validate field requirements based on selected operation."""
116
+ string_operations = (CompOp.EQ, CompOp.NE)
117
+ if self.operation in string_operations and self.comparison_value is None:
118
+ msg = f"Comparison_value required for {self.operation} operation"
119
+ raise ValueError(msg)
120
+
121
+ if self.operation and self.operation not in string_operations:
122
+ msg = f"{self.operation} is not a valid string operation"
123
+ raise ValueError(msg)
124
+
125
+ if self.operation:
126
+ self.result = self._check_condition()
127
+
128
+ return self
129
+
130
+ def _check_condition(self) -> bool:
131
+ """Evaluate the measurement based on the selected operation."""
132
+ res = False
133
+ match self.operation:
134
+ case CompOp.EQ:
135
+ if self.casesensitive:
136
+ res = self.value == self.comparison_value
137
+ else:
138
+ res = self.value.lower() == self.comparison_value.lower()
139
+ case CompOp.NE:
140
+ if self.casesensitive:
141
+ res = self.value != self.comparison_value
142
+ else:
143
+ res = self.value.lower() != self.comparison_value.lower()
144
+ return res
145
+
146
+
147
+ class Chart(ChartModel):
148
+ """Represents a chart with data and labels.
149
+
150
+ Args:
151
+ type (ChartType | None): chart type.
152
+ title (str | None): chart title.
153
+ x_label (str | None): X label.
154
+ y_label (str | None): Y label.
155
+ """
156
+
157
+ @model_validator(mode="after")
158
+ def validate_lines(self) -> Chart:
159
+ """Validate field requirements based on selected operation."""
160
+ self._diff_list_len_validator(self.x_data, self.y_data)
161
+ self._diff_list_len_validator(self.x_data, self.marker_name)
162
+
163
+ if len(self.x_data):
164
+ for i in range(len(self.x_data)):
165
+ self._diff_list_len_validator(self.x_data[i], self.y_data[i])
166
+ self._empty_list_validator(self.x_data[0])
167
+ self._empty_list_validator(self.marker_name)
168
+
169
+ return self
170
+
171
+ def add_series(
172
+ self,
173
+ x_data: list[int | float],
174
+ y_data: list[int | float],
175
+ marker_name: str | None = None,
176
+ ) -> None:
177
+ """Add data series to chart.
178
+
179
+ Args:
180
+ x_data (list[int | float]): X data.
181
+ y_data (list[int | float]): Y data.
182
+ marker_name (str | None): series marker name.
183
+ """
184
+ self._diff_list_len_validator(x_data, y_data)
185
+ self._empty_list_validator(x_data)
186
+ self.x_data.append(x_data)
187
+ self.y_data.append(y_data)
188
+ self.marker_name.append(marker_name)
189
+
190
+ def _diff_list_len_validator(self, data1: list, data2: list) -> None:
191
+ if len(data1) != len(data2):
192
+ msg = "data in single series must have the same length"
193
+ raise ValueError(msg)
194
+
195
+ def _empty_list_validator(self, data: list) -> None:
196
+ if len(data) == 0:
197
+ msg = "data series cannot be empty"
198
+ raise ValueError(msg)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: hardpy
3
- Version: 0.13.0
3
+ Version: 0.15.0
4
4
  Summary: HardPy library for device testing
5
5
  Project-URL: Homepage, https://github.com/everypinio/hardpy/
6
6
  Project-URL: Documentation, https://everypinio.github.io/hardpy/
@@ -51,6 +51,7 @@ Requires-Dist: ruff==0.8.0; extra == 'dev'
51
51
  Requires-Dist: wemake-python-styleguide>=0.19.2; extra == 'dev'
52
52
  Provides-Extra: tests
53
53
  Requires-Dist: psutil~=7.0.0; extra == 'tests'
54
+ Requires-Dist: pytest-timeout==2.4.0; extra == 'tests'
54
55
  Description-Content-Type: text/markdown
55
56
 
56
57
  <h1 align="center">
@@ -1,25 +1,25 @@
1
- hardpy/__init__.py,sha256=49-EDyH1KzK7kmuU9zFHAe8bUPfuayzcUIk3ksXiL7s,2237
1
+ hardpy/__init__.py,sha256=wIDpTCST_Cod8rJ3k-ilLHGjhbF6pU3_TFZUtwcwQZM,2866
2
2
  hardpy/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
- hardpy/cli/cli.py,sha256=FPXCFTqnC5fST9g7EjRd4ODBkvBPZ-r0XglF_vMU3Go,9164
3
+ hardpy/cli/cli.py,sha256=-KS8qggaCGz0Hcdd4TLJPwKpVSDfubSp5t5cWuXoMUc,9434
4
4
  hardpy/cli/template.py,sha256=44phTqeKgFch5xdAJmDQ-za1mM1_z60izRVbmCQHU-8,6225
5
5
  hardpy/common/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
6
- hardpy/common/config.py,sha256=nA2r2FrdKl0e-OqVvoa-3KvQ26Af-b86j7RMhGsWCPE,4966
6
+ hardpy/common/config.py,sha256=ei-NhZ72qdkNM1HnjWu6vgEgB4lEzTbWokZRaL2GAug,4998
7
7
  hardpy/common/stand_cloud/__init__.py,sha256=fezdiYAehtT2H-GAef-xZU12CbmCRe64XHA9UB3kJDU,456
8
- hardpy/common/stand_cloud/connector.py,sha256=oAfyT4h5HPWT5JeWcUBFyymncPmGWMpNkpeefYf99xM,7318
8
+ hardpy/common/stand_cloud/connector.py,sha256=scmKT09duPqqbQtwMNPnl59si_sErwqAY2PeiTSCZvg,7389
9
9
  hardpy/common/stand_cloud/exception.py,sha256=eKkqu5ylDRIGN_yZhvz2xVGm49XmlZ8nryALgdRqpbY,287
10
10
  hardpy/common/stand_cloud/oauth2.py,sha256=SDqtIwcuMgqfBkEZyo3GXeVPnvRBOr6dzeXowx3ZkEw,2803
11
11
  hardpy/common/stand_cloud/registration.py,sha256=UW-JGcvON5CMQQ-s2Mb4Ee3u_jmdQfSj3vPfZ_FuhHY,2370
12
12
  hardpy/common/stand_cloud/token_manager.py,sha256=8dX802F0CnOrOjOQInyYCrvuRdK0CeiCrTDITAbSLgQ,4055
13
13
  hardpy/common/stand_cloud/utils.py,sha256=GN3wzbrmF-Xe5iUXf_HurGO-YKltqd3Gc_7vG2eEL7c,692
14
14
  hardpy/hardpy_panel/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
15
- hardpy/hardpy_panel/api.py,sha256=BRY_RuYKPo0e1WdVCPS7iA46GzLIc5A4hLPvtagKqRc,3533
15
+ hardpy/hardpy_panel/api.py,sha256=xQZBv9zJ3uIVvMO_pb-zyty6vrOkFGHZCZpdvg_clVI,3865
16
16
  hardpy/hardpy_panel/frontend/dist/favicon.ico,sha256=sgIk5PKUKEKBDpkSrc8dJgjpObp0iF82Mec0GpfKId4,15406
17
- hardpy/hardpy_panel/frontend/dist/index.html,sha256=rDoetZX8aPQ5CD7Whs3GIIDF1NI9EwiAuTKJ_JM-sBI,1851
17
+ hardpy/hardpy_panel/frontend/dist/index.html,sha256=HgsuTaNZg-rq6m18f8RRijfxcEPwQNDzb9Dxc1rkaCY,1851
18
18
  hardpy/hardpy_panel/frontend/dist/logo192.png,sha256=E4K7drvhJCg9HcTpRihOXZhVJVBZ7-W97Se-3tDb46o,14485
19
19
  hardpy/hardpy_panel/frontend/dist/logo512.png,sha256=-fIMbqX7PYUpheK4kX1C1erRTe_hHZwFQYDLrAbhFRU,34188
20
20
  hardpy/hardpy_panel/frontend/dist/manifest.json,sha256=PfmJlN2JMJtHS6OnhU4b4X5wPQC_yRBdjesjoirObSA,502
21
- hardpy/hardpy_panel/frontend/dist/assets/allPaths-Cg7WZDXy.js,sha256=lyJFFIHSfH_cGbFXTxhXInVWAow03ydaTINjv_b9kJE,309
22
- hardpy/hardpy_panel/frontend/dist/assets/allPathsLoader-C79wUwqR.js,sha256=35KNR-uC0fCNycxT538NL9QRmxUXWEoeZKAxS9h3pC4,550
21
+ hardpy/hardpy_panel/frontend/dist/assets/allPaths-CV5wjLMB.js,sha256=N09wgcmig_DLDNU2XRGxwya65nrEHLFToqToqntmuc4,309
22
+ hardpy/hardpy_panel/frontend/dist/assets/allPathsLoader-JIzW_pSb.js,sha256=3C1eVG4e3OQX2dS_XwvpLkOkJQrh9OX3wWwLUzHXAiM,550
23
23
  hardpy/hardpy_panel/frontend/dist/assets/blueprint-icons-16-Bfs1BwbR.ttf,sha256=wA1ItrnCJli8ESQ1KwLR3egJZG55dKBbLPonqFIa0K0,117420
24
24
  hardpy/hardpy_panel/frontend/dist/assets/blueprint-icons-16-Btb8d-Hu.woff,sha256=edyqQN0nw4dNBs1pgr7pQB7nJhhR6T_YfklFcG_fHj0,53344
25
25
  hardpy/hardpy_panel/frontend/dist/assets/blueprint-icons-16-CzsyEoPG.svg,sha256=lDCQy06aS-9bmhwuFOUs-EdcR8MP2wqwAwky5oamtkQ,509417
@@ -30,48 +30,57 @@ hardpy/hardpy_panel/frontend/dist/assets/blueprint-icons-20-D9WO2FSG.woff2,sha25
30
30
  hardpy/hardpy_panel/frontend/dist/assets/blueprint-icons-20-Doom1bSH.eot,sha256=RPan5eGrt9_bHe9FXYXVYsbOA4J-BgNweKZJNaVXf2I,120680
31
31
  hardpy/hardpy_panel/frontend/dist/assets/blueprint-icons-20-DyVnGNfQ.svg,sha256=BsTLtmUaqeiMSZwv2ysmTV4qWVv-qYbwsE0_sVUjJk0,546938
32
32
  hardpy/hardpy_panel/frontend/dist/assets/blueprint-icons-20-ZW-9JnPf.woff,sha256=mQZTxE1PyyAL16VWuASOvXlZFwuI4aCPvbrhfgpdIdU,55356
33
+ hardpy/hardpy_panel/frontend/dist/assets/browser-ponyfill-CccdstaD.js,sha256=FLNVAidyg0bcRT15SkYoVOsL_YEEyjyZBQuRW6CviAs,10288
34
+ hardpy/hardpy_panel/frontend/dist/assets/index-6RIgWzcZ.js,sha256=8oKEqyS6CGqdCQPo5QZ8yrvDWk8tfn6jnCxgpfadFDs,1046765
33
35
  hardpy/hardpy_panel/frontend/dist/assets/index-BMEat_ws.js,sha256=ZiKN4IGxolgim42tqk68UOPUA0g8ABojet1dj4Wru1s,254121
34
36
  hardpy/hardpy_panel/frontend/dist/assets/index-BwCQzehg.css,sha256=uvaqKowYoduAxTwlw3ojcSjKqrMtu5XErb_T668JGdU,299275
35
- hardpy/hardpy_panel/frontend/dist/assets/index-De5CJ3kt.js,sha256=qi_vrV2HLYPUQyZKguRgI8U9Q2Ujp0CqyG6GVWDsE3M,984451
36
37
  hardpy/hardpy_panel/frontend/dist/assets/index-xb4M2ucX.js,sha256=eeaZrH0pRpkWViEVZ2Mt6f7VgpOxluRB7S8SovkFeTE,245762
37
38
  hardpy/hardpy_panel/frontend/dist/assets/logo_smol-CK3jE85c.png,sha256=E4K7drvhJCg9HcTpRihOXZhVJVBZ7-W97Se-3tDb46o,14485
38
- hardpy/hardpy_panel/frontend/dist/assets/splitPathsBySizeLoader-hWuLTMwD.js,sha256=ocYr1jFgVEcJXCdClz5Is83Cd0nZo-j-0p5I8scwjBU,472
39
+ hardpy/hardpy_panel/frontend/dist/assets/splitPathsBySizeLoader-DkZadBcn.js,sha256=pLRjEega0VLCJFhH8dCAPzjkLe_zIU92Hlkn_1O4EMQ,472
40
+ hardpy/hardpy_panel/frontend/dist/locales/de/translation.json,sha256=CyQ16ylGIPs-VSccDU35siMvrFjPpFoOk3NTncyhnOA,1954
41
+ hardpy/hardpy_panel/frontend/dist/locales/en/translation.json,sha256=RuITbwa-aaUIET6CPAUppaMcLeuxsB6ijq4ep2LnVZw,1803
42
+ hardpy/hardpy_panel/frontend/dist/locales/es/translation.json,sha256=UVENIDh-mBphPVIOLPK17VObTmlsCmJ_wkI9hc_uZSE,2019
43
+ hardpy/hardpy_panel/frontend/dist/locales/fr/translation.json,sha256=zjXb_cGXE55sTnOMe5fMtK0FDiOa9IVp55RRXanVHgw,2012
44
+ hardpy/hardpy_panel/frontend/dist/locales/ja/translation.json,sha256=xSDe9TN1f3gywlGFbD0O9jS1J7ikrv9QWxStPfT_ssc,2199
45
+ hardpy/hardpy_panel/frontend/dist/locales/ru/translation.json,sha256=Zo_5GhOFIwOnpQITD5x2Q7CYTI9Pdpvv844_ieW56jY,2609
46
+ hardpy/hardpy_panel/frontend/dist/locales/zh/translation.json,sha256=uxYSv8eXTMDewPvbFZSh21ZP0Wy4mx32XbbVkzXzlls,1790
39
47
  hardpy/pytest_hardpy/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
40
- hardpy/pytest_hardpy/plugin.py,sha256=vyG2LvZj5NC_M2iXmVNlGZJJFOpGwtviGbhMCHtyQqE,20017
41
- hardpy/pytest_hardpy/pytest_call.py,sha256=TNDcbH0uuquqpNVjT_MGXZ8ukpze3ceWA5M4DUuKuEM,13279
42
- hardpy/pytest_hardpy/pytest_wrapper.py,sha256=_eULTqbJhFj0uu3XPplS4WSrI_LJC_ZX2kA5t5YJ49U,5162
48
+ hardpy/pytest_hardpy/plugin.py,sha256=2B-jNRfuY30m6i0TPjeVetR9_oGs15bnYXd_gQ2hSDI,21102
49
+ hardpy/pytest_hardpy/pytest_call.py,sha256=QDpzQ2AxeSM9Qaz3TN6n0Tydr0zzOU6osIAr4-0F9ZU,21606
50
+ hardpy/pytest_hardpy/pytest_wrapper.py,sha256=0tG725R3qhLI6t6zi0-OL17FCwt3YI-mwrBjWe4U9A4,4694
43
51
  hardpy/pytest_hardpy/db/__init__.py,sha256=G6y13JPh8HaH2O9E3_LTH_bTUVSgiezQFjDGaNIljec,557
44
52
  hardpy/pytest_hardpy/db/base_connector.py,sha256=5a476F5LwvFUfQ4Yc0Q6biacULDrCk8UHPlpc6n0NRQ,1111
45
53
  hardpy/pytest_hardpy/db/base_server.py,sha256=XqTff225iIymPYUGGEja9r9WOilVw7ljcAVp1M8VuAI,404
46
- hardpy/pytest_hardpy/db/base_store.py,sha256=m-glO0EsHu0NYArVaKRXUIOE-wVwvenbFNACznYo1Tg,3806
47
- hardpy/pytest_hardpy/db/const.py,sha256=AltZXf-h88sV29v4vYLuWk5ax-Tuv_rC7CeBxN0AMtA,992
54
+ hardpy/pytest_hardpy/db/base_store.py,sha256=hj2ACXIbVzYD28VL49ZjSo-uDmFLaVsBTBgCCwhqb4s,4484
55
+ hardpy/pytest_hardpy/db/const.py,sha256=E_A0IKGeS3qyPX4fTfUE5ksARsrTKSVWqUkdmh8S_fo,1414
48
56
  hardpy/pytest_hardpy/db/runstore.py,sha256=tCXWo2AW0er3lbDcCqYbYxOBbINMZNtfnnjlIJpXmIA,949
49
57
  hardpy/pytest_hardpy/db/statestore.py,sha256=0sv4AqzwW_J34O-cb7aN3zmgULIVtZRi_qg4XvC2_L0,586
50
58
  hardpy/pytest_hardpy/db/schema/__init__.py,sha256=1S73W3PLQt8gX5Y33nbX1JdwLvnrtlKH4cElID3pwuc,263
51
- hardpy/pytest_hardpy/db/schema/v1.py,sha256=lWE5jWh5ek43-i4aKO51lflNPoyyzaveV06PP5nKQ3Y,9897
59
+ hardpy/pytest_hardpy/db/schema/v1.py,sha256=9_Kv5N-kFKNntNdy5POcPr6_hj1pVGM4vPqGcV-g7Xg,6338
52
60
  hardpy/pytest_hardpy/reporter/__init__.py,sha256=rztpM2HlLUpMOvad0JHbZU4Mk8PDDQyCFXLhpLktGQI,322
53
61
  hardpy/pytest_hardpy/reporter/base.py,sha256=KRkc5a7yk9ZsQ92gnBdHhJEXSSQiTWbEMSMzRMpJDFY,2915
54
- hardpy/pytest_hardpy/reporter/hook_reporter.py,sha256=0xdga2rqwxUJKpkX6t7XaY9hPdhoKmisIDoZ6IJVXXQ,13027
62
+ hardpy/pytest_hardpy/reporter/hook_reporter.py,sha256=vkN78UtXs5M-rmpDdxjFEwrAPOFIpSEU8TRZUdnuWJY,14619
55
63
  hardpy/pytest_hardpy/reporter/runner_reporter.py,sha256=YsK8wrLIulsixePG6WNfC4MagpKfhP5j0CUaXkcfeL0,790
56
64
  hardpy/pytest_hardpy/result/__init__.py,sha256=2afpuEuOcxYfIEOwWzsGZe960iQaPVCmsbYujijQg1s,592
57
65
  hardpy/pytest_hardpy/result/couchdb_config.py,sha256=ujxyJYM2pdZzi3GZ2Zysbz2_ZeTRN5sQc8AGuzRJm_0,3243
58
66
  hardpy/pytest_hardpy/result/report_loader/__init__.py,sha256=wq5Y-_JW2ExCRnQ9VVesKmTToEQrcTY5RxNJIWaT9ag,374
59
67
  hardpy/pytest_hardpy/result/report_loader/couchdb_loader.py,sha256=KcZ0JkCgWhrj2J9M04JBDy0fpqtpVEYtu9GCLDG27pU,2255
60
- hardpy/pytest_hardpy/result/report_loader/stand_cloud_loader.py,sha256=lRPDGIOFquo-KcCYxR6C4vnfe1m_dBWENFN8IkNZDPc,2217
68
+ hardpy/pytest_hardpy/result/report_loader/stand_cloud_loader.py,sha256=daS4cM3egwj8ej6yjLAMlM5zBIOwbWBBroF47nukQ5s,2478
61
69
  hardpy/pytest_hardpy/result/report_reader/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
62
- hardpy/pytest_hardpy/result/report_reader/couchdb_reader.py,sha256=GrROwfTVyJaVLPBxkvOM35HCksFEnWm0aVI8FibPikg,5911
70
+ hardpy/pytest_hardpy/result/report_reader/couchdb_reader.py,sha256=lnWSX-0QKbdMwtqfCtW0tiH9W_ZEPqQ3rb7Lc8gES7E,5726
63
71
  hardpy/pytest_hardpy/result/report_reader/stand_cloud_reader.py,sha256=uT7YSBu1QyURH9IkgRCdpbinn8LKXUhgVEhwPmGZV7I,3636
64
- hardpy/pytest_hardpy/utils/__init__.py,sha256=nvcT-9RRsRTxk1tP9qIua8rm_SskuuUfNGEkROtIn90,1637
72
+ hardpy/pytest_hardpy/utils/__init__.py,sha256=fXIPMCP6QTIQAR18RnPTxBYo-fQibN3ceaBgONdRJVc,1752
65
73
  hardpy/pytest_hardpy/utils/connection_data.py,sha256=Oq1LdIpmYkwakNCNwAPD-FTH4W7lj_v8vYkQCqJTof8,449
66
- hardpy/pytest_hardpy/utils/const.py,sha256=RuzRmnpvmUylRbj8CxtaVbo7J9kp6rELvjPdfUzMQLU,407
74
+ hardpy/pytest_hardpy/utils/const.py,sha256=xS3jBrW_D6IUTlAjSnLiHvSthieRHCj3uN_6fFAXS0w,1832
67
75
  hardpy/pytest_hardpy/utils/dialog_box.py,sha256=LNukQ7ukUzLUFmwwH6L6M8wWmF-Mo4HF-UpVkyf8nY8,11224
68
- hardpy/pytest_hardpy/utils/exception.py,sha256=N5g4tIorQaT0I5mFqqj9qoigf4YUwy7Jvy58VHL6IxE,1773
76
+ hardpy/pytest_hardpy/utils/exception.py,sha256=1l2VBZLUnjPDoOs744MtaP7Y9FuXUq7koSdH2Eo31nk,1042
69
77
  hardpy/pytest_hardpy/utils/machineid.py,sha256=6JAzUt7KtjTYn8kL9hSMaCQ20U8liH-zDT9v-5Ch7Q8,296
70
- hardpy/pytest_hardpy/utils/node_info.py,sha256=BibPo2ltxy-hIUQbaYA2om7x1LNK1JvQtHNC0EKl_9k,5474
78
+ hardpy/pytest_hardpy/utils/node_info.py,sha256=DaW566WvsyWR66CThuZ38UoHwQa-pu-4WRLg61OXDnE,7134
71
79
  hardpy/pytest_hardpy/utils/progress_calculator.py,sha256=TPl2gG0ZSvMe8otPythhF9hkD6fa6-mJAhy9yI83-yE,1071
72
80
  hardpy/pytest_hardpy/utils/singleton.py,sha256=tjUGs48o_vBeVpRsEBZEOTCoCUikpIFmQ1c3rsfymso,948
73
- hardpy-0.13.0.dist-info/METADATA,sha256=jAfzeUUp40Scg2F9tGrVGrdEqi1Y7wBGPAwgXWyiiRc,4003
74
- hardpy-0.13.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
75
- hardpy-0.13.0.dist-info/entry_points.txt,sha256=nL2sMkKMScNaOE0IPkYnu9Yr-BUswZvGSrwY-SxHY3E,102
76
- hardpy-0.13.0.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
77
- hardpy-0.13.0.dist-info/RECORD,,
81
+ hardpy/pytest_hardpy/utils/stand_type.py,sha256=p3AFtgMt-sn8QXRp60YM-xo2mEjZHUhYr_Mxhz1WyP0,7438
82
+ hardpy-0.15.0.dist-info/METADATA,sha256=_aaXwF48EZNFd0AqlYaTln3de2T5wRtCA6ukWtaUYOY,4058
83
+ hardpy-0.15.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
84
+ hardpy-0.15.0.dist-info/entry_points.txt,sha256=nL2sMkKMScNaOE0IPkYnu9Yr-BUswZvGSrwY-SxHY3E,102
85
+ hardpy-0.15.0.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
86
+ hardpy-0.15.0.dist-info/RECORD,,