Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make status printing look more like result printing. #715

Merged
merged 4 commits into from
Nov 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 7 additions & 48 deletions lib/pavilion/commands/result.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,8 @@ def run(self, pav_cfg, args):
if not self.update_results(pav_cfg, tests, log_file, save=args.save):
return errno.EINVAL

serieses = ",".join(
set([test.series for test in tests if test.series is not None]))
results = result_utils.get_results(pav_cfg, tests)
flat_results = []
all_passed = True
Expand All @@ -127,13 +129,14 @@ def run(self, pav_cfg, args):
fields = ["default", "common"]
test_fields = [f for f in flat_keys.keys() if f not in fields]
fields = fields + sorted(test_fields)
title_str=f"Available keys for specified tests in {serieses}."

output.draw_table(outfile=self.outfile,
field_info=field_info,
fields=fields,
rows=flatter_keys,
border=True,
title="Available keys for specified tests.")
title=title_str)

elif args.json or args.full:
if not results:
Expand All @@ -156,7 +159,7 @@ def run(self, pav_cfg, args):
pass

else:
flat_sorted_results = sort_results(args, flat_results)
flat_sorted_results = utils.sort_table(args.sort_by, flat_results)

field_info = {
'created': {'transform': output.get_relative_timestamp},
Expand All @@ -165,12 +168,13 @@ def run(self, pav_cfg, args):
'duration': {'transform': output.format_duration},
}

title_str=f"Test Results: {serieses}."
output.draw_table(
outfile=self.outfile,
field_info=field_info,
fields=fields,
rows=flat_sorted_results,
title=f"Test Results"
title=title_str
)

if args.show_log:
Expand Down Expand Up @@ -298,48 +302,3 @@ def update_results(self, pav_cfg: dict, tests: List[TestRun],
.format(results["result"]))

return True


def sort_results(args, results: List[dict]) -> List[dict]:
"""Same basic operation as pavilion.filters.get_sort_opts except
here the sort operation is performed on the results array rather
than stored as a function and called later.

If the sort-by key is present in the test object, the
sort will be performed in dir_db.select or select_from.
Otherwise the default sort will be performed in dir_db and here the
results dict will be sorted according to the key for output.

Results dicts without the key will be skipped with dummy value dval.
Thus the user may sort the results of incomplete series, by result keys specific to
a particular test in a series, or by keys that are not being displayed.
If the key is not in any of the results dicts, it simply returns a copy of
the results dict.

:param args: Command line arguments, for sort_by.
:param results: A list of flattened result dicts.
:returns: The sorted (or copied) list of results dicts.
"""

sort_key = args.sort_by
dval = None

sort_ascending = True
if sort_key.startswith('-'):
sort_ascending = False
sort_key = sort_key[1:]

for rslt in results:
if sort_key in rslt.keys():
if isinstance(rslt[sort_key], str):
dval = " "
else:
dval = float("-inf")
break

if not dval:
return results.copy()

rslts = sorted(results, key=lambda d: d.get(sort_key, dval), reverse=not sort_ascending)

return rslts
3 changes: 2 additions & 1 deletion lib/pavilion/commands/status.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,8 @@ def run(self, pav_cfg, args):
return self.print_summary(statuses)
else:
return status_utils.print_status(statuses, self.outfile, json=args.json,
series=args.series, note=args.note)
series=args.series, note=args.note,
sorter=args.sort_by)

def print_summary(self, statuses):
"""Print_summary takes in a list of test statuses.
Expand Down
13 changes: 11 additions & 2 deletions lib/pavilion/status_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

from pavilion import output
from pavilion import schedulers
from pavilion import utils
from pavilion.errors import TestRunError, TestRunNotFoundError, DeferredError
from pavilion.status_file import STATES
from pavilion.test_run import (TestRun)
Expand Down Expand Up @@ -131,7 +132,8 @@ def get_statuses(pav_cfg, tests: List[TestRun]):
return list(pool.map(get_this_status, tests))


def print_status(statuses: List[dict], outfile, note=False, series=False, json=False):
def print_status(statuses: List[dict], outfile,
note=False, series=False, json=False, sorter=False):
"""Prints the statuses provided in the statuses parameter.

:param statuses: list of dictionary objects containing the test_id,
Expand All @@ -141,6 +143,7 @@ def print_status(statuses: List[dict], outfile, note=False, series=False, json=F
not.
:param note: Print the status note.
:param series: Print the series id.
:param sorter: Sort tests by sorter key.
:param stream outfile: Stream to which the statuses should be printed.
:return: success or failure.
:rtype: int
Expand All @@ -156,6 +159,12 @@ def print_status(statuses: List[dict], outfile, note=False, series=False, json=F
if note:
fields.append('note')

if sorter:
flat_status = [utils.flatten_dictionary(status) for status in statuses]
flat_sorted_statuses = utils.sort_table(sorter, flat_status)
else:
flat_sorted_statuses = statuses

output.draw_table(
outfile=outfile,
field_info={
Expand All @@ -165,7 +174,7 @@ def print_status(statuses: List[dict], outfile, note=False, series=False, json=F
'test_id': {'title': 'Test'},
},
fields=fields,
rows=statuses,
rows=flat_sorted_statuses,
title='Test statuses')

return 0
Expand Down
44 changes: 44 additions & 0 deletions lib/pavilion/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -564,6 +564,50 @@ def auto_type_convert(value):

return value

def sort_table(sort_key, table_rows: List[dict]) -> List[dict]:
"""Same basic operation as pavilion.filters.get_sort_opts except
here the sort operation is performed on the results array rather
than stored as a function and called later.

If the sort-by key is present in the test object, the
sort will be performed in dir_db.select or select_from.
Otherwise the default sort will be performed in dir_db and here the
results dict will be sorted according to the key for output.

Results dicts without the key will be skipped with dummy value dval.
Thus the user may sort the results of incomplete series, by result keys specific to
a particular test in a series, or by keys that are not being displayed.
If the key is not in any of the results dicts, it simply returns a copy of
the results dict.

:param sort_key: Command line sort_by argument.
:param results: A list of flattened result dicts.
:returns: The sorted (or copied) list of results dicts.
"""

dval = None

sort_ascending = True
if sort_key.startswith('-'):
sort_ascending = False
sort_key = sort_key[1:]

for row in table_rows:
if sort_key in row.keys():
if isinstance(row[sort_key], str):
dval = " "
else:
dval = float("-inf")
break

if not dval:
return table_rows.copy()

sorted_rows = sorted(table_rows,
key=lambda d: d.get(sort_key, dval),
reverse=not sort_ascending)

return sorted_rows

class IndentedLog:
"""A logging object for writing indented, easy to follow logs."""
Expand Down
Loading