From 7752b68c749cc434feeacb5caf72d02de91aed46 Mon Sep 17 00:00:00 2001 From: merav-aharoni Date: Thu, 7 Sep 2023 22:37:24 +0300 Subject: [PATCH] Changes following implementation of Session in qiskit-ibm-provider (#1053) * Use 'converters' from qiskit-ibm-provider * Removed runtime_session.py and import it from qiskit-ibm-provider * Remove unused self._circuits_map * Fixed documentation --------- Co-authored-by: Kevin Tian --- qiskit_ibm_runtime/api/rest/runtime.py | 5 +- .../api/rest/runtime_session.py | 40 ----- qiskit_ibm_runtime/ibm_backend.py | 3 +- qiskit_ibm_runtime/runtime_job.py | 3 +- qiskit_ibm_runtime/session.py | 11 +- qiskit_ibm_runtime/utils/__init__.py | 2 +- qiskit_ibm_runtime/utils/converters.py | 160 ------------------ test/unit/test_utils_converters.py | 47 ----- 8 files changed, 11 insertions(+), 260 deletions(-) delete mode 100644 qiskit_ibm_runtime/api/rest/runtime_session.py delete mode 100644 qiskit_ibm_runtime/utils/converters.py delete mode 100644 test/unit/test_utils_converters.py diff --git a/qiskit_ibm_runtime/api/rest/runtime.py b/qiskit_ibm_runtime/api/rest/runtime.py index 1c9866883..86c97bb69 100644 --- a/qiskit_ibm_runtime/api/rest/runtime.py +++ b/qiskit_ibm_runtime/api/rest/runtime.py @@ -19,10 +19,11 @@ from qiskit_ibm_provider.api.rest.base import RestAdapterBase from qiskit_ibm_provider.api.rest.program_job import ProgramJob +from qiskit_ibm_provider.api.rest.runtime_session import RuntimeSession +from qiskit_ibm_provider.utils import local_to_utc + from .program import Program -from .runtime_session import RuntimeSession from ...utils import RuntimeEncoder -from ...utils.converters import local_to_utc from .cloud_backend import CloudBackend logger = logging.getLogger(__name__) diff --git a/qiskit_ibm_runtime/api/rest/runtime_session.py b/qiskit_ibm_runtime/api/rest/runtime_session.py deleted file mode 100644 index 5faceb145..000000000 --- a/qiskit_ibm_runtime/api/rest/runtime_session.py +++ /dev/null @@ -1,40 +0,0 @@ -# This code is part of Qiskit. -# -# (C) Copyright IBM 2022. -# -# This code is licensed under the Apache License, Version 2.0. You may -# obtain a copy of this license in the LICENSE.txt file in the root directory -# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. -# -# Any modifications or derivative works of this code must retain this -# copyright notice, and modified files need to carry a notice indicating -# that they have been altered from the originals. - -"""Runtime Session REST adapter.""" - - -from qiskit_ibm_provider.api.rest.base import RestAdapterBase -from ..session import RetrySession - - -class RuntimeSession(RestAdapterBase): - """Rest adapter for session related endpoints.""" - - URL_MAP = { - "close": "/close", - } - - def __init__(self, session: RetrySession, session_id: str, url_prefix: str = "") -> None: - """Job constructor. - - Args: - session: RetrySession to be used in the adapter. - session_id: Job ID of the first job in a runtime session. - url_prefix: Prefix to use in the URL. - """ - super().__init__(session, "{}/sessions/{}".format(url_prefix, session_id)) - - def close(self) -> None: - """Close this session.""" - url = self.get_url("close") - self.session.delete(url) diff --git a/qiskit_ibm_runtime/ibm_backend.py b/qiskit_ibm_runtime/ibm_backend.py index 496b35891..fcf3f2536 100644 --- a/qiskit_ibm_runtime/ibm_backend.py +++ b/qiskit_ibm_runtime/ibm_backend.py @@ -42,6 +42,8 @@ defaults_from_server_data, properties_from_server_data, ) +from qiskit_ibm_provider.utils import local_to_utc + from qiskit_ibm_runtime import ( # pylint: disable=unused-import,cyclic-import qiskit_runtime_service, ) @@ -52,7 +54,6 @@ from .utils.backend_converter import ( convert_to_target, ) -from .utils.converters import local_to_utc logger = logging.getLogger(__name__) diff --git a/qiskit_ibm_runtime/runtime_job.py b/qiskit_ibm_runtime/runtime_job.py index 008b73969..b6d9eeb8d 100644 --- a/qiskit_ibm_runtime/runtime_job.py +++ b/qiskit_ibm_runtime/runtime_job.py @@ -27,7 +27,7 @@ from qiskit.providers.job import JobV1 as Job # pylint: disable=unused-import,cyclic-import -from qiskit_ibm_provider.utils import validate_job_tags +from qiskit_ibm_provider.utils import validate_job_tags, utc_to_local from qiskit_ibm_runtime import qiskit_runtime_service from .constants import API_TO_JOB_ERROR_MESSAGE, API_TO_JOB_STATUS, DEFAULT_DECODERS @@ -44,7 +44,6 @@ from .api.clients import RuntimeClient, RuntimeWebsocketClient, WebsocketClientCloseCode from .exceptions import IBMError from .api.exceptions import RequestsApiError -from .utils.converters import utc_to_local from .api.client_parameters import ClientParameters from .utils.utils import CallableStr from .utils.deprecation import issue_deprecation_msg diff --git a/qiskit_ibm_runtime/session.py b/qiskit_ibm_runtime/session.py index 913247999..60054d61d 100644 --- a/qiskit_ibm_runtime/session.py +++ b/qiskit_ibm_runtime/session.py @@ -17,14 +17,13 @@ from functools import wraps from contextvars import ContextVar -from qiskit.circuit import QuantumCircuit +from qiskit_ibm_provider.utils.converters import hms_to_seconds from qiskit_ibm_runtime import QiskitRuntimeService from .runtime_job import RuntimeJob from .runtime_program import ParameterNamespace from .program.result_decoder import ResultDecoder from .ibm_backend import IBMBackend -from .utils.converters import hms_to_seconds from .utils.deprecation import issue_deprecation_msg from .exceptions import IBMInputValueError @@ -62,12 +61,13 @@ class Session: with Session(backend="ibmq_qasm_simulator") as session: sampler = Sampler(session=session, options=options) - job = sampler.run(circ) + job = sampler.run(ReferenceCircuits.bell()) print(f"Sampler job ID: {job.job_id()}") - print(f"Sampler job result:" {job.result()}) + print(f"Sampler job result: {job.result()}") # Close the session only if all jobs are finished and # you don't need to run more in the session. session.close() + """ def __init__( @@ -122,9 +122,6 @@ def __init__( self._session_id: Optional[str] = None self._active = True - - self._circuits_map: Dict[str, QuantumCircuit] = {} - self._max_time = ( max_time if max_time is None or isinstance(max_time, int) diff --git a/qiskit_ibm_runtime/utils/__init__.py b/qiskit_ibm_runtime/utils/__init__.py index 053f8691b..04e10428b 100644 --- a/qiskit_ibm_runtime/utils/__init__.py +++ b/qiskit_ibm_runtime/utils/__init__.py @@ -35,7 +35,7 @@ to_python_identifier """ -from .converters import ( +from qiskit_ibm_provider.utils.converters import ( utc_to_local, local_to_utc, seconds_to_duration, diff --git a/qiskit_ibm_runtime/utils/converters.py b/qiskit_ibm_runtime/utils/converters.py deleted file mode 100644 index adb50f37b..000000000 --- a/qiskit_ibm_runtime/utils/converters.py +++ /dev/null @@ -1,160 +0,0 @@ -# This code is part of Qiskit. -# -# (C) Copyright IBM 2021. -# -# This code is licensed under the Apache License, Version 2.0. You may -# obtain a copy of this license in the LICENSE.txt file in the root directory -# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. -# -# Any modifications or derivative works of this code must retain this -# copyright notice, and modified files need to carry a notice indicating -# that they have been altered from the originals. - -"""Utilities related to conversion.""" - -from typing import Union, Tuple, Any -from datetime import datetime, timedelta, timezone -from math import ceil -from dateutil import tz, parser - -from ..exceptions import IBMInputValueError - - -def utc_to_local(utc_dt: Union[datetime, str]) -> datetime: - """Convert a UTC ``datetime`` object or string to a local timezone ``datetime``. - - Args: - utc_dt: Input UTC `datetime` or string. - - Returns: - A ``datetime`` with the local timezone. - - Raises: - TypeError: If the input parameter value is not valid. - """ - if isinstance(utc_dt, str): - utc_dt = parser.parse(utc_dt) - if not isinstance(utc_dt, datetime): - raise TypeError("Input `utc_dt` is not string or datetime.") - utc_dt = utc_dt.replace(tzinfo=timezone.utc) # type: ignore[arg-type] - local_dt = utc_dt.astimezone(tz.tzlocal()) # type: ignore[attr-defined] - return local_dt - - -def local_to_utc(local_dt: Union[datetime, str]) -> datetime: - """Convert a local ``datetime`` object or string to a UTC ``datetime``. - - Args: - local_dt: Input local ``datetime`` or string. - - Returns: - A ``datetime`` in UTC. - - Raises: - TypeError: If the input parameter value is not valid. - """ - if isinstance(local_dt, str): - local_dt = parser.parse(local_dt) - if not isinstance(local_dt, datetime): - raise TypeError("Input `local_dt` is not string or datetime.") - - # Input is considered local if it's ``utcoffset()`` is ``None`` or none-zero. - if local_dt.utcoffset() is None or local_dt.utcoffset() != timedelta(0): - local_dt = local_dt.replace(tzinfo=tz.tzlocal()) - return local_dt.astimezone(tz.UTC) - return local_dt # Already in UTC. - - -def utc_to_local_all(data: Any) -> Any: - """Recursively convert all ``datetime`` in the input data from local time to UTC. - - Note: - Only lists and dictionaries are traversed. - - Args: - data: Data to be converted. - - Returns: - Converted data. - """ - if isinstance(data, datetime): - return utc_to_local(data) - elif isinstance(data, list): - return [utc_to_local_all(elem) for elem in data] - elif isinstance(data, dict): - return {key: utc_to_local_all(elem) for key, elem in data.items()} - return data - - -def seconds_to_duration(seconds: float) -> Tuple[int, int, int, int, int]: - """Converts seconds in a datetime delta to a duration. - - Args: - seconds: Number of seconds in time delta. - - Returns: - A tuple containing the duration in terms of days, - hours, minutes, seconds, and milliseconds. - """ - days = int(seconds // (3600 * 24)) - hours = int((seconds // 3600) % 24) - minutes = int((seconds // 60) % 60) - seconds = seconds % 60 - millisec = 0 - if seconds < 1: - millisec = int(ceil(seconds * 1000)) - seconds = 0 - else: - seconds = int(seconds) - return days, hours, minutes, seconds, millisec - - -def duration_difference(date_time: datetime) -> str: - """Compute the estimated duration until the given datetime. - - Args: - date_time: The input local datetime. - - Returns: - String giving the estimated duration. - """ - time_delta = date_time.replace(tzinfo=None) - datetime.now() - time_tuple = seconds_to_duration(time_delta.total_seconds()) - # The returned tuple contains the duration in terms of - # days, hours, minutes, seconds, and milliseconds. - time_str = "" - if time_tuple[0]: - time_str += "{} days".format(time_tuple[0]) - time_str += " {} hrs".format(time_tuple[1]) - elif time_tuple[1]: - time_str += "{} hrs".format(time_tuple[1]) - time_str += " {} min".format(time_tuple[2]) - elif time_tuple[2]: - time_str += "{} min".format(time_tuple[2]) - time_str += " {} sec".format(time_tuple[3]) - elif time_tuple[3]: - time_str += "{} sec".format(time_tuple[3]) - return time_str - - -def hms_to_seconds(hms: str, msg_prefix: str = "") -> int: - """Convert duration specified as hours minutes seconds to seconds. - - Args: - hms: The string input duration (in hours minutes seconds). Ex: 2h 10m 20s - msg_prefix: Additional message to prefix the error. - - Returns: - Total seconds (int) in the duration. - - Raises: - IBMInputValueError: when the given hms string is in an invalid format - """ - try: - date_time = parser.parse(hms) - hours = date_time.hour - minutes = date_time.minute - seconds = date_time.second - return int(timedelta(hours=hours, minutes=minutes, seconds=seconds).total_seconds()) - except parser.ParserError as parser_error: - raise IBMInputValueError(msg_prefix + str(parser_error)) diff --git a/test/unit/test_utils_converters.py b/test/unit/test_utils_converters.py deleted file mode 100644 index e9948b934..000000000 --- a/test/unit/test_utils_converters.py +++ /dev/null @@ -1,47 +0,0 @@ -# This code is part of Qiskit. -# -# (C) Copyright IBM 2022. -# -# This code is licensed under the Apache License, Version 2.0. You may -# obtain a copy of this license in the LICENSE.txt file in the root directory -# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. -# -# Any modifications or derivative works of this code must retain this -# copyright notice, and modified files need to carry a notice indicating -# that they have been altered from the originals. - -"""Tests for the methods utils.converters file.""" - -from qiskit_ibm_runtime.exceptions import IBMInputValueError -from qiskit_ibm_runtime.utils.converters import hms_to_seconds -from ..ibm_test_case import IBMTestCase - - -class TestUtilsConverters(IBMTestCase): - """Tests for the methods utils.converters file.""" - - def test_hms_to_seconds(self): - """Test converting hours minutes seconds (string) to seconds (int).""" - valid_strings = [ - ("2h", 7200), - ("50m", 3000), - ("20s", 20), - ("1h 30m", 5400), - ("3h 30m 30s", 12630), - ("3h 30s", 10830), - ("3h30m30s", 12630), - ] - invalid_strings = [ - "2d", - "24h", - "60m", - "60s", - "2w", - ] - for valid_string in valid_strings: - with self.subTest(valid_string=valid_string): - self.assertEqual(hms_to_seconds(valid_string[0]), valid_string[1]) - for invalid_string in invalid_strings: - with self.subTest(invalid_string=invalid_string): - with self.assertRaises(IBMInputValueError): - hms_to_seconds(invalid_string)