From 6ba32048169ced9775578940d3d70460d9d911f9 Mon Sep 17 00:00:00 2001 From: Christopher Haster Date: Mon, 11 Aug 2025 00:31:26 -0500 Subject: [PATCH] scripts: Some csv script tweaks to better interact with other scripts - Added --small-total. Like --small-header, this omits the first column which usually just has the informative text TOTAL. - Tweaked -Q/--small-table so it renders with --small-total if -Y/--summary is provided. - Added --total as an alias for --summary + --no-header + --small-total, i.e. printing only the totals (which may be multiple columns) and no other decoration. This is useful for scripting, now it's possible to extract just, say, the sum of some csv and embed with $(): echo $(./scripts/code.py lfs3.o --total) - Tweaked total to always output a number (0) instead of a dash (-), even if we have no results. This relies on Result() with no args, which risks breaking scripts where the Result type expects an argument. To hopefully catch this early, the table renderer currently creates a Result() before trying to fold the total result. - If first column is empty (--small-total + --small-header, --no-header, etc) collapse width to zero. This avoids a bunch of extra whitespace, but still includes the two spaces normal used to separate names from fields. But I think those spaces are a good thing. It makes it hard to miss the implicit padding in the table renderer that risks breaking dependent scripts. --- scripts/code.py | 42 +++++++++++++++++++++++++++++++++++------- scripts/cov.py | 42 +++++++++++++++++++++++++++++++++++------- scripts/csv.py | 42 +++++++++++++++++++++++++++++++++++------- scripts/ctx.py | 42 +++++++++++++++++++++++++++++++++++------- scripts/data.py | 42 +++++++++++++++++++++++++++++++++++------- scripts/perf.py | 42 +++++++++++++++++++++++++++++++++++------- scripts/perfbd.py | 42 +++++++++++++++++++++++++++++++++++------- scripts/stack.py | 42 +++++++++++++++++++++++++++++++++++------- scripts/structs.py | 42 +++++++++++++++++++++++++++++++++++------- 9 files changed, 315 insertions(+), 63 deletions(-) diff --git a/scripts/code.py b/scripts/code.py index d615e5c9..aa94ee8f 100755 --- a/scripts/code.py +++ b/scripts/code.py @@ -611,12 +611,28 @@ def table(Result, results, diff_results=None, *, no_header=False, small_header=False, no_total=False, + small_total=False, small_table=False, summary=False, + total=False, **_): import builtins all_, all = all, builtins.all + # small_table implies small_header + no_total or small_total + if small_table: + small_header = True + small_total = True + no_total = no_total or (not summary and not total) + # summary implies small_header + if summary: + small_header = True + # total implies summary + no_header + small_total + if total: + summary = True + no_header = True + small_total = True + if by is None: by = Result._by if fields is None: @@ -664,8 +680,7 @@ def table(Result, results, diff_results=None, *, sum(1 for n in table if n not in diff_table), sum(1 for n in diff_table if n not in table)) if diff_results is not None and not percent else '') - if not small_header and not small_table and not summary - else ''] + if not small_header else ''] if diff_results is None or percent: for k in fields: header.append(k) @@ -861,13 +876,15 @@ def table(Result, results, diff_results=None, *, table_recurse(results, diff_results, depth) # total - if not no_total and not (small_table and not summary): - r = next(iter(fold(Result, results, by=[])), None) + if not no_total: + r = next(iter(fold(Result, results, by=[])), Result()) if diff_results is None: diff_r = None else: - diff_r = next(iter(fold(Result, diff_results, by=[])), None) - lines.append(table_entry('TOTAL', r, diff_r)) + diff_r = next(iter(fold(Result, diff_results, by=[])), Result()) + lines.append(table_entry( + 'TOTAL' if not small_total else '', + r, diff_r)) # homogenize lines = [[x if isinstance(x, tuple) else (x, []) for x in line] @@ -882,6 +899,8 @@ def table(Result, results, diff_results=None, *, widths[i] = max(widths[i], ((len(x[0])+1+4-1)//4)*4-1) if i != len(line)-1: nwidths[i] = max(nwidths[i], 1+sum(2+len(n) for n in x[1])) + if not any(line[0][0] for line in lines): + widths[0] = 0 # print our table for line in lines: @@ -1202,14 +1221,23 @@ if __name__ == "__main__": '--no-total', action='store_true', help="Don't show the total.") + parser.add_argument( + '--small-total', + action='store_true', + help="Don't show TOTAL name.") parser.add_argument( '-Q', '--small-table', action='store_true', - help="Equivalent to --small-header + --no-total.") + help="Equivalent to --small-header + --no-total or --small-total.") parser.add_argument( '-Y', '--summary', action='store_true', help="Only show the total.") + parser.add_argument( + '--total', + action='store_true', + help="Equivalent to --summary + --no-header + --small-total. " + "Useful for scripting.") parser.add_argument( '--prefix', help="Prefix to use for fields in CSV/JSON output. Defaults " diff --git a/scripts/cov.py b/scripts/cov.py index 9701062b..b7bfcced 100755 --- a/scripts/cov.py +++ b/scripts/cov.py @@ -474,12 +474,28 @@ def table(Result, results, diff_results=None, *, no_header=False, small_header=False, no_total=False, + small_total=False, small_table=False, summary=False, + total=False, **_): import builtins all_, all = all, builtins.all + # small_table implies small_header + no_total or small_total + if small_table: + small_header = True + small_total = True + no_total = no_total or (not summary and not total) + # summary implies small_header + if summary: + small_header = True + # total implies summary + no_header + small_total + if total: + summary = True + no_header = True + small_total = True + if by is None: by = Result._by if fields is None: @@ -527,8 +543,7 @@ def table(Result, results, diff_results=None, *, sum(1 for n in table if n not in diff_table), sum(1 for n in diff_table if n not in table)) if diff_results is not None and not percent else '') - if not small_header and not small_table and not summary - else ''] + if not small_header else ''] if diff_results is None or percent: for k in fields: header.append(k) @@ -724,13 +739,15 @@ def table(Result, results, diff_results=None, *, table_recurse(results, diff_results, depth) # total - if not no_total and not (small_table and not summary): - r = next(iter(fold(Result, results, by=[])), None) + if not no_total: + r = next(iter(fold(Result, results, by=[])), Result()) if diff_results is None: diff_r = None else: - diff_r = next(iter(fold(Result, diff_results, by=[])), None) - lines.append(table_entry('TOTAL', r, diff_r)) + diff_r = next(iter(fold(Result, diff_results, by=[])), Result()) + lines.append(table_entry( + 'TOTAL' if not small_total else '', + r, diff_r)) # homogenize lines = [[x if isinstance(x, tuple) else (x, []) for x in line] @@ -745,6 +762,8 @@ def table(Result, results, diff_results=None, *, widths[i] = max(widths[i], ((len(x[0])+1+4-1)//4)*4-1) if i != len(line)-1: nwidths[i] = max(nwidths[i], 1+sum(2+len(n) for n in x[1])) + if not any(line[0][0] for line in lines): + widths[0] = 0 # print our table for line in lines: @@ -1175,14 +1194,23 @@ if __name__ == "__main__": '--no-total', action='store_true', help="Don't show the total.") + parser.add_argument( + '--small-total', + action='store_true', + help="Don't show TOTAL name.") parser.add_argument( '-Q', '--small-table', action='store_true', - help="Equivalent to --small-header + --no-total.") + help="Equivalent to --small-header + --no-total or --small-total.") parser.add_argument( '-Y', '--summary', action='store_true', help="Only show the total.") + parser.add_argument( + '--total', + action='store_true', + help="Equivalent to --summary + --no-header + --small-total. " + "Useful for scripting.") parser.add_argument( '--prefix', help="Prefix to use for fields in CSV/JSON output. Defaults " diff --git a/scripts/csv.py b/scripts/csv.py index 68a8bb67..a987ee76 100755 --- a/scripts/csv.py +++ b/scripts/csv.py @@ -1829,12 +1829,28 @@ def table(Result, results, diff_results=None, *, no_header=False, small_header=False, no_total=False, + small_total=False, small_table=False, summary=False, + total=False, **_): import builtins all_, all = all, builtins.all + # small_table implies small_header + no_total or small_total + if small_table: + small_header = True + small_total = True + no_total = no_total or (not summary and not total) + # summary implies small_header + if summary: + small_header = True + # total implies summary + no_header + small_total + if total: + summary = True + no_header = True + small_total = True + if by is None: by = Result._by if fields is None: @@ -1882,8 +1898,7 @@ def table(Result, results, diff_results=None, *, sum(1 for n in table if n not in diff_table), sum(1 for n in diff_table if n not in table)) if diff_results is not None and not percent else '') - if not small_header and not small_table and not summary - else ''] + if not small_header else ''] if diff_results is None or percent: for k in fields: header.append(k) @@ -2079,13 +2094,15 @@ def table(Result, results, diff_results=None, *, table_recurse(results, diff_results, depth) # total - if not no_total and not (small_table and not summary): - r = next(iter(fold(Result, results, by=[])), None) + if not no_total: + r = next(iter(fold(Result, results, by=[])), Result()) if diff_results is None: diff_r = None else: - diff_r = next(iter(fold(Result, diff_results, by=[])), None) - lines.append(table_entry('TOTAL', r, diff_r)) + diff_r = next(iter(fold(Result, diff_results, by=[])), Result()) + lines.append(table_entry( + 'TOTAL' if not small_total else '', + r, diff_r)) # homogenize lines = [[x if isinstance(x, tuple) else (x, []) for x in line] @@ -2100,6 +2117,8 @@ def table(Result, results, diff_results=None, *, widths[i] = max(widths[i], ((len(x[0])+1+4-1)//4)*4-1) if i != len(line)-1: nwidths[i] = max(nwidths[i], 1+sum(2+len(n) for n in x[1])) + if not any(line[0][0] for line in lines): + widths[0] = 0 # print our table for line in lines: @@ -2708,14 +2727,23 @@ if __name__ == "__main__": '--no-total', action='store_true', help="Don't show the total.") + parser.add_argument( + '--small-total', + action='store_true', + help="Don't show TOTAL name.") parser.add_argument( '-Q', '--small-table', action='store_true', - help="Equivalent to --small-header + --no-total.") + help="Equivalent to --small-header + --no-total or --small-total.") parser.add_argument( '-Y', '--summary', action='store_true', help="Only show the total.") + parser.add_argument( + '--total', + action='store_true', + help="Equivalent to --summary + --no-header + --small-total. " + "Useful for scripting.") parser.add_argument( '--prefix', help="Prefix to use for fields in CSV/JSON output.") diff --git a/scripts/ctx.py b/scripts/ctx.py index ee4421d7..fbf12a36 100755 --- a/scripts/ctx.py +++ b/scripts/ctx.py @@ -873,12 +873,28 @@ def table(Result, results, diff_results=None, *, no_header=False, small_header=False, no_total=False, + small_total=False, small_table=False, summary=False, + total=False, **_): import builtins all_, all = all, builtins.all + # small_table implies small_header + no_total or small_total + if small_table: + small_header = True + small_total = True + no_total = no_total or (not summary and not total) + # summary implies small_header + if summary: + small_header = True + # total implies summary + no_header + small_total + if total: + summary = True + no_header = True + small_total = True + if by is None: by = Result._by if fields is None: @@ -926,8 +942,7 @@ def table(Result, results, diff_results=None, *, sum(1 for n in table if n not in diff_table), sum(1 for n in diff_table if n not in table)) if diff_results is not None and not percent else '') - if not small_header and not small_table and not summary - else ''] + if not small_header else ''] if diff_results is None or percent: for k in fields: header.append(k) @@ -1123,13 +1138,15 @@ def table(Result, results, diff_results=None, *, table_recurse(results, diff_results, depth) # total - if not no_total and not (small_table and not summary): - r = next(iter(fold(Result, results, by=[])), None) + if not no_total: + r = next(iter(fold(Result, results, by=[])), Result()) if diff_results is None: diff_r = None else: - diff_r = next(iter(fold(Result, diff_results, by=[])), None) - lines.append(table_entry('TOTAL', r, diff_r)) + diff_r = next(iter(fold(Result, diff_results, by=[])), Result()) + lines.append(table_entry( + 'TOTAL' if not small_total else '', + r, diff_r)) # homogenize lines = [[x if isinstance(x, tuple) else (x, []) for x in line] @@ -1144,6 +1161,8 @@ def table(Result, results, diff_results=None, *, widths[i] = max(widths[i], ((len(x[0])+1+4-1)//4)*4-1) if i != len(line)-1: nwidths[i] = max(nwidths[i], 1+sum(2+len(n) for n in x[1])) + if not any(line[0][0] for line in lines): + widths[0] = 0 # print our table for line in lines: @@ -1523,14 +1542,23 @@ if __name__ == "__main__": '--no-total', action='store_true', help="Don't show the total.") + parser.add_argument( + '--small-total', + action='store_true', + help="Don't show TOTAL name.") parser.add_argument( '-Q', '--small-table', action='store_true', - help="Equivalent to --small-header + --no-total.") + help="Equivalent to --small-header + --no-total or --small-total.") parser.add_argument( '-Y', '--summary', action='store_true', help="Only show the total.") + parser.add_argument( + '--total', + action='store_true', + help="Equivalent to --summary + --no-header + --small-total. " + "Useful for scripting.") parser.add_argument( '--prefix', help="Prefix to use for fields in CSV/JSON output. Defaults " diff --git a/scripts/data.py b/scripts/data.py index d9f78799..15100d08 100755 --- a/scripts/data.py +++ b/scripts/data.py @@ -611,12 +611,28 @@ def table(Result, results, diff_results=None, *, no_header=False, small_header=False, no_total=False, + small_total=False, small_table=False, summary=False, + total=False, **_): import builtins all_, all = all, builtins.all + # small_table implies small_header + no_total or small_total + if small_table: + small_header = True + small_total = True + no_total = no_total or (not summary and not total) + # summary implies small_header + if summary: + small_header = True + # total implies summary + no_header + small_total + if total: + summary = True + no_header = True + small_total = True + if by is None: by = Result._by if fields is None: @@ -664,8 +680,7 @@ def table(Result, results, diff_results=None, *, sum(1 for n in table if n not in diff_table), sum(1 for n in diff_table if n not in table)) if diff_results is not None and not percent else '') - if not small_header and not small_table and not summary - else ''] + if not small_header else ''] if diff_results is None or percent: for k in fields: header.append(k) @@ -861,13 +876,15 @@ def table(Result, results, diff_results=None, *, table_recurse(results, diff_results, depth) # total - if not no_total and not (small_table and not summary): - r = next(iter(fold(Result, results, by=[])), None) + if not no_total: + r = next(iter(fold(Result, results, by=[])), Result()) if diff_results is None: diff_r = None else: - diff_r = next(iter(fold(Result, diff_results, by=[])), None) - lines.append(table_entry('TOTAL', r, diff_r)) + diff_r = next(iter(fold(Result, diff_results, by=[])), Result()) + lines.append(table_entry( + 'TOTAL' if not small_total else '', + r, diff_r)) # homogenize lines = [[x if isinstance(x, tuple) else (x, []) for x in line] @@ -882,6 +899,8 @@ def table(Result, results, diff_results=None, *, widths[i] = max(widths[i], ((len(x[0])+1+4-1)//4)*4-1) if i != len(line)-1: nwidths[i] = max(nwidths[i], 1+sum(2+len(n) for n in x[1])) + if not any(line[0][0] for line in lines): + widths[0] = 0 # print our table for line in lines: @@ -1202,14 +1221,23 @@ if __name__ == "__main__": '--no-total', action='store_true', help="Don't show the total.") + parser.add_argument( + '--small-total', + action='store_true', + help="Don't show TOTAL name.") parser.add_argument( '-Q', '--small-table', action='store_true', - help="Equivalent to --small-header + --no-total.") + help="Equivalent to --small-header + --no-total or --small-total.") parser.add_argument( '-Y', '--summary', action='store_true', help="Only show the total.") + parser.add_argument( + '--total', + action='store_true', + help="Equivalent to --summary + --no-header + --small-total. " + "Useful for scripting.") parser.add_argument( '--prefix', help="Prefix to use for fields in CSV/JSON output. Defaults " diff --git a/scripts/perf.py b/scripts/perf.py index d3754337..651f755c 100755 --- a/scripts/perf.py +++ b/scripts/perf.py @@ -972,12 +972,28 @@ def table(Result, results, diff_results=None, *, no_header=False, small_header=False, no_total=False, + small_total=False, small_table=False, summary=False, + total=False, **_): import builtins all_, all = all, builtins.all + # small_table implies small_header + no_total or small_total + if small_table: + small_header = True + small_total = True + no_total = no_total or (not summary and not total) + # summary implies small_header + if summary: + small_header = True + # total implies summary + no_header + small_total + if total: + summary = True + no_header = True + small_total = True + if by is None: by = Result._by if fields is None: @@ -1025,8 +1041,7 @@ def table(Result, results, diff_results=None, *, sum(1 for n in table if n not in diff_table), sum(1 for n in diff_table if n not in table)) if diff_results is not None and not percent else '') - if not small_header and not small_table and not summary - else ''] + if not small_header else ''] if diff_results is None or percent: for k in fields: header.append(k) @@ -1222,13 +1237,15 @@ def table(Result, results, diff_results=None, *, table_recurse(results, diff_results, depth) # total - if not no_total and not (small_table and not summary): - r = next(iter(fold(Result, results, by=[])), None) + if not no_total: + r = next(iter(fold(Result, results, by=[])), Result()) if diff_results is None: diff_r = None else: - diff_r = next(iter(fold(Result, diff_results, by=[])), None) - lines.append(table_entry('TOTAL', r, diff_r)) + diff_r = next(iter(fold(Result, diff_results, by=[])), Result()) + lines.append(table_entry( + 'TOTAL' if not small_total else '', + r, diff_r)) # homogenize lines = [[x if isinstance(x, tuple) else (x, []) for x in line] @@ -1243,6 +1260,8 @@ def table(Result, results, diff_results=None, *, widths[i] = max(widths[i], ((len(x[0])+1+4-1)//4)*4-1) if i != len(line)-1: nwidths[i] = max(nwidths[i], 1+sum(2+len(n) for n in x[1])) + if not any(line[0][0] for line in lines): + widths[0] = 0 # print our table for line in lines: @@ -1772,14 +1791,23 @@ if __name__ == "__main__": '--no-total', action='store_true', help="Don't show the total.") + parser.add_argument( + '--small-total', + action='store_true', + help="Don't show TOTAL name.") parser.add_argument( '-Q', '--small-table', action='store_true', - help="Equivalent to --small-header + --no-total.") + help="Equivalent to --small-header + --no-total or --small-total.") parser.add_argument( '-Y', '--summary', action='store_true', help="Only show the total.") + parser.add_argument( + '--total', + action='store_true', + help="Equivalent to --summary + --no-header + --small-total. " + "Useful for scripting.") parser.add_argument( '--prefix', help="Prefix to use for fields in CSV/JSON output. Defaults " diff --git a/scripts/perfbd.py b/scripts/perfbd.py index d714ba98..664d851b 100755 --- a/scripts/perfbd.py +++ b/scripts/perfbd.py @@ -946,12 +946,28 @@ def table(Result, results, diff_results=None, *, no_header=False, small_header=False, no_total=False, + small_total=False, small_table=False, summary=False, + total=False, **_): import builtins all_, all = all, builtins.all + # small_table implies small_header + no_total or small_total + if small_table: + small_header = True + small_total = True + no_total = no_total or (not summary and not total) + # summary implies small_header + if summary: + small_header = True + # total implies summary + no_header + small_total + if total: + summary = True + no_header = True + small_total = True + if by is None: by = Result._by if fields is None: @@ -999,8 +1015,7 @@ def table(Result, results, diff_results=None, *, sum(1 for n in table if n not in diff_table), sum(1 for n in diff_table if n not in table)) if diff_results is not None and not percent else '') - if not small_header and not small_table and not summary - else ''] + if not small_header else ''] if diff_results is None or percent: for k in fields: header.append(k) @@ -1196,13 +1211,15 @@ def table(Result, results, diff_results=None, *, table_recurse(results, diff_results, depth) # total - if not no_total and not (small_table and not summary): - r = next(iter(fold(Result, results, by=[])), None) + if not no_total: + r = next(iter(fold(Result, results, by=[])), Result()) if diff_results is None: diff_r = None else: - diff_r = next(iter(fold(Result, diff_results, by=[])), None) - lines.append(table_entry('TOTAL', r, diff_r)) + diff_r = next(iter(fold(Result, diff_results, by=[])), Result()) + lines.append(table_entry( + 'TOTAL' if not small_total else '', + r, diff_r)) # homogenize lines = [[x if isinstance(x, tuple) else (x, []) for x in line] @@ -1217,6 +1234,8 @@ def table(Result, results, diff_results=None, *, widths[i] = max(widths[i], ((len(x[0])+1+4-1)//4)*4-1) if i != len(line)-1: nwidths[i] = max(nwidths[i], 1+sum(2+len(n) for n in x[1])) + if not any(line[0][0] for line in lines): + widths[0] = 0 # print our table for line in lines: @@ -1773,14 +1792,23 @@ if __name__ == "__main__": '--no-total', action='store_true', help="Don't show the total.") + parser.add_argument( + '--small-total', + action='store_true', + help="Don't show TOTAL name.") parser.add_argument( '-Q', '--small-table', action='store_true', - help="Equivalent to --small-header + --no-total.") + help="Equivalent to --small-header + --no-total or --small-total.") parser.add_argument( '-Y', '--summary', action='store_true', help="Only show the total.") + parser.add_argument( + '--total', + action='store_true', + help="Equivalent to --summary + --no-header + --small-total. " + "Useful for scripting.") parser.add_argument( '--prefix', help="Prefix to use for fields in CSV/JSON output. Defaults " diff --git a/scripts/stack.py b/scripts/stack.py index c857f9fe..32e9ca0b 100755 --- a/scripts/stack.py +++ b/scripts/stack.py @@ -614,12 +614,28 @@ def table(Result, results, diff_results=None, *, no_header=False, small_header=False, no_total=False, + small_total=False, small_table=False, summary=False, + total=False, **_): import builtins all_, all = all, builtins.all + # small_table implies small_header + no_total or small_total + if small_table: + small_header = True + small_total = True + no_total = no_total or (not summary and not total) + # summary implies small_header + if summary: + small_header = True + # total implies summary + no_header + small_total + if total: + summary = True + no_header = True + small_total = True + if by is None: by = Result._by if fields is None: @@ -667,8 +683,7 @@ def table(Result, results, diff_results=None, *, sum(1 for n in table if n not in diff_table), sum(1 for n in diff_table if n not in table)) if diff_results is not None and not percent else '') - if not small_header and not small_table and not summary - else ''] + if not small_header else ''] if diff_results is None or percent: for k in fields: header.append(k) @@ -864,13 +879,15 @@ def table(Result, results, diff_results=None, *, table_recurse(results, diff_results, depth) # total - if not no_total and not (small_table and not summary): - r = next(iter(fold(Result, results, by=[])), None) + if not no_total: + r = next(iter(fold(Result, results, by=[])), Result()) if diff_results is None: diff_r = None else: - diff_r = next(iter(fold(Result, diff_results, by=[])), None) - lines.append(table_entry('TOTAL', r, diff_r)) + diff_r = next(iter(fold(Result, diff_results, by=[])), Result()) + lines.append(table_entry( + 'TOTAL' if not small_total else '', + r, diff_r)) # homogenize lines = [[x if isinstance(x, tuple) else (x, []) for x in line] @@ -885,6 +902,8 @@ def table(Result, results, diff_results=None, *, widths[i] = max(widths[i], ((len(x[0])+1+4-1)//4)*4-1) if i != len(line)-1: nwidths[i] = max(nwidths[i], 1+sum(2+len(n) for n in x[1])) + if not any(line[0][0] for line in lines): + widths[0] = 0 # print our table for line in lines: @@ -1266,14 +1285,23 @@ if __name__ == "__main__": '--no-total', action='store_true', help="Don't show the total.") + parser.add_argument( + '--small-total', + action='store_true', + help="Don't show TOTAL name.") parser.add_argument( '-Q', '--small-table', action='store_true', - help="Equivalent to --small-header + --no-total.") + help="Equivalent to --small-header + --no-total or --small-total.") parser.add_argument( '-Y', '--summary', action='store_true', help="Only show the total.") + parser.add_argument( + '--total', + action='store_true', + help="Equivalent to --summary + --no-header + --small-total. " + "Useful for scripting.") parser.add_argument( '--prefix', help="Prefix to use for fields in CSV/JSON output. Defaults " diff --git a/scripts/structs.py b/scripts/structs.py index be5bc9ae..0075c4f2 100755 --- a/scripts/structs.py +++ b/scripts/structs.py @@ -762,12 +762,28 @@ def table(Result, results, diff_results=None, *, no_header=False, small_header=False, no_total=False, + small_total=False, small_table=False, summary=False, + total=False, **_): import builtins all_, all = all, builtins.all + # small_table implies small_header + no_total or small_total + if small_table: + small_header = True + small_total = True + no_total = no_total or (not summary and not total) + # summary implies small_header + if summary: + small_header = True + # total implies summary + no_header + small_total + if total: + summary = True + no_header = True + small_total = True + if by is None: by = Result._by if fields is None: @@ -815,8 +831,7 @@ def table(Result, results, diff_results=None, *, sum(1 for n in table if n not in diff_table), sum(1 for n in diff_table if n not in table)) if diff_results is not None and not percent else '') - if not small_header and not small_table and not summary - else ''] + if not small_header else ''] if diff_results is None or percent: for k in fields: header.append(k) @@ -1012,13 +1027,15 @@ def table(Result, results, diff_results=None, *, table_recurse(results, diff_results, depth) # total - if not no_total and not (small_table and not summary): - r = next(iter(fold(Result, results, by=[])), None) + if not no_total: + r = next(iter(fold(Result, results, by=[])), Result()) if diff_results is None: diff_r = None else: - diff_r = next(iter(fold(Result, diff_results, by=[])), None) - lines.append(table_entry('TOTAL', r, diff_r)) + diff_r = next(iter(fold(Result, diff_results, by=[])), Result()) + lines.append(table_entry( + 'TOTAL' if not small_total else '', + r, diff_r)) # homogenize lines = [[x if isinstance(x, tuple) else (x, []) for x in line] @@ -1033,6 +1050,8 @@ def table(Result, results, diff_results=None, *, widths[i] = max(widths[i], ((len(x[0])+1+4-1)//4)*4-1) if i != len(line)-1: nwidths[i] = max(nwidths[i], 1+sum(2+len(n) for n in x[1])) + if not any(line[0][0] for line in lines): + widths[0] = 0 # print our table for line in lines: @@ -1412,14 +1431,23 @@ if __name__ == "__main__": '--no-total', action='store_true', help="Don't show the total.") + parser.add_argument( + '--small-total', + action='store_true', + help="Don't show TOTAL name.") parser.add_argument( '-Q', '--small-table', action='store_true', - help="Equivalent to --small-header + --no-total.") + help="Equivalent to --small-header + --no-total or --small-total.") parser.add_argument( '-Y', '--summary', action='store_true', help="Only show the total.") + parser.add_argument( + '--total', + action='store_true', + help="Equivalent to --summary + --no-header + --small-total. " + "Useful for scripting.") parser.add_argument( '--prefix', help="Prefix to use for fields in CSV/JSON output. Defaults "