pywebexec 1.6.12__py3-none-any.whl → 1.6.14__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 +27 -34
- pywebexec/version.py +2 -2
- {pywebexec-1.6.12.dist-info → pywebexec-1.6.14.dist-info}/METADATA +1 -1
- {pywebexec-1.6.12.dist-info → pywebexec-1.6.14.dist-info}/RECORD +8 -8
- {pywebexec-1.6.12.dist-info → pywebexec-1.6.14.dist-info}/LICENSE +0 -0
- {pywebexec-1.6.12.dist-info → pywebexec-1.6.14.dist-info}/WHEEL +0 -0
- {pywebexec-1.6.12.dist-info → pywebexec-1.6.14.dist-info}/entry_points.txt +0 -0
- {pywebexec-1.6.12.dist-info → pywebexec-1.6.14.dist-info}/top_level.txt +0 -0
pywebexec/pywebexec.py
CHANGED
@@ -182,11 +182,16 @@ class PyWebExec(Application):
|
|
182
182
|
return self.application
|
183
183
|
|
184
184
|
def get_visible_output(line):
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
185
|
+
try:
|
186
|
+
screen = pyte.Screen(len(line)+1, 2)
|
187
|
+
stream = pyte.Stream(screen)
|
188
|
+
stream.feed(line)
|
189
|
+
visible_line = screen.display[1].strip(" ")
|
190
|
+
if visible_line:
|
191
|
+
return visible_line
|
192
|
+
return screen.display[0].strip(" ")
|
193
|
+
except:
|
194
|
+
return ""
|
190
195
|
#38;2;66;59;165m
|
191
196
|
ANSI_ESCAPE = re.compile(br'(?:\x1B[@-Z\\-_]|\x1B([(]B|>)|(?:\x1B\[|\x9B)[0-?]*[ -/]*[@-~]|\x1B\[([0-9]{1,2};){0,4}[0-9]{1,3}[m|K]|\x1B\[[0-9;]*[mGKHF]|[\x00-\x1F\x7F])')
|
192
197
|
|
@@ -198,39 +203,27 @@ def strip_ansi_control_chars(text):
|
|
198
203
|
def decode_line(line: bytes) -> str:
|
199
204
|
"""try decode line exception on binary"""
|
200
205
|
try:
|
201
|
-
return get_visible_output(line.decode())
|
206
|
+
return get_visible_output(line.decode())
|
202
207
|
except UnicodeDecodeError:
|
203
208
|
return ""
|
204
209
|
|
205
210
|
|
206
|
-
def
|
207
|
-
"""last non empty line
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
last_pos = 0
|
212
|
-
while line in ["", "\n", "\r"] and size < maxsize:
|
213
|
-
try: # catch if file empty / only empty lines
|
214
|
-
if last_pos:
|
215
|
-
fd.seek(last_pos-2, os.SEEK_SET)
|
216
|
-
while fd.read(1) not in [b"\n", b"\r"] and size < maxsize:
|
217
|
-
fd.seek(-2, os.SEEK_CUR)
|
218
|
-
size += 1
|
211
|
+
def get_last_line(file_path, maxsize=1024):
|
212
|
+
"""Retrieve last non empty line after vt100 interpretation"""
|
213
|
+
with open(file_path, 'rb') as fd:
|
214
|
+
try:
|
215
|
+
fd.seek(-maxsize, os.SEEK_END)
|
219
216
|
except OSError:
|
220
217
|
fd.seek(0)
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
line =
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
def get_last_non_empty_line_of_file(file_path):
|
231
|
-
"""Get the last non-empty line of a file."""
|
232
|
-
with open(file_path, 'rb') as f:
|
233
|
-
return last_line(f)
|
218
|
+
lines = fd.read().split(b"\n")
|
219
|
+
if len(lines) == 1:
|
220
|
+
return ""
|
221
|
+
line = ""
|
222
|
+
while True:
|
223
|
+
line = decode_line(lines.pop())
|
224
|
+
if line or not lines:
|
225
|
+
break
|
226
|
+
return line
|
234
227
|
|
235
228
|
|
236
229
|
def start_gunicorn(daemonized=False, baselog=None):
|
@@ -443,7 +436,7 @@ def update_command_status(command_id, updates):
|
|
443
436
|
if status_data['status'] != 'running':
|
444
437
|
output_file_path = get_output_file_path(command_id)
|
445
438
|
if os.path.exists(output_file_path):
|
446
|
-
status_data['last_output_line'] =
|
439
|
+
status_data['last_output_line'] = get_last_line(output_file_path)
|
447
440
|
with open(status_file_path, 'w') as f:
|
448
441
|
json.dump(status_data, f)
|
449
442
|
|
@@ -585,7 +578,7 @@ def read_commands():
|
|
585
578
|
if last_line is None:
|
586
579
|
output_file_path = get_output_file_path(command_id)
|
587
580
|
if os.path.exists(output_file_path):
|
588
|
-
last_line =
|
581
|
+
last_line = get_last_line(output_file_path)
|
589
582
|
commands.append({
|
590
583
|
'command_id': command_id,
|
591
584
|
'status': status['status'],
|
pywebexec/version.py
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
pywebexec/__init__.py,sha256=4spIsVaF8RJt8S58AG_wWoORRNkws9Iwqprj27C3ljM,99
|
2
|
-
pywebexec/pywebexec.py,sha256=
|
3
|
-
pywebexec/version.py,sha256=
|
2
|
+
pywebexec/pywebexec.py,sha256=bfE0QBiErt3k5GCsobOLZOP5OT6JJs-39GvLkzWqnB0,32650
|
3
|
+
pywebexec/version.py,sha256=ENoeph2R-6hTwDBnYv-6HGbXQQBxCuxRZdUsEOyJGbk,413
|
4
4
|
pywebexec/static/css/Consolas NF.ttf,sha256=DJEOzF0eqZ-kxu3Gs_VE8X0NJqiobBzmxWDGpdgGRxI,1313900
|
5
5
|
pywebexec/static/css/style.css,sha256=MJHUBpjWL4sLxM7a7DxypmPKaFJQbmA_ESNXsbLviNI,8201
|
6
6
|
pywebexec/static/css/xterm.css,sha256=uo5phWaUiJgcz0DAzv46uoByLLbJLeetYosL1xf68rY,5559
|
@@ -33,9 +33,9 @@ pywebexec/static/js/xterm/xterm.js.map,sha256=Y7O2Pb-fIS7Z8AC1D5s04_aiW_Jf1f4mCf
|
|
33
33
|
pywebexec/templates/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
34
34
|
pywebexec/templates/index.html,sha256=5h8kLyzAhbvUDU9sEwrGIvD6FxAMcDZLXlN-ldlO8KU,2880
|
35
35
|
pywebexec/templates/popup.html,sha256=3ZqQcE9mYs-RXv0Lfb24zntOlvR137ZYI9mtCZNVAo0,1407
|
36
|
-
pywebexec-1.6.
|
37
|
-
pywebexec-1.6.
|
38
|
-
pywebexec-1.6.
|
39
|
-
pywebexec-1.6.
|
40
|
-
pywebexec-1.6.
|
41
|
-
pywebexec-1.6.
|
36
|
+
pywebexec-1.6.14.dist-info/LICENSE,sha256=gRJf0JPT_wsZJsUGlWPTS8Vypfl9vQ1qjp6sNbKykuA,1064
|
37
|
+
pywebexec-1.6.14.dist-info/METADATA,sha256=tX1rKBNoJV44ISefvftWsla6GhI87vX8ISlpCu-q3Cc,8001
|
38
|
+
pywebexec-1.6.14.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
|
39
|
+
pywebexec-1.6.14.dist-info/entry_points.txt,sha256=l52GBkPCXRkmlHfEyoVauyfBdg8o-CAtC8qQpOIjJK0,55
|
40
|
+
pywebexec-1.6.14.dist-info/top_level.txt,sha256=vHoHyzngrfGdm_nM7Xn_5iLmaCrf10XO1EhldgNLEQ8,10
|
41
|
+
pywebexec-1.6.14.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|