pywebexec 1.6.15__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 -33
- pywebexec/version.py +2 -2
- {pywebexec-1.6.15.dist-info → pywebexec-1.6.17.dist-info}/METADATA +1 -1
- {pywebexec-1.6.15.dist-info → pywebexec-1.6.17.dist-info}/RECORD +8 -8
- {pywebexec-1.6.15.dist-info → pywebexec-1.6.17.dist-info}/LICENSE +0 -0
- {pywebexec-1.6.15.dist-info → pywebexec-1.6.17.dist-info}/WHEEL +0 -0
- {pywebexec-1.6.15.dist-info → pywebexec-1.6.17.dist-info}/entry_points.txt +0 -0
- {pywebexec-1.6.15.dist-info → pywebexec-1.6.17.dist-info}/top_level.txt +0 -0
pywebexec/pywebexec.py
CHANGED
@@ -180,15 +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, 1)
|
187
|
-
stream = pyte.Stream(screen)
|
188
|
-
stream.feed(line)
|
189
|
-
return screen.display[0].strip(" ")
|
190
|
-
except:
|
191
|
-
return ""
|
192
183
|
#38;2;66;59;165m
|
193
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])')
|
194
185
|
|
@@ -205,22 +196,34 @@ def decode_line(line: bytes) -> str:
|
|
205
196
|
return ""
|
206
197
|
|
207
198
|
|
208
|
-
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):
|
209
218
|
"""Retrieve last non empty line after vt100 interpretation"""
|
219
|
+
cols = cols or 125
|
220
|
+
rows = rows or 24
|
210
221
|
with open(file_path, 'rb') as fd:
|
211
222
|
try:
|
212
223
|
fd.seek(-maxsize, os.SEEK_END)
|
213
224
|
except OSError:
|
214
225
|
fd.seek(0)
|
215
|
-
|
216
|
-
if len(lines) == 1:
|
217
|
-
return ""
|
218
|
-
line = ""
|
219
|
-
while True:
|
220
|
-
line = decode_line(lines.pop())
|
221
|
-
if line or not lines:
|
222
|
-
break
|
223
|
-
return line
|
226
|
+
return get_visible_output(fd.read(), cols, rows)
|
224
227
|
|
225
228
|
|
226
229
|
def start_gunicorn(daemonized=False, baselog=None):
|
@@ -428,21 +431,16 @@ def get_output_file_path(command_id):
|
|
428
431
|
|
429
432
|
def update_command_status(command_id, updates):
|
430
433
|
status_file_path = get_status_file_path(command_id)
|
431
|
-
|
432
|
-
|
433
|
-
if
|
434
|
+
status = read_command_status(command_id) or {}
|
435
|
+
status.update(updates)
|
436
|
+
if status.get('status') != 'running':
|
434
437
|
output_file_path = get_output_file_path(command_id)
|
435
438
|
if os.path.exists(output_file_path):
|
436
|
-
|
439
|
+
status['last_output_line'] = get_last_line(output_file_path, status.get('cols'), status.get('rows'))
|
440
|
+
command_status_cache[command_id] = status
|
437
441
|
with open(status_file_path, 'w') as f:
|
438
|
-
json.dump(
|
442
|
+
json.dump(status, f)
|
439
443
|
|
440
|
-
# Update cache if status is not "running"
|
441
|
-
if status_data['status'] != 'running':
|
442
|
-
command_status_cache[command_id] = status_data
|
443
|
-
elif command_id in command_status_cache:
|
444
|
-
del command_status_cache[command_id]
|
445
|
-
|
446
444
|
def read_command_status(command_id):
|
447
445
|
# Return cached status if available
|
448
446
|
if command_id in command_status_cache:
|
@@ -572,13 +570,13 @@ def read_commands():
|
|
572
570
|
if status:
|
573
571
|
command = command_str(status.get('command', '-'), status.get('params', []))
|
574
572
|
last_line = status.get('last_output_line')
|
575
|
-
if
|
573
|
+
if status.get('status') == 'running':
|
576
574
|
output_file_path = get_output_file_path(command_id)
|
577
575
|
if os.path.exists(output_file_path):
|
578
|
-
last_line = get_last_line(output_file_path)
|
576
|
+
last_line = get_last_line(output_file_path, status.get('cols'), status.get('rows'))
|
579
577
|
commands.append({
|
580
578
|
'command_id': command_id,
|
581
|
-
'status': status
|
579
|
+
'status': status.get('status'),
|
582
580
|
'start_time': status.get('start_time', 'N/A'),
|
583
581
|
'end_time': status.get('end_time', 'N/A'),
|
584
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
|