hardpy 0.15.2__py3-none-any.whl → 0.17.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/__init__.py +9 -6
- hardpy/cli/cli.py +16 -10
- hardpy/cli/template.py +5 -4
- hardpy/common/config.py +83 -50
- hardpy/{pytest_hardpy/utils → common}/singleton.py +1 -1
- hardpy/hardpy_panel/api.py +44 -13
- hardpy/hardpy_panel/frontend/dist/assets/{allPaths-CV5wjLMB.js → allPaths-COgYwK8M.js} +1 -1
- hardpy/hardpy_panel/frontend/dist/assets/{allPathsLoader-JIzW_pSb.js → allPathsLoader-B8vBKA-e.js} +2 -2
- hardpy/hardpy_panel/frontend/dist/assets/{blueprint-icons-16-Bfs1BwbR.ttf → blueprint-icons-16-B2twAPZE.ttf} +0 -0
- hardpy/hardpy_panel/frontend/dist/assets/{blueprint-icons-16-RCDSkC4W.eot → blueprint-icons-16-C0Unyq1d.eot} +0 -0
- hardpy/hardpy_panel/frontend/dist/assets/{blueprint-icons-16-CzsyEoPG.svg → blueprint-icons-16-CVy9qFng.svg} +249 -3
- hardpy/hardpy_panel/frontend/dist/assets/blueprint-icons-16-Ck1ifK4A.woff +0 -0
- hardpy/hardpy_panel/frontend/dist/assets/blueprint-icons-16-DwWyHYRo.woff2 +0 -0
- hardpy/hardpy_panel/frontend/dist/assets/blueprint-icons-20-9zitLjlL.woff2 +0 -0
- hardpy/hardpy_panel/frontend/dist/assets/blueprint-icons-20-CjKGIKxE.woff +0 -0
- hardpy/hardpy_panel/frontend/dist/assets/{blueprint-icons-20-DyVnGNfQ.svg → blueprint-icons-20-DQ09GSQq.svg} +249 -3
- hardpy/hardpy_panel/frontend/dist/assets/{blueprint-icons-20-BGGGsqDJ.ttf → blueprint-icons-20-DmR755bS.ttf} +0 -0
- hardpy/hardpy_panel/frontend/dist/assets/{blueprint-icons-20-Doom1bSH.eot → blueprint-icons-20-p9MhBXD8.eot} +0 -0
- hardpy/hardpy_panel/frontend/dist/assets/browser-ponyfill-CVrkrold.js +2 -0
- hardpy/hardpy_panel/frontend/dist/assets/index-B-fsa5Ru.js +1 -0
- hardpy/hardpy_panel/frontend/dist/assets/index-B3wEgxl0.js +4673 -0
- hardpy/hardpy_panel/frontend/dist/assets/index-B7T9xvaW.css +1 -0
- hardpy/hardpy_panel/frontend/dist/assets/index-DLOviMB1.js +1 -0
- hardpy/hardpy_panel/frontend/dist/assets/{splitPathsBySizeLoader-DkZadBcn.js → splitPathsBySizeLoader-CLCw9W9y.js} +1 -1
- hardpy/hardpy_panel/frontend/dist/index.html +2 -2
- hardpy/hardpy_panel/frontend/dist/locales/de/translation.json +22 -7
- hardpy/hardpy_panel/frontend/dist/locales/en/translation.json +22 -7
- hardpy/hardpy_panel/frontend/dist/locales/es/translation.json +22 -7
- hardpy/hardpy_panel/frontend/dist/locales/fr/translation.json +22 -7
- hardpy/hardpy_panel/frontend/dist/locales/ja/translation.json +16 -1
- hardpy/hardpy_panel/frontend/dist/locales/ru/translation.json +22 -7
- hardpy/hardpy_panel/frontend/dist/locales/zh/translation.json +16 -1
- hardpy/pytest_hardpy/db/__init__.py +12 -0
- hardpy/pytest_hardpy/db/base_store.py +31 -4
- hardpy/pytest_hardpy/db/runstore.py +1 -1
- hardpy/pytest_hardpy/db/schema/v1.py +8 -6
- hardpy/pytest_hardpy/db/statestore.py +1 -1
- hardpy/pytest_hardpy/plugin.py +38 -25
- hardpy/pytest_hardpy/pytest_call.py +74 -29
- hardpy/pytest_hardpy/pytest_wrapper.py +9 -7
- hardpy/pytest_hardpy/reporter/base.py +21 -1
- hardpy/pytest_hardpy/reporter/runner_reporter.py +1 -1
- hardpy/pytest_hardpy/result/report_loader/stand_cloud_loader.py +35 -4
- hardpy/pytest_hardpy/utils/__init__.py +0 -16
- hardpy/pytest_hardpy/utils/dialog_box.py +3 -0
- {hardpy-0.15.2.dist-info → hardpy-0.17.0.dist-info}/METADATA +17 -2
- hardpy-0.17.0.dist-info/RECORD +83 -0
- hardpy/hardpy_panel/frontend/dist/assets/blueprint-icons-16-Btb8d-Hu.woff +0 -0
- hardpy/hardpy_panel/frontend/dist/assets/blueprint-icons-16-DrH54W_x.woff2 +0 -0
- hardpy/hardpy_panel/frontend/dist/assets/blueprint-icons-20-D9WO2FSG.woff2 +0 -0
- hardpy/hardpy_panel/frontend/dist/assets/blueprint-icons-20-ZW-9JnPf.woff +0 -0
- hardpy/hardpy_panel/frontend/dist/assets/browser-ponyfill-CccdstaD.js +0 -2
- hardpy/hardpy_panel/frontend/dist/assets/index-6RIgWzcZ.js +0 -790
- hardpy/hardpy_panel/frontend/dist/assets/index-BMEat_ws.js +0 -1
- hardpy/hardpy_panel/frontend/dist/assets/index-BwCQzehg.css +0 -1
- hardpy/hardpy_panel/frontend/dist/assets/index-xb4M2ucX.js +0 -1
- hardpy/pytest_hardpy/db/base_connector.py +0 -31
- hardpy/pytest_hardpy/db/base_server.py +0 -14
- hardpy/pytest_hardpy/utils/connection_data.py +0 -13
- hardpy-0.15.2.dist-info/RECORD +0 -86
- /hardpy/pytest_hardpy/{utils → db}/stand_type.py +0 -0
- {hardpy-0.15.2.dist-info → hardpy-0.17.0.dist-info}/WHEEL +0 -0
- {hardpy-0.15.2.dist-info → hardpy-0.17.0.dist-info}/entry_points.txt +0 -0
- {hardpy-0.15.2.dist-info → hardpy-0.17.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-B3wEgxl0.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,8 +25,8 @@
|
|
|
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-
|
|
29
|
-
<link rel="stylesheet" crossorigin href="/assets/index-
|
|
28
|
+
<script type="module" crossorigin src="/assets/index-B3wEgxl0.js"></script>
|
|
29
|
+
<link rel="stylesheet" crossorigin href="/assets/index-B7T9xvaW.css">
|
|
30
30
|
</head>
|
|
31
31
|
<body>
|
|
32
32
|
<noscript>You need to enable JavaScript to run this app.</noscript>
|
|
@@ -11,24 +11,39 @@
|
|
|
11
11
|
"connection": "Verbindung wird hergestellt... 🧐🔎",
|
|
12
12
|
"dbError": "Datenbankverbindungsfehler. 🙅🏽♀️🚫",
|
|
13
13
|
"noEntries": "Keine Einträge in der Datenbank 🙅🏽♀️🚫",
|
|
14
|
+
"stoppedTestCase": "Angehaltener Testfall",
|
|
15
|
+
"failedTestCases": "Fehlgeschlagene Testfälle",
|
|
16
|
+
"modalResultDismissHint": "Klicken Sie irgendwo oder drücken Sie eine Taste, um zu schließen",
|
|
17
|
+
"modalResultAutoDismissHint": "Automatisches Schließen in {{seconds}} Sekunden...",
|
|
14
18
|
"status": {
|
|
15
|
-
"ready": "
|
|
16
|
-
"run": "
|
|
17
|
-
"passed": "
|
|
18
|
-
"failed": "
|
|
19
|
-
"stopped": "
|
|
20
|
-
"unknown": "
|
|
19
|
+
"ready": "Bereit",
|
|
20
|
+
"run": "Läuft",
|
|
21
|
+
"passed": "Bestanden",
|
|
22
|
+
"failed": "Fehlgeschlagen",
|
|
23
|
+
"stopped": "Gestoppt",
|
|
24
|
+
"unknown": "Unbekannt"
|
|
21
25
|
}
|
|
22
26
|
},
|
|
23
27
|
"button": {
|
|
24
28
|
"start": "Starten",
|
|
25
29
|
"stop": "Stoppen",
|
|
26
|
-
"confirm": "Bestätigen"
|
|
30
|
+
"confirm": "Bestätigen",
|
|
31
|
+
"pass": "Bestanden",
|
|
32
|
+
"fail": "Fehlgeschlagen"
|
|
27
33
|
},
|
|
28
34
|
"error": {
|
|
29
35
|
"dbConnectionTitle": "Datenbankverbindungsfehler",
|
|
30
36
|
"dbConnectionMessage": "Verbindung zur Datenbank konnte nicht hergestellt werden"
|
|
31
37
|
},
|
|
38
|
+
"chart": {
|
|
39
|
+
"dataChart": "Diagrammdaten",
|
|
40
|
+
"xAxis": "X-Achse",
|
|
41
|
+
"yAxis": "Y-Achse",
|
|
42
|
+
"chart": "Diagramm",
|
|
43
|
+
"showChart": "Diagramm anzeigen {{title}}",
|
|
44
|
+
"fullscreenButton": "Diagramm im Vollbildmodus öffnen",
|
|
45
|
+
"series": "Reihe {{number}}"
|
|
46
|
+
},
|
|
32
47
|
"operatorDialog": {
|
|
33
48
|
"defaultTitle": "Nachricht",
|
|
34
49
|
"imageAlt": "Operator-Nachrichtenbild",
|
|
@@ -11,24 +11,39 @@
|
|
|
11
11
|
"connection": "Establishing a connection... 🧐🔎",
|
|
12
12
|
"dbError": "Database connection error. 🙅🏽♀️🚫",
|
|
13
13
|
"noEntries": "No entries in the database 🙅🏽♀️🚫",
|
|
14
|
+
"stoppedTestCase": "Stopped Test Case",
|
|
15
|
+
"failedTestCases": "Failed Test Cases",
|
|
16
|
+
"modalResultDismissHint": "Click anywhere or press any key to dismiss",
|
|
17
|
+
"modalResultAutoDismissHint": "Auto-dismissing in {{seconds}} seconds...",
|
|
14
18
|
"status": {
|
|
15
|
-
"ready": "
|
|
16
|
-
"run": "
|
|
17
|
-
"passed": "
|
|
18
|
-
"failed": "
|
|
19
|
-
"stopped": "
|
|
20
|
-
"unknown": "
|
|
19
|
+
"ready": "Ready",
|
|
20
|
+
"run": "Run",
|
|
21
|
+
"passed": "Pass",
|
|
22
|
+
"failed": "Fail",
|
|
23
|
+
"stopped": "Stopped",
|
|
24
|
+
"unknown": "Unknown"
|
|
21
25
|
}
|
|
22
26
|
},
|
|
23
27
|
"button": {
|
|
24
28
|
"start": "Start",
|
|
25
29
|
"stop": "Stop",
|
|
26
|
-
"confirm": "Confirm"
|
|
30
|
+
"confirm": "Confirm",
|
|
31
|
+
"pass": "Pass",
|
|
32
|
+
"fail": "Fail"
|
|
27
33
|
},
|
|
28
34
|
"error": {
|
|
29
35
|
"dbConnectionTitle": "Database Connection Error",
|
|
30
36
|
"dbConnectionMessage": "Failed to establish connection with the database"
|
|
31
37
|
},
|
|
38
|
+
"chart": {
|
|
39
|
+
"dataChart": "Chart Data",
|
|
40
|
+
"xAxis": "X Axis",
|
|
41
|
+
"yAxis": "Y Axis",
|
|
42
|
+
"chart": "Chart",
|
|
43
|
+
"showChart": "Show chart {{title}}",
|
|
44
|
+
"fullscreenButton": "Open chart in full screen",
|
|
45
|
+
"series": "Series {{number}}"
|
|
46
|
+
},
|
|
32
47
|
"operatorDialog": {
|
|
33
48
|
"defaultTitle": "Message",
|
|
34
49
|
"imageAlt": "Operator message image",
|
|
@@ -11,24 +11,39 @@
|
|
|
11
11
|
"connection": "Estableciendo conexión... 🧐🔎",
|
|
12
12
|
"dbError": "Error de conexión a la base de datos. 🙅🏽♀️🚫",
|
|
13
13
|
"noEntries": "No hay entradas en la base de datos 🙅🏽♀️🚫",
|
|
14
|
+
"stoppedTestCase": "Caso de prueba detenido",
|
|
15
|
+
"failedTestCases": "Casos de prueba fallidos",
|
|
16
|
+
"modalResultDismissHint": "Haga clic en cualquier lugar o presione cualquier tecla para cerrar",
|
|
17
|
+
"modalResultAutoDismissHint": "Cierre automático en {{seconds}} segundos...",
|
|
14
18
|
"status": {
|
|
15
|
-
"ready": "
|
|
16
|
-
"run": "
|
|
17
|
-
"passed": "
|
|
18
|
-
"failed": "
|
|
19
|
-
"stopped": "
|
|
20
|
-
"unknown": "
|
|
19
|
+
"ready": "Listo",
|
|
20
|
+
"run": "Ejecutando",
|
|
21
|
+
"passed": "Aprobado",
|
|
22
|
+
"failed": "Fallado",
|
|
23
|
+
"stopped": "Detenido",
|
|
24
|
+
"unknown": "Desconocido"
|
|
21
25
|
}
|
|
22
26
|
},
|
|
23
27
|
"button": {
|
|
24
28
|
"start": "Iniciar",
|
|
25
29
|
"stop": "Detener",
|
|
26
|
-
"confirm": "Confirmar"
|
|
30
|
+
"confirm": "Confirmar",
|
|
31
|
+
"pass": "Aprobado",
|
|
32
|
+
"fail": "Fallado"
|
|
27
33
|
},
|
|
28
34
|
"error": {
|
|
29
35
|
"dbConnectionTitle": "Error de conexión a la base de datos",
|
|
30
36
|
"dbConnectionMessage": "No se pudo establecer la conexión con la base de datos"
|
|
31
37
|
},
|
|
38
|
+
"chart": {
|
|
39
|
+
"dataChart": "Datos del gráfico",
|
|
40
|
+
"xAxis": "Eje X",
|
|
41
|
+
"yAxis": "Eje Y",
|
|
42
|
+
"chart": "Gráfico",
|
|
43
|
+
"showChart": "Mostrar gráfico {{title}}",
|
|
44
|
+
"fullscreenButton": "Abrir gráfico en pantalla completa",
|
|
45
|
+
"series": "Serie {{number}}"
|
|
46
|
+
},
|
|
32
47
|
"operatorDialog": {
|
|
33
48
|
"defaultTitle": "Mensaje",
|
|
34
49
|
"imageAlt": "Imagen del mensaje del operador",
|
|
@@ -11,24 +11,39 @@
|
|
|
11
11
|
"connection": "Établissement de la connexion... 🧐🔎",
|
|
12
12
|
"dbError": "Erreur de connexion à la base de données. 🙅🏽♀️🚫",
|
|
13
13
|
"noEntries": "Aucune entrée dans la base de données 🙅🏽♀️🚫",
|
|
14
|
+
"stoppedTestCase": "Cas de test arrêté",
|
|
15
|
+
"failedTestCases": "Cas de test échoués",
|
|
16
|
+
"modalResultDismissHint": "Cliquez n'importe où ou appuyez sur n'importe quelle touche pour fermer",
|
|
17
|
+
"modalResultAutoDismissHint": "Fermeture automatique dans {{seconds}} secondes...",
|
|
14
18
|
"status": {
|
|
15
|
-
"ready": "
|
|
16
|
-
"run": "
|
|
17
|
-
"passed": "
|
|
18
|
-
"failed": "
|
|
19
|
-
"stopped": "
|
|
20
|
-
"unknown": "
|
|
19
|
+
"ready": "Prêt",
|
|
20
|
+
"run": "En cours",
|
|
21
|
+
"passed": "Réussi",
|
|
22
|
+
"failed": "Échoué",
|
|
23
|
+
"stopped": "Arrêté",
|
|
24
|
+
"unknown": "Inconnu"
|
|
21
25
|
}
|
|
22
26
|
},
|
|
23
27
|
"button": {
|
|
24
28
|
"start": "Commencer",
|
|
25
29
|
"stop": "Arrêter",
|
|
26
|
-
"confirm": "Confirmer"
|
|
30
|
+
"confirm": "Confirmer",
|
|
31
|
+
"pass": "Réussi",
|
|
32
|
+
"fail": "Échoué"
|
|
27
33
|
},
|
|
28
34
|
"error": {
|
|
29
35
|
"dbConnectionTitle": "Erreur de connexion à la base de données",
|
|
30
36
|
"dbConnectionMessage": "Échec de la connexion à la base de données"
|
|
31
37
|
},
|
|
38
|
+
"chart": {
|
|
39
|
+
"dataChart": "Données du graphique",
|
|
40
|
+
"xAxis": "Axe X",
|
|
41
|
+
"yAxis": "Axe Y",
|
|
42
|
+
"chart": "Graphique",
|
|
43
|
+
"showChart": "Afficher le graphique {{title}}",
|
|
44
|
+
"fullscreenButton": "Ouvrir le graphique en plein écran",
|
|
45
|
+
"series": "Série {{number}}"
|
|
46
|
+
},
|
|
32
47
|
"operatorDialog": {
|
|
33
48
|
"defaultTitle": "Message",
|
|
34
49
|
"imageAlt": "Image du message de l'opérateur",
|
|
@@ -11,6 +11,10 @@
|
|
|
11
11
|
"connection": "接続を確立しています... 🧐🔎",
|
|
12
12
|
"dbError": "データベース接続エラー. 🙅🏽♀️🚫",
|
|
13
13
|
"noEntries": "データベースにエントリがありません 🙅🏽♀️🚫",
|
|
14
|
+
"stoppedTestCase": "停止されたテストケース",
|
|
15
|
+
"failedTestCases": "失敗したテストケース",
|
|
16
|
+
"modalResultDismissHint": "どこかをクリックするか、任意のキーを押して閉じます",
|
|
17
|
+
"modalResultAutoDismissHint": "{{seconds}}秒後に自動的に閉じます...",
|
|
14
18
|
"status": {
|
|
15
19
|
"ready": "準備完了",
|
|
16
20
|
"run": "実行中",
|
|
@@ -23,12 +27,23 @@
|
|
|
23
27
|
"button": {
|
|
24
28
|
"start": "開始",
|
|
25
29
|
"stop": "停止",
|
|
26
|
-
"confirm": "確認"
|
|
30
|
+
"confirm": "確認",
|
|
31
|
+
"pass": "合格",
|
|
32
|
+
"fail": "不合格"
|
|
27
33
|
},
|
|
28
34
|
"error": {
|
|
29
35
|
"dbConnectionTitle": "データベース接続エラー",
|
|
30
36
|
"dbConnectionMessage": "データベースへの接続に失敗しました"
|
|
31
37
|
},
|
|
38
|
+
"chart": {
|
|
39
|
+
"dataChart": "チャートデータ",
|
|
40
|
+
"xAxis": "X軸",
|
|
41
|
+
"yAxis": "Y軸",
|
|
42
|
+
"chart": "グラフ",
|
|
43
|
+
"showChart": "グラフを表示 {{title}}",
|
|
44
|
+
"fullscreenButton": "グラフを全画面表示で開く",
|
|
45
|
+
"series": "シリーズ{{number}}"
|
|
46
|
+
},
|
|
32
47
|
"operatorDialog": {
|
|
33
48
|
"defaultTitle": "メッセージ",
|
|
34
49
|
"imageAlt": "オペレーターメッセージ画像",
|
|
@@ -11,24 +11,39 @@
|
|
|
11
11
|
"connection": "Установка соединения... 🧐🔎",
|
|
12
12
|
"dbError": "Ошибка подключения к базе данных. 🙅🏽♀️🚫",
|
|
13
13
|
"noEntries": "Нет записей в базе данных 🙅🏽♀️🚫",
|
|
14
|
+
"stoppedTestCase": "Остановленный тестовый случай",
|
|
15
|
+
"failedTestCases": "Проваленные тестовые случаи",
|
|
16
|
+
"modalResultDismissHint": "Нажмите на любое место на экране или нажмите любую клавишу для закрытия",
|
|
17
|
+
"modalResultAutoDismissHint": "Автоматическое закрытие через {{seconds}} секунд...",
|
|
14
18
|
"status": {
|
|
15
|
-
"ready": "
|
|
16
|
-
"run": "
|
|
17
|
-
"passed": "
|
|
18
|
-
"failed": "
|
|
19
|
-
"stopped": "
|
|
20
|
-
"unknown": "
|
|
19
|
+
"ready": "Готов",
|
|
20
|
+
"run": "Выполнение",
|
|
21
|
+
"passed": "Успех",
|
|
22
|
+
"failed": "Провалено",
|
|
23
|
+
"stopped": "Остановлено",
|
|
24
|
+
"unknown": "Неизвестно"
|
|
21
25
|
}
|
|
22
26
|
},
|
|
23
27
|
"button": {
|
|
24
28
|
"start": "Старт",
|
|
25
29
|
"stop": "Стоп",
|
|
26
|
-
"confirm": "Подтвердить"
|
|
30
|
+
"confirm": "Подтвердить",
|
|
31
|
+
"pass": "Успех",
|
|
32
|
+
"fail": "Провалено"
|
|
27
33
|
},
|
|
28
34
|
"error": {
|
|
29
35
|
"dbConnectionTitle": "Ошибка подключения к базе данных",
|
|
30
36
|
"dbConnectionMessage": "Не удалось установить соединение с базой данных"
|
|
31
37
|
},
|
|
38
|
+
"chart": {
|
|
39
|
+
"dataChart": "Данные графика",
|
|
40
|
+
"xAxis": "Ось X",
|
|
41
|
+
"yAxis": "Ось Y",
|
|
42
|
+
"chart": "График",
|
|
43
|
+
"showChart": "Показать график {{title}}",
|
|
44
|
+
"fullscreenButton": "Открыть график в полноэкранном режиме",
|
|
45
|
+
"series": "Серия {{number}}"
|
|
46
|
+
},
|
|
32
47
|
"operatorDialog": {
|
|
33
48
|
"defaultTitle": "Сообщение",
|
|
34
49
|
"imageAlt": "Изображение в сообщении оператора",
|
|
@@ -11,6 +11,10 @@
|
|
|
11
11
|
"connection": "正在建立连接... 🧐🔎",
|
|
12
12
|
"dbError": "数据库连接错误. 🙅🏽♀️🚫",
|
|
13
13
|
"noEntries": "数据库中没有条目 🙅🏽♀️🚫",
|
|
14
|
+
"stoppedTestCase": "已停止的测试用例",
|
|
15
|
+
"failedTestCases": "失败的测试用例",
|
|
16
|
+
"modalResultDismissHint": "点击任意位置或按任意键关闭",
|
|
17
|
+
"modalResultAutoDismissHint": "{{seconds}}秒后自动关闭...",
|
|
14
18
|
"status": {
|
|
15
19
|
"ready": "就绪",
|
|
16
20
|
"run": "运行中",
|
|
@@ -23,12 +27,23 @@
|
|
|
23
27
|
"button": {
|
|
24
28
|
"start": "开始",
|
|
25
29
|
"stop": "停止",
|
|
26
|
-
"confirm": "确认"
|
|
30
|
+
"confirm": "确认",
|
|
31
|
+
"pass": "通过",
|
|
32
|
+
"fail": "失败"
|
|
27
33
|
},
|
|
28
34
|
"error": {
|
|
29
35
|
"dbConnectionTitle": "数据库连接错误",
|
|
30
36
|
"dbConnectionMessage": "无法建立数据库连接"
|
|
31
37
|
},
|
|
38
|
+
"chart": {
|
|
39
|
+
"dataChart": "图表数据",
|
|
40
|
+
"xAxis": "X轴",
|
|
41
|
+
"yAxis": "Y轴",
|
|
42
|
+
"chart": "图表",
|
|
43
|
+
"showChart": "显示图表 {{title}}",
|
|
44
|
+
"fullscreenButton": "全屏显示图表",
|
|
45
|
+
"series": "系列{{number}}"
|
|
46
|
+
},
|
|
32
47
|
"operatorDialog": {
|
|
33
48
|
"defaultTitle": "消息",
|
|
34
49
|
"imageAlt": "操作员消息图片",
|
|
@@ -5,13 +5,25 @@ from hardpy.pytest_hardpy.db.base_store import BaseStore
|
|
|
5
5
|
from hardpy.pytest_hardpy.db.const import DatabaseField
|
|
6
6
|
from hardpy.pytest_hardpy.db.runstore import RunStore
|
|
7
7
|
from hardpy.pytest_hardpy.db.schema import ResultRunStore, ResultStateStore
|
|
8
|
+
from hardpy.pytest_hardpy.db.stand_type import (
|
|
9
|
+
Chart,
|
|
10
|
+
Instrument,
|
|
11
|
+
NumericMeasurement,
|
|
12
|
+
StringMeasurement,
|
|
13
|
+
SubUnit,
|
|
14
|
+
)
|
|
8
15
|
from hardpy.pytest_hardpy.db.statestore import StateStore
|
|
9
16
|
|
|
10
17
|
__all__ = [
|
|
11
18
|
"BaseStore",
|
|
19
|
+
"Chart",
|
|
12
20
|
"DatabaseField",
|
|
21
|
+
"Instrument",
|
|
22
|
+
"NumericMeasurement",
|
|
13
23
|
"ResultRunStore",
|
|
14
24
|
"ResultStateStore",
|
|
15
25
|
"RunStore",
|
|
16
26
|
"StateStore",
|
|
27
|
+
"StringMeasurement",
|
|
28
|
+
"SubUnit",
|
|
17
29
|
]
|
|
@@ -1,22 +1,31 @@
|
|
|
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
|
+
from json import dumps
|
|
4
5
|
from logging import getLogger
|
|
5
6
|
from typing import Any
|
|
6
7
|
|
|
7
8
|
from glom import assign, glom
|
|
8
|
-
from pycouchdb
|
|
9
|
+
from pycouchdb import Server as DbServer
|
|
10
|
+
from pycouchdb.client import Database
|
|
11
|
+
from pycouchdb.exceptions import Conflict, GenericError, NotFound
|
|
9
12
|
from pydantic._internal._model_construction import ModelMetaclass
|
|
13
|
+
from requests.exceptions import ConnectionError # noqa: A004
|
|
10
14
|
|
|
11
|
-
from hardpy.
|
|
15
|
+
from hardpy.common.config import ConfigManager
|
|
12
16
|
from hardpy.pytest_hardpy.db.const import DatabaseField as DF # noqa: N817
|
|
13
17
|
|
|
14
18
|
|
|
15
|
-
class BaseStore
|
|
19
|
+
class BaseStore:
|
|
16
20
|
"""HardPy base storage interface for CouchDB."""
|
|
17
21
|
|
|
18
22
|
def __init__(self, db_name: str) -> None:
|
|
19
|
-
|
|
23
|
+
config_manager = ConfigManager()
|
|
24
|
+
config = config_manager.config
|
|
25
|
+
self._db_srv = DbServer(config.database.url)
|
|
26
|
+
self._db_name = db_name
|
|
27
|
+
self._db = self._init_db()
|
|
28
|
+
self._doc_id = config.database.doc_id
|
|
20
29
|
self._log = getLogger(__name__)
|
|
21
30
|
self._doc: dict = self._init_doc()
|
|
22
31
|
self._schema: ModelMetaclass
|
|
@@ -47,6 +56,11 @@ class BaseStore(BaseConnector):
|
|
|
47
56
|
key (str): document key
|
|
48
57
|
value: document value
|
|
49
58
|
"""
|
|
59
|
+
try:
|
|
60
|
+
dumps(value)
|
|
61
|
+
except Exception: # noqa: BLE001
|
|
62
|
+
# serialize non-serializable objects as string
|
|
63
|
+
value = dumps(value, default=str)
|
|
50
64
|
if "." in key:
|
|
51
65
|
assign(self._doc, key, value)
|
|
52
66
|
else:
|
|
@@ -83,6 +97,19 @@ class BaseStore(BaseConnector):
|
|
|
83
97
|
self._log.debug("Database will be created for the first time")
|
|
84
98
|
self._doc: dict = self._init_doc()
|
|
85
99
|
|
|
100
|
+
def _init_db(self) -> Database:
|
|
101
|
+
try:
|
|
102
|
+
return self._db_srv.create(self._db_name) # type: ignore
|
|
103
|
+
except Conflict:
|
|
104
|
+
# database is already created
|
|
105
|
+
return self._db_srv.database(self._db_name)
|
|
106
|
+
except GenericError as exc:
|
|
107
|
+
msg = f"Error initializing database {exc}"
|
|
108
|
+
raise RuntimeError(msg) from exc
|
|
109
|
+
except ConnectionError as exc:
|
|
110
|
+
msg = f"Error initializing database: {exc}"
|
|
111
|
+
raise RuntimeError(msg) from exc
|
|
112
|
+
|
|
86
113
|
def _init_doc(self) -> dict:
|
|
87
114
|
try:
|
|
88
115
|
doc = self._db.get(self._doc_id)
|
|
@@ -5,9 +5,9 @@ from logging import getLogger
|
|
|
5
5
|
|
|
6
6
|
from pycouchdb.exceptions import Conflict, NotFound
|
|
7
7
|
|
|
8
|
+
from hardpy.common.singleton import SingletonMeta
|
|
8
9
|
from hardpy.pytest_hardpy.db.base_store import BaseStore
|
|
9
10
|
from hardpy.pytest_hardpy.db.schema import ResultRunStore
|
|
10
|
-
from hardpy.pytest_hardpy.utils import SingletonMeta
|
|
11
11
|
|
|
12
12
|
|
|
13
13
|
class RunStore(BaseStore, metaclass=SingletonMeta):
|
|
@@ -8,7 +8,7 @@ from typing import ClassVar
|
|
|
8
8
|
|
|
9
9
|
from pydantic import BaseModel, ConfigDict, Field
|
|
10
10
|
|
|
11
|
-
from hardpy.pytest_hardpy.utils import (
|
|
11
|
+
from hardpy.pytest_hardpy.utils.const import (
|
|
12
12
|
ChartType,
|
|
13
13
|
ComparisonOperation as CompOp,
|
|
14
14
|
Group,
|
|
@@ -78,7 +78,7 @@ class Dut(BaseModel):
|
|
|
78
78
|
part_number: str | None = None
|
|
79
79
|
revision: str | None = None
|
|
80
80
|
sub_units: list[SubUnit] = []
|
|
81
|
-
info: Mapping[str, str | int | float] = {}
|
|
81
|
+
info: Mapping[str, str | int | float | None] = {}
|
|
82
82
|
|
|
83
83
|
|
|
84
84
|
class SubUnit(BaseModel):
|
|
@@ -91,7 +91,7 @@ class SubUnit(BaseModel):
|
|
|
91
91
|
serial_number: str | None = None
|
|
92
92
|
part_number: str | None = None
|
|
93
93
|
revision: str | None = None
|
|
94
|
-
info: Mapping[str, str | int | float] = {}
|
|
94
|
+
info: Mapping[str, str | int | float | None] = {}
|
|
95
95
|
|
|
96
96
|
|
|
97
97
|
class Instrument(BaseModel):
|
|
@@ -101,9 +101,11 @@ class Instrument(BaseModel):
|
|
|
101
101
|
|
|
102
102
|
name: str | None = None
|
|
103
103
|
revision: str | None = None
|
|
104
|
+
serial_number: str | None = None
|
|
105
|
+
part_number: str | None = None
|
|
104
106
|
number: int | None = None
|
|
105
107
|
comment: str | None = None
|
|
106
|
-
info: Mapping[str, str | int | float] = {}
|
|
108
|
+
info: Mapping[str, str | int | float | None] = {}
|
|
107
109
|
|
|
108
110
|
|
|
109
111
|
class TestStand(BaseModel):
|
|
@@ -119,7 +121,7 @@ class TestStand(BaseModel):
|
|
|
119
121
|
number: int | None = None
|
|
120
122
|
drivers: dict = {} # deprecated, remove in v2
|
|
121
123
|
instruments: list[Instrument] = []
|
|
122
|
-
info: Mapping[str, str | int | float] = {}
|
|
124
|
+
info: Mapping[str, str | int | float | None] = {}
|
|
123
125
|
|
|
124
126
|
|
|
125
127
|
class Process(BaseModel):
|
|
@@ -129,7 +131,7 @@ class Process(BaseModel):
|
|
|
129
131
|
|
|
130
132
|
name: str | None = None
|
|
131
133
|
number: int | None = None
|
|
132
|
-
info: Mapping[str, str | int | float] = {}
|
|
134
|
+
info: Mapping[str, str | int | float | None] = {}
|
|
133
135
|
|
|
134
136
|
|
|
135
137
|
class IBaseMeasurement(BaseModel, ABC):
|
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
|
|
4
4
|
from logging import getLogger
|
|
5
5
|
|
|
6
|
+
from hardpy.common.singleton import SingletonMeta
|
|
6
7
|
from hardpy.pytest_hardpy.db.base_store import BaseStore
|
|
7
8
|
from hardpy.pytest_hardpy.db.schema import ResultStateStore
|
|
8
|
-
from hardpy.pytest_hardpy.utils import SingletonMeta
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
class StateStore(BaseStore, metaclass=SingletonMeta):
|
hardpy/pytest_hardpy/plugin.py
CHANGED
|
@@ -32,14 +32,10 @@ from pytest import (
|
|
|
32
32
|
skip,
|
|
33
33
|
)
|
|
34
34
|
|
|
35
|
+
from hardpy.common.config import ConfigManager, HardpyConfig
|
|
35
36
|
from hardpy.common.stand_cloud.connector import StandCloudConnector, StandCloudError
|
|
36
37
|
from hardpy.pytest_hardpy.reporter import HookReporter
|
|
37
|
-
from hardpy.pytest_hardpy.utils import
|
|
38
|
-
ConnectionData,
|
|
39
|
-
NodeInfo,
|
|
40
|
-
ProgressCalculator,
|
|
41
|
-
TestStatus,
|
|
42
|
-
)
|
|
38
|
+
from hardpy.pytest_hardpy.utils import NodeInfo, ProgressCalculator, TestStatus
|
|
43
39
|
from hardpy.pytest_hardpy.utils.node_info import TestDependencyInfo
|
|
44
40
|
|
|
45
41
|
if __debug__:
|
|
@@ -51,11 +47,11 @@ if __debug__:
|
|
|
51
47
|
|
|
52
48
|
def pytest_addoption(parser: Parser) -> None:
|
|
53
49
|
"""Register argparse-style options."""
|
|
54
|
-
|
|
50
|
+
default_config = HardpyConfig()
|
|
55
51
|
parser.addoption(
|
|
56
52
|
"--hardpy-db-url",
|
|
57
53
|
action="store",
|
|
58
|
-
default=
|
|
54
|
+
default=default_config.database.url,
|
|
59
55
|
help="database url",
|
|
60
56
|
)
|
|
61
57
|
parser.addoption(
|
|
@@ -90,13 +86,13 @@ def pytest_addoption(parser: Parser) -> None:
|
|
|
90
86
|
parser.addoption(
|
|
91
87
|
"--sc-address",
|
|
92
88
|
action="store",
|
|
93
|
-
default=
|
|
89
|
+
default=default_config.stand_cloud.address,
|
|
94
90
|
help="StandCloud address",
|
|
95
91
|
)
|
|
96
92
|
parser.addoption(
|
|
97
93
|
"--sc-connection-only",
|
|
98
94
|
action="store_true",
|
|
99
|
-
default=
|
|
95
|
+
default=default_config.stand_cloud.connection_only,
|
|
100
96
|
help="check StandCloud availability",
|
|
101
97
|
)
|
|
102
98
|
parser.addoption(
|
|
@@ -144,11 +140,15 @@ class HardpyPlugin:
|
|
|
144
140
|
|
|
145
141
|
def pytest_configure(self, config: Config) -> None:
|
|
146
142
|
"""Configure pytest."""
|
|
147
|
-
|
|
143
|
+
config_manager = ConfigManager()
|
|
144
|
+
hardpy_config = config_manager.read_config(Path(config.rootpath))
|
|
145
|
+
|
|
146
|
+
if not hardpy_config:
|
|
147
|
+
hardpy_config = HardpyConfig()
|
|
148
148
|
|
|
149
149
|
database_url = config.getoption("--hardpy-db-url")
|
|
150
150
|
if database_url:
|
|
151
|
-
|
|
151
|
+
hardpy_config.database.url = str(database_url) # type: ignore
|
|
152
152
|
|
|
153
153
|
tests_name = config.getoption("--hardpy-tests-name")
|
|
154
154
|
if tests_name:
|
|
@@ -160,11 +160,11 @@ class HardpyPlugin:
|
|
|
160
160
|
|
|
161
161
|
sc_address = config.getoption("--sc-address")
|
|
162
162
|
if sc_address:
|
|
163
|
-
|
|
163
|
+
hardpy_config.stand_cloud.address = str(sc_address) # type: ignore
|
|
164
164
|
|
|
165
165
|
sc_connection_only = config.getoption("--sc-connection-only")
|
|
166
166
|
if sc_connection_only:
|
|
167
|
-
|
|
167
|
+
hardpy_config.stand_cloud.connection_only = bool(sc_connection_only) # type: ignore
|
|
168
168
|
|
|
169
169
|
_args = config.getoption("--hardpy-start-arg") or []
|
|
170
170
|
if _args:
|
|
@@ -181,7 +181,7 @@ class HardpyPlugin:
|
|
|
181
181
|
# must be init after config data is set
|
|
182
182
|
try:
|
|
183
183
|
self._reporter = HookReporter(bool(is_clear_database))
|
|
184
|
-
except
|
|
184
|
+
except Exception as exc: # noqa: BLE001
|
|
185
185
|
exit(str(exc), ExitCode.INTERNAL_ERROR)
|
|
186
186
|
|
|
187
187
|
def pytest_sessionfinish(self, session: Session, exitstatus: int) -> None:
|
|
@@ -246,25 +246,34 @@ class HardpyPlugin:
|
|
|
246
246
|
|
|
247
247
|
def pytest_runtestloop(self, session: Session) -> bool | None:
|
|
248
248
|
"""Call at the start of test run."""
|
|
249
|
-
|
|
249
|
+
try:
|
|
250
|
+
self._progress.set_test_amount(session.testscollected)
|
|
251
|
+
except ValueError:
|
|
252
|
+
msg = "No tests collected"
|
|
253
|
+
self._reporter.set_alert(msg)
|
|
254
|
+
self._reporter.update_db_by_doc()
|
|
255
|
+
exit(msg, ExitCode.NO_TESTS_COLLECTED)
|
|
250
256
|
if session.config.option.collectonly:
|
|
251
257
|
# ignore collect only mode
|
|
252
258
|
return True
|
|
253
259
|
|
|
254
|
-
|
|
260
|
+
config_manager = ConfigManager()
|
|
255
261
|
|
|
256
262
|
# running tests depends on a connection to StandCloud
|
|
257
|
-
if
|
|
263
|
+
if config_manager.config.stand_cloud.connection_only:
|
|
258
264
|
try:
|
|
259
|
-
sc_connector = StandCloudConnector(
|
|
265
|
+
sc_connector = StandCloudConnector(
|
|
266
|
+
addr=config_manager.config.stand_cloud.address,
|
|
267
|
+
)
|
|
260
268
|
except StandCloudError as exc:
|
|
261
269
|
msg = str(exc)
|
|
262
270
|
self._reporter.set_alert(msg)
|
|
271
|
+
self._reporter.update_db_by_doc()
|
|
263
272
|
exit(msg, ExitCode.INTERNAL_ERROR)
|
|
264
273
|
try:
|
|
265
274
|
sc_connector.healthcheck()
|
|
266
275
|
except Exception: # noqa: BLE001
|
|
267
|
-
addr =
|
|
276
|
+
addr = config_manager.config.stand_cloud.address
|
|
268
277
|
msg = (
|
|
269
278
|
f"StandCloud service at the address {addr} "
|
|
270
279
|
"not available or HardPy user is not authorized"
|
|
@@ -337,24 +346,28 @@ class HardpyPlugin:
|
|
|
337
346
|
self._reporter.clear_case_data(module_id, case_id)
|
|
338
347
|
self._reporter.update_db_by_doc()
|
|
339
348
|
|
|
349
|
+
# clear the error code if there were no failed tests before
|
|
350
|
+
if caused_dut_failure_id is None:
|
|
351
|
+
self._reporter.clear_error_code()
|
|
352
|
+
|
|
340
353
|
try:
|
|
341
354
|
item.runtest()
|
|
342
355
|
call.excinfo = None
|
|
343
356
|
self._is_critical_not_passed = False
|
|
344
357
|
is_dut_failure = False
|
|
345
358
|
self._reporter.set_case_status(module_id, case_id, TestStatus.PASSED)
|
|
346
|
-
# clear the error code if there were no failed tests before
|
|
347
|
-
if caused_dut_failure_id is None:
|
|
348
|
-
self._reporter.clear_error_code()
|
|
349
359
|
break
|
|
350
360
|
except AssertionError:
|
|
351
361
|
self._reporter.set_case_status(module_id, case_id, TestStatus.FAILED)
|
|
352
362
|
is_dut_failure = True
|
|
353
363
|
if current_attempt == attempt:
|
|
354
364
|
break
|
|
355
|
-
|
|
356
365
|
# set the caused dut failure id only the first time
|
|
357
|
-
if
|
|
366
|
+
if (
|
|
367
|
+
is_dut_failure
|
|
368
|
+
and caused_dut_failure_id is None
|
|
369
|
+
and call.excinfo.typename != "Skipped"
|
|
370
|
+
):
|
|
358
371
|
self._reporter.set_caused_dut_failure_id(module_id, case_id)
|
|
359
372
|
|
|
360
373
|
# Reporting hooks
|