1515
1616from pydantic import BaseModel , ConfigDict
1717
18+ from dvsim .job .status import JobStatus
1819from dvsim .job .time import JobTime
1920from dvsim .logging import log
2021from dvsim .tool .utils import get_sim_tool_plugin
@@ -210,7 +211,7 @@ def _make_odir(self) -> None:
210211
211212 Path (self .job_spec .odir ).mkdir (exist_ok = True , parents = True )
212213
213- def _link_odir (self , status : str ) -> None :
214+ def _link_odir (self , status : JobStatus ) -> None :
214215 """Soft-links the job's directory based on job's status.
215216
216217 The dispatched, passed and failed directories in the scratch area
@@ -220,8 +221,8 @@ def _link_odir(self, status: str) -> None:
220221 mk_symlink (path = self .job_spec .odir , link = dest )
221222
222223 # Delete the symlink from dispatched directory if it exists.
223- if status != "D" :
224- old = Path (self .job_spec .links ["D" ], self .job_spec .qual_name )
224+ if status != JobStatus . DISPATCHED :
225+ old = Path (self .job_spec .links [JobStatus . DISPATCHED ], self .job_spec .qual_name )
225226 rm_path (old )
226227
227228 def _dump_env_vars (self , exports : Mapping [str , str ]) -> None :
@@ -258,7 +259,7 @@ def launch(self) -> None:
258259 self ._do_launch ()
259260
260261 @abstractmethod
261- def poll (self ) -> str | None :
262+ def poll (self ) -> JobStatus | None :
262263 """Poll the launched job for completion.
263264
264265 Invokes _check_status() and _post_finish() when the job completes.
@@ -272,14 +273,14 @@ def poll(self) -> str | None:
272273 def kill (self ) -> None :
273274 """Terminate the job."""
274275
275- def _check_status (self ) -> tuple [str , ErrorMessage | None ]:
276- """Determine the outcome of the job (P/F if it ran to completion).
276+ def _check_status (self ) -> tuple [JobStatus , ErrorMessage | None ]:
277+ """Determine the outcome of the job (Passed/Failed if it ran to completion).
277278
278279 Returns:
279280 (status, err_msg) extracted from the log, where the status is
280- "P" if the it passed, "F" otherwise. This is invoked by poll() just
281- after the job finishes. err_msg is an instance of the named tuple
282- ErrorMessage.
281+ Passed if the job passed, Failed otherwise. This is invoked by
282+ poll() just after the job finishes. err_msg is an instance of the
283+ named tuple ErrorMessage.
283284
284285 """
285286
@@ -307,7 +308,7 @@ def _find_patterns(patterns: Sequence[str], line: str) -> Sequence[str] | None:
307308 return None
308309
309310 if self .job_spec .dry_run :
310- return "P" , None
311+ return JobStatus . PASSED , None
311312
312313 # Only one fail pattern needs to be seen.
313314 chk_failed = bool (self .job_spec .fail_patterns )
@@ -324,7 +325,7 @@ def _find_patterns(patterns: Sequence[str], line: str) -> Sequence[str] | None:
324325 ) as f :
325326 lines = f .readlines ()
326327 except OSError as e :
327- return "F" , ErrorMessage (
328+ return JobStatus . FAILED , ErrorMessage (
328329 line_number = None ,
329330 message = f"Error opening file { self .job_spec .log_path } :\n { e } " ,
330331 context = [],
@@ -368,7 +369,7 @@ def _find_patterns(patterns: Sequence[str], line: str) -> Sequence[str] | None:
368369 # If failed, then nothing else to do. Just return.
369370 # Provide some extra lines for context.
370371 end = cnt + 5
371- return "F" , ErrorMessage (
372+ return JobStatus . FAILED , ErrorMessage (
372373 line_number = cnt + 1 ,
373374 message = line .strip (),
374375 context = lines [cnt :end ],
@@ -384,32 +385,32 @@ def _find_patterns(patterns: Sequence[str], line: str) -> Sequence[str] | None:
384385 # exit code for whatever reason, then show the last 10 lines of the log
385386 # as the failure message, which might help with the debug.
386387 if self .exit_code != 0 :
387- return "F" , ErrorMessage (
388+ return JobStatus . FAILED , ErrorMessage (
388389 line_number = None ,
389390 message = "Job returned non-zero exit code" ,
390391 context = lines [- 10 :],
391392 )
392393 if chk_passed :
393- return "F" , ErrorMessage (
394+ return JobStatus . FAILED , ErrorMessage (
394395 line_number = None ,
395396 message = f"Some pass patterns missing: { pass_patterns } " ,
396397 context = lines [- 10 :],
397398 )
398- return "P" , None
399+ return JobStatus . PASSED , None
399400
400- def _post_finish (self , status : str , err_msg : ErrorMessage ) -> None :
401+ def _post_finish (self , status : JobStatus , err_msg : ErrorMessage ) -> None :
401402 """Do post-completion activities, such as preparing the results.
402403
403404 Must be invoked by poll(), after the job outcome is determined.
404405
405406 Args:
406- status: status of the job, either 'P', 'F' or 'K' .
407+ status: status of the completed job (must be either Passed, Failed or Killed) .
407408 err_msg: an instance of the named tuple ErrorMessage.
408409
409410 """
410- assert status in [ "P" , "F" , "K" ]
411+ assert status . completed
411412 self ._link_odir (status )
412- log .debug ("Item %s has completed execution: %s" , self , status )
413+ log .debug ("Item %s has completed execution: %s" , self , status . shorthand )
413414
414415 try :
415416 # Run the target-specific cleanup tasks regardless of the job's
@@ -419,16 +420,16 @@ def _post_finish(self, status: str, err_msg: ErrorMessage) -> None:
419420 except Exception as e :
420421 # If the job had already failed, then don't do anything. If it's
421422 # cleanup task failed, then mark the job as failed.
422- if status == "P" :
423- status = "F"
423+ if status == JobStatus . PASSED :
424+ status = JobStatus . FAILED
424425 err_msg = ErrorMessage (
425426 line_number = None ,
426427 message = f"{ e } " ,
427428 context = [f"{ e } " ],
428429 )
429430
430431 self .status = status
431- if self .status != "P" :
432+ if self .status != JobStatus . PASSED :
432433 assert err_msg
433434 assert isinstance (err_msg , ErrorMessage )
434435 self .fail_msg = err_msg
0 commit comments