pywebexec 2.0.15__py3-none-any.whl → 2.0.17__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 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
 
@@ -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: 120px;
149
148
  text-align: right;
150
149
  }
151
150
  select {
@@ -162,10 +161,10 @@ font-size: 14px;
162
161
  border-radius: 15px;
163
162
  border-bottom-right-radius: 5px;
164
163
  border: 1px solid #ccc;
165
- padding: 3px 8px;
164
+ padding: 3px 10px;
166
165
  margin: 0px;
167
166
  width: unset;
168
- line-height: 1.25;
167
+ line-height: 1.42857143;
169
168
  font-weight: normal;
170
169
  font-family: Arial, Helvetica, sans-serif;
171
170
  font-size: 14px;
@@ -17,7 +17,7 @@ body {
17
17
  overflow: hidden;
18
18
  }
19
19
  .table-container {
20
- height: 150px;
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
- th {
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
- input.style.width = 'auto';
3
- input.style.width = `${input.scrollWidth + 3}px`;
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
- schemaForm.querySelectorAll('input[type="text"]').forEach(input => {
8
- if (! inputHandlers.includes(input)) {
9
- input.setAttribute('size', '12');
10
- input.addEventListener('input', () => adjustInputWidth(input));
11
- inputHandlers.push(input);
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
- formDesc = extractKeysAndPlaceholders(schema);
36
- schemaForm = form[0];
37
- if (onSubmit != null) {
38
- formDesc.push({
39
- type: 'submit',
40
- title: 'Run',
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
- formInputHandle();
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
- form[0].querySelectorAll('textarea').forEach(txt => {
59
- txt.style.height = "0";
60
- txt.style.height = txt.scrollHeight + "px";
61
- txt.setAttribute("spellcheck", "false")
62
- txt.addEventListener("input", (e) => {
63
- e.target.style.height = "0";
64
- e.target.style.height = (e.target.scrollHeight+2) + "px";
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
- return jsform;
75
+ return jsform;
69
76
  }
70
77
 
71
78
  async function getSwaggerSpec() {
72
- const response = await fetch('/swagger.yaml');
73
- if (!response.ok) {
74
- return null;
75
- }
76
- const yamlText = await response.text();
77
- // Changed from yaml.parse to jsyaml.load because js-yaml exposes jsyaml
78
- return jsyaml.load(yamlText);
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
- const swaggerSpec = await getSwaggerSpec();
83
- const result = {};
84
- for (const path in swaggerSpec.paths) {
85
- const pathItem = swaggerSpec.paths[path];
86
- if (pathItem.post) {
87
- const postDef = pathItem.post;
88
- // Look for a parameter in the body with a schema property
89
- if (postDef.parameters && Array.isArray(postDef.parameters)) {
90
- const bodyParam = postDef.parameters.find(p => p.in === 'body' && p.schema);
91
- result[path] = bodyParam ? bodyParam.schema : null;
92
- } else {
93
- result[path] = null;
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
- return result;
103
+ }
104
+ return result;
98
105
  }
99
106
 
100
107
  let schemaForm;
pywebexec/version.py CHANGED
@@ -17,5 +17,5 @@ __version__: str
17
17
  __version_tuple__: VERSION_TUPLE
18
18
  version_tuple: VERSION_TUPLE
19
19
 
20
- __version__ = version = '2.0.15'
21
- __version_tuple__ = version_tuple = (2, 0, 15)
20
+ __version__ = version = '2.0.17'
21
+ __version_tuple__ = version_tuple = (2, 0, 17)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: pywebexec
3
- Version: 2.0.15
3
+ Version: 2.0.17
4
4
  Summary: Simple Python HTTP Exec Server
5
5
  Home-page: https://github.com/joknarf/pywebexec
6
6
  Author: Franck Jouvanceau
@@ -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=j80Opy0MS86DZO8aDsMVagucsgawhCBsGAHEth5Cx7o,41241
3
+ pywebexec/pywebexec.py,sha256=z_ri7z0r2jrpf1yeih1TEFaBnH39y40zfmuZY2UIu5c,42061
4
4
  pywebexec/swagger.yaml,sha256=j-KZnU4rGR-Fsk8y_EbqYzqVgtAZ8EjZIKAqZSxyyc0,5858
5
- pywebexec/version.py,sha256=KHS-lBTKNnvt3tG-_wZMLCgf3YmPRtYxOn1Og_4pyik,513
6
- pywebexec/static/css/form.css,sha256=LLzr3GwEOVr6Isf8WAvSpAnz_uQPSXKKjEL6IO4iQQQ,4540
5
+ pywebexec/version.py,sha256=DMmD4ZGa2_6FkPEauCreBHTWcl7y2bBceqfptG6Zlmw,513
6
+ pywebexec/static/css/form.css,sha256=Zek0sCsO6CEP5fqss2C8P-OLg9FysP8r-90xwxwSWRk,4471
7
7
  pywebexec/static/css/markdown.css,sha256=3RzUnpVBdF6cQuB_NXV7hMTc0quYU8sfyuZcpsREj6A,1939
8
- pywebexec/static/css/style.css,sha256=abBWoSmxzq0mDTn0q7cUSZnXGoxIss8WWGAOxFM0e38,9905
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=9xyANDut7QjFafTjbXIU9Tsv_8z9KCCP-uVF3w-uics,3142
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.15.dist-info/LICENSE,sha256=gRJf0JPT_wsZJsUGlWPTS8Vypfl9vQ1qjp6sNbKykuA,1064
70
- pywebexec-2.0.15.dist-info/METADATA,sha256=iBvcpvWU_1V7uVfxqXE2tt59pMuMW5c7Q59W5eYz0Rc,11645
71
- pywebexec-2.0.15.dist-info/WHEEL,sha256=52BFRY2Up02UkjOa29eZOS2VxUrpPORXg1pkohGGUS8,91
72
- pywebexec-2.0.15.dist-info/entry_points.txt,sha256=l52GBkPCXRkmlHfEyoVauyfBdg8o-CAtC8qQpOIjJK0,55
73
- pywebexec-2.0.15.dist-info/top_level.txt,sha256=vHoHyzngrfGdm_nM7Xn_5iLmaCrf10XO1EhldgNLEQ8,10
74
- pywebexec-2.0.15.dist-info/RECORD,,
69
+ pywebexec-2.0.17.dist-info/LICENSE,sha256=gRJf0JPT_wsZJsUGlWPTS8Vypfl9vQ1qjp6sNbKykuA,1064
70
+ pywebexec-2.0.17.dist-info/METADATA,sha256=MQnEQHNeT4QTx7kM8o_kceb6sCUdqVKSwH2qvrxqBtY,11645
71
+ pywebexec-2.0.17.dist-info/WHEEL,sha256=52BFRY2Up02UkjOa29eZOS2VxUrpPORXg1pkohGGUS8,91
72
+ pywebexec-2.0.17.dist-info/entry_points.txt,sha256=l52GBkPCXRkmlHfEyoVauyfBdg8o-CAtC8qQpOIjJK0,55
73
+ pywebexec-2.0.17.dist-info/top_level.txt,sha256=vHoHyzngrfGdm_nM7Xn_5iLmaCrf10XO1EhldgNLEQ8,10
74
+ pywebexec-2.0.17.dist-info/RECORD,,