Skip to content

Commit

Permalink
Merge pull request #171 from qiskit-community/save-metadata
Browse files Browse the repository at this point in the history
add backend cancel job methods and save metadata
  • Loading branch information
Cynocracy committed Feb 29, 2024
2 parents 7937066 + dc8bca9 commit b381f3c
Show file tree
Hide file tree
Showing 10 changed files with 58 additions and 21 deletions.
27 changes: 14 additions & 13 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,14 @@

"""Sphinx doc build configuration."""
import qiskit_sphinx_theme
from qiskit_ionq.version import VERSION_INFO

# -- Project information -----------------------------------------------------

project = "Qiskit IonQ Provider" # pylint: disable=invalid-name
copyright = "2020, IonQ, Inc." # pylint: disable=invalid-name,redefined-builtin
author = "IonQ, Inc." # pylint: disable=invalid-name
release = "0.0.1" # pylint: disable=invalid-name
release = VERSION_INFO # pylint: disable=invalid-name


# -- General configuration ---------------------------------------------------
Expand All @@ -57,15 +58,15 @@
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = [
'sphinx.ext.napoleon',
'sphinx.ext.autodoc',
'sphinx.ext.autosummary',
'sphinx.ext.mathjax',
'sphinx.ext.viewcode',
'sphinx.ext.extlinks',
'jupyter_sphinx',
'sphinx_panels',
'qiskit_sphinx_theme',
"sphinx.ext.napoleon",
"sphinx.ext.autodoc",
"sphinx.ext.autosummary",
"sphinx.ext.mathjax",
"sphinx.ext.viewcode",
"sphinx.ext.extlinks",
"jupyter_sphinx",
"sphinx_panels",
"qiskit_sphinx_theme",
]

# Add any paths that contain templates here, relative to this directory.
Expand All @@ -74,7 +75,7 @@
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
# This pattern also affects html_static_path and html_extra_path.
exclude_patterns = ['_build', '**.ipynb_checkpoints']
exclude_patterns = ["_build", "**.ipynb_checkpoints"]


# -- Options for HTML output -------------------------------------------------
Expand All @@ -88,10 +89,10 @@
autosummary_generate_overwrite = False

autodoc_default_options = {
'inherited-members': None,
"inherited-members": None,
}

autoclass_content = 'both'
autoclass_content = "both"
#
# Sphinx doc mappings
intersphinx_mapping = {
Expand Down
9 changes: 9 additions & 0 deletions qiskit_ionq/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,16 @@

"""Provider for IonQ backends"""

import warnings
from .ionq_provider import IonQProvider
from .version import __version__
from .ionq_gates import GPIGate, GPI2Gate, MSGate, ZZGate
from .constants import ErrorMitigation

# warn if qiskit is not installed
try:
from qiskit.version import get_version_info # pylint: disable=unused-import
except ImportError:
warnings.warn(
"Qiskit is not installed. Please install the latest version of Qiskit."
)
9 changes: 8 additions & 1 deletion qiskit_ionq/ionq_backend.py
Original file line number Diff line number Diff line change
Expand Up @@ -261,9 +261,16 @@ def retrieve_job(self, job_id):

def retrieve_jobs(self, job_ids):
"""get a list of jobs from a specific backend, job id"""

return [ionq_job.IonQJob(self, job_id, self.client) for job_id in job_ids]

def cancel_job(self, job_id):
"""cancels a job from a specific backend, by job id."""
return self.client.cancel_job(job_id)

def cancel_jobs(self, job_ids):
"""cancels a list of jobs from a specific backend, job id"""
return [self.client.cancel_job(job_id) for job_id in job_ids]

def has_valid_mapping(self, circuit) -> bool:
"""checks if the circuit has at least one
valid qubit -> bit measurement.
Expand Down
13 changes: 12 additions & 1 deletion qiskit_ionq/ionq_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ def make_path(self, *parts):
Returns:
str: A URL to use for an API call.
"""
return "/".join([self._url] + list(parts))
return f"{self._url}/{'/'.join(parts)}"

def _get_with_retry(self, req_path, params=None, headers=None, timeout=30):
"""Make a GET request with retry logic and exception handling.
Expand Down Expand Up @@ -174,6 +174,17 @@ def cancel_job(self, job_id: str):
exceptions.IonQAPIError.raise_for_status(res)
return res.json()

def cancel_jobs(self, job_ids: list):
"""Cancel multiple jobs at once.
Args:
job_ids (list): A list of job IDs to cancel.
Returns:
list: A list of :meth:`cancel_job <cancel_job>` responses.
"""
return [self.cancel_job(job_id) for job_id in job_ids]

@retry(exceptions=IonQRetriableError, tries=3)
def delete_job(self, job_id: str):
"""Delete a job and associated data.
Expand Down
14 changes: 11 additions & 3 deletions qiskit_ionq/ionq_job.py
Original file line number Diff line number Diff line change
Expand Up @@ -321,7 +321,7 @@ def status(self):

# Otherwise, look up a status enum from the response.
response = self._client.retrieve_job(self._job_id)
api_response_status = response["status"]
api_response_status = response.get("status")
try:
status_enum = constants.APIJobStatus(api_response_status)
except ValueError as ex:
Expand All @@ -346,7 +346,7 @@ def status(self):
) from ex

if self._status in jobstatus.JOB_FINAL_STATES:
self._metadata = response.get("metadata") or {}
self._save_metadata(response)

if self._status == jobstatus.JobStatus.DONE:
self._num_qubits = response.get("qubits")
Expand Down Expand Up @@ -404,7 +404,7 @@ def _format_result(self, data):

# Format the inner result payload.
success = self._status == jobstatus.JobStatus.DONE
metadata = self._metadata
metadata = self._metadata.get("metadata", {})
sampler_seed = (
int(metadata.get("sampler_seed", ""))
if metadata.get("sampler_seed", "").isdigit()
Expand Down Expand Up @@ -452,5 +452,13 @@ def _format_result(self, data):
}
)

def _save_metadata(self, response):
"""Save metadata from the response to the job instance.
Args:
response (dict): A JSON body response from a REST API call.
"""
self._metadata.update(response)


__all__ = ["IonQJob"]
2 changes: 1 addition & 1 deletion qiskit_ionq/ionq_provider.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ def __init__(self, token: str = None, url: str = None, custom_headers: dict = No
]
)

def get_backend(self, name=None, gateset="qis", **kwargs):
def get_backend(self, name: str = None, gateset="qis", **kwargs):
"""Return a single backend matching the specified filtering.
Args:
name (str): name of the backend.
Expand Down
2 changes: 1 addition & 1 deletion qiskit_ionq/version.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
pkg_parent = pathlib.Path(__file__).parent.parent.absolute()

# major, minor, micro
VERSION_INFO = ".".join(map(str, (0, 5, 0, "dev1")))
VERSION_INFO = ".".join(map(str, (0, 5, 0, "dev2")))


def _minimal_ext_cmd(cmd: List[str]) -> bytes:
Expand Down
1 change: 1 addition & 0 deletions requirements-docs.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
qiskit>=1.0.0
retry>=0.9.0
Sphinx>=4.5.0
sphinx-tabs>=1.1.11
Expand Down
1 change: 1 addition & 0 deletions requirements-test.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
qiskit>=1.0.0
pytest
requests-mock>=1.8.0
pytest-cov==2.10.1
1 change: 0 additions & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
qiskit>=0.4.0
decorator>=5.1.0
requests>=2.24.0
retry>=0.9.0
Expand Down

0 comments on commit b381f3c

Please sign in to comment.