def run_with_api(self, api): """Creates a new ``IBMQJob`` running with the provided API object.""" backend = FakeRueschlikon() self._current_api = api self._current_qjob = IBMQJob(backend, None, api, qobj=new_fake_qobj()) self._current_qjob.submit() return self._current_qjob
def run_on_backend(backend, qobj, backend_options=None, noise_config=None, skip_qobj_validation=False): if skip_qobj_validation: job_id = str(uuid.uuid4()) if is_aer_provider(backend): from qiskit.providers.aer.aerjob import AerJob temp_backend_options = backend_options[ 'backend_options'] if backend_options != {} else None temp_noise_config = noise_config[ 'noise_model'] if noise_config != {} else None job = AerJob(backend, job_id, backend._run_job, qobj, temp_backend_options, temp_noise_config, False) job._future = job._executor.submit(job._fn, job._job_id, job._qobj, *job._args) elif is_basicaer_provider(backend): backend._set_options(qobj_config=qobj.config, **backend_options) job = BasicAerJob(backend, job_id, backend._run_job, qobj) job._future = job._executor.submit(job._fn, job._job_id, job._qobj) elif is_ibmq_provider(backend): # TODO: IBMQJob performs validation during the constructor. the following lines does not # skip validation but run as is. from qiskit.providers.ibmq.ibmqjob import IBMQJob job = IBMQJob(backend, None, backend._api, qobj=qobj) job._future = job._executor.submit(job._submit_callback) else: logger.info( "Can't skip qobj validation for the third-party provider.") job = backend.run(qobj, **backend_options, **noise_config) return job else: job = backend.run(qobj, **backend_options, **noise_config) return job
def run_on_backend(backend, qobj, backend_options=None, noise_config=None, skip_qobj_validation=False): if skip_qobj_validation: job_id = str(uuid.uuid4()) if is_simulator_backend(backend): if is_aer_provider(backend): job = backend.run(qobj, **backend_options, **noise_config) else: job = SimulatorsJob(backend, job_id, backend._run_job, qobj) job._future = job._executor.submit(job._fn, job._job_id, job._qobj) elif is_ibmq_provider(backend): job = IBMQJob(backend, None, backend._api, not is_simulator_backend(backend), qobj=qobj) job._future = job._executor.submit(job._fn, job._job_id, job._qobj) else: logger.info( "Can not skip qobj validation for the third-party provider.") job = backend.run(qobj, **backend_options, **noise_config) return job else: job = backend.run(qobj, **backend_options, **noise_config) return job
def run_on_backend(backend, qobj, backend_options=None, noise_config=None, skip_qobj_validation=False): if skip_qobj_validation: job_id = str(uuid.uuid4()) if backend.configuration().simulator: if type(backend.provider()).__name__ == 'AerProvider': from qiskit.providers.aer.aerjob import AerJob job = AerJob(backend, job_id, backend._run_job, qobj, backend_options, noise_config) job._future = job._executor.submit(job._fn, job._job_id, job._qobj, backend_options, noise_config) else: job = SimulatorsJob(backend, job_id, backend._run_job, qobj) job._future = job._executor.submit(job._fn, job._job_id, job._qobj) else: job = IBMQJob(backend, None, backend._api, not backend.configuration().simulator, qobj=qobj) job._future = job._executor.submit(job._fn, job._job_id, job._qobj) return job else: job = backend.run(qobj, **backend_options, **noise_config) return job
def _call_circuit(self, name, **kwargs): """Execute a Circuit. Args: name (str): name of the Circuit. **kwargs: parameters passed to the Circuit. Returns: Result: the result of executing the circuit. Raises: CircuitAvailabilityError: if Circuits are not available. CircuitSubmitError: if there was an error submitting the Circuit. CircuitResultError: if the result of the Circuit could not be returned. """ try: response = self.client.circuit_run(name=name, **kwargs) except RequestsApiError as ex: # Revise the original requests exception to intercept. response = ex.original_exception.response # Check for errors related to the submission. try: body = response.json() except ValueError: body = {} # Generic authorization or unavailable endpoint error. if response.status_code in (401, 404): raise CircuitAvailabilityError() from None if response.status_code == 400: # Hub permission error. if body.get('error', {}).get('code') == 'HUB_NOT_FOUND': raise CircuitAvailabilityError() from None # Generic error. if body.get('error', {}).get('code') == 'GENERIC_ERROR': raise CircuitAvailabilityError() from None # Handle the rest of the exceptions as unexpected. raise CircuitSubmitError(str(ex)) except Exception as ex: # Handle non-requests exception as unexpected. raise CircuitSubmitError(str(ex)) # Extra check for IBMQConnector code path. if 'error' in response: # Hub permission error. if response['error'].get('code') == 'HUB_NOT_FOUND': raise CircuitAvailabilityError() from None # Generic error. if response['error'].get('code') == 'GENERIC_ERROR': raise CircuitAvailabilityError() from None raise CircuitSubmitError(str(response)) # Create a Job for the circuit. try: job = IBMQJob(backend=None, job_id=response['id'], api=self.client, creation_date=response['creationDate'], api_status=response['status']) except Exception as ex: raise CircuitResultError(str(ex)) # Wait for the job to complete, explicitly checking for errors. job._wait_for_completion() if job.status() is JobStatus.ERROR: raise CircuitResultError('Job {} finished with an error'.format( job.job_id())) return job.result()
class TestIBMQJobStates(JobTestCase): """Test the states of an IBMQJob.""" def setUp(self): self._current_api = None self._current_qjob = None def test_unrecognized_status(self): job = self.run_with_api(UnknownStatusAPI()) with self.assertRaises(JobError): self.wait_for_initialization(job) def test_validating_job(self): job = self.run_with_api(ValidatingAPI()) self.wait_for_initialization(job) self.assertEqual(job.status(), JobStatus.VALIDATING) def test_error_while_creating_job(self): job = self.run_with_api(ErrorWhileCreatingAPI()) self.wait_for_initialization(job) self.assertEqual(job.status(), JobStatus.ERROR) def test_error_while_validating_job(self): job = self.run_with_api(ErrorWhileValidatingAPI()) self.wait_for_initialization(job) self.assertEqual(job.status(), JobStatus.VALIDATING) self._current_api.progress() self.assertEqual(job.status(), JobStatus.ERROR) def test_status_flow_for_non_queued_job(self): job = self.run_with_api(NonQueuedAPI()) self.wait_for_initialization(job) self.assertEqual(job.status(), JobStatus.RUNNING) self._current_api.progress() self.assertEqual(job.status(), JobStatus.DONE) def test_status_flow_for_queued_job(self): job = self.run_with_api(QueuedAPI()) self.wait_for_initialization(job) self.assertEqual(job.status(), JobStatus.QUEUED) self._current_api.progress() self.assertEqual(job.status(), JobStatus.RUNNING) self._current_api.progress() self.assertEqual(job.status(), JobStatus.DONE) def test_status_flow_for_cancellable_job(self): job = self.run_with_api(CancellableAPI()) self.wait_for_initialization(job) self.assertEqual(job.status(), JobStatus.RUNNING) can_cancel = job.cancel() self.assertTrue(can_cancel) self._current_api.progress() self.assertEqual(job.status(), JobStatus.CANCELLED) def test_status_flow_for_non_cancellable_job(self): job = self.run_with_api(NonCancellableAPI()) self.wait_for_initialization(job) self.assertEqual(job.status(), JobStatus.RUNNING) can_cancel = job.cancel() self.assertFalse(can_cancel) self._current_api.progress() self.assertEqual(job.status(), JobStatus.RUNNING) def test_status_flow_for_errored_cancellation(self): job = self.run_with_api(ErroredCancellationAPI()) self.wait_for_initialization(job) self.assertEqual(job.status(), JobStatus.RUNNING) can_cancel = job.cancel() self.assertFalse(can_cancel) self.assertEqual(job.status(), JobStatus.RUNNING) def test_status_flow_for_unable_to_run_valid_qobj(self): """Contrary to other tests, this one is expected to fail even for a non-job-related issue. If the API fails while sending a job, we don't get an id so we can not query for the job status.""" job = self.run_with_api(UnavailableRunAPI()) with self.assertRaises(JobError): self.wait_for_initialization(job) with self.assertRaises(JobError): job.status() def test_api_throws_temporarily_but_job_is_finished(self): job = self.run_with_api( ThrowingNonJobRelatedErrorAPI(errors_before_success=2)) # First time we query the server... with self.assertRaises(JobError): # The error happens inside wait_for_initialization, the first time # it calls to status() after INITIALIZING. self.wait_for_initialization(job) # Also an explicit second time... with self.assertRaises(JobError): job.status() # Now the API gets fixed and doesn't throw anymore. self.assertEqual(job.status(), JobStatus.DONE) def test_status_flow_for_unable_to_run_invalid_qobj(self): job = self.run_with_api(RejectingJobAPI()) self.wait_for_initialization(job) self.assertEqual(job.status(), JobStatus.ERROR) def test_error_while_running_job(self): job = self.run_with_api(ErrorWhileRunningAPI()) self.wait_for_initialization(job) self.assertEqual(job.status(), JobStatus.RUNNING) self._current_api.progress() self.assertEqual(job.status(), JobStatus.ERROR) self.assertIn('Error 1', job.error_message()) self.assertIn('Error 2', job.error_message()) def test_cancelled_result(self): job = self.run_with_api(CancellableAPI()) self.wait_for_initialization(job) job.cancel() self._current_api.progress() with self.assertRaises(JobError): _ = job.result() self.assertEqual(job.status(), JobStatus.CANCELLED) def test_errored_result(self): job = self.run_with_api(ThrowingGetJobAPI()) self.wait_for_initialization(job) with self.assertRaises(ApiError): job.result() def test_completed_result(self): job = self.run_with_api(NonQueuedAPI()) self.wait_for_initialization(job) self._current_api.progress() self.assertEqual(job.result().success, True) self.assertEqual(job.status(), JobStatus.DONE) def test_block_on_result_waiting_until_completed(self): from concurrent import futures job = self.run_with_api(NonQueuedAPI()) with futures.ThreadPoolExecutor() as executor: executor.submit(_auto_progress_api, self._current_api) result = job.result() self.assertEqual(result.success, True) self.assertEqual(job.status(), JobStatus.DONE) def test_block_on_result_waiting_until_cancelled(self): from concurrent.futures import ThreadPoolExecutor job = self.run_with_api(CancellableAPI()) with ThreadPoolExecutor() as executor: executor.submit(_auto_progress_api, self._current_api) with self.assertRaises(JobError): job.result() self.assertEqual(job.status(), JobStatus.CANCELLED) def test_block_on_result_waiting_until_exception(self): from concurrent.futures import ThreadPoolExecutor job = self.run_with_api(ThrowingAPI()) with ThreadPoolExecutor() as executor: executor.submit(_auto_progress_api, self._current_api) with self.assertRaises(JobError): job.result() def test_never_complete_result_with_timeout(self): job = self.run_with_api(NonQueuedAPI()) self.wait_for_initialization(job) with self.assertRaises(JobTimeoutError): job.result(timeout=0.2) def test_cancel_while_initializing_fails(self): job = self.run_with_api(CancellableAPI()) can_cancel = job.cancel() self.assertFalse(can_cancel) self.assertEqual(job.status(), JobStatus.INITIALIZING) def test_only_final_states_cause_detailed_request(self): from unittest import mock # The state ERROR_CREATING_JOB is only handled when running the job, # and not while checking the status, so it is not tested. all_state_apis = { 'COMPLETED': NonQueuedAPI, 'CANCELLED': CancellableAPI, 'ERROR_VALIDATING_JOB': ErrorWhileValidatingAPI, 'ERROR_RUNNING_JOB': ErrorWhileRunningAPI } for status, api in all_state_apis.items(): with self.subTest(status=status): job = self.run_with_api(api()) self.wait_for_initialization(job) with suppress(BaseFakeAPI.NoMoreStatesError): self._current_api.progress() with mock.patch.object(self._current_api, 'get_job', wraps=self._current_api.get_job): job.status() if ApiJobStatus(status) in API_JOB_FINAL_STATES: self.assertTrue(self._current_api.get_job.called) else: self.assertFalse(self._current_api.get_job.called) def run_with_api(self, api): """Creates a new ``IBMQJob`` running with the provided API object.""" backend = FakeRueschlikon() self._current_api = api self._current_qjob = IBMQJob(backend, None, api, qobj=new_fake_qobj()) self._current_qjob.submit() return self._current_qjob