multiSSH3 5.69__tar.gz → 5.72__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.69 → multissh3-5.72}/PKG-INFO +1 -1
- {multissh3-5.69 → multissh3-5.72}/multiSSH3.egg-info/PKG-INFO +1 -1
- {multissh3-5.69 → multissh3-5.72}/multiSSH3.py +19 -16
- {multissh3-5.69 → multissh3-5.72}/README.md +0 -0
- {multissh3-5.69 → multissh3-5.72}/multiSSH3.egg-info/SOURCES.txt +0 -0
- {multissh3-5.69 → multissh3-5.72}/multiSSH3.egg-info/dependency_links.txt +0 -0
- {multissh3-5.69 → multissh3-5.72}/multiSSH3.egg-info/entry_points.txt +0 -0
- {multissh3-5.69 → multissh3-5.72}/multiSSH3.egg-info/requires.txt +0 -0
- {multissh3-5.69 → multissh3-5.72}/multiSSH3.egg-info/top_level.txt +0 -0
- {multissh3-5.69 → multissh3-5.72}/setup.cfg +0 -0
- {multissh3-5.69 → multissh3-5.72}/setup.py +0 -0
- {multissh3-5.69 → multissh3-5.72}/test/test.py +0 -0
- {multissh3-5.69 → multissh3-5.72}/test/testCurses.py +0 -0
- {multissh3-5.69 → multissh3-5.72}/test/testCursesOld.py +0 -0
- {multissh3-5.69 → multissh3-5.72}/test/testPerfCompact.py +0 -0
- {multissh3-5.69 → multissh3-5.72}/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.72'
|
|
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',
|
|
@@ -1191,12 +1191,13 @@ def __handle_writing_stream(stream,stop_event,host):
|
|
|
1191
1191
|
line = '> ' + ''.join(__keyPressesIn[sentInput]).encode().decode().replace('\n', '↵')
|
|
1192
1192
|
host.output.append(line)
|
|
1193
1193
|
host.stdout.append(line)
|
|
1194
|
+
host.lineNumToPrintSet.add(len(host.output)-1)
|
|
1194
1195
|
sentInput += 1
|
|
1195
1196
|
host.lastUpdateTime = time.monotonic()
|
|
1196
1197
|
else:
|
|
1197
1198
|
time.sleep(0.01) # sleep for 10ms
|
|
1198
1199
|
if sentInput < len(__keyPressesIn) - 1 :
|
|
1199
|
-
eprint(f"Warning: {len(__keyPressesIn)-sentInput} key presses are not sent before the process is terminated!")
|
|
1200
|
+
eprint(f"Warning: {len(__keyPressesIn)-sentInput} lines of key presses are not sent before the process is terminated!")
|
|
1200
1201
|
# # send the last line
|
|
1201
1202
|
# if __keyPressesIn and __keyPressesIn[-1]:
|
|
1202
1203
|
# stream.write(''.join(__keyPressesIn[-1]).encode())
|
|
@@ -1853,19 +1854,19 @@ def _get_hosts_to_display (hosts, max_num_hosts, hosts_to_display = None):
|
|
|
1853
1854
|
waiting_hosts = [host for host in hosts if host.returncode is None and not host.output]
|
|
1854
1855
|
new_hosts_to_display = (running_hosts + failed_hosts + finished_hosts + waiting_hosts)[:max_num_hosts]
|
|
1855
1856
|
if not hosts_to_display:
|
|
1856
|
-
return new_hosts_to_display , {'running':len(running_hosts), 'failed':len(failed_hosts), 'finished':len(finished_hosts), 'waiting':len(waiting_hosts)}
|
|
1857
|
+
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)
|
|
1857
1858
|
# 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
|
|
1859
|
+
rearrangedHosts = set()
|
|
1858
1860
|
for i, host in enumerate(new_hosts_to_display):
|
|
1859
1861
|
if host not in hosts_to_display or i != hosts_to_display.index(host):
|
|
1860
|
-
|
|
1861
|
-
return new_hosts_to_display , {'running':len(running_hosts), 'failed':len(failed_hosts), 'finished':len(finished_hosts), 'waiting':len(waiting_hosts)}
|
|
1862
|
+
rearrangedHosts.add(host)
|
|
1863
|
+
return new_hosts_to_display , {'running':len(running_hosts), 'failed':len(failed_hosts), 'finished':len(finished_hosts), 'waiting':len(waiting_hosts)}, rearrangedHosts
|
|
1862
1864
|
|
|
1863
1865
|
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'):
|
|
1864
1866
|
_ = config_reason
|
|
1865
1867
|
try:
|
|
1866
1868
|
box_ansi_color = None
|
|
1867
1869
|
org_dim = stdscr.getmaxyx()
|
|
1868
|
-
new_configured = True
|
|
1869
1870
|
# To do this, first we need to know the size of the terminal
|
|
1870
1871
|
max_y, max_x = org_dim
|
|
1871
1872
|
# we will use one line to print the aggregated stats for the hosts.
|
|
@@ -1889,7 +1890,7 @@ def __generate_display(stdscr, hosts, lineToDisplay = -1,curserPosition = 0, min
|
|
|
1889
1890
|
max_num_hosts = max_num_hosts_x * max_num_hosts_y
|
|
1890
1891
|
if max_num_hosts < 1:
|
|
1891
1892
|
return (lineToDisplay,curserPosition , min_char_len, min_line_len, single_window, 'Terminal too small to display any hosts')
|
|
1892
|
-
hosts_to_display , host_stats = _get_hosts_to_display(hosts, max_num_hosts)
|
|
1893
|
+
hosts_to_display , host_stats, rearrangedHosts = _get_hosts_to_display(hosts, max_num_hosts)
|
|
1893
1894
|
if len(hosts_to_display) == 0:
|
|
1894
1895
|
return (lineToDisplay,curserPosition , min_char_len, min_line_len, single_window, 'No hosts to display')
|
|
1895
1896
|
# Now we calculate the actual number of hosts we will display for x and y
|
|
@@ -2080,16 +2081,15 @@ def __generate_display(stdscr, hosts, lineToDisplay = -1,curserPosition = 0, min
|
|
|
2080
2081
|
if time.perf_counter() - last_refresh_time < 0.01:
|
|
2081
2082
|
time.sleep(max(0,0.01 - time.perf_counter() + last_refresh_time))
|
|
2082
2083
|
#stdscr.clear()
|
|
2083
|
-
hosts_to_display, host_stats = _get_hosts_to_display(hosts, max_num_hosts,hosts_to_display)
|
|
2084
2084
|
for host_window, host in zip(host_windows, hosts_to_display):
|
|
2085
2085
|
# we will only update the window if there is new output or the window is not fully printed
|
|
2086
|
-
if
|
|
2087
|
-
host.lineNumToPrintSet.update(range(len(host.output)))
|
|
2086
|
+
if host in rearrangedHosts:
|
|
2088
2087
|
linePrintOut = f'{host.name}:[{host.command}]'.replace('\n', ' ').replace('\r', ' ').strip()
|
|
2089
2088
|
_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)
|
|
2090
2089
|
# clear the window
|
|
2091
2090
|
for i in range(host_window_height - 1):
|
|
2092
2091
|
_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)
|
|
2092
|
+
host.lineNumToPrintSet.update(range(len(host.output)))
|
|
2093
2093
|
# for i in range(host.printedLines, len(host.output)):
|
|
2094
2094
|
# _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)
|
|
2095
2095
|
# host.printedLines = len(host.output)
|
|
@@ -2110,7 +2110,7 @@ def __generate_display(stdscr, hosts, lineToDisplay = -1,curserPosition = 0, min
|
|
|
2110
2110
|
if org_dim != stdscr.getmaxyx():
|
|
2111
2111
|
return (lineToDisplay,curserPosition , min_char_len, min_line_len, single_window, 'Terminal resize detected')
|
|
2112
2112
|
host_window.refresh()
|
|
2113
|
-
|
|
2113
|
+
hosts_to_display, host_stats,rearrangedHosts = _get_hosts_to_display(hosts, max_num_hosts,hosts_to_display)
|
|
2114
2114
|
last_refresh_time = time.perf_counter()
|
|
2115
2115
|
except Exception as e:
|
|
2116
2116
|
import traceback
|
|
@@ -2263,7 +2263,7 @@ def generate_output(hosts, usejson = False, greppable = False):
|
|
|
2263
2263
|
rtnStr += "User Inputs: \n "
|
|
2264
2264
|
rtnStr += '\n '.join(CMDsOut)
|
|
2265
2265
|
rtnStr += '\n'
|
|
2266
|
-
__keyPressesIn
|
|
2266
|
+
__keyPressesIn[-1].clear()
|
|
2267
2267
|
if __global_suppress_printout and not outputs:
|
|
2268
2268
|
rtnStr += 'Success'
|
|
2269
2269
|
return rtnStr
|
|
@@ -2438,7 +2438,7 @@ def getStrCommand(hosts = DEFAULT_HOSTS,commands = None,oneonone = DEFAULT_ONE_O
|
|
|
2438
2438
|
copy_id = False, unavailable_host_expiry = DEFAULT_UNAVAILABLE_HOST_EXPIRY,no_history = DEFAULT_NO_HISTORY,
|
|
2439
2439
|
history_file = DEFAULT_HISTORY_FILE, env_file = DEFAULT_ENV_FILE,
|
|
2440
2440
|
repeat = DEFAULT_REPEAT,interval = DEFAULT_INTERVAL,
|
|
2441
|
-
shortend = False):
|
|
2441
|
+
shortend = False,tabSeperated = False):
|
|
2442
2442
|
_ = called
|
|
2443
2443
|
_ = returnUnfinished
|
|
2444
2444
|
_ = willUpdateUnreachableHosts
|
|
@@ -2462,7 +2462,10 @@ def getStrCommand(hosts = DEFAULT_HOSTS,commands = None,oneonone = DEFAULT_ONE_O
|
|
|
2462
2462
|
commandStr = '"' + '" "'.join(commands) + '"' if commands else ''
|
|
2463
2463
|
filePath = os.path.abspath(__file__)
|
|
2464
2464
|
programName = filePath if filePath else 'mssh'
|
|
2465
|
-
|
|
2465
|
+
if tabSeperated:
|
|
2466
|
+
return f'{programName}\t{argsStr}\t{hostStr}\t{commandStr}'
|
|
2467
|
+
else:
|
|
2468
|
+
return f'{programName} {argsStr} {hostStr} {commandStr}'
|
|
2466
2469
|
|
|
2467
2470
|
#%% ------------ Record History Block ----------------
|
|
2468
2471
|
def record_command_history(kwargs):
|
|
@@ -2486,7 +2489,7 @@ def record_command_history(kwargs):
|
|
|
2486
2489
|
for name in sig.parameters
|
|
2487
2490
|
if name in kwargs
|
|
2488
2491
|
}
|
|
2489
|
-
strCommand = getStrCommand(**wanted)
|
|
2492
|
+
strCommand = getStrCommand(**wanted,shortend=True,tabSeperated=True)
|
|
2490
2493
|
with open(history_file, 'a') as f:
|
|
2491
2494
|
# it follows <timestamp>\t<strCommand>\n
|
|
2492
2495
|
f.write(f'{int(time.time())}\t{strCommand}\n')
|
|
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
|