scripts: Tweaked table renderer to not hide conflicting results
I think this is currently only possible with overlapping by/field fields, but hiding results with conflicting by fields is not ideal. Especially since this function is central to so many scripts: cat test.csv a,b,c x,2,1 x,1,2 x,1,3 Before: ./scripts/csv.py test.csv -ba -bb -fb -fc warning: by fields are unstable a,b b c x,2 2 1 TOTAL 4 6 After: ./scripts/csv.py test.csv -ba -bb -fb -fc a,b b c x,2 2 5 x,2 2 1 TOTAL 4 6 This solves the main issue with unstable by fields, so no more warning. Note that some features rely on by being unique to work (added/removed numbers, compare fields, etc). They shouldn't error, but may be incorrect/unintuitive with conflicting by fields, so avoiding conflicting by fields is still a good idea.
This commit is contained in:
+38
-58
@@ -640,30 +640,13 @@ def table(Result, results, diff_results=None, *,
|
|||||||
types = Result._types
|
types = Result._types
|
||||||
|
|
||||||
# organize by name
|
# organize by name
|
||||||
table = {
|
def table_name(r):
|
||||||
','.join(str(getattr(r, k)
|
return ','.join(str(getattr(r, k)
|
||||||
if getattr(r, k) is not None
|
if getattr(r, k) is not None
|
||||||
else '')
|
else '')
|
||||||
for k in by): r
|
for k in by)
|
||||||
for r in results}
|
table = {table_name(r): r for r in results}
|
||||||
diff_table = {
|
diff_table = {table_name(r): r for r in diff_results or []}
|
||||||
','.join(str(getattr(r, k)
|
|
||||||
if getattr(r, k) is not None
|
|
||||||
else '')
|
|
||||||
for k in by): r
|
|
||||||
for r in diff_results or []}
|
|
||||||
|
|
||||||
# lost results? note this can happen if a by field references the
|
|
||||||
# same field as a field field, and the field field changes during
|
|
||||||
# folding
|
|
||||||
#
|
|
||||||
# it's not an _error_, but can lead to really confusing results, so
|
|
||||||
# at least warn
|
|
||||||
if (len(table) != len(results)
|
|
||||||
or (diff_results is not None
|
|
||||||
and len(diff_table) != len(diff_results))):
|
|
||||||
print("warning: by fields are unstable",
|
|
||||||
file=sys.stderr)
|
|
||||||
|
|
||||||
# find compare entry if there is one
|
# find compare entry if there is one
|
||||||
if compare:
|
if compare:
|
||||||
@@ -705,9 +688,9 @@ def table(Result, results, diff_results=None, *,
|
|||||||
del diff_table
|
del diff_table
|
||||||
|
|
||||||
# entry helper
|
# entry helper
|
||||||
def table_entry(name, r, diff_r=None):
|
def table_entry(n, r, diff_r=None):
|
||||||
# prepend name
|
# prepend name
|
||||||
entry = [name]
|
entry = [n]
|
||||||
|
|
||||||
# normal entry?
|
# normal entry?
|
||||||
if ((compare is None or r == compare_r)
|
if ((compare is None or r == compare_r)
|
||||||
@@ -782,30 +765,26 @@ def table(Result, results, diff_results=None, *,
|
|||||||
depth_,
|
depth_,
|
||||||
prefixes=('', '', '', '')):
|
prefixes=('', '', '', '')):
|
||||||
# build the children table at each layer
|
# build the children table at each layer
|
||||||
table_ = {
|
table_ = {table_name(r): r for r in results_}
|
||||||
','.join(str(getattr(r, k)
|
diff_table_ = {table_name(r): r for r in diff_results_ or []}
|
||||||
if getattr(r, k) is not None
|
# this gets a bit tricky, we want to merge both result and diff
|
||||||
else '')
|
# result names, while preserving duplicates in the result list
|
||||||
for k in by): r
|
results__ = [(n, r)
|
||||||
for r in results_}
|
for n, r in it.chain(
|
||||||
diff_table_ = {
|
((table_name(r), r) for r in results_),
|
||||||
','.join(str(getattr(r, k)
|
((table_name(r), None)
|
||||||
if getattr(r, k) is not None
|
for r in diff_results_ or []
|
||||||
else '')
|
if table_name(r) not in table_))
|
||||||
for k in by): r
|
|
||||||
for r in diff_results_ or []}
|
|
||||||
names_ = [n
|
|
||||||
for n in table_.keys() | diff_table_.keys()
|
|
||||||
if diff_results is None
|
if diff_results is None
|
||||||
or all_
|
or all_
|
||||||
or any(
|
or any(
|
||||||
types[k].ratio(
|
types[k].ratio(
|
||||||
getattr(table_.get(n), k, None),
|
getattr(r, k, None),
|
||||||
getattr(diff_table_.get(n), k, None))
|
getattr(diff_table_.get(n), k, None))
|
||||||
for k in fields)]
|
for k in fields)]
|
||||||
|
|
||||||
# sort again, now with diff info, note that python's sort is stable
|
# sort again, now with diff info, note that python's sort is stable
|
||||||
names_.sort(key=lambda n: (
|
results__.sort(key=lambda nr: (lambda n, r: (
|
||||||
# sort by explicit sort fields
|
# sort by explicit sort fields
|
||||||
next(
|
next(
|
||||||
tuple((Rev
|
tuple((Rev
|
||||||
@@ -816,35 +795,34 @@ def table(Result, results, diff_results=None, *,
|
|||||||
else ()
|
else ()
|
||||||
for k_ in ([k] if k else Result._sort)))
|
for k_ in ([k] if k else Result._sort)))
|
||||||
for k, reverse in (sort or []))
|
for k, reverse in (sort or []))
|
||||||
for r_ in [table_.get(n), diff_table_.get(n)]
|
for r_ in [r, diff_table_.get(n)]
|
||||||
if r_ is not None),
|
if r_ is not None),
|
||||||
# sort by ratio if diffing
|
# sort by ratio if diffing
|
||||||
Rev(tuple(types[k].ratio(
|
Rev(tuple(types[k].ratio(
|
||||||
getattr(table_.get(n), k, None),
|
getattr(r, k, None),
|
||||||
getattr(diff_table_.get(n), k, None))
|
getattr(diff_table_.get(n), k, None))
|
||||||
for k in fields))
|
for k in fields))
|
||||||
if diff_results is not None
|
if diff_results is not None
|
||||||
else (),
|
else (),
|
||||||
# move compare entry to the top, note this can be
|
# move compare entry to the top, note this can be
|
||||||
# overridden by explicitly sorting by fields
|
# overridden by explicitly sorting by fields
|
||||||
(table_.get(n) != compare_r,
|
(r != compare_r,
|
||||||
# sort by ratio if comparing
|
# sort by ratio if comparing
|
||||||
Rev(tuple(
|
Rev(tuple(
|
||||||
types[k].ratio(
|
types[k].ratio(
|
||||||
getattr(table_.get(n), k, None),
|
getattr(r, k, None),
|
||||||
getattr(compare_r, k, None))
|
getattr(compare_r, k, None))
|
||||||
for k in fields)))
|
for k in fields)))
|
||||||
if compare
|
if compare
|
||||||
else (),
|
else (),
|
||||||
# sort by result
|
# sort by result
|
||||||
(table_[n],) if n in table_ else (),
|
(r,) if r is not None else (),
|
||||||
# and finally by name (diffs may be missing results)
|
# and finally by name (diffs may be missing results)
|
||||||
n))
|
n))(*nr))
|
||||||
|
|
||||||
for i, name in enumerate(names_):
|
for i, (n, r) in enumerate(results__):
|
||||||
# find comparable results
|
# find comparable results
|
||||||
r = table_.get(name)
|
diff_r = diff_table_.get(n)
|
||||||
diff_r = diff_table_.get(name)
|
|
||||||
|
|
||||||
# figure out a good label
|
# figure out a good label
|
||||||
if labels is not None:
|
if labels is not None:
|
||||||
@@ -856,26 +834,28 @@ def table(Result, results, diff_results=None, *,
|
|||||||
for r_ in [r, diff_r]
|
for r_ in [r, diff_r]
|
||||||
if r_ is not None)
|
if r_ is not None)
|
||||||
else:
|
else:
|
||||||
label = name
|
label = n
|
||||||
|
|
||||||
# build line
|
# build line
|
||||||
line = table_entry(label, r, diff_r)
|
line = table_entry(label, r, diff_r)
|
||||||
|
|
||||||
# add prefixes
|
# add prefixes
|
||||||
line = [x if isinstance(x, tuple) else (x, []) for x in line]
|
line = [x if isinstance(x, tuple) else (x, []) for x in line]
|
||||||
line[0] = (prefixes[0+(i==len(names_)-1)] + line[0][0], line[0][1])
|
line[0] = (
|
||||||
|
prefixes[0+(i==len(results__)-1)] + line[0][0],
|
||||||
|
line[0][1])
|
||||||
lines.append(line)
|
lines.append(line)
|
||||||
|
|
||||||
# recurse?
|
# recurse?
|
||||||
if name in table_ and depth_ > 1:
|
if r is not None and depth_ > 1:
|
||||||
table_recurse(
|
table_recurse(
|
||||||
getattr(r, Result._children),
|
getattr(r, Result._children),
|
||||||
getattr(diff_r, Result._children, None),
|
getattr(diff_r, Result._children, None),
|
||||||
depth_-1,
|
depth_-1,
|
||||||
(prefixes[2+(i==len(names_)-1)] + "|-> ",
|
(prefixes[2+(i==len(results__)-1)] + "|-> ",
|
||||||
prefixes[2+(i==len(names_)-1)] + "'-> ",
|
prefixes[2+(i==len(results__)-1)] + "'-> ",
|
||||||
prefixes[2+(i==len(names_)-1)] + "| ",
|
prefixes[2+(i==len(results__)-1)] + "| ",
|
||||||
prefixes[2+(i==len(names_)-1)] + " "))
|
prefixes[2+(i==len(results__)-1)] + " "))
|
||||||
|
|
||||||
# build entries
|
# build entries
|
||||||
if not summary:
|
if not summary:
|
||||||
|
|||||||
+38
-58
@@ -503,30 +503,13 @@ def table(Result, results, diff_results=None, *,
|
|||||||
types = Result._types
|
types = Result._types
|
||||||
|
|
||||||
# organize by name
|
# organize by name
|
||||||
table = {
|
def table_name(r):
|
||||||
','.join(str(getattr(r, k)
|
return ','.join(str(getattr(r, k)
|
||||||
if getattr(r, k) is not None
|
if getattr(r, k) is not None
|
||||||
else '')
|
else '')
|
||||||
for k in by): r
|
for k in by)
|
||||||
for r in results}
|
table = {table_name(r): r for r in results}
|
||||||
diff_table = {
|
diff_table = {table_name(r): r for r in diff_results or []}
|
||||||
','.join(str(getattr(r, k)
|
|
||||||
if getattr(r, k) is not None
|
|
||||||
else '')
|
|
||||||
for k in by): r
|
|
||||||
for r in diff_results or []}
|
|
||||||
|
|
||||||
# lost results? note this can happen if a by field references the
|
|
||||||
# same field as a field field, and the field field changes during
|
|
||||||
# folding
|
|
||||||
#
|
|
||||||
# it's not an _error_, but can lead to really confusing results, so
|
|
||||||
# at least warn
|
|
||||||
if (len(table) != len(results)
|
|
||||||
or (diff_results is not None
|
|
||||||
and len(diff_table) != len(diff_results))):
|
|
||||||
print("warning: by fields are unstable",
|
|
||||||
file=sys.stderr)
|
|
||||||
|
|
||||||
# find compare entry if there is one
|
# find compare entry if there is one
|
||||||
if compare:
|
if compare:
|
||||||
@@ -568,9 +551,9 @@ def table(Result, results, diff_results=None, *,
|
|||||||
del diff_table
|
del diff_table
|
||||||
|
|
||||||
# entry helper
|
# entry helper
|
||||||
def table_entry(name, r, diff_r=None):
|
def table_entry(n, r, diff_r=None):
|
||||||
# prepend name
|
# prepend name
|
||||||
entry = [name]
|
entry = [n]
|
||||||
|
|
||||||
# normal entry?
|
# normal entry?
|
||||||
if ((compare is None or r == compare_r)
|
if ((compare is None or r == compare_r)
|
||||||
@@ -645,30 +628,26 @@ def table(Result, results, diff_results=None, *,
|
|||||||
depth_,
|
depth_,
|
||||||
prefixes=('', '', '', '')):
|
prefixes=('', '', '', '')):
|
||||||
# build the children table at each layer
|
# build the children table at each layer
|
||||||
table_ = {
|
table_ = {table_name(r): r for r in results_}
|
||||||
','.join(str(getattr(r, k)
|
diff_table_ = {table_name(r): r for r in diff_results_ or []}
|
||||||
if getattr(r, k) is not None
|
# this gets a bit tricky, we want to merge both result and diff
|
||||||
else '')
|
# result names, while preserving duplicates in the result list
|
||||||
for k in by): r
|
results__ = [(n, r)
|
||||||
for r in results_}
|
for n, r in it.chain(
|
||||||
diff_table_ = {
|
((table_name(r), r) for r in results_),
|
||||||
','.join(str(getattr(r, k)
|
((table_name(r), None)
|
||||||
if getattr(r, k) is not None
|
for r in diff_results_ or []
|
||||||
else '')
|
if table_name(r) not in table_))
|
||||||
for k in by): r
|
|
||||||
for r in diff_results_ or []}
|
|
||||||
names_ = [n
|
|
||||||
for n in table_.keys() | diff_table_.keys()
|
|
||||||
if diff_results is None
|
if diff_results is None
|
||||||
or all_
|
or all_
|
||||||
or any(
|
or any(
|
||||||
types[k].ratio(
|
types[k].ratio(
|
||||||
getattr(table_.get(n), k, None),
|
getattr(r, k, None),
|
||||||
getattr(diff_table_.get(n), k, None))
|
getattr(diff_table_.get(n), k, None))
|
||||||
for k in fields)]
|
for k in fields)]
|
||||||
|
|
||||||
# sort again, now with diff info, note that python's sort is stable
|
# sort again, now with diff info, note that python's sort is stable
|
||||||
names_.sort(key=lambda n: (
|
results__.sort(key=lambda nr: (lambda n, r: (
|
||||||
# sort by explicit sort fields
|
# sort by explicit sort fields
|
||||||
next(
|
next(
|
||||||
tuple((Rev
|
tuple((Rev
|
||||||
@@ -679,35 +658,34 @@ def table(Result, results, diff_results=None, *,
|
|||||||
else ()
|
else ()
|
||||||
for k_ in ([k] if k else Result._sort)))
|
for k_ in ([k] if k else Result._sort)))
|
||||||
for k, reverse in (sort or []))
|
for k, reverse in (sort or []))
|
||||||
for r_ in [table_.get(n), diff_table_.get(n)]
|
for r_ in [r, diff_table_.get(n)]
|
||||||
if r_ is not None),
|
if r_ is not None),
|
||||||
# sort by ratio if diffing
|
# sort by ratio if diffing
|
||||||
Rev(tuple(types[k].ratio(
|
Rev(tuple(types[k].ratio(
|
||||||
getattr(table_.get(n), k, None),
|
getattr(r, k, None),
|
||||||
getattr(diff_table_.get(n), k, None))
|
getattr(diff_table_.get(n), k, None))
|
||||||
for k in fields))
|
for k in fields))
|
||||||
if diff_results is not None
|
if diff_results is not None
|
||||||
else (),
|
else (),
|
||||||
# move compare entry to the top, note this can be
|
# move compare entry to the top, note this can be
|
||||||
# overridden by explicitly sorting by fields
|
# overridden by explicitly sorting by fields
|
||||||
(table_.get(n) != compare_r,
|
(r != compare_r,
|
||||||
# sort by ratio if comparing
|
# sort by ratio if comparing
|
||||||
Rev(tuple(
|
Rev(tuple(
|
||||||
types[k].ratio(
|
types[k].ratio(
|
||||||
getattr(table_.get(n), k, None),
|
getattr(r, k, None),
|
||||||
getattr(compare_r, k, None))
|
getattr(compare_r, k, None))
|
||||||
for k in fields)))
|
for k in fields)))
|
||||||
if compare
|
if compare
|
||||||
else (),
|
else (),
|
||||||
# sort by result
|
# sort by result
|
||||||
(table_[n],) if n in table_ else (),
|
(r,) if r is not None else (),
|
||||||
# and finally by name (diffs may be missing results)
|
# and finally by name (diffs may be missing results)
|
||||||
n))
|
n))(*nr))
|
||||||
|
|
||||||
for i, name in enumerate(names_):
|
for i, (n, r) in enumerate(results__):
|
||||||
# find comparable results
|
# find comparable results
|
||||||
r = table_.get(name)
|
diff_r = diff_table_.get(n)
|
||||||
diff_r = diff_table_.get(name)
|
|
||||||
|
|
||||||
# figure out a good label
|
# figure out a good label
|
||||||
if labels is not None:
|
if labels is not None:
|
||||||
@@ -719,26 +697,28 @@ def table(Result, results, diff_results=None, *,
|
|||||||
for r_ in [r, diff_r]
|
for r_ in [r, diff_r]
|
||||||
if r_ is not None)
|
if r_ is not None)
|
||||||
else:
|
else:
|
||||||
label = name
|
label = n
|
||||||
|
|
||||||
# build line
|
# build line
|
||||||
line = table_entry(label, r, diff_r)
|
line = table_entry(label, r, diff_r)
|
||||||
|
|
||||||
# add prefixes
|
# add prefixes
|
||||||
line = [x if isinstance(x, tuple) else (x, []) for x in line]
|
line = [x if isinstance(x, tuple) else (x, []) for x in line]
|
||||||
line[0] = (prefixes[0+(i==len(names_)-1)] + line[0][0], line[0][1])
|
line[0] = (
|
||||||
|
prefixes[0+(i==len(results__)-1)] + line[0][0],
|
||||||
|
line[0][1])
|
||||||
lines.append(line)
|
lines.append(line)
|
||||||
|
|
||||||
# recurse?
|
# recurse?
|
||||||
if name in table_ and depth_ > 1:
|
if r is not None and depth_ > 1:
|
||||||
table_recurse(
|
table_recurse(
|
||||||
getattr(r, Result._children),
|
getattr(r, Result._children),
|
||||||
getattr(diff_r, Result._children, None),
|
getattr(diff_r, Result._children, None),
|
||||||
depth_-1,
|
depth_-1,
|
||||||
(prefixes[2+(i==len(names_)-1)] + "|-> ",
|
(prefixes[2+(i==len(results__)-1)] + "|-> ",
|
||||||
prefixes[2+(i==len(names_)-1)] + "'-> ",
|
prefixes[2+(i==len(results__)-1)] + "'-> ",
|
||||||
prefixes[2+(i==len(names_)-1)] + "| ",
|
prefixes[2+(i==len(results__)-1)] + "| ",
|
||||||
prefixes[2+(i==len(names_)-1)] + " "))
|
prefixes[2+(i==len(results__)-1)] + " "))
|
||||||
|
|
||||||
# build entries
|
# build entries
|
||||||
if not summary:
|
if not summary:
|
||||||
|
|||||||
+38
-58
@@ -1962,30 +1962,13 @@ def table(Result, results, diff_results=None, *,
|
|||||||
types = Result._types
|
types = Result._types
|
||||||
|
|
||||||
# organize by name
|
# organize by name
|
||||||
table = {
|
def table_name(r):
|
||||||
','.join(str(getattr(r, k)
|
return ','.join(str(getattr(r, k)
|
||||||
if getattr(r, k) is not None
|
if getattr(r, k) is not None
|
||||||
else '')
|
else '')
|
||||||
for k in by): r
|
for k in by)
|
||||||
for r in results}
|
table = {table_name(r): r for r in results}
|
||||||
diff_table = {
|
diff_table = {table_name(r): r for r in diff_results or []}
|
||||||
','.join(str(getattr(r, k)
|
|
||||||
if getattr(r, k) is not None
|
|
||||||
else '')
|
|
||||||
for k in by): r
|
|
||||||
for r in diff_results or []}
|
|
||||||
|
|
||||||
# lost results? note this can happen if a by field references the
|
|
||||||
# same field as a field field, and the field field changes during
|
|
||||||
# folding
|
|
||||||
#
|
|
||||||
# it's not an _error_, but can lead to really confusing results, so
|
|
||||||
# at least warn
|
|
||||||
if (len(table) != len(results)
|
|
||||||
or (diff_results is not None
|
|
||||||
and len(diff_table) != len(diff_results))):
|
|
||||||
print("warning: by fields are unstable",
|
|
||||||
file=sys.stderr)
|
|
||||||
|
|
||||||
# find compare entry if there is one
|
# find compare entry if there is one
|
||||||
if compare:
|
if compare:
|
||||||
@@ -2027,9 +2010,9 @@ def table(Result, results, diff_results=None, *,
|
|||||||
del diff_table
|
del diff_table
|
||||||
|
|
||||||
# entry helper
|
# entry helper
|
||||||
def table_entry(name, r, diff_r=None):
|
def table_entry(n, r, diff_r=None):
|
||||||
# prepend name
|
# prepend name
|
||||||
entry = [name]
|
entry = [n]
|
||||||
|
|
||||||
# normal entry?
|
# normal entry?
|
||||||
if ((compare is None or r == compare_r)
|
if ((compare is None or r == compare_r)
|
||||||
@@ -2104,30 +2087,26 @@ def table(Result, results, diff_results=None, *,
|
|||||||
depth_,
|
depth_,
|
||||||
prefixes=('', '', '', '')):
|
prefixes=('', '', '', '')):
|
||||||
# build the children table at each layer
|
# build the children table at each layer
|
||||||
table_ = {
|
table_ = {table_name(r): r for r in results_}
|
||||||
','.join(str(getattr(r, k)
|
diff_table_ = {table_name(r): r for r in diff_results_ or []}
|
||||||
if getattr(r, k) is not None
|
# this gets a bit tricky, we want to merge both result and diff
|
||||||
else '')
|
# result names, while preserving duplicates in the result list
|
||||||
for k in by): r
|
results__ = [(n, r)
|
||||||
for r in results_}
|
for n, r in it.chain(
|
||||||
diff_table_ = {
|
((table_name(r), r) for r in results_),
|
||||||
','.join(str(getattr(r, k)
|
((table_name(r), None)
|
||||||
if getattr(r, k) is not None
|
for r in diff_results_ or []
|
||||||
else '')
|
if table_name(r) not in table_))
|
||||||
for k in by): r
|
|
||||||
for r in diff_results_ or []}
|
|
||||||
names_ = [n
|
|
||||||
for n in table_.keys() | diff_table_.keys()
|
|
||||||
if diff_results is None
|
if diff_results is None
|
||||||
or all_
|
or all_
|
||||||
or any(
|
or any(
|
||||||
types[k].ratio(
|
types[k].ratio(
|
||||||
getattr(table_.get(n), k, None),
|
getattr(r, k, None),
|
||||||
getattr(diff_table_.get(n), k, None))
|
getattr(diff_table_.get(n), k, None))
|
||||||
for k in fields)]
|
for k in fields)]
|
||||||
|
|
||||||
# sort again, now with diff info, note that python's sort is stable
|
# sort again, now with diff info, note that python's sort is stable
|
||||||
names_.sort(key=lambda n: (
|
results__.sort(key=lambda nr: (lambda n, r: (
|
||||||
# sort by explicit sort fields
|
# sort by explicit sort fields
|
||||||
next(
|
next(
|
||||||
tuple((Rev
|
tuple((Rev
|
||||||
@@ -2138,35 +2117,34 @@ def table(Result, results, diff_results=None, *,
|
|||||||
else ()
|
else ()
|
||||||
for k_ in ([k] if k else Result._sort)))
|
for k_ in ([k] if k else Result._sort)))
|
||||||
for k, reverse in (sort or []))
|
for k, reverse in (sort or []))
|
||||||
for r_ in [table_.get(n), diff_table_.get(n)]
|
for r_ in [r, diff_table_.get(n)]
|
||||||
if r_ is not None),
|
if r_ is not None),
|
||||||
# sort by ratio if diffing
|
# sort by ratio if diffing
|
||||||
Rev(tuple(types[k].ratio(
|
Rev(tuple(types[k].ratio(
|
||||||
getattr(table_.get(n), k, None),
|
getattr(r, k, None),
|
||||||
getattr(diff_table_.get(n), k, None))
|
getattr(diff_table_.get(n), k, None))
|
||||||
for k in fields))
|
for k in fields))
|
||||||
if diff_results is not None
|
if diff_results is not None
|
||||||
else (),
|
else (),
|
||||||
# move compare entry to the top, note this can be
|
# move compare entry to the top, note this can be
|
||||||
# overridden by explicitly sorting by fields
|
# overridden by explicitly sorting by fields
|
||||||
(table_.get(n) != compare_r,
|
(r != compare_r,
|
||||||
# sort by ratio if comparing
|
# sort by ratio if comparing
|
||||||
Rev(tuple(
|
Rev(tuple(
|
||||||
types[k].ratio(
|
types[k].ratio(
|
||||||
getattr(table_.get(n), k, None),
|
getattr(r, k, None),
|
||||||
getattr(compare_r, k, None))
|
getattr(compare_r, k, None))
|
||||||
for k in fields)))
|
for k in fields)))
|
||||||
if compare
|
if compare
|
||||||
else (),
|
else (),
|
||||||
# sort by result
|
# sort by result
|
||||||
(table_[n],) if n in table_ else (),
|
(r,) if r is not None else (),
|
||||||
# and finally by name (diffs may be missing results)
|
# and finally by name (diffs may be missing results)
|
||||||
n))
|
n))(*nr))
|
||||||
|
|
||||||
for i, name in enumerate(names_):
|
for i, (n, r) in enumerate(results__):
|
||||||
# find comparable results
|
# find comparable results
|
||||||
r = table_.get(name)
|
diff_r = diff_table_.get(n)
|
||||||
diff_r = diff_table_.get(name)
|
|
||||||
|
|
||||||
# figure out a good label
|
# figure out a good label
|
||||||
if labels is not None:
|
if labels is not None:
|
||||||
@@ -2178,26 +2156,28 @@ def table(Result, results, diff_results=None, *,
|
|||||||
for r_ in [r, diff_r]
|
for r_ in [r, diff_r]
|
||||||
if r_ is not None)
|
if r_ is not None)
|
||||||
else:
|
else:
|
||||||
label = name
|
label = n
|
||||||
|
|
||||||
# build line
|
# build line
|
||||||
line = table_entry(label, r, diff_r)
|
line = table_entry(label, r, diff_r)
|
||||||
|
|
||||||
# add prefixes
|
# add prefixes
|
||||||
line = [x if isinstance(x, tuple) else (x, []) for x in line]
|
line = [x if isinstance(x, tuple) else (x, []) for x in line]
|
||||||
line[0] = (prefixes[0+(i==len(names_)-1)] + line[0][0], line[0][1])
|
line[0] = (
|
||||||
|
prefixes[0+(i==len(results__)-1)] + line[0][0],
|
||||||
|
line[0][1])
|
||||||
lines.append(line)
|
lines.append(line)
|
||||||
|
|
||||||
# recurse?
|
# recurse?
|
||||||
if name in table_ and depth_ > 1:
|
if r is not None and depth_ > 1:
|
||||||
table_recurse(
|
table_recurse(
|
||||||
getattr(r, Result._children),
|
getattr(r, Result._children),
|
||||||
getattr(diff_r, Result._children, None),
|
getattr(diff_r, Result._children, None),
|
||||||
depth_-1,
|
depth_-1,
|
||||||
(prefixes[2+(i==len(names_)-1)] + "|-> ",
|
(prefixes[2+(i==len(results__)-1)] + "|-> ",
|
||||||
prefixes[2+(i==len(names_)-1)] + "'-> ",
|
prefixes[2+(i==len(results__)-1)] + "'-> ",
|
||||||
prefixes[2+(i==len(names_)-1)] + "| ",
|
prefixes[2+(i==len(results__)-1)] + "| ",
|
||||||
prefixes[2+(i==len(names_)-1)] + " "))
|
prefixes[2+(i==len(results__)-1)] + " "))
|
||||||
|
|
||||||
# build entries
|
# build entries
|
||||||
if not summary:
|
if not summary:
|
||||||
|
|||||||
+38
-58
@@ -899,30 +899,13 @@ def table(Result, results, diff_results=None, *,
|
|||||||
types = Result._types
|
types = Result._types
|
||||||
|
|
||||||
# organize by name
|
# organize by name
|
||||||
table = {
|
def table_name(r):
|
||||||
','.join(str(getattr(r, k)
|
return ','.join(str(getattr(r, k)
|
||||||
if getattr(r, k) is not None
|
if getattr(r, k) is not None
|
||||||
else '')
|
else '')
|
||||||
for k in by): r
|
for k in by)
|
||||||
for r in results}
|
table = {table_name(r): r for r in results}
|
||||||
diff_table = {
|
diff_table = {table_name(r): r for r in diff_results or []}
|
||||||
','.join(str(getattr(r, k)
|
|
||||||
if getattr(r, k) is not None
|
|
||||||
else '')
|
|
||||||
for k in by): r
|
|
||||||
for r in diff_results or []}
|
|
||||||
|
|
||||||
# lost results? note this can happen if a by field references the
|
|
||||||
# same field as a field field, and the field field changes during
|
|
||||||
# folding
|
|
||||||
#
|
|
||||||
# it's not an _error_, but can lead to really confusing results, so
|
|
||||||
# at least warn
|
|
||||||
if (len(table) != len(results)
|
|
||||||
or (diff_results is not None
|
|
||||||
and len(diff_table) != len(diff_results))):
|
|
||||||
print("warning: by fields are unstable",
|
|
||||||
file=sys.stderr)
|
|
||||||
|
|
||||||
# find compare entry if there is one
|
# find compare entry if there is one
|
||||||
if compare:
|
if compare:
|
||||||
@@ -964,9 +947,9 @@ def table(Result, results, diff_results=None, *,
|
|||||||
del diff_table
|
del diff_table
|
||||||
|
|
||||||
# entry helper
|
# entry helper
|
||||||
def table_entry(name, r, diff_r=None):
|
def table_entry(n, r, diff_r=None):
|
||||||
# prepend name
|
# prepend name
|
||||||
entry = [name]
|
entry = [n]
|
||||||
|
|
||||||
# normal entry?
|
# normal entry?
|
||||||
if ((compare is None or r == compare_r)
|
if ((compare is None or r == compare_r)
|
||||||
@@ -1041,30 +1024,26 @@ def table(Result, results, diff_results=None, *,
|
|||||||
depth_,
|
depth_,
|
||||||
prefixes=('', '', '', '')):
|
prefixes=('', '', '', '')):
|
||||||
# build the children table at each layer
|
# build the children table at each layer
|
||||||
table_ = {
|
table_ = {table_name(r): r for r in results_}
|
||||||
','.join(str(getattr(r, k)
|
diff_table_ = {table_name(r): r for r in diff_results_ or []}
|
||||||
if getattr(r, k) is not None
|
# this gets a bit tricky, we want to merge both result and diff
|
||||||
else '')
|
# result names, while preserving duplicates in the result list
|
||||||
for k in by): r
|
results__ = [(n, r)
|
||||||
for r in results_}
|
for n, r in it.chain(
|
||||||
diff_table_ = {
|
((table_name(r), r) for r in results_),
|
||||||
','.join(str(getattr(r, k)
|
((table_name(r), None)
|
||||||
if getattr(r, k) is not None
|
for r in diff_results_ or []
|
||||||
else '')
|
if table_name(r) not in table_))
|
||||||
for k in by): r
|
|
||||||
for r in diff_results_ or []}
|
|
||||||
names_ = [n
|
|
||||||
for n in table_.keys() | diff_table_.keys()
|
|
||||||
if diff_results is None
|
if diff_results is None
|
||||||
or all_
|
or all_
|
||||||
or any(
|
or any(
|
||||||
types[k].ratio(
|
types[k].ratio(
|
||||||
getattr(table_.get(n), k, None),
|
getattr(r, k, None),
|
||||||
getattr(diff_table_.get(n), k, None))
|
getattr(diff_table_.get(n), k, None))
|
||||||
for k in fields)]
|
for k in fields)]
|
||||||
|
|
||||||
# sort again, now with diff info, note that python's sort is stable
|
# sort again, now with diff info, note that python's sort is stable
|
||||||
names_.sort(key=lambda n: (
|
results__.sort(key=lambda nr: (lambda n, r: (
|
||||||
# sort by explicit sort fields
|
# sort by explicit sort fields
|
||||||
next(
|
next(
|
||||||
tuple((Rev
|
tuple((Rev
|
||||||
@@ -1075,35 +1054,34 @@ def table(Result, results, diff_results=None, *,
|
|||||||
else ()
|
else ()
|
||||||
for k_ in ([k] if k else Result._sort)))
|
for k_ in ([k] if k else Result._sort)))
|
||||||
for k, reverse in (sort or []))
|
for k, reverse in (sort or []))
|
||||||
for r_ in [table_.get(n), diff_table_.get(n)]
|
for r_ in [r, diff_table_.get(n)]
|
||||||
if r_ is not None),
|
if r_ is not None),
|
||||||
# sort by ratio if diffing
|
# sort by ratio if diffing
|
||||||
Rev(tuple(types[k].ratio(
|
Rev(tuple(types[k].ratio(
|
||||||
getattr(table_.get(n), k, None),
|
getattr(r, k, None),
|
||||||
getattr(diff_table_.get(n), k, None))
|
getattr(diff_table_.get(n), k, None))
|
||||||
for k in fields))
|
for k in fields))
|
||||||
if diff_results is not None
|
if diff_results is not None
|
||||||
else (),
|
else (),
|
||||||
# move compare entry to the top, note this can be
|
# move compare entry to the top, note this can be
|
||||||
# overridden by explicitly sorting by fields
|
# overridden by explicitly sorting by fields
|
||||||
(table_.get(n) != compare_r,
|
(r != compare_r,
|
||||||
# sort by ratio if comparing
|
# sort by ratio if comparing
|
||||||
Rev(tuple(
|
Rev(tuple(
|
||||||
types[k].ratio(
|
types[k].ratio(
|
||||||
getattr(table_.get(n), k, None),
|
getattr(r, k, None),
|
||||||
getattr(compare_r, k, None))
|
getattr(compare_r, k, None))
|
||||||
for k in fields)))
|
for k in fields)))
|
||||||
if compare
|
if compare
|
||||||
else (),
|
else (),
|
||||||
# sort by result
|
# sort by result
|
||||||
(table_[n],) if n in table_ else (),
|
(r,) if r is not None else (),
|
||||||
# and finally by name (diffs may be missing results)
|
# and finally by name (diffs may be missing results)
|
||||||
n))
|
n))(*nr))
|
||||||
|
|
||||||
for i, name in enumerate(names_):
|
for i, (n, r) in enumerate(results__):
|
||||||
# find comparable results
|
# find comparable results
|
||||||
r = table_.get(name)
|
diff_r = diff_table_.get(n)
|
||||||
diff_r = diff_table_.get(name)
|
|
||||||
|
|
||||||
# figure out a good label
|
# figure out a good label
|
||||||
if labels is not None:
|
if labels is not None:
|
||||||
@@ -1115,26 +1093,28 @@ def table(Result, results, diff_results=None, *,
|
|||||||
for r_ in [r, diff_r]
|
for r_ in [r, diff_r]
|
||||||
if r_ is not None)
|
if r_ is not None)
|
||||||
else:
|
else:
|
||||||
label = name
|
label = n
|
||||||
|
|
||||||
# build line
|
# build line
|
||||||
line = table_entry(label, r, diff_r)
|
line = table_entry(label, r, diff_r)
|
||||||
|
|
||||||
# add prefixes
|
# add prefixes
|
||||||
line = [x if isinstance(x, tuple) else (x, []) for x in line]
|
line = [x if isinstance(x, tuple) else (x, []) for x in line]
|
||||||
line[0] = (prefixes[0+(i==len(names_)-1)] + line[0][0], line[0][1])
|
line[0] = (
|
||||||
|
prefixes[0+(i==len(results__)-1)] + line[0][0],
|
||||||
|
line[0][1])
|
||||||
lines.append(line)
|
lines.append(line)
|
||||||
|
|
||||||
# recurse?
|
# recurse?
|
||||||
if name in table_ and depth_ > 1:
|
if r is not None and depth_ > 1:
|
||||||
table_recurse(
|
table_recurse(
|
||||||
getattr(r, Result._children),
|
getattr(r, Result._children),
|
||||||
getattr(diff_r, Result._children, None),
|
getattr(diff_r, Result._children, None),
|
||||||
depth_-1,
|
depth_-1,
|
||||||
(prefixes[2+(i==len(names_)-1)] + "|-> ",
|
(prefixes[2+(i==len(results__)-1)] + "|-> ",
|
||||||
prefixes[2+(i==len(names_)-1)] + "'-> ",
|
prefixes[2+(i==len(results__)-1)] + "'-> ",
|
||||||
prefixes[2+(i==len(names_)-1)] + "| ",
|
prefixes[2+(i==len(results__)-1)] + "| ",
|
||||||
prefixes[2+(i==len(names_)-1)] + " "))
|
prefixes[2+(i==len(results__)-1)] + " "))
|
||||||
|
|
||||||
# build entries
|
# build entries
|
||||||
if not summary:
|
if not summary:
|
||||||
|
|||||||
+38
-58
@@ -640,30 +640,13 @@ def table(Result, results, diff_results=None, *,
|
|||||||
types = Result._types
|
types = Result._types
|
||||||
|
|
||||||
# organize by name
|
# organize by name
|
||||||
table = {
|
def table_name(r):
|
||||||
','.join(str(getattr(r, k)
|
return ','.join(str(getattr(r, k)
|
||||||
if getattr(r, k) is not None
|
if getattr(r, k) is not None
|
||||||
else '')
|
else '')
|
||||||
for k in by): r
|
for k in by)
|
||||||
for r in results}
|
table = {table_name(r): r for r in results}
|
||||||
diff_table = {
|
diff_table = {table_name(r): r for r in diff_results or []}
|
||||||
','.join(str(getattr(r, k)
|
|
||||||
if getattr(r, k) is not None
|
|
||||||
else '')
|
|
||||||
for k in by): r
|
|
||||||
for r in diff_results or []}
|
|
||||||
|
|
||||||
# lost results? note this can happen if a by field references the
|
|
||||||
# same field as a field field, and the field field changes during
|
|
||||||
# folding
|
|
||||||
#
|
|
||||||
# it's not an _error_, but can lead to really confusing results, so
|
|
||||||
# at least warn
|
|
||||||
if (len(table) != len(results)
|
|
||||||
or (diff_results is not None
|
|
||||||
and len(diff_table) != len(diff_results))):
|
|
||||||
print("warning: by fields are unstable",
|
|
||||||
file=sys.stderr)
|
|
||||||
|
|
||||||
# find compare entry if there is one
|
# find compare entry if there is one
|
||||||
if compare:
|
if compare:
|
||||||
@@ -705,9 +688,9 @@ def table(Result, results, diff_results=None, *,
|
|||||||
del diff_table
|
del diff_table
|
||||||
|
|
||||||
# entry helper
|
# entry helper
|
||||||
def table_entry(name, r, diff_r=None):
|
def table_entry(n, r, diff_r=None):
|
||||||
# prepend name
|
# prepend name
|
||||||
entry = [name]
|
entry = [n]
|
||||||
|
|
||||||
# normal entry?
|
# normal entry?
|
||||||
if ((compare is None or r == compare_r)
|
if ((compare is None or r == compare_r)
|
||||||
@@ -782,30 +765,26 @@ def table(Result, results, diff_results=None, *,
|
|||||||
depth_,
|
depth_,
|
||||||
prefixes=('', '', '', '')):
|
prefixes=('', '', '', '')):
|
||||||
# build the children table at each layer
|
# build the children table at each layer
|
||||||
table_ = {
|
table_ = {table_name(r): r for r in results_}
|
||||||
','.join(str(getattr(r, k)
|
diff_table_ = {table_name(r): r for r in diff_results_ or []}
|
||||||
if getattr(r, k) is not None
|
# this gets a bit tricky, we want to merge both result and diff
|
||||||
else '')
|
# result names, while preserving duplicates in the result list
|
||||||
for k in by): r
|
results__ = [(n, r)
|
||||||
for r in results_}
|
for n, r in it.chain(
|
||||||
diff_table_ = {
|
((table_name(r), r) for r in results_),
|
||||||
','.join(str(getattr(r, k)
|
((table_name(r), None)
|
||||||
if getattr(r, k) is not None
|
for r in diff_results_ or []
|
||||||
else '')
|
if table_name(r) not in table_))
|
||||||
for k in by): r
|
|
||||||
for r in diff_results_ or []}
|
|
||||||
names_ = [n
|
|
||||||
for n in table_.keys() | diff_table_.keys()
|
|
||||||
if diff_results is None
|
if diff_results is None
|
||||||
or all_
|
or all_
|
||||||
or any(
|
or any(
|
||||||
types[k].ratio(
|
types[k].ratio(
|
||||||
getattr(table_.get(n), k, None),
|
getattr(r, k, None),
|
||||||
getattr(diff_table_.get(n), k, None))
|
getattr(diff_table_.get(n), k, None))
|
||||||
for k in fields)]
|
for k in fields)]
|
||||||
|
|
||||||
# sort again, now with diff info, note that python's sort is stable
|
# sort again, now with diff info, note that python's sort is stable
|
||||||
names_.sort(key=lambda n: (
|
results__.sort(key=lambda nr: (lambda n, r: (
|
||||||
# sort by explicit sort fields
|
# sort by explicit sort fields
|
||||||
next(
|
next(
|
||||||
tuple((Rev
|
tuple((Rev
|
||||||
@@ -816,35 +795,34 @@ def table(Result, results, diff_results=None, *,
|
|||||||
else ()
|
else ()
|
||||||
for k_ in ([k] if k else Result._sort)))
|
for k_ in ([k] if k else Result._sort)))
|
||||||
for k, reverse in (sort or []))
|
for k, reverse in (sort or []))
|
||||||
for r_ in [table_.get(n), diff_table_.get(n)]
|
for r_ in [r, diff_table_.get(n)]
|
||||||
if r_ is not None),
|
if r_ is not None),
|
||||||
# sort by ratio if diffing
|
# sort by ratio if diffing
|
||||||
Rev(tuple(types[k].ratio(
|
Rev(tuple(types[k].ratio(
|
||||||
getattr(table_.get(n), k, None),
|
getattr(r, k, None),
|
||||||
getattr(diff_table_.get(n), k, None))
|
getattr(diff_table_.get(n), k, None))
|
||||||
for k in fields))
|
for k in fields))
|
||||||
if diff_results is not None
|
if diff_results is not None
|
||||||
else (),
|
else (),
|
||||||
# move compare entry to the top, note this can be
|
# move compare entry to the top, note this can be
|
||||||
# overridden by explicitly sorting by fields
|
# overridden by explicitly sorting by fields
|
||||||
(table_.get(n) != compare_r,
|
(r != compare_r,
|
||||||
# sort by ratio if comparing
|
# sort by ratio if comparing
|
||||||
Rev(tuple(
|
Rev(tuple(
|
||||||
types[k].ratio(
|
types[k].ratio(
|
||||||
getattr(table_.get(n), k, None),
|
getattr(r, k, None),
|
||||||
getattr(compare_r, k, None))
|
getattr(compare_r, k, None))
|
||||||
for k in fields)))
|
for k in fields)))
|
||||||
if compare
|
if compare
|
||||||
else (),
|
else (),
|
||||||
# sort by result
|
# sort by result
|
||||||
(table_[n],) if n in table_ else (),
|
(r,) if r is not None else (),
|
||||||
# and finally by name (diffs may be missing results)
|
# and finally by name (diffs may be missing results)
|
||||||
n))
|
n))(*nr))
|
||||||
|
|
||||||
for i, name in enumerate(names_):
|
for i, (n, r) in enumerate(results__):
|
||||||
# find comparable results
|
# find comparable results
|
||||||
r = table_.get(name)
|
diff_r = diff_table_.get(n)
|
||||||
diff_r = diff_table_.get(name)
|
|
||||||
|
|
||||||
# figure out a good label
|
# figure out a good label
|
||||||
if labels is not None:
|
if labels is not None:
|
||||||
@@ -856,26 +834,28 @@ def table(Result, results, diff_results=None, *,
|
|||||||
for r_ in [r, diff_r]
|
for r_ in [r, diff_r]
|
||||||
if r_ is not None)
|
if r_ is not None)
|
||||||
else:
|
else:
|
||||||
label = name
|
label = n
|
||||||
|
|
||||||
# build line
|
# build line
|
||||||
line = table_entry(label, r, diff_r)
|
line = table_entry(label, r, diff_r)
|
||||||
|
|
||||||
# add prefixes
|
# add prefixes
|
||||||
line = [x if isinstance(x, tuple) else (x, []) for x in line]
|
line = [x if isinstance(x, tuple) else (x, []) for x in line]
|
||||||
line[0] = (prefixes[0+(i==len(names_)-1)] + line[0][0], line[0][1])
|
line[0] = (
|
||||||
|
prefixes[0+(i==len(results__)-1)] + line[0][0],
|
||||||
|
line[0][1])
|
||||||
lines.append(line)
|
lines.append(line)
|
||||||
|
|
||||||
# recurse?
|
# recurse?
|
||||||
if name in table_ and depth_ > 1:
|
if r is not None and depth_ > 1:
|
||||||
table_recurse(
|
table_recurse(
|
||||||
getattr(r, Result._children),
|
getattr(r, Result._children),
|
||||||
getattr(diff_r, Result._children, None),
|
getattr(diff_r, Result._children, None),
|
||||||
depth_-1,
|
depth_-1,
|
||||||
(prefixes[2+(i==len(names_)-1)] + "|-> ",
|
(prefixes[2+(i==len(results__)-1)] + "|-> ",
|
||||||
prefixes[2+(i==len(names_)-1)] + "'-> ",
|
prefixes[2+(i==len(results__)-1)] + "'-> ",
|
||||||
prefixes[2+(i==len(names_)-1)] + "| ",
|
prefixes[2+(i==len(results__)-1)] + "| ",
|
||||||
prefixes[2+(i==len(names_)-1)] + " "))
|
prefixes[2+(i==len(results__)-1)] + " "))
|
||||||
|
|
||||||
# build entries
|
# build entries
|
||||||
if not summary:
|
if not summary:
|
||||||
|
|||||||
+38
-58
@@ -998,30 +998,13 @@ def table(Result, results, diff_results=None, *,
|
|||||||
types = Result._types
|
types = Result._types
|
||||||
|
|
||||||
# organize by name
|
# organize by name
|
||||||
table = {
|
def table_name(r):
|
||||||
','.join(str(getattr(r, k)
|
return ','.join(str(getattr(r, k)
|
||||||
if getattr(r, k) is not None
|
if getattr(r, k) is not None
|
||||||
else '')
|
else '')
|
||||||
for k in by): r
|
for k in by)
|
||||||
for r in results}
|
table = {table_name(r): r for r in results}
|
||||||
diff_table = {
|
diff_table = {table_name(r): r for r in diff_results or []}
|
||||||
','.join(str(getattr(r, k)
|
|
||||||
if getattr(r, k) is not None
|
|
||||||
else '')
|
|
||||||
for k in by): r
|
|
||||||
for r in diff_results or []}
|
|
||||||
|
|
||||||
# lost results? note this can happen if a by field references the
|
|
||||||
# same field as a field field, and the field field changes during
|
|
||||||
# folding
|
|
||||||
#
|
|
||||||
# it's not an _error_, but can lead to really confusing results, so
|
|
||||||
# at least warn
|
|
||||||
if (len(table) != len(results)
|
|
||||||
or (diff_results is not None
|
|
||||||
and len(diff_table) != len(diff_results))):
|
|
||||||
print("warning: by fields are unstable",
|
|
||||||
file=sys.stderr)
|
|
||||||
|
|
||||||
# find compare entry if there is one
|
# find compare entry if there is one
|
||||||
if compare:
|
if compare:
|
||||||
@@ -1063,9 +1046,9 @@ def table(Result, results, diff_results=None, *,
|
|||||||
del diff_table
|
del diff_table
|
||||||
|
|
||||||
# entry helper
|
# entry helper
|
||||||
def table_entry(name, r, diff_r=None):
|
def table_entry(n, r, diff_r=None):
|
||||||
# prepend name
|
# prepend name
|
||||||
entry = [name]
|
entry = [n]
|
||||||
|
|
||||||
# normal entry?
|
# normal entry?
|
||||||
if ((compare is None or r == compare_r)
|
if ((compare is None or r == compare_r)
|
||||||
@@ -1140,30 +1123,26 @@ def table(Result, results, diff_results=None, *,
|
|||||||
depth_,
|
depth_,
|
||||||
prefixes=('', '', '', '')):
|
prefixes=('', '', '', '')):
|
||||||
# build the children table at each layer
|
# build the children table at each layer
|
||||||
table_ = {
|
table_ = {table_name(r): r for r in results_}
|
||||||
','.join(str(getattr(r, k)
|
diff_table_ = {table_name(r): r for r in diff_results_ or []}
|
||||||
if getattr(r, k) is not None
|
# this gets a bit tricky, we want to merge both result and diff
|
||||||
else '')
|
# result names, while preserving duplicates in the result list
|
||||||
for k in by): r
|
results__ = [(n, r)
|
||||||
for r in results_}
|
for n, r in it.chain(
|
||||||
diff_table_ = {
|
((table_name(r), r) for r in results_),
|
||||||
','.join(str(getattr(r, k)
|
((table_name(r), None)
|
||||||
if getattr(r, k) is not None
|
for r in diff_results_ or []
|
||||||
else '')
|
if table_name(r) not in table_))
|
||||||
for k in by): r
|
|
||||||
for r in diff_results_ or []}
|
|
||||||
names_ = [n
|
|
||||||
for n in table_.keys() | diff_table_.keys()
|
|
||||||
if diff_results is None
|
if diff_results is None
|
||||||
or all_
|
or all_
|
||||||
or any(
|
or any(
|
||||||
types[k].ratio(
|
types[k].ratio(
|
||||||
getattr(table_.get(n), k, None),
|
getattr(r, k, None),
|
||||||
getattr(diff_table_.get(n), k, None))
|
getattr(diff_table_.get(n), k, None))
|
||||||
for k in fields)]
|
for k in fields)]
|
||||||
|
|
||||||
# sort again, now with diff info, note that python's sort is stable
|
# sort again, now with diff info, note that python's sort is stable
|
||||||
names_.sort(key=lambda n: (
|
results__.sort(key=lambda nr: (lambda n, r: (
|
||||||
# sort by explicit sort fields
|
# sort by explicit sort fields
|
||||||
next(
|
next(
|
||||||
tuple((Rev
|
tuple((Rev
|
||||||
@@ -1174,35 +1153,34 @@ def table(Result, results, diff_results=None, *,
|
|||||||
else ()
|
else ()
|
||||||
for k_ in ([k] if k else Result._sort)))
|
for k_ in ([k] if k else Result._sort)))
|
||||||
for k, reverse in (sort or []))
|
for k, reverse in (sort or []))
|
||||||
for r_ in [table_.get(n), diff_table_.get(n)]
|
for r_ in [r, diff_table_.get(n)]
|
||||||
if r_ is not None),
|
if r_ is not None),
|
||||||
# sort by ratio if diffing
|
# sort by ratio if diffing
|
||||||
Rev(tuple(types[k].ratio(
|
Rev(tuple(types[k].ratio(
|
||||||
getattr(table_.get(n), k, None),
|
getattr(r, k, None),
|
||||||
getattr(diff_table_.get(n), k, None))
|
getattr(diff_table_.get(n), k, None))
|
||||||
for k in fields))
|
for k in fields))
|
||||||
if diff_results is not None
|
if diff_results is not None
|
||||||
else (),
|
else (),
|
||||||
# move compare entry to the top, note this can be
|
# move compare entry to the top, note this can be
|
||||||
# overridden by explicitly sorting by fields
|
# overridden by explicitly sorting by fields
|
||||||
(table_.get(n) != compare_r,
|
(r != compare_r,
|
||||||
# sort by ratio if comparing
|
# sort by ratio if comparing
|
||||||
Rev(tuple(
|
Rev(tuple(
|
||||||
types[k].ratio(
|
types[k].ratio(
|
||||||
getattr(table_.get(n), k, None),
|
getattr(r, k, None),
|
||||||
getattr(compare_r, k, None))
|
getattr(compare_r, k, None))
|
||||||
for k in fields)))
|
for k in fields)))
|
||||||
if compare
|
if compare
|
||||||
else (),
|
else (),
|
||||||
# sort by result
|
# sort by result
|
||||||
(table_[n],) if n in table_ else (),
|
(r,) if r is not None else (),
|
||||||
# and finally by name (diffs may be missing results)
|
# and finally by name (diffs may be missing results)
|
||||||
n))
|
n))(*nr))
|
||||||
|
|
||||||
for i, name in enumerate(names_):
|
for i, (n, r) in enumerate(results__):
|
||||||
# find comparable results
|
# find comparable results
|
||||||
r = table_.get(name)
|
diff_r = diff_table_.get(n)
|
||||||
diff_r = diff_table_.get(name)
|
|
||||||
|
|
||||||
# figure out a good label
|
# figure out a good label
|
||||||
if labels is not None:
|
if labels is not None:
|
||||||
@@ -1214,26 +1192,28 @@ def table(Result, results, diff_results=None, *,
|
|||||||
for r_ in [r, diff_r]
|
for r_ in [r, diff_r]
|
||||||
if r_ is not None)
|
if r_ is not None)
|
||||||
else:
|
else:
|
||||||
label = name
|
label = n
|
||||||
|
|
||||||
# build line
|
# build line
|
||||||
line = table_entry(label, r, diff_r)
|
line = table_entry(label, r, diff_r)
|
||||||
|
|
||||||
# add prefixes
|
# add prefixes
|
||||||
line = [x if isinstance(x, tuple) else (x, []) for x in line]
|
line = [x if isinstance(x, tuple) else (x, []) for x in line]
|
||||||
line[0] = (prefixes[0+(i==len(names_)-1)] + line[0][0], line[0][1])
|
line[0] = (
|
||||||
|
prefixes[0+(i==len(results__)-1)] + line[0][0],
|
||||||
|
line[0][1])
|
||||||
lines.append(line)
|
lines.append(line)
|
||||||
|
|
||||||
# recurse?
|
# recurse?
|
||||||
if name in table_ and depth_ > 1:
|
if r is not None and depth_ > 1:
|
||||||
table_recurse(
|
table_recurse(
|
||||||
getattr(r, Result._children),
|
getattr(r, Result._children),
|
||||||
getattr(diff_r, Result._children, None),
|
getattr(diff_r, Result._children, None),
|
||||||
depth_-1,
|
depth_-1,
|
||||||
(prefixes[2+(i==len(names_)-1)] + "|-> ",
|
(prefixes[2+(i==len(results__)-1)] + "|-> ",
|
||||||
prefixes[2+(i==len(names_)-1)] + "'-> ",
|
prefixes[2+(i==len(results__)-1)] + "'-> ",
|
||||||
prefixes[2+(i==len(names_)-1)] + "| ",
|
prefixes[2+(i==len(results__)-1)] + "| ",
|
||||||
prefixes[2+(i==len(names_)-1)] + " "))
|
prefixes[2+(i==len(results__)-1)] + " "))
|
||||||
|
|
||||||
# build entries
|
# build entries
|
||||||
if not summary:
|
if not summary:
|
||||||
|
|||||||
+38
-58
@@ -972,30 +972,13 @@ def table(Result, results, diff_results=None, *,
|
|||||||
types = Result._types
|
types = Result._types
|
||||||
|
|
||||||
# organize by name
|
# organize by name
|
||||||
table = {
|
def table_name(r):
|
||||||
','.join(str(getattr(r, k)
|
return ','.join(str(getattr(r, k)
|
||||||
if getattr(r, k) is not None
|
if getattr(r, k) is not None
|
||||||
else '')
|
else '')
|
||||||
for k in by): r
|
for k in by)
|
||||||
for r in results}
|
table = {table_name(r): r for r in results}
|
||||||
diff_table = {
|
diff_table = {table_name(r): r for r in diff_results or []}
|
||||||
','.join(str(getattr(r, k)
|
|
||||||
if getattr(r, k) is not None
|
|
||||||
else '')
|
|
||||||
for k in by): r
|
|
||||||
for r in diff_results or []}
|
|
||||||
|
|
||||||
# lost results? note this can happen if a by field references the
|
|
||||||
# same field as a field field, and the field field changes during
|
|
||||||
# folding
|
|
||||||
#
|
|
||||||
# it's not an _error_, but can lead to really confusing results, so
|
|
||||||
# at least warn
|
|
||||||
if (len(table) != len(results)
|
|
||||||
or (diff_results is not None
|
|
||||||
and len(diff_table) != len(diff_results))):
|
|
||||||
print("warning: by fields are unstable",
|
|
||||||
file=sys.stderr)
|
|
||||||
|
|
||||||
# find compare entry if there is one
|
# find compare entry if there is one
|
||||||
if compare:
|
if compare:
|
||||||
@@ -1037,9 +1020,9 @@ def table(Result, results, diff_results=None, *,
|
|||||||
del diff_table
|
del diff_table
|
||||||
|
|
||||||
# entry helper
|
# entry helper
|
||||||
def table_entry(name, r, diff_r=None):
|
def table_entry(n, r, diff_r=None):
|
||||||
# prepend name
|
# prepend name
|
||||||
entry = [name]
|
entry = [n]
|
||||||
|
|
||||||
# normal entry?
|
# normal entry?
|
||||||
if ((compare is None or r == compare_r)
|
if ((compare is None or r == compare_r)
|
||||||
@@ -1114,30 +1097,26 @@ def table(Result, results, diff_results=None, *,
|
|||||||
depth_,
|
depth_,
|
||||||
prefixes=('', '', '', '')):
|
prefixes=('', '', '', '')):
|
||||||
# build the children table at each layer
|
# build the children table at each layer
|
||||||
table_ = {
|
table_ = {table_name(r): r for r in results_}
|
||||||
','.join(str(getattr(r, k)
|
diff_table_ = {table_name(r): r for r in diff_results_ or []}
|
||||||
if getattr(r, k) is not None
|
# this gets a bit tricky, we want to merge both result and diff
|
||||||
else '')
|
# result names, while preserving duplicates in the result list
|
||||||
for k in by): r
|
results__ = [(n, r)
|
||||||
for r in results_}
|
for n, r in it.chain(
|
||||||
diff_table_ = {
|
((table_name(r), r) for r in results_),
|
||||||
','.join(str(getattr(r, k)
|
((table_name(r), None)
|
||||||
if getattr(r, k) is not None
|
for r in diff_results_ or []
|
||||||
else '')
|
if table_name(r) not in table_))
|
||||||
for k in by): r
|
|
||||||
for r in diff_results_ or []}
|
|
||||||
names_ = [n
|
|
||||||
for n in table_.keys() | diff_table_.keys()
|
|
||||||
if diff_results is None
|
if diff_results is None
|
||||||
or all_
|
or all_
|
||||||
or any(
|
or any(
|
||||||
types[k].ratio(
|
types[k].ratio(
|
||||||
getattr(table_.get(n), k, None),
|
getattr(r, k, None),
|
||||||
getattr(diff_table_.get(n), k, None))
|
getattr(diff_table_.get(n), k, None))
|
||||||
for k in fields)]
|
for k in fields)]
|
||||||
|
|
||||||
# sort again, now with diff info, note that python's sort is stable
|
# sort again, now with diff info, note that python's sort is stable
|
||||||
names_.sort(key=lambda n: (
|
results__.sort(key=lambda nr: (lambda n, r: (
|
||||||
# sort by explicit sort fields
|
# sort by explicit sort fields
|
||||||
next(
|
next(
|
||||||
tuple((Rev
|
tuple((Rev
|
||||||
@@ -1148,35 +1127,34 @@ def table(Result, results, diff_results=None, *,
|
|||||||
else ()
|
else ()
|
||||||
for k_ in ([k] if k else Result._sort)))
|
for k_ in ([k] if k else Result._sort)))
|
||||||
for k, reverse in (sort or []))
|
for k, reverse in (sort or []))
|
||||||
for r_ in [table_.get(n), diff_table_.get(n)]
|
for r_ in [r, diff_table_.get(n)]
|
||||||
if r_ is not None),
|
if r_ is not None),
|
||||||
# sort by ratio if diffing
|
# sort by ratio if diffing
|
||||||
Rev(tuple(types[k].ratio(
|
Rev(tuple(types[k].ratio(
|
||||||
getattr(table_.get(n), k, None),
|
getattr(r, k, None),
|
||||||
getattr(diff_table_.get(n), k, None))
|
getattr(diff_table_.get(n), k, None))
|
||||||
for k in fields))
|
for k in fields))
|
||||||
if diff_results is not None
|
if diff_results is not None
|
||||||
else (),
|
else (),
|
||||||
# move compare entry to the top, note this can be
|
# move compare entry to the top, note this can be
|
||||||
# overridden by explicitly sorting by fields
|
# overridden by explicitly sorting by fields
|
||||||
(table_.get(n) != compare_r,
|
(r != compare_r,
|
||||||
# sort by ratio if comparing
|
# sort by ratio if comparing
|
||||||
Rev(tuple(
|
Rev(tuple(
|
||||||
types[k].ratio(
|
types[k].ratio(
|
||||||
getattr(table_.get(n), k, None),
|
getattr(r, k, None),
|
||||||
getattr(compare_r, k, None))
|
getattr(compare_r, k, None))
|
||||||
for k in fields)))
|
for k in fields)))
|
||||||
if compare
|
if compare
|
||||||
else (),
|
else (),
|
||||||
# sort by result
|
# sort by result
|
||||||
(table_[n],) if n in table_ else (),
|
(r,) if r is not None else (),
|
||||||
# and finally by name (diffs may be missing results)
|
# and finally by name (diffs may be missing results)
|
||||||
n))
|
n))(*nr))
|
||||||
|
|
||||||
for i, name in enumerate(names_):
|
for i, (n, r) in enumerate(results__):
|
||||||
# find comparable results
|
# find comparable results
|
||||||
r = table_.get(name)
|
diff_r = diff_table_.get(n)
|
||||||
diff_r = diff_table_.get(name)
|
|
||||||
|
|
||||||
# figure out a good label
|
# figure out a good label
|
||||||
if labels is not None:
|
if labels is not None:
|
||||||
@@ -1188,26 +1166,28 @@ def table(Result, results, diff_results=None, *,
|
|||||||
for r_ in [r, diff_r]
|
for r_ in [r, diff_r]
|
||||||
if r_ is not None)
|
if r_ is not None)
|
||||||
else:
|
else:
|
||||||
label = name
|
label = n
|
||||||
|
|
||||||
# build line
|
# build line
|
||||||
line = table_entry(label, r, diff_r)
|
line = table_entry(label, r, diff_r)
|
||||||
|
|
||||||
# add prefixes
|
# add prefixes
|
||||||
line = [x if isinstance(x, tuple) else (x, []) for x in line]
|
line = [x if isinstance(x, tuple) else (x, []) for x in line]
|
||||||
line[0] = (prefixes[0+(i==len(names_)-1)] + line[0][0], line[0][1])
|
line[0] = (
|
||||||
|
prefixes[0+(i==len(results__)-1)] + line[0][0],
|
||||||
|
line[0][1])
|
||||||
lines.append(line)
|
lines.append(line)
|
||||||
|
|
||||||
# recurse?
|
# recurse?
|
||||||
if name in table_ and depth_ > 1:
|
if r is not None and depth_ > 1:
|
||||||
table_recurse(
|
table_recurse(
|
||||||
getattr(r, Result._children),
|
getattr(r, Result._children),
|
||||||
getattr(diff_r, Result._children, None),
|
getattr(diff_r, Result._children, None),
|
||||||
depth_-1,
|
depth_-1,
|
||||||
(prefixes[2+(i==len(names_)-1)] + "|-> ",
|
(prefixes[2+(i==len(results__)-1)] + "|-> ",
|
||||||
prefixes[2+(i==len(names_)-1)] + "'-> ",
|
prefixes[2+(i==len(results__)-1)] + "'-> ",
|
||||||
prefixes[2+(i==len(names_)-1)] + "| ",
|
prefixes[2+(i==len(results__)-1)] + "| ",
|
||||||
prefixes[2+(i==len(names_)-1)] + " "))
|
prefixes[2+(i==len(results__)-1)] + " "))
|
||||||
|
|
||||||
# build entries
|
# build entries
|
||||||
if not summary:
|
if not summary:
|
||||||
|
|||||||
+38
-58
@@ -640,30 +640,13 @@ def table(Result, results, diff_results=None, *,
|
|||||||
types = Result._types
|
types = Result._types
|
||||||
|
|
||||||
# organize by name
|
# organize by name
|
||||||
table = {
|
def table_name(r):
|
||||||
','.join(str(getattr(r, k)
|
return ','.join(str(getattr(r, k)
|
||||||
if getattr(r, k) is not None
|
if getattr(r, k) is not None
|
||||||
else '')
|
else '')
|
||||||
for k in by): r
|
for k in by)
|
||||||
for r in results}
|
table = {table_name(r): r for r in results}
|
||||||
diff_table = {
|
diff_table = {table_name(r): r for r in diff_results or []}
|
||||||
','.join(str(getattr(r, k)
|
|
||||||
if getattr(r, k) is not None
|
|
||||||
else '')
|
|
||||||
for k in by): r
|
|
||||||
for r in diff_results or []}
|
|
||||||
|
|
||||||
# lost results? note this can happen if a by field references the
|
|
||||||
# same field as a field field, and the field field changes during
|
|
||||||
# folding
|
|
||||||
#
|
|
||||||
# it's not an _error_, but can lead to really confusing results, so
|
|
||||||
# at least warn
|
|
||||||
if (len(table) != len(results)
|
|
||||||
or (diff_results is not None
|
|
||||||
and len(diff_table) != len(diff_results))):
|
|
||||||
print("warning: by fields are unstable",
|
|
||||||
file=sys.stderr)
|
|
||||||
|
|
||||||
# find compare entry if there is one
|
# find compare entry if there is one
|
||||||
if compare:
|
if compare:
|
||||||
@@ -705,9 +688,9 @@ def table(Result, results, diff_results=None, *,
|
|||||||
del diff_table
|
del diff_table
|
||||||
|
|
||||||
# entry helper
|
# entry helper
|
||||||
def table_entry(name, r, diff_r=None):
|
def table_entry(n, r, diff_r=None):
|
||||||
# prepend name
|
# prepend name
|
||||||
entry = [name]
|
entry = [n]
|
||||||
|
|
||||||
# normal entry?
|
# normal entry?
|
||||||
if ((compare is None or r == compare_r)
|
if ((compare is None or r == compare_r)
|
||||||
@@ -782,30 +765,26 @@ def table(Result, results, diff_results=None, *,
|
|||||||
depth_,
|
depth_,
|
||||||
prefixes=('', '', '', '')):
|
prefixes=('', '', '', '')):
|
||||||
# build the children table at each layer
|
# build the children table at each layer
|
||||||
table_ = {
|
table_ = {table_name(r): r for r in results_}
|
||||||
','.join(str(getattr(r, k)
|
diff_table_ = {table_name(r): r for r in diff_results_ or []}
|
||||||
if getattr(r, k) is not None
|
# this gets a bit tricky, we want to merge both result and diff
|
||||||
else '')
|
# result names, while preserving duplicates in the result list
|
||||||
for k in by): r
|
results__ = [(n, r)
|
||||||
for r in results_}
|
for n, r in it.chain(
|
||||||
diff_table_ = {
|
((table_name(r), r) for r in results_),
|
||||||
','.join(str(getattr(r, k)
|
((table_name(r), None)
|
||||||
if getattr(r, k) is not None
|
for r in diff_results_ or []
|
||||||
else '')
|
if table_name(r) not in table_))
|
||||||
for k in by): r
|
|
||||||
for r in diff_results_ or []}
|
|
||||||
names_ = [n
|
|
||||||
for n in table_.keys() | diff_table_.keys()
|
|
||||||
if diff_results is None
|
if diff_results is None
|
||||||
or all_
|
or all_
|
||||||
or any(
|
or any(
|
||||||
types[k].ratio(
|
types[k].ratio(
|
||||||
getattr(table_.get(n), k, None),
|
getattr(r, k, None),
|
||||||
getattr(diff_table_.get(n), k, None))
|
getattr(diff_table_.get(n), k, None))
|
||||||
for k in fields)]
|
for k in fields)]
|
||||||
|
|
||||||
# sort again, now with diff info, note that python's sort is stable
|
# sort again, now with diff info, note that python's sort is stable
|
||||||
names_.sort(key=lambda n: (
|
results__.sort(key=lambda nr: (lambda n, r: (
|
||||||
# sort by explicit sort fields
|
# sort by explicit sort fields
|
||||||
next(
|
next(
|
||||||
tuple((Rev
|
tuple((Rev
|
||||||
@@ -816,35 +795,34 @@ def table(Result, results, diff_results=None, *,
|
|||||||
else ()
|
else ()
|
||||||
for k_ in ([k] if k else Result._sort)))
|
for k_ in ([k] if k else Result._sort)))
|
||||||
for k, reverse in (sort or []))
|
for k, reverse in (sort or []))
|
||||||
for r_ in [table_.get(n), diff_table_.get(n)]
|
for r_ in [r, diff_table_.get(n)]
|
||||||
if r_ is not None),
|
if r_ is not None),
|
||||||
# sort by ratio if diffing
|
# sort by ratio if diffing
|
||||||
Rev(tuple(types[k].ratio(
|
Rev(tuple(types[k].ratio(
|
||||||
getattr(table_.get(n), k, None),
|
getattr(r, k, None),
|
||||||
getattr(diff_table_.get(n), k, None))
|
getattr(diff_table_.get(n), k, None))
|
||||||
for k in fields))
|
for k in fields))
|
||||||
if diff_results is not None
|
if diff_results is not None
|
||||||
else (),
|
else (),
|
||||||
# move compare entry to the top, note this can be
|
# move compare entry to the top, note this can be
|
||||||
# overridden by explicitly sorting by fields
|
# overridden by explicitly sorting by fields
|
||||||
(table_.get(n) != compare_r,
|
(r != compare_r,
|
||||||
# sort by ratio if comparing
|
# sort by ratio if comparing
|
||||||
Rev(tuple(
|
Rev(tuple(
|
||||||
types[k].ratio(
|
types[k].ratio(
|
||||||
getattr(table_.get(n), k, None),
|
getattr(r, k, None),
|
||||||
getattr(compare_r, k, None))
|
getattr(compare_r, k, None))
|
||||||
for k in fields)))
|
for k in fields)))
|
||||||
if compare
|
if compare
|
||||||
else (),
|
else (),
|
||||||
# sort by result
|
# sort by result
|
||||||
(table_[n],) if n in table_ else (),
|
(r,) if r is not None else (),
|
||||||
# and finally by name (diffs may be missing results)
|
# and finally by name (diffs may be missing results)
|
||||||
n))
|
n))(*nr))
|
||||||
|
|
||||||
for i, name in enumerate(names_):
|
for i, (n, r) in enumerate(results__):
|
||||||
# find comparable results
|
# find comparable results
|
||||||
r = table_.get(name)
|
diff_r = diff_table_.get(n)
|
||||||
diff_r = diff_table_.get(name)
|
|
||||||
|
|
||||||
# figure out a good label
|
# figure out a good label
|
||||||
if labels is not None:
|
if labels is not None:
|
||||||
@@ -856,26 +834,28 @@ def table(Result, results, diff_results=None, *,
|
|||||||
for r_ in [r, diff_r]
|
for r_ in [r, diff_r]
|
||||||
if r_ is not None)
|
if r_ is not None)
|
||||||
else:
|
else:
|
||||||
label = name
|
label = n
|
||||||
|
|
||||||
# build line
|
# build line
|
||||||
line = table_entry(label, r, diff_r)
|
line = table_entry(label, r, diff_r)
|
||||||
|
|
||||||
# add prefixes
|
# add prefixes
|
||||||
line = [x if isinstance(x, tuple) else (x, []) for x in line]
|
line = [x if isinstance(x, tuple) else (x, []) for x in line]
|
||||||
line[0] = (prefixes[0+(i==len(names_)-1)] + line[0][0], line[0][1])
|
line[0] = (
|
||||||
|
prefixes[0+(i==len(results__)-1)] + line[0][0],
|
||||||
|
line[0][1])
|
||||||
lines.append(line)
|
lines.append(line)
|
||||||
|
|
||||||
# recurse?
|
# recurse?
|
||||||
if name in table_ and depth_ > 1:
|
if r is not None and depth_ > 1:
|
||||||
table_recurse(
|
table_recurse(
|
||||||
getattr(r, Result._children),
|
getattr(r, Result._children),
|
||||||
getattr(diff_r, Result._children, None),
|
getattr(diff_r, Result._children, None),
|
||||||
depth_-1,
|
depth_-1,
|
||||||
(prefixes[2+(i==len(names_)-1)] + "|-> ",
|
(prefixes[2+(i==len(results__)-1)] + "|-> ",
|
||||||
prefixes[2+(i==len(names_)-1)] + "'-> ",
|
prefixes[2+(i==len(results__)-1)] + "'-> ",
|
||||||
prefixes[2+(i==len(names_)-1)] + "| ",
|
prefixes[2+(i==len(results__)-1)] + "| ",
|
||||||
prefixes[2+(i==len(names_)-1)] + " "))
|
prefixes[2+(i==len(results__)-1)] + " "))
|
||||||
|
|
||||||
# build entries
|
# build entries
|
||||||
if not summary:
|
if not summary:
|
||||||
|
|||||||
+38
-58
@@ -788,30 +788,13 @@ def table(Result, results, diff_results=None, *,
|
|||||||
types = Result._types
|
types = Result._types
|
||||||
|
|
||||||
# organize by name
|
# organize by name
|
||||||
table = {
|
def table_name(r):
|
||||||
','.join(str(getattr(r, k)
|
return ','.join(str(getattr(r, k)
|
||||||
if getattr(r, k) is not None
|
if getattr(r, k) is not None
|
||||||
else '')
|
else '')
|
||||||
for k in by): r
|
for k in by)
|
||||||
for r in results}
|
table = {table_name(r): r for r in results}
|
||||||
diff_table = {
|
diff_table = {table_name(r): r for r in diff_results or []}
|
||||||
','.join(str(getattr(r, k)
|
|
||||||
if getattr(r, k) is not None
|
|
||||||
else '')
|
|
||||||
for k in by): r
|
|
||||||
for r in diff_results or []}
|
|
||||||
|
|
||||||
# lost results? note this can happen if a by field references the
|
|
||||||
# same field as a field field, and the field field changes during
|
|
||||||
# folding
|
|
||||||
#
|
|
||||||
# it's not an _error_, but can lead to really confusing results, so
|
|
||||||
# at least warn
|
|
||||||
if (len(table) != len(results)
|
|
||||||
or (diff_results is not None
|
|
||||||
and len(diff_table) != len(diff_results))):
|
|
||||||
print("warning: by fields are unstable",
|
|
||||||
file=sys.stderr)
|
|
||||||
|
|
||||||
# find compare entry if there is one
|
# find compare entry if there is one
|
||||||
if compare:
|
if compare:
|
||||||
@@ -853,9 +836,9 @@ def table(Result, results, diff_results=None, *,
|
|||||||
del diff_table
|
del diff_table
|
||||||
|
|
||||||
# entry helper
|
# entry helper
|
||||||
def table_entry(name, r, diff_r=None):
|
def table_entry(n, r, diff_r=None):
|
||||||
# prepend name
|
# prepend name
|
||||||
entry = [name]
|
entry = [n]
|
||||||
|
|
||||||
# normal entry?
|
# normal entry?
|
||||||
if ((compare is None or r == compare_r)
|
if ((compare is None or r == compare_r)
|
||||||
@@ -930,30 +913,26 @@ def table(Result, results, diff_results=None, *,
|
|||||||
depth_,
|
depth_,
|
||||||
prefixes=('', '', '', '')):
|
prefixes=('', '', '', '')):
|
||||||
# build the children table at each layer
|
# build the children table at each layer
|
||||||
table_ = {
|
table_ = {table_name(r): r for r in results_}
|
||||||
','.join(str(getattr(r, k)
|
diff_table_ = {table_name(r): r for r in diff_results_ or []}
|
||||||
if getattr(r, k) is not None
|
# this gets a bit tricky, we want to merge both result and diff
|
||||||
else '')
|
# result names, while preserving duplicates in the result list
|
||||||
for k in by): r
|
results__ = [(n, r)
|
||||||
for r in results_}
|
for n, r in it.chain(
|
||||||
diff_table_ = {
|
((table_name(r), r) for r in results_),
|
||||||
','.join(str(getattr(r, k)
|
((table_name(r), None)
|
||||||
if getattr(r, k) is not None
|
for r in diff_results_ or []
|
||||||
else '')
|
if table_name(r) not in table_))
|
||||||
for k in by): r
|
|
||||||
for r in diff_results_ or []}
|
|
||||||
names_ = [n
|
|
||||||
for n in table_.keys() | diff_table_.keys()
|
|
||||||
if diff_results is None
|
if diff_results is None
|
||||||
or all_
|
or all_
|
||||||
or any(
|
or any(
|
||||||
types[k].ratio(
|
types[k].ratio(
|
||||||
getattr(table_.get(n), k, None),
|
getattr(r, k, None),
|
||||||
getattr(diff_table_.get(n), k, None))
|
getattr(diff_table_.get(n), k, None))
|
||||||
for k in fields)]
|
for k in fields)]
|
||||||
|
|
||||||
# sort again, now with diff info, note that python's sort is stable
|
# sort again, now with diff info, note that python's sort is stable
|
||||||
names_.sort(key=lambda n: (
|
results__.sort(key=lambda nr: (lambda n, r: (
|
||||||
# sort by explicit sort fields
|
# sort by explicit sort fields
|
||||||
next(
|
next(
|
||||||
tuple((Rev
|
tuple((Rev
|
||||||
@@ -964,35 +943,34 @@ def table(Result, results, diff_results=None, *,
|
|||||||
else ()
|
else ()
|
||||||
for k_ in ([k] if k else Result._sort)))
|
for k_ in ([k] if k else Result._sort)))
|
||||||
for k, reverse in (sort or []))
|
for k, reverse in (sort or []))
|
||||||
for r_ in [table_.get(n), diff_table_.get(n)]
|
for r_ in [r, diff_table_.get(n)]
|
||||||
if r_ is not None),
|
if r_ is not None),
|
||||||
# sort by ratio if diffing
|
# sort by ratio if diffing
|
||||||
Rev(tuple(types[k].ratio(
|
Rev(tuple(types[k].ratio(
|
||||||
getattr(table_.get(n), k, None),
|
getattr(r, k, None),
|
||||||
getattr(diff_table_.get(n), k, None))
|
getattr(diff_table_.get(n), k, None))
|
||||||
for k in fields))
|
for k in fields))
|
||||||
if diff_results is not None
|
if diff_results is not None
|
||||||
else (),
|
else (),
|
||||||
# move compare entry to the top, note this can be
|
# move compare entry to the top, note this can be
|
||||||
# overridden by explicitly sorting by fields
|
# overridden by explicitly sorting by fields
|
||||||
(table_.get(n) != compare_r,
|
(r != compare_r,
|
||||||
# sort by ratio if comparing
|
# sort by ratio if comparing
|
||||||
Rev(tuple(
|
Rev(tuple(
|
||||||
types[k].ratio(
|
types[k].ratio(
|
||||||
getattr(table_.get(n), k, None),
|
getattr(r, k, None),
|
||||||
getattr(compare_r, k, None))
|
getattr(compare_r, k, None))
|
||||||
for k in fields)))
|
for k in fields)))
|
||||||
if compare
|
if compare
|
||||||
else (),
|
else (),
|
||||||
# sort by result
|
# sort by result
|
||||||
(table_[n],) if n in table_ else (),
|
(r,) if r is not None else (),
|
||||||
# and finally by name (diffs may be missing results)
|
# and finally by name (diffs may be missing results)
|
||||||
n))
|
n))(*nr))
|
||||||
|
|
||||||
for i, name in enumerate(names_):
|
for i, (n, r) in enumerate(results__):
|
||||||
# find comparable results
|
# find comparable results
|
||||||
r = table_.get(name)
|
diff_r = diff_table_.get(n)
|
||||||
diff_r = diff_table_.get(name)
|
|
||||||
|
|
||||||
# figure out a good label
|
# figure out a good label
|
||||||
if labels is not None:
|
if labels is not None:
|
||||||
@@ -1004,26 +982,28 @@ def table(Result, results, diff_results=None, *,
|
|||||||
for r_ in [r, diff_r]
|
for r_ in [r, diff_r]
|
||||||
if r_ is not None)
|
if r_ is not None)
|
||||||
else:
|
else:
|
||||||
label = name
|
label = n
|
||||||
|
|
||||||
# build line
|
# build line
|
||||||
line = table_entry(label, r, diff_r)
|
line = table_entry(label, r, diff_r)
|
||||||
|
|
||||||
# add prefixes
|
# add prefixes
|
||||||
line = [x if isinstance(x, tuple) else (x, []) for x in line]
|
line = [x if isinstance(x, tuple) else (x, []) for x in line]
|
||||||
line[0] = (prefixes[0+(i==len(names_)-1)] + line[0][0], line[0][1])
|
line[0] = (
|
||||||
|
prefixes[0+(i==len(results__)-1)] + line[0][0],
|
||||||
|
line[0][1])
|
||||||
lines.append(line)
|
lines.append(line)
|
||||||
|
|
||||||
# recurse?
|
# recurse?
|
||||||
if name in table_ and depth_ > 1:
|
if r is not None and depth_ > 1:
|
||||||
table_recurse(
|
table_recurse(
|
||||||
getattr(r, Result._children),
|
getattr(r, Result._children),
|
||||||
getattr(diff_r, Result._children, None),
|
getattr(diff_r, Result._children, None),
|
||||||
depth_-1,
|
depth_-1,
|
||||||
(prefixes[2+(i==len(names_)-1)] + "|-> ",
|
(prefixes[2+(i==len(results__)-1)] + "|-> ",
|
||||||
prefixes[2+(i==len(names_)-1)] + "'-> ",
|
prefixes[2+(i==len(results__)-1)] + "'-> ",
|
||||||
prefixes[2+(i==len(names_)-1)] + "| ",
|
prefixes[2+(i==len(results__)-1)] + "| ",
|
||||||
prefixes[2+(i==len(names_)-1)] + " "))
|
prefixes[2+(i==len(results__)-1)] + " "))
|
||||||
|
|
||||||
# build entries
|
# build entries
|
||||||
if not summary:
|
if not summary:
|
||||||
|
|||||||
Reference in New Issue
Block a user