Skip to content

Commit

Permalink
Filter jobs with created after/before parameters (#367)
Browse files Browse the repository at this point in the history
* add creation date filters

* add tests

* update unit test

* add sleep to unit test

* update tests

* fix tests

* Apply suggestions from code review

Co-authored-by: Rathish Cholarajan <rathish.c@ibm.com>
Co-authored-by: Rathish Cholarajan <rathishc24@gmail.com>
  • Loading branch information
3 people committed Jun 14, 2022
1 parent f1aac5b commit 861b7d2
Show file tree
Hide file tree
Showing 8 changed files with 84 additions and 1 deletion.
10 changes: 10 additions & 0 deletions qiskit_ibm_runtime/api/clients/runtime.py
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,8 @@ def jobs_get(
project: str = None,
job_tags: Optional[List[str]] = None,
session_id: Optional[str] = None,
created_after: Optional[python_datetime] = None,
created_before: Optional[python_datetime] = None,
descending: bool = True,
) -> Dict:
"""Get job data for all jobs.
Expand All @@ -234,6 +236,12 @@ def jobs_get(
project: Filter by project - hub, group, and project must all be specified.
job_tags: Filter by tags assigned to jobs. Matched jobs are associated with all tags.
session_id: Job ID of the first job in a runtime session.
created_after: Filter by the given start date, in local time. This is used to
find jobs whose creation dates are after (greater than or equal to) this
local date/time.
created_before: Filter by the given end date, in local time. This is used to
find jobs whose creation dates are before (less than or equal to) this
local date/time.
descending: If ``True``, return the jobs in descending order of the job
creation date (i.e. newest first) until the limit is reached.
Expand All @@ -250,6 +258,8 @@ def jobs_get(
project=project,
job_tags=job_tags,
session_id=session_id,
created_after=created_after,
created_before=created_before,
descending=descending,
)

Expand Down
14 changes: 14 additions & 0 deletions qiskit_ibm_runtime/api/rest/runtime.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,15 @@
"""Runtime REST adapter."""

import logging
from datetime import datetime
from typing import Dict, Any, List, Union, Optional
import json

from .base import RestAdapterBase
from .program import Program
from .program_job import ProgramJob
from ...utils import RuntimeEncoder
from ...utils.converters import local_to_utc
from .cloud_backend import CloudBackend

logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -176,6 +178,8 @@ def jobs_get(
project: str = None,
job_tags: Optional[List[str]] = None,
session_id: Optional[str] = None,
created_after: Optional[datetime] = None,
created_before: Optional[datetime] = None,
descending: bool = True,
) -> Dict:
"""Get a list of job data.
Expand All @@ -191,6 +195,12 @@ def jobs_get(
project: Filter by project - hub, group, and project must all be specified.
job_tags: Filter by tags assigned to jobs. Matched jobs are associated with all tags.
session_id: Job ID of the first job in a runtime session.
created_after: Filter by the given start date, in local time. This is used to
find jobs whose creation dates are after (greater than or equal to) this
local date/time.
created_before: Filter by the given end date, in local time. This is used to
find jobs whose creation dates are before (less than or equal to) this
local date/time.
descending: If ``True``, return the jobs in descending order of the job
creation date (i.e. newest first) until the limit is reached.
Expand All @@ -211,6 +221,10 @@ def jobs_get(
payload["tags"] = job_tags
if session_id:
payload["session_id"] = session_id
if created_after:
payload["created_after"] = local_to_utc(created_after).isoformat()
if created_before:
payload["created_before"] = local_to_utc(created_before).isoformat()
if descending is False:
payload["sort"] = "ASC"
if all([hub, group, project]):
Expand Down
11 changes: 11 additions & 0 deletions qiskit_ibm_runtime/qiskit_runtime_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import logging
import traceback
import warnings
from datetime import datetime
from collections import OrderedDict
from typing import Dict, Callable, Optional, Union, List, Any, Type

Expand Down Expand Up @@ -1219,6 +1220,8 @@ def jobs(
instance: Optional[str] = None,
job_tags: Optional[List[str]] = None,
session_id: Optional[str] = None,
created_after: Optional[datetime] = None,
created_before: Optional[datetime] = None,
descending: bool = True,
) -> List[RuntimeJob]:
"""Retrieve all runtime jobs, subject to optional filtering.
Expand All @@ -1234,6 +1237,12 @@ def jobs(
hub/group/project format.
job_tags: Filter by tags assigned to jobs. Matched jobs are associated with all tags.
session_id: Job ID of the first job in a runtime session.
created_after: Filter by the given start date, in local time. This is used to
find jobs whose creation dates are after (greater than or equal to) this
local date/time.
created_before: Filter by the given end date, in local time. This is used to
find jobs whose creation dates are before (less than or equal to) this
local date/time.
descending: If ``True``, return the jobs in descending order of the job
creation date (i.e. newest first) until the limit is reached.
Expand Down Expand Up @@ -1266,6 +1275,8 @@ def jobs(
project=project,
job_tags=job_tags,
session_id=session_id,
created_after=created_after,
created_before=created_before,
descending=descending,
)
job_page = jobs_response["jobs"]
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
upgrade:
- |
:meth:`~qiskit_ibm_runtime.QiskitRuntimeService.jobs` has two new parameters, ``created_after``
and ``created_before``. These can be used to filter jobs by creation date in local time.
15 changes: 14 additions & 1 deletion test/integration/test_retrieve_job.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
"""Tests for job functions using real runtime service."""

import uuid

from datetime import datetime, timezone
from qiskit.providers.jobstatus import JobStatus

from ..ibm_test_case import IBMIntegrationJobTestCase
Expand Down Expand Up @@ -150,6 +150,19 @@ def test_retrieve_jobs_by_session_id(self, service):
rjobs = service.jobs(session_id="test")
self.assertFalse(rjobs)

@run_integration_test
def test_jobs_filter_by_date(self, service):
"""Test retrieving jobs by creation date."""
current_time = datetime.now(timezone.utc)
job = self._run_program(service)
job.wait_for_final_state()
time_after_job = datetime.now(timezone.utc)
rjobs = service.jobs(created_before=time_after_job, created_after=current_time)
self.assertTrue(job.job_id in [j.job_id for j in rjobs])
for job in rjobs:
self.assertTrue(job.creation_date <= time_after_job)
self.assertTrue(job.creation_date >= current_time)

@run_integration_test
def test_jobs_filter_by_hgp(self, service):
"""Test retrieving jobs by hgp."""
Expand Down
2 changes: 2 additions & 0 deletions test/program.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

import uuid
import copy
from datetime import datetime, timezone
from qiskit_ibm_runtime import QiskitRuntimeService


Expand Down Expand Up @@ -102,4 +103,5 @@ def run_program(
max_execution_time=max_execution_time,
session_id=session_id,
)
job._creation_date = datetime.now(timezone.utc)
return job
10 changes: 10 additions & 0 deletions test/unit/mock/fake_runtime_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import json
import time
import uuid
from datetime import timezone, datetime as python_datetime
from concurrent.futures import ThreadPoolExecutor
from functools import wraps
from typing import Optional, Dict, Any, List
Expand Down Expand Up @@ -133,6 +134,7 @@ def __init__(
self.log_level = log_level
self._session_id = session_id
self._max_execution_time = max_execution_time
self._creation_date = python_datetime.now(timezone.utc)
if final_status is None:
self._future = self._executor.submit(self._auto_progress)
self._result = None
Expand Down Expand Up @@ -421,6 +423,8 @@ def jobs_get(
project=None,
job_tags=None,
session_id=None,
created_after=None,
created_before=None,
descending=True,
):
"""Get all jobs."""
Expand Down Expand Up @@ -450,6 +454,12 @@ def jobs_get(
if session_id:
jobs = [job for job in jobs if job._session_id == session_id]
count = len(jobs)
if created_after:
jobs = [job for job in jobs if job._creation_date >= created_after]
count = len(jobs)
if created_before:
jobs = [job for job in jobs if job._creation_date <= created_before]
count = len(jobs)
jobs = jobs[skip : limit + skip]
if descending is False:
jobs.reverse()
Expand Down
17 changes: 17 additions & 0 deletions test/unit/test_job_retrieval.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

"""Tests for runtime job retrieval."""

from datetime import datetime, timedelta, timezone
from qiskit_ibm_runtime.exceptions import IBMInputValueError
from .mock.fake_runtime_service import FakeRuntimeService
from ..ibm_test_case import IBMTestCase
Expand Down Expand Up @@ -243,6 +244,22 @@ def test_jobs_filter_by_session_id(self):
rjobs = service.jobs(program_id=program_id, session_id="no_test_session_id")
self.assertFalse(rjobs)

def test_jobs_filter_by_date(self):
"""Test retrieving jobs filtered by date."""
service = self._ibm_quantum_service
current_time = datetime.now(timezone.utc) - timedelta(seconds=5)
job = run_program(service=service)
with mock_wait_for_final_state(service, job):
job.wait_for_final_state()
time_after_job = datetime.now(timezone.utc)
rjobs = service.jobs(
created_before=time_after_job,
created_after=current_time,
)
self.assertTrue(job.job_id in [j.job_id for j in rjobs])
self.assertTrue(job._creation_date <= time_after_job)
self.assertTrue(job._creation_date >= current_time)

def test_jobs_sort_by_date(self):
"""Test retrieving jobs sorted by the date."""
service = self._ibm_quantum_service
Expand Down

0 comments on commit 861b7d2

Please sign in to comment.