pywebexec 1.6.16__py3-none-any.whl → 1.6.17__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 +31 -36
- pywebexec/version.py +2 -2
- {pywebexec-1.6.16.dist-info → pywebexec-1.6.17.dist-info}/METADATA +1 -1
- {pywebexec-1.6.16.dist-info → pywebexec-1.6.17.dist-info}/RECORD +8 -8
- {pywebexec-1.6.16.dist-info → pywebexec-1.6.17.dist-info}/LICENSE +0 -0
- {pywebexec-1.6.16.dist-info → pywebexec-1.6.17.dist-info}/WHEEL +0 -0
- {pywebexec-1.6.16.dist-info → pywebexec-1.6.17.dist-info}/entry_points.txt +0 -0
- {pywebexec-1.6.16.dist-info → pywebexec-1.6.17.dist-info}/top_level.txt +0 -0
pywebexec/pywebexec.py
CHANGED
@@ -180,18 +180,6 @@ class PyWebExec(Application):
|
|
180
180
|
|
181
181
|
def load(self):
|
182
182
|
return self.application
|
183
|
-
|
184
|
-
def get_visible_output(line):
|
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 ""
|
195
183
|
#38;2;66;59;165m
|
196
184
|
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])')
|
197
185
|
|
@@ -208,22 +196,34 @@ def decode_line(line: bytes) -> str:
|
|
208
196
|
return ""
|
209
197
|
|
210
198
|
|
211
|
-
def
|
199
|
+
def get_visible_output(line, cols, rows):
|
200
|
+
"""pyte vt100 render to get last line"""
|
201
|
+
try:
|
202
|
+
screen = pyte.Screen(cols, rows)
|
203
|
+
stream = pyte.ByteStream(screen)
|
204
|
+
stream.feed(line)
|
205
|
+
visible_line = ""
|
206
|
+
row = rows - 1
|
207
|
+
while row > 0:
|
208
|
+
visible_line = screen.display[row].strip(" ")
|
209
|
+
if visible_line:
|
210
|
+
return visible_line
|
211
|
+
row -= 1
|
212
|
+
except:
|
213
|
+
return ""
|
214
|
+
return ""
|
215
|
+
|
216
|
+
|
217
|
+
def get_last_line(file_path, cols=None, rows=None, maxsize=2048):
|
212
218
|
"""Retrieve last non empty line after vt100 interpretation"""
|
219
|
+
cols = cols or 125
|
220
|
+
rows = rows or 24
|
213
221
|
with open(file_path, 'rb') as fd:
|
214
222
|
try:
|
215
223
|
fd.seek(-maxsize, os.SEEK_END)
|
216
224
|
except OSError:
|
217
225
|
fd.seek(0)
|
218
|
-
|
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
|
226
|
+
return get_visible_output(fd.read(), cols, rows)
|
227
227
|
|
228
228
|
|
229
229
|
def start_gunicorn(daemonized=False, baselog=None):
|
@@ -431,21 +431,16 @@ def get_output_file_path(command_id):
|
|
431
431
|
|
432
432
|
def update_command_status(command_id, updates):
|
433
433
|
status_file_path = get_status_file_path(command_id)
|
434
|
-
|
435
|
-
|
436
|
-
if
|
434
|
+
status = read_command_status(command_id) or {}
|
435
|
+
status.update(updates)
|
436
|
+
if status.get('status') != 'running':
|
437
437
|
output_file_path = get_output_file_path(command_id)
|
438
438
|
if os.path.exists(output_file_path):
|
439
|
-
|
439
|
+
status['last_output_line'] = get_last_line(output_file_path, status.get('cols'), status.get('rows'))
|
440
|
+
command_status_cache[command_id] = status
|
440
441
|
with open(status_file_path, 'w') as f:
|
441
|
-
json.dump(
|
442
|
+
json.dump(status, f)
|
442
443
|
|
443
|
-
# Update cache if status is not "running"
|
444
|
-
if status_data['status'] != 'running':
|
445
|
-
command_status_cache[command_id] = status_data
|
446
|
-
elif command_id in command_status_cache:
|
447
|
-
del command_status_cache[command_id]
|
448
|
-
|
449
444
|
def read_command_status(command_id):
|
450
445
|
# Return cached status if available
|
451
446
|
if command_id in command_status_cache:
|
@@ -575,13 +570,13 @@ def read_commands():
|
|
575
570
|
if status:
|
576
571
|
command = command_str(status.get('command', '-'), status.get('params', []))
|
577
572
|
last_line = status.get('last_output_line')
|
578
|
-
if
|
573
|
+
if status.get('status') == 'running':
|
579
574
|
output_file_path = get_output_file_path(command_id)
|
580
575
|
if os.path.exists(output_file_path):
|
581
|
-
last_line = get_last_line(output_file_path)
|
576
|
+
last_line = get_last_line(output_file_path, status.get('cols'), status.get('rows'))
|
582
577
|
commands.append({
|
583
578
|
'command_id': command_id,
|
584
|
-
'status': status
|
579
|
+
'status': status.get('status'),
|
585
580
|
'start_time': status.get('start_time', 'N/A'),
|
586
581
|
'end_time': status.get('end_time', 'N/A'),
|
587
582
|
'command': command,
|
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=mCNUbnttBIloCVmVl3jRuqA3kE6K9SlYLlDEAHb-dL0,32556
|
3
|
+
pywebexec/version.py,sha256=bUNPwAsnC5Y4wwmtKw5lZfH0PuKwJg_38vSI9Pv11Qo,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.17.dist-info/LICENSE,sha256=gRJf0JPT_wsZJsUGlWPTS8Vypfl9vQ1qjp6sNbKykuA,1064
|
37
|
+
pywebexec-1.6.17.dist-info/METADATA,sha256=WOoqeA6-jB64mcwinFFIrJatxvesYYJAhXruiXmf0rA,8001
|
38
|
+
pywebexec-1.6.17.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
|
39
|
+
pywebexec-1.6.17.dist-info/entry_points.txt,sha256=l52GBkPCXRkmlHfEyoVauyfBdg8o-CAtC8qQpOIjJK0,55
|
40
|
+
pywebexec-1.6.17.dist-info/top_level.txt,sha256=vHoHyzngrfGdm_nM7Xn_5iLmaCrf10XO1EhldgNLEQ8,10
|
41
|
+
pywebexec-1.6.17.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|