hardpy 0.18.3__py3-none-any.whl → 0.19.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.
- hardpy/common/config.py +45 -2
- hardpy/hardpy_panel/api.py +100 -11
- hardpy/hardpy_panel/frontend/dist/assets/{allPaths-31ulJ0tA.js → allPaths-C_-7WXHD.js} +1 -1
- hardpy/hardpy_panel/frontend/dist/assets/{allPathsLoader-HPn4WHWu.js → allPathsLoader-DgH0Xily.js} +2 -2
- hardpy/hardpy_panel/frontend/dist/assets/{browser-ponyfill-BQ1ipruI.js → browser-ponyfill-BbOvdqIF.js} +1 -1
- hardpy/hardpy_panel/frontend/dist/assets/index-DEJb2W0B.js +4679 -0
- hardpy/hardpy_panel/frontend/dist/assets/{splitPathsBySizeLoader-ev1ZiRR9.js → splitPathsBySizeLoader-o5HCcdVL.js} +1 -1
- hardpy/hardpy_panel/frontend/dist/index.html +1 -1
- hardpy/hardpy_panel/frontend/dist/locales/cs/translation.json +85 -0
- hardpy/hardpy_panel/frontend/dist/locales/de/translation.json +11 -1
- hardpy/hardpy_panel/frontend/dist/locales/en/translation.json +11 -1
- hardpy/hardpy_panel/frontend/dist/locales/es/translation.json +11 -1
- hardpy/hardpy_panel/frontend/dist/locales/fr/translation.json +11 -1
- hardpy/hardpy_panel/frontend/dist/locales/ja/translation.json +11 -1
- hardpy/hardpy_panel/frontend/dist/locales/ru/translation.json +11 -1
- hardpy/hardpy_panel/frontend/dist/locales/zh/translation.json +11 -1
- hardpy/pytest_hardpy/plugin.py +24 -0
- hardpy/pytest_hardpy/pytest_wrapper.py +91 -5
- hardpy/pytest_hardpy/reporter/base.py +5 -0
- hardpy/pytest_hardpy/reporter/hook_reporter.py +19 -2
- {hardpy-0.18.3.dist-info → hardpy-0.19.1.dist-info}/METADATA +2 -1
- {hardpy-0.18.3.dist-info → hardpy-0.19.1.dist-info}/RECORD +25 -24
- hardpy/hardpy_panel/frontend/dist/assets/index-BK2y65ib.js +0 -4673
- {hardpy-0.18.3.dist-info → hardpy-0.19.1.dist-info}/WHEEL +0 -0
- {hardpy-0.18.3.dist-info → hardpy-0.19.1.dist-info}/entry_points.txt +0 -0
- {hardpy-0.18.3.dist-info → hardpy-0.19.1.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-DEJb2W0B.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-DLOviMB1.js").then(t=>t.I),[])];case 1:return r=e.sent(),[3,4];case 2:return[4,i(()=>import("./index-B-fsa5Ru.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-DEJb2W0B.js"></script>
|
|
29
29
|
<link rel="stylesheet" crossorigin href="/assets/index-B7T9xvaW.css">
|
|
30
30
|
</head>
|
|
31
31
|
<body>
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
{
|
|
2
|
+
"app": {
|
|
3
|
+
"title": "HardPy Panel operátora",
|
|
4
|
+
"lastLaunch": "Poslední běh:",
|
|
5
|
+
"duration": "Doba trvání",
|
|
6
|
+
"seconds": "s",
|
|
7
|
+
"soundOn": "Zapnout zvuk",
|
|
8
|
+
"soundOff": "Vypnout zvuk",
|
|
9
|
+
"debugOn": "Zapnout režim ladění",
|
|
10
|
+
"debugOff": "Vypnout režim ladění",
|
|
11
|
+
"connection": "Navazuji spojení... 🧐🔎",
|
|
12
|
+
"dbError": "Chyba připojení k databázi. 🙅🏽♀️🚫",
|
|
13
|
+
"noEntries": "Žádné záznamy v databázi 🙅🏽♀️🚫",
|
|
14
|
+
"stoppedTestCase": "Zastavený test",
|
|
15
|
+
"failedTestCases": "Testy selhaly",
|
|
16
|
+
"modalResultDismissHint": "Klikněte kamkoliv nebo stiskněte libovolnou klávesu pro zavření",
|
|
17
|
+
"modalResultAutoDismissHint": "Automaticky zmizí za {{seconds}} sekund...",
|
|
18
|
+
"manualCollectOn": "Zapnout manuální výběr testů",
|
|
19
|
+
"manualCollectOff": "Vypnout manuální výběr testů",
|
|
20
|
+
"testConfigurationSelector": "Vyberte testovací konfiguraci",
|
|
21
|
+
"status": {
|
|
22
|
+
"ready": "Připraveno",
|
|
23
|
+
"run": "Běží",
|
|
24
|
+
"passed": "Uspěl",
|
|
25
|
+
"failed": "Neuspěl",
|
|
26
|
+
"stopped": "Zastaveno",
|
|
27
|
+
"unknown": "Neznámý"
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
"button": {
|
|
31
|
+
"start": "Začít",
|
|
32
|
+
"stop": "Zastavit",
|
|
33
|
+
"confirm": "Potvrdit",
|
|
34
|
+
"pass": "OK",
|
|
35
|
+
"fail": "Zrušit"
|
|
36
|
+
},
|
|
37
|
+
"error": {
|
|
38
|
+
"dbConnectionTitle": "Chyba připojení k databázi",
|
|
39
|
+
"dbConnectionMessage": "Nepodařilo se navázat spojení s databází"
|
|
40
|
+
},
|
|
41
|
+
"chart": {
|
|
42
|
+
"dataChart": "Grafy",
|
|
43
|
+
"xAxis": "Osa X",
|
|
44
|
+
"yAxis": "Osa Y",
|
|
45
|
+
"chart": "Graf",
|
|
46
|
+
"showChart": "Zobrazit graf {{title}}",
|
|
47
|
+
"fullscreenButton": "Otevřít graf na celé obrazovce",
|
|
48
|
+
"series": "Řada {{number}}"
|
|
49
|
+
},
|
|
50
|
+
"operatorDialog": {
|
|
51
|
+
"defaultTitle": "Zpráva",
|
|
52
|
+
"imageAlt": "Obrázek pro operátora",
|
|
53
|
+
"htmlCodeTitle": "HTML kód",
|
|
54
|
+
"htmlLinkTitle": "HTML odkaz",
|
|
55
|
+
"enterAnswer": "Zadejte odpověď",
|
|
56
|
+
"fieldNotEmpty": "Pole nesmí být prázdné",
|
|
57
|
+
"notificationTitle": "Oznámení",
|
|
58
|
+
"notificationDesc": "Okno bylo uzavřeno. Testy byly zastaveny.",
|
|
59
|
+
"numericInputError": "Zadejte prosím číslo",
|
|
60
|
+
"radioButtonError": "Vyberte prosím jednu možnost",
|
|
61
|
+
"checkboxError": "Vyberte prosím alespoň jednu možnost"
|
|
62
|
+
},
|
|
63
|
+
"suiteList": {
|
|
64
|
+
"loadingTests": "Načítání testů... 🤔",
|
|
65
|
+
"refreshHint": "Zkuste aktualizovat stránku.",
|
|
66
|
+
"standName": "Název stanoviště",
|
|
67
|
+
"status": "Stav",
|
|
68
|
+
"startTime": "Čas zahájení",
|
|
69
|
+
"finishTime": "Čas dokončení",
|
|
70
|
+
"alert": "Upozornění"
|
|
71
|
+
},
|
|
72
|
+
"testSuite": {
|
|
73
|
+
"nameColumn": "Název",
|
|
74
|
+
"dataColumn": "Údaje",
|
|
75
|
+
"loading": "Načítám...",
|
|
76
|
+
"stubName": "Sada testů",
|
|
77
|
+
"runSelectedTests": "Spustit {{count}} vybrané testy",
|
|
78
|
+
"noTestsSelected": "Nebyly vybrány žádné testy",
|
|
79
|
+
"testsStarted": "Zahájené testy {{count}}",
|
|
80
|
+
"startError": "Chyba při spouštění testů",
|
|
81
|
+
"connectionError": "Chyba připojení",
|
|
82
|
+
"selectionColumn": "Vybrat",
|
|
83
|
+
"skipped": "Přeskočeno"
|
|
84
|
+
}
|
|
85
|
+
}
|
|
@@ -15,6 +15,9 @@
|
|
|
15
15
|
"failedTestCases": "Fehlgeschlagene Testfälle",
|
|
16
16
|
"modalResultDismissHint": "Klicken Sie irgendwo oder drücken Sie eine Taste, um zu schließen",
|
|
17
17
|
"modalResultAutoDismissHint": "Automatisches Schließen in {{seconds}} Sekunden...",
|
|
18
|
+
"manualCollectOn": "Manuelle Sammlung ein",
|
|
19
|
+
"manualCollectOff": "Manuelle Sammlung aus",
|
|
20
|
+
"testConfigurationSelector": "Testkonfiguration auswählen",
|
|
18
21
|
"status": {
|
|
19
22
|
"ready": "Bereit",
|
|
20
23
|
"run": "Läuft",
|
|
@@ -70,6 +73,13 @@
|
|
|
70
73
|
"nameColumn": "Name",
|
|
71
74
|
"dataColumn": "Daten",
|
|
72
75
|
"loading": "Wird geladen...",
|
|
73
|
-
"stubName": "Testgruppe"
|
|
76
|
+
"stubName": "Testgruppe",
|
|
77
|
+
"runSelectedTests": "{{count}} ausgewählte Tests ausführen",
|
|
78
|
+
"noTestsSelected": "Keine Tests ausgewählt",
|
|
79
|
+
"testsStarted": "{{count}} Tests gestartet",
|
|
80
|
+
"startError": "Fehler beim Starten der Tests",
|
|
81
|
+
"connectionError": "Verbindungsfehler",
|
|
82
|
+
"selectionColumn": "Auswählen",
|
|
83
|
+
"skipped": "Übersprungen"
|
|
74
84
|
}
|
|
75
85
|
}
|
|
@@ -15,6 +15,9 @@
|
|
|
15
15
|
"failedTestCases": "Failed Test Cases",
|
|
16
16
|
"modalResultDismissHint": "Click anywhere or press any key to dismiss",
|
|
17
17
|
"modalResultAutoDismissHint": "Auto-dismissing in {{seconds}} seconds...",
|
|
18
|
+
"manualCollectOn": "Manual collect on",
|
|
19
|
+
"manualCollectOff": "Manual collect off",
|
|
20
|
+
"testConfigurationSelector": "Select test configuration",
|
|
18
21
|
"status": {
|
|
19
22
|
"ready": "Ready",
|
|
20
23
|
"run": "Run",
|
|
@@ -70,6 +73,13 @@
|
|
|
70
73
|
"nameColumn": "Name",
|
|
71
74
|
"dataColumn": "Data",
|
|
72
75
|
"loading": "Loading...",
|
|
73
|
-
"stubName": "Test Suite"
|
|
76
|
+
"stubName": "Test Suite",
|
|
77
|
+
"runSelectedTests": "Run {{count}} selected tests",
|
|
78
|
+
"noTestsSelected": "No tests selected",
|
|
79
|
+
"testsStarted": "Started {{count}} tests",
|
|
80
|
+
"startError": "Error starting tests",
|
|
81
|
+
"connectionError": "Connection error",
|
|
82
|
+
"selectionColumn": "Select",
|
|
83
|
+
"skipped": "Skipped"
|
|
74
84
|
}
|
|
75
85
|
}
|
|
@@ -15,6 +15,9 @@
|
|
|
15
15
|
"failedTestCases": "Casos de prueba fallidos",
|
|
16
16
|
"modalResultDismissHint": "Haga clic en cualquier lugar o presione cualquier tecla para cerrar",
|
|
17
17
|
"modalResultAutoDismissHint": "Cierre automático en {{seconds}} segundos...",
|
|
18
|
+
"manualCollectOn": "Recolección manual activada",
|
|
19
|
+
"manualCollectOff": "Recolección manual desactivada",
|
|
20
|
+
"testConfigurationSelector": "Seleccionar configuración de prueba",
|
|
18
21
|
"status": {
|
|
19
22
|
"ready": "Listo",
|
|
20
23
|
"run": "Ejecutando",
|
|
@@ -70,6 +73,13 @@
|
|
|
70
73
|
"nameColumn": "Nombre",
|
|
71
74
|
"dataColumn": "Datos",
|
|
72
75
|
"loading": "Cargando...",
|
|
73
|
-
"stubName": "Conjunto de pruebas"
|
|
76
|
+
"stubName": "Conjunto de pruebas",
|
|
77
|
+
"runSelectedTests": "Ejecutar {{count}} pruebas seleccionadas",
|
|
78
|
+
"noTestsSelected": "No hay pruebas seleccionadas",
|
|
79
|
+
"testsStarted": "{{count}} pruebas iniciadas",
|
|
80
|
+
"startError": "Error al iniciar las pruebas",
|
|
81
|
+
"connectionError": "Error de conexión",
|
|
82
|
+
"selectionColumn": "Seleccionar",
|
|
83
|
+
"skipped": "Omitido"
|
|
74
84
|
}
|
|
75
85
|
}
|
|
@@ -15,6 +15,9 @@
|
|
|
15
15
|
"failedTestCases": "Cas de test échoués",
|
|
16
16
|
"modalResultDismissHint": "Cliquez n'importe où ou appuyez sur n'importe quelle touche pour fermer",
|
|
17
17
|
"modalResultAutoDismissHint": "Fermeture automatique dans {{seconds}} secondes...",
|
|
18
|
+
"manualCollectOn": "Collecte manuelle activée",
|
|
19
|
+
"manualCollectOff": "Collecte manuelle désactivée",
|
|
20
|
+
"testConfigurationSelector": "Sélectionner la configuration de test",
|
|
18
21
|
"status": {
|
|
19
22
|
"ready": "Prêt",
|
|
20
23
|
"run": "En cours",
|
|
@@ -70,6 +73,13 @@
|
|
|
70
73
|
"nameColumn": "Nom",
|
|
71
74
|
"dataColumn": "Données",
|
|
72
75
|
"loading": "Chargement...",
|
|
73
|
-
"stubName": "Suite de tests"
|
|
76
|
+
"stubName": "Suite de tests",
|
|
77
|
+
"runSelectedTests": "Exécuter {{count}} tests sélectionnés",
|
|
78
|
+
"noTestsSelected": "Aucun test sélectionné",
|
|
79
|
+
"testsStarted": "{{count}} tests démarrés",
|
|
80
|
+
"startError": "Erreur de démarrage des tests",
|
|
81
|
+
"connectionError": "Erreur de connexion",
|
|
82
|
+
"selectionColumn": "Sélectionner",
|
|
83
|
+
"skipped": "Ignoré"
|
|
74
84
|
}
|
|
75
85
|
}
|
|
@@ -15,6 +15,9 @@
|
|
|
15
15
|
"failedTestCases": "失敗したテストケース",
|
|
16
16
|
"modalResultDismissHint": "どこかをクリックするか、任意のキーを押して閉じます",
|
|
17
17
|
"modalResultAutoDismissHint": "{{seconds}}秒後に自動的に閉じます...",
|
|
18
|
+
"manualCollectOn": "手動収集オン",
|
|
19
|
+
"manualCollectOff": "手動収集オフ",
|
|
20
|
+
"testConfigurationSelector": "テスト構成を選択する",
|
|
18
21
|
"status": {
|
|
19
22
|
"ready": "準備完了",
|
|
20
23
|
"run": "実行中",
|
|
@@ -70,6 +73,13 @@
|
|
|
70
73
|
"nameColumn": "名前",
|
|
71
74
|
"dataColumn": "データ",
|
|
72
75
|
"loading": "読み込み中...",
|
|
73
|
-
"stubName": "テストスイート"
|
|
76
|
+
"stubName": "テストスイート",
|
|
77
|
+
"runSelectedTests": "選択した{{count}}個のテストを実行",
|
|
78
|
+
"noTestsSelected": "テストが選択されていません",
|
|
79
|
+
"testsStarted": "{{count}}個のテストを開始しました",
|
|
80
|
+
"startError": "テストの開始エラー",
|
|
81
|
+
"connectionError": "接続エラー",
|
|
82
|
+
"selectionColumn": "選択",
|
|
83
|
+
"skipped": "スキップ済み"
|
|
74
84
|
}
|
|
75
85
|
}
|
|
@@ -15,6 +15,9 @@
|
|
|
15
15
|
"failedTestCases": "Проваленные тестовые случаи",
|
|
16
16
|
"modalResultDismissHint": "Нажмите на любое место на экране или нажмите любую клавишу для закрытия",
|
|
17
17
|
"modalResultAutoDismissHint": "Автоматическое закрытие через {{seconds}} секунд...",
|
|
18
|
+
"manualCollectOn": "Ручной сбор включен",
|
|
19
|
+
"manualCollectOff": "Ручной сбор выключен",
|
|
20
|
+
"testConfigurationSelector": "Выберите конфигурацию теста",
|
|
18
21
|
"status": {
|
|
19
22
|
"ready": "Готов",
|
|
20
23
|
"run": "Выполнение",
|
|
@@ -70,6 +73,13 @@
|
|
|
70
73
|
"nameColumn": "Название",
|
|
71
74
|
"dataColumn": "Данные",
|
|
72
75
|
"loading": "Загрузка...",
|
|
73
|
-
"stubName": "Тестовый набор"
|
|
76
|
+
"stubName": "Тестовый набор",
|
|
77
|
+
"runSelectedTests": "Запустить {{count}} выбранных тестов",
|
|
78
|
+
"noTestsSelected": "Тесты не выбраны",
|
|
79
|
+
"testsStarted": "Запущено {{count}} тестов",
|
|
80
|
+
"startError": "Ошибка запуска тестов",
|
|
81
|
+
"connectionError": "Ошибка соединения",
|
|
82
|
+
"selectionColumn": "Выбрать",
|
|
83
|
+
"skipped": "Пропущен"
|
|
74
84
|
}
|
|
75
85
|
}
|
|
@@ -15,6 +15,9 @@
|
|
|
15
15
|
"failedTestCases": "失败的测试用例",
|
|
16
16
|
"modalResultDismissHint": "点击任意位置或按任意键关闭",
|
|
17
17
|
"modalResultAutoDismissHint": "{{seconds}}秒后自动关闭...",
|
|
18
|
+
"manualCollectOn": "手动收集开启",
|
|
19
|
+
"manualCollectOff": "手动收集关闭",
|
|
20
|
+
"testConfigurationSelector": "选择测试配置",
|
|
18
21
|
"status": {
|
|
19
22
|
"ready": "就绪",
|
|
20
23
|
"run": "运行中",
|
|
@@ -70,6 +73,13 @@
|
|
|
70
73
|
"nameColumn": "名称",
|
|
71
74
|
"dataColumn": "数据",
|
|
72
75
|
"loading": "加载中...",
|
|
73
|
-
"stubName": "测试套件"
|
|
76
|
+
"stubName": "测试套件",
|
|
77
|
+
"runSelectedTests": "运行 {{count}} 个选中的测试",
|
|
78
|
+
"noTestsSelected": "未选择任何测试",
|
|
79
|
+
"testsStarted": "已启动 {{count}} 个测试",
|
|
80
|
+
"startError": "启动测试时出错",
|
|
81
|
+
"connectionError": "连接错误",
|
|
82
|
+
"selectionColumn": "选择",
|
|
83
|
+
"skipped": "已跳过"
|
|
74
84
|
}
|
|
75
85
|
}
|
hardpy/pytest_hardpy/plugin.py
CHANGED
|
@@ -205,6 +205,7 @@ class HardpyPlugin:
|
|
|
205
205
|
status = self._get_run_status(exitstatus)
|
|
206
206
|
if status == TestStatus.STOPPED:
|
|
207
207
|
self._stop_tests()
|
|
208
|
+
self._validate_stop_time()
|
|
208
209
|
self._reporter.finish(status)
|
|
209
210
|
self._reporter.update_db_by_doc()
|
|
210
211
|
self._reporter.compact_all()
|
|
@@ -483,6 +484,29 @@ class HardpyPlugin:
|
|
|
483
484
|
case _:
|
|
484
485
|
return TestStatus.FAILED
|
|
485
486
|
|
|
487
|
+
def _validate_stop_time(self) -> None:
|
|
488
|
+
"""Update module and case stop times if they are not set.
|
|
489
|
+
|
|
490
|
+
If module start time is set but module stop time is not set,
|
|
491
|
+
set module stop time to module start time.
|
|
492
|
+
If case start time is set but case stop time is not set, set
|
|
493
|
+
case stop time to case start time.
|
|
494
|
+
"""
|
|
495
|
+
for module_id, module_data in self._results.items():
|
|
496
|
+
module_start_time = self._reporter.get_module_start_time(module_id)
|
|
497
|
+
module_stop_time = self._reporter.get_module_stop_time(module_id)
|
|
498
|
+
if module_start_time and not module_stop_time:
|
|
499
|
+
self._reporter.set_module_stop_time(module_start_time)
|
|
500
|
+
for module_data_key in module_data:
|
|
501
|
+
# skip module status
|
|
502
|
+
if module_data_key == "module_status":
|
|
503
|
+
continue
|
|
504
|
+
case_id = module_data_key
|
|
505
|
+
case_start_time = self._reporter.get_case_start_time(module_id, case_id)
|
|
506
|
+
case_stop_time = self._reporter.get_case_stop_time(module_id, case_id)
|
|
507
|
+
if case_start_time and not case_stop_time:
|
|
508
|
+
self._reporter.set_case_stop_time(case_start_time)
|
|
509
|
+
|
|
486
510
|
def _stop_tests(self) -> None:
|
|
487
511
|
"""Update module and case statuses to stopped and skipped."""
|
|
488
512
|
is_module_stopped = False
|
|
@@ -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
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
+
import logging
|
|
5
6
|
import signal
|
|
6
7
|
import subprocess
|
|
7
8
|
import sys
|
|
@@ -11,6 +12,9 @@ from hardpy.common.config import ConfigManager
|
|
|
11
12
|
from hardpy.pytest_hardpy.db import DatabaseField as DF # noqa: N817
|
|
12
13
|
from hardpy.pytest_hardpy.reporter import RunnerReporter
|
|
13
14
|
|
|
15
|
+
logging.basicConfig(level=logging.INFO)
|
|
16
|
+
logger = logging.getLogger(__name__)
|
|
17
|
+
|
|
14
18
|
|
|
15
19
|
class PyTestWrapper:
|
|
16
20
|
"""Wrapper for pytest subprocess."""
|
|
@@ -24,11 +28,35 @@ class PyTestWrapper:
|
|
|
24
28
|
# before clients come in
|
|
25
29
|
self._config_manager = ConfigManager()
|
|
26
30
|
self.config = self._config_manager.config
|
|
27
|
-
self.collect(is_clear_database=True)
|
|
28
31
|
|
|
29
|
-
|
|
32
|
+
# Check to see if there are any test configs defined in the TOML file
|
|
33
|
+
if not self.config.test_configs:
|
|
34
|
+
self.collect(is_clear_database=True)
|
|
35
|
+
else:
|
|
36
|
+
self._reporter.clear_database()
|
|
37
|
+
# Check if there's a current test config selected in statestore
|
|
38
|
+
config_name = self.config.current_test_config
|
|
39
|
+
if config_name:
|
|
40
|
+
try:
|
|
41
|
+
self.collect(is_clear_database=True)
|
|
42
|
+
except Exception:
|
|
43
|
+
# No existing test configs in statestore, will be initialized later
|
|
44
|
+
msg = "Error retrieving current test config from statestore."
|
|
45
|
+
logger.exception(msg)
|
|
46
|
+
else:
|
|
47
|
+
logger.info("No existing test config selection found.")
|
|
48
|
+
|
|
49
|
+
def start(
|
|
50
|
+
self,
|
|
51
|
+
start_args: dict | None = None,
|
|
52
|
+
selected_tests: list[str] | None = None,
|
|
53
|
+
) -> bool:
|
|
30
54
|
"""Start pytest subprocess.
|
|
31
55
|
|
|
56
|
+
Args:
|
|
57
|
+
start_args: Additional start arguments
|
|
58
|
+
selected_tests: List of selected tests
|
|
59
|
+
|
|
32
60
|
Returns:
|
|
33
61
|
bool: True if pytest was started
|
|
34
62
|
"""
|
|
@@ -45,15 +73,23 @@ class PyTestWrapper:
|
|
|
45
73
|
"--hardpy-db-url",
|
|
46
74
|
self.config.database.url,
|
|
47
75
|
"--hardpy-tests-name",
|
|
48
|
-
self.
|
|
76
|
+
self._tests_name(),
|
|
49
77
|
"--sc-address",
|
|
50
78
|
self.config.stand_cloud.address,
|
|
51
79
|
]
|
|
80
|
+
|
|
81
|
+
if selected_tests:
|
|
82
|
+
selected_test_cases = self._select_test_cases(selected_tests)
|
|
83
|
+
cmd.extend(selected_test_cases)
|
|
84
|
+
|
|
85
|
+
self._add_config_file(cmd)
|
|
86
|
+
|
|
52
87
|
if self.config.stand_cloud.connection_only:
|
|
53
88
|
cmd.append("--sc-connection-only")
|
|
54
89
|
if self.config.stand_cloud.autosync:
|
|
55
90
|
cmd.append("--sc-autosync")
|
|
56
91
|
cmd.append("--hardpy-pt")
|
|
92
|
+
|
|
57
93
|
if start_args:
|
|
58
94
|
for key, value in start_args.items():
|
|
59
95
|
arg_str = f"{key}={value}"
|
|
@@ -87,12 +123,18 @@ class PyTestWrapper:
|
|
|
87
123
|
return True
|
|
88
124
|
return False
|
|
89
125
|
|
|
90
|
-
def collect(
|
|
126
|
+
def collect(
|
|
127
|
+
self,
|
|
128
|
+
*,
|
|
129
|
+
is_clear_database: bool = False,
|
|
130
|
+
selected_tests: list[str] | None = None,
|
|
131
|
+
) -> bool:
|
|
91
132
|
"""Perform pytest collection.
|
|
92
133
|
|
|
93
134
|
Args:
|
|
94
135
|
is_clear_database (bool): indicates whether database
|
|
95
136
|
should be cleared. Defaults to False.
|
|
137
|
+
selected_tests (list[str]): list of selected tests
|
|
96
138
|
|
|
97
139
|
Returns:
|
|
98
140
|
bool: True if collection was started
|
|
@@ -110,13 +152,19 @@ class PyTestWrapper:
|
|
|
110
152
|
"--hardpy-db-url",
|
|
111
153
|
self.config.database.url,
|
|
112
154
|
"--hardpy-tests-name",
|
|
113
|
-
self.
|
|
155
|
+
self._tests_name(),
|
|
114
156
|
"--hardpy-pt",
|
|
115
157
|
]
|
|
116
158
|
|
|
117
159
|
if is_clear_database:
|
|
118
160
|
args.append("--hardpy-clear-database")
|
|
119
161
|
|
|
162
|
+
self._add_config_file(args)
|
|
163
|
+
|
|
164
|
+
if selected_tests:
|
|
165
|
+
selected_test_cases = self._select_test_cases(selected_tests)
|
|
166
|
+
args.extend(selected_test_cases)
|
|
167
|
+
|
|
120
168
|
subprocess.Popen( # noqa: S603
|
|
121
169
|
[self.python_executable, *args],
|
|
122
170
|
cwd=self._config_manager.tests_path,
|
|
@@ -158,3 +206,41 @@ class PyTestWrapper:
|
|
|
158
206
|
"""
|
|
159
207
|
config_manager = ConfigManager()
|
|
160
208
|
return config_manager.config.model_dump()
|
|
209
|
+
|
|
210
|
+
def _tests_name(self) -> str:
|
|
211
|
+
manual_str = ""
|
|
212
|
+
if self.config.frontend.manual_collect:
|
|
213
|
+
manual_str = " Manual mode"
|
|
214
|
+
|
|
215
|
+
tests_name = (
|
|
216
|
+
self.config.tests_name + f" {self.config.current_test_config}"
|
|
217
|
+
if self.config.current_test_config
|
|
218
|
+
else self.config.tests_name
|
|
219
|
+
)
|
|
220
|
+
return tests_name + manual_str
|
|
221
|
+
|
|
222
|
+
def _add_config_file(self, cmd: list) -> None:
|
|
223
|
+
"""Add test configuration file if specified."""
|
|
224
|
+
config_name = self.config.current_test_config
|
|
225
|
+
test_config_file = None
|
|
226
|
+
|
|
227
|
+
if self.config.test_configs:
|
|
228
|
+
for config in self.config.test_configs:
|
|
229
|
+
if config.name == config_name:
|
|
230
|
+
test_config_file = config.file
|
|
231
|
+
break
|
|
232
|
+
|
|
233
|
+
if test_config_file:
|
|
234
|
+
logging.info(f"Using test configuration file: {test_config_file}")
|
|
235
|
+
cmd.extend(["--config-file", test_config_file])
|
|
236
|
+
|
|
237
|
+
def _select_test_cases(self, selected_tests: list[str]) -> list[str]:
|
|
238
|
+
test_cases = []
|
|
239
|
+
for test_path in selected_tests:
|
|
240
|
+
if "::" in test_path:
|
|
241
|
+
module_name, case_name = test_path.split("::", 1)
|
|
242
|
+
case_path = f"{module_name}.py::{case_name}"
|
|
243
|
+
test_cases.append(case_path)
|
|
244
|
+
else:
|
|
245
|
+
test_cases.append(f"{test_path}.py")
|
|
246
|
+
return test_cases
|
|
@@ -20,8 +20,7 @@ class HookReporter(BaseReporter):
|
|
|
20
20
|
def __init__(self, is_clear_database: bool = False) -> None:
|
|
21
21
|
super().__init__()
|
|
22
22
|
if is_clear_database:
|
|
23
|
-
self.
|
|
24
|
-
self._runstore.clear()
|
|
23
|
+
self.clear_database()
|
|
25
24
|
self._log = getLogger(__name__)
|
|
26
25
|
|
|
27
26
|
def init_doc(self, doc_name: str) -> None:
|
|
@@ -232,6 +231,15 @@ class HookReporter(BaseReporter):
|
|
|
232
231
|
key = self.generate_key(DF.MODULES, module_id, DF.START_TIME)
|
|
233
232
|
return self._statestore.get_field(key)
|
|
234
233
|
|
|
234
|
+
def get_module_stop_time(self, module_id: str) -> int:
|
|
235
|
+
"""Get module stop time.
|
|
236
|
+
|
|
237
|
+
Returns:
|
|
238
|
+
int: module time
|
|
239
|
+
"""
|
|
240
|
+
key = self.generate_key(DF.MODULES, module_id, DF.STOP_TIME)
|
|
241
|
+
return self._statestore.get_field(key)
|
|
242
|
+
|
|
235
243
|
def get_case_start_time(self, module_id: str, case_id: str) -> int:
|
|
236
244
|
"""Get case start time.
|
|
237
245
|
|
|
@@ -241,6 +249,15 @@ class HookReporter(BaseReporter):
|
|
|
241
249
|
key = self.generate_key(DF.MODULES, module_id, DF.CASES, case_id, DF.START_TIME)
|
|
242
250
|
return self._statestore.get_field(key)
|
|
243
251
|
|
|
252
|
+
def get_case_stop_time(self, module_id: str, case_id: str) -> int:
|
|
253
|
+
"""Get case stop time.
|
|
254
|
+
|
|
255
|
+
Returns:
|
|
256
|
+
int: module time
|
|
257
|
+
"""
|
|
258
|
+
key = self.generate_key(DF.MODULES, module_id, DF.CASES, case_id, DF.STOP_TIME)
|
|
259
|
+
return self._statestore.get_field(key)
|
|
260
|
+
|
|
244
261
|
def set_caused_dut_failure_id(self, module_id: str, case_id: str) -> None:
|
|
245
262
|
"""Set caused DUT failure id.
|
|
246
263
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: hardpy
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.19.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/
|
|
@@ -69,6 +69,7 @@ HardPy is a python library for creating a test bench for devices.
|
|
|
69
69
|
[](https://docs.pytest.org/en/latest/)
|
|
70
70
|
[](https://everypinio.github.io/hardpy/)
|
|
71
71
|
[](https://www.reddit.com/r/HardPy)
|
|
72
|
+
[]()
|
|
72
73
|
[](https://t.me/everypin)
|
|
73
74
|
|
|
74
75
|
</div>
|
|
@@ -3,7 +3,7 @@ hardpy/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
|
3
3
|
hardpy/cli/cli.py,sha256=eg89XAcPSosykXyeWitcTigE-ZYiDeCknPWp9TpXxeA,11359
|
|
4
4
|
hardpy/cli/template.py,sha256=kOl8hsj6iBTFIDUli_dzHkH8mlnoJzOlr9muLpTEayg,6230
|
|
5
5
|
hardpy/common/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
6
|
-
hardpy/common/config.py,sha256=
|
|
6
|
+
hardpy/common/config.py,sha256=cgs4rGgRbKsDasM1NupmdERK2XaHZin3lLn346WRnKk,7730
|
|
7
7
|
hardpy/common/singleton.py,sha256=RVMqbluN-mhlJ4QOYcRzQLA68Hs8t83XNyihyUwhYGo,948
|
|
8
8
|
hardpy/common/stand_cloud/__init__.py,sha256=fezdiYAehtT2H-GAef-xZU12CbmCRe64XHA9UB3kJDU,456
|
|
9
9
|
hardpy/common/stand_cloud/connector.py,sha256=PD1Gr1QOuFUmCsnlPY2zb_WF9Nrr8BGTlbRC2_LTKFE,8147
|
|
@@ -13,14 +13,14 @@ hardpy/common/stand_cloud/registration.py,sha256=UW-JGcvON5CMQQ-s2Mb4Ee3u_jmdQfS
|
|
|
13
13
|
hardpy/common/stand_cloud/token_manager.py,sha256=oHLDip0a-0mmAiRQN5IuypTSNyOnSB43TSWlprOLRI0,4843
|
|
14
14
|
hardpy/common/stand_cloud/utils.py,sha256=GN3wzbrmF-Xe5iUXf_HurGO-YKltqd3Gc_7vG2eEL7c,692
|
|
15
15
|
hardpy/hardpy_panel/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
16
|
-
hardpy/hardpy_panel/api.py,sha256=
|
|
16
|
+
hardpy/hardpy_panel/api.py,sha256=F4wSHiE5kiFvthR_TdrcmXSbfq-gP00uZKC0Pnoyq-4,10744
|
|
17
17
|
hardpy/hardpy_panel/frontend/dist/favicon.ico,sha256=sgIk5PKUKEKBDpkSrc8dJgjpObp0iF82Mec0GpfKId4,15406
|
|
18
|
-
hardpy/hardpy_panel/frontend/dist/index.html,sha256=
|
|
18
|
+
hardpy/hardpy_panel/frontend/dist/index.html,sha256=Hhb9wXuzSNSaG5KgX_63fvg0XEzwkp80jc-g-uobwqQ,1851
|
|
19
19
|
hardpy/hardpy_panel/frontend/dist/logo192.png,sha256=E4K7drvhJCg9HcTpRihOXZhVJVBZ7-W97Se-3tDb46o,14485
|
|
20
20
|
hardpy/hardpy_panel/frontend/dist/logo512.png,sha256=-fIMbqX7PYUpheK4kX1C1erRTe_hHZwFQYDLrAbhFRU,34188
|
|
21
21
|
hardpy/hardpy_panel/frontend/dist/manifest.json,sha256=PfmJlN2JMJtHS6OnhU4b4X5wPQC_yRBdjesjoirObSA,502
|
|
22
|
-
hardpy/hardpy_panel/frontend/dist/assets/allPaths-
|
|
23
|
-
hardpy/hardpy_panel/frontend/dist/assets/allPathsLoader-
|
|
22
|
+
hardpy/hardpy_panel/frontend/dist/assets/allPaths-C_-7WXHD.js,sha256=g19yyAeijLh7WccMXT8_tuk1S-uWTOyPFzWHpyUZLQc,309
|
|
23
|
+
hardpy/hardpy_panel/frontend/dist/assets/allPathsLoader-DgH0Xily.js,sha256=CRNnNN2zycYIwYtzHnBbPj5EbtZSGVhLGfvbOswm4SM,550
|
|
24
24
|
hardpy/hardpy_panel/frontend/dist/assets/blueprint-icons-16-B2twAPZE.ttf,sha256=OcrUHPBAaLvJxb2DOethXFXg8PClDcyvpsh0mToLFPM,136248
|
|
25
25
|
hardpy/hardpy_panel/frontend/dist/assets/blueprint-icons-16-C0Unyq1d.eot,sha256=Bl93LjY8pyBj0Iip1lUxMM-0l1zLrRjoGmKPPnAQIgw,136456
|
|
26
26
|
hardpy/hardpy_panel/frontend/dist/assets/blueprint-icons-16-CVy9qFng.svg,sha256=57jlcc-NFRVJNJ3t-1fOnJvgdbYhcrF5a06LJLhWc5A,601027
|
|
@@ -31,24 +31,25 @@ hardpy/hardpy_panel/frontend/dist/assets/blueprint-icons-20-CjKGIKxE.woff,sha256
|
|
|
31
31
|
hardpy/hardpy_panel/frontend/dist/assets/blueprint-icons-20-DQ09GSQq.svg,sha256=3gLRYNxd_Y4iz6pspH4Bf7Ql4F6LH5haZzbTfxA53HQ,638634
|
|
32
32
|
hardpy/hardpy_panel/frontend/dist/assets/blueprint-icons-20-DmR755bS.ttf,sha256=yr5g5Jw9ZnxJJ7e1quOv977VE3NU2GRB60BMRrOJrcI,139424
|
|
33
33
|
hardpy/hardpy_panel/frontend/dist/assets/blueprint-icons-20-p9MhBXD8.eot,sha256=CFx8t8ONhB4INIrK860N56_t1dmS7FuRF7i0HKKo58k,139632
|
|
34
|
-
hardpy/hardpy_panel/frontend/dist/assets/browser-ponyfill-
|
|
34
|
+
hardpy/hardpy_panel/frontend/dist/assets/browser-ponyfill-BbOvdqIF.js,sha256=ga4pi7C6UzfwyVTi8QiAL0rpgvlXPi37PXqlLP8A-Ug,10294
|
|
35
35
|
hardpy/hardpy_panel/frontend/dist/assets/index-B-fsa5Ru.js,sha256=IonL7d7ppdDr-_FRJZQPWI4HHFTiygYvZGVlUxHY9R8,294235
|
|
36
36
|
hardpy/hardpy_panel/frontend/dist/assets/index-B7T9xvaW.css,sha256=5m7QXWbthqi_Va8qlvnTZeuRzSN_ZJUdhyeb3JD6ZME,315862
|
|
37
|
-
hardpy/hardpy_panel/frontend/dist/assets/index-
|
|
37
|
+
hardpy/hardpy_panel/frontend/dist/assets/index-DEJb2W0B.js,sha256=TVKRBm2PplF8vsQM_bEiA7VNhUKZHMDpD5Il33haQ40,6026022
|
|
38
38
|
hardpy/hardpy_panel/frontend/dist/assets/index-DLOviMB1.js,sha256=sI0W1vvwqvIwKP2_jglrwOhej3n5rJD72-d4ZhlUHqM,285612
|
|
39
39
|
hardpy/hardpy_panel/frontend/dist/assets/logo_smol-CK3jE85c.png,sha256=E4K7drvhJCg9HcTpRihOXZhVJVBZ7-W97Se-3tDb46o,14485
|
|
40
|
-
hardpy/hardpy_panel/frontend/dist/assets/splitPathsBySizeLoader-
|
|
41
|
-
hardpy/hardpy_panel/frontend/dist/locales/
|
|
42
|
-
hardpy/hardpy_panel/frontend/dist/locales/
|
|
43
|
-
hardpy/hardpy_panel/frontend/dist/locales/
|
|
44
|
-
hardpy/hardpy_panel/frontend/dist/locales/
|
|
45
|
-
hardpy/hardpy_panel/frontend/dist/locales/
|
|
46
|
-
hardpy/hardpy_panel/frontend/dist/locales/
|
|
47
|
-
hardpy/hardpy_panel/frontend/dist/locales/
|
|
40
|
+
hardpy/hardpy_panel/frontend/dist/assets/splitPathsBySizeLoader-o5HCcdVL.js,sha256=ZvdGFd8j0qHvEPUqfpcCFtwRg2ptF-uPZCoJMUUK2Ac,472
|
|
41
|
+
hardpy/hardpy_panel/frontend/dist/locales/cs/translation.json,sha256=kCSbBWfQQ6lrVKlOeByXAhAoG5bBxrxf7-PTvvQgR2M,2964
|
|
42
|
+
hardpy/hardpy_panel/frontend/dist/locales/de/translation.json,sha256=wZRO5iz8VvaEjACSWHJNjjKerd8YcPo7gpziCpjfF1Q,3073
|
|
43
|
+
hardpy/hardpy_panel/frontend/dist/locales/en/translation.json,sha256=_vsAG4aOto5C-xiCQK0zip02u6f9wHr-T_BRr_DUdTo,2776
|
|
44
|
+
hardpy/hardpy_panel/frontend/dist/locales/es/translation.json,sha256=vkXYntVaRnl-aEZZpPFlQE7qJXC2rAuDvbAcXMwQ9V8,3154
|
|
45
|
+
hardpy/hardpy_panel/frontend/dist/locales/fr/translation.json,sha256=eZuiKx9s1Nz3E9xJ6o7HwRbofQzdOxF6WL9gzu8iMYs,3160
|
|
46
|
+
hardpy/hardpy_panel/frontend/dist/locales/ja/translation.json,sha256=4_MrBUHCneXgvGuWexs0a_viOxcEt40CWCKCgLHQHgU,3378
|
|
47
|
+
hardpy/hardpy_panel/frontend/dist/locales/ru/translation.json,sha256=LvJavIT8_HdrIMIvgGtRBoGOCs3DeBNyYg0BHALwmEg,4097
|
|
48
|
+
hardpy/hardpy_panel/frontend/dist/locales/zh/translation.json,sha256=ZmoqrndiAtatXSVDpz6looKb_2U_XnJdIidfK9o-uXY,2781
|
|
48
49
|
hardpy/pytest_hardpy/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
49
|
-
hardpy/pytest_hardpy/plugin.py,sha256=
|
|
50
|
+
hardpy/pytest_hardpy/plugin.py,sha256=m8vbDAA_cuxOlraJ2V_DvQ81E_06zJaTLF771nLLQMI,24591
|
|
50
51
|
hardpy/pytest_hardpy/pytest_call.py,sha256=qUDrK1iUjhGEs4bmBFTk9E0YfFzsePoHhVDRY6ngRV8,22878
|
|
51
|
-
hardpy/pytest_hardpy/pytest_wrapper.py,sha256=
|
|
52
|
+
hardpy/pytest_hardpy/pytest_wrapper.py,sha256=TS-Ysm1ou-bkkc50A0tdJWXCNx51sB1EOkUUYxQ64GA,7737
|
|
52
53
|
hardpy/pytest_hardpy/db/__init__.py,sha256=nat_tUO2cxPIp9e6U8Fvg6V4NcZ9TVg27u0GHoKelD4,865
|
|
53
54
|
hardpy/pytest_hardpy/db/base_store.py,sha256=d1lkTB7CpHTKysD2yuuGQFai44OtOmtTbq-WaBYojhw,5545
|
|
54
55
|
hardpy/pytest_hardpy/db/const.py,sha256=E_A0IKGeS3qyPX4fTfUE5ksARsrTKSVWqUkdmh8S_fo,1414
|
|
@@ -59,8 +60,8 @@ hardpy/pytest_hardpy/db/tempstore.py,sha256=WKIykL_4A9j8n-F7pIy_9fj4BNOfzqWkUwg0
|
|
|
59
60
|
hardpy/pytest_hardpy/db/schema/__init__.py,sha256=1S73W3PLQt8gX5Y33nbX1JdwLvnrtlKH4cElID3pwuc,263
|
|
60
61
|
hardpy/pytest_hardpy/db/schema/v1.py,sha256=0RGZP-2lDeA3r8-simEEnjlHOAyziYSMXb9BINQyVbM,6377
|
|
61
62
|
hardpy/pytest_hardpy/reporter/__init__.py,sha256=rztpM2HlLUpMOvad0JHbZU4Mk8PDDQyCFXLhpLktGQI,322
|
|
62
|
-
hardpy/pytest_hardpy/reporter/base.py,sha256=
|
|
63
|
-
hardpy/pytest_hardpy/reporter/hook_reporter.py,sha256=
|
|
63
|
+
hardpy/pytest_hardpy/reporter/base.py,sha256=hUt0UTzZOa9KdHj66cOnqgDVakYh4GncE1YkCFqwCBs,3666
|
|
64
|
+
hardpy/pytest_hardpy/reporter/hook_reporter.py,sha256=Et312HLWQ-WUSjRSNa4Yg392HbRRbCNfzRQWvcCC11c,16199
|
|
64
65
|
hardpy/pytest_hardpy/reporter/runner_reporter.py,sha256=d9hyThq0tywelPnIIHVED2SyztavE5LbgcBSejXfnhA,787
|
|
65
66
|
hardpy/pytest_hardpy/result/__init__.py,sha256=2afpuEuOcxYfIEOwWzsGZe960iQaPVCmsbYujijQg1s,592
|
|
66
67
|
hardpy/pytest_hardpy/result/couchdb_config.py,sha256=ujxyJYM2pdZzi3GZ2Zysbz2_ZeTRN5sQc8AGuzRJm_0,3243
|
|
@@ -79,8 +80,8 @@ hardpy/pytest_hardpy/utils/exception.py,sha256=1l2VBZLUnjPDoOs744MtaP7Y9FuXUq7ko
|
|
|
79
80
|
hardpy/pytest_hardpy/utils/machineid.py,sha256=6JAzUt7KtjTYn8kL9hSMaCQ20U8liH-zDT9v-5Ch7Q8,296
|
|
80
81
|
hardpy/pytest_hardpy/utils/node_info.py,sha256=DaW566WvsyWR66CThuZ38UoHwQa-pu-4WRLg61OXDnE,7134
|
|
81
82
|
hardpy/pytest_hardpy/utils/progress_calculator.py,sha256=TPl2gG0ZSvMe8otPythhF9hkD6fa6-mJAhy9yI83-yE,1071
|
|
82
|
-
hardpy-0.
|
|
83
|
-
hardpy-0.
|
|
84
|
-
hardpy-0.
|
|
85
|
-
hardpy-0.
|
|
86
|
-
hardpy-0.
|
|
83
|
+
hardpy-0.19.1.dist-info/METADATA,sha256=nuj7JBfKBLgOYLW8ENRaflRnbGPZ0NesNnjjdKqGL7Y,5087
|
|
84
|
+
hardpy-0.19.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
85
|
+
hardpy-0.19.1.dist-info/entry_points.txt,sha256=nL2sMkKMScNaOE0IPkYnu9Yr-BUswZvGSrwY-SxHY3E,102
|
|
86
|
+
hardpy-0.19.1.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
|
|
87
|
+
hardpy-0.19.1.dist-info/RECORD,,
|