diff --git a/src/con_duct/suite/ls.py b/src/con_duct/suite/ls.py index bec5745..bfee0f0 100644 --- a/src/con_duct/suite/ls.py +++ b/src/con_duct/suite/ls.py @@ -132,11 +132,16 @@ def pyout_ls(run_data_list): table(row) -def ls(args: argparse.Namespace) -> int: +def glob_info_files(pattern): info_files = [] - for each in args.pattern: + for each in pattern: matches = glob.glob(f"{each}_info.json") info_files.extend(matches) + return info_files + + +def ls(args: argparse.Namespace) -> int: + info_files = glob_info_files(args.pattern) 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) diff --git a/test/test_ls.py b/test/test_ls.py index 4a13e0a..f874ae3 100644 --- a/test/test_ls.py +++ b/test/test_ls.py @@ -1,6 +1,15 @@ import json +import os +import tempfile from unittest.mock import mock_open, patch -from con_duct.suite.ls import _flatten_dict, _restrict_row, load_duct_runs +from con_duct.suite.ls import ( + SummaryFormatter, + _flatten_dict, + _restrict_row, + glob_info_files, + load_duct_runs, + process_run_data, +) def test_load_duct_runs_sanity(): @@ -52,3 +61,91 @@ def test_restrict_row(): assert "prefix" in result assert "exit_code" in result assert "extra" not in result + + +def test_process_run_data(): + run_data = [ + { + "prefix": "/test/path", + "exit_code": 0, + "wall_clock_time": 0.12345678, + } + ] + formatter = SummaryFormatter(enable_colors=False) + result = process_run_data(run_data, ["wall_clock_time"], formatter) + assert isinstance(result, list) + assert result[0]["prefix"] == "/test/path" + assert "exit_code" not in result[0] + assert result[0]["wall_clock_time"] == "0.123 sec" + + +def test_glob_info_files_sanity(): + # Create mock files in the temp directory + with tempfile.TemporaryDirectory() as temp_dir: + filenames = ["file1_info.json", "file2_info.json", "other_file.txt"] + for filename in filenames: + open(os.path.join(temp_dir, filename), "w").close() + + result = glob_info_files([os.path.join(temp_dir, "*")]) + + # Only JSON files with `_info.json` should be returned + assert sorted(result) == sorted( + [ + os.path.join(temp_dir, "file1_info.json"), + os.path.join(temp_dir, "file2_info.json"), + ] + ) + + +def test_glob_info_files_specifics(): + # Create mock files in the temp directory + with tempfile.TemporaryDirectory() as temp_dir: + filenames = ["file1_info.json", "file2_info.json", "file3_info.json"] + for filename in filenames: + open(os.path.join(temp_dir, filename), "w").close() + + to_check = [os.path.join(temp_dir, pattern) for pattern in ["file1", "file2"]] + result = glob_info_files(to_check) + + # No file3 + assert sorted(result) == sorted( + [ + os.path.join(temp_dir, "file1_info.json"), + os.path.join(temp_dir, "file2_info.json"), + ] + ) + + +def test_glob_info_files_pattern(): + # Create mock files in the temp directory + with tempfile.TemporaryDirectory() as temp_dir: + filenames = [ + "file1_info.json", + "file2_info.json", + "file3_info.json", + "notf_info.json", + ] + for filename in filenames: + open(os.path.join(temp_dir, filename), "w").close() + + result = glob_info_files([os.path.join(temp_dir, "f*")]) + + # No file3 + assert sorted(result) == sorted( + [ + os.path.join(temp_dir, "file1_info.json"), + os.path.join(temp_dir, "file2_info.json"), + os.path.join(temp_dir, "file3_info.json"), + ] + ) + + +def test_glob_info_files_none(): + # Create mock files in the temp directory + with tempfile.TemporaryDirectory() as temp_dir: + filenames = ["file1_info.json", "file2_info.json", "file3_info.json"] + for filename in filenames: + open(os.path.join(temp_dir, filename), "w").close() + + result = glob_info_files([os.path.join(temp_dir, "fakefile")]) + assert len(result) == 0