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.
@@ -1 +1 @@
1
- import{_ as o,a as _,b as i,p as c,I as u}from"./index-Bl_IX0Up.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};
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-Bl_IX0Up.js"></script>
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>
@@ -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
- if con_data.sc_connection_only: # check
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 from READY or RUN to STOPPED."""
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 = module_data["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
- # update module statuses
425
- self._results[module_id]["module_status"] = TestStatus.STOPPED
426
- self._reporter.set_module_status(module_id, TestStatus.STOPPED)
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
- # case value is empty - case is not finished
434
- if module_value is None:
435
- case_id = module_key
436
- self._results[module_id][case_id] = TestStatus.STOPPED
437
- self._reporter.set_case_status(
438
- module_id,
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
- msg = "PYTEST_CURRENT_TEST variable is not set"
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 set_alert(self, alert: str) -> None:
198
- """Set alert message.
222
+ def get_module_start_time(self, module_id: str) -> int:
223
+ """Get module start time.
199
224
 
200
- Args:
201
- alert (str): alert message
225
+ Returns:
226
+ int: module time
202
227
  """
203
- self.set_doc_value(DF.ALERT, alert, statestore_only=True)
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.12.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=XSlfRd_tRoBEsZUrJXoMbs6VF40whcjixmzsbUrVfNo,9045
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=euoD6rG8hclol6SJ2629bcAIjj6UZdl9sEp6mlm_Kzw,7024
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/oauth_callback.py,sha256=GkADOnQ46HwxKEdgG_4bS1xX0ybfdQqMK3us-dMuHVw,3322
11
- hardpy/common/stand_cloud/registration.py,sha256=HxvTex-PxanfVMYt7jiOuxs2lSMt0-f5PbWBvbobvCU,6754
12
- hardpy/common/stand_cloud/token_storage.py,sha256=aH3-BRefCR-CHd0La6wOEwWxBZY8wOkdXh8WE86vLMo,856
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=d2hl85yjg39vnovgIVFrahQXYvCXS0LFDL2j_M_ZRqI,1851
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-B26356fZ.js,sha256=CbXV61mb3jGcg6XKR_5-qFByVFdSwrD7etX1ivlI_jg,309
21
- hardpy/hardpy_panel/frontend/dist/assets/allPathsLoader-0BeGWuiy.js,sha256=py8TcDy4MrJJYLL6q66zXdHFM7KEltoUvN5r7atd2rc,550
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-BEs5IL5-.js,sha256=19mgQwGFpV8yOhxvL02RtnpEye_5NIAeHC06_1NdY9E,472
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=smyZM03ijUsAvCcqnbNJU2YyjEt8xqkKaw5uL3OXTg8,18732
40
- hardpy/pytest_hardpy/pytest_call.py,sha256=NaJHZkaY85bG3gFVGHbIZPOAP761-iezRzUAjursLXA,13132
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=IGVzKpOTN2uauhrUn3HWTyHhhMQFXAWcOvfo1EzDOkw,2707
53
- hardpy/pytest_hardpy/reporter/hook_reporter.py,sha256=8cOlOgmLqDty4ib3p5gkZdi6ZAYqAFIjQhQ3Vm6AHGU,11952
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.12.0.dist-info/METADATA,sha256=jUwQ1T4g6Cpvqae4ZCdFagy5g4kKD1zr5QTJ9eaeNbs,3978
73
- hardpy-0.12.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
74
- hardpy-0.12.0.dist-info/entry_points.txt,sha256=nL2sMkKMScNaOE0IPkYnu9Yr-BUswZvGSrwY-SxHY3E,102
75
- hardpy-0.12.0.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
76
- hardpy-0.12.0.dist-info/RECORD,,
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