From 274222b5186dad50c13d9f409636359627bf8435 Mon Sep 17 00:00:00 2001 From: Christopher Haster Date: Tue, 27 Sep 2022 15:25:53 -0500 Subject: [PATCH] Added some automatic sizing for field-names in scripts/runners --- runners/bench_runner.c | 84 ++++++++++++++++++++---- runners/test_runner.c | 105 ++++++++++++++++++++++++----- scripts/code.py | 26 +++++--- scripts/coverage.py | 34 +++++----- scripts/data.py | 26 +++++--- scripts/stack.py | 27 +++++--- scripts/struct_.py | 26 +++++--- scripts/summary.py | 146 +++++++++++++++++++++++++---------------- 8 files changed, 331 insertions(+), 143 deletions(-) diff --git a/runners/bench_runner.c b/runners/bench_runner.c index f7e33479..7a6e2fa5 100644 --- a/runners/bench_runner.c +++ b/runners/bench_runner.c @@ -665,7 +665,7 @@ void perm_count( // operations we can do static void summary(void) { - printf("%-36s %7s %7s %7s %11s\n", + printf("%-23s %7s %7s %7s %11s\n", "", "flags", "suites", "cases", "perms"); size_t suites = 0; size_t cases = 0; @@ -707,7 +707,7 @@ static void summary(void) { sprintf(flag_buf, "%s%s", (flags & BENCH_REENTRANT) ? "r" : "", (!flags) ? "-" : ""); - printf("%-36s %7s %7zu %7zu %11s\n", + printf("%-23s %7s %7zu %7zu %11s\n", "TOTAL", flag_buf, suites, @@ -716,8 +716,18 @@ static void summary(void) { } static void list_suites(void) { - printf("%-36s %7s %7s %11s\n", "suite", "flags", "cases", "perms"); + // at least size so that names fit + unsigned name_width = 23; + for (size_t i = 0; i < BENCH_SUITE_COUNT; i++) { + size_t len = strlen(bench_suites[i].name); + if (len > name_width) { + name_width = len; + } + } + name_width = 4*((name_width+1+4-1)/4)-1; + printf("%-*s %7s %7s %11s\n", + name_width, "suite", "flags", "cases", "perms"); for (size_t t = 0; t < bench_id_count; t++) { for (size_t i = 0; i < BENCH_SUITE_COUNT; i++) { bench_define_suite(&bench_suites[i]); @@ -756,7 +766,8 @@ static void list_suites(void) { sprintf(flag_buf, "%s%s", (bench_suites[i].flags & BENCH_REENTRANT) ? "r" : "", (!bench_suites[i].flags) ? "-" : ""); - printf("%-36s %7s %7zu %11s\n", + printf("%-*s %7s %7zu %11s\n", + name_width, bench_suites[i].name, flag_buf, cases, @@ -766,8 +777,19 @@ static void list_suites(void) { } static void list_cases(void) { - printf("%-36s %7s %11s\n", "case", "flags", "perms"); + // at least size so that names fit + unsigned name_width = 23; + for (size_t i = 0; i < BENCH_SUITE_COUNT; i++) { + for (size_t j = 0; j < bench_suites[i].case_count; j++) { + size_t len = strlen(bench_suites[i].cases[j].name); + if (len > name_width) { + name_width = len; + } + } + } + name_width = 4*((name_width+1+4-1)/4)-1; + printf("%-*s %7s %11s\n", name_width, "case", "flags", "perms"); for (size_t t = 0; t < bench_id_count; t++) { for (size_t i = 0; i < BENCH_SUITE_COUNT; i++) { bench_define_suite(&bench_suites[i]); @@ -799,7 +821,8 @@ static void list_cases(void) { ? "r" : "", (!bench_suites[i].cases[j].flags) ? "-" : ""); - printf("%-36s %7s %11s\n", + printf("%-*s %7s %11s\n", + name_width, bench_suites[i].cases[j].name, flag_buf, perm_buf); @@ -809,8 +832,17 @@ static void list_cases(void) { } static void list_suite_paths(void) { - printf("%-36s %s\n", "suite", "path"); + // at least size so that names fit + unsigned name_width = 23; + for (size_t i = 0; i < BENCH_SUITE_COUNT; i++) { + size_t len = strlen(bench_suites[i].name); + if (len > name_width) { + name_width = len; + } + } + name_width = 4*((name_width+1+4-1)/4)-1; + printf("%-*s %s\n", name_width, "suite", "path"); for (size_t t = 0; t < bench_id_count; t++) { for (size_t i = 0; i < BENCH_SUITE_COUNT; i++) { size_t cases = 0; @@ -823,6 +855,8 @@ static void list_suite_paths(void) { || strcmp(bench_ids[t].name, bench_suites[i].cases[j].name) == 0)) { continue; + + cases += 1; } } @@ -831,7 +865,8 @@ static void list_suite_paths(void) { continue; } - printf("%-36s %s\n", + printf("%-*s %s\n", + name_width, bench_suites[i].name, bench_suites[i].path); } @@ -839,8 +874,19 @@ static void list_suite_paths(void) { } static void list_case_paths(void) { - printf("%-36s %s\n", "case", "path"); + // at least size so that names fit + unsigned name_width = 23; + for (size_t i = 0; i < BENCH_SUITE_COUNT; i++) { + for (size_t j = 0; j < bench_suites[i].case_count; j++) { + size_t len = strlen(bench_suites[i].cases[j].name); + if (len > name_width) { + name_width = len; + } + } + } + name_width = 4*((name_width+1+4-1)/4)-1; + printf("%-*s %s\n", name_width, "case", "path"); for (size_t t = 0; t < bench_id_count; t++) { for (size_t i = 0; i < BENCH_SUITE_COUNT; i++) { for (size_t j = 0; j < bench_suites[i].case_count; j++) { @@ -853,7 +899,8 @@ static void list_case_paths(void) { continue; } - printf("%-36s %s\n", + printf("%-*s %s\n", + name_width, bench_suites[i].cases[j].name, bench_suites[i].cases[j].path); } @@ -1099,16 +1146,27 @@ const bench_geometry_t *bench_geometries = builtin_geometries; size_t bench_geometry_count = 5; static void list_geometries(void) { + // at least size so that names fit + unsigned name_width = 23; + for (size_t g = 0; builtin_geometries[g].name; g++) { + size_t len = strlen(builtin_geometries[g].name); + if (len > name_width) { + name_width = len; + } + } + name_width = 4*((name_width+1+4-1)/4)-1; + // yes we do need to define a suite, this does a bit of bookeeping // such as setting up the define cache bench_define_suite(&(const struct bench_suite){0}); - printf("%-24s %7s %7s %7s %7s %11s\n", - "geometry", "read", "prog", "erase", "count", "size"); + printf("%-*s %7s %7s %7s %7s %11s\n", + name_width, "geometry", "read", "prog", "erase", "count", "size"); for (size_t g = 0; builtin_geometries[g].name; g++) { bench_define_geometry(&builtin_geometries[g]); bench_define_flush(); - printf("%-24s %7ju %7ju %7ju %7ju %11ju\n", + printf("%-*s %7ju %7ju %7ju %7ju %11ju\n", + name_width, builtin_geometries[g].name, READ_SIZE, PROG_SIZE, diff --git a/runners/test_runner.c b/runners/test_runner.c index f0e1ff6e..7b754474 100644 --- a/runners/test_runner.c +++ b/runners/test_runner.c @@ -691,7 +691,7 @@ void perm_count( // operations we can do static void summary(void) { - printf("%-36s %7s %7s %7s %11s\n", + printf("%-23s %7s %7s %7s %11s\n", "", "flags", "suites", "cases", "perms"); size_t suites = 0; size_t cases = 0; @@ -735,7 +735,7 @@ static void summary(void) { sprintf(flag_buf, "%s%s", (flags & TEST_REENTRANT) ? "r" : "", (!flags) ? "-" : ""); - printf("%-36s %7s %7zu %7zu %11s\n", + printf("%-23s %7s %7zu %7zu %11s\n", "TOTAL", flag_buf, suites, @@ -744,8 +744,18 @@ static void summary(void) { } static void list_suites(void) { - printf("%-36s %7s %7s %11s\n", "suite", "flags", "cases", "perms"); + // at least size so that names fit + unsigned name_width = 23; + for (size_t i = 0; i < TEST_SUITE_COUNT; i++) { + size_t len = strlen(test_suites[i].name); + if (len > name_width) { + name_width = len; + } + } + name_width = 4*((name_width+1+4-1)/4)-1; + printf("%-*s %7s %7s %11s\n", + name_width, "suite", "flags", "cases", "perms"); for (size_t t = 0; t < test_id_count; t++) { for (size_t i = 0; i < TEST_SUITE_COUNT; i++) { test_define_suite(&test_suites[i]); @@ -786,7 +796,8 @@ static void list_suites(void) { sprintf(flag_buf, "%s%s", (test_suites[i].flags & TEST_REENTRANT) ? "r" : "", (!test_suites[i].flags) ? "-" : ""); - printf("%-36s %7s %7zu %11s\n", + printf("%-*s %7s %7zu %11s\n", + name_width, test_suites[i].name, flag_buf, cases, @@ -796,8 +807,19 @@ static void list_suites(void) { } static void list_cases(void) { - printf("%-36s %7s %11s\n", "case", "flags", "perms"); + // at least size so that names fit + unsigned name_width = 23; + for (size_t i = 0; i < TEST_SUITE_COUNT; i++) { + for (size_t j = 0; j < test_suites[i].case_count; j++) { + size_t len = strlen(test_suites[i].cases[j].name); + if (len > name_width) { + name_width = len; + } + } + } + name_width = 4*((name_width+1+4-1)/4)-1; + printf("%-*s %7s %11s\n", name_width, "case", "flags", "perms"); for (size_t t = 0; t < test_id_count; t++) { for (size_t i = 0; i < TEST_SUITE_COUNT; i++) { test_define_suite(&test_suites[i]); @@ -831,7 +853,8 @@ static void list_cases(void) { ? "r" : "", (!test_suites[i].cases[j].flags) ? "-" : ""); - printf("%-36s %7s %11s\n", + printf("%-*s %7s %11s\n", + name_width, test_suites[i].cases[j].name, flag_buf, perm_buf); @@ -841,8 +864,17 @@ static void list_cases(void) { } static void list_suite_paths(void) { - printf("%-36s %s\n", "suite", "path"); + // at least size so that names fit + unsigned name_width = 23; + for (size_t i = 0; i < TEST_SUITE_COUNT; i++) { + size_t len = strlen(test_suites[i].name); + if (len > name_width) { + name_width = len; + } + } + name_width = 4*((name_width+1+4-1)/4)-1; + printf("%-*s %s\n", name_width, "suite", "path"); for (size_t t = 0; t < test_id_count; t++) { for (size_t i = 0; i < TEST_SUITE_COUNT; i++) { size_t cases = 0; @@ -856,6 +888,8 @@ static void list_suite_paths(void) { test_suites[i].cases[j].name) == 0)) { continue; } + + cases += 1; } // no tests found? @@ -863,7 +897,8 @@ static void list_suite_paths(void) { continue; } - printf("%-36s %s\n", + printf("%-*s %s\n", + name_width, test_suites[i].name, test_suites[i].path); } @@ -871,8 +906,19 @@ static void list_suite_paths(void) { } static void list_case_paths(void) { - printf("%-36s %s\n", "case", "path"); + // at least size so that names fit + unsigned name_width = 23; + for (size_t i = 0; i < TEST_SUITE_COUNT; i++) { + for (size_t j = 0; j < test_suites[i].case_count; j++) { + size_t len = strlen(test_suites[i].cases[j].name); + if (len > name_width) { + name_width = len; + } + } + } + name_width = 4*((name_width+1+4-1)/4)-1; + printf("%-*s %s\n", name_width, "case", "path"); for (size_t t = 0; t < test_id_count; t++) { for (size_t i = 0; i < TEST_SUITE_COUNT; i++) { for (size_t j = 0; j < test_suites[i].case_count; j++) { @@ -885,7 +931,8 @@ static void list_case_paths(void) { continue; } - printf("%-36s %s\n", + printf("%-*s %s\n", + name_width, test_suites[i].cases[j].name, test_suites[i].cases[j].path); } @@ -1139,16 +1186,27 @@ const test_geometry_t *test_geometries = builtin_geometries; size_t test_geometry_count = 5; static void list_geometries(void) { + // at least size so that names fit + unsigned name_width = 23; + for (size_t g = 0; builtin_geometries[g].name; g++) { + size_t len = strlen(builtin_geometries[g].name); + if (len > name_width) { + name_width = len; + } + } + name_width = 4*((name_width+1+4-1)/4)-1; + // yes we do need to define a suite, this does a bit of bookeeping // such as setting up the define cache test_define_suite(&(const struct test_suite){0}); - printf("%-24s %7s %7s %7s %7s %11s\n", - "geometry", "read", "prog", "erase", "count", "size"); + printf("%-*s %7s %7s %7s %7s %11s\n", + name_width, "geometry", "read", "prog", "erase", "count", "size"); for (size_t g = 0; builtin_geometries[g].name; g++) { test_define_geometry(&builtin_geometries[g]); test_define_flush(); - printf("%-24s %7ju %7ju %7ju %7ju %11ju\n", + printf("%-*s %7ju %7ju %7ju %7ju %11ju\n", + name_width, builtin_geometries[g].name, READ_SIZE, PROG_SIZE, @@ -1669,18 +1727,29 @@ const test_powerloss_t *test_powerlosses = (const test_powerloss_t[]){ size_t test_powerloss_count = 1; static void list_powerlosses(void) { - printf("%-24s %s\n", "scenario", "description"); + // at least size so that names fit + unsigned name_width = 23; + for (size_t i = 0; builtin_powerlosses[i].name; i++) { + size_t len = strlen(builtin_powerlosses[i].name); + if (len > name_width) { + name_width = len; + } + } + name_width = 4*((name_width+1+4-1)/4)-1; + + printf("%-*s %s\n", name_width, "scenario", "description"); size_t i = 0; for (; builtin_powerlosses[i].name; i++) { - printf("%-24s %s\n", + printf("%-*s %s\n", + name_width, builtin_powerlosses[i].name, builtin_powerlosses_help[i]); } // a couple more options with special parsing - printf("%-24s %s\n", "1,2,3", builtin_powerlosses_help[i+0]); - printf("%-24s %s\n", "{1,2,3}", builtin_powerlosses_help[i+1]); - printf("%-24s %s\n", ":1248g1", builtin_powerlosses_help[i+2]); + printf("%-*s %s\n", name_width, "1,2,3", builtin_powerlosses_help[i+0]); + printf("%-*s %s\n", name_width, "{1,2,3}", builtin_powerlosses_help[i+1]); + printf("%-*s %s\n", name_width, ":1248g1", builtin_powerlosses_help[i+2]); } diff --git a/scripts/code.py b/scripts/code.py index eeaf8a0c..df16ece6 100755 --- a/scripts/code.py +++ b/scripts/code.py @@ -243,14 +243,20 @@ def table(results, diff_results=None, *, reverse=False) # print header - print('%-36s' % ('%s%s' % ( - 'file' if by_file else 'function', - ' (%d added, %d removed)' % ( - 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 summary else ''), - end='') + if not summary: + title = '%s%s' % ( + 'file' if by_file else 'function', + ' (%d added, %d removed)' % ( + 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 '') + name_width = max(it.chain([23, len(title)], (len(n) for n in names))) + else: + title = '' + name_width = 23 + name_width = 4*((name_width+1+4-1)//4)-1 + + print('%-*s ' % (name_width, title), end='') if diff_results is None: print(' %s' % ('size'.rjust(len(IntField.none)))) elif percent: @@ -273,7 +279,7 @@ def table(results, diff_results=None, *, if not ratio and not all_: continue - print('%-36s' % name, end='') + print('%-*s ' % (name_width, name), end='') if diff_results is None: print(' %s' % ( r.code_size.table() @@ -312,7 +318,7 @@ def table(results, diff_results=None, *, r.code_size if r else None, diff_r.code_size if diff_r else None) - print('%-36s' % 'TOTAL', end='') + print('%-*s ' % (name_width, 'TOTAL'), end='') if diff_results is None: print(' %s' % ( r.code_size.table() diff --git a/scripts/coverage.py b/scripts/coverage.py index f24744e8..4e4541ac 100755 --- a/scripts/coverage.py +++ b/scripts/coverage.py @@ -320,12 +320,12 @@ def table(results, diff_results=None, *, else ['function']) table = { - (r.file, r.line) if by_line + '%s:%s' % (r.file, r.line) if by_line else r.file if by_file else r.function: r for r in results} diff_table = { - (r.file, r.line) if by_line + '%s:%s' % (r.file, r.line) if by_line else r.file if by_file else r.function: r for r in diff_results or []} @@ -359,16 +359,20 @@ def table(results, diff_results=None, *, reverse=False) # print header - print('%-36s' % ('%s%s' % ( - 'line' if by_line - else 'file' if by_file - else 'function', - ' (%d added, %d removed)' % ( - 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 summary else ''), - end='') + if not summary: + title = '%s%s' % ( + 'line' if by_line else 'file' if by_file else 'function', + ' (%d added, %d removed)' % ( + 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 '') + name_width = max(it.chain([23, len(title)], (len(n) for n in names))) + else: + title = '' + name_width = 23 + name_width = 4*((name_width+1+4-1)//4)-1 + + print('%-*s ' % (name_width, title), end='') if diff_results is None: print(' %s %s' % ( 'hits/line'.rjust(len(FracField.none)), @@ -401,9 +405,7 @@ def table(results, diff_results=None, *, if not line_ratio and not branch_ratio and not all_: continue - print('%-36s' % ( - ':'.join('%s' % n for n in name) - if by_line else name), end='') + print('%-*s ' % (name_width, name), end='') if diff_results is None: print(' %s %s' % ( r.coverage_lines.table() @@ -460,7 +462,7 @@ def table(results, diff_results=None, *, r.coverage_branches if r else None, diff_r.coverage_branches if diff_r else None) - print('%-36s' % 'TOTAL', end='') + print('%-*s ' % (name_width, 'TOTAL'), end='') if diff_results is None: print(' %s %s' % ( r.coverage_lines.table() diff --git a/scripts/data.py b/scripts/data.py index 690ac025..60707567 100755 --- a/scripts/data.py +++ b/scripts/data.py @@ -244,14 +244,20 @@ def table(results, diff_results=None, *, reverse=False) # print header - print('%-36s' % ('%s%s' % ( - 'file' if by_file else 'function', - ' (%d added, %d removed)' % ( - 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 summary else ''), - end='') + if not summary: + title = '%s%s' % ( + 'file' if by_file else 'function', + ' (%d added, %d removed)' % ( + 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 '') + name_width = max(it.chain([23, len(title)], (len(n) for n in names))) + else: + title = '' + name_width = 23 + name_width = 4*((name_width+1+4-1)//4)-1 + + print('%-*s ' % (name_width, title), end='') if diff_results is None: print(' %s' % ('size'.rjust(len(IntField.none)))) elif percent: @@ -274,7 +280,7 @@ def table(results, diff_results=None, *, if not ratio and not all_: continue - print('%-36s' % name, end='') + print('%-*s ' % (name_width, name), end='') if diff_results is None: print(' %s' % ( r.data_size.table() @@ -313,7 +319,7 @@ def table(results, diff_results=None, *, r.data_size if r else None, diff_r.data_size if diff_r else None) - print('%-36s' % 'TOTAL', end='') + print('%-*s ' % (name_width, 'TOTAL'), end='') if diff_results is None: print(' %s' % ( r.data_size.table() diff --git a/scripts/stack.py b/scripts/stack.py index a3bbd486..ed5f1fce 100755 --- a/scripts/stack.py +++ b/scripts/stack.py @@ -329,20 +329,27 @@ def table(results, calls, diff_results=None, *, names.sort(key=lambda n: (table[n].stack_frame,) if n in table else (), reverse=False) - # adjust the name width based on the expected call depth, note that we - # can't always find the depth due to recursion - width = 36 + (4*depth if not m.isinf(depth) else 0) - # print header - if not tree: - print('%-*s' % (width, '%s%s' % ( + if not summary: + title = '%s%s' % ( 'file' if by_file else 'function', ' (%d added, %d removed)' % ( 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 summary else ''), - end='') + name_width = max(it.chain([23, len(title)], (len(n) for n in names))) + else: + title = '' + name_width = 23 + name_width = 4*((name_width+1+4-1)//4)-1 + + # adjust the name width based on the expected call depth, note that we + # can't always find the depth due to recursion + if not m.isinf(depth): + name_width += 4*depth + + if not tree: + print('%-*s ' % (name_width, title), end='') if diff_results is None: print(' %s %s' % ( 'frame'.rjust(len(IntField.none)), @@ -376,7 +383,7 @@ def table(results, calls, diff_results=None, *, continue is_last = (i == len(names_)-1) - print('%-*s' % (width, prefixes[0+is_last] + name), end='') + print('%-*s ' % (name_width, prefixes[0+is_last]+name), end='') if tree: print() elif diff_results is None: @@ -444,7 +451,7 @@ def table(results, calls, diff_results=None, *, r.stack_limit if r else None, diff_r.stack_limit if diff_r else None) - print('%-*s' % (width, 'TOTAL'), end='') + print('%-*s ' % (name_width, 'TOTAL'), end='') if diff_results is None: print(' %s %s' % ( r.stack_frame.table() diff --git a/scripts/struct_.py b/scripts/struct_.py index 9351bb33..bdb98f73 100755 --- a/scripts/struct_.py +++ b/scripts/struct_.py @@ -286,14 +286,20 @@ def table(results, diff_results=None, *, reverse=False) # print header - print('%-36s' % ('%s%s' % ( - 'file' if by_file else 'struct', - ' (%d added, %d removed)' % ( - 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 summary else ''), - end='') + if not summary: + title = '%s%s' % ( + 'file' if by_file else 'struct', + ' (%d added, %d removed)' % ( + 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 '') + name_width = max(it.chain([23, len(title)], (len(n) for n in names))) + else: + title = '' + name_width = 23 + name_width = 4*((name_width+1+4-1)//4)-1 + + print('%-*s ' % (name_width, title), end='') if diff_results is None: print(' %s' % ('size'.rjust(len(IntField.none)))) elif percent: @@ -316,7 +322,7 @@ def table(results, diff_results=None, *, if not ratio and not all_: continue - print('%-36s' % name, end='') + print('%-*s ' % (name_width, name), end='') if diff_results is None: print(' %s' % ( r.struct_size.table() @@ -355,7 +361,7 @@ def table(results, diff_results=None, *, r.struct_size if r else None, diff_r.struct_size if diff_r else None) - print('%-36s' % 'TOTAL', end='') + print('%-*s ' % (name_width, 'TOTAL'), end='') if diff_results is None: print(' %s' % ( r.struct_size.table() diff --git a/scripts/summary.py b/scripts/summary.py index d257a3fa..98c1a538 100755 --- a/scripts/summary.py +++ b/scripts/summary.py @@ -422,8 +422,12 @@ def table(results, total, diff_results=None, diff_total=None, *, **_): all_, all = all, __builtins__.all - table = {tuple(r.get(k,'') for k in by): r for r in results} - diff_table = {tuple(r.get(k,'') for k in by): r for r in diff_results or []} + table = { + ','.join(r.get(k,'') for k in by): r + for r in results} + diff_table = { + ','.join(r.get(k,'') for k in by): r + for r in diff_results or []} # sort, note that python's sort is stable names = list(table.keys() | diff_table.keys()) @@ -446,30 +450,40 @@ def table(results, total, diff_results=None, diff_total=None, *, reverse=False) # print header - print('%-36s' % ('%s%s' % ( - ','.join(k for k in by), - ' (%d added, %d removed)' % ( - 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 summary else ''), - end='') - if diff_results is None: - print(' %s' % ( - ' '.join(k.rjust(len(types[k].none)) - for k in fields))) - elif percent: - print(' %s' % ( - ' '.join(k.rjust(len(types[k].diff_none)) - for k in fields))) + if not summary: + title = '%s%s' % ( + ','.join(by), + ' (%d added, %d removed)' % ( + 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 '') + name_width = max(it.chain([23, len(title)], (len(n) for n in names))) else: + title = '' + name_width = 23 + name_width = 4*((name_width+1+4-1)//4)-1 + + print('%-*s ' % (name_width, title), end='') + if diff_results is None: + widths = [ + 4*((max(len(types[k].none), len(k))+1+4-1)//4)-1 + for k in fields] + print(' %s' % ( + ' '.join(k.rjust(w) for w, k in zip(widths, fields)))) + elif percent: + widths = [ + 4*((max(len(types[k].diff_none), len(k))+1+4-1)//4)-1 + for k in fields] + print(' %s' % ( + ' '.join(k.rjust(w) for w, k in zip(widths, fields)))) + else: + widths = [ + 4*((max(len(types[k].diff_none), 1+len(k))+1+4-1)//4)-1 + for k in fields] print(' %s %s %s' % ( - ' '.join(('o'+k).rjust(len(types[k].diff_none)) - for k in fields), - ' '.join(('n'+k).rjust(len(types[k].diff_none)) - for k in fields), - ' '.join(('d'+k).rjust(len(types[k].diff_none)) - for k in fields))) + ' '.join(('o'+k).rjust(w) for w, k in zip(widths, fields)), + ' '.join(('n'+k).rjust(w) for w, k in zip(widths, fields)), + ' '.join(('d'+k).rjust(w) for w, k in zip(widths, fields)))) # print entries if not summary: @@ -482,17 +496,21 @@ def table(results, total, diff_results=None, diff_total=None, *, if not any(ratios) and not all_: continue - print('%-36s' % ','.join(name), end='') + print('%-*s ' % (name_width, name), end='') if diff_results is None: print(' %s' % ( - ' '.join(r[k].table() - if k in r else types[k].none - for k in fields))) + ' '.join( + (r[k].table() + if k in r + else types[k].none).rjust(w) + for w, k in zip(widths, fields)))) elif percent: print(' %s%s' % ( - ' '.join(r[k].diff_table() - if k in r else types[k].diff_none - for k in fields), + ' '.join( + (r[k].diff_table().rjust(w) + if k in r + else types[k].diff_none).rjust(w) + for w, k in zip(widths, fields)), ' (%s)' % ', '.join( '+∞%' if t == +m.inf else '-∞%' if t == -m.inf @@ -500,15 +518,21 @@ def table(results, total, diff_results=None, diff_total=None, *, for t in ratios))) else: print(' %s %s %s%s' % ( - ' '.join(diff_r[k].diff_table() - if k in diff_r else types[k].diff_none - for k in fields), - ' '.join(r[k].diff_table() - if k in r else types[k].diff_none - for k in fields), - ' '.join(types[k].diff_diff(r.get(k), diff_r.get(k)) - if k in r or k in diff_r else types[k].diff_none - for k in fields), + ' '.join( + (diff_r[k].diff_table() + if k in diff_r + else types[k].diff_none).rjust(w) + for w, k in zip(widths, fields)), + ' '.join( + (r[k].diff_table() + if k in r + else types[k].diff_none).rjust(w) + for w, k in zip(widths, fields)), + ' '.join( + (types[k].diff_diff(r.get(k), diff_r.get(k)) + if k in r or k in diff_r + else types[k].diff_none).rjust(w) + for w, k in zip(widths, fields)), ' (%s)' % ', '.join( '+∞%' if t == +m.inf else '-∞%' if t == -m.inf @@ -524,17 +548,21 @@ def table(results, total, diff_results=None, diff_total=None, *, ratios = [types[k].ratio(r.get(k), diff_r.get(k)) for k in fields] - print('%-36s' % 'TOTAL', end='') + print('%-*s ' % (name_width, 'TOTAL'), end='') if diff_results is None: print(' %s' % ( - ' '.join(r[k].table() - if k in r else types[k].none - for k in fields))) + ' '.join( + (r[k].table() + if k in r + else types[k].none).rjust(w) + for w, k in zip(widths, fields)))) elif percent: print(' %s%s' % ( - ' '.join(r[k].diff_table() - if k in r else types[k].diff_none - for k in fields), + ' '.join( + (r[k].diff_table().rjust(w) + if k in r + else types[k].diff_none).rjust(w) + for w, k in zip(widths, fields)), ' (%s)' % ', '.join( '+∞%' if t == +m.inf else '-∞%' if t == -m.inf @@ -542,15 +570,21 @@ def table(results, total, diff_results=None, diff_total=None, *, for t in ratios))) else: print(' %s %s %s%s' % ( - ' '.join(diff_r[k].diff_table() - if k in diff_r else types[k].diff_none - for k in fields), - ' '.join(r[k].diff_table() - if k in r else types[k].diff_none - for k in fields), - ' '.join(types[k].diff_diff(r.get(k), diff_r.get(k)) - if k in r or k in diff_r else types[k].diff_none - for k in fields), + ' '.join( + (diff_r[k].diff_table() + if k in diff_r + else types[k].diff_none).rjust(w) + for w, k in zip(widths, fields)), + ' '.join( + (r[k].diff_table() + if k in r + else types[k].diff_none).rjust(w) + for w, k in zip(widths, fields)), + ' '.join( + (types[k].diff_diff(r.get(k), diff_r.get(k)) + if k in r or k in diff_r + else types[k].diff_none).rjust(w) + for w, k in zip(widths, fields)), ' (%s)' % ', '.join( '+∞%' if t == +m.inf else '-∞%' if t == -m.inf