pywebexec 2.0.9__py3-none-any.whl → 2.0.11__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
@@ -358,7 +358,8 @@ def parseargs():
358
358
  parser.add_argument("-g", "--gencert", action="store_true", help="https server self signed cert")
359
359
  parser.add_argument("-T", "--tokenurl", action="store_true", help="generate safe url to access")
360
360
  parser.add_argument("action", nargs="?", help="daemon action start/stop/restart/status/shareterm/term",
361
- choices=["start","stop","restart","status","shareterm", "term"])
361
+ choices=["start","stop","restart","status","shareterm", "term", "run"])
362
+ parser.add_argument("command", nargs="*", help="command to run")
362
363
 
363
364
  args = parser.parse_args()
364
365
  if not os.path.exists(CONFDIR):
@@ -378,6 +379,12 @@ def parseargs():
378
379
  if args.action == "term":
379
380
  COMMAND_STATUS_DIR = f"{os.getcwd()}/{COMMAND_STATUS_DIR}"
380
381
  sys.exit(start_term())
382
+ elif args.action == "run":
383
+ command = args.command[0]
384
+ params = args.command[1:]
385
+ command_id = term_command_id
386
+ exit_code = run_command("localhost", args.user, command, params, command_id, tty_rows, tty_cols)
387
+ sys.exit(exit_code)
381
388
 
382
389
  (hostname, ip) = host_ip.get_host_ip(args.listen)
383
390
 
@@ -483,10 +490,14 @@ def run_command(fromip, user, command, params, command_id, rows, cols):
483
490
  # app.logger.info(f'{fromip} run_command {command_id} {user}: {command} {params}')
484
491
  log_info(fromip, user, f'run_command {command_id}: {command_str(command, params)}')
485
492
  start_time = datetime.now(timezone.utc).isoformat()
493
+ if user:
494
+ os.environ['PYWEBEXEC_USER'] = user
486
495
  update_command_status(command_id, {
487
496
  'command': command,
488
497
  'params': params,
489
498
  'start_time': start_time,
499
+ 'status': 'running',
500
+ 'from': fromip,
490
501
  'user': user,
491
502
  'cols': cols,
492
503
  'rows': rows,
@@ -539,7 +550,7 @@ def run_command(fromip, user, command, params, command_id, rows, cols):
539
550
  with open(get_output_file_path(command_id), 'a') as output_file:
540
551
  output_file.write(str(e))
541
552
  app.logger.error(fromip, user, f'Error running command {command_id}: {e}')
542
-
553
+ return exit_code
543
554
 
544
555
  def command_str(command, params):
545
556
  try:
@@ -603,12 +614,6 @@ def check_processes():
603
614
  'exit_code': -1,
604
615
  })
605
616
 
606
- args = parseargs()
607
- if args.cert:
608
- app.config['SESSION_COOKIE_SECURE'] = True
609
- app.config['TITLE'] = f"{args.title} API"
610
-
611
-
612
617
  def log_info(fromip, user, message):
613
618
  app.logger.info(f"{user} {fromip}: {message}")
614
619
 
@@ -618,6 +623,14 @@ def log_error(fromip, user, message):
618
623
  def log_request(message):
619
624
  log_info(request.remote_addr, session.get('username', '-'), message)
620
625
 
626
+
627
+ args = parseargs()
628
+ if args.cert:
629
+ app.config['SESSION_COOKIE_SECURE'] = True
630
+ app.config['TITLE'] = f"{args.title} API"
631
+
632
+
633
+
621
634
  def get_executable(cmd):
622
635
  if os.path.isfile(cmd) and os.access(cmd, os.X_OK):
623
636
  help_file = f"{cmd}.help"
@@ -8,152 +8,173 @@
8
8
  #schemaForm, .schema-form {
9
9
  font-size: 14px;
10
10
 
11
- .glyphicon-plus-sign:before {
12
- content: "\e081";
13
- }
14
- .glyphicon-minus-sign:before {
15
- content: "\e082";
16
- }
17
-
18
- .glyphicon {
19
- position: relative;
20
- top: 1px;
21
- display: inline-block;
22
- font-family: 'Glyphicons Halflings';
23
- font-style: normal;
24
- font-weight: normal;
25
- line-height: 1;
26
- -webkit-font-smoothing: antialiased;
27
- -moz-osx-font-smoothing: grayscale;
28
- }
11
+ .glyphicon-plus-sign:before {
12
+ content: "\e081";
13
+ }
14
+ .glyphicon-minus-sign:before {
15
+ content: "\e082";
16
+ }
29
17
 
30
- .btn {
31
- font-size: 14px;
32
- font-weight: normal;
33
- text-align: center;
34
- white-space: nowrap;
35
- cursor: pointer;
36
- padding: 3px 13px;
37
- border: 1px solid transparent;
38
- border-radius: 15px;
39
- font-family: Arial, Helvetica, sans-serif;
40
- }
41
- .btn-primary {
42
- position: relative;
43
- margin-bottom: 10px;
44
- height: 24px;
45
- top: 20px;
46
- color: #fff;
47
- background-color: #337ab7;
48
- border-color: #2e6da4;
49
- }
50
- .btn-primary:hover {
51
- background-color: #286090;
52
- border-color: #204d74;
53
- }
54
- .btn-default {
55
- background-color: transparent;
56
- padding: 3px 5px 2px 5px;
57
- color: #333;
58
- /* border: 1px solid #ccc; */
59
- /* color: #eee; */
60
- }
18
+ .glyphicon {
19
+ position: relative;
20
+ top: 1px;
21
+ display: inline-block;
22
+ font-family: 'Glyphicons Halflings';
23
+ font-style: normal;
24
+ font-weight: normal;
25
+ line-height: 1;
26
+ -webkit-font-smoothing: antialiased;
27
+ -moz-osx-font-smoothing: grayscale;
28
+ }
61
29
 
30
+ .btn {
31
+ font-size: 14px;
32
+ font-weight: normal;
33
+ text-align: center;
34
+ white-space: nowrap;
35
+ cursor: pointer;
36
+ padding: 3px 13px;
37
+ border: 1px solid transparent;
38
+ border-radius: 15px;
39
+ font-family: Arial, Helvetica, sans-serif;
40
+ }
41
+ .btn-primary {
42
+ position: relative;
43
+ margin-bottom: 10px;
44
+ height: 24px;
45
+ top: 20px;
46
+ color: #fff;
47
+ background-color: #337ab7;
48
+ border-color: #2e6da4;
49
+ }
50
+ .btn-primary:hover {
51
+ background-color: #286090;
52
+ border-color: #204d74;
53
+ }
54
+ .btn-default {
55
+ background-color: transparent;
56
+ padding: 3px 5px 2px 5px;
57
+ color: #333;
58
+ /* border: 1px solid #ccc; */
59
+ /* color: #eee; */
60
+ }
62
61
 
63
- /* Custom Style */
64
- .help-block {
65
- font-size: 12px;
66
- color: #808080;
67
- display: block;
68
- margin-top: 5px;
69
- margin-bottom: 10px;
70
- }
71
- .form-control {
72
- font-size: 14px;
73
- font-weight: normal;
74
- line-height: 1.42857143;
75
- color: #555;
76
- background-color: #fff;
77
- background-image: none;
78
- border: 1px solid #ccc;
79
- display: inline-block;
80
- width: auto;
81
- vertical-align: middle;
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
- box-sizing: border-box;
85
- padding: 3px 10px;
86
- height: 24px;
87
- border-radius: 15px;
88
- margin: 0;
89
- -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);
90
- box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);
91
- -webkit-transition: border-color ease-in-out .15s, -webkit-box-shadow ease-in-out .15s;
92
- -o-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;
93
- transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;
94
- }
95
- .form-control:focus {
96
- border-color: #66afe9;
97
- outline: 0;
98
- -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, .6);
99
- box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, .6);
100
- }
101
62
 
102
- .jsonform-required > label:after {
103
- content: ' *';
104
- color: red;
105
- }
106
- label {
107
- display: inline-block;
108
- max-width: 100%;
109
- margin-bottom: 5px;
110
- font-weight: bold;
111
- color: #444;
112
- margin-left: 5px;
113
- font-size: 14px;
114
- }
115
- .form-inline {
116
- align-items: unset;
117
- display: flex;
118
- flex-flow: wrap;
119
- gap: 10px;
120
- }
121
- .form-inline .checkbox {
122
- margin-top: 0px;
123
- margin-bottom: 1px;
124
- padding: 0;
125
- }
126
- input[type="checkbox"] {
127
- display: block;
128
- position: relative;
129
- margin: 0;
130
- top: 5px;
131
- }
132
- li > div > label {
133
- display: none;
134
- }
135
- ul {
136
- padding: 0;
137
- margin: 0;
138
- }
139
- li {
140
- display: flex;
141
- }
142
- input, select {
143
- min-width: unset;
144
- max-width: unset;
145
- width: auto;
146
- }
147
- input[type="number"] {
148
- max-width: 100px;
149
- text-align: right;
150
- }
151
- select {
152
- -webkit-appearance: auto;
153
- -moz-appearance: auto;
154
- appearance: auto;
155
- }
63
+ /* Custom Style */
64
+ .help-block {
65
+ font-size: 12px;
66
+ color: #808080;
67
+ display: block;
68
+ margin-top: 5px;
69
+ margin-bottom: 10px;
70
+ }
71
+ .form-control {
72
+ font-size: 14px;
73
+ font-weight: normal;
74
+ line-height: 1.42857143;
75
+ color: #555;
76
+ background-color: #fff;
77
+ background-image: none;
78
+ border: 1px solid #ccc;
79
+ display: inline-block;
80
+ width: auto;
81
+ vertical-align: middle;
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
+ box-sizing: border-box;
85
+ padding: 3px 10px;
86
+ height: 24px;
87
+ border-radius: 15px;
88
+ margin: 0;
89
+ -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);
90
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);
91
+ -webkit-transition: border-color ease-in-out .15s, -webkit-box-shadow ease-in-out .15s;
92
+ -o-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;
93
+ transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;
94
+ }
95
+ .form-control:focus {
96
+ border-color: #66afe9;
97
+ outline: 0;
98
+ -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, .6);
99
+ box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, .6);
100
+ }
156
101
 
102
+ .jsonform-required > label:after {
103
+ content: ' *';
104
+ color: red;
105
+ }
106
+ label {
107
+ display: inline-block;
108
+ max-width: 100%;
109
+ margin-bottom: 5px;
110
+ font-weight: bold;
111
+ color: #444;
112
+ margin-left: 5px;
113
+ font-size: 14px;
114
+ }
115
+ .form-inline {
116
+ align-items: unset;
117
+ display: flex;
118
+ flex-flow: wrap;
119
+ gap: 10px;
120
+ }
121
+ .form-inline .checkbox {
122
+ margin-top: 0px;
123
+ margin-bottom: 1px;
124
+ padding: 0;
125
+ }
126
+ input[type="checkbox"] {
127
+ display: block;
128
+ position: relative;
129
+ margin: 0;
130
+ top: 5px;
131
+ }
132
+ li > div > label {
133
+ display: none;
134
+ }
135
+ ul {
136
+ padding: 0;
137
+ margin: 0;
138
+ }
139
+ li {
140
+ display: flex;
141
+ }
142
+ input, select {
143
+ min-width: unset;
144
+ max-width: unset;
145
+ width: auto;
146
+ }
147
+ input[type="number"] {
148
+ max-width: 100px;
149
+ text-align: right;
150
+ }
151
+ select {
152
+ -webkit-appearance: auto;
153
+ -moz-appearance: auto;
154
+ appearance: auto;
155
+ }
156
+ textarea {
157
+ min-height: 24px;
158
+ max-height: 300px;
159
+ overflow-y: auto;
160
+ resize: vertical;
161
+ border-radius: 5px;
162
+ border: 1px solid #ccc;
163
+ padding: 3px;
164
+ margin: 0px;
165
+ width: unset;
166
+ line-height: 1.15;
167
+ font-weight: normal;
168
+ font-family: Arial, Helvetica, sans-serif;
169
+ font-size: 14px;
170
+ box-sizing: border-box;
171
+ }
172
+ textarea:focus {
173
+ border-color: #66afe9;
174
+ outline: 0;
175
+ -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, .6);
176
+ box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, .6);
177
+ }
157
178
  }
158
179
 
159
180
  .swagger-ui textarea {
@@ -440,6 +440,7 @@ body.dimmed * {
440
440
  text-overflow: ellipsis;
441
441
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
442
442
  font-size: 14px;
443
+ display: inline-block;
443
444
  }
444
445
 
445
446
  .nbrunning {
@@ -297,7 +297,7 @@ paramsInput.addEventListener('focus', () => {
297
297
  });
298
298
  setHelpDivPosition();
299
299
  paramsContainer.style.display = 'block';
300
- const input1 = schemaFormPW.querySelector('input[type="text"]');
300
+ const input1 = schemaFormPW.querySelector('input, select, textarea');
301
301
  if (input1) {
302
302
  input1.focus();
303
303
  }
@@ -54,6 +54,16 @@ function createSchemaForm(form, schema, onSubmit) {
54
54
  btn.addEventListener('click', formInputHandle);
55
55
  });
56
56
  formInputHandle();
57
+
58
+ form[0].querySelectorAll('textarea').forEach(txt => {
59
+ txt.style.height = "0";
60
+ txt.style.height = txt.scrollHeight + "px";
61
+ txt.addEventListener("input", (e) => {
62
+ e.target.style.height = "0";
63
+ e.target.style.height = (e.target.scrollHeight+2) + "px";
64
+ });
65
+ });
66
+
57
67
  return jsform;
58
68
  }
59
69
 
@@ -88,3 +98,5 @@ async function getPostParametersSchema() {
88
98
 
89
99
  let schemaForm;
90
100
  let inputHandlers = [];
101
+
102
+
@@ -92,7 +92,7 @@ window.onload = function() {
92
92
  // form.addEventListener("input", formInput(node, jsform));
93
93
  form.addEventListener("input", addFormInputListener(node, jsform));
94
94
  node.parentNode.insertBefore(form, node.nextSibling);
95
- item1 = form.querySelector("input, select");
95
+ item1 = form.querySelector("input, select, textarea");
96
96
  if (item1) {
97
97
  item1.focus();
98
98
  }
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.9'
21
- __version_tuple__ = version_tuple = (2, 0, 9)
20
+ __version__ = version = '2.0.11'
21
+ __version_tuple__ = version_tuple = (2, 0, 11)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: pywebexec
3
- Version: 2.0.9
3
+ Version: 2.0.11
4
4
  Summary: Simple Python HTTP Exec Server
5
5
  Home-page: https://github.com/joknarf/pywebexec
6
6
  Author: Franck Jouvanceau
@@ -60,6 +60,7 @@ Requires-Dist: pexpect>=4.9.0
60
60
  Requires-Dist: gunicorn>=21.2.0
61
61
  Requires-Dist: ldap3>=2.9.1
62
62
  Requires-Dist: pyte>=0.8.1
63
+ Requires-Dist: PyYAML>=6.0.1
63
64
 
64
65
  [![Pypi version](https://img.shields.io/pypi/v/pywebexec.svg)](https://pypi.org/project/pywebexec/)
65
66
  ![Publish Package](https://github.com/joknarf/pywebexec/actions/workflows/python-publish.yml/badge.svg)
@@ -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=bC9mOWBsOEVX_70BfJl6tF-4T0tm2WXcBvxcLprN4rw,40738
3
+ pywebexec/pywebexec.py,sha256=7lSu1C5BBA1dGzVnDG3uFcYrNriPzOs2xJrjvpOMmP4,41219
4
4
  pywebexec/swagger.yaml,sha256=j-KZnU4rGR-Fsk8y_EbqYzqVgtAZ8EjZIKAqZSxyyc0,5858
5
- pywebexec/version.py,sha256=3Hw94mCihPHQHp2v84oiOR-GC2moriN-S3C3Yu8rLmU,511
6
- pywebexec/static/css/form.css,sha256=qYbZM-3vPszy4nRHroejvUwFuGtEbP1v4IhYlKOu0VU,3598
5
+ pywebexec/version.py,sha256=ezqxaA_NJjcV2_xyyCKbUv0Hzhb-fF2wEhuUihfV7qo,513
6
+ pywebexec/static/css/form.css,sha256=FSSFfw_-w4Yb9jUlXmgpLhXQsJj--vI2IyEY99tGvHA,4480
7
7
  pywebexec/static/css/markdown.css,sha256=3RzUnpVBdF6cQuB_NXV7hMTc0quYU8sfyuZcpsREj6A,1939
8
- pywebexec/static/css/style.css,sha256=UGkHGA2z_25kUAiamfzxz0IfZBt8y0zsGMR13Kp6R9I,9809
8
+ pywebexec/static/css/style.css,sha256=KmHUDRwl-d-DE15-RmzY3PqPITIUnupVdiTKXUCZ5IY,9834
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
@@ -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=iltgIJXWVUxAUhBfXGCHSP8mK8cQdtg-AagbGe7Hv9o,11762
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=bd874Geg9vri1c_seUGVynxZswGb5IcyWLZxYlcryCA,2784
38
+ pywebexec/static/js/schemaform.js,sha256=U19pjVht7XwaSKojxwABZyJ98HvVn1LaK9SLsTlwT70,3096
39
39
  pywebexec/static/js/script.js,sha256=fwTo9Iz4xsl6wGs-Nm8-Ng8aXzDfvews5cHfzhSfg_0,17987
40
- pywebexec/static/js/swagger-form.js,sha256=mreGChUkous8mqizrozDEMb2Tw5HBvwZ2N6k0CuaF4U,3796
40
+ pywebexec/static/js/swagger-form.js,sha256=uTRGKrcyBqq910RLmdlV-HpFri3RaAXpqUPSQSyoe6o,3806
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
@@ -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.9.dist-info/LICENSE,sha256=gRJf0JPT_wsZJsUGlWPTS8Vypfl9vQ1qjp6sNbKykuA,1064
70
- pywebexec-2.0.9.dist-info/METADATA,sha256=QncOMIqrewgqpi_vwc8u9ld1SNr0iYm5u8ZSorD_9rE,11615
71
- pywebexec-2.0.9.dist-info/WHEEL,sha256=52BFRY2Up02UkjOa29eZOS2VxUrpPORXg1pkohGGUS8,91
72
- pywebexec-2.0.9.dist-info/entry_points.txt,sha256=l52GBkPCXRkmlHfEyoVauyfBdg8o-CAtC8qQpOIjJK0,55
73
- pywebexec-2.0.9.dist-info/top_level.txt,sha256=vHoHyzngrfGdm_nM7Xn_5iLmaCrf10XO1EhldgNLEQ8,10
74
- pywebexec-2.0.9.dist-info/RECORD,,
69
+ pywebexec-2.0.11.dist-info/LICENSE,sha256=gRJf0JPT_wsZJsUGlWPTS8Vypfl9vQ1qjp6sNbKykuA,1064
70
+ pywebexec-2.0.11.dist-info/METADATA,sha256=iaooCY4aWcnRzcPZoI2dp0GKidIMoGxU0Evn6d38OpA,11645
71
+ pywebexec-2.0.11.dist-info/WHEEL,sha256=52BFRY2Up02UkjOa29eZOS2VxUrpPORXg1pkohGGUS8,91
72
+ pywebexec-2.0.11.dist-info/entry_points.txt,sha256=l52GBkPCXRkmlHfEyoVauyfBdg8o-CAtC8qQpOIjJK0,55
73
+ pywebexec-2.0.11.dist-info/top_level.txt,sha256=vHoHyzngrfGdm_nM7Xn_5iLmaCrf10XO1EhldgNLEQ8,10
74
+ pywebexec-2.0.11.dist-info/RECORD,,