pywebexec 2.2.0__py3-none-any.whl → 2.2.2__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.
@@ -211,6 +211,19 @@
211
211
  box-shadow: unset;
212
212
  outline: 0;
213
213
  }
214
+ .controls > .checkbox input {
215
+ top: 5px;
216
+ }
217
+ .checkbox {
218
+ label {
219
+ font-weight: normal;
220
+ }
221
+ input {
222
+ top: 1px;
223
+ display: unset;
224
+ margin-right: 4px;
225
+ }
226
+ }
214
227
  }
215
228
 
216
229
  .swagger-ui textarea {
@@ -264,42 +264,36 @@ paramsInput.addEventListener('focus', () => {
264
264
  }
265
265
  if (gExecutables[currentCmd] && gExecutables[currentCmd].schema && gExecutables[currentCmd].schema.properties && paramsContainer.style.display == 'none') {
266
266
  createSchemaForm($('#schemaForm'), gExecutables[currentCmd].schema, async function (errors, values) {
267
- if (errors) {
268
- console.log(errors);
269
- alert(errors[0].message);
270
- return false;
271
- } else {
272
- const commandName = commandInput.value;
273
- fitAddon.fit();
274
- terminal.clear();
275
- payload = { params: values, rows: terminal.rows, cols: terminal.cols }
276
- if ('parallel' in values) {
277
- payload['parallel'] = values['parallel'];
278
- payload['delay'] = values['delay'];
279
- delete payload['params']['parallel'];
280
- delete payload['params']['delay'];
281
- }
282
- try {
283
- const response = await fetch(`/commands/${commandName}`, {
284
- method: 'POST',
285
- headers: {
286
- 'Content-Type': 'application/json'
287
- },
288
- body: JSON.stringify(payload)
289
- });
290
-
291
- if (!response.ok) {
292
- throw new Error('Failed to launch command');
293
- }
294
-
295
- const data = await response.json();
296
- viewOutput(data.command_id);
297
- fetchCommands();
298
- commandInput.focus();
299
- commandInput.setSelectionRange(0, commandInput.value.length);
300
- } catch (error) {
301
- console.log('Error running command:', error);
267
+ const commandName = commandInput.value;
268
+ fitAddon.fit();
269
+ terminal.clear();
270
+ payload = { params: values, rows: terminal.rows, cols: terminal.cols }
271
+ if ('parallel' in values) {
272
+ payload['parallel'] = values['parallel'];
273
+ payload['delay'] = values['delay'];
274
+ delete payload['params']['parallel'];
275
+ delete payload['params']['delay'];
276
+ }
277
+ try {
278
+ const response = await fetch(`/commands/${commandName}`, {
279
+ method: 'POST',
280
+ headers: {
281
+ 'Content-Type': 'application/json'
282
+ },
283
+ body: JSON.stringify(payload)
284
+ });
285
+
286
+ if (!response.ok) {
287
+ throw new Error('Failed to launch command');
302
288
  }
289
+
290
+ const data = await response.json();
291
+ viewOutput(data.command_id);
292
+ fetchCommands();
293
+ commandInput.focus();
294
+ commandInput.setSelectionRange(0, commandInput.value.length);
295
+ } catch (error) {
296
+ console.log('Error running command:', error);
303
297
  }
304
298
  }, currentCmd);
305
299
  setHelpDivPosition();
@@ -54,12 +54,48 @@ function extractKeysAndPlaceholders(obj, formoptions, prefix = '') {
54
54
  return result;
55
55
  }
56
56
 
57
- function createSchemaForm(form, schema, onSubmit, schemaName) {
58
- if (schemaValues[schemaName]) {
59
- value = schemaValues[schemaName];
60
- } else {
61
- value = {};
57
+ // ...existing code...
58
+
59
+ function convertTextareaToArray(values, formDesc, schema) {
60
+ // Helper function to get schema type for a key path
61
+ function getSchemaType(schema, keyPath) {
62
+ const keys = keyPath.split('.');
63
+ let current = schema.properties;
64
+ for (const key of keys) {
65
+ if (!current || !current[key] || !current[key].properties) {
66
+ return current?.[key]?.type;
67
+ }
68
+ current = current[key].properties;
69
+ }
70
+ return null;
71
+ }
72
+
73
+ // Convert textarea values to arrays if schema type matches
74
+ for (let i = 0; i < formDesc.length; i++) {
75
+ if (formDesc[i].type == 'textarea') {
76
+ const schemaType = getSchemaType(schema, formDesc[i].key);
77
+ if (schemaType === 'array') {
78
+ const keys = formDesc[i].key.split('.');
79
+ let obj = values;
80
+ for (let j = 0; j < keys.length - 1; j++) {
81
+ obj = obj[keys[j]];
82
+ }
83
+ const lastKey = keys[keys.length - 1];
84
+ const val = obj[lastKey];
85
+ if (val) {
86
+ obj[lastKey] = val.trim().split(/[\s\r,]+/).filter(x => x);
87
+ } else {
88
+ delete obj[lastKey];
89
+ }
90
+ }
91
+ }
62
92
  }
93
+ return values;
94
+ }
95
+
96
+ // ...existing code...
97
+
98
+ function createSchemaForm(form, schema, onSubmit, schemaName) {
63
99
  if (schema && schema.schema_options) {
64
100
  schema_options = schema.schema_options;
65
101
  } else {
@@ -80,6 +116,33 @@ function createSchemaForm(form, schema, onSubmit, schemaName) {
80
116
  }
81
117
  }
82
118
  formDesc = extractKeysAndPlaceholders(schema, formoptions);
119
+ if (schemaValues[schemaName]) {
120
+ value = schemaValues[schemaName];
121
+ // convert array for textarea formDesc type to string separated by newlines
122
+ // if in formDesc a key has type textarea, convert the value to string separated by newlines
123
+ // formDesc=[{key: 'db.sid', type: 'textarea'}]
124
+ // value = {db: {sid: ['AA', 'BB']}}
125
+ // convert to
126
+ // value = {db: {sid: 'AA\nBB'}}
127
+ for (let i = 0; i < formDesc.length; i++) {
128
+ if (formDesc[i].type === 'textarea') {
129
+ const keys = formDesc[i].key.split('.');
130
+ let obj = value;
131
+ for (let j = 0; j < keys.length - 1; j++) {
132
+ if (!(keys[j] in obj)) obj[keys[j]] = {};
133
+ obj = obj[keys[j]];
134
+ }
135
+ const lastKey = keys[keys.length - 1];
136
+ const val = obj[lastKey];
137
+ if (val && Array.isArray(val)) {
138
+ obj[lastKey] = val.join('\n');
139
+ }
140
+ }
141
+ }
142
+ } else {
143
+ value = {};
144
+ }
145
+
83
146
  schemaForm = form[0];
84
147
  if (onSubmit != null) {
85
148
  if (schema_options && schema_options.batch_param) {
@@ -149,9 +212,20 @@ function createSchemaForm(form, schema, onSubmit, schemaName) {
149
212
  form[0].classList.add('form-inline');
150
213
  jsform = form.jsonForm({
151
214
  schema: schema,
152
- onSubmit: onSubmit,
215
+ onSubmit: function (errors, values) {
216
+ convertTextareaToArray(values, formDesc, schema);
217
+ env = JSV.createEnvironment();
218
+ report = env.validate(values, schema);
219
+ errors = report.errors;
220
+ if (errors.length > 0) {
221
+ alert(errors[0].message);
222
+ return false;
223
+ }
224
+ onSubmit(errors, values);
225
+ },
153
226
  form: formDesc,
154
227
  value: value,
228
+ validate: false,
155
229
  // params: {
156
230
  // fieldHtmlClass: "input-small",
157
231
  // }
@@ -168,9 +242,8 @@ function createSchemaForm(form, schema, onSubmit, schemaName) {
168
242
  txt.setAttribute("spellcheck", "false");
169
243
  txt.addEventListener("input", () => adjustTxtHeight(txt));
170
244
  });
171
-
172
245
  form[0].addEventListener('input', () => {
173
- schemaValues[schemaName] = jsform.root.getFormValues();
246
+ schemaValues[schemaName] = convertTextareaToArray(jsform.root.getFormValues(), formDesc, schema);
174
247
  localStorage.setItem('schemaValues', JSON.stringify(schemaValues));
175
248
  });
176
249
 
@@ -265,7 +265,6 @@ async function viewOutput(command_id) {
265
265
  } else {
266
266
  command = `${data.command.replace(/^\.\//, '')} ${data.params.join(' ')}`;
267
267
  }
268
- console.log(command);
269
268
  setCommandStatus(data.status)
270
269
  commandInfo.innerHTML = command;
271
270
  commandInfo.setAttribute('title', command);
@@ -1,8 +1,9 @@
1
1
  let ui;
2
2
  let swaggerSchemas = {};
3
+
3
4
  function addFormInputListener(textArea, jsform){
4
5
  return function (event) {
5
- jsonString = JSON.stringify(jsform.root.getFormValues(), null, 2);
6
+ jsonString = JSON.stringify(convertTextareaToArray(jsform.root.getFormValues(), jsform.formDesc.form, jsform.formDesc.schema), null, 2);
6
7
  textArea.value = jsonString;
7
8
 
8
9
  // Find the React fiber node
@@ -107,7 +108,8 @@ window.onload = function() {
107
108
  form.id = routePathId;
108
109
  form.classList.add("schema-form");
109
110
  jsform = createSchemaForm($(form), swaggerSchemas[routePath], null, routePath);
110
- // form.addEventListener("input", formInput(node, jsform));
111
+ // form.addEventListener("input", formInput(node, jsform));
112
+ setTimeout(() => addFormInputListener(paramtext, jsform)(), 100);
111
113
  form.addEventListener("input", addFormInputListener(paramtext, jsform));
112
114
  paramtext.parentNode.insertBefore(form, paramtext.nextSibling);
113
115
  item1 = form.querySelector("input, select, textarea");
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.2.0'
21
- __version_tuple__ = version_tuple = (2, 2, 0)
20
+ __version__ = version = '2.2.2'
21
+ __version_tuple__ = version_tuple = (2, 2, 2)
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.2
1
+ Metadata-Version: 2.4
2
2
  Name: pywebexec
3
- Version: 2.2.0
3
+ Version: 2.2.2
4
4
  Summary: Simple Python HTTP Exec Server
5
5
  Home-page: https://github.com/joknarf/pywebexec
6
6
  Author: Franck Jouvanceau
@@ -62,6 +62,7 @@ Requires-Dist: ldap3>=2.9.1
62
62
  Requires-Dist: pyte>=0.8.1
63
63
  Requires-Dist: PyYAML>=6.0.1
64
64
  Requires-Dist: run-para>=1.0.2
65
+ Dynamic: license-file
65
66
 
66
67
  [![Pypi version](https://img.shields.io/pypi/v/pywebexec.svg)](https://pypi.org/project/pywebexec/)
67
68
  ![Publish Package](https://github.com/joknarf/pywebexec/actions/workflows/python-publish.yml/badge.svg)
@@ -2,8 +2,8 @@ pywebexec/__init__.py,sha256=197fHJy0UDBwTTpGCGortZRr-w2kTaD7MxqdbVmTEi0,61
2
2
  pywebexec/host_ip.py,sha256=Ud_HTflWVQ8789aoQ2RZdT1wGI-ccvrwSWGz_c7T3TI,1241
3
3
  pywebexec/pywebexec.py,sha256=R-jp9BiUMJZW7m9N9kQC6dpIueUgFVDo4n9_GFb1rOs,45734
4
4
  pywebexec/swagger.yaml,sha256=I_oLpp7Hqel8SDEEykvpmCT-Gv3ytGlziq9bvQOrtZY,7598
5
- pywebexec/version.py,sha256=wdFcRBeaWRZXknL-E8RTk9hV9M-OMto6dfJ90sc1i9A,511
6
- pywebexec/static/css/form.css,sha256=eApJskeJ3MCzC7_p4gXgoIbvbG5s8m4bP1O4KHHqeiA,5293
5
+ pywebexec/version.py,sha256=YDBduKhVnvbZfZTbXbsjQMbxTwgIIXIZ646Mj9YV074,511
6
+ pywebexec/static/css/form.css,sha256=HnQ4A7QSQu1lC6P8h4hGpUMtOXujNg8SR1_qteu7oDk,5487
7
7
  pywebexec/static/css/markdown.css,sha256=br4-iK9wigTs54N2KHtjgZ4KLH0THVSvJo-XZAdMHiE,1970
8
8
  pywebexec/static/css/style.css,sha256=R1VOPNV2ztROKy9Fgf3tvUrtuKagY027tFJ8C866yWU,9991
9
9
  pywebexec/static/css/swagger-ui.css,sha256=xhXN8fnUaIACGHuPIEIr9-qmyYr6Zx0k2wv4Qy7Bg1Y,154985
@@ -33,11 +33,11 @@ pywebexec/static/images/resume.svg,sha256=99LP1Ya2JXakRCO9kW8JMuT_4a_CannF65Eiuw
33
33
  pywebexec/static/images/running.svg,sha256=fBCYwYb2O9K4N3waC2nURP25NRwZlqR4PbDZy6JQMww,610
34
34
  pywebexec/static/images/success.svg,sha256=NVwezvVMplt46ElW798vqGfrL21Mw_DWHUp_qiD_FU8,489
35
35
  pywebexec/static/images/swagger-ui.svg,sha256=FR0yeOVwe4zCYKZAjCGcT_m0Mf25NexIVaSXifIkoU0,2117
36
- pywebexec/static/js/executables.js,sha256=2ZSlsEMbfATr1EwUJMEAoS5G_wSUuWgT6AVQijawvtE,12160
36
+ pywebexec/static/js/executables.js,sha256=lF9Icb4VzbxSCTmcz-TUjvFKQ_ygmSgPq0Q_uaTRR-g,11866
37
37
  pywebexec/static/js/popup.js,sha256=O3DEWnyb5yGW9tjODYycc-ujWndyAfnJMxulaQeogtc,9700
38
- pywebexec/static/js/schemaform.js,sha256=GtIfd5YBaEr-KC1vXvZPFa5sYWRqdcjvP0Ozl7mr0YQ,6474
39
- pywebexec/static/js/script.js,sha256=sMOwgeRi59X0QyTTI58SqC4Sp_F7pK5JfozCkJMOHjs,18234
40
- pywebexec/static/js/swagger-form.js,sha256=sW7cUYJnd1ZZSMaMqaB2LCkjB1tfvSkdcAr-eW6UpZU,4430
38
+ pywebexec/static/js/schemaform.js,sha256=NLMAnS2GpyhGp286HUBqQXJAAQaqFMtJ03rGVrh8JaM,8856
39
+ pywebexec/static/js/script.js,sha256=X5TN2q1m6ZGPK72e1MWgyQWk1agOrcOWuGdwVWB9HJk,18204
40
+ pywebexec/static/js/swagger-form.js,sha256=EYXqHIE105DkXPCPi5-eYzux9nPLmJuisf-5EwFypsQ,4578
41
41
  pywebexec/static/js/js-yaml/LICENSE,sha256=oHvCRGi5ZUznalR9R6LbKC0HcztxXbTHOpi9Y5YflVA,1084
42
42
  pywebexec/static/js/js-yaml/js-yaml.min.js,sha256=Rdw90D3AegZwWiwpibjH9wkBPwS9U4bjJ51ORH8H69c,39430
43
43
  pywebexec/static/js/marked/LICENSE.md,sha256=jjo_gvWaYJWPVsoI9EVkfDKkcz3HymwsRvbriYRxq5w,2942
@@ -67,9 +67,9 @@ pywebexec/templates/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSu
67
67
  pywebexec/templates/index.html,sha256=w18O2plH_yS8bqlPsu5hwFFmCj9H2hWLSV8B6ADcSwU,3900
68
68
  pywebexec/templates/popup.html,sha256=3kpMccKD_OLLhJ4Y9KRw6Ny8wQWjVaRrUfV9y5-bDiQ,1580
69
69
  pywebexec/templates/swagger_ui.html,sha256=9ngyldkyEdLonBjl97mbIZUlVk-jxwcHrvFzMSrveyU,1067
70
- pywebexec-2.2.0.dist-info/LICENSE,sha256=gRJf0JPT_wsZJsUGlWPTS8Vypfl9vQ1qjp6sNbKykuA,1064
71
- pywebexec-2.2.0.dist-info/METADATA,sha256=PdGpfSzOG74LxsHEY8AUmPw5l_gsGIjChSTJIAKjxIk,12810
72
- pywebexec-2.2.0.dist-info/WHEEL,sha256=beeZ86-EfXScwlR_HKu4SllMC9wUEj_8Z_4FJ3egI2w,91
73
- pywebexec-2.2.0.dist-info/entry_points.txt,sha256=l52GBkPCXRkmlHfEyoVauyfBdg8o-CAtC8qQpOIjJK0,55
74
- pywebexec-2.2.0.dist-info/top_level.txt,sha256=vHoHyzngrfGdm_nM7Xn_5iLmaCrf10XO1EhldgNLEQ8,10
75
- pywebexec-2.2.0.dist-info/RECORD,,
70
+ pywebexec-2.2.2.dist-info/licenses/LICENSE,sha256=gRJf0JPT_wsZJsUGlWPTS8Vypfl9vQ1qjp6sNbKykuA,1064
71
+ pywebexec-2.2.2.dist-info/METADATA,sha256=6wl5EJ2M1Oww4Pn6Pu5wRAIqf0cHv6DixTl4jv5ICf4,12832
72
+ pywebexec-2.2.2.dist-info/WHEEL,sha256=tTnHoFhvKQHCh4jz3yCn0WPTYIy7wXx3CJtJ7SJGV7c,91
73
+ pywebexec-2.2.2.dist-info/entry_points.txt,sha256=l52GBkPCXRkmlHfEyoVauyfBdg8o-CAtC8qQpOIjJK0,55
74
+ pywebexec-2.2.2.dist-info/top_level.txt,sha256=vHoHyzngrfGdm_nM7Xn_5iLmaCrf10XO1EhldgNLEQ8,10
75
+ pywebexec-2.2.2.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (76.1.0)
2
+ Generator: setuptools (77.0.1)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5