|
9 | 9 | import inspect |
10 | 10 | import logging |
11 | 11 | import os |
| 12 | +import re |
12 | 13 | import time |
13 | 14 | import traceback |
14 | 15 | import uuid |
@@ -375,12 +376,13 @@ def delete(self, force_delete: bool = False) -> DSCJob: |
375 | 376 | """ |
376 | 377 | runs = self.run_list() |
377 | 378 | for run in runs: |
378 | | - if run.lifecycle_state in [ |
379 | | - DataScienceJobRun.LIFECYCLE_STATE_ACCEPTED, |
380 | | - DataScienceJobRun.LIFECYCLE_STATE_IN_PROGRESS, |
381 | | - DataScienceJobRun.LIFECYCLE_STATE_NEEDS_ATTENTION, |
382 | | - ]: |
383 | | - run.cancel(wait_for_completion=True) |
| 379 | + if force_delete: |
| 380 | + if run.lifecycle_state in [ |
| 381 | + DataScienceJobRun.LIFECYCLE_STATE_ACCEPTED, |
| 382 | + DataScienceJobRun.LIFECYCLE_STATE_IN_PROGRESS, |
| 383 | + DataScienceJobRun.LIFECYCLE_STATE_NEEDS_ATTENTION, |
| 384 | + ]: |
| 385 | + run.cancel(wait_for_completion=True) |
384 | 386 | run.delete() |
385 | 387 | self.client.delete_job(self.id) |
386 | 388 | return self |
@@ -582,6 +584,25 @@ def logging(self) -> OCILog: |
582 | 584 | id=self.log_id, log_group_id=self.log_details.log_group_id, **auth |
583 | 585 | ) |
584 | 586 |
|
| 587 | + @property |
| 588 | + def exit_code(self): |
| 589 | + """The exit code of the job run from the lifecycle details. |
| 590 | + Note that, |
| 591 | + None will be returned if the job run is not finished or failed without exit code. |
| 592 | + 0 will be returned if job run succeeded. |
| 593 | + """ |
| 594 | + if self.lifecycle_state == self.LIFECYCLE_STATE_SUCCEEDED: |
| 595 | + return 0 |
| 596 | + if not self.lifecycle_details: |
| 597 | + return None |
| 598 | + match = re.search(r"exit code (\d+)", self.lifecycle_details) |
| 599 | + if not match: |
| 600 | + return None |
| 601 | + try: |
| 602 | + return int(match.group(1)) |
| 603 | + except Exception: |
| 604 | + return None |
| 605 | + |
585 | 606 | @staticmethod |
586 | 607 | def _format_log(message: str, date_time: datetime.datetime) -> dict: |
587 | 608 | """Formats a message as log record with datetime. |
@@ -655,6 +676,22 @@ def _check_and_print_status(self, prev_status) -> str: |
655 | 676 | print(f"{timestamp} - {status}") |
656 | 677 | return status |
657 | 678 |
|
| 679 | + def wait(self, interval: float = SLEEP_INTERVAL): |
| 680 | + """Waits for the job run until if finishes. |
| 681 | +
|
| 682 | + Parameters |
| 683 | + ---------- |
| 684 | + interval : float |
| 685 | + Time interval in seconds between each request to update the logs. |
| 686 | + Defaults to 3 (seconds). |
| 687 | +
|
| 688 | + """ |
| 689 | + self.sync() |
| 690 | + while self.status not in self.TERMINAL_STATES: |
| 691 | + time.sleep(interval) |
| 692 | + self.sync() |
| 693 | + return self |
| 694 | + |
658 | 695 | def watch( |
659 | 696 | self, |
660 | 697 | interval: float = SLEEP_INTERVAL, |
@@ -830,6 +867,12 @@ def download(self, to_dir): |
830 | 867 | self.job.download(to_dir) |
831 | 868 | return self |
832 | 869 |
|
| 870 | + def delete(self, force_delete: bool = False): |
| 871 | + if force_delete: |
| 872 | + self.cancel(wait_for_completion=True) |
| 873 | + super().delete() |
| 874 | + return |
| 875 | + |
833 | 876 |
|
834 | 877 | # This is for backward compatibility |
835 | 878 | DSCJobRun = DataScienceJobRun |
|
0 commit comments