diff --git a/CIME/SystemTests/system_tests_common.py b/CIME/SystemTests/system_tests_common.py index ea757d1220c..e977e6f08e9 100644 --- a/CIME/SystemTests/system_tests_common.py +++ b/CIME/SystemTests/system_tests_common.py @@ -154,6 +154,7 @@ def build( ninja=False, dry_run=False, separate_builds=False, + skip_submit=False, ): """ Do NOT override this method, this method is the framework that @@ -164,6 +165,9 @@ def build( self._ninja = ninja self._dry_run = dry_run self._user_separate_builds = separate_builds + + was_run_pend = self._test_status.current_is(RUN_PHASE, TEST_PEND_STATUS) + for phase_name, phase_bool in [ (SHAREDLIB_BUILD_PHASE, not model_only), (MODEL_BUILD_PHASE, not sharedlib_only), @@ -202,6 +206,15 @@ def build( comments=("time={:d}".format(int(time_taken))), ) + # Building model while job is queued and awaiting run + if ( + skip_submit + and was_run_pend + and self._test_status.current_is(SUBMIT_PHASE, TEST_PEND_STATUS) + ): + with self._test_status: + self._test_status.set_status(SUBMIT_PHASE, TEST_PASS_STATUS) + return success def build_phase(self, sharedlib_only=False, model_only=False): diff --git a/CIME/Tools/case.build b/CIME/Tools/case.build index c8e4d54c467..4edf177198e 100755 --- a/CIME/Tools/case.build +++ b/CIME/Tools/case.build @@ -80,6 +80,14 @@ def parse_command_line(args, description): help="Build each component one at a time, separately, with output going to separate logs", ) + parser.add_argument( + "--skip-submit", + action="store_true", + help="Sets the current test phase to RUN, skipping the SUBMIT phase. This " + "may be useful if rebuilding the model while this test is in the batch queue. " + "ONLY USE IF A TEST CASE, OTHERWISE IGNORED.", + ) + parser.add_argument( "--dry-run", action="store_true", @@ -173,6 +181,7 @@ def parse_command_line(args, description): args.separate_builds, args.ninja, args.dry_run, + args.skip_submit, ) @@ -191,6 +200,7 @@ def _main_func(description): separate_builds, ninja, dry_run, + skip_submit, ) = parse_command_line(sys.argv, description) success = True @@ -234,6 +244,7 @@ def _main_func(description): ninja=ninja, dry_run=dry_run, separate_builds=separate_builds, + skip_submit=skip_submit, ) else: diff --git a/CIME/test_status.py b/CIME/test_status.py index 20d2cef93a9..90714631eb8 100644 --- a/CIME/test_status.py +++ b/CIME/test_status.py @@ -274,6 +274,17 @@ def get_status(self, phase): def get_comment(self, phase): return self._phase_statuses[phase][1] if phase in self._phase_statuses else None + def current_is(self, phase, status): + try: + latest = self.get_latest_phase() + except KeyError: + return False + + return latest == phase and self.get_status(phase) == status + + def get_latest_phase(self): + return list(self._phase_statuses.keys())[-1] + def phase_statuses_dump( self, prefix="", skip_passes=False, skip_phase_list=None, xfails=None ): diff --git a/CIME/tests/test_unit_test_status.py b/CIME/tests/test_unit_test_status.py index 0b79c8bac6a..9b3036801fc 100755 --- a/CIME/tests/test_unit_test_status.py +++ b/CIME/tests/test_unit_test_status.py @@ -41,6 +41,20 @@ def _set_phase_to_status(self, phase, status): with self._ts: self._ts.set_status(phase, status) + def test_get_latest_phase(self): + assert self._ts.get_latest_phase() == test_status.RUN_PHASE + + def test_current_is(self): + assert self._ts.current_is(test_status.RUN_PHASE, test_status.TEST_PASS_STATUS) + + assert not self._ts.current_is( + test_status.RUN_PHASE, test_status.TEST_PEND_STATUS + ) + + assert not self._ts.current_is( + test_status.SUBMIT_PHASE, test_status.TEST_PASS_STATUS + ) + # ------------------------------------------------------------------------ # Tests of TestStatus.phase_statuses_dump # ------------------------------------------------------------------------