@@ -40,21 +40,21 @@ class DSClient:
4040 Example:
4141 Basic usage with automatic authentication:
4242
43- >>> client = DSClient()
43+ >>> ds = DSClient()
4444 Enter DesignSafe Username: myuser
4545 Enter DesignSafe Password: [hidden]
4646 Authentication successful.
4747
4848 Using explicit credentials:
4949
50- >>> client = DSClient(username="myuser", password="mypass")
50+ >>> ds = DSClient(username="myuser", password="mypass")
5151 Authentication successful.
5252
5353 Using a pre-authenticated Tapis client:
5454
5555 >>> tapis = Tapis(base_url="https://designsafe.tapis.io", ...)
5656 >>> tapis.get_tokens()
57- >>> client = DSClient(tapis_client=tapis)
57+ >>> ds = DSClient(tapis_client=tapis)
5858 """
5959
6060 def __init__ (self , tapis_client : Optional [Tapis ] = None , ** auth_kwargs ):
@@ -196,7 +196,7 @@ def translate_uri_to_path(self, *args, **kwargs) -> str:
196196 str: The corresponding DesignSafe local path (e.g., /home/jupyter/MyData/path).
197197
198198 Example:
199- >>> local_path = client .files.translate_uri_to_path("tapis://designsafe.storage.default/user/data")
199+ >>> local_path = ds .files.translate_uri_to_path("tapis://designsafe.storage.default/user/data")
200200 >>> print(local_path) # "/home/jupyter/MyData/data"
201201 """
202202 return files_module .tapis_uri_to_local_path (* args , ** kwargs )
@@ -453,7 +453,7 @@ def generate_request(
453453 JobSubmissionError: If job request generation fails.
454454
455455 Example:
456- >>> job_request = client .jobs.generate_request(
456+ >>> job_request = ds .jobs.generate_request(
457457 ... app_id="matlab-r2023a",
458458 ... input_dir_uri="tapis://designsafe.storage.default/username/input/",
459459 ... script_filename="run_analysis.m",
@@ -506,8 +506,8 @@ def submit_request(self, job_request: Dict[str, Any]) -> SubmittedJob:
506506 JobSubmissionError: If the Tapis submission fails or encounters an error.
507507
508508 Example:
509- >>> job_request = client .jobs.generate_request(...)
510- >>> submitted_job = client .jobs.submit_request(job_request)
509+ >>> job_request = ds .jobs.generate_request(...)
510+ >>> submitted_job = ds .jobs.submit_request(job_request)
511511 >>> print(f"Job submitted with UUID: {submitted_job.uuid}")
512512 """
513513 return jobs_module .submit_job_request (self ._tapis , job_request )
@@ -523,7 +523,7 @@ def get(self, job_uuid: str) -> SubmittedJob:
523523 SubmittedJob: A SubmittedJob object for monitoring and managing the job.
524524
525525 Example:
526- >>> job = client .jobs.get("12345678-1234-1234-1234-123456789abc")
526+ >>> job = ds .jobs.get("12345678-1234-1234-1234-123456789abc")
527527 >>> status = job.status
528528 """
529529 return SubmittedJob (self ._tapis , job_uuid )
@@ -541,7 +541,7 @@ def get_status(self, job_uuid: str) -> str:
541541 JobMonitorError: If status retrieval fails.
542542
543543 Example:
544- >>> status = client .jobs.get_status("12345678-1234-1234-1234-123456789abc")
544+ >>> status = ds .jobs.get_status("12345678-1234-1234-1234-123456789abc")
545545 >>> print(f"Job status: {status}")
546546 """
547547 return jobs_module .get_job_status (self ._tapis , job_uuid )
@@ -555,7 +555,7 @@ def get_runtime_summary(self, job_uuid: str, verbose: bool = False):
555555 Defaults to False.
556556
557557 Example:
558- >>> client .jobs.get_runtime_summary("12345678-1234-1234-1234-123456789abc")
558+ >>> ds .jobs.get_runtime_summary("12345678-1234-1234-1234-123456789abc")
559559 Runtime Summary
560560 ---------------
561561 QUEUED time: 00:05:30
@@ -572,7 +572,44 @@ def interpret_status(self, final_status: str, job_uuid: Optional[str] = None):
572572 job_uuid (str, optional): The job UUID for context in the message.
573573
574574 Example:
575- >>> client .jobs.interpret_status("FINISHED", "12345678-1234-1234-1234-123456789abc")
575+ >>> ds .jobs.interpret_status("FINISHED", "12345678-1234-1234-1234-123456789abc")
576576 Job 12345678-1234-1234-1234-123456789abc completed successfully.
577577 """
578578 jobs_module .interpret_job_status (final_status , job_uuid )
579+
580+ def list (
581+ self ,
582+ app_id : Optional [str ] = None ,
583+ status : Optional [str ] = None ,
584+ limit : int = 100 ,
585+ verbose : bool = False ,
586+ ):
587+ """List jobs as a pandas DataFrame with optional filtering.
588+
589+ Fetches jobs from Tapis ordered by creation date (newest first)
590+ and returns them as a DataFrame. Filters are applied client-side.
591+
592+ Args:
593+ app_id (str, optional): Filter by application ID.
594+ status (str, optional): Filter by job status (e.g., "FINISHED").
595+ Case-insensitive.
596+ limit (int, optional): Maximum jobs to fetch. Defaults to 100.
597+ verbose (bool, optional): Print job count. Defaults to False.
598+
599+ Returns:
600+ pd.DataFrame: Job metadata with formatted datetime columns.
601+
602+ Raises:
603+ JobMonitorError: If the Tapis API call fails.
604+
605+ Example:
606+ >>> df = ds.jobs.list(app_id="matlab-r2023a", status="FINISHED")
607+ >>> print(df[["name", "uuid", "status", "created_dt"]])
608+ """
609+ return jobs_module .list_jobs (
610+ self ._tapis ,
611+ app_id = app_id ,
612+ status = status ,
613+ limit = limit ,
614+ verbose = verbose ,
615+ )
0 commit comments