Interspersed precent/notes in measurement scripts

This is a bit more complicated, but make testmarks really showed how
confusing this could get.

Now, instead of:

  suite                             passed    time
  test_alloc                       304/304     1.6 (100.0%)
  test_badblocks                 6880/6880  1323.3 (100.0%)
  ... snip ...
  test_rbyd                  385878/385878   592.7 (100.0%)
  test_relocations               7899/7899   318.8 (100.0%)
  TOTAL                      548206/548206  6229.7 (100.0%)

Percents/notes are interspersed next to their relevant fields:

  suite                             passed             time
  test_alloc                       304/304 (100.0%)     1.6
  test_badblocks                 6880/6880 (100.0%)  1323.3
  ... snip ...
  test_rbyd                  385878/385878 (100.0%)   592.7
  test_relocations               7899/7899 (100.0%)   318.8
  TOTAL                      548206/548206 (100.0%)  6229.7

Note has no effect on scripts with only a single field (code.py, etc).

But it does make multi-field diffs a bit more readable:

  $ ./scripts/stack.py -u after.stack.csv -d before.stack.csv -p
  function                       frame             limit
  lfsr_bd_sync                       8 (+100.0%)     216 (+100.0%)
  lfsr_bd_flush                     40 (+25.0%)      208 (+4.0%)
  ... snip ...
  lfsr_file_flush                   32 (+0.0%)      2424 (-0.3%)
  lfsr_file_flush_                 216 (-3.6%)      2392 (-0.3%)
  TOTAL                           9008 (+0.4%)      2600 (-0.3%)
This commit is contained in:
Christopher Haster
2024-06-02 14:40:52 -05:00
parent a231bbac6e
commit 06bfed7a8b
8 changed files with 466 additions and 455 deletions

View File

@@ -399,14 +399,14 @@ def table(Result, results, diff_results=None, *,
lines = []
# header
header = []
header.append('%s%s' % (
header = [
'%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 '')
if not summary else '')
if not summary else '']
if diff_results is None:
for k in fields:
header.append(k)
@@ -420,22 +420,29 @@ def table(Result, results, diff_results=None, *,
header.append('n'+k)
for k in fields:
header.append('d'+k)
header.append('')
lines.append(header)
def table_entry(name, r, diff_r=None):
entry = []
entry.append(name)
entry = [name]
if diff_results is None:
for k in fields:
entry.append(getattr(r, k).table()
entry.append(
(getattr(r, k).table(),
getattr(getattr(r, k), 'notes', lambda: [])())
if getattr(r, k, None) is not None
else types[k].none)
elif percent:
for k in fields:
entry.append(getattr(r, k).table()
entry.append(
(getattr(r, k).table()
if getattr(r, k, None) is not None
else types[k].none)
else types[k].none,
(lambda t: ['+∞%'] if t == +m.inf
else ['-∞%'] if t == -m.inf
else ['%+.1f%%' % (100*t)])(
types[k].ratio(
getattr(r, k, None),
getattr(diff_r, k, None)))))
else:
for k in fields:
entry.append(getattr(diff_r, k).table()
@@ -446,30 +453,17 @@ def table(Result, results, diff_results=None, *,
if getattr(r, k, None) is not None
else types[k].none)
for k in fields:
entry.append(types[k].diff(
entry.append(
(types[k].diff(
getattr(r, k, None),
getattr(diff_r, k, None)))
if diff_results is None:
notes = []
for k in fields:
try:
notes.extend(getattr(r, k).notes())
except AttributeError:
pass
entry.append(' (%s)' % ', '.join(notes)
if notes else '')
else:
ratios = [
getattr(diff_r, k, None)),
(lambda t: ['+∞%'] if t == +m.inf
else ['-∞%'] if t == -m.inf
else ['%+.1f%%' % (100*t)] if t
else [])(
types[k].ratio(
getattr(r, k, None),
getattr(diff_r, k, None))
for k in fields]
entry.append(' (%s)' % ', '.join(
'+∞%' if t == +m.inf
else '-∞%' if t == -m.inf
else '%+.1f%%' % (100*t)
for t in ratios)
if percent or any(ratios) else '')
getattr(diff_r, k, None)))))
return entry
# entries
@@ -496,21 +490,28 @@ def table(Result, results, diff_results=None, *,
diff_r = next(iter(fold(Result, diff_results, by=[])), None)
lines.append(table_entry('TOTAL', r, diff_r))
# find the best widths, note that column 0 contains the names and
# column -1 the ratios/notes, so those are handled a bit differently
widths = [
((max(it.chain([w], (len(l[i]) for l in lines)))+1+4-1)//4)*4-1
for w, i in zip(
it.chain([23], it.repeat(7)),
range(len(lines[0])-1))]
# homogenize
lines = [
[x if isinstance(x, tuple) else (x, []) for x in line]
for line in lines]
# find the best widths, note that column 0 contains the names and is
# handled a bit differently
widths = co.defaultdict(lambda: 7, {0: 23})
notes = co.defaultdict(lambda: 0)
for line in lines:
for i, x in enumerate(line):
widths[i] = max(widths[i], ((len(x[0])+1+4-1)//4)*4-1)
notes[i] = max(notes[i], 1+2*len(x[1])+sum(len(n) for n in x[1]))
# print our table
for line in lines:
print('%-*s %s%s' % (
widths[0], line[0],
' '.join('%*s' % (w, x)
for w, x in zip(widths[1:], line[1:-1])),
line[-1]))
print('%-*s %s' % (
widths[0], line[0][0],
' '.join('%*s%-*s' % (
widths[i], x[0],
notes[i], ' (%s)' % ', '.join(x[1]) if x[1] else '')
for i, x in enumerate(line[1:], 1))))
def main(obj_paths, *,

View File

@@ -387,14 +387,14 @@ def table(Result, results, diff_results=None, *,
lines = []
# header
header = []
header.append('%s%s' % (
header = [
'%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 '')
if not summary else '')
if not summary else '']
if diff_results is None:
for k in fields:
header.append(k)
@@ -408,22 +408,29 @@ def table(Result, results, diff_results=None, *,
header.append('n'+k)
for k in fields:
header.append('d'+k)
header.append('')
lines.append(header)
def table_entry(name, r, diff_r=None):
entry = []
entry.append(name)
entry = [name]
if diff_results is None:
for k in fields:
entry.append(getattr(r, k).table()
entry.append(
(getattr(r, k).table(),
getattr(getattr(r, k), 'notes', lambda: [])())
if getattr(r, k, None) is not None
else types[k].none)
elif percent:
for k in fields:
entry.append(getattr(r, k).table()
entry.append(
(getattr(r, k).table()
if getattr(r, k, None) is not None
else types[k].none)
else types[k].none,
(lambda t: ['+∞%'] if t == +m.inf
else ['-∞%'] if t == -m.inf
else ['%+.1f%%' % (100*t)])(
types[k].ratio(
getattr(r, k, None),
getattr(diff_r, k, None)))))
else:
for k in fields:
entry.append(getattr(diff_r, k).table()
@@ -434,30 +441,17 @@ def table(Result, results, diff_results=None, *,
if getattr(r, k, None) is not None
else types[k].none)
for k in fields:
entry.append(types[k].diff(
entry.append(
(types[k].diff(
getattr(r, k, None),
getattr(diff_r, k, None)))
if diff_results is None:
notes = []
for k in fields:
try:
notes.extend(getattr(r, k).notes())
except AttributeError:
pass
entry.append(' (%s)' % ', '.join(notes)
if notes else '')
else:
ratios = [
getattr(diff_r, k, None)),
(lambda t: ['+∞%'] if t == +m.inf
else ['-∞%'] if t == -m.inf
else ['%+.1f%%' % (100*t)] if t
else [])(
types[k].ratio(
getattr(r, k, None),
getattr(diff_r, k, None))
for k in fields]
entry.append(' (%s)' % ', '.join(
'+∞%' if t == +m.inf
else '-∞%' if t == -m.inf
else '%+.1f%%' % (100*t)
for t in ratios)
if percent or any(ratios) else '')
getattr(diff_r, k, None)))))
return entry
# entries
@@ -484,21 +478,28 @@ def table(Result, results, diff_results=None, *,
diff_r = next(iter(fold(Result, diff_results, by=[])), None)
lines.append(table_entry('TOTAL', r, diff_r))
# find the best widths, note that column 0 contains the names and
# column -1 the ratios/notes, so those are handled a bit differently
widths = [
((max(it.chain([w], (len(l[i]) for l in lines)))+1+4-1)//4)*4-1
for w, i in zip(
it.chain([23], it.repeat(7)),
range(len(lines[0])-1))]
# homogenize
lines = [
[x if isinstance(x, tuple) else (x, []) for x in line]
for line in lines]
# find the best widths, note that column 0 contains the names and is
# handled a bit differently
widths = co.defaultdict(lambda: 7, {0: 23})
notes = co.defaultdict(lambda: 0)
for line in lines:
for i, x in enumerate(line):
widths[i] = max(widths[i], ((len(x[0])+1+4-1)//4)*4-1)
notes[i] = max(notes[i], 1+2*len(x[1])+sum(len(n) for n in x[1]))
# print our table
for line in lines:
print('%-*s %s%s' % (
widths[0], line[0],
' '.join('%*s' % (w, x)
for w, x in zip(widths[1:], line[1:-1])),
line[-1]))
print('%-*s %s' % (
widths[0], line[0][0],
' '.join('%*s%-*s' % (
widths[i], x[0],
notes[i], ' (%s)' % ', '.join(x[1]) if x[1] else '')
for i, x in enumerate(line[1:], 1))))
def annotate(Result, results, *,

View File

@@ -399,14 +399,14 @@ def table(Result, results, diff_results=None, *,
lines = []
# header
header = []
header.append('%s%s' % (
header = [
'%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 '')
if not summary else '')
if not summary else '']
if diff_results is None:
for k in fields:
header.append(k)
@@ -420,22 +420,29 @@ def table(Result, results, diff_results=None, *,
header.append('n'+k)
for k in fields:
header.append('d'+k)
header.append('')
lines.append(header)
def table_entry(name, r, diff_r=None):
entry = []
entry.append(name)
entry = [name]
if diff_results is None:
for k in fields:
entry.append(getattr(r, k).table()
entry.append(
(getattr(r, k).table(),
getattr(getattr(r, k), 'notes', lambda: [])())
if getattr(r, k, None) is not None
else types[k].none)
elif percent:
for k in fields:
entry.append(getattr(r, k).table()
entry.append(
(getattr(r, k).table()
if getattr(r, k, None) is not None
else types[k].none)
else types[k].none,
(lambda t: ['+∞%'] if t == +m.inf
else ['-∞%'] if t == -m.inf
else ['%+.1f%%' % (100*t)])(
types[k].ratio(
getattr(r, k, None),
getattr(diff_r, k, None)))))
else:
for k in fields:
entry.append(getattr(diff_r, k).table()
@@ -446,30 +453,17 @@ def table(Result, results, diff_results=None, *,
if getattr(r, k, None) is not None
else types[k].none)
for k in fields:
entry.append(types[k].diff(
entry.append(
(types[k].diff(
getattr(r, k, None),
getattr(diff_r, k, None)))
if diff_results is None:
notes = []
for k in fields:
try:
notes.extend(getattr(r, k).notes())
except AttributeError:
pass
entry.append(' (%s)' % ', '.join(notes)
if notes else '')
else:
ratios = [
getattr(diff_r, k, None)),
(lambda t: ['+∞%'] if t == +m.inf
else ['-∞%'] if t == -m.inf
else ['%+.1f%%' % (100*t)] if t
else [])(
types[k].ratio(
getattr(r, k, None),
getattr(diff_r, k, None))
for k in fields]
entry.append(' (%s)' % ', '.join(
'+∞%' if t == +m.inf
else '-∞%' if t == -m.inf
else '%+.1f%%' % (100*t)
for t in ratios)
if percent or any(ratios) else '')
getattr(diff_r, k, None)))))
return entry
# entries
@@ -496,21 +490,28 @@ def table(Result, results, diff_results=None, *,
diff_r = next(iter(fold(Result, diff_results, by=[])), None)
lines.append(table_entry('TOTAL', r, diff_r))
# find the best widths, note that column 0 contains the names and
# column -1 the ratios/notes, so those are handled a bit differently
widths = [
((max(it.chain([w], (len(l[i]) for l in lines)))+1+4-1)//4)*4-1
for w, i in zip(
it.chain([23], it.repeat(7)),
range(len(lines[0])-1))]
# homogenize
lines = [
[x if isinstance(x, tuple) else (x, []) for x in line]
for line in lines]
# find the best widths, note that column 0 contains the names and is
# handled a bit differently
widths = co.defaultdict(lambda: 7, {0: 23})
notes = co.defaultdict(lambda: 0)
for line in lines:
for i, x in enumerate(line):
widths[i] = max(widths[i], ((len(x[0])+1+4-1)//4)*4-1)
notes[i] = max(notes[i], 1+2*len(x[1])+sum(len(n) for n in x[1]))
# print our table
for line in lines:
print('%-*s %s%s' % (
widths[0], line[0],
' '.join('%*s' % (w, x)
for w, x in zip(widths[1:], line[1:-1])),
line[-1]))
print('%-*s %s' % (
widths[0], line[0][0],
' '.join('%*s%-*s' % (
widths[i], x[0],
notes[i], ' (%s)' % ', '.join(x[1]) if x[1] else '')
for i, x in enumerate(line[1:], 1))))
def main(obj_paths, *,

View File

@@ -723,14 +723,14 @@ def table(Result, results, diff_results=None, *,
lines = []
# header
header = []
header.append('%s%s' % (
header = [
'%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 '')
if not summary else '')
if not summary else '']
if diff_results is None:
for k in fields:
header.append(k)
@@ -744,22 +744,29 @@ def table(Result, results, diff_results=None, *,
header.append('n'+k)
for k in fields:
header.append('d'+k)
header.append('')
lines.append(header)
def table_entry(name, r, diff_r=None):
entry = []
entry.append(name)
entry = [name]
if diff_results is None:
for k in fields:
entry.append(getattr(r, k).table()
entry.append(
(getattr(r, k).table(),
getattr(getattr(r, k), 'notes', lambda: [])())
if getattr(r, k, None) is not None
else types[k].none)
elif percent:
for k in fields:
entry.append(getattr(r, k).table()
entry.append(
(getattr(r, k).table()
if getattr(r, k, None) is not None
else types[k].none)
else types[k].none,
(lambda t: ['+∞%'] if t == +m.inf
else ['-∞%'] if t == -m.inf
else ['%+.1f%%' % (100*t)])(
types[k].ratio(
getattr(r, k, None),
getattr(diff_r, k, None)))))
else:
for k in fields:
entry.append(getattr(diff_r, k).table()
@@ -770,30 +777,17 @@ def table(Result, results, diff_results=None, *,
if getattr(r, k, None) is not None
else types[k].none)
for k in fields:
entry.append(types[k].diff(
entry.append(
(types[k].diff(
getattr(r, k, None),
getattr(diff_r, k, None)))
if diff_results is None:
notes = []
for k in fields:
try:
notes.extend(getattr(r, k).notes())
except AttributeError:
pass
entry.append(' (%s)' % ', '.join(notes)
if notes else '')
else:
ratios = [
getattr(diff_r, k, None)),
(lambda t: ['+∞%'] if t == +m.inf
else ['-∞%'] if t == -m.inf
else ['%+.1f%%' % (100*t)] if t
else [])(
types[k].ratio(
getattr(r, k, None),
getattr(diff_r, k, None))
for k in fields]
entry.append(' (%s)' % ', '.join(
'+∞%' if t == +m.inf
else '-∞%' if t == -m.inf
else '%+.1f%%' % (100*t)
for t in ratios)
if percent or any(ratios) else '')
getattr(diff_r, k, None)))))
return entry
# entries
@@ -820,13 +814,19 @@ def table(Result, results, diff_results=None, *,
diff_r = next(iter(fold(Result, diff_results, by=[])), None)
lines.append(table_entry('TOTAL', r, diff_r))
# find the best widths, note that column 0 contains the names and
# column -1 the ratios/notes, so those are handled a bit differently
widths = [
((max(it.chain([w], (len(l[i]) for l in lines)))+1+4-1)//4)*4-1
for w, i in zip(
it.chain([23], it.repeat(7)),
range(len(lines[0])-1))]
# homogenize
lines = [
[x if isinstance(x, tuple) else (x, []) for x in line]
for line in lines]
# find the best widths, note that column 0 contains the names and is
# handled a bit differently
widths = co.defaultdict(lambda: 7, {0: 23})
notes = co.defaultdict(lambda: 0)
for line in lines:
for i, x in enumerate(line):
widths[i] = max(widths[i], ((len(x[0])+1+4-1)//4)*4-1)
notes[i] = max(notes[i], 1+2*len(x[1])+sum(len(n) for n in x[1]))
# adjust the name width based on the call depth
if not summary:
@@ -855,11 +855,12 @@ def table(Result, results, diff_results=None, *,
widths[0] += 4*max(depth_-1, 0)
# print the tree recursively
print('%-*s %s%s' % (
widths[0], lines[0][0],
' '.join('%*s' % (w, x)
for w, x in zip(widths[1:], lines[0][1:-1])),
lines[0][-1]))
print('%-*s %s' % (
widths[0], lines[0][0][0],
' '.join('%*s%-*s' % (
widths[i], x[0],
notes[i], ' (%s)' % ', '.join(x[1]) if x[1] else '')
for i, x in enumerate(lines[0][1:], 1))))
if not summary:
def recurse(results_, depth_, prefixes=('', '', '', '')):
@@ -887,14 +888,15 @@ def table(Result, results, diff_results=None, *,
r = table_[name]
is_last = (i == len(names_)-1)
line = table_entry(name, r)
line = [x if isinstance(x, tuple) else (x, []) for x in line]
print('%s%-*s %s' % (
prefixes[0+is_last],
widths[0] - len(prefixes[0+is_last]),
name,
' '.join('%*s' % (w, x)
for w, x in zip(
widths[1:],
table_entry(name, r)[1:]))))
widths[0] - len(prefixes[0+is_last]), line[0][0],
' '.join('%*s%-*s' % (
widths[i], x[0],
notes[i], ' (%s)' % ', '.join(x[1]) if x[1] else '')
for i, x in enumerate(line[1:], 1))))
# recurse?
if depth_ > 1:
@@ -909,11 +911,12 @@ def table(Result, results, diff_results=None, *,
# we have enough going on with diffing to make the top layer
# a special case
for name, line in zip(names, lines[1:-1]):
print('%-*s %s%s' % (
widths[0], line[0],
' '.join('%*s' % (w, x)
for w, x in zip(widths[1:], line[1:-1])),
line[-1]))
print('%-*s %s' % (
widths[0], line[0][0],
' '.join('%*s%-*s' % (
widths[i], x[0],
notes[i], ' (%s)' % ', '.join(x[1]) if x[1] else '')
for i, x in enumerate(line[1:], 1))))
if name in table and depth > 1:
recurse(
@@ -924,11 +927,12 @@ def table(Result, results, diff_results=None, *,
"| ",
" "))
print('%-*s %s%s' % (
widths[0], lines[-1][0],
' '.join('%*s' % (w, x)
for w, x in zip(widths[1:], lines[-1][1:-1])),
lines[-1][-1]))
print('%-*s %s' % (
widths[0], lines[-1][0][0],
' '.join('%*s%-*s' % (
widths[i], x[0],
notes[i], ' (%s)' % ', '.join(x[1]) if x[1] else '')
for i, x in enumerate(lines[-1][1:], 1))))
def annotate(Result, results, *,

View File

@@ -687,14 +687,14 @@ def table(Result, results, diff_results=None, *,
lines = []
# header
header = []
header.append('%s%s' % (
header = [
'%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 '')
if not summary else '')
if not summary else '']
if diff_results is None:
for k in fields:
header.append(k)
@@ -708,22 +708,29 @@ def table(Result, results, diff_results=None, *,
header.append('n'+k)
for k in fields:
header.append('d'+k)
header.append('')
lines.append(header)
def table_entry(name, r, diff_r=None):
entry = []
entry.append(name)
entry = [name]
if diff_results is None:
for k in fields:
entry.append(getattr(r, k).table()
entry.append(
(getattr(r, k).table(),
getattr(getattr(r, k), 'notes', lambda: [])())
if getattr(r, k, None) is not None
else types[k].none)
elif percent:
for k in fields:
entry.append(getattr(r, k).table()
entry.append(
(getattr(r, k).table()
if getattr(r, k, None) is not None
else types[k].none)
else types[k].none,
(lambda t: ['+∞%'] if t == +m.inf
else ['-∞%'] if t == -m.inf
else ['%+.1f%%' % (100*t)])(
types[k].ratio(
getattr(r, k, None),
getattr(diff_r, k, None)))))
else:
for k in fields:
entry.append(getattr(diff_r, k).table()
@@ -734,30 +741,17 @@ def table(Result, results, diff_results=None, *,
if getattr(r, k, None) is not None
else types[k].none)
for k in fields:
entry.append(types[k].diff(
entry.append(
(types[k].diff(
getattr(r, k, None),
getattr(diff_r, k, None)))
if diff_results is None:
notes = []
for k in fields:
try:
notes.extend(getattr(r, k).notes())
except AttributeError:
pass
entry.append(' (%s)' % ', '.join(notes)
if notes else '')
else:
ratios = [
getattr(diff_r, k, None)),
(lambda t: ['+∞%'] if t == +m.inf
else ['-∞%'] if t == -m.inf
else ['%+.1f%%' % (100*t)] if t
else [])(
types[k].ratio(
getattr(r, k, None),
getattr(diff_r, k, None))
for k in fields]
entry.append(' (%s)' % ', '.join(
'+∞%' if t == +m.inf
else '-∞%' if t == -m.inf
else '%+.1f%%' % (100*t)
for t in ratios)
if percent or any(ratios) else '')
getattr(diff_r, k, None)))))
return entry
# entries
@@ -784,13 +778,19 @@ def table(Result, results, diff_results=None, *,
diff_r = next(iter(fold(Result, diff_results, by=[])), None)
lines.append(table_entry('TOTAL', r, diff_r))
# find the best widths, note that column 0 contains the names and
# column -1 the ratios/notes, so those are handled a bit differently
widths = [
((max(it.chain([w], (len(l[i]) for l in lines)))+1+4-1)//4)*4-1
for w, i in zip(
it.chain([23], it.repeat(7)),
range(len(lines[0])-1))]
# homogenize
lines = [
[x if isinstance(x, tuple) else (x, []) for x in line]
for line in lines]
# find the best widths, note that column 0 contains the names and is
# handled a bit differently
widths = co.defaultdict(lambda: 7, {0: 23})
notes = co.defaultdict(lambda: 0)
for line in lines:
for i, x in enumerate(line):
widths[i] = max(widths[i], ((len(x[0])+1+4-1)//4)*4-1)
notes[i] = max(notes[i], 1+2*len(x[1])+sum(len(n) for n in x[1]))
# adjust the name width based on the call depth
if not summary:
@@ -819,11 +819,12 @@ def table(Result, results, diff_results=None, *,
widths[0] += 4*max(depth_-1, 0)
# print the tree recursively
print('%-*s %s%s' % (
widths[0], lines[0][0],
' '.join('%*s' % (w, x)
for w, x in zip(widths[1:], lines[0][1:-1])),
lines[0][-1]))
print('%-*s %s' % (
widths[0], lines[0][0][0],
' '.join('%*s%-*s' % (
widths[i], x[0],
notes[i], ' (%s)' % ', '.join(x[1]) if x[1] else '')
for i, x in enumerate(lines[0][1:], 1))))
if not summary:
def recurse(results_, depth_, prefixes=('', '', '', '')):
@@ -851,14 +852,15 @@ def table(Result, results, diff_results=None, *,
r = table_[name]
is_last = (i == len(names_)-1)
line = table_entry(name, r)
line = [x if isinstance(x, tuple) else (x, []) for x in line]
print('%s%-*s %s' % (
prefixes[0+is_last],
widths[0] - len(prefixes[0+is_last]),
name,
' '.join('%*s' % (w, x)
for w, x in zip(
widths[1:],
table_entry(name, r)[1:]))))
widths[0] - len(prefixes[0+is_last]), line[0][0],
' '.join('%*s%-*s' % (
widths[i], x[0],
notes[i], ' (%s)' % ', '.join(x[1]) if x[1] else '')
for i, x in enumerate(line[1:], 1))))
# recurse?
if depth_ > 1:
@@ -873,11 +875,12 @@ def table(Result, results, diff_results=None, *,
# we have enough going on with diffing to make the top layer
# a special case
for name, line in zip(names, lines[1:-1]):
print('%-*s %s%s' % (
widths[0], line[0],
' '.join('%*s' % (w, x)
for w, x in zip(widths[1:], line[1:-1])),
line[-1]))
print('%-*s %s' % (
widths[0], line[0][0],
' '.join('%*s%-*s' % (
widths[i], x[0],
notes[i], ' (%s)' % ', '.join(x[1]) if x[1] else '')
for i, x in enumerate(line[1:], 1))))
if name in table and depth > 1:
recurse(
@@ -888,11 +891,12 @@ def table(Result, results, diff_results=None, *,
"| ",
" "))
print('%-*s %s%s' % (
widths[0], lines[-1][0],
' '.join('%*s' % (w, x)
for w, x in zip(widths[1:], lines[-1][1:-1])),
lines[-1][-1]))
print('%-*s %s' % (
widths[0], lines[-1][0][0],
' '.join('%*s%-*s' % (
widths[i], x[0],
notes[i], ' (%s)' % ', '.join(x[1]) if x[1] else '')
for i, x in enumerate(lines[-1][1:], 1))))
def annotate(Result, results, *,

View File

@@ -358,14 +358,14 @@ def table(Result, results, diff_results=None, *,
lines = []
# header
header = []
header.append('%s%s' % (
header = [
'%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 '')
if not summary else '')
if not summary else '']
if diff_results is None:
for k in fields:
header.append(k)
@@ -379,22 +379,29 @@ def table(Result, results, diff_results=None, *,
header.append('n'+k)
for k in fields:
header.append('d'+k)
header.append('')
lines.append(header)
def table_entry(name, r, diff_r=None):
entry = []
entry.append(name)
entry = [name]
if diff_results is None:
for k in fields:
entry.append(getattr(r, k).table()
entry.append(
(getattr(r, k).table(),
getattr(getattr(r, k), 'notes', lambda: [])())
if getattr(r, k, None) is not None
else types[k].none)
elif percent:
for k in fields:
entry.append(getattr(r, k).table()
entry.append(
(getattr(r, k).table()
if getattr(r, k, None) is not None
else types[k].none)
else types[k].none,
(lambda t: ['+∞%'] if t == +m.inf
else ['-∞%'] if t == -m.inf
else ['%+.1f%%' % (100*t)])(
types[k].ratio(
getattr(r, k, None),
getattr(diff_r, k, None)))))
else:
for k in fields:
entry.append(getattr(diff_r, k).table()
@@ -405,30 +412,17 @@ def table(Result, results, diff_results=None, *,
if getattr(r, k, None) is not None
else types[k].none)
for k in fields:
entry.append(types[k].diff(
entry.append(
(types[k].diff(
getattr(r, k, None),
getattr(diff_r, k, None)))
if diff_results is None:
notes = []
for k in fields:
try:
notes.extend(getattr(r, k).notes())
except AttributeError:
pass
entry.append(' (%s)' % ', '.join(notes)
if notes else '')
else:
ratios = [
getattr(diff_r, k, None)),
(lambda t: ['+∞%'] if t == +m.inf
else ['-∞%'] if t == -m.inf
else ['%+.1f%%' % (100*t)] if t
else [])(
types[k].ratio(
getattr(r, k, None),
getattr(diff_r, k, None))
for k in fields]
entry.append(' (%s)' % ', '.join(
'+∞%' if t == +m.inf
else '-∞%' if t == -m.inf
else '%+.1f%%' % (100*t)
for t in ratios)
if percent or any(ratios) else '')
getattr(diff_r, k, None)))))
return entry
# entries
@@ -455,13 +449,19 @@ def table(Result, results, diff_results=None, *,
diff_r = next(iter(fold(Result, diff_results, by=[])), None)
lines.append(table_entry('TOTAL', r, diff_r))
# find the best widths, note that column 0 contains the names and
# column -1 the ratios/notes, so those are handled a bit differently
widths = [
((max(it.chain([w], (len(l[i]) for l in lines)))+1+4-1)//4)*4-1
for w, i in zip(
it.chain([23], it.repeat(7)),
range(len(lines[0])-1))]
# homogenize
lines = [
[x if isinstance(x, tuple) else (x, []) for x in line]
for line in lines]
# find the best widths, note that column 0 contains the names and is
# handled a bit differently
widths = co.defaultdict(lambda: 7, {0: 23})
notes = co.defaultdict(lambda: 0)
for line in lines:
for i, x in enumerate(line):
widths[i] = max(widths[i], ((len(x[0])+1+4-1)//4)*4-1)
notes[i] = max(notes[i], 1+2*len(x[1])+sum(len(n) for n in x[1]))
# adjust the name width based on the call depth
if not summary:
@@ -486,11 +486,12 @@ def table(Result, results, diff_results=None, *,
widths[0] += 4*max(depth_-1, 0)
# print the tree recursively
print('%-*s %s%s' % (
widths[0], lines[0][0],
' '.join('%*s' % (w, x)
for w, x in zip(widths[1:], lines[0][1:-1])),
lines[0][-1]))
print('%-*s %s' % (
widths[0], lines[0][0][0],
' '.join('%*s%-*s' % (
widths[i], x[0],
notes[i], ' (%s)' % ', '.join(x[1]) if x[1] else '')
for i, x in enumerate(lines[0][1:], 1))))
if not summary:
line_table = {n: l for n, l in zip(names, lines[1:-1])}
@@ -502,17 +503,13 @@ def table(Result, results, diff_results=None, *,
line = line_table[name]
is_last = (i == len(names_)-1)
print('%s%-*s ' % (
print('%s%-*s %s' % (
prefixes[0+is_last],
widths[0] - len(prefixes[0+is_last]),
line[0]),
end='')
print(' %s%s' % (
' '.join('%*s' % (w, x)
for w, x in zip(widths[1:], line[1:-1])),
line[-1]),
end='')
print()
widths[0] - len(prefixes[0+is_last]), line[0][0],
' '.join('%*s%-*s' % (
widths[i], x[0],
notes[i], ' (%s)' % ', '.join(x[1]) if x[1] else '')
for i, x in enumerate(line[1:], 1))))
# recurse?
if name in table and depth_ > 1:
@@ -530,11 +527,12 @@ def table(Result, results, diff_results=None, *,
recurse(names, depth)
print('%-*s %s%s' % (
widths[0], lines[-1][0],
' '.join('%*s' % (w, x)
for w, x in zip(widths[1:], lines[-1][1:-1])),
lines[-1][-1]))
print('%-*s %s' % (
widths[0], lines[-1][0][0],
' '.join('%*s%-*s' % (
widths[i], x[0],
notes[i], ' (%s)' % ', '.join(x[1]) if x[1] else '')
for i, x in enumerate(lines[-1][1:], 1))))
def main(ci_paths,

View File

@@ -348,14 +348,14 @@ def table(Result, results, diff_results=None, *,
lines = []
# header
header = []
header.append('%s%s' % (
header = [
'%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 '')
if not summary else '')
if not summary else '']
if diff_results is None:
for k in fields:
header.append(k)
@@ -369,22 +369,29 @@ def table(Result, results, diff_results=None, *,
header.append('n'+k)
for k in fields:
header.append('d'+k)
header.append('')
lines.append(header)
def table_entry(name, r, diff_r=None):
entry = []
entry.append(name)
entry = [name]
if diff_results is None:
for k in fields:
entry.append(getattr(r, k).table()
entry.append(
(getattr(r, k).table(),
getattr(getattr(r, k), 'notes', lambda: [])())
if getattr(r, k, None) is not None
else types[k].none)
elif percent:
for k in fields:
entry.append(getattr(r, k).table()
entry.append(
(getattr(r, k).table()
if getattr(r, k, None) is not None
else types[k].none)
else types[k].none,
(lambda t: ['+∞%'] if t == +m.inf
else ['-∞%'] if t == -m.inf
else ['%+.1f%%' % (100*t)])(
types[k].ratio(
getattr(r, k, None),
getattr(diff_r, k, None)))))
else:
for k in fields:
entry.append(getattr(diff_r, k).table()
@@ -395,30 +402,17 @@ def table(Result, results, diff_results=None, *,
if getattr(r, k, None) is not None
else types[k].none)
for k in fields:
entry.append(types[k].diff(
entry.append(
(types[k].diff(
getattr(r, k, None),
getattr(diff_r, k, None)))
if diff_results is None:
notes = []
for k in fields:
try:
notes.extend(getattr(r, k).notes())
except AttributeError:
pass
entry.append(' (%s)' % ', '.join(notes)
if notes else '')
else:
ratios = [
getattr(diff_r, k, None)),
(lambda t: ['+∞%'] if t == +m.inf
else ['-∞%'] if t == -m.inf
else ['%+.1f%%' % (100*t)] if t
else [])(
types[k].ratio(
getattr(r, k, None),
getattr(diff_r, k, None))
for k in fields]
entry.append(' (%s)' % ', '.join(
'+∞%' if t == +m.inf
else '-∞%' if t == -m.inf
else '%+.1f%%' % (100*t)
for t in ratios)
if percent or any(ratios) else '')
getattr(diff_r, k, None)))))
return entry
# entries
@@ -445,21 +439,28 @@ def table(Result, results, diff_results=None, *,
diff_r = next(iter(fold(Result, diff_results, by=[])), None)
lines.append(table_entry('TOTAL', r, diff_r))
# find the best widths, note that column 0 contains the names and
# column -1 the ratios/notes, so those are handled a bit differently
widths = [
((max(it.chain([w], (len(l[i]) for l in lines)))+1+4-1)//4)*4-1
for w, i in zip(
it.chain([23], it.repeat(7)),
range(len(lines[0])-1))]
# homogenize
lines = [
[x if isinstance(x, tuple) else (x, []) for x in line]
for line in lines]
# find the best widths, note that column 0 contains the names and is
# handled a bit differently
widths = co.defaultdict(lambda: 7, {0: 23})
notes = co.defaultdict(lambda: 0)
for line in lines:
for i, x in enumerate(line):
widths[i] = max(widths[i], ((len(x[0])+1+4-1)//4)*4-1)
notes[i] = max(notes[i], 1+2*len(x[1])+sum(len(n) for n in x[1]))
# print our table
for line in lines:
print('%-*s %s%s' % (
widths[0], line[0],
' '.join('%*s' % (w, x)
for w, x in zip(widths[1:], line[1:-1])),
line[-1]))
print('%-*s %s' % (
widths[0], line[0][0],
' '.join('%*s%-*s' % (
widths[i], x[0],
notes[i], ' (%s)' % ', '.join(x[1]) if x[1] else '')
for i, x in enumerate(line[1:], 1))))
def main(obj_paths, *,

View File

@@ -479,14 +479,14 @@ def table(Result, results, diff_results=None, *,
lines = []
# header
header = []
header.append('%s%s' % (
header = [
'%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 '')
if not summary else '')
if not summary else '']
if diff_results is None:
for k in fields:
header.append(k)
@@ -500,22 +500,29 @@ def table(Result, results, diff_results=None, *,
header.append('n'+k)
for k in fields:
header.append('d'+k)
header.append('')
lines.append(header)
def table_entry(name, r, diff_r=None):
entry = []
entry.append(name)
entry = [name]
if diff_results is None:
for k in fields:
entry.append(getattr(r, k).table()
entry.append(
(getattr(r, k).table(),
getattr(getattr(r, k), 'notes', lambda: [])())
if getattr(r, k, None) is not None
else types[k].none)
elif percent:
for k in fields:
entry.append(getattr(r, k).table()
entry.append(
(getattr(r, k).table()
if getattr(r, k, None) is not None
else types[k].none)
else types[k].none,
(lambda t: ['+∞%'] if t == +m.inf
else ['-∞%'] if t == -m.inf
else ['%+.1f%%' % (100*t)])(
types[k].ratio(
getattr(r, k, None),
getattr(diff_r, k, None)))))
else:
for k in fields:
entry.append(getattr(diff_r, k).table()
@@ -526,30 +533,17 @@ def table(Result, results, diff_results=None, *,
if getattr(r, k, None) is not None
else types[k].none)
for k in fields:
entry.append(types[k].diff(
entry.append(
(types[k].diff(
getattr(r, k, None),
getattr(diff_r, k, None)))
if diff_results is None:
notes = []
for k in fields:
try:
notes.extend(getattr(r, k).notes())
except AttributeError:
pass
entry.append(' (%s)' % ', '.join(notes)
if notes else '')
else:
ratios = [
getattr(diff_r, k, None)),
(lambda t: ['+∞%'] if t == +m.inf
else ['-∞%'] if t == -m.inf
else ['%+.1f%%' % (100*t)] if t
else [])(
types[k].ratio(
getattr(r, k, None),
getattr(diff_r, k, None))
for k in fields]
entry.append(' (%s)' % ', '.join(
'+∞%' if t == +m.inf
else '-∞%' if t == -m.inf
else '%+.1f%%' % (100*t)
for t in ratios)
if percent or any(ratios) else '')
getattr(diff_r, k, None)))))
return entry
# entries
@@ -576,21 +570,28 @@ def table(Result, results, diff_results=None, *,
diff_r = next(iter(fold(Result, diff_results, by=[])), None)
lines.append(table_entry('TOTAL', r, diff_r))
# find the best widths, note that column 0 contains the names and
# column -1 the ratios/notes, so those are handled a bit differently
widths = [
((max(it.chain([w], (len(l[i]) for l in lines)))+1+4-1)//4)*4-1
for w, i in zip(
it.chain([23], it.repeat(7)),
range(len(lines[0])-1))]
# homogenize
lines = [
[x if isinstance(x, tuple) else (x, []) for x in line]
for line in lines]
# find the best widths, note that column 0 contains the names and is
# handled a bit differently
widths = co.defaultdict(lambda: 7, {0: 23})
notes = co.defaultdict(lambda: 0)
for line in lines:
for i, x in enumerate(line):
widths[i] = max(widths[i], ((len(x[0])+1+4-1)//4)*4-1)
notes[i] = max(notes[i], 1+2*len(x[1])+sum(len(n) for n in x[1]))
# print our table
for line in lines:
print('%-*s %s%s' % (
widths[0], line[0],
' '.join('%*s' % (w, x)
for w, x in zip(widths[1:], line[1:-1])),
line[-1]))
print('%-*s %s' % (
widths[0], line[0][0],
' '.join('%*s%-*s' % (
widths[i], x[0],
notes[i], ' (%s)' % ', '.join(x[1]) if x[1] else '')
for i, x in enumerate(line[1:], 1))))
def main(csv_paths, *,