diff --git a/azure-quantum/azure/quantum/cirq/job.py b/azure-quantum/azure/quantum/cirq/job.py index 363a03c8..6f513223 100644 --- a/azure-quantum/azure/quantum/cirq/job.py +++ b/azure-quantum/azure/quantum/cirq/job.py @@ -150,7 +150,7 @@ def cancel(self): def delete(self): """Delete the given job.""" - self._azure_job.workspace.cancel_job(self._azure_job) + self._azure_job.workspace.delete_job(self._azure_job) def __str__(self) -> str: return f"azure.quantum.cirq.Job(job_id={self.job_id()})" diff --git a/azure-quantum/azure/quantum/cirq/targets/ionq.py b/azure-quantum/azure/quantum/cirq/targets/ionq.py index 8c03bca0..baddf6fd 100644 --- a/azure-quantum/azure/quantum/cirq/targets/ionq.py +++ b/azure-quantum/azure/quantum/cirq/targets/ionq.py @@ -77,7 +77,7 @@ def cancel_job(self, job_id: str): def delete_job(self, job_id: str): azure_job = self._workspace.get_job(job_id) - self._workspace.cancel_job(azure_job) + self._workspace.delete_job(azure_job) def get_results( self, job_id: str, sharpen: Optional[bool] = None, extra_query_params: Optional[dict] = None diff --git a/azure-quantum/azure/quantum/job/job.py b/azure-quantum/azure/quantum/job/job.py index 5ce57b9e..9ad0b957 100644 --- a/azure-quantum/azure/quantum/job/job.py +++ b/azure-quantum/azure/quantum/job/job.py @@ -55,6 +55,10 @@ def submit(self): def refresh(self): """Refreshes the Job's details by querying the workspace.""" self.details = self.workspace.get_job(self.id).details + + def delete(self): + """Delete the given job.""" + self.workspace.delete_job(self) def has_completed(self) -> bool: """Check if the job has completed.""" diff --git a/azure-quantum/azure/quantum/qiskit/job.py b/azure-quantum/azure/quantum/qiskit/job.py index e04a64bd..efc23cf7 100644 --- a/azure-quantum/azure/quantum/qiskit/job.py +++ b/azure-quantum/azure/quantum/qiskit/job.py @@ -108,6 +108,10 @@ def cancel(self): """Attempt to cancel the job.""" self._workspace.cancel_job(self._azure_job) + def delete(self): + """Delete the job.""" + self._workspace.delete_job(self._azure_job) + def status(self): """Return the status of the job, among the values of ``JobStatus``.""" self._azure_job.refresh() diff --git a/azure-quantum/azure/quantum/workspace.py b/azure-quantum/azure/quantum/workspace.py index a32ea86f..f7b37f6e 100644 --- a/azure-quantum/azure/quantum/workspace.py +++ b/azure-quantum/azure/quantum/workspace.py @@ -464,6 +464,18 @@ def cancel_job(self, job: Job) -> Job: job.id) return Job(self, details) + def delete_job(self, job: Job) -> None: + """Deletes a job. + :param job: + Job to delete. + """ + client = self._get_jobs_client() + client.delete( + self.subscription_id, + self.resource_group, + self.name, + job.details.id) + def get_job(self, job_id: str) -> Job: """ Returns the job corresponding to the given id. diff --git a/azure-quantum/tests/mock_client.py b/azure-quantum/tests/mock_client.py index cf94bb36..6a815d57 100644 --- a/azure-quantum/tests/mock_client.py +++ b/azure-quantum/tests/mock_client.py @@ -203,7 +203,7 @@ def delete( ) -> None: for jd in self._store: if jd.id == job_id: - jd.status = "Cancelled" + self._store.remove(jd) return None raise KeyError(job_id) diff --git a/azure-quantum/tests/test_workspace.py b/azure-quantum/tests/test_workspace.py index da1e9c38..993110dc 100644 --- a/azure-quantum/tests/test_workspace.py +++ b/azure-quantum/tests/test_workspace.py @@ -3,6 +3,7 @@ # Licensed under the MIT License. ## +import pytest import os from unittest import mock from azure.quantum.job.job import Job @@ -384,6 +385,59 @@ def test_workspace_cancel_job_success(): assert result.details.status == "Cancelled" assert result.id == job_id +def test_workspace_delete_job_success(): + ws = WorkspaceMock( + subscription_id=SUBSCRIPTION_ID, + resource_group=RESOURCE_GROUP, + name=WORKSPACE + ) + + job_id = "test-delete-success" + + details = JobDetails( + id=job_id, + name=job_id, + container_uri="http://example.com/container", + input_data_format="microsoft.resource-estimate.v2", + provider_id="ionq", + target="ionq.simulator", + status="Executing" + ) + + ws._client.services.jobs._store.append(details) + + job = Job(ws, details) + + ws.delete_job(job) + + with pytest.raises(KeyError): + ws.get_job(job_id) + +def test_job_delete_success(): + ws = WorkspaceMock( + subscription_id=SUBSCRIPTION_ID, + resource_group=RESOURCE_GROUP, + name=WORKSPACE, + ) + + job_id = "test-job-delete-success" + details = JobDetails( + id=job_id, + name=f"job-{job_id}", + container_uri="https://example.com/container", + input_data_format="microsoft.resource-estimates.v2", + provider_id="ionq", + target="ionq.simulator", + status="Executing", + ) + ws._client.services.jobs._store.append(details) + + job = Job(ws, details) + job.delete() + + with pytest.raises(KeyError): + ws.get_job(job_id) + def test_workspace_user_agent_appid(): app_id = "MyEnvVarAppId"