From dd135982a11d21f3508e5730638ac124d359fe65 Mon Sep 17 00:00:00 2001 From: annkay108 Date: Fri, 16 May 2025 11:17:03 +0200 Subject: [PATCH 1/3] add basic skeleton for Pennylane Job Request class --- mqss_client/__init__.py | 3 ++- mqss_client/job.py | 18 ++++++++++++++++++ mqss_client/mqss_client.py | 20 +++++++++++++++++++- test/mqss_client_tests_base.py | 20 ++++++++++++++++++++ test/test_mqss_client_live.py | 7 +++++++ test/test_mqss_client_mock.py | 3 ++- 6 files changed, 68 insertions(+), 3 deletions(-) diff --git a/mqss_client/__init__.py b/mqss_client/__init__.py index 974202c..419cda4 100644 --- a/mqss_client/__init__.py +++ b/mqss_client/__init__.py @@ -1,6 +1,6 @@ """MQSS Client package""" -from .job import CircuitJobRequest, HamiltonianJobRequest, JobStatus, Result +from .job import CircuitJobRequest, HamiltonianJobRequest, JobStatus, Result, PennylaneJobRequest from .mqss_client import MQSSClient from .resource_info import ResourceInfo @@ -11,4 +11,5 @@ "HamiltonianJobRequest", "JobStatus", "Result", + "PennylaneJobRequest", ] diff --git a/mqss_client/job.py b/mqss_client/job.py index 7df49b0..bada28f 100644 --- a/mqss_client/job.py +++ b/mqss_client/job.py @@ -65,6 +65,24 @@ def to_json_dict(self) -> dict: "coefficients_str": self.coefficients_str, } +@dataclass +class PennylaneJobRequest(JobRequest): + """Class to hold Pennylane job information""" + resource_name: str + circuits: str + circuit_format: str + shots: int + no_modify: bool + + def to_json_dict(self) -> dict: + """Convert PennylaneJobRequest to JSON dictionary""" + return { + "resource_name": self.resource_name, + "circuits": self.circuits, + "circuit_format": self.circuit_format, + "shots": self.shots, + "no_modify": self.no_modify, + } @dataclass class Result: diff --git a/mqss_client/mqss_client.py b/mqss_client/mqss_client.py index a825a37..d650dba 100644 --- a/mqss_client/mqss_client.py +++ b/mqss_client/mqss_client.py @@ -8,7 +8,14 @@ from typing import Dict, Optional, Union from .hpc_client import HPCOffloadClient -from .job import CircuitJobRequest, HamiltonianJobRequest, JobRequest, JobStatus, Result +from .job import ( + CircuitJobRequest, + HamiltonianJobRequest, + JobRequest, + JobStatus, + Result, + PennylaneJobRequest, +) from .resource_info import ResourceInfo from .rest_client import RESTClient @@ -56,6 +63,11 @@ def submit_job(self, job_request: JobRequest) -> str: "hamiltonian_job", job_request.to_json_dict(), ) + elif isinstance(job_request, PennylaneJobRequest): + rsp_json = self.client.post( + "pennylane_job", + job_request.to_json_dict(), + ) else: raise ValueError("Invalid job request type") @@ -73,6 +85,8 @@ def cancel_job(self, uuid: str, job_type: JobRequest) -> None: self.client.delete(f"job/{uuid}") elif isinstance(job_type, HamiltonianJobRequest): self.client.delete(f"hamiltonian_job/{uuid}") + elif isinstance(job_type, PennylaneJobRequest): + self.client.delete(f"pennylane_job/{uuid}") else: raise ValueError("Invalid job request type") @@ -82,6 +96,8 @@ def job_status(self, uuid: str, job_type: JobRequest) -> JobStatus: rsp_json = self.client.get(f"job/{uuid}/status") elif isinstance(job_type, HamiltonianJobRequest): rsp_json = self.client.get(f"hamiltonian_job/{uuid}/status") + elif isinstance(job_type, PennylaneJobRequest): + rsp_json = self.client.get(f"pennylane_job/{uuid}/status") else: raise ValueError("Invalid job request type") @@ -98,6 +114,8 @@ def job_result(self, uuid: str, job_type: JobRequest) -> Optional[Result]: result_json = self.client.get(f"job/{uuid}/result") elif isinstance(job_type, HamiltonianJobRequest): result_json = self.client.get(f"hamiltonian_job/{uuid}/result") + elif isinstance(job_type, PennylaneJobRequest): + result_json = self.client.get(f"pennylane_job/{uuid}/result") else: raise ValueError("Invalid job request type") diff --git a/test/mqss_client_tests_base.py b/test/mqss_client_tests_base.py index 2000c96..6bf6c3b 100644 --- a/test/mqss_client_tests_base.py +++ b/test/mqss_client_tests_base.py @@ -7,6 +7,7 @@ MQSSClient, ResourceInfo, Result, + PennylaneJobRequest, ) from .config import CURRENT_RESOURCES, TOKEN, URL, get_qasm @@ -43,6 +44,16 @@ def hamiltonian_job_request(resource_name): coefficients_str=coefficients_str, ) +@pytest.fixture +def pennylane_job_request(resource_name): + """Fixture to create a pennylane job request""" + return PennylaneJobRequest( + resource_name=resource_name, + circuits=get_qasm(), + circuit_format="qasm", + shots=1000, + no_modify=False, + ) class BaseMQSSClientTests: """Base class for MQSS client tests.""" @@ -105,6 +116,15 @@ def test_submit_hamiltonian_job( assert job_id is not None client.cancel_job(job_id, hamiltonian_job_request) + + def test_submit_pennylane_job( + self, client: MQSSClient, pennylane_job_request + ) -> None: + """Test submitting a Pennylane job.""" + job_id = client.submit_job(pennylane_job_request) + assert job_id is not None + client.cancel_job(job_id, pennylane_job_request) + def test_job_status( self, client: MQSSClient, circuit_job_request, monkeypatch ) -> None: diff --git a/test/test_mqss_client_live.py b/test/test_mqss_client_live.py index 64be5f0..698cbce 100644 --- a/test/test_mqss_client_live.py +++ b/test/test_mqss_client_live.py @@ -58,6 +58,13 @@ def test_submit_hamiltonian_job( hamiltonian_job_request.resource_name = online_resource_name(client) return super().test_submit_hamiltonian_job(client, hamiltonian_job_request) + def test_submit_pennylane_job( + self, client: MQSSClient, pennylane_job_request + ) -> None: + """Test submitting a Pennylane job.""" + pennylane_job_request.resource_name = online_resource_name(client) + return super().test_submit_pennylane_job(client, pennylane_job_request) + def test_job_status( self, client: MQSSClient, circuit_job_request, monkeypatch ) -> None: diff --git a/test/test_mqss_client_mock.py b/test/test_mqss_client_mock.py index afec0f6..ac7f378 100644 --- a/test/test_mqss_client_mock.py +++ b/test/test_mqss_client_mock.py @@ -10,9 +10,10 @@ circuit_job_request, hamiltonian_job_request, resource_name, + pennylane_job_request, ) -__all__ = ["circuit_job_request", "hamiltonian_job_request", "resource_name"] +__all__ = ["circuit_job_request", "hamiltonian_job_request", "resource_name", "pennylane_job_request"] @pytest.mark.mock From 9f94a2faf987ff1f5209a27318068ae00556babd Mon Sep 17 00:00:00 2001 From: annkay108 Date: Tue, 20 May 2025 14:38:02 +0200 Subject: [PATCH 2/3] add the pennylane test --- mqss_client/job.py | 2 +- test/mocks.py | 10 +++++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/mqss_client/job.py b/mqss_client/job.py index bada28f..d6d7bce 100644 --- a/mqss_client/job.py +++ b/mqss_client/job.py @@ -78,7 +78,7 @@ def to_json_dict(self) -> dict: """Convert PennylaneJobRequest to JSON dictionary""" return { "resource_name": self.resource_name, - "circuits": self.circuits, + "circuit": self.circuits, "circuit_format": self.circuit_format, "shots": self.shots, "no_modify": self.no_modify, diff --git a/test/mocks.py b/test/mocks.py index 1684a33..c30d0a1 100644 --- a/test/mocks.py +++ b/test/mocks.py @@ -20,9 +20,11 @@ # For job endpoints "job": {"jobs": ["mock-uuid-12345"]}, "hamiltonian_job": {"jobs": ["mock-uuid-12345"]}, + "pennylane_job": {"jobs": ["mock-uuid-12345"]}, # Status endpoints "job/mock-uuid-12345/status": {"status": "PENDING"}, "hamiltonian_job/mock-uuid-12345/status": {"status": "PENDING"}, + "pennylane_job/mock-uuid-12345/status": {"status": "PENDING"}, # Result endpoints "job/mock-uuid-12345/result": { "result": '{"00": 500, "11": 500}', @@ -36,6 +38,12 @@ "timestamp_submitted": "2023-04-14 10:00:00.123456", "timestamp_scheduled": "2023-04-14 10:05:00.123456", }, + "pennylane_job/mock-uuid-12345/result": { + "result": '{"00": 500, "11": 500}', + "timestamp_completed": "2023-04-14 10:15:30.123456", + "timestamp_submitted": "2023-04-14 10:00:00.123456", + "timestamp_scheduled": "2023-04-14 10:05:00.123456", + }, } @@ -63,7 +71,7 @@ def mock_receive(queue_name): method = message_data.get("method", "") # Handle POST requests for job creation - if (request_path in ["job", "hamiltonian_job"]) and method == "POST": + if (request_path in ["job", "hamiltonian_job","pennylane_job"]) and method == "POST": return json.dumps({"uuid": "mock-uuid-12345"}) # Handle GET requests using the shared data From c60743634debd7861c8067e33bbfc4b3077b2f27 Mon Sep 17 00:00:00 2001 From: annkay108 Date: Tue, 20 May 2025 14:59:25 +0200 Subject: [PATCH 3/3] pre-commit fixes --- mqss_client/__init__.py | 8 +++++++- mqss_client/job.py | 3 +++ mqss_client/mqss_client.py | 2 +- test/mocks.py | 6 ++++-- test/mqss_client_tests_base.py | 5 +++-- test/test_mqss_client_live.py | 2 +- test/test_mqss_client_mock.py | 9 +++++++-- 7 files changed, 26 insertions(+), 9 deletions(-) diff --git a/mqss_client/__init__.py b/mqss_client/__init__.py index 419cda4..851ac84 100644 --- a/mqss_client/__init__.py +++ b/mqss_client/__init__.py @@ -1,6 +1,12 @@ """MQSS Client package""" -from .job import CircuitJobRequest, HamiltonianJobRequest, JobStatus, Result, PennylaneJobRequest +from .job import ( + CircuitJobRequest, + HamiltonianJobRequest, + JobStatus, + PennylaneJobRequest, + Result, +) from .mqss_client import MQSSClient from .resource_info import ResourceInfo diff --git a/mqss_client/job.py b/mqss_client/job.py index d6d7bce..171d31d 100644 --- a/mqss_client/job.py +++ b/mqss_client/job.py @@ -65,9 +65,11 @@ def to_json_dict(self) -> dict: "coefficients_str": self.coefficients_str, } + @dataclass class PennylaneJobRequest(JobRequest): """Class to hold Pennylane job information""" + resource_name: str circuits: str circuit_format: str @@ -84,6 +86,7 @@ def to_json_dict(self) -> dict: "no_modify": self.no_modify, } + @dataclass class Result: """Result Class to hold counts""" diff --git a/mqss_client/mqss_client.py b/mqss_client/mqss_client.py index d650dba..8a4089d 100644 --- a/mqss_client/mqss_client.py +++ b/mqss_client/mqss_client.py @@ -13,8 +13,8 @@ HamiltonianJobRequest, JobRequest, JobStatus, - Result, PennylaneJobRequest, + Result, ) from .resource_info import ResourceInfo from .rest_client import RESTClient diff --git a/test/mocks.py b/test/mocks.py index c30d0a1..c5a337f 100644 --- a/test/mocks.py +++ b/test/mocks.py @@ -38,7 +38,7 @@ "timestamp_submitted": "2023-04-14 10:00:00.123456", "timestamp_scheduled": "2023-04-14 10:05:00.123456", }, - "pennylane_job/mock-uuid-12345/result": { + "pennylane_job/mock-uuid-12345/result": { "result": '{"00": 500, "11": 500}', "timestamp_completed": "2023-04-14 10:15:30.123456", "timestamp_submitted": "2023-04-14 10:00:00.123456", @@ -71,7 +71,9 @@ def mock_receive(queue_name): method = message_data.get("method", "") # Handle POST requests for job creation - if (request_path in ["job", "hamiltonian_job","pennylane_job"]) and method == "POST": + if ( + request_path in ["job", "hamiltonian_job", "pennylane_job"] + ) and method == "POST": return json.dumps({"uuid": "mock-uuid-12345"}) # Handle GET requests using the shared data diff --git a/test/mqss_client_tests_base.py b/test/mqss_client_tests_base.py index 6bf6c3b..360972b 100644 --- a/test/mqss_client_tests_base.py +++ b/test/mqss_client_tests_base.py @@ -5,9 +5,9 @@ HamiltonianJobRequest, JobStatus, MQSSClient, + PennylaneJobRequest, ResourceInfo, Result, - PennylaneJobRequest, ) from .config import CURRENT_RESOURCES, TOKEN, URL, get_qasm @@ -44,6 +44,7 @@ def hamiltonian_job_request(resource_name): coefficients_str=coefficients_str, ) + @pytest.fixture def pennylane_job_request(resource_name): """Fixture to create a pennylane job request""" @@ -55,6 +56,7 @@ def pennylane_job_request(resource_name): no_modify=False, ) + class BaseMQSSClientTests: """Base class for MQSS client tests.""" @@ -116,7 +118,6 @@ def test_submit_hamiltonian_job( assert job_id is not None client.cancel_job(job_id, hamiltonian_job_request) - def test_submit_pennylane_job( self, client: MQSSClient, pennylane_job_request ) -> None: diff --git a/test/test_mqss_client_live.py b/test/test_mqss_client_live.py index 698cbce..11e67dd 100644 --- a/test/test_mqss_client_live.py +++ b/test/test_mqss_client_live.py @@ -64,7 +64,7 @@ def test_submit_pennylane_job( """Test submitting a Pennylane job.""" pennylane_job_request.resource_name = online_resource_name(client) return super().test_submit_pennylane_job(client, pennylane_job_request) - + def test_job_status( self, client: MQSSClient, circuit_job_request, monkeypatch ) -> None: diff --git a/test/test_mqss_client_mock.py b/test/test_mqss_client_mock.py index ac7f378..2d36fd9 100644 --- a/test/test_mqss_client_mock.py +++ b/test/test_mqss_client_mock.py @@ -9,11 +9,16 @@ BaseMQSSClientTests, circuit_job_request, hamiltonian_job_request, - resource_name, pennylane_job_request, + resource_name, ) -__all__ = ["circuit_job_request", "hamiltonian_job_request", "resource_name", "pennylane_job_request"] +__all__ = [ + "circuit_job_request", + "hamiltonian_job_request", + "resource_name", + "pennylane_job_request", +] @pytest.mark.mock