pywebexec 2.0.14__tar.gz → 2.0.16__tar.gz

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.
Files changed (83) hide show
  1. {pywebexec-2.0.14/pywebexec.egg-info → pywebexec-2.0.16}/PKG-INFO +1 -1
  2. {pywebexec-2.0.14 → pywebexec-2.0.16}/pywebexec/pywebexec.py +18 -1
  3. {pywebexec-2.0.14 → pywebexec-2.0.16}/pywebexec/static/css/form.css +4 -4
  4. {pywebexec-2.0.14 → pywebexec-2.0.16}/pywebexec/static/css/style.css +7 -3
  5. pywebexec-2.0.16/pywebexec/static/js/schemaform.js +110 -0
  6. {pywebexec-2.0.14 → pywebexec-2.0.16}/pywebexec/version.py +2 -2
  7. {pywebexec-2.0.14 → pywebexec-2.0.16/pywebexec.egg-info}/PKG-INFO +1 -1
  8. pywebexec-2.0.14/pywebexec/static/js/schemaform.js +0 -103
  9. {pywebexec-2.0.14 → pywebexec-2.0.16}/.github/workflows/python-publish.yml +0 -0
  10. {pywebexec-2.0.14 → pywebexec-2.0.16}/.gitignore +0 -0
  11. {pywebexec-2.0.14 → pywebexec-2.0.16}/LICENSE +0 -0
  12. {pywebexec-2.0.14 → pywebexec-2.0.16}/README.md +0 -0
  13. {pywebexec-2.0.14 → pywebexec-2.0.16}/pyproject.toml +0 -0
  14. {pywebexec-2.0.14 → pywebexec-2.0.16}/pywebexec/__init__.py +0 -0
  15. {pywebexec-2.0.14 → pywebexec-2.0.16}/pywebexec/host_ip.py +0 -0
  16. {pywebexec-2.0.14 → pywebexec-2.0.16}/pywebexec/static/css/markdown.css +0 -0
  17. {pywebexec-2.0.14 → pywebexec-2.0.16}/pywebexec/static/css/swagger-ui.css +0 -0
  18. {pywebexec-2.0.14 → pywebexec-2.0.16}/pywebexec/static/css/swagger-ui.css.map +0 -0
  19. {pywebexec-2.0.14 → pywebexec-2.0.16}/pywebexec/static/css/xterm.css +0 -0
  20. {pywebexec-2.0.14 → pywebexec-2.0.16}/pywebexec/static/fonts/CommitMonoNerdFontMono-Regular.ttf +0 -0
  21. {pywebexec-2.0.14 → pywebexec-2.0.16}/pywebexec/static/fonts/LICENSE +0 -0
  22. {pywebexec-2.0.14 → pywebexec-2.0.16}/pywebexec/static/fonts/glyphicons-halflings-regular.eot +0 -0
  23. {pywebexec-2.0.14 → pywebexec-2.0.16}/pywebexec/static/fonts/glyphicons-halflings-regular.svg +0 -0
  24. {pywebexec-2.0.14 → pywebexec-2.0.16}/pywebexec/static/fonts/glyphicons-halflings-regular.ttf +0 -0
  25. {pywebexec-2.0.14 → pywebexec-2.0.16}/pywebexec/static/fonts/glyphicons-halflings-regular.woff +0 -0
  26. {pywebexec-2.0.14 → pywebexec-2.0.16}/pywebexec/static/fonts/glyphicons-halflings-regular.woff2 +0 -0
  27. {pywebexec-2.0.14 → pywebexec-2.0.16}/pywebexec/static/images/aborted.svg +0 -0
  28. {pywebexec-2.0.14 → pywebexec-2.0.16}/pywebexec/static/images/copy.svg +0 -0
  29. {pywebexec-2.0.14 → pywebexec-2.0.16}/pywebexec/static/images/copy_ok.svg +0 -0
  30. {pywebexec-2.0.14 → pywebexec-2.0.16}/pywebexec/static/images/down-arrow.svg +0 -0
  31. {pywebexec-2.0.14 → pywebexec-2.0.16}/pywebexec/static/images/failed.svg +0 -0
  32. {pywebexec-2.0.14 → pywebexec-2.0.16}/pywebexec/static/images/favicon.svg +0 -0
  33. {pywebexec-2.0.14 → pywebexec-2.0.16}/pywebexec/static/images/fit-tty.svg +0 -0
  34. {pywebexec-2.0.14 → pywebexec-2.0.16}/pywebexec/static/images/fit-win.svg +0 -0
  35. {pywebexec-2.0.14 → pywebexec-2.0.16}/pywebexec/static/images/font-decrease.svg +0 -0
  36. {pywebexec-2.0.14 → pywebexec-2.0.16}/pywebexec/static/images/font-increase.svg +0 -0
  37. {pywebexec-2.0.14 → pywebexec-2.0.16}/pywebexec/static/images/norun.svg +0 -0
  38. {pywebexec-2.0.14 → pywebexec-2.0.16}/pywebexec/static/images/pause.svg +0 -0
  39. {pywebexec-2.0.14 → pywebexec-2.0.16}/pywebexec/static/images/popup.svg +0 -0
  40. {pywebexec-2.0.14 → pywebexec-2.0.16}/pywebexec/static/images/resume.svg +0 -0
  41. {pywebexec-2.0.14 → pywebexec-2.0.16}/pywebexec/static/images/running.svg +0 -0
  42. {pywebexec-2.0.14 → pywebexec-2.0.16}/pywebexec/static/images/success.svg +0 -0
  43. {pywebexec-2.0.14 → pywebexec-2.0.16}/pywebexec/static/images/swagger-ui.svg +0 -0
  44. {pywebexec-2.0.14 → pywebexec-2.0.16}/pywebexec/static/js/executables.js +0 -0
  45. {pywebexec-2.0.14 → pywebexec-2.0.16}/pywebexec/static/js/js-yaml/LICENSE +0 -0
  46. {pywebexec-2.0.14 → pywebexec-2.0.16}/pywebexec/static/js/js-yaml/js-yaml.min.js +0 -0
  47. {pywebexec-2.0.14 → pywebexec-2.0.16}/pywebexec/static/js/marked/LICENSE.md +0 -0
  48. {pywebexec-2.0.14 → pywebexec-2.0.16}/pywebexec/static/js/marked/marked.min.js +0 -0
  49. {pywebexec-2.0.14 → pywebexec-2.0.16}/pywebexec/static/js/popup.js +0 -0
  50. {pywebexec-2.0.14 → pywebexec-2.0.16}/pywebexec/static/js/script.js +0 -0
  51. {pywebexec-2.0.14 → pywebexec-2.0.16}/pywebexec/static/js/swagger-form.js +0 -0
  52. {pywebexec-2.0.14 → pywebexec-2.0.16}/pywebexec/static/js/swagger-ui/LICENSE +0 -0
  53. {pywebexec-2.0.14 → pywebexec-2.0.16}/pywebexec/static/js/swagger-ui/swagger-ui-bundle.js +0 -0
  54. {pywebexec-2.0.14 → pywebexec-2.0.16}/pywebexec/static/js/swagger-ui/swagger-ui-standalone-preset.js +0 -0
  55. {pywebexec-2.0.14 → pywebexec-2.0.16}/pywebexec/static/js/xterm/LICENSE +0 -0
  56. {pywebexec-2.0.14 → pywebexec-2.0.16}/pywebexec/static/js/xterm/addon-canvas.js +0 -0
  57. {pywebexec-2.0.14 → pywebexec-2.0.16}/pywebexec/static/js/xterm/addon-canvas.js.map +0 -0
  58. {pywebexec-2.0.14 → pywebexec-2.0.16}/pywebexec/static/js/xterm/addon-fit.js +0 -0
  59. {pywebexec-2.0.14 → pywebexec-2.0.16}/pywebexec/static/js/xterm/addon-fit.js.map +0 -0
  60. {pywebexec-2.0.14 → pywebexec-2.0.16}/pywebexec/static/js/xterm/addon-unicode-graphemes.js +0 -0
  61. {pywebexec-2.0.14 → pywebexec-2.0.16}/pywebexec/static/js/xterm/addon-unicode-graphemes.js.map +0 -0
  62. {pywebexec-2.0.14 → pywebexec-2.0.16}/pywebexec/static/js/xterm/addon-unicode11.js +0 -0
  63. {pywebexec-2.0.14 → pywebexec-2.0.16}/pywebexec/static/js/xterm/addon-unicode11.js.map +0 -0
  64. {pywebexec-2.0.14 → pywebexec-2.0.16}/pywebexec/static/js/xterm/xterm.js +0 -0
  65. {pywebexec-2.0.14 → pywebexec-2.0.16}/pywebexec/static/js/xterm/xterm.js.map +0 -0
  66. {pywebexec-2.0.14 → pywebexec-2.0.16}/pywebexec/static/jsonform/LICENSE +0 -0
  67. {pywebexec-2.0.14 → pywebexec-2.0.16}/pywebexec/static/jsonform/deps/README.md +0 -0
  68. {pywebexec-2.0.14 → pywebexec-2.0.16}/pywebexec/static/jsonform/deps/img/glyphicons-halflings.png +0 -0
  69. {pywebexec-2.0.14 → pywebexec-2.0.16}/pywebexec/static/jsonform/deps/jquery.min.js +0 -0
  70. {pywebexec-2.0.14 → pywebexec-2.0.16}/pywebexec/static/jsonform/deps/underscore.js +0 -0
  71. {pywebexec-2.0.14 → pywebexec-2.0.16}/pywebexec/static/jsonform/lib/jsonform.js +0 -0
  72. {pywebexec-2.0.14 → pywebexec-2.0.16}/pywebexec/swagger.yaml +0 -0
  73. {pywebexec-2.0.14 → pywebexec-2.0.16}/pywebexec/templates/__init__.py +0 -0
  74. {pywebexec-2.0.14 → pywebexec-2.0.16}/pywebexec/templates/index.html +0 -0
  75. {pywebexec-2.0.14 → pywebexec-2.0.16}/pywebexec/templates/popup.html +0 -0
  76. {pywebexec-2.0.14 → pywebexec-2.0.16}/pywebexec/templates/swagger_ui.html +0 -0
  77. {pywebexec-2.0.14 → pywebexec-2.0.16}/pywebexec.egg-info/SOURCES.txt +0 -0
  78. {pywebexec-2.0.14 → pywebexec-2.0.16}/pywebexec.egg-info/dependency_links.txt +0 -0
  79. {pywebexec-2.0.14 → pywebexec-2.0.16}/pywebexec.egg-info/entry_points.txt +0 -0
  80. {pywebexec-2.0.14 → pywebexec-2.0.16}/pywebexec.egg-info/requires.txt +0 -0
  81. {pywebexec-2.0.14 → pywebexec-2.0.16}/pywebexec.egg-info/top_level.txt +0 -0
  82. {pywebexec-2.0.14 → pywebexec-2.0.16}/pywebexecdev +0 -0
  83. {pywebexec-2.0.14 → pywebexec-2.0.16}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: pywebexec
3
- Version: 2.0.14
3
+ Version: 2.0.16
4
4
  Summary: Simple Python HTTP Exec Server
5
5
  Home-page: https://github.com/joknarf/pywebexec
6
6
  Author: Franck Jouvanceau
@@ -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: 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 8px;
164
+ padding: 3px 10px;
165
165
  margin: 0px;
166
166
  width: unset;
167
- line-height: 1.25;
167
+ line-height: 1.42857143;
168
168
  font-weight: normal;
169
169
  font-family: Arial, Helvetica, sans-serif;
170
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;
@@ -0,0 +1,110 @@
1
+ function adjustInputWidth(input) {
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`;
9
+ }
10
+
11
+ function formInputHandle() {
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
+ });
23
+ }
24
+
25
+ function extractKeysAndPlaceholders(obj, prefix = '') {
26
+ let result = [];
27
+
28
+ for (let key in obj.properties) {
29
+ if (obj.properties[key].type === 'object' && obj.properties[key].properties) {
30
+ result = result.concat(extractKeysAndPlaceholders(obj.properties[key], prefix ? `${prefix}.${key}` : key));
31
+ } else {
32
+ result.push({
33
+ key: prefix ? `${prefix}.${key}` : key,
34
+ placeholder: obj.properties[key].example || null
35
+ });
36
+ }
37
+ }
38
+ return result;
39
+ }
40
+
41
+ function createSchemaForm(form, schema, onSubmit) {
42
+ formDesc = extractKeysAndPlaceholders(schema);
43
+ schemaForm = form[0];
44
+ if (onSubmit != null) {
45
+ formDesc.push({
46
+ type: 'submit',
47
+ title: 'Run',
48
+ });
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();
64
+
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";
72
+ });
73
+ });
74
+
75
+ return jsform;
76
+ }
77
+
78
+ async function getSwaggerSpec() {
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);
86
+ }
87
+
88
+ async function getPostParametersSchema() {
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;
101
+ }
102
+ }
103
+ }
104
+ return result;
105
+ }
106
+
107
+ let schemaForm;
108
+ let inputHandlers = [];
109
+
110
+
@@ -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.14'
21
- __version_tuple__ = version_tuple = (2, 0, 14)
20
+ __version__ = version = '2.0.16'
21
+ __version_tuple__ = version_tuple = (2, 0, 16)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: pywebexec
3
- Version: 2.0.14
3
+ Version: 2.0.16
4
4
  Summary: Simple Python HTTP Exec Server
5
5
  Home-page: https://github.com/joknarf/pywebexec
6
6
  Author: Franck Jouvanceau
@@ -1,103 +0,0 @@
1
- function adjustInputWidth(input) {
2
- input.style.width = 'auto';
3
- input.style.width = `${input.scrollWidth + 3}px`;
4
- }
5
-
6
- 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
- });
14
- }
15
-
16
- function extractKeysAndPlaceholders(obj, prefix = '') {
17
- let result = [];
18
-
19
- for (let key in obj.properties) {
20
- if (obj.properties[key].type === 'object' && obj.properties[key].properties) {
21
- // Si la propriété est un objet, appeler récursivement
22
- result = result.concat(extractKeysAndPlaceholders(obj.properties[key], prefix ? `${prefix}.${key}` : key));
23
- } else {
24
- // Sinon, ajouter au résultat
25
- result.push({
26
- key: prefix ? `${prefix}.${key}` : key,
27
- placeholder: obj.properties[key].example || null
28
- });
29
- }
30
- }
31
- return result;
32
- }
33
-
34
- 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);
55
- });
56
- formInputHandle();
57
-
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
- });
66
- });
67
-
68
- return jsform;
69
- }
70
-
71
- 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
- }
80
-
81
- 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
- }
95
- }
96
- }
97
- return result;
98
- }
99
-
100
- let schemaForm;
101
- let inputHandlers = [];
102
-
103
-
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes