pywebexec 2.0.14__py3-none-any.whl → 2.0.16__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.
- pywebexec/pywebexec.py +18 -1
- pywebexec/static/css/form.css +4 -4
- pywebexec/static/css/style.css +7 -3
- pywebexec/static/js/schemaform.js +69 -62
- pywebexec/version.py +2 -2
- {pywebexec-2.0.14.dist-info → pywebexec-2.0.16.dist-info}/METADATA +1 -1
- {pywebexec-2.0.14.dist-info → pywebexec-2.0.16.dist-info}/RECORD +11 -11
- {pywebexec-2.0.14.dist-info → pywebexec-2.0.16.dist-info}/LICENSE +0 -0
- {pywebexec-2.0.14.dist-info → pywebexec-2.0.16.dist-info}/WHEEL +0 -0
- {pywebexec-2.0.14.dist-info → pywebexec-2.0.16.dist-info}/entry_points.txt +0 -0
- {pywebexec-2.0.14.dist-info → pywebexec-2.0.16.dist-info}/top_level.txt +0 -0
pywebexec/pywebexec.py
CHANGED
@@ -6,6 +6,7 @@ import os
|
|
6
6
|
import json
|
7
7
|
import uuid
|
8
8
|
import argparse
|
9
|
+
import shutil
|
9
10
|
import random
|
10
11
|
import string
|
11
12
|
from datetime import datetime, timezone, timedelta
|
@@ -358,7 +359,7 @@ def parseargs():
|
|
358
359
|
parser.add_argument("-g", "--gencert", action="store_true", help="https server self signed cert")
|
359
360
|
parser.add_argument("-T", "--tokenurl", action="store_true", help="generate safe url to access")
|
360
361
|
parser.add_argument("action", nargs="?", help="daemon action start/stop/restart/status/shareterm/term",
|
361
|
-
choices=["start","stop","restart","status","shareterm", "term", "run"])
|
362
|
+
choices=["start","stop","restart","status","shareterm", "term", "run", "run-para"])
|
362
363
|
parser.add_argument("command", nargs="*", help="command to run")
|
363
364
|
|
364
365
|
args = parser.parse_args()
|
@@ -383,8 +384,24 @@ def parseargs():
|
|
383
384
|
command = args.command[0]
|
384
385
|
params = args.command[1:]
|
385
386
|
command_id = term_command_id
|
387
|
+
print("Command:", command_id, flush=True)
|
386
388
|
exit_code = run_command("localhost", args.user, command, params, command_id, tty_rows, tty_cols)
|
387
389
|
sys.exit(exit_code)
|
390
|
+
elif args.action == "run-para":
|
391
|
+
runpara = shutil.which("run-para")
|
392
|
+
if not runpara:
|
393
|
+
print("Error: run-para not found, install using pip install run-para", file=sys.stderr)
|
394
|
+
sys.exit(1)
|
395
|
+
args.command = sys.argv[sys.argv.index("run-para")+1:]
|
396
|
+
try:
|
397
|
+
commandindex = args.command.index("--")
|
398
|
+
except ValueError:
|
399
|
+
print("Error: run-para: No command supplied", file=sys.stderr)
|
400
|
+
sys.exit(1)
|
401
|
+
runparams = args.command[0:commandindex]
|
402
|
+
command = args.command[commandindex+1:]
|
403
|
+
result = subprocess.run([runpara, '-n', *runparams, "--", sys.argv[0], "-d", args.dir, "--", "run", *command], bufsize=0)
|
404
|
+
sys.exit(result.returncode)
|
388
405
|
|
389
406
|
(hostname, ip) = host_ip.get_host_ip(args.listen)
|
390
407
|
|
pywebexec/static/css/form.css
CHANGED
@@ -80,7 +80,6 @@ font-size: 14px;
|
|
80
80
|
width: auto;
|
81
81
|
vertical-align: middle;
|
82
82
|
box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);
|
83
|
-
transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;
|
84
83
|
box-sizing: border-box;
|
85
84
|
padding: 3px 10px;
|
86
85
|
height: 24px;
|
@@ -145,7 +144,7 @@ font-size: 14px;
|
|
145
144
|
width: auto;
|
146
145
|
}
|
147
146
|
input[type="number"] {
|
148
|
-
max-width: 100px;
|
147
|
+
/* max-width: 100px; */
|
149
148
|
text-align: right;
|
150
149
|
}
|
151
150
|
select {
|
@@ -160,11 +159,12 @@ font-size: 14px;
|
|
160
159
|
resize: both;
|
161
160
|
max-width: 700px;
|
162
161
|
border-radius: 15px;
|
162
|
+
border-bottom-right-radius: 5px;
|
163
163
|
border: 1px solid #ccc;
|
164
|
-
padding: 3px
|
164
|
+
padding: 3px 10px;
|
165
165
|
margin: 0px;
|
166
166
|
width: unset;
|
167
|
-
line-height: 1.
|
167
|
+
line-height: 1.42857143;
|
168
168
|
font-weight: normal;
|
169
169
|
font-family: Arial, Helvetica, sans-serif;
|
170
170
|
font-size: 14px;
|
pywebexec/static/css/style.css
CHANGED
@@ -17,7 +17,7 @@ body {
|
|
17
17
|
overflow: hidden;
|
18
18
|
}
|
19
19
|
.table-container {
|
20
|
-
height:
|
20
|
+
height: 173px;
|
21
21
|
overflow-y: auto;
|
22
22
|
position: relative;
|
23
23
|
border-radius: 10px;
|
@@ -29,12 +29,15 @@ table {
|
|
29
29
|
border-collapse: collapse;
|
30
30
|
}
|
31
31
|
th, td {
|
32
|
-
padding: 7px;
|
33
32
|
text-align: left;
|
34
33
|
border-bottom: 1px solid #ddd;
|
35
34
|
white-space: nowrap;
|
36
35
|
}
|
37
|
-
|
36
|
+
td {
|
37
|
+
padding: 4px 7px;; /* 2px 7px; */
|
38
|
+
}
|
39
|
+
th {
|
40
|
+
padding: 7px;
|
38
41
|
background-color: #444;
|
39
42
|
color: #eee;
|
40
43
|
position: sticky;
|
@@ -431,6 +434,7 @@ body.dimmed * {
|
|
431
434
|
}
|
432
435
|
.command-line {
|
433
436
|
padding: 5px 10px 6px 10px;
|
437
|
+
margin-top: 4px;
|
434
438
|
background-color: #111;
|
435
439
|
color: #eee;
|
436
440
|
max-width: 300px;
|
@@ -1,16 +1,25 @@
|
|
1
1
|
function adjustInputWidth(input) {
|
2
|
-
|
3
|
-
|
2
|
+
input.style.width = 'auto';
|
3
|
+
if (input.type === 'number') {
|
4
|
+
delta = 30;
|
5
|
+
} else {
|
6
|
+
delta = 3;
|
7
|
+
}
|
8
|
+
input.style.width = `${input.scrollWidth + delta}px`;
|
4
9
|
}
|
5
10
|
|
6
11
|
function formInputHandle() {
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
12
|
+
schemaForm.querySelectorAll('input[type="text"], input[type="number"]').forEach(input => {
|
13
|
+
if (! inputHandlers.includes(input)) {
|
14
|
+
if (input.value) {
|
15
|
+
input.setAttribute('size', Math.max(input.value.length - 2, 2));
|
16
|
+
} else {
|
17
|
+
input.setAttribute('size', '12');
|
18
|
+
}
|
19
|
+
input.addEventListener('input', () => adjustInputWidth(input));
|
20
|
+
inputHandlers.push(input);
|
21
|
+
}
|
22
|
+
});
|
14
23
|
}
|
15
24
|
|
16
25
|
function extractKeysAndPlaceholders(obj, prefix = '') {
|
@@ -18,10 +27,8 @@ function extractKeysAndPlaceholders(obj, prefix = '') {
|
|
18
27
|
|
19
28
|
for (let key in obj.properties) {
|
20
29
|
if (obj.properties[key].type === 'object' && obj.properties[key].properties) {
|
21
|
-
// Si la propriété est un objet, appeler récursivement
|
22
30
|
result = result.concat(extractKeysAndPlaceholders(obj.properties[key], prefix ? `${prefix}.${key}` : key));
|
23
31
|
} else {
|
24
|
-
// Sinon, ajouter au résultat
|
25
32
|
result.push({
|
26
33
|
key: prefix ? `${prefix}.${key}` : key,
|
27
34
|
placeholder: obj.properties[key].example || null
|
@@ -32,69 +39,69 @@ function extractKeysAndPlaceholders(obj, prefix = '') {
|
|
32
39
|
}
|
33
40
|
|
34
41
|
function createSchemaForm(form, schema, onSubmit) {
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
});
|
42
|
-
}
|
43
|
-
form[0].classList.add('form-inline');
|
44
|
-
jsform = form.jsonForm({
|
45
|
-
schema: schema,
|
46
|
-
onSubmit: onSubmit,
|
47
|
-
form: formDesc,
|
48
|
-
// params: {
|
49
|
-
// fieldHtmlClass: "input-small",
|
50
|
-
// }
|
51
|
-
});
|
52
|
-
form[0].firstChild.classList.add('form-inline');
|
53
|
-
form[0].querySelectorAll('._jsonform-array-addmore').forEach(btn => {
|
54
|
-
btn.addEventListener('click', formInputHandle);
|
42
|
+
formDesc = extractKeysAndPlaceholders(schema);
|
43
|
+
schemaForm = form[0];
|
44
|
+
if (onSubmit != null) {
|
45
|
+
formDesc.push({
|
46
|
+
type: 'submit',
|
47
|
+
title: 'Run',
|
55
48
|
});
|
56
|
-
|
49
|
+
}
|
50
|
+
form[0].classList.add('form-inline');
|
51
|
+
jsform = form.jsonForm({
|
52
|
+
schema: schema,
|
53
|
+
onSubmit: onSubmit,
|
54
|
+
form: formDesc,
|
55
|
+
// params: {
|
56
|
+
// fieldHtmlClass: "input-small",
|
57
|
+
// }
|
58
|
+
});
|
59
|
+
form[0].firstChild.classList.add('form-inline');
|
60
|
+
form[0].querySelectorAll('._jsonform-array-addmore').forEach(btn => {
|
61
|
+
btn.addEventListener('click', formInputHandle);
|
62
|
+
});
|
63
|
+
formInputHandle();
|
57
64
|
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
});
|
65
|
+
form[0].querySelectorAll('textarea').forEach(txt => {
|
66
|
+
txt.style.height = "0";
|
67
|
+
txt.style.height = txt.scrollHeight + "px";
|
68
|
+
txt.setAttribute("spellcheck", "false")
|
69
|
+
txt.addEventListener("input", (e) => {
|
70
|
+
e.target.style.height = "0";
|
71
|
+
e.target.style.height = (e.target.scrollHeight+2) + "px";
|
66
72
|
});
|
73
|
+
});
|
67
74
|
|
68
|
-
|
75
|
+
return jsform;
|
69
76
|
}
|
70
77
|
|
71
78
|
async function getSwaggerSpec() {
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
+
const response = await fetch('/swagger.yaml');
|
80
|
+
if (!response.ok) {
|
81
|
+
return null;
|
82
|
+
}
|
83
|
+
const yamlText = await response.text();
|
84
|
+
// Changed from yaml.parse to jsyaml.load because js-yaml exposes jsyaml
|
85
|
+
return jsyaml.load(yamlText);
|
79
86
|
}
|
80
87
|
|
81
88
|
async function getPostParametersSchema() {
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
}
|
89
|
+
const swaggerSpec = await getSwaggerSpec();
|
90
|
+
const result = {};
|
91
|
+
for (const path in swaggerSpec.paths) {
|
92
|
+
const pathItem = swaggerSpec.paths[path];
|
93
|
+
if (pathItem.post) {
|
94
|
+
const postDef = pathItem.post;
|
95
|
+
// Look for a parameter in the body with a schema property
|
96
|
+
if (postDef.parameters && Array.isArray(postDef.parameters)) {
|
97
|
+
const bodyParam = postDef.parameters.find(p => p.in === 'body' && p.schema);
|
98
|
+
result[path] = bodyParam ? bodyParam.schema : null;
|
99
|
+
} else {
|
100
|
+
result[path] = null;
|
95
101
|
}
|
96
102
|
}
|
97
|
-
|
103
|
+
}
|
104
|
+
return result;
|
98
105
|
}
|
99
106
|
|
100
107
|
let schemaForm;
|
pywebexec/version.py
CHANGED
@@ -1,11 +1,11 @@
|
|
1
1
|
pywebexec/__init__.py,sha256=197fHJy0UDBwTTpGCGortZRr-w2kTaD7MxqdbVmTEi0,61
|
2
2
|
pywebexec/host_ip.py,sha256=Ud_HTflWVQ8789aoQ2RZdT1wGI-ccvrwSWGz_c7T3TI,1241
|
3
|
-
pywebexec/pywebexec.py,sha256=
|
3
|
+
pywebexec/pywebexec.py,sha256=z_ri7z0r2jrpf1yeih1TEFaBnH39y40zfmuZY2UIu5c,42061
|
4
4
|
pywebexec/swagger.yaml,sha256=j-KZnU4rGR-Fsk8y_EbqYzqVgtAZ8EjZIKAqZSxyyc0,5858
|
5
|
-
pywebexec/version.py,sha256=
|
6
|
-
pywebexec/static/css/form.css,sha256=
|
5
|
+
pywebexec/version.py,sha256=EKK00w5csA9NOnnxoF7dOLtlj1z8v-7kg5DnmxSTw3I,513
|
6
|
+
pywebexec/static/css/form.css,sha256=QTDPjr9PIKkhHVXCL7b1okLtmkmPVzpOhOn8CmLNpv0,4477
|
7
7
|
pywebexec/static/css/markdown.css,sha256=3RzUnpVBdF6cQuB_NXV7hMTc0quYU8sfyuZcpsREj6A,1939
|
8
|
-
pywebexec/static/css/style.css,sha256=
|
8
|
+
pywebexec/static/css/style.css,sha256=ynccbEDzK07rurLm-UirUs5j_hVfXlIgaHeUIq9WvA0,9969
|
9
9
|
pywebexec/static/css/swagger-ui.css,sha256=xhXN8fnUaIACGHuPIEIr9-qmyYr6Zx0k2wv4Qy7Bg1Y,154985
|
10
10
|
pywebexec/static/css/swagger-ui.css.map,sha256=dJy-xBn_htK4BNupTMIl33ddse7BXsrCdDJWlTJodnw,258842
|
11
11
|
pywebexec/static/css/xterm.css,sha256=uo5phWaUiJgcz0DAzv46uoByLLbJLeetYosL1xf68rY,5559
|
@@ -35,7 +35,7 @@ pywebexec/static/images/success.svg,sha256=NVwezvVMplt46ElW798vqGfrL21Mw_DWHUp_q
|
|
35
35
|
pywebexec/static/images/swagger-ui.svg,sha256=FR0yeOVwe4zCYKZAjCGcT_m0Mf25NexIVaSXifIkoU0,2117
|
36
36
|
pywebexec/static/js/executables.js,sha256=3HfOsrrurtnVd-AAHpkAtvnbJDB8k7nxRwtZXRQTzuI,11767
|
37
37
|
pywebexec/static/js/popup.js,sha256=0fr3pp4j9D2fXEVnHyQrx2bPWFHfgbb336dbewgH1d8,9023
|
38
|
-
pywebexec/static/js/schemaform.js,sha256=
|
38
|
+
pywebexec/static/js/schemaform.js,sha256=RUUnReUKlB6GnlhN-sI0AE4-nHWBONfqxo0owSSDED8,3095
|
39
39
|
pywebexec/static/js/script.js,sha256=fwTo9Iz4xsl6wGs-Nm8-Ng8aXzDfvews5cHfzhSfg_0,17987
|
40
40
|
pywebexec/static/js/swagger-form.js,sha256=uTRGKrcyBqq910RLmdlV-HpFri3RaAXpqUPSQSyoe6o,3806
|
41
41
|
pywebexec/static/js/js-yaml/LICENSE,sha256=oHvCRGi5ZUznalR9R6LbKC0HcztxXbTHOpi9Y5YflVA,1084
|
@@ -66,9 +66,9 @@ pywebexec/templates/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSu
|
|
66
66
|
pywebexec/templates/index.html,sha256=KeNLBH9PN_ZuGhzwrjvRTj2oBtbINv_SbwGQpOahNWo,3820
|
67
67
|
pywebexec/templates/popup.html,sha256=3kpMccKD_OLLhJ4Y9KRw6Ny8wQWjVaRrUfV9y5-bDiQ,1580
|
68
68
|
pywebexec/templates/swagger_ui.html,sha256=9ngyldkyEdLonBjl97mbIZUlVk-jxwcHrvFzMSrveyU,1067
|
69
|
-
pywebexec-2.0.
|
70
|
-
pywebexec-2.0.
|
71
|
-
pywebexec-2.0.
|
72
|
-
pywebexec-2.0.
|
73
|
-
pywebexec-2.0.
|
74
|
-
pywebexec-2.0.
|
69
|
+
pywebexec-2.0.16.dist-info/LICENSE,sha256=gRJf0JPT_wsZJsUGlWPTS8Vypfl9vQ1qjp6sNbKykuA,1064
|
70
|
+
pywebexec-2.0.16.dist-info/METADATA,sha256=6CxYnG68OaoGaPZKr7m2FMz938JRvt4XlO-oHYKE__I,11645
|
71
|
+
pywebexec-2.0.16.dist-info/WHEEL,sha256=52BFRY2Up02UkjOa29eZOS2VxUrpPORXg1pkohGGUS8,91
|
72
|
+
pywebexec-2.0.16.dist-info/entry_points.txt,sha256=l52GBkPCXRkmlHfEyoVauyfBdg8o-CAtC8qQpOIjJK0,55
|
73
|
+
pywebexec-2.0.16.dist-info/top_level.txt,sha256=vHoHyzngrfGdm_nM7Xn_5iLmaCrf10XO1EhldgNLEQ8,10
|
74
|
+
pywebexec-2.0.16.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|