pywebexec 1.7.1__py3-none-any.whl → 1.7.2__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
@@ -56,6 +56,8 @@ if os.path.isdir(f"{CONFDIR}/.config"):
56
56
  CONFDIR += '/.config'
57
57
  CONFDIR += "/.pywebexec"
58
58
  term_command_id = str(uuid.uuid4())
59
+ tty_cols = 125
60
+ tty_rows = 30
59
61
 
60
62
  # In-memory cache for command statuses
61
63
  status_cache = {}
@@ -181,6 +183,8 @@ class PyWebExec(Application):
181
183
  return self.application
182
184
  #38;2;66;59;165m
183
185
  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])')
186
+ 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])')
187
+ ANSI_ESCAPE = re.compile(br'(\x1B\[([0-9]{1,2};){0,4}[0-9]{1,3}[m|K]|\x1B\[[0-9;]*[mGKHF])')
184
188
 
185
189
  def strip_ansi_control_chars(text):
186
190
  """Remove ANSI and control characters from the text."""
@@ -202,12 +206,10 @@ def get_visible_output(line, cols, rows):
202
206
  stream = pyte.ByteStream(screen)
203
207
  stream.feed(line)
204
208
  visible_line = ""
205
- row = rows - 1
206
- while row > 0:
207
- visible_line = screen.display[row].strip(" ")
209
+ for visible_line in reversed(screen.display):
210
+ visible_line = visible_line.strip(" ")
208
211
  if visible_line:
209
212
  return visible_line
210
- row -= 1
211
213
  except:
212
214
  return ""
213
215
  return ""
@@ -215,8 +217,8 @@ def get_visible_output(line, cols, rows):
215
217
 
216
218
  def get_last_line(file_path, cols=None, rows=None, maxsize=2048):
217
219
  """Retrieve last non empty line after vt100 interpretation"""
218
- cols = cols or 125
219
- rows = rows or 24
220
+ cols = cols or tty_cols
221
+ rows = rows or tty_rows
220
222
  with open(file_path, 'rb') as fd:
221
223
  try:
222
224
  fd.seek(-maxsize, os.SEEK_END)
@@ -429,9 +431,6 @@ def get_status_file_path(command_id):
429
431
  def get_output_file_path(command_id):
430
432
  return os.path.join(COMMAND_STATUS_DIR, f'{command_id}_output.txt')
431
433
 
432
- def get_done_file_path(command_id):
433
- return os.path.join(COMMAND_STATUS_DIR, f'{command_id}.done')
434
-
435
434
  def update_command_status(command_id, updates):
436
435
  status_file_path = get_status_file_path(command_id)
437
436
  status = read_command_status(command_id) or {}
@@ -443,8 +442,6 @@ def update_command_status(command_id, updates):
443
442
  status_cache[command_id] = status
444
443
  with open(status_file_path, 'w') as f:
445
444
  json.dump(status, f)
446
- if status.get('status') != 'running':
447
- open(get_done_file_path(command_id), 'a').close()
448
445
 
449
446
 
450
447
  def read_command_status(command_id):
@@ -455,7 +452,7 @@ def read_command_status(command_id):
455
452
  status = status_data.get('status')
456
453
  if status and status != "running":
457
454
  return status_data
458
- if command_id in status_cache and not os.path.exists(get_done_file_path(command_id)):
455
+ if command_id in status_cache and status_cache.get('last_read',0)>datetime.now().timestamp()-0.5:
459
456
  return status_data
460
457
  status_file_path = get_status_file_path(command_id)
461
458
  if not os.path.exists(status_file_path):
@@ -465,6 +462,7 @@ def read_command_status(command_id):
465
462
  status_data.update(json.load(f))
466
463
  except json.JSONDecodeError:
467
464
  return None
465
+ status_data['last_read'] = datetime.now().timestamp()
468
466
  status_cache[command_id] = status_data
469
467
  return status_data
470
468
 
@@ -501,18 +499,19 @@ def run_command(fromip, user, command, params, command_id):
501
499
  'command': command,
502
500
  'params': params,
503
501
  'start_time': start_time,
504
- 'user': user
502
+ 'user': user,
503
+ 'cols': tty_cols,
504
+ 'rows': tty_rows,
505
505
  })
506
506
  output_file_path = get_output_file_path(command_id)
507
507
  try:
508
508
  with open(output_file_path, 'wb') as fd:
509
- p = pexpect.spawn(command, params, ignore_sighup=True, timeout=None)
509
+ p = pexpect.spawn(command, params, ignore_sighup=True, timeout=None, dimensions=(tty_rows, tty_cols))
510
510
  update_command_status(command_id, {
511
511
  'status': 'running',
512
512
  'pid': p.pid,
513
513
  'user': user
514
514
  })
515
- p.setwinsize(24, 125)
516
515
  p.logfile = fd
517
516
  p.expect(pexpect.EOF)
518
517
  fd.flush()
@@ -798,6 +797,7 @@ def get_command_output(command_id):
798
797
  'output': output[-maxsize:],
799
798
  'status': status_data.get("status"),
800
799
  'cols': status_data.get("cols"),
800
+ 'rows': status_data.get("rows"),
801
801
  'links': {
802
802
  'next': f'{request.url_root}command_output/{command_id}?offset={new_offset}&maxsize={maxsize}{token_param}'
803
803
  }
@@ -48,7 +48,6 @@ select { /* Safari bug */
48
48
  min-width: 150px;
49
49
  }
50
50
  .output {
51
- white-space: pre-wrap;
52
51
  background: #111;
53
52
  padding: 10px;
54
53
  border: 1px solid #ccc;
@@ -329,20 +328,18 @@ span {
329
328
 
330
329
  .pause {
331
330
  background-image: url("/static/images/pause.svg");
332
- /*background-size: contain;*/
333
- background-repeat: no-repeat;
334
- background-position: center;
335
- background-size: 24px 24px;
336
331
  }
337
332
  .resume {
338
333
  background-image: url("/static/images/resume.svg");
339
- /*background-size: contain;*/
340
- background-repeat: no-repeat;
341
- background-position: center;
342
- background-size: 24px 24px;
343
334
  }
344
335
 
345
- .pause-resume-button {
336
+ .fit-window {
337
+ background-image: url("/static/images/fit-win.svg");
338
+ }
339
+ .fit-tty {
340
+ background-image: url("/static/images/fit-tty.svg");
341
+ }
342
+ .pause-resume-button, .fit-button {
346
343
  background-color: transparent;
347
344
  border: none;
348
345
  /*padding: 0;*/
@@ -350,6 +347,10 @@ span {
350
347
  height: 24px;
351
348
  cursor: pointer;
352
349
  flex-shrink: 0;
350
+ background-repeat: no-repeat;
351
+ background-position: center;
352
+ background-size: 24px 24px;
353
+
353
354
  }
354
355
 
355
356
 
@@ -389,4 +390,8 @@ span {
389
390
  border-radius: 17px;
390
391
  min-width: 17px;
391
392
  text-align: center;
393
+ }
394
+
395
+ .xterm-accessibility {
396
+ display: none;
392
397
  }
@@ -0,0 +1 @@
1
+ <svg height="200px" width="200px" version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="-42.63 -42.63 558.91 558.91" xml:space="preserve" fill="#000000"><g id="SVGRepo_bgCarrier" stroke-width="0"></g><g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round"></g><g id="SVGRepo_iconCarrier"> <circle style="fill:#404040;" cx="236.827" cy="236.827" r="236.827"></circle> <g> <path style="fill:#FFFFFF;" d="M421.487,220.971c-32.306,0-64.612,0-96.919,0c10.033-10.033,20.07-20.067,30.104-30.1 c12.782-12.778-7.128-32.538-19.939-19.726c-17.999,17.995-35.993,35.99-53.992,53.984c-5.422,5.419-5.277,14.453,0.105,19.835 c17.999,17.999,35.993,35.993,53.992,53.992c12.782,12.782,32.542-7.128,19.726-19.939c-9.996-9.996-19.992-19.992-29.988-29.988 c32.235,0,64.47,0,96.705,0C439.396,249.026,439.557,220.971,421.487,220.971z"></path> <path style="fill:#FFFFFF;" d="M193.011,225.021c-17.999-17.999-35.993-35.99-53.992-53.984 c-12.782-12.782-32.542,7.128-19.726,19.939c10,10,19.999,19.995,29.995,29.995c-32.239,0-64.474,0-96.713,0 c-18.111,0-18.272,28.054-0.202,28.054c32.302,0,64.601,0,96.904,0c-10.03,10.033-20.063,20.059-30.092,30.092 c-12.782,12.782,7.128,32.542,19.939,19.726c17.999-17.999,35.993-35.993,53.992-53.992 C198.541,239.434,198.396,230.399,193.011,225.021z"></path> <circle style="fill:#FFFFFF;" cx="236.827" cy="236.79" r="24.098"></circle> </g> </g></svg>
@@ -0,0 +1 @@
1
+ <svg height="200px" width="200px" version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="-42.63 -42.63 558.91 558.91" xml:space="preserve" fill="#000000"><g id="SVGRepo_bgCarrier" stroke-width="0"></g><g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round"></g><g id="SVGRepo_iconCarrier"> <circle style="fill:#404040;" cx="236.827" cy="236.827" r="236.827"></circle> <g> <path style="fill:#FFFFFF;" d="M431.251,225.029c-17.999-17.999-35.993-36.001-53.992-53.996 c-12.778-12.782-32.542,7.128-19.726,19.939c9.996,10,19.992,19.995,29.991,29.995c-32.235,0-64.474,0-96.709,0 c-18.111,0-18.272,28.054-0.202,28.054c32.306,0,64.612,0,96.919,0c-10.033,10.033-20.07,20.067-30.104,30.1 c-12.782,12.778,7.128,32.538,19.939,19.726c17.999-17.995,35.993-35.99,53.992-53.984 C436.782,239.437,436.633,230.406,431.251,225.029z"></path> <path style="fill:#FFFFFF;" d="M183.247,220.964c-32.302,0-64.605,0-96.907,0c10.033-10.033,20.063-20.067,30.096-30.1 c12.782-12.782-7.128-32.542-19.939-19.726c-17.999,17.999-35.993,35.997-53.992,53.996c-5.422,5.422-5.277,14.453,0.105,19.835 c17.999,17.999,35.993,35.99,53.992,53.984c12.782,12.782,32.542-7.128,19.726-19.939c-10-10-19.999-19.996-29.995-29.995 c32.239,0,64.474,0,96.713,0C201.155,249.018,201.316,220.964,183.247,220.964z"></path> <circle style="fill:#FFFFFF;" cx="236.827" cy="236.79" r="24.098"></circle> </g> </g></svg>
@@ -75,8 +75,30 @@ let fullOutput = '';
75
75
  let outputLength = 0;
76
76
  let slider = null;
77
77
  let isPaused = false;
78
+ let cols = 0;
79
+ let rows = 0;
80
+ let fitWindow = false;
81
+
78
82
  const toggleButton = document.getElementById('toggleFetch');
79
83
  const pausedMessage = document.getElementById('pausedMessage');
84
+ const toggleFitButton = document.getElementById('toggleFit');
85
+
86
+ function autoFit(scroll=true) {
87
+ // Scroll output div to bottom
88
+ const outputDiv = document.getElementById('output');
89
+ outputDiv.scrollTop = terminal.element.clientHeight - outputDiv.clientHeight + 20;
90
+ if (cols && !fitWindow) {
91
+ let fit = fitAddon.proposeDimensions();
92
+ if (fit.rows < rows) {
93
+ terminal.resize(cols, rows);
94
+ } else {
95
+ terminal.resize(cols, fit.rows);
96
+ }
97
+ } else {
98
+ fitAddon.fit();
99
+ }
100
+ if (scroll) terminal.scrollToBottom();
101
+ }
80
102
 
81
103
  function getTokenParam() {
82
104
  const urlParams = new URLSearchParams(window.location.search);
@@ -104,8 +126,10 @@ async function fetchOutput(url) {
104
126
  clearInterval(outputInterval);
105
127
  } else {
106
128
  if (data.cols) {
107
- terminal.resize(data.cols, terminal.rows);
108
- } else fitAddon.fit();
129
+ cols = data.cols;
130
+ rows = data.rows;
131
+ autoFit(false);
132
+ }
109
133
  percentage = slider.value;
110
134
  fullOutput += data.output;
111
135
  if (fullOutput.length > maxSize)
@@ -178,8 +202,7 @@ function adjustOutputHeight() {
178
202
  const outputTop = outputDiv.getBoundingClientRect().top;
179
203
  const maxHeight = windowHeight - outputTop - 60; // Adjusted for slider height
180
204
  outputDiv.style.height = `${maxHeight}px`;
181
- fitAddon.fit();
182
- sliderUpdateOutput();
205
+ autoFit();
183
206
  }
184
207
 
185
208
  function sliderUpdateOutput() {
@@ -214,9 +237,20 @@ function toggleFetchOutput() {
214
237
  }
215
238
  isPaused = !isPaused;
216
239
  }
240
+ function toggleFit() {
241
+ fitWindow = ! fitWindow;
242
+ if (fitWindow) {
243
+ toggleFitButton.classList.add('fit-tty');
244
+ toggleFitButton.setAttribute('title', 'terminal fit tty');
245
+ } else {
246
+ toggleFitButton.classList.remove('fit-tty');
247
+ toggleFitButton.setAttribute('title', 'terminal fit window');
248
+ }
249
+ autoFit();
250
+ }
217
251
 
218
252
  toggleButton.addEventListener('click', toggleFetchOutput);
219
-
253
+ toggleFitButton.addEventListener('click', toggleFit);
220
254
  window.addEventListener('resize', adjustOutputHeight);
221
255
  window.addEventListener('load', () => {
222
256
  slider = document.getElementById('outputSlider');
@@ -229,11 +263,11 @@ window.addEventListener('load', () => {
229
263
  document.getElementById('decreaseFontSize').addEventListener('click', () => {
230
264
  fontSize = Math.max(8, fontSize - 1);
231
265
  terminal.options.fontSize = fontSize;
232
- fitAddon.fit();
266
+ autoFit();
233
267
  });
234
268
 
235
269
  document.getElementById('increaseFontSize').addEventListener('click', () => {
236
270
  fontSize = Math.min(32, fontSize + 1);
237
271
  terminal.options.fontSize = fontSize;
238
- fitAddon.fit();
272
+ autoFit();
239
273
  });
@@ -11,6 +11,9 @@ let fontSize = 14;
11
11
  let isPaused = false;
12
12
  let showRunningOnly = false;
13
13
  let hiddenCommandIds = [];
14
+ let fitWindow = false;
15
+ let cols = 0;
16
+ let rows = 0;
14
17
 
15
18
  function initTerminal()
16
19
  {
@@ -97,6 +100,23 @@ terminal.onSelectionChange(() => {
97
100
  }
98
101
  });
99
102
 
103
+ function autoFit(scroll=true) {
104
+ // Scroll output div to bottom
105
+ const outputDiv = document.getElementById('output');
106
+ outputDiv.scrollTop = terminal.element.clientHeight - outputDiv.clientHeight + 20;
107
+ if (cols && !fitWindow) {
108
+ let fit = fitAddon.proposeDimensions();
109
+ if (fit.rows < rows) {
110
+ terminal.resize(cols, rows);
111
+ } else {
112
+ terminal.resize(cols, fit.rows);
113
+ }
114
+ } else {
115
+ fitAddon.fit();
116
+ }
117
+ if (scroll) terminal.scrollToBottom();
118
+ }
119
+
100
120
  function getTokenParam() {
101
121
  const urlParams = new URLSearchParams(window.location.search);
102
122
  return urlParams.get('token') ? `?token=${urlParams.get('token')}` : '';
@@ -201,8 +221,10 @@ async function fetchOutput(url) {
201
221
  clearInterval(outputInterval);
202
222
  } else {
203
223
  if (data.cols) {
204
- terminal.resize(data.cols, terminal.rows);
205
- } else fitAddon.fit();
224
+ cols = data.cols;
225
+ rows = data.rows;
226
+ autoFit(scroll=false);
227
+ }
206
228
  fullOutput += data.output;
207
229
  if (fullOutput.length > maxSize)
208
230
  fullOutput = fullOutput.slice(-maxSize);
@@ -370,7 +392,7 @@ function adjustOutputHeight() {
370
392
  const outputTop = outputDiv.getBoundingClientRect().top;
371
393
  const maxHeight = windowHeight - outputTop - 60; // Adjusted for slider height
372
394
  outputDiv.style.height = `${maxHeight}px`;
373
- fitAddon.fit();
395
+ autoFit();
374
396
  }
375
397
 
376
398
  function initResizer() {
@@ -412,17 +434,19 @@ slider.addEventListener('input', sliderUpdateOutput);
412
434
  document.getElementById('decreaseFontSize').addEventListener('click', () => {
413
435
  fontSize = Math.max(8, fontSize - 1);
414
436
  terminal.options.fontSize = fontSize;
415
- fitAddon.fit();
437
+ autoFit();
416
438
  });
417
439
 
418
440
  document.getElementById('increaseFontSize').addEventListener('click', () => {
419
441
  fontSize = Math.min(32, fontSize + 1);
420
442
  terminal.options.fontSize = fontSize;
421
- fitAddon.fit();
443
+ autoFit();
422
444
  });
423
445
 
424
446
  const toggleButton = document.getElementById('toggleFetch');
425
447
  const pausedMessage = document.getElementById('pausedMessage');
448
+ const toggleFitButton = document.getElementById('toggleFit');
449
+
426
450
 
427
451
  function toggleFetchOutput() {
428
452
  if (isPaused) {
@@ -446,8 +470,20 @@ function toggleFetchOutput() {
446
470
  }
447
471
  isPaused = !isPaused;
448
472
  }
473
+ function toggleFit() {
474
+ fitWindow = ! fitWindow;
475
+ if (fitWindow) {
476
+ toggleFitButton.classList.add('fit-tty');
477
+ toggleFitButton.setAttribute('title', 'terminal fit tty');
478
+ } else {
479
+ toggleFitButton.classList.remove('fit-tty');
480
+ toggleFitButton.setAttribute('title', 'terminal fit window');
481
+ }
482
+ autoFit();
483
+ }
449
484
 
450
485
  toggleButton.addEventListener('click', toggleFetchOutput);
486
+ toggleFitButton.addEventListener('click', toggleFit);
451
487
 
452
488
  document.getElementById('thStatus').addEventListener('click', () => {
453
489
  showRunningOnly = !showRunningOnly;
@@ -52,6 +52,7 @@
52
52
  <button id="toggleFetch" class="pause-resume-button pause"></button>
53
53
  <button id="decreaseFontSize" class="font-size-button font-decrease"></button>
54
54
  <button id="increaseFontSize" class="font-size-button font-increase"></button>
55
+ <button id="toggleFit" class="fit-button fit-window" title="terminal fit window"></button>
55
56
  </div>
56
57
  <script src="/static/js/xterm/xterm.js"></script>
57
58
  <script src="/static/js/xterm/addon-canvas.js"></script>
@@ -20,6 +20,7 @@
20
20
  <button id="toggleFetch" class="pause-resume-button pause"></button>
21
21
  <button id="decreaseFontSize" class="font-size-button font-decrease"></button>
22
22
  <button id="increaseFontSize" class="font-size-button font-increase"></button>
23
+ <button id="toggleFit" class="fit-button fit-window" title="terminal fit window"></button>
23
24
  </div>
24
25
  <script src="/static/js/xterm/xterm.js"></script>
25
26
  <script src="/static/js/xterm/addon-canvas.js"></script>
pywebexec/version.py CHANGED
@@ -12,5 +12,5 @@ __version__: str
12
12
  __version_tuple__: VERSION_TUPLE
13
13
  version_tuple: VERSION_TUPLE
14
14
 
15
- __version__ = version = '1.7.1'
16
- __version_tuple__ = version_tuple = (1, 7, 1)
15
+ __version__ = version = '1.7.2'
16
+ __version_tuple__ = version_tuple = (1, 7, 2)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: pywebexec
3
- Version: 1.7.1
3
+ Version: 1.7.2
4
4
  Summary: Simple Python HTTP Exec Server
5
5
  Home-page: https://github.com/joknarf/pywebexec
6
6
  Author: Franck Jouvanceau
@@ -1,8 +1,8 @@
1
1
  pywebexec/__init__.py,sha256=4spIsVaF8RJt8S58AG_wWoORRNkws9Iwqprj27C3ljM,99
2
- pywebexec/pywebexec.py,sha256=yPag3ijHH1mzI6k6DjyvBms7FNAQ3UH_IPyeCHU-AO8,33323
3
- pywebexec/version.py,sha256=kn-QYzzAhfbnfKK6EpE9gJz8TDZkEk52evaid1DHkG4,411
2
+ pywebexec/pywebexec.py,sha256=gJsI7kob3IyB6DVoWWSyEHOcxpWlsZz-b7jQUyePA-A,33555
3
+ pywebexec/version.py,sha256=Qj1rYkRQ0hSV6NX03bgvPhjsn6HWrQ8maBXi446C5ZM,411
4
4
  pywebexec/static/css/Consolas NF.ttf,sha256=DJEOzF0eqZ-kxu3Gs_VE8X0NJqiobBzmxWDGpdgGRxI,1313900
5
- pywebexec/static/css/style.css,sha256=MJHUBpjWL4sLxM7a7DxypmPKaFJQbmA_ESNXsbLviNI,8201
5
+ pywebexec/static/css/style.css,sha256=3s7QgbCh4wb7kfZ7Pjo-B6o3lDIBogZ-3j6AfaPdpzU,8209
6
6
  pywebexec/static/css/xterm.css,sha256=uo5phWaUiJgcz0DAzv46uoByLLbJLeetYosL1xf68rY,5559
7
7
  pywebexec/static/images/aborted.svg,sha256=2nuvSwGBIZGWtlM1DrBO3qiSq1reDbcZDAj9rJXBnjY,380
8
8
  pywebexec/static/images/copy.svg,sha256=d9OwtGh5GzzZHzYcDrLfNxZYLth1Q64x7bRyYxu4Px0,622
@@ -10,6 +10,8 @@ pywebexec/static/images/copy_ok.svg,sha256=mEqUVUhSq8xaJK2msQkxRawnz_KwlCZ-tok8Q
10
10
  pywebexec/static/images/down-arrow.svg,sha256=4TclEmntMvKk_F_ADXgTpGtviYo826EDmmZiGE7HQBI,121
11
11
  pywebexec/static/images/failed.svg,sha256=rSTBWOtiz7slGDobeU_vaLaMM8CoPeul_tQgWVBcodo,1438
12
12
  pywebexec/static/images/favicon.svg,sha256=9gSN5Oak1zTWhTCyutlupPBKUxcbdoVt7dvhk8xvEug,1224
13
+ pywebexec/static/images/fit-tty.svg,sha256=gyRB9cqvXFSUOzpBq_Cr0Hv8nIpfr5ca74uUXjkLR-A,1438
14
+ pywebexec/static/images/fit-win.svg,sha256=_JNK-ew7mc8QIFG2D2TPNm0W2wN2d3Oa6d2d8iwbCFQ,1435
13
15
  pywebexec/static/images/font-decrease.svg,sha256=89TJXQpfZ-XDJ2qC0c7cbLH-tWC-4AJQr_VOgsp06Gg,1782
14
16
  pywebexec/static/images/font-increase.svg,sha256=u-EBxUzmOhKx4UH96fb4gLZ0l6Jkew1HLhcSqz7Z1ak,1869
15
17
  pywebexec/static/images/norun.svg,sha256=_9PyQklBOfUwFak1gVrm-76tYM825urAFhj-zMBec20,555
@@ -19,8 +21,8 @@ pywebexec/static/images/resume.svg,sha256=99LP1Ya2JXakRCO9kW8JMuT_4a_CannF65Eiuw
19
21
  pywebexec/static/images/running.svg,sha256=fBCYwYb2O9K4N3waC2nURP25NRwZlqR4PbDZy6JQMww,610
20
22
  pywebexec/static/images/success.svg,sha256=NVwezvVMplt46ElW798vqGfrL21Mw_DWHUp_qiD_FU8,489
21
23
  pywebexec/static/js/commands.js,sha256=h2fkd9qpypLBxvhEEbay23nwuqUwcKJA0vHugcyL8pU,7961
22
- pywebexec/static/js/popup.js,sha256=I5TLYUm5s2p12a0VfFONOxxzhXLBmnpVzM-B5W-GPis,8294
23
- pywebexec/static/js/script.js,sha256=EPofQO0ec2bwIr2YdzzNY3dcXipW2_Mi2j34DIYvJeE,17096
24
+ pywebexec/static/js/popup.js,sha256=UPKtjPLIR5KaAV2i1iWUGwcCTX1tT3vnOIMc8VKQqag,9311
25
+ pywebexec/static/js/script.js,sha256=W5NfzFYdyfQpALx_bjeppQFVWxvZGMoVTTq0VOnITxw,18147
24
26
  pywebexec/static/js/xterm/LICENSE,sha256=EU1P4eXTull-_T9I80VuwnJXubB-zLzUl3xpEYj2T1M,1083
25
27
  pywebexec/static/js/xterm/addon-canvas.js,sha256=ez6QTVvsmLVNJmdJlM-ZQ5bErwlxAQ_9DUmDIptl2TM,94607
26
28
  pywebexec/static/js/xterm/addon-canvas.js.map,sha256=ECBA4B-BqUpdFeRzlsEWLSQnudnhLP-yPQJ8_hKquMo,379537
@@ -31,11 +33,11 @@ pywebexec/static/js/xterm/addon-unicode11.js.map,sha256=paDj5KKtTIUGedQn2x7CaUTD
31
33
  pywebexec/static/js/xterm/xterm.js,sha256=H5kaw7Syg-v5bmCuI6AKUnZd06Lkb6b92p8aqwMvdJU,289441
32
34
  pywebexec/static/js/xterm/xterm.js.map,sha256=Y7O2Pb-fIS7Z8AC1D5s04_aiW_Jf1f4mCfN0U_OI6Zw,1118392
33
35
  pywebexec/templates/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
34
- pywebexec/templates/index.html,sha256=5h8kLyzAhbvUDU9sEwrGIvD6FxAMcDZLXlN-ldlO8KU,2880
35
- pywebexec/templates/popup.html,sha256=3ZqQcE9mYs-RXv0Lfb24zntOlvR137ZYI9mtCZNVAo0,1407
36
- pywebexec-1.7.1.dist-info/LICENSE,sha256=gRJf0JPT_wsZJsUGlWPTS8Vypfl9vQ1qjp6sNbKykuA,1064
37
- pywebexec-1.7.1.dist-info/METADATA,sha256=2qLB_f1jdH1RY5hctK3TZcD8_EofCTtsfLp0uYix0Is,8000
38
- pywebexec-1.7.1.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
39
- pywebexec-1.7.1.dist-info/entry_points.txt,sha256=l52GBkPCXRkmlHfEyoVauyfBdg8o-CAtC8qQpOIjJK0,55
40
- pywebexec-1.7.1.dist-info/top_level.txt,sha256=vHoHyzngrfGdm_nM7Xn_5iLmaCrf10XO1EhldgNLEQ8,10
41
- pywebexec-1.7.1.dist-info/RECORD,,
36
+ pywebexec/templates/index.html,sha256=2fEN8cggHBEd8-RamDFpnekVJtIbRembFSw0-1YEptc,2979
37
+ pywebexec/templates/popup.html,sha256=GT2jY7oOxpCaBaRl924QJWdFBmfSOP952T13d37R_pY,1506
38
+ pywebexec-1.7.2.dist-info/LICENSE,sha256=gRJf0JPT_wsZJsUGlWPTS8Vypfl9vQ1qjp6sNbKykuA,1064
39
+ pywebexec-1.7.2.dist-info/METADATA,sha256=NudV7MvLxsTsIZzpTjzNuLJNijAmoK0C9o5VDIg0oRI,8000
40
+ pywebexec-1.7.2.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
41
+ pywebexec-1.7.2.dist-info/entry_points.txt,sha256=l52GBkPCXRkmlHfEyoVauyfBdg8o-CAtC8qQpOIjJK0,55
42
+ pywebexec-1.7.2.dist-info/top_level.txt,sha256=vHoHyzngrfGdm_nM7Xn_5iLmaCrf10XO1EhldgNLEQ8,10
43
+ pywebexec-1.7.2.dist-info/RECORD,,