diff --git a/lib/pavilion/cmd_utils.py b/lib/pavilion/cmd_utils.py index 7376446f2..0647b7b08 100644 --- a/lib/pavilion/cmd_utils.py +++ b/lib/pavilion/cmd_utils.py @@ -140,23 +140,40 @@ def arg_filtered_tests(pav_cfg: "PavConfig", args: argparse.Namespace, args.tests = ids - if 'all' in args.tests: - for arg, default in filters.TEST_FILTER_DEFAULTS.items(): - if hasattr(args, arg) and default != getattr(args, arg): - break + has_filter_defaults = False + + for arg, default in filters.TEST_FILTER_DEFAULTS.items(): + if hasattr(args, arg) and default != getattr(args, arg): + has_filter_defaults = True + break + + # "all" takes priority over everything else + if "all" in args.tests: + args.tests = ["all"] + elif "last" in args.tests: + args.tests = ["last"] + elif len(args.tests) == 0: + if has_filter_defaults or args.filter is not None: + args.tests = ["all"] else: - output.fprint(verbose, "Using default search filters: The current system, user, and " - "created less than 1 day ago.", color=output.CYAN) - args.filter = make_filter_query() + args.tests = ["last"] + + if "all" in args.tests and args.filter is not None and not has_filter_defaults: + output.fprint(verbose, "Using default search filters: The current system, user, and " + "created less than 1 day ago.", color=output.CYAN) + args.filter = make_filter_query() if args.filter is None: filter_func = filters.const(True) # Always return True else: - filter_func = filters.parse_query(args.filter) + try: + filter_func = filters.parse_query(args.filter) + except filters.FilterParseError: + raise PavilionError(f"Invalid syntax in filter query: {args.filter}") order_func, order_asc = filters.get_sort_opts(sort_by, "TEST") - if 'all' in args.tests: + if "all" in args.tests: tests = dir_db.SelectItems([], []) working_dirs = set(map(lambda cfg: cfg['working_dir'], pav_cfg.configs.values())) @@ -177,9 +194,6 @@ def arg_filtered_tests(pav_cfg: "PavConfig", args: argparse.Namespace, return tests - if not args.tests: - args.tests.append('last') - test_paths = test_list_to_paths(pav_cfg, args.tests, verbose) return dir_db.select_from( @@ -194,13 +208,15 @@ def arg_filtered_tests(pav_cfg: "PavConfig", args: argparse.Namespace, def make_filter_query() -> str: - template = 'user={} and created<{}' + """Construct the default filter query, which targets tests created + by the current user on the current system more recently than 1 day ago.""" + + template = 'user={} and created>1 day' user = utils.get_login() - time = (dt.datetime.now() - dt.timedelta(days=1)).isoformat() sysname = sys_vars.get_vars(defer=True).get('sys_name') - fargs = [user, time] + fargs = [user] if sysname is not None and len(sysname) > 0: template += ' and sys_name={}' @@ -250,7 +266,10 @@ def arg_filtered_series(pav_cfg: config.PavConfig, args: argparse.Namespace, if args.filter is None: filter_func = filters.const(True) # Always return True else: - filter_func = filters.parse_query(args.filter) + try: + filter_func = filters.parse_query(args.filter) + except filters.FilterParseError: + raise PavilionError(f"Invalid syntax in filter query: {args.filter}") found_series = dir_db.select( pav_cfg=pav_cfg, diff --git a/lib/pavilion/commands/status.py b/lib/pavilion/commands/status.py index 035a2d2a1..0f302eaaa 100644 --- a/lib/pavilion/commands/status.py +++ b/lib/pavilion/commands/status.py @@ -7,6 +7,7 @@ from pavilion import filters from pavilion import output from pavilion import status_utils +from pavilion.errors import PavilionError from .base_classes import Command @@ -53,7 +54,7 @@ def run(self, pav_cfg, args): series.""" try: test_paths = cmd_utils.arg_filtered_tests(pav_cfg, args, verbose=self.errfile).paths - except ValueError as err: + except (ValueError, PavilionError) as err: output.fprint(self.errfile, err, color=output.RED) return errno.EINVAL diff --git a/lib/pavilion/filters/filters.lark b/lib/pavilion/filters/filters.lark index dea78dedd..dc37c272c 100644 --- a/lib/pavilion/filters/filters.lark +++ b/lib/pavilion/filters/filters.lark @@ -30,9 +30,9 @@ keyword: NAME | duration // Lark's INTs are restricted to non-negative values -duration: INT [WS] unit ["s"] +duration: INT unit ["s"] -unit: SECOND +?unit: SECOND | MINUTE | HOUR | DAY diff --git a/lib/pavilion/test_run/test_attrs.py b/lib/pavilion/test_run/test_attrs.py index 30d3ca33d..79af9bfc7 100644 --- a/lib/pavilion/test_run/test_attrs.py +++ b/lib/pavilion/test_run/test_attrs.py @@ -47,6 +47,7 @@ class TestAttributes(Mapping): """ serializers = { + "status": lambda s: s.path.as_posix(), 'suite_path': lambda p: p.as_posix(), } @@ -54,6 +55,7 @@ class TestAttributes(Mapping): 'created': utils.deserialize_datetime, 'finished': utils.deserialize_datetime, 'started': utils.deserialize_datetime, + "status": lambda s: TestStatusFile(Path(s)), 'suite_path': lambda p: Path(p) if p is not None else None, } @@ -383,6 +385,9 @@ def _get_status_file(self) -> Optional[TestStatusFile]: started = basic_attr( name='started', doc="The start time for this test run.") + status = basic_attr( + name='status', + doc="The status file associated with the test") suite_path = basic_attr( name='suite_path', doc="Path to the suite_file that defined this test run."