diff --git a/src/con_duct/suite/ls.py b/src/con_duct/suite/ls.py index fba7cdd..9d6316c 100644 --- a/src/con_duct/suite/ls.py +++ b/src/con_duct/suite/ls.py @@ -7,12 +7,10 @@ import yaml from con_duct.__main__ import DUCT_OUTPUT_PREFIX, SummaryFormatter -LS_SUMMARY_FORMAT = { - "prefix": "Prefix: {value}", - "command": "\tCommand: {value}", - "exit_code": "\tExit Code {value!E}", - "wall_clock_time": "\tWall Clock Time: {value:.3f} sec", - "peak_rss": "\tMemory Peak Usage (RSS): {value!S}", +VALUE_TRANSFORMATION_MAP = { + "exit_code": "{value!E}", + "wall_clock_time": "{value:.3f} sec", + "peak_rss": "{value!S}", } @@ -24,6 +22,18 @@ def load_duct_runs(info_files: List[str]) -> List[dict]: return loaded +def process_run_data( + run_data_list: List[str], fields: List[str], formatter +) -> List[OrderedDict]: + output_rows = [] + for row in run_data_list: + flattened = _flatten_dict(row) + restricted = _restrict_row(fields, flattened) + formatted = _format_row(restricted, formatter) + output_rows.append(formatted) + return output_rows + + def _flatten_dict(d, parent_key="", sep="."): """Flatten a nested dictionary, creating keys as dot-separated paths.""" items = [] @@ -45,21 +55,20 @@ def _restrict_row(field_list, row): return restricted +def _format_row(row, formatter): + transformed = OrderedDict() + for col, value in row.items(): + if transformation := VALUE_TRANSFORMATION_MAP.get(col): + value = formatter.format(transformation, value=value) + transformed[col] = value + return transformed + + def pyout_ls(run_data_list): # Generate Tabular table to output table = pyout.Tabular( style=dict( header_=dict(bold=True, transform=str.upper), - # Default styling could be provided from some collection of styling files - default_=dict( - color=dict( - lookup={ - "Trix": "green", - "110": "red", - "100": "green", # since no grey for now - } - ) - ), ), ) for row in run_data_list: @@ -71,17 +80,16 @@ def pyout_ls(run_data_list): def ls(args: argparse.Namespace) -> int: pattern = f"{DUCT_OUTPUT_PREFIX[:DUCT_OUTPUT_PREFIX.index('{')]}*_info.json" info_files = glob.glob(pattern) - run_data_list = load_duct_runs(info_files) - output_rows = [] - for row in run_data_list: - flattened = _flatten_dict(row) - output_rows.append(_restrict_row(args.fields, flattened)) + run_data_raw = load_duct_runs(info_files) + formatter = SummaryFormatter(enable_colors=args.colors) + output_rows = process_run_data(run_data_raw, args.fields, formatter) if args.format == "summaries": - formatter = SummaryFormatter() # TODO enable_colors=self.colors) for row in output_rows: for col, value in row.items(): - print(formatter.format(LS_SUMMARY_FORMAT[col], value=value)) + if not col == "prefix": + col = f"\t{col}" + print(f"{col.replace('_', ' ').title()}: {value}") elif args.format == "pyout": pyout_ls(output_rows) elif args.format == "json": diff --git a/src/con_duct/suite/main.py b/src/con_duct/suite/main.py index 0622113..830bb17 100644 --- a/src/con_duct/suite/main.py +++ b/src/con_duct/suite/main.py @@ -1,4 +1,5 @@ import argparse +import os import sys from typing import List, Optional from con_duct.suite.ls import ls @@ -69,6 +70,12 @@ def main(argv: Optional[List[str]] = None) -> None: "execution_summary.peak_rss", ], ) + parser_ls.add_argument( + "--colors", + action="store_true", + default=os.getenv("DUCT_COLORS", False), + help="Use colors in duct output.", + ) parser_ls.set_defaults(func=ls) args = parser.parse_args(argv)