pywebexec 2.3.4__py3-none-any.whl → 2.3.6__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
@@ -921,6 +921,8 @@ def run_dynamic_command(cmd):
921
921
  if value:
922
922
  params += f"{prefix} "
923
923
  continue
924
+ if prefix and not value: # skip empty params with prefix
925
+ continue
924
926
  if isinstance(value, dict) or convert_values.get(param, None) == "json":
925
927
  value = shlex.quote(json.dumps(value, indent=2, sort_keys=False))
926
928
  elif convert_values.get(param, None) == "quote":
@@ -9,6 +9,9 @@
9
9
  font-size: 14px;
10
10
  font-family: Arial, Helvetica, sans-serif;
11
11
 
12
+ div {
13
+ scrollbar-width: thin;
14
+ }
12
15
  .glyphicon-plus-sign:before {
13
16
  content: "\e081";
14
17
  }
@@ -123,6 +126,7 @@
123
126
  margin-top: 0px;
124
127
  margin-bottom: 1px;
125
128
  padding: 0;
129
+ padding-right: 10px;
126
130
  }
127
131
  input[type="checkbox"] {
128
132
  display: block;
@@ -148,6 +152,21 @@
148
152
  .controls input[type="text"] {
149
153
  width: 110px;;
150
154
  }
155
+
156
+ .controls > div:not([id]) { /* for checkboxes */
157
+ scrollbar-width: thin;
158
+ scrollbar-gutter: stable;
159
+ overflow-y: auto;
160
+ max-height: 100px;
161
+ border: solid 1px #ccc;
162
+ border-radius: 5px;
163
+ padding: 5px 2px;
164
+ }
165
+ .controls > div.range {
166
+ overflow-y: hidden;
167
+ padding: 0px 5px;
168
+ }
169
+
151
170
  input[type="number"] {
152
171
  max-width: 120px;
153
172
  text-align: right;
@@ -174,6 +193,7 @@
174
193
  font-family: Arial, Helvetica, sans-serif;
175
194
  font-size: 14px;
176
195
  box-sizing: border-box;
196
+ scrollbar-width: thin;
177
197
  }
178
198
  textarea:focus {
179
199
  border-color: #66afe9;
@@ -201,9 +221,13 @@
201
221
  ._jsonform-array-deletelast {
202
222
  display: none;
203
223
  }
204
- ._jsonform-array-buttons {
224
+ ul ~ ._jsonform-array-buttons {
205
225
  display: block;
206
226
  width: 100%;
227
+ }
228
+ ._jsonform-array-buttons {
229
+ /* display: block; */
230
+ /* width: 100%; */
207
231
  text-align: right;
208
232
  }
209
233
  i[title="Delete current"] {
@@ -237,6 +261,34 @@
237
261
  background-color: #f2dede;
238
262
  border-color: #ebccd1;
239
263
  }
264
+ #reset-form:hover {
265
+ background-color: #e8e8e8;
266
+ border-color: #adadad;
267
+ }
268
+ #reset-form {
269
+ position: relative;
270
+ margin-bottom: 10px;
271
+ height: 24px;
272
+ top: 20px;
273
+ background-color: #f5f5f5;
274
+ border-color: #ccc;
275
+ height: 24px;
276
+ color: #333;
277
+ padding: 3px 13px;
278
+ }
279
+ fieldset {
280
+ border: 1px solid #ccc;
281
+ border-radius: 5px;
282
+ padding-top: 9px;
283
+ width: 100%;
284
+ label {
285
+ padding-right: 5px;
286
+ }
287
+ }
288
+ fieldset > div {
289
+ /* display: block ruby; */
290
+ padding-bottom: 5px;
291
+ }
240
292
  }
241
293
 
242
294
  .swagger-ui textarea {
@@ -16,6 +16,9 @@ body {
16
16
  font-family: Arial, sans-serif;
17
17
  overflow: hidden;
18
18
  }
19
+ div {
20
+ scrollbar-width: thin;
21
+ }
19
22
  .table-container {
20
23
  height: 173px;
21
24
  overflow-y: auto;
@@ -53,7 +53,34 @@ function extractKeysAndPlaceholders(obj, formoptions, prefix = '') {
53
53
  return result;
54
54
  }
55
55
 
56
- // ...existing code...
56
+
57
+ // Convert objects to JSON strings where schema type is object without properties
58
+ function convertObjectsToJsonStrings(obj, schema, prefix = '') {
59
+ // Helper function to get schema type and check for properties
60
+ function getSchemaTypeForKey(schema, keyPath) {
61
+ const keys = keyPath.split('.');
62
+ let current = schema.properties;
63
+ for (const key of keys) {
64
+ if (!current || !current[key]) return null;
65
+ current = current[key];
66
+ }
67
+ return current;
68
+ }
69
+
70
+ for (const key in obj) {
71
+ const keyPath = prefix ? `${prefix}.${key}` : key;
72
+ const schemaType = getSchemaTypeForKey(schema, keyPath);
73
+
74
+ if (schemaType && schemaType.type === 'object' && !schemaType.properties) {
75
+ if (typeof obj[key] === 'object' && obj[key] !== null) {
76
+ obj[key] = JSON.stringify(obj[key], null, 2);
77
+ }
78
+ } else if (typeof obj[key] === 'object' && obj[key] !== null) {
79
+ convertObjectsToJsonStrings(obj[key], schema, keyPath);
80
+ }
81
+ }
82
+ }
83
+
57
84
 
58
85
  function convertTextareaToArray(values, formDesc, schema) {
59
86
  // Helper function to get schema type for a key path
@@ -107,6 +134,7 @@ function validateSchemaForm(form, formDesc, schema, values, schemaName) {
107
134
  err.style.display = 'none';
108
135
  return true;
109
136
  }
137
+
110
138
  function createSchemaForm($form, schema, onSubmit, schemaName) {
111
139
  if (schema && schema.schema_options) {
112
140
  schema_options = schema.schema_options;
@@ -151,6 +179,7 @@ function createSchemaForm($form, schema, onSubmit, schemaName) {
151
179
  }
152
180
  }
153
181
  }
182
+ convertObjectsToJsonStrings(value, schema);
154
183
  } else {
155
184
  value = {};
156
185
  }
@@ -205,8 +234,27 @@ function createSchemaForm($form, schema, onSubmit, schemaName) {
205
234
  }
206
235
  }
207
236
  formDesc.push({
208
- type: 'submit',
209
- title: 'Run',
237
+ type: 'actions',
238
+ items: [
239
+ {
240
+ type: 'submit',
241
+ title: 'Run',
242
+ id: 'run-form',
243
+ },
244
+ {
245
+ type: 'button',
246
+ title: 'Reset',
247
+ id: 'reset-form',
248
+ onClick: function (evt) {
249
+ console.log('reset');
250
+ evt.preventDefault();
251
+ evt.stopPropagation();
252
+ evt.stopImmediatePropagation();
253
+ schemaValues[schemaName] = {};
254
+ createSchemaForm($form, schema, onSubmit, schemaName);
255
+ },
256
+ },
257
+ ],
210
258
  });
211
259
  } else {
212
260
  if (schema_params_options && schema_params_options.batch_param) {
@@ -308,5 +356,3 @@ async function getPostParametersSchema() {
308
356
  let schemaForm;
309
357
  // let inputHandlers = [];
310
358
  let schemaValues = JSON.parse(localStorage.getItem('schemaValues')) || {};
311
-
312
-
@@ -222,10 +222,20 @@ async function fetchOutput(url) {
222
222
  fullOutput = fullOutput.slice(-maxSize);
223
223
 
224
224
  if (data.status != 'running') {
225
- const htmlContent = extractHtml(fullOutput);
226
- if (htmlContent) {
227
- document.getElementById('output').innerHTML = htmlContent;
228
- document.getElementById('output').classList.add('outputhtml');
225
+ if (data.status === 'success') {
226
+ const htmlContent = extractHtml(fullOutput);
227
+ if (htmlContent) {
228
+ document.getElementById('output').innerHTML = htmlContent;
229
+ document.getElementById('output').classList.add('outputhtml');
230
+ } else {
231
+ if (slider.value == 1000)
232
+ terminal.write(data.output);
233
+ else {
234
+ percentage = Math.round((outputLength * 1000)/fullOutput.length);
235
+ slider.value = percentage;
236
+ outputPercentage.innerText = `${Math.floor(percentage/10)}%`;
237
+ }
238
+ }
229
239
  } else {
230
240
  if (slider.value == 1000)
231
241
  terminal.write(data.output);
@@ -303,14 +313,18 @@ async function viewOutput(command_id) {
303
313
  const outputResponse = await fetch(nextOutputLink);
304
314
  const outputData = await outputResponse.json();
305
315
  const output = outputData.output;
306
- const htmlContent = extractHtml(output);
307
- if (htmlContent) {
308
- document.getElementById('output').innerHTML = htmlContent;
309
- document.getElementById('output').classList.add('outputhtml');
316
+ document.getElementById('output').classList.remove('outputhtml');
317
+ document.getElementById('output').innerHTML = '';
318
+ document.getElementById('output').appendChild(terminal.element);
319
+ if (data.status === 'success') {
320
+ const htmlContent = extractHtml(output);
321
+ if (htmlContent) {
322
+ document.getElementById('output').innerHTML = htmlContent;
323
+ document.getElementById('output').classList.add('outputhtml');
324
+ } else {
325
+ terminal.write(output);
326
+ }
310
327
  } else {
311
- document.getElementById('output').classList.remove('outputhtml');
312
- document.getElementById('output').innerHTML = '';
313
- document.getElementById('output').appendChild(terminal.element);
314
328
  terminal.write(output);
315
329
  }
316
330
  toggleButton.style.display = 'none';
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.3.4'
21
- __version_tuple__ = version_tuple = (2, 3, 4)
20
+ __version__ = version = '2.3.6'
21
+ __version_tuple__ = version_tuple = (2, 3, 6)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pywebexec
3
- Version: 2.3.4
3
+ Version: 2.3.6
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=oiCMlo2o3AkkgXDarUSx8T3FWXKI0vk1-EPnx5FGBd8,1332
3
- pywebexec/pywebexec.py,sha256=LD917ZeDVnOSMuLWPkl9JT1baaDvZ_e0Yk7RTs5yBfk,48273
3
+ pywebexec/pywebexec.py,sha256=1M5CtxKr5YkEMBhuVSrwnMNcVRuf7iQf-uxF4Lf0ouQ,48375
4
4
  pywebexec/swagger.yaml,sha256=I_oLpp7Hqel8SDEEykvpmCT-Gv3ytGlziq9bvQOrtZY,7598
5
- pywebexec/version.py,sha256=uwWN-nUjSdzfl2KBdAxl_KFIRtDM-6vnPwbujKx_J2g,511
6
- pywebexec/static/css/form.css,sha256=XC_0ES5yMHYz0S2OHR0RAboQN7fBUmg5ZIq8Qm5rHP0,5806
5
+ pywebexec/version.py,sha256=vyHreFbi5FOhiaz30HIVL3nIoqJd89y5l-gC9UA3AqA,511
6
+ pywebexec/static/css/form.css,sha256=YdhZw3B-UuXZCAuq9e3a8Wc9uP_2h0M3Et9ke3yhWww,6823
7
7
  pywebexec/static/css/markdown.css,sha256=br4-iK9wigTs54N2KHtjgZ4KLH0THVSvJo-XZAdMHiE,1970
8
- pywebexec/static/css/style.css,sha256=9P46lB-YLCYWRKIG58h_6Goj49ImAMxcWibh_uyrmDo,10308
8
+ pywebexec/static/css/style.css,sha256=pUmylXwbFIoXrdaJRVOUohlKIhOIilapH97NyIlgGV4,10343
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,8 +35,8 @@ 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=cTgCFHr_F9bFCirtfG_uR32vOY3vNUr4Ih3Wglj5lFc,11988
37
37
  pywebexec/static/js/popup.js,sha256=IaKmk2U2hEn-Nv6krf_PPW6LaG8NcpCkJKb7lUX0qZo,11457
38
- pywebexec/static/js/schemaform.js,sha256=NlFXFKJI53izxPXct3a5XiB1RhWGt0_EIp6o1HfsryU,9624
39
- pywebexec/static/js/script.js,sha256=Baj26fNeBV1_dFV3nqa75Y_B534M6D_3VALRxp6qeNo,20155
38
+ pywebexec/static/js/schemaform.js,sha256=57FeWNWJT1zW9sG3ujZEOG7vLoiHif5ROQZori2QNMg,11131
39
+ pywebexec/static/js/script.js,sha256=TI3TSylgBxh_a6QvYWlg4CyJ6LMPxnhFl8WRtRDGD0Y,20810
40
40
  pywebexec/static/js/swagger-form.js,sha256=CLcSHMhk5P4-_2MIRBoJLgEnIj_9keDDSzUugXHZjio,4565
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
@@ -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=MAPr-z96VERAecDvX37V8q2Nxph-O0fNDBul1x2w9SI,1147
70
- pywebexec-2.3.4.dist-info/licenses/LICENSE,sha256=gRJf0JPT_wsZJsUGlWPTS8Vypfl9vQ1qjp6sNbKykuA,1064
71
- pywebexec-2.3.4.dist-info/METADATA,sha256=h0SQW-btDQIC76B1kbUZc2M-PRX7wnQOyKWcHj1hf4Q,13015
72
- pywebexec-2.3.4.dist-info/WHEEL,sha256=DK49LOLCYiurdXXOXwGJm6U4DkHkg4lcxjhqwRa0CP4,91
73
- pywebexec-2.3.4.dist-info/entry_points.txt,sha256=l52GBkPCXRkmlHfEyoVauyfBdg8o-CAtC8qQpOIjJK0,55
74
- pywebexec-2.3.4.dist-info/top_level.txt,sha256=vHoHyzngrfGdm_nM7Xn_5iLmaCrf10XO1EhldgNLEQ8,10
75
- pywebexec-2.3.4.dist-info/RECORD,,
70
+ pywebexec-2.3.6.dist-info/licenses/LICENSE,sha256=gRJf0JPT_wsZJsUGlWPTS8Vypfl9vQ1qjp6sNbKykuA,1064
71
+ pywebexec-2.3.6.dist-info/METADATA,sha256=zV6Ic_s-W01Ng6h-PYSJKMbr3eK07j7tnmV3NBoR9b8,13015
72
+ pywebexec-2.3.6.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
73
+ pywebexec-2.3.6.dist-info/entry_points.txt,sha256=l52GBkPCXRkmlHfEyoVauyfBdg8o-CAtC8qQpOIjJK0,55
74
+ pywebexec-2.3.6.dist-info/top_level.txt,sha256=vHoHyzngrfGdm_nM7Xn_5iLmaCrf10XO1EhldgNLEQ8,10
75
+ pywebexec-2.3.6.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (78.0.2)
2
+ Generator: setuptools (78.1.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5