multiSSH3 5.51__tar.gz → 5.52__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: multiSSH3
3
- Version: 5.51
3
+ Version: 5.52
4
4
  Summary: Run commands on multiple hosts via SSH
5
5
  Home-page: https://github.com/yufei-pan/multiSSH3
6
6
  Author: Yufei Pan
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: multiSSH3
3
- Version: 5.51
3
+ Version: 5.52
4
4
  Summary: Run commands on multiple hosts via SSH
5
5
  Home-page: https://github.com/yufei-pan/multiSSH3
6
6
  Author: Yufei Pan
@@ -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.51'
57
+ version = '5.52'
58
58
  VERSION = version
59
59
  __version__ = version
60
- COMMIT_DATE = '2025-01-30'
60
+ COMMIT_DATE = '2025-03-01'
61
61
 
62
62
  CONFIG_FILE_CHAIN = ['./multiSSH3.config.json',
63
63
  '~/multiSSH3.config.json',
@@ -490,49 +490,69 @@ def replace_magic_strings(string,keys,value,case_sensitive=False):
490
490
  string = re.sub(re.escape(key),value,string,flags=re.IGNORECASE)
491
491
  return string
492
492
 
493
- def pretty_format_table(data):
494
- version = 1.0
495
- if not data:
496
- return ''
497
- if type(data) == str:
498
- data = data.strip('\n').split('\n')
499
- data = [line.split('\t') for line in data]
500
- elif isinstance(data, dict):
501
- # flatten the 2D dict to a list of lists
502
- if isinstance(next(iter(data.values())), dict):
503
- tempData = [['key'] + list(next(iter(data.values())).keys())]
504
- tempData.extend( [[key] + list(value.values()) for key, value in data.items()])
505
- data = tempData
506
- else:
507
- # it is a dict of lists
508
- data = [[key] + list(value) for key, value in data.items()]
509
- elif type(data) != list:
510
- data = list(data)
511
- # format the list into 2d list of list of strings
512
- if isinstance(data[0], dict):
513
- tempData = [data[0].keys()]
514
- tempData.extend([list(item.values()) for item in data])
515
- data = tempData
516
- data = [[str(item) for item in row] for row in data]
517
- num_cols = len(data[0])
518
- col_widths = [0] * num_cols
519
- # Calculate the maximum width of each column
520
- for c in range(num_cols):
521
- col_widths[c] = max(len(row[c]) for row in data)
522
- # Build the row format string
523
- row_format = ' | '.join('{{:<{}}}'.format(width) for width in col_widths)
524
- # Print the header
525
- header = data[0]
526
- outTable = []
527
- outTable.append(row_format.format(*header))
528
- outTable.append('-+-'.join('-' * width for width in col_widths))
529
- for row in data[1:]:
530
- # if the row is empty, print an divider
531
- if not any(row):
532
- outTable.append('-+-'.join('-' * width for width in col_widths))
533
- else:
534
- outTable.append(row_format.format(*row))
535
- return '\n'.join(outTable) + '\n'
493
+ def pretty_format_table(data, delimiter = '\t',header = None):
494
+ version = 1.1
495
+ if not data:
496
+ return ''
497
+ if type(data) == str:
498
+ data = data.strip('\n').split('\n')
499
+ data = [line.split(delimiter) for line in data]
500
+ elif isinstance(data, dict):
501
+ # flatten the 2D dict to a list of lists
502
+ if isinstance(next(iter(data.values())), dict):
503
+ tempData = [['key'] + list(next(iter(data.values())).keys())]
504
+ tempData.extend( [[key] + list(value.values()) for key, value in data.items()])
505
+ data = tempData
506
+ else:
507
+ # it is a dict of lists
508
+ data = [[key] + list(value) for key, value in data.items()]
509
+ elif type(data) != list:
510
+ data = list(data)
511
+ # format the list into 2d list of list of strings
512
+ if isinstance(data[0], dict):
513
+ tempData = [data[0].keys()]
514
+ tempData.extend([list(item.values()) for item in data])
515
+ data = tempData
516
+ data = [[str(item) for item in row] for row in data]
517
+ num_cols = len(data[0])
518
+ col_widths = [0] * num_cols
519
+ # Calculate the maximum width of each column
520
+ for c in range(num_cols):
521
+ #col_widths[c] = max(len(row[c]) for row in data)
522
+ # handle ansii escape sequences
523
+ col_widths[c] = max(len(re.sub(r'\x1b\[[0-?]*[ -/]*[@-~]','',row[c])) for row in data)
524
+ # Build the row format string
525
+ row_format = ' | '.join('{{:<{}}}'.format(width) for width in col_widths)
526
+ # Print the header
527
+ if not header:
528
+ header = data[0]
529
+ outTable = []
530
+ outTable.append(row_format.format(*header))
531
+ outTable.append('-+-'.join('-' * width for width in col_widths))
532
+ for row in data[1:]:
533
+ # if the row is empty, print an divider
534
+ if not any(row):
535
+ outTable.append('-+-'.join('-' * width for width in col_widths))
536
+ else:
537
+ outTable.append(row_format.format(*row))
538
+ else:
539
+ # pad / truncate header to appropriate length
540
+ if isinstance(header,str):
541
+ header = header.split(delimiter)
542
+ if len(header) < num_cols:
543
+ header += ['']*(num_cols-len(header))
544
+ elif len(header) > num_cols:
545
+ header = header[:num_cols]
546
+ outTable = []
547
+ outTable.append(row_format.format(*header))
548
+ outTable.append('-+-'.join('-' * width for width in col_widths))
549
+ for row in data:
550
+ # if the row is empty, print an divider
551
+ if not any(row):
552
+ outTable.append('-+-'.join('-' * width for width in col_widths))
553
+ else:
554
+ outTable.append(row_format.format(*row))
555
+ return '\n'.join(outTable) + '\n'
536
556
 
537
557
  # ------------ Compacting Hostnames ----------------
538
558
  def __tokenize_hostname(hostname):
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes