iqm-client 25.2.0__py3-none-any.whl → 25.4.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -130,7 +130,8 @@ class TokenManager:
130
130
  )
131
131
  else:
132
132
  raise ClientConfigurationError(
133
- f"Invalid combination of authentication parameters specified: {list(auth_parameters)}",
133
+ f"""Invalid combination of authentication parameters specified: {list(auth_parameters)},
134
+ Use either ['token'] or ['username', 'password'].""",
134
135
  )
135
136
 
136
137
  def get_bearer_token(self, retries: int = 1) -> str | None:
@@ -170,6 +170,7 @@ class IQMClient:
170
170
  *,
171
171
  timeout: float,
172
172
  retry: bool = False,
173
+ allow_errors: bool = False,
173
174
  ) -> requests.Response:
174
175
  """Make a HTTP GET request to an IQM server endpoint.
175
176
 
@@ -180,6 +181,7 @@ class IQMClient:
180
181
  endpoint_args: Arguments for the endpoint.
181
182
  timeout: HTTP request timeout (in seconds).
182
183
  retry: Iff True, keep trying if you get a 502 error.
184
+ allow_errors: Iff true, don't raise exceptions for error responses.
183
185
 
184
186
  Returns:
185
187
  HTTP response to the request.
@@ -199,9 +201,10 @@ class IQMClient:
199
201
  )
200
202
 
201
203
  response = self._retry_request_on_error(request) if retry else request()
202
- self._check_not_found_error(response)
203
- self._check_authentication_errors(response)
204
- response.raise_for_status()
204
+ if not allow_errors:
205
+ self._check_not_found_error(response)
206
+ self._check_authentication_errors(response)
207
+ response.raise_for_status()
205
208
  return response
206
209
 
207
210
  def _deserialize_response(
@@ -672,91 +675,60 @@ class IQMClient:
672
675
  )
673
676
  status = status_response.json()
674
677
  if Status(status["status"]) not in Status.terminal_statuses():
675
- return RunResult.from_dict(
676
- {
677
- "measurements": [],
678
- "status": status["status"],
679
- "message": "",
680
- "metadata": {
681
- "calibration_set_id": None,
682
- "circuits_batch": [],
683
- "parameters": None,
684
- "timestamps": {},
685
- },
686
- }
687
- )
678
+ return RunResult.from_dict({"status": status["status"], "metadata": {}})
688
679
 
689
- result = self._retry_request_on_error(
690
- lambda: requests.get(
691
- self._api.url(APIEndpoint.GET_JOB_RESULT, str(job_id)),
692
- headers=self._default_headers(),
693
- timeout=timeout_secs,
694
- )
695
- )
696
- if result.status_code != 404:
697
- result.raise_for_status()
698
- measurements = [] if result.status_code == 404 else result.json()
699
- request_parameters = (
700
- {}
701
- if result.status_code == 404
702
- else requests.get(
703
- self._api.url(APIEndpoint.GET_JOB_REQUEST_PARAMETERS, str(job_id)),
704
- headers=self._default_headers(),
705
- timeout=timeout_secs,
706
- ).json()
707
- )
708
- calibration_set_id = (
709
- None
710
- if result.status_code == 404
711
- else requests.get(
712
- self._api.url(APIEndpoint.GET_JOB_CALIBRATION_SET_ID, str(job_id)),
713
- headers=self._default_headers(),
714
- timeout=timeout_secs,
715
- ).json()
716
- )
717
- circuits_batch = (
718
- []
719
- if result.status_code == 404
720
- else requests.get(
721
- self._api.url(APIEndpoint.GET_JOB_CIRCUITS_BATCH, str(job_id)),
722
- headers=self._default_headers(),
723
- timeout=timeout_secs,
724
- ).json()
680
+ result = self._get_request(
681
+ APIEndpoint.GET_JOB_RESULT, (str(job_id),), timeout=timeout_secs, retry=True, allow_errors=True
725
682
  )
726
- timeline = (
727
- []
728
- if result.status_code == 404
729
- else requests.get(
730
- self._api.url(APIEndpoint.GET_JOB_TIMELINE, str(job_id)),
731
- headers=self._default_headers(),
732
- timeout=timeout_secs,
733
- ).json()
734
- )
735
- error_message_response = requests.get(
736
- self._api.url(APIEndpoint.GET_JOB_ERROR_LOG, str(job_id)),
737
- headers=self._default_headers(),
738
- timeout=timeout_secs,
683
+
684
+ error_log_response = self._get_request(
685
+ APIEndpoint.GET_JOB_ERROR_LOG, (str(job_id),), timeout=timeout_secs, allow_errors=True
739
686
  )
740
- error_message = error_message_response.text if error_message_response.status_code == 200 else None
687
+ if error_log_response.status_code == 200:
688
+ error_log = error_log_response.json()
689
+ if isinstance(error_log, dict) and "user_error_message" in error_log:
690
+ error_message = error_log["user_error_message"]
691
+ else:
692
+ # backwards compatibility for older error_log format
693
+ # TODO: remove when not needed anymore
694
+ error_message = error_log_response.text
695
+ else:
696
+ error_message = None
697
+
698
+ if result.status_code == 404:
699
+ return RunResult.from_dict({"status": status["status"], "message": error_message, "metadata": {}})
700
+ else:
701
+ result.raise_for_status()
702
+
703
+ measurements = result.json()
704
+ request_parameters = self._get_request(
705
+ APIEndpoint.GET_JOB_REQUEST_PARAMETERS, (str(job_id),), timeout=timeout_secs, allow_errors=True
706
+ ).json()
707
+ calibration_set_id = self._get_request(
708
+ APIEndpoint.GET_JOB_CALIBRATION_SET_ID, (str(job_id),), timeout=timeout_secs, allow_errors=True
709
+ ).json()
710
+ circuits_batch = self._get_request(
711
+ APIEndpoint.GET_JOB_CIRCUITS_BATCH, (str(job_id),), timeout=timeout_secs, allow_errors=True
712
+ ).json()
713
+ timeline = self._get_request(
714
+ APIEndpoint.GET_JOB_TIMELINE, (str(job_id),), timeout=timeout_secs, allow_errors=True
715
+ ).json()
716
+
741
717
  return RunResult.from_dict(
742
718
  {
743
719
  "measurements": measurements,
744
720
  "status": status["status"],
745
721
  "message": error_message,
746
722
  "metadata": {
747
- "`": calibration_set_id,
723
+ "calibration_set_id": calibration_set_id,
748
724
  "circuits_batch": circuits_batch,
749
- "parameters": (
750
- None
751
- if result.status_code == 404
752
- else {
753
- "shots": request_parameters["shots"],
754
- "max_circuit_duration_over_t2": request_parameters["max_circuit_duration_over_t2"],
755
- "heralding_mode": request_parameters["heralding_mode"],
756
- "move_validation_mode": request_parameters["move_validation_mode"],
757
- "move_gate_frame_tracking_mode": request_parameters["move_gate_frame_tracking_mode"],
758
- }
759
- ),
725
+ "parameters": {
726
+ "shots": request_parameters["shots"],
727
+ "max_circuit_duration_over_t2": request_parameters["max_circuit_duration_over_t2"],
728
+ "heralding_mode": request_parameters["heralding_mode"],
729
+ "move_validation_mode": request_parameters["move_validation_mode"],
730
+ "move_gate_frame_tracking_mode": request_parameters["move_gate_frame_tracking_mode"],
731
+ },
760
732
  "timestamps": {datapoint["status"]: datapoint["timestamp"] for datapoint in timeline},
761
733
  },
762
734
  }
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: iqm-client
3
- Version: 25.2.0
3
+ Version: 25.4.0
4
4
  Summary: Client library for accessing an IQM quantum computer
5
5
  Author-email: IQM Finland Oy <developers@meetiqm.com>
6
6
  License: Apache License
@@ -19,9 +19,9 @@ iqm/cirq_iqm/examples/demo_iqm_execution.py,sha256=6NTEMbrWInA5kW44ajzEam3PBITCO
19
19
  iqm/cirq_iqm/examples/usage.ipynb,sha256=Kyfyu_MwqzTavHVNjgrWJo1tZPeJwTw7ExcU0MFYNRk,34208
20
20
  iqm/iqm_client/__init__.py,sha256=D-8W54EcQIxk_1JZo_86GYlR1YitHhPIiFwwLJ2IfGE,1411
21
21
  iqm/iqm_client/api.py,sha256=V57vslYSn5g1IgXWtWuxp3hD1DbY18dKUexRdxEuX78,8268
22
- iqm/iqm_client/authentication.py,sha256=Zbc5DpTwrcwNePKyZ_7KAFxwQFSVyZelQR_CWRCmlME,12187
22
+ iqm/iqm_client/authentication.py,sha256=4MO7VRIH1cIkjidIDqGfnemvc04UHEAfs-sZWXwBcLw,12258
23
23
  iqm/iqm_client/errors.py,sha256=ty2P-sg80zlAoL3_kC3PlprgDUv4PI-KFhmmxaaapS0,1429
24
- iqm/iqm_client/iqm_client.py,sha256=w6jhi70MorKMCiASu706Y_PORCSE_3R-F_h8q5bugnw,50647
24
+ iqm/iqm_client/iqm_client.py,sha256=SFImZk5DrAq51hr2G5sk242mO-8LYz-Mlc6Rc_JIuZE,50019
25
25
  iqm/iqm_client/models.py,sha256=YjlerNleeE1kOmzRsux-o02h7XSqv0u0KQEERufdxKk,50302
26
26
  iqm/iqm_client/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
27
27
  iqm/iqm_client/transpile.py,sha256=-iIZaxaTaQLy6pMkRG15VN8X1ZE_iNhX3pjsNjqg6P8,36935
@@ -56,10 +56,10 @@ iqm/qiskit_iqm/fake_backends/fake_apollo.py,sha256=eT2vd3kQBi1rrvxCpePymBCfFK84d
56
56
  iqm/qiskit_iqm/fake_backends/fake_deneb.py,sha256=RzQXmLXmBARDiMKVxk5Aw9fVbc6IYlW0A5jibk9iYD0,3156
57
57
  iqm/qiskit_iqm/fake_backends/fake_garnet.py,sha256=GI0xafTCj1Um09qVuccO6GPOGBm6ygul_O40Wu220Ys,5555
58
58
  iqm/qiskit_iqm/fake_backends/iqm_fake_backend.py,sha256=wJtfsxjPYbDKmzaz5R4AuaXvvPHa21WyPtRgNctL9eY,16785
59
- iqm_client-25.2.0.dist-info/AUTHORS.rst,sha256=qsxeK5A3-B_xK3hNbhFHEIkoHNpo7sdzYyRTs7Bdtm8,795
60
- iqm_client-25.2.0.dist-info/LICENSE.txt,sha256=2DXrmQtVVUV9Fc9RBFJidMiTEaQlG2oAtlC9PMrEwTk,11333
61
- iqm_client-25.2.0.dist-info/METADATA,sha256=XOVnYXYoVM8N1Nld_jDXAVELROOcY-DyFcgcTAGz7W0,17079
62
- iqm_client-25.2.0.dist-info/WHEEL,sha256=y4mX-SOX4fYIkonsAGA5N0Oy-8_gI4FXw5HNI1xqvWg,91
63
- iqm_client-25.2.0.dist-info/entry_points.txt,sha256=Kk2qfRwk8vbIJ7qCAvmaUogfRRn6t92_hBFhe6kqAE4,1317
64
- iqm_client-25.2.0.dist-info/top_level.txt,sha256=NB4XRfyDS6_wG9gMsyX-9LTU7kWnTQxNvkbzIxGv3-c,4
65
- iqm_client-25.2.0.dist-info/RECORD,,
59
+ iqm_client-25.4.0.dist-info/AUTHORS.rst,sha256=qsxeK5A3-B_xK3hNbhFHEIkoHNpo7sdzYyRTs7Bdtm8,795
60
+ iqm_client-25.4.0.dist-info/LICENSE.txt,sha256=2DXrmQtVVUV9Fc9RBFJidMiTEaQlG2oAtlC9PMrEwTk,11333
61
+ iqm_client-25.4.0.dist-info/METADATA,sha256=Ipu01b2XtcWWZ5KE9rMipahHIUR5vvBxgSfYHjrCvaA,17079
62
+ iqm_client-25.4.0.dist-info/WHEEL,sha256=y4mX-SOX4fYIkonsAGA5N0Oy-8_gI4FXw5HNI1xqvWg,91
63
+ iqm_client-25.4.0.dist-info/entry_points.txt,sha256=Kk2qfRwk8vbIJ7qCAvmaUogfRRn6t92_hBFhe6kqAE4,1317
64
+ iqm_client-25.4.0.dist-info/top_level.txt,sha256=NB4XRfyDS6_wG9gMsyX-9LTU7kWnTQxNvkbzIxGv3-c,4
65
+ iqm_client-25.4.0.dist-info/RECORD,,