diff --git a/qiskit_ibm_provider/job/ibm_composite_job.py b/qiskit_ibm_provider/job/ibm_composite_job.py index 8eb305f8b..7a62650b2 100644 --- a/qiskit_ibm_provider/job/ibm_composite_job.py +++ b/qiskit_ibm_provider/job/ibm_composite_job.py @@ -21,7 +21,7 @@ import uuid from collections import defaultdict from concurrent import futures -from datetime import datetime +from datetime import datetime as python_datetime from functools import wraps from typing import Dict, Optional, Tuple, Any, List, Callable, Union @@ -122,7 +122,7 @@ def __init__( backend: "ibm_backend.IBMBackend", api_client: AccountClient, job_id: Optional[str] = None, - creation_date: Optional[datetime] = None, + creation_date: Optional[python_datetime] = None, jobs: Optional[List[IBMCircuitJob]] = None, circuits_list: Optional[List[List[QuantumCircuit]]] = None, run_config: Optional[Dict] = None, @@ -373,9 +373,18 @@ def _async_submit(self, sub_job: SubJob) -> None: pass @_requires_submit - def properties(self) -> Optional[Union[List[BackendProperties], BackendProperties]]: + def properties( + self, refresh: bool = False, datetime: Optional[python_datetime] = None + ) -> Optional[Union[List[BackendProperties], BackendProperties]]: """Return the backend properties for this job. + Args: + refresh: If ``True``, re-query the server for the backend properties. + Otherwise, return a cached version. + datetime: By specifying `datetime`, this function returns an instance + of the :class:`BackendProperties` + whose timestamp is closest to, but older than, the specified `datetime`. + Note: This method blocks until all sub-jobs are submitted. @@ -392,7 +401,7 @@ def properties(self) -> Optional[Union[List[BackendProperties], BackendPropertie self._properties = [] properties_ts = [] for job in self._get_circuit_jobs(): - props = job.properties() + props = job.properties(refresh, datetime) if props.last_update_date not in properties_ts: self._properties.append(props) properties_ts.append(props.last_update_date) @@ -752,7 +761,7 @@ def queue_info(self) -> Optional[QueueInfo]: self._queue_info = None return self._queue_info - def creation_date(self) -> Optional[datetime]: + def creation_date(self) -> Optional[python_datetime]: """Return job creation date, in local time. Returns: diff --git a/qiskit_ibm_provider/job/ibm_job.py b/qiskit_ibm_provider/job/ibm_job.py index 82c13f25f..07455d3d0 100644 --- a/qiskit_ibm_provider/job/ibm_job.py +++ b/qiskit_ibm_provider/job/ibm_job.py @@ -14,7 +14,7 @@ import logging from abc import ABC, abstractmethod -from datetime import datetime +from datetime import datetime as python_datetime from typing import Dict, Optional, Any, List, Union from qiskit.circuit.quantumcircuit import QuantumCircuit @@ -68,14 +68,23 @@ def __init__( # Append suffix to key to avoid conflicts. self._data[key + "_"] = value - def properties(self) -> Optional[BackendProperties]: + def properties( + self, refresh: bool = False, datetime: Optional[python_datetime] = None + ) -> Optional[BackendProperties]: """Return the backend properties for this job. + Args: + refresh: If ``True``, re-query the server for the backend properties. + Otherwise, return a cached version. + datetime: By specifying `datetime`, this function returns an instance + of the :class:`BackendProperties` + whose timestamp is closest to, but older than, the specified `datetime`. + Returns: The backend properties used for this job, or ``None`` if properties are not available. """ - pass + return self._backend.properties(refresh, datetime) @abstractmethod def result( @@ -166,7 +175,7 @@ def queue_info(self) -> Optional[QueueInfo]: pass @abstractmethod - def creation_date(self) -> datetime: + def creation_date(self) -> python_datetime: """Return job creation date, in local time. Returns: diff --git a/releasenotes/notes/job_properties-19724d5b369855ad.yaml b/releasenotes/notes/job_properties-19724d5b369855ad.yaml new file mode 100644 index 000000000..e33c77a62 --- /dev/null +++ b/releasenotes/notes/job_properties-19724d5b369855ad.yaml @@ -0,0 +1,5 @@ +--- +fixes: + - | + The method :meth:`job.properties()` previously did nothing. Now it + returns the backend properties for this job. diff --git a/test/integration/test_backend.py b/test/integration/test_backend.py index e809033ab..ef7a22331 100644 --- a/test/integration/test_backend.py +++ b/test/integration/test_backend.py @@ -12,6 +12,7 @@ """IBMBackend Test.""" +from datetime import datetime, timedelta from unittest import mock, skip from unittest.mock import patch @@ -20,7 +21,7 @@ from qiskit.providers.exceptions import QiskitBackendNotFoundError from qiskit.test.reference_circuits import ReferenceCircuits -from qiskit_ibm_provider import IBMBackend, IBMProvider, least_busy +from qiskit_ibm_provider import IBMBackend, IBMProvider from qiskit_ibm_provider.ibm_qubit_properties import IBMQubitProperties from qiskit_ibm_provider.exceptions import IBMBackendValueError @@ -174,19 +175,26 @@ def test_retrieve_backend_not_exist(self): def test_too_many_qubits_in_circuit(self): """Check error message if circuit contains more qubits than supported on the backend.""" - backends = self.dependencies.provider.backends( - instance=self.dependencies.instance, simulator=False + num = len(self.backend.properties().qubits) + num_qubits = num + 1 + circuit = QuantumCircuit(num_qubits, num_qubits) + with self.assertRaises(IBMBackendValueError) as err: + _ = self.backend.run(circuit) + self.assertIn( + f"Circuit contains {num_qubits} qubits, but backend has only {num}.", + str(err.exception), ) - least_busy_backend = least_busy(backends) - if least_busy_backend.properties(): - self.assertTrue(least_busy_backend) - - num = len(least_busy_backend.properties().qubits) - num_qubits = num + 1 - circuit = QuantumCircuit(num_qubits, num_qubits) - with self.assertRaises(IBMBackendValueError) as err: - _ = least_busy_backend.run(circuit) - self.assertIn( - f"Circuit contains {num_qubits} qubits, but backend has only {num}.", - str(err.exception), - ) + + def test_job_backend_properties(self): + """Test job backend properties.""" + job = self.backend.run(ReferenceCircuits.bell()) + backend_version = self.backend.properties().backend_version + job_version = job.properties().backend_version + self.assertEqual(job_version, backend_version) + + prev_datetime = datetime.now() - timedelta(days=30) + prev_backend_version = self.backend.properties( + datetime=prev_datetime + ).backend_version + prev_job_version = job.properties(datetime=prev_datetime).backend_version + self.assertEqual(prev_job_version, prev_backend_version)