hardpy 0.5.1__py3-none-any.whl → 0.6.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.
Files changed (42) hide show
  1. hardpy/__init__.py +10 -0
  2. hardpy/cli/__init__.py +0 -0
  3. hardpy/cli/cli.py +145 -0
  4. hardpy/cli/template.py +220 -0
  5. hardpy/common/__init__.py +0 -0
  6. hardpy/common/config.py +159 -0
  7. hardpy/hardpy_panel/api.py +49 -6
  8. hardpy/hardpy_panel/frontend/dist/asset-manifest.json +3 -3
  9. hardpy/hardpy_panel/frontend/dist/index.html +1 -1
  10. hardpy/hardpy_panel/frontend/dist/static/js/main.7c954faf.js +3 -0
  11. hardpy/hardpy_panel/frontend/dist/static/js/main.7c954faf.js.map +1 -0
  12. hardpy/pytest_hardpy/db/base_connector.py +7 -1
  13. hardpy/pytest_hardpy/db/base_server.py +4 -4
  14. hardpy/pytest_hardpy/db/base_store.py +13 -3
  15. hardpy/pytest_hardpy/db/const.py +3 -0
  16. hardpy/pytest_hardpy/db/schema.py +47 -11
  17. hardpy/pytest_hardpy/db/statestore.py +11 -0
  18. hardpy/pytest_hardpy/plugin.py +93 -33
  19. hardpy/pytest_hardpy/pytest_call.py +65 -5
  20. hardpy/pytest_hardpy/pytest_wrapper.py +62 -60
  21. hardpy/pytest_hardpy/reporter/base.py +1 -1
  22. hardpy/pytest_hardpy/reporter/hook_reporter.py +7 -3
  23. hardpy/pytest_hardpy/result/report_loader/couchdb_loader.py +3 -2
  24. hardpy/pytest_hardpy/result/report_reader/couchdb_reader.py +2 -2
  25. hardpy/pytest_hardpy/utils/__init__.py +7 -4
  26. hardpy/pytest_hardpy/utils/connection_data.py +17 -0
  27. hardpy/pytest_hardpy/utils/const.py +4 -14
  28. hardpy/pytest_hardpy/utils/dialog_box.py +1 -1
  29. hardpy/pytest_hardpy/utils/exception.py +14 -0
  30. hardpy/pytest_hardpy/utils/node_info.py +1 -1
  31. hardpy/pytest_hardpy/utils/progress_calculator.py +1 -1
  32. hardpy/pytest_hardpy/utils/singleton.py +1 -1
  33. {hardpy-0.5.1.dist-info → hardpy-0.6.1.dist-info}/METADATA +25 -57
  34. {hardpy-0.5.1.dist-info → hardpy-0.6.1.dist-info}/RECORD +38 -34
  35. {hardpy-0.5.1.dist-info → hardpy-0.6.1.dist-info}/entry_points.txt +1 -1
  36. hardpy/hardpy_panel/frontend/dist/static/js/main.da686f40.js +0 -3
  37. hardpy/hardpy_panel/frontend/dist/static/js/main.da686f40.js.map +0 -1
  38. hardpy/hardpy_panel/runner.py +0 -54
  39. hardpy/pytest_hardpy/utils/config_data.py +0 -35
  40. /hardpy/hardpy_panel/frontend/dist/static/js/{main.da686f40.js.LICENSE.txt → main.7c954faf.js.LICENSE.txt} +0 -0
  41. {hardpy-0.5.1.dist-info → hardpy-0.6.1.dist-info}/WHEEL +0 -0
  42. {hardpy-0.5.1.dist-info → hardpy-0.6.1.dist-info}/licenses/LICENSE +0 -0
@@ -1,16 +1,16 @@
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 sys
5
4
  import signal
6
- import subprocess
7
- from socket import socket
5
+ import subprocess # noqa: S404
6
+ import sys
8
7
  from platform import system
8
+ from socket import socket
9
9
 
10
- from hardpy.pytest_hardpy.utils.config_data import ConfigData
10
+ from hardpy.common.config import ConfigManager
11
11
 
12
12
 
13
- class PyTestWrapper(object):
13
+ class PyTestWrapper:
14
14
  """Wrapper for pytest subprocess."""
15
15
 
16
16
  def __init__(self):
@@ -19,13 +19,14 @@ class PyTestWrapper(object):
19
19
 
20
20
  # Make sure test structure is stored in DB
21
21
  # before clients come in
22
- self.config = ConfigData()
23
- self.collect()
22
+ self.config = ConfigManager().get_config()
23
+ self.collect(is_clear_database=True)
24
24
 
25
- def start(self):
25
+ def start(self) -> bool:
26
26
  """Start pytest subprocess.
27
27
 
28
- Returns True if pytest was started.
28
+ Returns:
29
+ bool: True if pytest was started
29
30
  """
30
31
  if self.python_executable is None:
31
32
  return False
@@ -39,21 +40,15 @@ class PyTestWrapper(object):
39
40
  self.python_executable,
40
41
  "-m",
41
42
  "pytest",
42
- "--hardpy-dbp",
43
- str(self.config.db_port),
44
- "--hardpy-dbh",
45
- self.config.db_host,
46
- "--hardpy-dbu",
47
- self.config.db_user,
48
- "--hardpy-dbpw",
49
- self.config.db_pswd,
43
+ "--hardpy-db-url",
44
+ self.config.database.connection_url(),
50
45
  "--hardpy-sp",
51
- str(self.config.socket_port),
52
- "--hardpy-sa",
53
- self.config.socket_addr,
46
+ str(self.config.socket.port),
47
+ "--hardpy-sh",
48
+ self.config.socket.host,
54
49
  "--hardpy-pt",
55
50
  ],
56
- cwd=self.config.tests_dir.absolute(),
51
+ cwd=ConfigManager().get_tests_path(),
57
52
  )
58
53
  elif system() == "Windows":
59
54
  self._proc = subprocess.Popen( # noqa: S603
@@ -61,21 +56,15 @@ class PyTestWrapper(object):
61
56
  self.python_executable,
62
57
  "-m",
63
58
  "pytest",
64
- "--hardpy-dbp",
65
- str(self.config.db_port),
66
- "--hardpy-dbh",
67
- self.config.db_host,
68
- "--hardpy-dbu",
69
- self.config.db_user,
70
- "--hardpy-dbpw",
71
- self.config.db_pswd,
59
+ "--hardpy-db-url",
60
+ self.config.database.connection_url(),
72
61
  "--hardpy-sp",
73
- str(self.config.socket_port),
74
- "--hardpy-sa",
75
- self.config.socket_addr,
62
+ str(self.config.socket.port),
63
+ "--hardpy-sh",
64
+ self.config.socket.host,
76
65
  "--hardpy-pt",
77
66
  ],
78
- cwd=self.config.tests_dir.absolute(),
67
+ cwd=ConfigManager().get_tests_path(),
79
68
  creationflags=subprocess.CREATE_NEW_PROCESS_GROUP,
80
69
  )
81
70
 
@@ -84,7 +73,8 @@ class PyTestWrapper(object):
84
73
  def stop(self) -> bool:
85
74
  """Stop pytest subprocess.
86
75
 
87
- Returns True if pytest was running and stopped.
76
+ Returns:
77
+ bool: True if pytest was running and stopped
88
78
  """
89
79
  if self.is_running() and self._proc:
90
80
  if system() == "Linux":
@@ -94,10 +84,15 @@ class PyTestWrapper(object):
94
84
  return True
95
85
  return False
96
86
 
97
- def collect(self) -> bool:
87
+ def collect(self, is_clear_database: bool = False) -> bool:
98
88
  """Perform pytest collection.
99
89
 
100
- Returns True if collection was started.
90
+ Args:
91
+ is_clear_database (bool): indicates whether database
92
+ should be cleared. Defaults to False.
93
+
94
+ Returns:
95
+ bool: True if collection was started
101
96
  """
102
97
  if self.python_executable is None:
103
98
  return False
@@ -105,45 +100,52 @@ class PyTestWrapper(object):
105
100
  if self.is_running():
106
101
  return False
107
102
 
103
+ args = [
104
+ "-m",
105
+ "pytest",
106
+ "--collect-only",
107
+ "--hardpy-db-url",
108
+ self.config.database.connection_url(),
109
+ "--hardpy-sp",
110
+ str(self.config.socket.port),
111
+ "--hardpy-sh",
112
+ self.config.socket.host,
113
+ "--hardpy-pt",
114
+ ]
115
+
116
+ if is_clear_database:
117
+ args.append("--hardpy-clear-database")
118
+ args.append(str(is_clear_database))
119
+
108
120
  subprocess.Popen( # noqa: S603
109
- [
110
- self.python_executable,
111
- "-m" "pytest",
112
- "--collect-only",
113
- "--hardpy-dbp",
114
- str(self.config.db_port),
115
- "--hardpy-dbh",
116
- self.config.db_host,
117
- "--hardpy-dbu",
118
- self.config.db_user,
119
- "--hardpy-dbpw",
120
- self.config.db_pswd,
121
- "--hardpy-pt",
122
- ],
123
- cwd=self.config.tests_dir.absolute(),
121
+ [self.python_executable, *args],
122
+ cwd=ConfigManager().get_tests_path(),
124
123
  )
125
124
  return True
126
125
 
127
- def confirm_dialog_box(self, dialog_box_output: str):
128
- """Set dialog box data to pytest subprocess.
126
+ def send_data(self, data: str):
127
+ """Send data to pytest subprocess.
129
128
 
130
129
  Args:
131
- dialog_box_output (str): dialog box output data
130
+ data (str): Data to be sent. Can be dialog
131
+ box output or operator message visibility.
132
132
 
133
133
  Returns:
134
- bool: True if dialog box was confirmed, else False
134
+ bool: True if dialog box was confirmed/closed, else False
135
135
  """
136
- config_data = ConfigData()
137
-
138
136
  try:
139
137
  client = socket()
140
- client.connect((config_data.socket_addr, config_data.socket_port))
141
- client.sendall(dialog_box_output.encode("utf-8"))
138
+ client.connect((self.config.socket.host, self.config.socket.port))
139
+ client.sendall(data.encode("utf-8"))
142
140
  client.close()
143
141
  except Exception:
144
142
  return False
145
143
  return True
146
144
 
147
145
  def is_running(self) -> bool | None:
148
- """Check if pytest is running."""
146
+ """Check if pytest is running.
147
+
148
+ Returns:
149
+ bool | None: True if self._proc is not None
150
+ """
149
151
  return self._proc and self._proc.poll() is None
@@ -6,7 +6,7 @@ from logging import getLogger
6
6
  from hardpy.pytest_hardpy.db import StateStore, RunStore
7
7
 
8
8
 
9
- class BaseReporter(object):
9
+ class BaseReporter:
10
10
  """Base class for test reporter."""
11
11
 
12
12
  def __init__(self):
@@ -9,14 +9,16 @@ from natsort import natsorted
9
9
 
10
10
  from hardpy.pytest_hardpy.db import DatabaseField as DF
11
11
  from hardpy.pytest_hardpy.reporter.base import BaseReporter
12
- from hardpy.pytest_hardpy.utils import TestStatus, RunStatus, NodeInfo
12
+ from hardpy.pytest_hardpy.utils import TestStatus, NodeInfo
13
13
 
14
14
 
15
15
  class HookReporter(BaseReporter):
16
16
  """Reporter for using in the hook HardPy plugin's hooks."""
17
17
 
18
- def __init__(self): # noqa: WPS612
18
+ def __init__(self, is_clear_database: bool = False): # noqa: WPS612
19
19
  super().__init__()
20
+ if is_clear_database:
21
+ self._statestore.clear()
20
22
  self._log = getLogger(__name__)
21
23
 
22
24
  def init_doc(self, doc_name: str):
@@ -33,6 +35,7 @@ class HookReporter(BaseReporter):
33
35
  self.set_doc_value(DF.PROGRESS, 0)
34
36
  self.set_doc_value(DF.DRIVERS, {})
35
37
  self.set_doc_value(DF.ARTIFACT, {}, runstore_only=True)
38
+ self.set_doc_value(DF.OPERATOR_MSG, {}, statestore_only=True)
36
39
 
37
40
  def start(self):
38
41
  """Start test."""
@@ -43,7 +46,7 @@ class HookReporter(BaseReporter):
43
46
  self.set_doc_value(DF.TIMEZONE, tzname) # noqa: WPS432
44
47
  self.set_doc_value(DF.PROGRESS, 0)
45
48
 
46
- def finish(self, status: RunStatus):
49
+ def finish(self, status: TestStatus):
47
50
  """Finish test.
48
51
 
49
52
  This method must be called at the end of test run.
@@ -196,6 +199,7 @@ class HookReporter(BaseReporter):
196
199
  DF.STOP_TIME: None,
197
200
  DF.ASSERTION_MSG: None,
198
201
  DF.MSG: None,
202
+ DF.ATTEMPT: 0,
199
203
  }
200
204
 
201
205
  if item.get(node_info.module_id) is None: # noqa: WPS204
@@ -2,6 +2,7 @@
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 logging import getLogger
5
+ from uuid import uuid4
5
6
 
6
7
  from pycouchdb import Server as DbServer
7
8
  from pycouchdb.exceptions import Conflict
@@ -11,7 +12,7 @@ from hardpy.pytest_hardpy.db.schema import ResultRunStore
11
12
  from hardpy.pytest_hardpy.result.couchdb_config import CouchdbConfig
12
13
 
13
14
 
14
- class CouchdbLoader(object):
15
+ class CouchdbLoader:
15
16
  """CouchDB report generator."""
16
17
 
17
18
  def __init__(self, config: CouchdbConfig):
@@ -51,7 +52,7 @@ class CouchdbLoader(object):
51
52
  device_serial_number = report.dut.serial_number
52
53
  if not device_serial_number:
53
54
  self._log.warning("Device serial number is not provided in the report.")
54
- return f"report_{timestamp}"
55
+ return f"report_{timestamp}_no_serial_{str(uuid4())[:6]}"
55
56
  return f"report_{timestamp}_{device_serial_number}"
56
57
 
57
58
  def _schema_to_dict(self, report: ResultRunStore, report_id: str) -> dict:
@@ -15,7 +15,7 @@ from hardpy.pytest_hardpy.result.couchdb_config import CouchdbConfig
15
15
 
16
16
 
17
17
  @dataclass
18
- class ReportInfo(object):
18
+ class ReportInfo:
19
19
  """CouchDB report info."""
20
20
 
21
21
  name: str
@@ -26,7 +26,7 @@ class ReportInfo(object):
26
26
  first_failed_test_id: Optional[str]
27
27
 
28
28
 
29
- class CouchdbReader(object):
29
+ class CouchdbReader:
30
30
  """CouchDB report info reader."""
31
31
 
32
32
  def __init__(self, config: CouchdbConfig):
@@ -3,11 +3,13 @@
3
3
 
4
4
  from hardpy.pytest_hardpy.utils.node_info import NodeInfo
5
5
  from hardpy.pytest_hardpy.utils.progress_calculator import ProgressCalculator
6
- from hardpy.pytest_hardpy.utils.const import TestStatus, RunStatus
6
+ from hardpy.pytest_hardpy.utils.const import TestStatus
7
7
  from hardpy.pytest_hardpy.utils.singleton import Singleton
8
- from hardpy.pytest_hardpy.utils.config_data import ConfigData
8
+ from hardpy.pytest_hardpy.utils.connection_data import ConnectionData
9
9
  from hardpy.pytest_hardpy.utils.exception import (
10
10
  DuplicateSerialNumberError,
11
+ DuplicatePartNumberError,
12
+ DuplicateTestStandNameError,
11
13
  DuplicateDialogBoxError,
12
14
  WidgetInfoError,
13
15
  )
@@ -27,10 +29,11 @@ __all__ = [
27
29
  "NodeInfo",
28
30
  "ProgressCalculator",
29
31
  "TestStatus",
30
- "RunStatus",
31
32
  "Singleton",
32
- "ConfigData",
33
+ "ConnectionData",
33
34
  "DuplicateSerialNumberError",
35
+ "DuplicatePartNumberError",
36
+ "DuplicateTestStandNameError",
34
37
  "DuplicateDialogBoxError",
35
38
  "WidgetInfoError",
36
39
  "DialogBox",
@@ -0,0 +1,17 @@
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 socket import gethostname
5
+
6
+ from hardpy.pytest_hardpy.utils.singleton import Singleton
7
+
8
+
9
+ class ConnectionData(Singleton):
10
+ """Connection data storage."""
11
+
12
+ def __init__(self):
13
+ if not self._initialized:
14
+ self.database_url: str = "http://dev:dev@localhost:5984/"
15
+ self.socket_host: str = gethostname()
16
+ self.socket_port: int = 6525
17
+ self._initialized = True
@@ -5,7 +5,10 @@ from enum import Enum
5
5
 
6
6
 
7
7
  class TestStatus(str, Enum): # noqa: WPS600
8
- """Pytest test status."""
8
+ """Pytest test status.
9
+
10
+ Statuses, that can be returned by Pytest.
11
+ """
9
12
 
10
13
  PASSED = "passed"
11
14
  FAILED = "failed"
@@ -14,16 +17,3 @@ class TestStatus(str, Enum): # noqa: WPS600
14
17
  RUN = "run"
15
18
  READY = "ready"
16
19
  STOPPED = "stopped"
17
-
18
-
19
- class RunStatus(str, Enum): # noqa: WPS600
20
- """Pytest run status."""
21
-
22
- PASSED = "passed"
23
- FAILED = "failed"
24
- STOPPED = "stopped"
25
- STARTED = "started"
26
- COLLECTED = "collected"
27
- BUSY = "busy"
28
- READY = "ready"
29
- ERROR = "error"
@@ -147,7 +147,7 @@ class CheckboxWidget(IWidget):
147
147
  """
148
148
  super().__init__(WidgetType.CHECKBOX)
149
149
  if not fields:
150
- raise ValueError("RadiobuttonWidget must have at least one field")
150
+ raise ValueError("Checkbox must have at least one field")
151
151
  self.info["fields"] = fields
152
152
 
153
153
  def convert_data(self, input_data: str) -> list[str] | None:
@@ -16,6 +16,20 @@ class DuplicateSerialNumberError(HardpyError):
16
16
  super().__init__(self.__doc__) # type: ignore
17
17
 
18
18
 
19
+ class DuplicatePartNumberError(HardpyError):
20
+ """The part number has already been determined."""
21
+
22
+ def __init__(self):
23
+ super().__init__(self.__doc__) # type: ignore
24
+
25
+
26
+ class DuplicateTestStandNameError(HardpyError):
27
+ """The test stand name has already been determined."""
28
+
29
+ def __init__(self):
30
+ super().__init__(self.__doc__) # type: ignore
31
+
32
+
19
33
  class DuplicateDialogBoxError(HardpyError):
20
34
  """The dialog box has already been determined."""
21
35
 
@@ -19,7 +19,7 @@ class TestDependencyInfo(NamedTuple):
19
19
  case_id: str | None
20
20
 
21
21
 
22
- class NodeInfo(object):
22
+ class NodeInfo:
23
23
  """Test node info."""
24
24
 
25
25
  def __init__(self, item: Item):
@@ -4,7 +4,7 @@
4
4
  from logging import getLogger
5
5
 
6
6
 
7
- class ProgressCalculator(object):
7
+ class ProgressCalculator:
8
8
  """Test run progress calculator."""
9
9
 
10
10
  def __init__(self):
@@ -1,7 +1,7 @@
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
- class Singleton(object):
4
+ class Singleton:
5
5
  """Singleton class.
6
6
 
7
7
  In the child class must be used constructor of type:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: hardpy
3
- Version: 0.5.1
3
+ Version: 0.6.1
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/
@@ -28,7 +28,9 @@ Requires-Dist: glom>=23.3.0
28
28
  Requires-Dist: natsort>=8.4.0
29
29
  Requires-Dist: pycouchdb>=1.14.2
30
30
  Requires-Dist: pydantic>=2.4.0
31
- Requires-Dist: pytest<9,>7
31
+ Requires-Dist: pytest<9,>=7
32
+ Requires-Dist: rtoml~=0.11.0
33
+ Requires-Dist: typer<1.0,>=0.12
32
34
  Requires-Dist: uvicorn>=0.23.2
33
35
  Provides-Extra: build
34
36
  Requires-Dist: build==1.0.3; extra == 'build'
@@ -74,71 +76,37 @@ HardPy allows you to:
74
76
  pip install hardpy
75
77
  ```
76
78
 
77
- ## Examples
78
-
79
- Find examples of using the **HardPy** in the `examples` folder.
80
-
81
79
  ## Getting Started
82
80
 
83
- #### CouchDB
84
-
85
- This is a simple instruction for Linux.
86
- For Windows, follow the instructions from the
87
- [documentation](https://everypinio.github.io/hardpy/documentation/database/#couchdb-instance).
88
-
89
- Launch CouchDB with Docker.
90
- The Docker version must be 24.0.0 or higher.
91
- Create `couchdb.ini` file:
92
-
93
- ```ini
94
- [chttpd]
95
- enable_cors=true
96
-
97
- [cors]
98
- origins = *
99
- methods = GET, PUT, POST, HEAD, DELETE
100
- credentials = true
101
- headers = accept, authorization, content-type, origin, referer, x-csrf-token
81
+ 1. Create your first test bench.
82
+ ```bash
83
+ hardpy init
102
84
  ```
103
-
104
- Run the Docker container from folder with couchdb.ini file:
105
-
85
+ 2. Launch [CouchDB](https://couchdb.apache.org/) database via [docker compose](https://docs.docker.com/compose/) in the background.
106
86
  ```bash
107
- docker run --rm --name couchdb -p 5984:5984 -e COUCHDB_USER=dev -e COUCHDB_PASSWORD=dev -v ./couchdb.ini:/opt/couchdb/etc/local.ini couchdb:3.3
87
+ cd tests
88
+ docker compose up -d
108
89
  ```
109
-
110
- Command for Windows:
111
-
90
+ 3. Launch HardPy operator panel.
112
91
  ```bash
113
- docker run --rm --name couchdb -p 5984:5984 -e COUCHDB_USER=dev -e COUCHDB_PASSWORD=dev -v .\couchdb.ini:/opt/couchdb/etc/local.ini couchdb:3.3.2
92
+ hardpy run
114
93
  ```
94
+ 4. View operator panel in browser: http://localhost:8000/
115
95
 
116
- #### Test steps
117
-
118
- Add simple test to `tests` folder
119
-
120
- ```python
121
- # test_1.py
122
- import pytest
123
-
124
- def test_one():
125
- assert True
126
- ```
127
- #### Operator panel
96
+ <h1 align="center">
97
+ <img src="https://everypinio.github.io/hardpy/img/hardpy_operator_panel_hello_hardpy.png"
98
+ alt="hardpy operator panel" style="width:600px;">
99
+ </h1>
128
100
 
129
- Launch `hardpy-panel` from tests folder or launch `hardpy-panel tests` and open page http://localhost:8000/ in browser.
101
+ 5. View the latest test report: http://localhost:5984/_utils
130
102
 
131
- <h1 align="center">
132
- <img src="https://everypinio.github.io/hardpy/img/hardpy_operator_panel_hello_hardpy.png"
133
- alt="hardpy operator panel" style="width:600px;">
134
- </h1>
103
+ Login and password: **dev**, database - **runstore**, document - **current**.
135
104
 
136
- #### Test report
105
+ <h1 align="center">
106
+ <img src="https://everypinio.github.io/hardpy/img/runstore_hello_hardpy.png"
107
+ alt="hardpy runstore" style="width:500px;">
108
+ </h1>
137
109
 
138
- The last test report is stored in **runstore** database, document - **current**.
139
- You can view the CouchDB instance through Fauxton web interface: http://localhost:5984/_utils
110
+ ## Examples
140
111
 
141
- <h1 align="center">
142
- <img src="https://everypinio.github.io/hardpy/img/runstore_hello_hardpy.png"
143
- alt="hardpy runstore" style="width:600px;">
144
- </h1>
112
+ Find more examples of using the **HardPy** in the [examples](https://github.com/everypinio/hardpy/tree/main/examples) folder.
@@ -1,10 +1,14 @@
1
- hardpy/__init__.py,sha256=_opqN5uChXP1nbR703eYrghBQ8wCR593sc5k04lCboM,1414
1
+ hardpy/__init__.py,sha256=1GtlRzkpmNVjZ6LcNYFVmEtgFCR3T6gLSLBLrZA9Nog,1692
2
+ hardpy/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
+ hardpy/cli/cli.py,sha256=Z0KGzZplCaHfyttKjMIqnE5upaca-H1XyiaZ2fUCHvM,4504
4
+ hardpy/cli/template.py,sha256=IgroGdzkKUn5BExDYtzw9djr1Ryvj39wRUF-VlKCToE,6461
5
+ hardpy/common/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
6
+ hardpy/common/config.py,sha256=rkvbFXFxoqBkYsEbCcnWX5d6G9hzS9Mr4mgQoSMbY6U,4497
2
7
  hardpy/hardpy_panel/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
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=WKgjuP2ksuEcMXfMu-965znPimRRRa9gNuzhU16L4kg,2824
8
+ hardpy/hardpy_panel/api.py,sha256=ew_3cTMW5XzS_EtHkH41z8ckOcJ_a5_zi3-AE8OKtEI,2969
9
+ hardpy/hardpy_panel/frontend/dist/asset-manifest.json,sha256=BnMkNkch6nsMmxLzKmOB3ne_jq-d5ksz2AS_M25r-jA,2824
6
10
  hardpy/hardpy_panel/frontend/dist/favicon.ico,sha256=sgIk5PKUKEKBDpkSrc8dJgjpObp0iF82Mec0GpfKId4,15406
7
- hardpy/hardpy_panel/frontend/dist/index.html,sha256=JsA4OoOv3mDXVkADLj1GvLAdDWb4U8coml1T7tYbfqg,656
11
+ hardpy/hardpy_panel/frontend/dist/index.html,sha256=6Ea-Fn6tO3DbWeeYbMp4HYix1SILrdny4OKnk2odti8,656
8
12
  hardpy/hardpy_panel/frontend/dist/logo512.png,sha256=-fIMbqX7PYUpheK4kX1C1erRTe_hHZwFQYDLrAbhFRU,34188
9
13
  hardpy/hardpy_panel/frontend/dist/manifest.json,sha256=PfmJlN2JMJtHS6OnhU4b4X5wPQC_yRBdjesjoirObSA,502
10
14
  hardpy/hardpy_panel/frontend/dist/static/css/main.e8a862f1.css,sha256=gNl6kGMBhtswNrUU6X2S6uosRU7xhxqI_p9gsEtBUqE,318244
@@ -21,9 +25,9 @@ hardpy/hardpy_panel/frontend/dist/static/js/blueprint-icons-all-paths.f63155c9.c
21
25
  hardpy/hardpy_panel/frontend/dist/static/js/blueprint-icons-all-paths.f63155c9.chunk.js.map,sha256=p1xKHRK4AZutkZsQHiWSNU61tYp7I3iUuyLLm3eqkHQ,2833
22
26
  hardpy/hardpy_panel/frontend/dist/static/js/blueprint-icons-split-paths-by-size-loader.52a072d3.chunk.js,sha256=Jl5xm_jQ9IXKhCagHHvnIhwYXb379Q5FFBiqPoKdUIE,605
23
27
  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.da686f40.js,sha256=20nf2pUAWN6a3DcOxklP_Jb6HJoWrr0qEJ6CQc0iaQA,1061346
25
- hardpy/hardpy_panel/frontend/dist/static/js/main.da686f40.js.LICENSE.txt,sha256=ForPNukClWMEP3pF9LMYoU-ve-LsyCH-rYU8eLki_FY,2315
26
- hardpy/hardpy_panel/frontend/dist/static/js/main.da686f40.js.map,sha256=LbY-5IH1ePKLPGT6gshR1eK_5j2L4U_Bpl5T7WLkXpo,5301647
28
+ hardpy/hardpy_panel/frontend/dist/static/js/main.7c954faf.js,sha256=e6kjJZEVUdfYrF2TE7_jXWmRkxv555N6ARVR5OSNquA,1062573
29
+ hardpy/hardpy_panel/frontend/dist/static/js/main.7c954faf.js.LICENSE.txt,sha256=ForPNukClWMEP3pF9LMYoU-ve-LsyCH-rYU8eLki_FY,2315
30
+ hardpy/hardpy_panel/frontend/dist/static/js/main.7c954faf.js.map,sha256=VpaF9MC2wZxpMZf-a7PgfXikuXzwK4nL3qKmknf-yn4,5306007
27
31
  hardpy/hardpy_panel/frontend/dist/static/media/blueprint-icons-16.520846c6beb41df528c8.eot,sha256=PTCTrQYNHX2hIPUaYWtOKrI30-iQGXt_EGxq6JCXie0,117628
28
32
  hardpy/hardpy_panel/frontend/dist/static/media/blueprint-icons-16.5c52b39c697f2323ce8b.svg,sha256=lDCQy06aS-9bmhwuFOUs-EdcR8MP2wqwAwky5oamtkQ,509417
29
33
  hardpy/hardpy_panel/frontend/dist/static/media/blueprint-icons-16.84db1772f4bfb529f64f.woff,sha256=edyqQN0nw4dNBs1pgr7pQB7nJhhR6T_YfklFcG_fHj0,53344
@@ -36,37 +40,37 @@ hardpy/hardpy_panel/frontend/dist/static/media/blueprint-icons-20.afbadb627d43b7
36
40
  hardpy/hardpy_panel/frontend/dist/static/media/blueprint-icons-20.e857f5a5132b8bfa71a1.woff,sha256=mQZTxE1PyyAL16VWuASOvXlZFwuI4aCPvbrhfgpdIdU,55356
37
41
  hardpy/hardpy_panel/frontend/dist/static/media/logo_smol.5b16f92447a4a9e80331.png,sha256=E4K7drvhJCg9HcTpRihOXZhVJVBZ7-W97Se-3tDb46o,14485
38
42
  hardpy/pytest_hardpy/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
39
- hardpy/pytest_hardpy/plugin.py,sha256=2-0ql5By6ROROEcHtxlXwpJ3zIqUeLC7GSOBE7AAkM4,12643
40
- hardpy/pytest_hardpy/pytest_call.py,sha256=mjRF1cXWmCRe9CL_Bz_kbEKUyDSldF7Ja1FkmjHIDdE,8442
41
- hardpy/pytest_hardpy/pytest_wrapper.py,sha256=18kCuS-TVXcXC2QiMsrbc5gHjv48tIMv0F3xAJCdi_U,4508
43
+ hardpy/pytest_hardpy/plugin.py,sha256=5DF29vbTPQ-nohiDDYay6Ml6GUHFnxZZDZHtKSFAOZE,14044
44
+ hardpy/pytest_hardpy/pytest_call.py,sha256=yXhp40ccOyeN0AJygenjQQ6fQKS2B85eW4-wZP2OgIQ,10184
45
+ hardpy/pytest_hardpy/pytest_wrapper.py,sha256=p11L4d1VIDmgeG8ltRQrmBRXqK1HRqBCQo63Qia_0SQ,4495
42
46
  hardpy/pytest_hardpy/db/__init__.py,sha256=MxDufncz0zgRAxrndvPXXW4NrU7rRP7MzIrR7S5Cwwo,558
43
- hardpy/pytest_hardpy/db/base_connector.py,sha256=7KUgPY-GmAo8MFN4OFpG5y3WH1xjohRnpeQ1gxQF1tg,751
44
- hardpy/pytest_hardpy/db/base_server.py,sha256=uBnq5zGkzEIq_EGzLw0C8kfDEDvQyN52Y6L41KKL9FQ,397
45
- hardpy/pytest_hardpy/db/base_store.py,sha256=DiYaBOwufEOdtDpo9dUb3ZaZ7-c1FInAWjLpUXSEFHA,2668
46
- hardpy/pytest_hardpy/db/const.py,sha256=b4Hq0gaT8SF5YBg21EIHoF3RMMHD3nRJBpvGmvVYQn0,648
47
+ hardpy/pytest_hardpy/db/base_connector.py,sha256=cmNV4Y6jFij8Fpp_74W0nqdBFa3J9c9in7MDeNJ4ZL0,1046
48
+ hardpy/pytest_hardpy/db/base_server.py,sha256=zZbek5jNjtXRVxOhFLWvmKrtOZsbQwrsW0pcql2gpUg,396
49
+ hardpy/pytest_hardpy/db/base_store.py,sha256=WkgBvvY4pEYp83jP3HxxSfmLztoMzAXh199J_mOQcX8,2900
50
+ hardpy/pytest_hardpy/db/const.py,sha256=7jmJOZA-V-Jjf8vyFqTuyqrKueiPDUO60jNj2z5jKsQ,738
47
51
  hardpy/pytest_hardpy/db/runstore.py,sha256=50amoTIO7OTqd5Ks1_7uTzqjCldLpTapkxbIQOgj1sQ,1023
48
- hardpy/pytest_hardpy/db/schema.py,sha256=AAf1qXEge0Bd2xwwx4A2DBOtUkbE36DTpbsOPczPUZ4,7529
49
- hardpy/pytest_hardpy/db/statestore.py,sha256=1BUfA4oqG4vx7z5v_uUYi_Un6YA769JeuShxDicrl9Q,636
52
+ hardpy/pytest_hardpy/db/schema.py,sha256=dDwVlXT1Jt_A-ZtjjbZG_QR6AeqTdHT79eLEIjkZIxU,8262
53
+ hardpy/pytest_hardpy/db/statestore.py,sha256=IBgPXQ0aAtaAOVW2Q-U9Pv0GqYY8o340K30EvDRdsAI,1025
50
54
  hardpy/pytest_hardpy/reporter/__init__.py,sha256=RONapygH3c_FyXokAlyCVJXGV2cV_jCYDxLymvvA1uE,322
51
- hardpy/pytest_hardpy/reporter/base.py,sha256=M-lwli64ty9FW8HlGEpUyoFsZv48tyNgzPjCWVUrATY,1941
52
- hardpy/pytest_hardpy/reporter/hook_reporter.py,sha256=kZ3jx--ne9l3a27TmVdZCPBoqy53EuHYg2fHDGuJNes,10068
55
+ hardpy/pytest_hardpy/reporter/base.py,sha256=mnu_1exZ7IHj5SvhsAeRdZoZPe9uZFQoTt-Bg0wsO5s,1933
56
+ hardpy/pytest_hardpy/reporter/hook_reporter.py,sha256=WE7Z5KP-9VapexIev6Igd-H9Vxp_bjWxyug6fgbpJgA,10255
53
57
  hardpy/pytest_hardpy/reporter/runner_reporter.py,sha256=NXkBIoERqmLI-GYtHavmOWC5t6NIpcAE-NECrUKIAJs,827
54
58
  hardpy/pytest_hardpy/result/__init__.py,sha256=NMeCGx3yh8ds9VpaUpuNFDxbwgYFq3e-o7W6rYIv8uI,346
55
59
  hardpy/pytest_hardpy/result/couchdb_config.py,sha256=kttsrWzv9D99R3ms-hFbzVbrZ78B2me6rrJgncfs5jk,3129
56
60
  hardpy/pytest_hardpy/result/report_loader/__init__.py,sha256=FuHuD6IFZyaKj0yu5urhf6nkxGbiPONJ-WHnJ2jHwyc,251
57
- hardpy/pytest_hardpy/result/report_loader/couchdb_loader.py,sha256=1BGncK1NnwYJanm5TYETjMkqR7tmrUfGK8Sgnp2JZC8,2203
61
+ hardpy/pytest_hardpy/result/report_loader/couchdb_loader.py,sha256=Wwo_JBoPpwh72iHFaq5ZqHZw-_tWsXyalqje1jzYlfY,2247
58
62
  hardpy/pytest_hardpy/result/report_reader/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
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=UjvjcEV2r5nBB2hmez5cSq-TNdH6NNKmfSDVwxj66cE,1181
61
- hardpy/pytest_hardpy/utils/config_data.py,sha256=953nSUndqfiqk6oVMb7GYA4RYCFPIKkPpSthXgKtKKY,1113
62
- hardpy/pytest_hardpy/utils/const.py,sha256=rjW1Rzhe2vCr8GeQqeN_pafepGDYhjhY4u1VfTOVI6U,625
63
- hardpy/pytest_hardpy/utils/dialog_box.py,sha256=XmKQoPuBmesgv8fBm3FvIarRGxYFbvYq54vXnINA5fw,8196
64
- hardpy/pytest_hardpy/utils/exception.py,sha256=khifykRuFS7GyIyQcJeMg6VOgwhPPvzNqnIuyD2onzg,785
65
- hardpy/pytest_hardpy/utils/node_info.py,sha256=VnEbhKBNAL5xpuFtJTCg90TmkjkFCQA59F5W2RcOlx4,3157
66
- hardpy/pytest_hardpy/utils/progress_calculator.py,sha256=r0qb3p6_yDIyLeCshF3Ceo5pCzd3BoTahL4rCD2oMNw,1041
67
- hardpy/pytest_hardpy/utils/singleton.py,sha256=C8cgRDydnG2b5dcN1LCLw4aM-AUMAvJc1W39mTkNWlQ,614
68
- hardpy-0.5.1.dist-info/METADATA,sha256=rqydaDWQCSC8_UiPYkz6uF0_C475CleUaREiDWbX1DY,4305
69
- hardpy-0.5.1.dist-info/WHEEL,sha256=TJPnKdtrSue7xZ_AVGkp9YXcvDrobsjBds1du3Nx6dc,87
70
- hardpy-0.5.1.dist-info/entry_points.txt,sha256=q73g5GfznSUpjkayi0SV4uaAtrf7D-7rmDoWoEZmZe0,120
71
- hardpy-0.5.1.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
72
- hardpy-0.5.1.dist-info/RECORD,,
63
+ hardpy/pytest_hardpy/result/report_reader/couchdb_reader.py,sha256=Ns82mzerDa4HipX6Xea1uGkXmhf8UotX6KsiChD1ViM,5618
64
+ hardpy/pytest_hardpy/utils/__init__.py,sha256=R2a5la6zEQdEeeL-W-OWpAFFzXHswu8a_nAw3C53y38,1295
65
+ hardpy/pytest_hardpy/utils/connection_data.py,sha256=GTKXzl9MXt1XkwEPi6NxdWUghRmZOWBV8nfgnbRh50s,541
66
+ hardpy/pytest_hardpy/utils/const.py,sha256=SsqRisrq9OlCb9cK5sEjFW_bZ9V2Qw61P9iYObIj5Fg,423
67
+ hardpy/pytest_hardpy/utils/dialog_box.py,sha256=lY_q_SGRdWtza4paHrsMfKTCsSkN_V8WIH7V7r_PNdo,8187
68
+ hardpy/pytest_hardpy/utils/exception.py,sha256=BlkVea4wwHJeXcU1rpUqH9IbMBFQYHghOXhHWSvDz8Q,1156
69
+ hardpy/pytest_hardpy/utils/node_info.py,sha256=qBzNCv-0YwIcLxES3kIvOLSblaJ3ICrtKl-tdF2Ndnk,3149
70
+ hardpy/pytest_hardpy/utils/progress_calculator.py,sha256=L6jJgkO1uxx5U2KKmQfTsGwgX5Atrqka5KV7uiMcou8,1033
71
+ hardpy/pytest_hardpy/utils/singleton.py,sha256=vP1BMzLkQF0j7t7crijPj6uyAowfviihJeXDJvhTDxU,606
72
+ hardpy-0.6.1.dist-info/METADATA,sha256=HtkFMKxgEnDfNOSz8C-CQcyGYAyF_kmF2fAJM7MfcVI,3586
73
+ hardpy-0.6.1.dist-info/WHEEL,sha256=TJPnKdtrSue7xZ_AVGkp9YXcvDrobsjBds1du3Nx6dc,87
74
+ hardpy-0.6.1.dist-info/entry_points.txt,sha256=nL2sMkKMScNaOE0IPkYnu9Yr-BUswZvGSrwY-SxHY3E,102
75
+ hardpy-0.6.1.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
76
+ hardpy-0.6.1.dist-info/RECORD,,