hardpy 0.12.0__py3-none-any.whl → 0.13.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/cli/cli.py +16 -11
- hardpy/common/stand_cloud/connector.py +142 -135
- hardpy/common/stand_cloud/oauth2.py +88 -0
- hardpy/common/stand_cloud/registration.py +50 -211
- hardpy/common/stand_cloud/token_manager.py +119 -0
- hardpy/common/stand_cloud/utils.py +33 -0
- hardpy/hardpy_panel/frontend/dist/assets/{allPaths-B26356fZ.js → allPaths-Cg7WZDXy.js} +1 -1
- hardpy/hardpy_panel/frontend/dist/assets/{allPathsLoader-0BeGWuiy.js → allPathsLoader-C79wUwqR.js} +2 -2
- hardpy/hardpy_panel/frontend/dist/assets/{index-Bl_IX0Up.js → index-De5CJ3kt.js} +2 -2
- hardpy/hardpy_panel/frontend/dist/assets/{splitPathsBySizeLoader-BEs5IL5-.js → splitPathsBySizeLoader-hWuLTMwD.js} +1 -1
- hardpy/hardpy_panel/frontend/dist/index.html +1 -1
- hardpy/pytest_hardpy/plugin.py +48 -24
- hardpy/pytest_hardpy/pytest_call.py +7 -3
- hardpy/pytest_hardpy/reporter/base.py +8 -0
- hardpy/pytest_hardpy/reporter/hook_reporter.py +40 -5
- {hardpy-0.12.0.dist-info → hardpy-0.13.0.dist-info}/METADATA +2 -1
- {hardpy-0.12.0.dist-info → hardpy-0.13.0.dist-info}/RECORD +20 -19
- hardpy/common/stand_cloud/oauth_callback.py +0 -95
- hardpy/common/stand_cloud/token_storage.py +0 -27
- {hardpy-0.12.0.dist-info → hardpy-0.13.0.dist-info}/WHEEL +0 -0
- {hardpy-0.12.0.dist-info → hardpy-0.13.0.dist-info}/entry_points.txt +0 -0
- {hardpy-0.12.0.dist-info → hardpy-0.13.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
import{_ as o,a as _,b as i,p as c,I as u}from"./index-
|
|
1
|
+
import{_ as o,a as _,b as i,p as c,I as u}from"./index-De5CJ3kt.js";var p=function(n,s){return o(void 0,void 0,void 0,function(){var a,r;return _(this,function(e){switch(e.label){case 0:return a=c(n),s!==u.STANDARD?[3,2]:[4,i(()=>import("./index-xb4M2ucX.js").then(t=>t.I),[])];case 1:return r=e.sent(),[3,4];case 2:return[4,i(()=>import("./index-BMEat_ws.js").then(t=>t.I),[])];case 3:r=e.sent(),e.label=4;case 4:return[2,r[a]]}})})};export{p as splitPathsBySizeLoader};
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
Learn how to configure a non-root public URL by running `npm run build`.
|
|
26
26
|
-->
|
|
27
27
|
<title>HardPy Operator Panel</title>
|
|
28
|
-
<script type="module" crossorigin src="/assets/index-
|
|
28
|
+
<script type="module" crossorigin src="/assets/index-De5CJ3kt.js"></script>
|
|
29
29
|
<link rel="stylesheet" crossorigin href="/assets/index-BwCQzehg.css">
|
|
30
30
|
</head>
|
|
31
31
|
<body>
|
hardpy/pytest_hardpy/plugin.py
CHANGED
|
@@ -175,6 +175,8 @@ class HardpyPlugin:
|
|
|
175
175
|
if "--collect-only" in session.config.invocation_params.args:
|
|
176
176
|
return
|
|
177
177
|
status = self._get_run_status(exitstatus)
|
|
178
|
+
if status == TestStatus.STOPPED:
|
|
179
|
+
self._stop_tests()
|
|
178
180
|
self._reporter.finish(status)
|
|
179
181
|
self._reporter.update_db_by_doc()
|
|
180
182
|
self._reporter.compact_all()
|
|
@@ -237,7 +239,8 @@ class HardpyPlugin:
|
|
|
237
239
|
|
|
238
240
|
con_data = ConnectionData()
|
|
239
241
|
|
|
240
|
-
|
|
242
|
+
# running tests depends on a connection to StandCloud
|
|
243
|
+
if con_data.sc_connection_only:
|
|
241
244
|
try:
|
|
242
245
|
sc_connector = StandCloudConnector(addr=con_data.sc_address)
|
|
243
246
|
except StandCloudError as exc:
|
|
@@ -407,40 +410,61 @@ class HardpyPlugin:
|
|
|
407
410
|
case ExitCode.TESTS_FAILED:
|
|
408
411
|
return TestStatus.FAILED
|
|
409
412
|
case ExitCode.INTERRUPTED:
|
|
410
|
-
self._stop_tests()
|
|
411
413
|
return TestStatus.STOPPED
|
|
412
414
|
case _:
|
|
413
415
|
return TestStatus.FAILED
|
|
414
416
|
|
|
415
417
|
def _stop_tests(self) -> None:
|
|
416
|
-
"""Update module and case statuses
|
|
418
|
+
"""Update module and case statuses to stopped and skipped."""
|
|
419
|
+
is_module_stopped = False
|
|
420
|
+
is_case_stopped = False
|
|
421
|
+
valid_statuses = {TestStatus.PASSED, TestStatus.FAILED, TestStatus.SKIPPED}
|
|
417
422
|
for module_id, module_data in self._results.items():
|
|
418
|
-
module_status =
|
|
419
|
-
|
|
420
|
-
# skip not ready and running modules
|
|
421
|
-
if module_status not in {TestStatus.READY, TestStatus.RUN}:
|
|
423
|
+
module_status = self._reporter.get_module_status(module_id)
|
|
424
|
+
if module_status in valid_statuses:
|
|
422
425
|
continue
|
|
423
426
|
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
# update case statuses
|
|
429
|
-
for module_key, module_value in module_data.items():
|
|
430
|
-
# module status is not a case_id
|
|
431
|
-
if module_key == "module_status":
|
|
427
|
+
is_module_stopped = self._stop_module(module_id, is_module_stopped)
|
|
428
|
+
for module_data_key in module_data:
|
|
429
|
+
# skip module status
|
|
430
|
+
if module_data_key == "module_status":
|
|
432
431
|
continue
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
case_id,
|
|
440
|
-
TestStatus.STOPPED,
|
|
441
|
-
)
|
|
432
|
+
case_id = module_data_key
|
|
433
|
+
case_status = self._reporter.get_case_status(module_id, case_id)
|
|
434
|
+
if case_status in valid_statuses:
|
|
435
|
+
continue
|
|
436
|
+
is_case_stopped = self._stop_case(module_id, case_id, is_case_stopped)
|
|
437
|
+
|
|
442
438
|
self._reporter.update_db_by_doc()
|
|
443
439
|
|
|
440
|
+
def _stop_module(self, module_id: str, is_module_stopped: bool) -> bool:
|
|
441
|
+
# stopped status is set only once other statuses are skipped
|
|
442
|
+
if is_module_stopped is False:
|
|
443
|
+
module_status = TestStatus.STOPPED
|
|
444
|
+
is_module_stopped = True
|
|
445
|
+
if not self._reporter.get_module_start_time(module_id):
|
|
446
|
+
self._reporter.set_module_start_time(module_id)
|
|
447
|
+
self._reporter.set_module_stop_time(module_id)
|
|
448
|
+
else:
|
|
449
|
+
module_status = TestStatus.SKIPPED
|
|
450
|
+
self._results[module_id]["module_status"] = module_status
|
|
451
|
+
self._reporter.set_module_status(module_id, module_status)
|
|
452
|
+
return is_module_stopped
|
|
453
|
+
|
|
454
|
+
def _stop_case(self, module_id: str, case_id: str, is_case_stopped: bool) -> bool:
|
|
455
|
+
# stopped status is set only once other statuses are skipped
|
|
456
|
+
if is_case_stopped is False:
|
|
457
|
+
case_status = TestStatus.STOPPED
|
|
458
|
+
is_case_stopped = True
|
|
459
|
+
if not self._reporter.get_case_start_time(module_id, case_id):
|
|
460
|
+
self._reporter.set_case_start_time(module_id, case_id)
|
|
461
|
+
self._reporter.set_case_stop_time(module_id, case_id)
|
|
462
|
+
else:
|
|
463
|
+
case_status = TestStatus.SKIPPED
|
|
464
|
+
self._results[module_id][case_id] = case_status
|
|
465
|
+
self._reporter.set_case_status(module_id, case_id, case_status)
|
|
466
|
+
return is_case_stopped
|
|
467
|
+
|
|
444
468
|
def _decode_assertion_msg(
|
|
445
469
|
self,
|
|
446
470
|
error: (
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
5
|
from dataclasses import dataclass
|
|
6
|
+
from inspect import stack
|
|
6
7
|
from os import environ
|
|
7
8
|
from time import sleep
|
|
8
9
|
from typing import Any
|
|
@@ -181,8 +182,8 @@ def set_message(msg: str, msg_key: str | None = None) -> None:
|
|
|
181
182
|
If not specified, a random ID will be generated.
|
|
182
183
|
"""
|
|
183
184
|
current_test = _get_current_test()
|
|
184
|
-
reporter = RunnerReporter()
|
|
185
185
|
|
|
186
|
+
reporter = RunnerReporter()
|
|
186
187
|
if msg_key is None:
|
|
187
188
|
msg_key = str(uuid4())
|
|
188
189
|
|
|
@@ -323,8 +324,8 @@ def run_dialog_box(dialog_box_data: DialogBox) -> Any: # noqa: ANN401
|
|
|
323
324
|
if not dialog_box_data.dialog_text:
|
|
324
325
|
msg = "The 'dialog_text' argument cannot be empty."
|
|
325
326
|
raise ValueError(msg)
|
|
326
|
-
current_test = _get_current_test()
|
|
327
327
|
reporter = RunnerReporter()
|
|
328
|
+
current_test = _get_current_test()
|
|
328
329
|
key = reporter.generate_key(
|
|
329
330
|
DF.MODULES,
|
|
330
331
|
current_test.module_id,
|
|
@@ -420,7 +421,10 @@ def _get_current_test() -> CurrentTestInfo:
|
|
|
420
421
|
current_node = environ.get("PYTEST_CURRENT_TEST")
|
|
421
422
|
|
|
422
423
|
if current_node is None:
|
|
423
|
-
|
|
424
|
+
reporter = RunnerReporter()
|
|
425
|
+
caller = stack()[1].function
|
|
426
|
+
msg = f"Function {caller} can't be called outside of the test."
|
|
427
|
+
reporter.set_alert(msg)
|
|
424
428
|
raise RuntimeError(msg)
|
|
425
429
|
|
|
426
430
|
module_delimiter = ".py::"
|
|
@@ -53,6 +53,14 @@ class BaseReporter:
|
|
|
53
53
|
self._runstore.update_doc_value(key, value)
|
|
54
54
|
self._statestore.update_doc_value(key, value)
|
|
55
55
|
|
|
56
|
+
def set_alert(self, alert: str) -> None:
|
|
57
|
+
"""Set alert message.
|
|
58
|
+
|
|
59
|
+
Args:
|
|
60
|
+
alert (str): alert message
|
|
61
|
+
"""
|
|
62
|
+
self.set_doc_value(DF.ALERT, alert, statestore_only=True)
|
|
63
|
+
|
|
56
64
|
def update_db_by_doc(self) -> None:
|
|
57
65
|
"""Update database by current document."""
|
|
58
66
|
self._statestore.update_db()
|
|
@@ -129,6 +129,19 @@ class HookReporter(BaseReporter):
|
|
|
129
129
|
key = self.generate_key(DF.MODULES, module_id, DF.CASES, case_id, DF.STATUS)
|
|
130
130
|
self.set_doc_value(key, status)
|
|
131
131
|
|
|
132
|
+
def get_case_status(self, module_id: str, case_id: str) -> str:
|
|
133
|
+
"""Set test case status.
|
|
134
|
+
|
|
135
|
+
Args:
|
|
136
|
+
module_id (str): module id
|
|
137
|
+
case_id (str): case id
|
|
138
|
+
|
|
139
|
+
Returns:
|
|
140
|
+
str: test case status
|
|
141
|
+
"""
|
|
142
|
+
key = self.generate_key(DF.MODULES, module_id, DF.CASES, case_id, DF.STATUS)
|
|
143
|
+
return self._statestore.get_field(key)
|
|
144
|
+
|
|
132
145
|
def set_case_start_time(self, module_id: str, case_id: str) -> None:
|
|
133
146
|
"""Set test case start_time.
|
|
134
147
|
|
|
@@ -159,6 +172,18 @@ class HookReporter(BaseReporter):
|
|
|
159
172
|
key = self.generate_key(DF.MODULES, module_id, DF.STATUS)
|
|
160
173
|
self.set_doc_value(key, status)
|
|
161
174
|
|
|
175
|
+
def get_module_status(self, module_id: str) -> str:
|
|
176
|
+
"""Get test module status.
|
|
177
|
+
|
|
178
|
+
Args:
|
|
179
|
+
module_id (str): module id
|
|
180
|
+
|
|
181
|
+
Returns:
|
|
182
|
+
str: test module status
|
|
183
|
+
"""
|
|
184
|
+
key = self.generate_key(DF.MODULES, module_id, DF.STATUS)
|
|
185
|
+
return self._statestore.get_field(key)
|
|
186
|
+
|
|
162
187
|
def set_module_start_time(self, module_id: str) -> None:
|
|
163
188
|
"""Set test module status.
|
|
164
189
|
|
|
@@ -194,13 +219,23 @@ class HookReporter(BaseReporter):
|
|
|
194
219
|
)
|
|
195
220
|
self.set_doc_value(key, attempt, statestore_only=True)
|
|
196
221
|
|
|
197
|
-
def
|
|
198
|
-
"""
|
|
222
|
+
def get_module_start_time(self, module_id: str) -> int:
|
|
223
|
+
"""Get module start time.
|
|
199
224
|
|
|
200
|
-
|
|
201
|
-
|
|
225
|
+
Returns:
|
|
226
|
+
int: module time
|
|
202
227
|
"""
|
|
203
|
-
self.
|
|
228
|
+
key = self.generate_key(DF.MODULES, module_id, DF.START_TIME)
|
|
229
|
+
return self._statestore.get_field(key)
|
|
230
|
+
|
|
231
|
+
def get_case_start_time(self, module_id: str, case_id: str) -> int:
|
|
232
|
+
"""Get case start time.
|
|
233
|
+
|
|
234
|
+
Returns:
|
|
235
|
+
int: module time
|
|
236
|
+
"""
|
|
237
|
+
key = self.generate_key(DF.MODULES, module_id, DF.CASES, case_id, DF.START_TIME)
|
|
238
|
+
return self._statestore.get_field(key)
|
|
204
239
|
|
|
205
240
|
def update_node_order(self, nodes: dict) -> None:
|
|
206
241
|
"""Update node order.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: hardpy
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.13.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/
|
|
@@ -34,6 +34,7 @@ Requires-Dist: py-machineid~=0.6.0
|
|
|
34
34
|
Requires-Dist: pycouchdb<2,>=1.14.2
|
|
35
35
|
Requires-Dist: pydantic<3,>=2.4.0
|
|
36
36
|
Requires-Dist: pytest<9,>=7
|
|
37
|
+
Requires-Dist: qrcode>=8
|
|
37
38
|
Requires-Dist: requests-oauth2client<2,>=1.5.0
|
|
38
39
|
Requires-Dist: requests-oauthlib<3,>=2.0.0
|
|
39
40
|
Requires-Dist: requests<3,>=2.30.0
|
|
@@ -1,24 +1,25 @@
|
|
|
1
1
|
hardpy/__init__.py,sha256=49-EDyH1KzK7kmuU9zFHAe8bUPfuayzcUIk3ksXiL7s,2237
|
|
2
2
|
hardpy/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
3
|
-
hardpy/cli/cli.py,sha256=
|
|
3
|
+
hardpy/cli/cli.py,sha256=FPXCFTqnC5fST9g7EjRd4ODBkvBPZ-r0XglF_vMU3Go,9164
|
|
4
4
|
hardpy/cli/template.py,sha256=44phTqeKgFch5xdAJmDQ-za1mM1_z60izRVbmCQHU-8,6225
|
|
5
5
|
hardpy/common/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
6
6
|
hardpy/common/config.py,sha256=nA2r2FrdKl0e-OqVvoa-3KvQ26Af-b86j7RMhGsWCPE,4966
|
|
7
7
|
hardpy/common/stand_cloud/__init__.py,sha256=fezdiYAehtT2H-GAef-xZU12CbmCRe64XHA9UB3kJDU,456
|
|
8
|
-
hardpy/common/stand_cloud/connector.py,sha256=
|
|
8
|
+
hardpy/common/stand_cloud/connector.py,sha256=oAfyT4h5HPWT5JeWcUBFyymncPmGWMpNkpeefYf99xM,7318
|
|
9
9
|
hardpy/common/stand_cloud/exception.py,sha256=eKkqu5ylDRIGN_yZhvz2xVGm49XmlZ8nryALgdRqpbY,287
|
|
10
|
-
hardpy/common/stand_cloud/
|
|
11
|
-
hardpy/common/stand_cloud/registration.py,sha256=
|
|
12
|
-
hardpy/common/stand_cloud/
|
|
10
|
+
hardpy/common/stand_cloud/oauth2.py,sha256=SDqtIwcuMgqfBkEZyo3GXeVPnvRBOr6dzeXowx3ZkEw,2803
|
|
11
|
+
hardpy/common/stand_cloud/registration.py,sha256=UW-JGcvON5CMQQ-s2Mb4Ee3u_jmdQfSj3vPfZ_FuhHY,2370
|
|
12
|
+
hardpy/common/stand_cloud/token_manager.py,sha256=8dX802F0CnOrOjOQInyYCrvuRdK0CeiCrTDITAbSLgQ,4055
|
|
13
|
+
hardpy/common/stand_cloud/utils.py,sha256=GN3wzbrmF-Xe5iUXf_HurGO-YKltqd3Gc_7vG2eEL7c,692
|
|
13
14
|
hardpy/hardpy_panel/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
14
15
|
hardpy/hardpy_panel/api.py,sha256=BRY_RuYKPo0e1WdVCPS7iA46GzLIc5A4hLPvtagKqRc,3533
|
|
15
16
|
hardpy/hardpy_panel/frontend/dist/favicon.ico,sha256=sgIk5PKUKEKBDpkSrc8dJgjpObp0iF82Mec0GpfKId4,15406
|
|
16
|
-
hardpy/hardpy_panel/frontend/dist/index.html,sha256=
|
|
17
|
+
hardpy/hardpy_panel/frontend/dist/index.html,sha256=rDoetZX8aPQ5CD7Whs3GIIDF1NI9EwiAuTKJ_JM-sBI,1851
|
|
17
18
|
hardpy/hardpy_panel/frontend/dist/logo192.png,sha256=E4K7drvhJCg9HcTpRihOXZhVJVBZ7-W97Se-3tDb46o,14485
|
|
18
19
|
hardpy/hardpy_panel/frontend/dist/logo512.png,sha256=-fIMbqX7PYUpheK4kX1C1erRTe_hHZwFQYDLrAbhFRU,34188
|
|
19
20
|
hardpy/hardpy_panel/frontend/dist/manifest.json,sha256=PfmJlN2JMJtHS6OnhU4b4X5wPQC_yRBdjesjoirObSA,502
|
|
20
|
-
hardpy/hardpy_panel/frontend/dist/assets/allPaths-
|
|
21
|
-
hardpy/hardpy_panel/frontend/dist/assets/allPathsLoader-
|
|
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
|
|
22
23
|
hardpy/hardpy_panel/frontend/dist/assets/blueprint-icons-16-Bfs1BwbR.ttf,sha256=wA1ItrnCJli8ESQ1KwLR3egJZG55dKBbLPonqFIa0K0,117420
|
|
23
24
|
hardpy/hardpy_panel/frontend/dist/assets/blueprint-icons-16-Btb8d-Hu.woff,sha256=edyqQN0nw4dNBs1pgr7pQB7nJhhR6T_YfklFcG_fHj0,53344
|
|
24
25
|
hardpy/hardpy_panel/frontend/dist/assets/blueprint-icons-16-CzsyEoPG.svg,sha256=lDCQy06aS-9bmhwuFOUs-EdcR8MP2wqwAwky5oamtkQ,509417
|
|
@@ -30,14 +31,14 @@ hardpy/hardpy_panel/frontend/dist/assets/blueprint-icons-20-Doom1bSH.eot,sha256=
|
|
|
30
31
|
hardpy/hardpy_panel/frontend/dist/assets/blueprint-icons-20-DyVnGNfQ.svg,sha256=BsTLtmUaqeiMSZwv2ysmTV4qWVv-qYbwsE0_sVUjJk0,546938
|
|
31
32
|
hardpy/hardpy_panel/frontend/dist/assets/blueprint-icons-20-ZW-9JnPf.woff,sha256=mQZTxE1PyyAL16VWuASOvXlZFwuI4aCPvbrhfgpdIdU,55356
|
|
32
33
|
hardpy/hardpy_panel/frontend/dist/assets/index-BMEat_ws.js,sha256=ZiKN4IGxolgim42tqk68UOPUA0g8ABojet1dj4Wru1s,254121
|
|
33
|
-
hardpy/hardpy_panel/frontend/dist/assets/index-Bl_IX0Up.js,sha256=eiRyh2G4k3lhsY2Xr5b6MvfYaMW0qKEOxw0VkZkZ8o4,984130
|
|
34
34
|
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
|
|
35
36
|
hardpy/hardpy_panel/frontend/dist/assets/index-xb4M2ucX.js,sha256=eeaZrH0pRpkWViEVZ2Mt6f7VgpOxluRB7S8SovkFeTE,245762
|
|
36
37
|
hardpy/hardpy_panel/frontend/dist/assets/logo_smol-CK3jE85c.png,sha256=E4K7drvhJCg9HcTpRihOXZhVJVBZ7-W97Se-3tDb46o,14485
|
|
37
|
-
hardpy/hardpy_panel/frontend/dist/assets/splitPathsBySizeLoader-
|
|
38
|
+
hardpy/hardpy_panel/frontend/dist/assets/splitPathsBySizeLoader-hWuLTMwD.js,sha256=ocYr1jFgVEcJXCdClz5Is83Cd0nZo-j-0p5I8scwjBU,472
|
|
38
39
|
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=
|
|
40
|
+
hardpy/pytest_hardpy/plugin.py,sha256=vyG2LvZj5NC_M2iXmVNlGZJJFOpGwtviGbhMCHtyQqE,20017
|
|
41
|
+
hardpy/pytest_hardpy/pytest_call.py,sha256=TNDcbH0uuquqpNVjT_MGXZ8ukpze3ceWA5M4DUuKuEM,13279
|
|
41
42
|
hardpy/pytest_hardpy/pytest_wrapper.py,sha256=_eULTqbJhFj0uu3XPplS4WSrI_LJC_ZX2kA5t5YJ49U,5162
|
|
42
43
|
hardpy/pytest_hardpy/db/__init__.py,sha256=G6y13JPh8HaH2O9E3_LTH_bTUVSgiezQFjDGaNIljec,557
|
|
43
44
|
hardpy/pytest_hardpy/db/base_connector.py,sha256=5a476F5LwvFUfQ4Yc0Q6biacULDrCk8UHPlpc6n0NRQ,1111
|
|
@@ -49,8 +50,8 @@ hardpy/pytest_hardpy/db/statestore.py,sha256=0sv4AqzwW_J34O-cb7aN3zmgULIVtZRi_qg
|
|
|
49
50
|
hardpy/pytest_hardpy/db/schema/__init__.py,sha256=1S73W3PLQt8gX5Y33nbX1JdwLvnrtlKH4cElID3pwuc,263
|
|
50
51
|
hardpy/pytest_hardpy/db/schema/v1.py,sha256=lWE5jWh5ek43-i4aKO51lflNPoyyzaveV06PP5nKQ3Y,9897
|
|
51
52
|
hardpy/pytest_hardpy/reporter/__init__.py,sha256=rztpM2HlLUpMOvad0JHbZU4Mk8PDDQyCFXLhpLktGQI,322
|
|
52
|
-
hardpy/pytest_hardpy/reporter/base.py,sha256=
|
|
53
|
-
hardpy/pytest_hardpy/reporter/hook_reporter.py,sha256=
|
|
53
|
+
hardpy/pytest_hardpy/reporter/base.py,sha256=KRkc5a7yk9ZsQ92gnBdHhJEXSSQiTWbEMSMzRMpJDFY,2915
|
|
54
|
+
hardpy/pytest_hardpy/reporter/hook_reporter.py,sha256=0xdga2rqwxUJKpkX6t7XaY9hPdhoKmisIDoZ6IJVXXQ,13027
|
|
54
55
|
hardpy/pytest_hardpy/reporter/runner_reporter.py,sha256=YsK8wrLIulsixePG6WNfC4MagpKfhP5j0CUaXkcfeL0,790
|
|
55
56
|
hardpy/pytest_hardpy/result/__init__.py,sha256=2afpuEuOcxYfIEOwWzsGZe960iQaPVCmsbYujijQg1s,592
|
|
56
57
|
hardpy/pytest_hardpy/result/couchdb_config.py,sha256=ujxyJYM2pdZzi3GZ2Zysbz2_ZeTRN5sQc8AGuzRJm_0,3243
|
|
@@ -69,8 +70,8 @@ hardpy/pytest_hardpy/utils/machineid.py,sha256=6JAzUt7KtjTYn8kL9hSMaCQ20U8liH-zD
|
|
|
69
70
|
hardpy/pytest_hardpy/utils/node_info.py,sha256=BibPo2ltxy-hIUQbaYA2om7x1LNK1JvQtHNC0EKl_9k,5474
|
|
70
71
|
hardpy/pytest_hardpy/utils/progress_calculator.py,sha256=TPl2gG0ZSvMe8otPythhF9hkD6fa6-mJAhy9yI83-yE,1071
|
|
71
72
|
hardpy/pytest_hardpy/utils/singleton.py,sha256=tjUGs48o_vBeVpRsEBZEOTCoCUikpIFmQ1c3rsfymso,948
|
|
72
|
-
hardpy-0.
|
|
73
|
-
hardpy-0.
|
|
74
|
-
hardpy-0.
|
|
75
|
-
hardpy-0.
|
|
76
|
-
hardpy-0.
|
|
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,,
|
|
@@ -1,95 +0,0 @@
|
|
|
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
|
-
import json
|
|
5
|
-
from http import HTTPStatus
|
|
6
|
-
|
|
7
|
-
from fastapi import FastAPI, Request
|
|
8
|
-
from fastapi.responses import HTMLResponse
|
|
9
|
-
from fastapi.templating import Jinja2Templates
|
|
10
|
-
|
|
11
|
-
app = FastAPI()
|
|
12
|
-
|
|
13
|
-
templates = Jinja2Templates(directory="templates")
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
@app.route("/oauth2/callback")
|
|
17
|
-
async def index(request: Request) -> None:
|
|
18
|
-
"""OAuth2 callback page."""
|
|
19
|
-
print(json.dumps(dict(request.query_params))) # noqa: T201
|
|
20
|
-
success_template = """
|
|
21
|
-
<html><body>
|
|
22
|
-
<h1>😎 Success</h1>
|
|
23
|
-
<p>You have been redirected from the Authentication Portal<p>
|
|
24
|
-
<p>Your received response data:</p>
|
|
25
|
-
<ul>
|
|
26
|
-
<li><b>Authorization Code</b>: <i>{{code}}</i></li>
|
|
27
|
-
<li><b>Issuer</b>: <i>{{iss}}</i></li>
|
|
28
|
-
<li><b>Scope of the access request</b>: <i>{{scope}}</i></li>
|
|
29
|
-
<li><b>State data</b>: <i>{{state}}</i></li>
|
|
30
|
-
</ul>
|
|
31
|
-
<p>It is the technical data needed by the application that requests access token.</p>
|
|
32
|
-
<p>Probably, the application already received this information.</p>
|
|
33
|
-
<p><b>ℹ️ You can close the window</b></p>
|
|
34
|
-
</body></html>
|
|
35
|
-
""" # noqa: E501, RUF001
|
|
36
|
-
|
|
37
|
-
error_template = """
|
|
38
|
-
<html><body>
|
|
39
|
-
<h1>😞 Error: '{{error}}'</h1>
|
|
40
|
-
<p>You have been redirected from the Authentication Portal<p>
|
|
41
|
-
<p>Your received response data:</p>
|
|
42
|
-
<ul>
|
|
43
|
-
<li><b>Error description</b>: <i>{{error_description}}</i></li>
|
|
44
|
-
<li><b>Issuer</b>: <i>{{iss}}</i></li>
|
|
45
|
-
<li><b>State data</b>: <i>{{state}}</i></li>
|
|
46
|
-
</ul>
|
|
47
|
-
<p>It is the technical data needed by the application that requests access token.</p>
|
|
48
|
-
<p>Probably, the application already received this information.</p>
|
|
49
|
-
<p><b>ℹ️ You can close the window</b></p>
|
|
50
|
-
</body></html>
|
|
51
|
-
""" # noqa: E501, RUF001
|
|
52
|
-
|
|
53
|
-
if request.query_params.get("code") is not None:
|
|
54
|
-
return HTMLResponse(
|
|
55
|
-
content=success_template.replace(
|
|
56
|
-
"{{code}}",
|
|
57
|
-
request.query_params.get("code"), # type: ignore
|
|
58
|
-
)
|
|
59
|
-
.replace("{{iss}}", request.query_params.get("iss"))
|
|
60
|
-
.replace("{{scope}}", request.query_params.get("scope"))
|
|
61
|
-
.replace("{{state}}", request.query_params.get("state")),
|
|
62
|
-
status_code=HTTPStatus.OK,
|
|
63
|
-
)
|
|
64
|
-
|
|
65
|
-
if request.query_params.get("error") is not None:
|
|
66
|
-
return HTMLResponse(
|
|
67
|
-
content=error_template.replace(
|
|
68
|
-
"{{error}}",
|
|
69
|
-
request.query_params.get("error"), # type: ignore
|
|
70
|
-
)
|
|
71
|
-
.replace(
|
|
72
|
-
"{{error_description}}",
|
|
73
|
-
request.query_params.get("error_description"),
|
|
74
|
-
)
|
|
75
|
-
.replace("{{iss}}", request.query_params.get("iss"))
|
|
76
|
-
.replace("{{state}}", request.query_params.get("state")),
|
|
77
|
-
status_code=HTTPStatus.OK,
|
|
78
|
-
)
|
|
79
|
-
|
|
80
|
-
server_error = """
|
|
81
|
-
<html><body>
|
|
82
|
-
<h1>Internal Server Error'</h1>
|
|
83
|
-
</body></html>
|
|
84
|
-
"""
|
|
85
|
-
|
|
86
|
-
return HTMLResponse(
|
|
87
|
-
content=server_error,
|
|
88
|
-
status_code=HTTPStatus.INTERNAL_SERVER_ERROR,
|
|
89
|
-
) # type: ignore
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
if __name__ == "__main__":
|
|
93
|
-
import uvicorn
|
|
94
|
-
|
|
95
|
-
uvicorn.run(app, host="127.0.0.1", port=8088)
|
|
@@ -1,27 +0,0 @@
|
|
|
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
|
-
from __future__ import annotations
|
|
4
|
-
|
|
5
|
-
from platform import system
|
|
6
|
-
from typing import TYPE_CHECKING
|
|
7
|
-
|
|
8
|
-
from keyring.core import load_keyring
|
|
9
|
-
|
|
10
|
-
if TYPE_CHECKING:
|
|
11
|
-
from keyring.backend import KeyringBackend
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
def get_token_store() -> tuple[KeyringBackend, KeyringBackend]:
|
|
15
|
-
"""Get token store.
|
|
16
|
-
|
|
17
|
-
Returns:
|
|
18
|
-
tuple[KeyringBackend, KeyringBackend]: token store
|
|
19
|
-
"""
|
|
20
|
-
if system() == "Linux":
|
|
21
|
-
storage_keyring = load_keyring("keyring.backends.SecretService.Keyring")
|
|
22
|
-
elif system() == "Windows":
|
|
23
|
-
storage_keyring = load_keyring("keyring.backends.Windows.WinVaultKeyring")
|
|
24
|
-
# TODO(xorialexandrov): add memory keyring or other store
|
|
25
|
-
mem_keyring = storage_keyring
|
|
26
|
-
|
|
27
|
-
return storage_keyring, mem_keyring
|
|
File without changes
|
|
File without changes
|
|
File without changes
|