Skip to content
This repository was archived by the owner on Jul 24, 2024. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
464192f
Remove version field from runtime program (#152)
rathishcholarajan Oct 18, 2021
abb98d0
Rename isPublic to is_public when creating or reading runtime program…
rathishcholarajan Oct 18, 2021
31fdd4b
Update programId to program_id when running program (#139)
renier Oct 18, 2021
0d5ebf8
Add support to view program update date (#160)
rathishcholarajan Oct 18, 2021
767afeb
Upload runtime program using 'data' field (#157)
rathishcholarajan Oct 19, 2021
24dfa95
Read programs from "programs" array in response (#161)
rathishcholarajan Oct 19, 2021
79cd9bd
Remove version field from runtime program (#152)
rathishcholarajan Oct 18, 2021
45ab0b2
Rename isPublic to is_public when creating or reading runtime program…
rathishcholarajan Oct 18, 2021
faff4e2
Update programId to program_id when running program (#139)
renier Oct 18, 2021
bcc27fb
Add support to view program update date (#160)
rathishcholarajan Oct 18, 2021
866d045
Upload runtime program using 'data' field (#157)
rathishcholarajan Oct 19, 2021
eda2a51
Read programs from "programs" array in response (#161)
rathishcholarajan Oct 19, 2021
ab33b52
Pass program as base64 string to update (#168)
rathishcholarajan Oct 21, 2021
a8fe605
Accept JSON schema as program metadata (#158)
rathishcholarajan Oct 25, 2021
1b26e0b
Merge branch 'runtime-release-q4' of https://github.com/Qiskit-Partne…
kt474 Oct 26, 2021
df4eb81
Pass program params as object (#171)
rathishcholarajan Oct 27, 2021
e3e4315
Fix integration tests
rathishcholarajan Oct 27, 2021
f5712bc
Merge branch 'runtime-release-q4' of https://github.com/Qiskit-Partne…
kt474 Oct 28, 2021
0f95825
Use count to reduce one last extra call to API (#172)
rathishcholarajan Oct 28, 2021
b532b14
Allow updating runtime metadata in place (#188)
jyu00 Oct 29, 2021
c1065f0
Merge branch 'runtime-release-q4' of https://github.com/Qiskit-Partne…
kt474 Nov 1, 2021
f5b4e54
Remove version field from runtime program (#152)
rathishcholarajan Oct 18, 2021
93a2b85
Rename isPublic to is_public when creating or reading runtime program…
rathishcholarajan Oct 18, 2021
966d42a
Update programId to program_id when running program (#139)
renier Oct 18, 2021
031fc25
Add support to view program update date (#160)
rathishcholarajan Oct 18, 2021
1561a9b
Upload runtime program using 'data' field (#157)
rathishcholarajan Oct 19, 2021
b656ece
Read programs from "programs" array in response (#161)
rathishcholarajan Oct 19, 2021
8fb3669
Pass program as base64 string to update (#168)
rathishcholarajan Oct 21, 2021
74472c5
Accept JSON schema as program metadata (#158)
rathishcholarajan Oct 25, 2021
ee76158
Pass program params as object (#171)
rathishcholarajan Oct 27, 2021
da52271
Fix integration tests
rathishcholarajan Oct 27, 2021
f3033b8
Use count to reduce one last extra call to API (#172)
rathishcholarajan Oct 28, 2021
aea236b
Allow updating runtime metadata in place (#188)
jyu00 Oct 29, 2021
e71b402
Merge branch 'runtime-release-q4' of https://github.com/Qiskit-Partne…
kt474 Nov 2, 2021
4102480
Allow filtering runtime jobs by program ID (#193)
rathishcholarajan Nov 4, 2021
8e8bcb3
Allow runtime program authors to retrieve program data (#174)
kt474 Nov 4, 2021
07f0d53
Update cache after updating program (#196)
rathishcholarajan Nov 5, 2021
8133076
Allow filtering runtime jobs by provider (#197)
kt474 Nov 8, 2021
4522d9b
Support pagination for retrieving runtime programs (#170)
kt474 Nov 8, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 51 additions & 36 deletions qiskit_ibm/api/clients/runtime.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
"""Client for accessing IBM Quantum runtime service."""

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

from qiskit_ibm.credentials import Credentials
from qiskit_ibm.api.session import RetrySession
Expand All @@ -39,40 +39,36 @@ def __init__(
**credentials.connection_parameters())
self.api = Runtime(self._session)

def list_programs(self) -> List[Dict]:
def list_programs(self, limit: int = None, skip: int = None) -> Dict[str, Any]:
"""Return a list of runtime programs.

Args:
limit: The number of programs to return.
skip: The number of programs to skip.

Returns:
A list of quantum programs.
A list of runtime programs.
"""
return self.api.list_programs()
return self.api.list_programs(limit, skip)

def program_create(
self,
program_data: bytes,
program_data: str,
name: str,
description: str,
max_execution_time: int,
is_public: Optional[bool] = False,
version: Optional[str] = None,
backend_requirements: Optional[Dict] = None,
parameters: Optional[Dict] = None,
return_values: Optional[List] = None,
interim_results: Optional[List] = None
spec: Optional[Dict] = None
) -> Dict:
"""Create a new program.

Args:
name: Name of the program.
program_data: Program data.
program_data: Program data (base64 encoded).
description: Program description.
max_execution_time: Maximum execution time.
is_public: Whether the program should be public.
version: Program version.
backend_requirements: Backend requirements.
parameters: Program parameters.
return_values: Program return values.
interim_results: Program interim results.
spec: Backend requirements, parameters, interim results, return values, etc.

Returns:
Server response.
Expand All @@ -81,9 +77,7 @@ def program_create(
program_data=program_data,
name=name,
description=description, max_execution_time=max_execution_time,
is_public=is_public, version=version, backend_requirements=backend_requirements,
parameters=parameters, return_values=return_values,
interim_results=interim_results
is_public=is_public, spec=spec
)

def program_get(self, program_id: str) -> Dict:
Expand All @@ -97,17 +91,6 @@ def program_get(self, program_id: str) -> Dict:
"""
return self.api.program(program_id).get()

def program_get_data(self, program_id: str) -> Dict:
"""Return a specific program and its data.

Args:
program_id: Program ID.

Returns:
Program information, including data.
"""
return self.api.program(program_id).get_data()

def set_program_visibility(self, program_id: str, public: bool) -> None:
"""Sets a program's visibility.

Expand All @@ -127,7 +110,7 @@ def program_run(
program_id: str,
credentials: Credentials,
backend_name: str,
params: str,
params: Dict,
image: str
) -> Dict:
"""Run the specified program.
Expand Down Expand Up @@ -155,14 +138,32 @@ def program_delete(self, program_id: str) -> None:
"""
self.api.program(program_id).delete()

def program_update(self, program_id: str, program_data: str) -> None:
def program_update(
self,
program_id: str,
program_data: str = None,
name: str = None,
description: str = None,
max_execution_time: int = None,
spec: Optional[Dict] = None
) -> None:
"""Update a program.

Args:
program_id: Program ID.
program_data: Program data.
program_data: Program data (base64 encoded).
name: Name of the program.
description: Program description.
max_execution_time: Maximum execution time.
spec: Backend requirements, parameters, interim results, return values, etc.
"""
self.api.program(program_id).update(program_data)
if program_data:
self.api.program(program_id).update_data(program_data)

if any([name, description, max_execution_time, spec]):
self.api.program(program_id).update_metadata(
name=name, description=description,
max_execution_time=max_execution_time, spec=spec)

def job_get(self, job_id: str) -> Dict:
"""Get job data.
Expand All @@ -177,19 +178,33 @@ def job_get(self, job_id: str) -> Dict:
logger.debug("Runtime job get response: %s", response)
return response

def jobs_get(self, limit: int = None, skip: int = None, pending: bool = None) -> Dict:
def jobs_get(
self,
limit: int = None,
skip: int = None,
pending: bool = None,
program_id: str = None,
hub: str = None,
group: str = None,
project: str = None
) -> Dict:
"""Get job data for all jobs.

Args:
limit: Number of results to return.
skip: Number of results to skip.
pending: Returns 'QUEUED' and 'RUNNING' jobs if True,
returns 'DONE', 'CANCELLED' and 'ERROR' jobs if False.
program_id: Filter by Program ID.
hub: Filter by hub - hub, group, and project must all be specified.
group: Filter by group - hub, group, and project must all be specified.
project: Filter by project - hub, group, and project must all be specified.

Returns:
JSON response.
"""
return self.api.jobs_get(limit=limit, skip=skip, pending=pending)
return self.api.jobs_get(limit=limit, skip=skip, pending=pending,
program_id=program_id, hub=hub, group=group, project=project)

def job_results(self, job_id: str) -> str:
"""Get the results of a program job.
Expand Down
132 changes: 80 additions & 52 deletions qiskit_ibm/api/rest/runtime.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

from .base import RestAdapterBase
from ..session import RetrySession
from ...runtime.utils import RuntimeEncoder

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -54,65 +55,56 @@ def program_job(self, job_id: str) -> 'ProgramJob':
"""
return ProgramJob(self.session, job_id)

def list_programs(self) -> List[Dict]:
def list_programs(self, limit: int = None, skip: int = None) -> Dict[str, Any]:
"""Return a list of runtime programs.

Args:
limit: The number of programs to return.
skip: The number of programs to skip.

Returns:
JSON response.
A list of runtime programs.
"""
url = self.get_url('programs')
return self.session.get(url).json()
payload: Dict[str, int] = {}
if limit:
payload['limit'] = limit
if skip:
payload['offset'] = skip
return self.session.get(url, params=payload).json()

def create_program(
self,
program_data: bytes,
program_data: str,
name: str,
description: str,
max_execution_time: int,
is_public: Optional[bool] = False,
version: Optional[str] = None,
backend_requirements: Optional[Dict] = None,
parameters: Optional[Dict] = None,
return_values: Optional[List] = None,
interim_results: Optional[List] = None
spec: Optional[Dict] = None
) -> Dict:
"""Upload a new program.

Args:
program_data: Program data.
program_data: Program data (base64 encoded).
name: Name of the program.
description: Program description.
max_execution_time: Maximum execution time.
is_public: Whether the program should be public.
version: Program version.
backend_requirements: Backend requirements.
parameters: Program parameters.
return_values: Program return values.
interim_results: Program interim results.
spec: Backend requirements, parameters, interim results, return values, etc.

Returns:
JSON response.
"""
url = self.get_url('programs')
data = {'name': name,
'cost': str(max_execution_time),
'description': description.encode(),
'max_execution_time': max_execution_time,
'isPublic': is_public}
if version is not None:
data['version'] = version
if backend_requirements:
data['backendRequirements'] = json.dumps(backend_requirements)
if parameters:
data['parameters'] = json.dumps({"doc": parameters})
if return_values:
data['returnValues'] = json.dumps(return_values)
if interim_results:
data['interimResults'] = json.dumps(interim_results)

files = {'program': (name, program_data)} # type: ignore[dict-item]
response = self.session.post(url, data=data, files=files).json()
return response
payload = {'name': name,
'data': program_data,
'cost': max_execution_time,
'description': description,
'is_public': is_public}
if spec is not None:
payload['spec'] = spec
data = json.dumps(payload)
return self.session.post(url, data=data).json()

def program_run(
self,
Expand All @@ -121,7 +113,7 @@ def program_run(
group: str,
project: str,
backend_name: str,
params: str,
params: Dict,
image: str
) -> Dict:
"""Execute the program.
Expand All @@ -140,25 +132,38 @@ def program_run(
"""
url = self.get_url('jobs')
payload = {
'programId': program_id,
'program_id': program_id,
'hub': hub,
'group': group,
'project': project,
'backend': backend_name,
'params': [params],
'params': params,
'runtime': image
}
data = json.dumps(payload)
data = json.dumps(payload, cls=RuntimeEncoder)
return self.session.post(url, data=data).json()

def jobs_get(self, limit: int = None, skip: int = None, pending: bool = None) -> Dict:
def jobs_get(
self,
limit: int = None,
skip: int = None,
pending: bool = None,
program_id: str = None,
hub: str = None,
group: str = None,
project: str = None
) -> Dict:
"""Get a list of job data.

Args:
limit: Number of results to return.
skip: Number of results to skip.
pending: Returns 'QUEUED' and 'RUNNING' jobs if True,
returns 'DONE', 'CANCELLED' and 'ERROR' jobs if False.
program_id: Filter by Program ID.
hub: Filter by hub - hub, group, and project must all be specified.
group: Filter by group - hub, group, and project must all be specified.
project: Filter by project - hub, group, and project must all be specified.

Returns:
JSON response.
Expand All @@ -171,6 +176,10 @@ def jobs_get(self, limit: int = None, skip: int = None, pending: bool = None) ->
payload['offset'] = skip
if pending is not None:
payload['pending'] = 'true' if pending else 'false'
if program_id:
payload['program'] = program_id
if all([hub, group, project]):
payload['provider'] = f"{hub}/{group}/{project}"
return self.session.get(url, params=payload).json()

def logout(self) -> None:
Expand Down Expand Up @@ -211,15 +220,6 @@ def get(self) -> Dict[str, Any]:
url = self.get_url('self')
return self.session.get(url).json()

def get_data(self) -> Dict[str, Any]:
"""Return program information, including data.

Returns:
JSON response.
"""
url = self.get_url('data')
return self.session.get(url).json()

def make_public(self) -> None:
"""Sets a runtime program's visibility to public."""
url = self.get_url('public')
Expand All @@ -239,15 +239,43 @@ def delete(self) -> None:
url = self.get_url('self')
self.session.delete(url)

def update(self, program_data: str) -> None:
"""Update a program.
def update_data(self, program_data: str) -> None:
"""Update program data.

Args:
program_data: Program data.
program_data: Program data (base64 encoded).
"""
url = self.get_url("data")
self.session.put(url, data=program_data,
headers={'Content-Type': 'text/plain'})
headers={'Content-Type': 'application/octet-stream'})

def update_metadata(
self,
name: str = None,
description: str = None,
max_execution_time: int = None,
spec: Optional[Dict] = None
) -> None:
"""Update program metadata.

Args:
name: Name of the program.
description: Program description.
max_execution_time: Maximum execution time.
spec: Backend requirements, parameters, interim results, return values, etc.
"""
url = self.get_url("self")
payload: Dict = {}
if name:
payload["name"] = name
if description:
payload["description"] = description
if max_execution_time:
payload["cost"] = max_execution_time
if spec:
payload["spec"] = spec

self.session.patch(url, json=payload)


class ProgramJob(RestAdapterBase):
Expand Down
Loading