multiSSH3 5.71__tar.gz → 5.73__tar.gz
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.
Potentially problematic release.
This version of multiSSH3 might be problematic. Click here for more details.
- {multissh3-5.71 → multissh3-5.73}/PKG-INFO +1 -1
- {multissh3-5.71 → multissh3-5.73}/multiSSH3.egg-info/PKG-INFO +1 -1
- {multissh3-5.71 → multissh3-5.73}/multiSSH3.py +26 -19
- {multissh3-5.71 → multissh3-5.73}/README.md +0 -0
- {multissh3-5.71 → multissh3-5.73}/multiSSH3.egg-info/SOURCES.txt +0 -0
- {multissh3-5.71 → multissh3-5.73}/multiSSH3.egg-info/dependency_links.txt +0 -0
- {multissh3-5.71 → multissh3-5.73}/multiSSH3.egg-info/entry_points.txt +0 -0
- {multissh3-5.71 → multissh3-5.73}/multiSSH3.egg-info/requires.txt +0 -0
- {multissh3-5.71 → multissh3-5.73}/multiSSH3.egg-info/top_level.txt +0 -0
- {multissh3-5.71 → multissh3-5.73}/setup.cfg +0 -0
- {multissh3-5.71 → multissh3-5.73}/setup.py +0 -0
- {multissh3-5.71 → multissh3-5.73}/test/test.py +0 -0
- {multissh3-5.71 → multissh3-5.73}/test/testCurses.py +0 -0
- {multissh3-5.71 → multissh3-5.73}/test/testCursesOld.py +0 -0
- {multissh3-5.71 → multissh3-5.73}/test/testPerfCompact.py +0 -0
- {multissh3-5.71 → multissh3-5.73}/test/testPerfExpand.py +0 -0
|
@@ -54,10 +54,10 @@ except AttributeError:
|
|
|
54
54
|
# If neither is available, use a dummy decorator
|
|
55
55
|
def cache_decorator(func):
|
|
56
56
|
return func
|
|
57
|
-
version = '5.
|
|
57
|
+
version = '5.73'
|
|
58
58
|
VERSION = version
|
|
59
59
|
__version__ = version
|
|
60
|
-
COMMIT_DATE = '2025-05-
|
|
60
|
+
COMMIT_DATE = '2025-05-21'
|
|
61
61
|
|
|
62
62
|
CONFIG_FILE_CHAIN = ['./multiSSH3.config.json',
|
|
63
63
|
'~/multiSSH3.config.json',
|
|
@@ -1824,14 +1824,14 @@ def _curses_add_string_to_window(window, line = '', y = 0, x = 0, number_of_char
|
|
|
1824
1824
|
charsWritten += min(len(segment), numChar - charsWritten)
|
|
1825
1825
|
# if we have finished printing segments but we still have space, we will fill it with fill_char
|
|
1826
1826
|
trail_fill_length = numChar - charsWritten - len(trail_str)
|
|
1827
|
-
if trail_fill_length > 0:
|
|
1828
|
-
window.addnstr(y, x + charsWritten,fill_char * (trail_fill_length // len(fill_char) + 1), trail_fill_length, boxAttr)
|
|
1827
|
+
if trail_fill_length > 0 and fill_char:
|
|
1828
|
+
window.addnstr(y, x + charsWritten,fill_char * (trail_fill_length // len(fill_char) + 1), trail_fill_length , boxAttr)
|
|
1829
1829
|
charsWritten += trail_fill_length
|
|
1830
1830
|
if len(trail_str) > 0 and charsWritten < numChar:
|
|
1831
1831
|
window.addnstr(y, x + charsWritten, trail_str, numChar - charsWritten, boxAttr)
|
|
1832
1832
|
charsWritten += min(len(trail_str), numChar - charsWritten)
|
|
1833
1833
|
|
|
1834
|
-
def _get_hosts_to_display (hosts, max_num_hosts, hosts_to_display = None):
|
|
1834
|
+
def _get_hosts_to_display (hosts, max_num_hosts, hosts_to_display = None, indexOffset = 0):
|
|
1835
1835
|
'''
|
|
1836
1836
|
Generate a list for the hosts to be displayed on the screen. This is used to display as much relevant information as possible.
|
|
1837
1837
|
|
|
@@ -1852,21 +1852,23 @@ def _get_hosts_to_display (hosts, max_num_hosts, hosts_to_display = None):
|
|
|
1852
1852
|
failed_hosts = [host for host in hosts if host.returncode is not None and host.returncode != 0]
|
|
1853
1853
|
finished_hosts = [host for host in hosts if host.returncode is not None and host.returncode == 0]
|
|
1854
1854
|
waiting_hosts = [host for host in hosts if host.returncode is None and not host.output]
|
|
1855
|
-
new_hosts_to_display = (running_hosts + failed_hosts + finished_hosts + waiting_hosts)
|
|
1855
|
+
new_hosts_to_display = (running_hosts + failed_hosts + finished_hosts + waiting_hosts)
|
|
1856
|
+
new_hosts_to_display = new_hosts_to_display[indexOffset:] + new_hosts_to_display[:indexOffset]
|
|
1857
|
+
new_hosts_to_display = new_hosts_to_display[:max_num_hosts]
|
|
1856
1858
|
if not hosts_to_display:
|
|
1857
|
-
return new_hosts_to_display , {'running':len(running_hosts), 'failed':len(failed_hosts), 'finished':len(finished_hosts), 'waiting':len(waiting_hosts)}
|
|
1859
|
+
return new_hosts_to_display , {'running':len(running_hosts), 'failed':len(failed_hosts), 'finished':len(finished_hosts), 'waiting':len(waiting_hosts)}, set(new_hosts_to_display)
|
|
1858
1860
|
# we will compare the new_hosts_to_display with the old one, if some hosts are not in their original position, we will reprint all lines
|
|
1861
|
+
rearrangedHosts = set()
|
|
1859
1862
|
for i, host in enumerate(new_hosts_to_display):
|
|
1860
1863
|
if host not in hosts_to_display or i != hosts_to_display.index(host):
|
|
1861
|
-
|
|
1862
|
-
return new_hosts_to_display , {'running':len(running_hosts), 'failed':len(failed_hosts), 'finished':len(finished_hosts), 'waiting':len(waiting_hosts)}
|
|
1864
|
+
rearrangedHosts.add(host)
|
|
1865
|
+
return new_hosts_to_display , {'running':len(running_hosts), 'failed':len(failed_hosts), 'finished':len(finished_hosts), 'waiting':len(waiting_hosts)}, rearrangedHosts
|
|
1863
1866
|
|
|
1864
1867
|
def __generate_display(stdscr, hosts, lineToDisplay = -1,curserPosition = 0, min_char_len = DEFAULT_CURSES_MINIMUM_CHAR_LEN, min_line_len = DEFAULT_CURSES_MINIMUM_LINE_LEN,single_window=DEFAULT_SINGLE_WINDOW, config_reason = 'New Configuration'):
|
|
1865
1868
|
_ = config_reason
|
|
1866
1869
|
try:
|
|
1867
1870
|
box_ansi_color = None
|
|
1868
1871
|
org_dim = stdscr.getmaxyx()
|
|
1869
|
-
new_configured = True
|
|
1870
1872
|
# To do this, first we need to know the size of the terminal
|
|
1871
1873
|
max_y, max_x = org_dim
|
|
1872
1874
|
# we will use one line to print the aggregated stats for the hosts.
|
|
@@ -1890,7 +1892,7 @@ def __generate_display(stdscr, hosts, lineToDisplay = -1,curserPosition = 0, min
|
|
|
1890
1892
|
max_num_hosts = max_num_hosts_x * max_num_hosts_y
|
|
1891
1893
|
if max_num_hosts < 1:
|
|
1892
1894
|
return (lineToDisplay,curserPosition , min_char_len, min_line_len, single_window, 'Terminal too small to display any hosts')
|
|
1893
|
-
hosts_to_display , host_stats = _get_hosts_to_display(hosts, max_num_hosts)
|
|
1895
|
+
hosts_to_display , host_stats, rearrangedHosts = _get_hosts_to_display(hosts, max_num_hosts)
|
|
1894
1896
|
if len(hosts_to_display) == 0:
|
|
1895
1897
|
return (lineToDisplay,curserPosition , min_char_len, min_line_len, single_window, 'No hosts to display')
|
|
1896
1898
|
# Now we calculate the actual number of hosts we will display for x and y
|
|
@@ -1949,6 +1951,7 @@ def __generate_display(stdscr, hosts, lineToDisplay = -1,curserPosition = 0, min
|
|
|
1949
1951
|
#bottom_border.addnstr(0, 0, '-' * (max_x - 1), max_x - 1)
|
|
1950
1952
|
_curses_add_string_to_window(window=bottom_border, y=0, line='-' * (max_x - 1),fill_char='-',box_ansi_color=box_ansi_color)
|
|
1951
1953
|
bottom_border.refresh()
|
|
1954
|
+
indexOffset = 0
|
|
1952
1955
|
while host_stats['running'] > 0 or host_stats['waiting'] > 0:
|
|
1953
1956
|
# Check for keypress
|
|
1954
1957
|
key = stdscr.getch()
|
|
@@ -1981,6 +1984,10 @@ def __generate_display(stdscr, hosts, lineToDisplay = -1,curserPosition = 0, min
|
|
|
1981
1984
|
elif key == 125 and not __keyPressesIn[-1]: # 125 is the key code for }
|
|
1982
1985
|
# if last line is empty, we will reconfigure the ww to be larger
|
|
1983
1986
|
return (lineToDisplay,curserPosition , min_char_len +1, min_line_len, single_window, 'Increase character length')
|
|
1987
|
+
elif key == 60 and not __keyPressesIn[-1]: # 60 is the key code for <
|
|
1988
|
+
indexOffset = (indexOffset - 1 ) % len(hosts)
|
|
1989
|
+
elif key == 62 and not __keyPressesIn[-1]: # 62 is the key code for >
|
|
1990
|
+
indexOffset = (indexOffset +1 ) % len(hosts)
|
|
1984
1991
|
# We handle positional keys
|
|
1985
1992
|
# if the key is up arrow, we will move the line to display up
|
|
1986
1993
|
elif key == 259: # 259 is the key code for up arrow
|
|
@@ -1989,7 +1996,7 @@ def __generate_display(stdscr, hosts, lineToDisplay = -1,curserPosition = 0, min
|
|
|
1989
1996
|
elif key == 258: # 258 is the key code for down arrow
|
|
1990
1997
|
lineToDisplay = min(lineToDisplay + 1, -1)
|
|
1991
1998
|
# if the key is left arrow, we will move the cursor left
|
|
1992
|
-
elif key == 260: # 260 is the key code for left arrow
|
|
1999
|
+
elif key == 260: # 260 is the key │code for left arrow
|
|
1993
2000
|
curserPosition = min(max(curserPosition - 1, 0), len(__keyPressesIn[lineToDisplay]) -1)
|
|
1994
2001
|
# if the key is right arrow, we will move the cursor right
|
|
1995
2002
|
elif key == 261: # 261 is the key code for right arrow
|
|
@@ -2042,7 +2049,7 @@ def __generate_display(stdscr, hosts, lineToDisplay = -1,curserPosition = 0, min
|
|
|
2042
2049
|
# We generate the aggregated stats if user did not input anything
|
|
2043
2050
|
if not __keyPressesIn[lineToDisplay]:
|
|
2044
2051
|
#stats = '┍'+ f" Total: {len(hosts)} Running: {host_stats['running']} Failed: {host_stats['failed']} Finished: {host_stats['finished']} Waiting: {host_stats['waiting']} ww: {min_char_len} wh:{min_line_len} "[:max_x - 2].center(max_x - 2, "━")
|
|
2045
|
-
stats = f"Total: {len(hosts)} Running: {host_stats['running']} Failed: {host_stats['failed']} Finished: {host_stats['finished']} Waiting: {host_stats['waiting']} ww: {min_char_len} wh:{min_line_len} "
|
|
2052
|
+
stats = f"Total: {len(hosts)} Running: {host_stats['running']} Failed: {host_stats['failed']} Finished: {host_stats['finished']} Waiting: {host_stats['waiting']} ww: {min_char_len} wh:{min_line_len} i:{indexOffset} "
|
|
2046
2053
|
else:
|
|
2047
2054
|
# we use the stat bar to display the key presses
|
|
2048
2055
|
encodedLine = ''.join(__keyPressesIn[lineToDisplay]).encode().decode().strip('\n') + ' '
|
|
@@ -2081,16 +2088,15 @@ def __generate_display(stdscr, hosts, lineToDisplay = -1,curserPosition = 0, min
|
|
|
2081
2088
|
if time.perf_counter() - last_refresh_time < 0.01:
|
|
2082
2089
|
time.sleep(max(0,0.01 - time.perf_counter() + last_refresh_time))
|
|
2083
2090
|
#stdscr.clear()
|
|
2084
|
-
hosts_to_display, host_stats = _get_hosts_to_display(hosts, max_num_hosts,hosts_to_display)
|
|
2085
2091
|
for host_window, host in zip(host_windows, hosts_to_display):
|
|
2086
2092
|
# we will only update the window if there is new output or the window is not fully printed
|
|
2087
|
-
if
|
|
2088
|
-
host.lineNumToPrintSet.update(range(len(host.output)))
|
|
2093
|
+
if host in rearrangedHosts:
|
|
2089
2094
|
linePrintOut = f'{host.name}:[{host.command}]'.replace('\n', ' ').replace('\r', ' ').strip()
|
|
2090
2095
|
_curses_add_string_to_window(window=host_window, y=0, line=linePrintOut, color_pair_list=[-1, -1, 1],centered=True,fill_char='─',lead_str='┼',box_ansi_color=box_ansi_color)
|
|
2091
2096
|
# clear the window
|
|
2092
2097
|
for i in range(host_window_height - 1):
|
|
2093
2098
|
_curses_add_string_to_window(window=host_window, color_pair_list=[-1, -1, 1], y=i + 1,lead_str='│',keep_top_n_lines=1,box_ansi_color=box_ansi_color)
|
|
2099
|
+
host.lineNumToPrintSet.update(range(len(host.output)))
|
|
2094
2100
|
# for i in range(host.printedLines, len(host.output)):
|
|
2095
2101
|
# _curses_add_string_to_window(window=host_window, y=i + 1, line=host.output[i], color_pair_list=host.current_color_pair,lead_str='│',keep_top_n_lines=1,box_ansi_color=box_ansi_color)
|
|
2096
2102
|
# host.printedLines = len(host.output)
|
|
@@ -2103,15 +2109,16 @@ def __generate_display(stdscr, hosts, lineToDisplay = -1,curserPosition = 0, min
|
|
|
2103
2109
|
for lineNumToReprint in sorted(lineNumToPrintSet):
|
|
2104
2110
|
# if the line is visible, we will reprint it
|
|
2105
2111
|
if visibleLowerBound <= lineNumToReprint <= len(host.output):
|
|
2106
|
-
_curses_add_string_to_window(window=host_window, y=lineNumToReprint + 1, line=host.output[lineNumToReprint], color_pair_list=host.current_color_pair,lead_str='│',keep_top_n_lines=1,box_ansi_color=box_ansi_color)
|
|
2112
|
+
_curses_add_string_to_window(window=host_window, y=lineNumToReprint + 1, line=host.output[lineNumToReprint], color_pair_list=host.current_color_pair,lead_str='│',keep_top_n_lines=1,box_ansi_color=box_ansi_color,fill_char='')
|
|
2107
2113
|
except Exception as e:
|
|
2108
2114
|
# import traceback
|
|
2109
2115
|
# print(str(e).strip())
|
|
2110
2116
|
# print(traceback.format_exc().strip())
|
|
2111
2117
|
if org_dim != stdscr.getmaxyx():
|
|
2112
2118
|
return (lineToDisplay,curserPosition , min_char_len, min_line_len, single_window, 'Terminal resize detected')
|
|
2113
|
-
host_window.
|
|
2114
|
-
|
|
2119
|
+
host_window.noutrefresh()
|
|
2120
|
+
hosts_to_display, host_stats,rearrangedHosts = _get_hosts_to_display(hosts, max_num_hosts,hosts_to_display, indexOffset)
|
|
2121
|
+
curses.doupdate()
|
|
2115
2122
|
last_refresh_time = time.perf_counter()
|
|
2116
2123
|
except Exception as e:
|
|
2117
2124
|
import traceback
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|