iqm-station-control-client 11.1.0__py3-none-any.whl → 11.2.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.
@@ -31,14 +31,20 @@ from iqm.station_control.interface.models import (
31
31
  ObservationUpdate,
32
32
  RunLite,
33
33
  SequenceMetadataData,
34
+ StaticQuantumArchitecture,
34
35
  )
35
36
  from iqm.station_control.interface.pydantic_base import PydanticBase
36
37
 
37
38
  T = TypeVar("T")
38
39
 
39
40
 
40
- class ResponseWithMeta(PydanticBase, Generic[T]):
41
- """Class used for query endpoints to return metadata in addition to the returned items."""
41
+ class ListWithMetaResponse(PydanticBase, Generic[T]):
42
+ """Class used for list endpoints to envelope the items to a dict with additional metadata.
43
+
44
+ This should be used only in REST API communication (JSON). For Python users,
45
+ this model should be deserialized to :class:`iqm.pulse.ListWithMeta`:,
46
+ which behaves like a standard list.
47
+ """
42
48
 
43
49
  items: list[T]
44
50
  meta: Meta | None = None
@@ -96,5 +102,9 @@ class SequenceMetadataDataList(ListModel):
96
102
  root: list[SequenceMetadataData]
97
103
 
98
104
 
105
+ class StaticQuantumArchitectureList(ListModel):
106
+ root: list[StaticQuantumArchitecture]
107
+
108
+
99
109
  class RunLiteList(ListModel):
100
110
  root: list[RunLite]
@@ -44,12 +44,12 @@ from iqm.station_control.client.list_models import (
44
44
  DutFieldDataList,
45
45
  DutList,
46
46
  ListModel,
47
+ ListWithMetaResponse,
47
48
  ObservationDataList,
48
49
  ObservationDefinitionList,
49
50
  ObservationLiteList,
50
51
  ObservationSetDataList,
51
52
  ObservationUpdateList,
52
- ResponseWithMeta,
53
53
  RunLiteList,
54
54
  SequenceMetadataDataList,
55
55
  )
@@ -181,7 +181,7 @@ class _StationControlClientBase(StationControlInterface):
181
181
  if not response.ok:
182
182
  try:
183
183
  response_json = response.json()
184
- error_message = response_json.get("message") or response_json["detail"]
184
+ error_message = response_json.get("message")
185
185
  except (json.JSONDecodeError, KeyError):
186
186
  error_message = response.text
187
187
 
@@ -215,7 +215,7 @@ class _StationControlClientBase(StationControlInterface):
215
215
  headers["Content-Type"] = "application/json; charset=UTF-8"
216
216
  elif octets is not None:
217
217
  data = octets
218
- headers["Content-Type"] = "application/octet-stream"
218
+ headers["Content-Type"] = "application/protobuf"
219
219
 
220
220
  if self._enable_opentelemetry:
221
221
  parent_span_context = trace.set_span_in_context(trace.get_current_span())
@@ -310,7 +310,7 @@ class StationControlClient(_StationControlClientBase):
310
310
 
311
311
  @cache
312
312
  def get_channel_properties(self) -> dict[str, ChannelProperties]:
313
- headers = {"accept": "application/octet-stream"}
313
+ headers = {"accept": "application/protobuf"}
314
314
  response = self._send_request(requests.get, "channel-properties", headers=headers)
315
315
  decoded_dict = unpack_channel_properties(response.content)
316
316
  return decoded_dict
@@ -620,11 +620,11 @@ class StationControlClient(_StationControlClientBase):
620
620
  # This validates the provided data as a JSON string or bytes object.
621
621
  # If your incoming data is a JSON payload, this is generally considered faster.
622
622
  if list_with_meta:
623
- response_with_meta: ResponseWithMeta = ResponseWithMeta.model_validate_json(response.text)
624
- meta = response_with_meta.meta or Meta()
623
+ list_with_meta_response: ListWithMetaResponse = ListWithMetaResponse.model_validate_json(response.text)
624
+ meta = list_with_meta_response.meta or Meta()
625
625
  if meta and meta.errors:
626
626
  logger.warning("Errors in station control response:\n - %s", "\n - ".join(meta.errors))
627
- return ListWithMeta(model_class.model_validate(response_with_meta.items), meta=meta)
627
+ return ListWithMeta(model_class.model_validate(list_with_meta_response.items), meta=meta)
628
628
  model = model_class.model_validate_json(response.text)
629
629
  if isinstance(model, ListModel):
630
630
  return model.root
@@ -15,6 +15,7 @@
15
15
 
16
16
  from collections.abc import Iterable
17
17
  from dataclasses import dataclass
18
+ from typing import Generic, TypeVar
18
19
 
19
20
 
20
21
  @dataclass(kw_only=True)
@@ -28,9 +29,14 @@ class Meta:
28
29
  errors: list[str] | None = None
29
30
 
30
31
 
31
- class ListWithMeta(list):
32
+ T = TypeVar("T")
33
+
34
+
35
+ class ListWithMeta(list, Generic[T]):
32
36
  """Standard list extension holding optional metadata as well."""
33
37
 
34
- def __init__(self, items: Iterable, *, meta: Meta):
38
+ meta: Meta | None
39
+
40
+ def __init__(self, items: Iterable[T], *, meta: Meta | None = None):
35
41
  super().__init__(items)
36
42
  self.meta = meta
@@ -17,16 +17,6 @@ from iqm.station_control.interface.models.type_aliases import DutType
17
17
  from iqm.station_control.interface.pydantic_base import PydanticBase
18
18
 
19
19
 
20
- class DutData(PydanticBase):
21
- """Represents a Device Under Test, or DUT, for short."""
22
-
23
- label: str
24
- """DUT label of the device."""
25
- dut_type: DutType
26
- """String indicating the DUT type of the device
27
- Can be either 'chip' or 'twpa'."""
28
-
29
-
30
20
  class DutFieldData(PydanticBase):
31
21
  """A DUT field or path and its unit."""
32
22
 
@@ -34,3 +24,12 @@ class DutFieldData(PydanticBase):
34
24
  """DUT field or path."""
35
25
  unit: str
36
26
  """SI unit of the value. Empty string means the value is dimensionless."""
27
+
28
+
29
+ class DutData(PydanticBase):
30
+ """Represents a Device Under Test, or DUT, for short."""
31
+
32
+ label: str
33
+ """DUT label of the device."""
34
+ dut_type: DutType
35
+ """Type of the device."""
@@ -13,7 +13,10 @@
13
13
  # limitations under the License.
14
14
  """Static quantum architecture (SQA) related interface models."""
15
15
 
16
- from pydantic import Field
16
+ from typing import Any
17
+ import warnings
18
+
19
+ from pydantic import Field, model_validator
17
20
 
18
21
  from iqm.station_control.interface.pydantic_base import PydanticBase
19
22
 
@@ -24,6 +27,13 @@ class StaticQuantumArchitecture(PydanticBase):
24
27
  For example, the names of its components and the connections between them.
25
28
  """
26
29
 
30
+ # Optional *for now* since 2025-10-04 (backwards compatible)
31
+ dut_label: str | None = Field(
32
+ default=None,
33
+ json_schema_extra={"x-optional-deprecated": True},
34
+ )
35
+ """Identifies the QPU."""
36
+
27
37
  qubits: list[str] = Field(
28
38
  examples=[["QB1", "QB2"]],
29
39
  )
@@ -38,3 +48,14 @@ class StaticQuantumArchitecture(PydanticBase):
38
48
  examples=[[("QB1", "QB2"), ("QB1", "CR1")]],
39
49
  )
40
50
  """Components (qubits and computational resonators) connected by a coupler on the QPU, sorted."""
51
+
52
+ @model_validator(mode="before")
53
+ @classmethod
54
+ def _warn_missing_dut_label(cls, data: Any) -> Any:
55
+ if isinstance(data, dict) and "dut_label" not in data:
56
+ warnings.warn(
57
+ "Missing 'dut_label'. This field will become REQUIRED in a future release.",
58
+ DeprecationWarning,
59
+ stacklevel=2,
60
+ )
61
+ return data
@@ -13,7 +13,7 @@
13
13
  # limitations under the License.
14
14
  """Type hint aliases used in the station control interface."""
15
15
 
16
- from typing import Literal
16
+ from typing import Literal, TypeAlias
17
17
  from uuid import UUID
18
18
 
19
19
  import numpy as np
@@ -23,8 +23,8 @@ import numpy as np
23
23
  # and then deserialized back to UUID on the server side.
24
24
  StrUUID = str | UUID
25
25
 
26
- DutType = Literal["chip", "twpa"]
27
- GetObservationsMode = Literal["all_latest", "tags_and", "tags_or", "sequence"]
28
- SoftwareVersionSet = dict[str, str]
29
- Statuses = list[tuple[str, int, int]]
30
- SweepResults = dict[str, list[np.ndarray]]
26
+ DutType: TypeAlias = Literal["chip", "twpa"]
27
+ GetObservationsMode: TypeAlias = Literal["all_latest", "tags_and", "tags_or", "sequence"]
28
+ SoftwareVersionSet: TypeAlias = dict[str, str]
29
+ Statuses: TypeAlias = list[tuple[str, int, int]]
30
+ SweepResults: TypeAlias = dict[str, list[np.ndarray]]
@@ -18,6 +18,7 @@ from pydantic import BaseModel, ConfigDict
18
18
 
19
19
  class PydanticBase(BaseModel):
20
20
  """Pydantic base model to change the behaviour of pydantic globally.
21
+
21
22
  Note that setting model_config in child classes will merge the configs rather than override this one.
22
23
  https://docs.pydantic.dev/latest/concepts/config/#change-behaviour-globally
23
24
  """
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: iqm-station-control-client
3
- Version: 11.1.0
3
+ Version: 11.2.0
4
4
  Summary: Python client for communicating with Station Control Service
5
5
  Author-email: IQM Finland Oy <info@meetiqm.com>
6
6
  License: Apache License
@@ -214,7 +214,7 @@ Requires-Python: >=3.11
214
214
  Description-Content-Type: text/x-rst
215
215
  License-File: LICENSE.txt
216
216
  Requires-Dist: iqm-exa-common <28,>=27
217
- Requires-Dist: iqm-data-definitions <3.0,>=2.13
217
+ Requires-Dist: iqm-data-definitions <3.0,>=2.18
218
218
  Requires-Dist: opentelemetry-exporter-otlp <2.0,>=1.25.0
219
219
  Requires-Dist: protobuf <5.0,>=4.25.3
220
220
  Requires-Dist: types-protobuf
@@ -1,8 +1,8 @@
1
1
  iqm/station_control/client/__init__.py,sha256=1ND-AkIE9xLGIscH3WN44eyll9nlFhXeyCm-8EDFGQ4,942
2
- iqm/station_control/client/list_models.py,sha256=jpnmUqFvmzGxhq6fDBrV2crIgGNY5NfYqj5odpyWO-w,2524
2
+ iqm/station_control/client/list_models.py,sha256=oKwa5ukh0OIXJTxLmi0awJV6xTLVKyxxduAs88O8xIA,2856
3
3
  iqm/station_control/client/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
4
  iqm/station_control/client/qon.py,sha256=9URsapeqVXi2h6xX0BKpl2fYKKkwGicLN-isI_Mmh0s,27768
5
- iqm/station_control/client/station_control.py,sha256=XbRkDvKiRvNsCQmMZPe1tkBDYR57q9oYLRC2HHsIRKg,29089
5
+ iqm/station_control/client/station_control.py,sha256=z4acuGR1rP2vt2TwohQ_nlqeZWVG2iGblGnQT-jCJwc,29081
6
6
  iqm/station_control/client/utils.py,sha256=-6K4KgOgA4iyUCqX-w26JvFxlwlGBehGj4tIWCEbn74,3360
7
7
  iqm/station_control/client/iqm_server/__init__.py,sha256=nLsRHN1rnOKXwuzaq_liUpAYV3sis5jkyHccSdacV7U,624
8
8
  iqm/station_control/client/iqm_server/error.py,sha256=a8l7UTnzfbD8KDHP-uOve77S6LR1ai9uM_J_xHbLs0Y,1175
@@ -36,12 +36,12 @@ iqm/station_control/client/serializers/struct_serializer.py,sha256=7LSlrGVz0c-yi
36
36
  iqm/station_control/client/serializers/sweep_serializers.py,sha256=iFeBb4RFbHpVZifyduUypACSvulhkzdQIyG0gDoXOwM,5807
37
37
  iqm/station_control/client/serializers/task_serializers.py,sha256=mj5HWOolXLsqGaky7OYAWCW-BVp1RKN7vPtyiYpMaO8,3700
38
38
  iqm/station_control/interface/__init__.py,sha256=bBjhkiUSdwmx-CoNrT8pI4eGStI9RFUcW5CdpIRrd5k,785
39
- iqm/station_control/interface/list_with_meta.py,sha256=M8BacgBDjbf7yabNK-OHCJWrci5hewXA9vd8MrqrZts,1187
39
+ iqm/station_control/interface/list_with_meta.py,sha256=P8T83qIQvCssY-aWrvf3aT827PAw1f57oEasgZPyXKY,1294
40
40
  iqm/station_control/interface/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
41
- iqm/station_control/interface/pydantic_base.py,sha256=pQCa-8SRgBKMSwG-KyXA1HcIxE_qGMJt9g_eOGdZ31g,1303
41
+ iqm/station_control/interface/pydantic_base.py,sha256=IfGW2fErFYRmhC5gjT26ueSwtW2S4eBW5xZDe7lutDg,1304
42
42
  iqm/station_control/interface/station_control.py,sha256=5gtDouAQ13KnyXNQUcBrpKG9pZdjIsX6fLJU9bmYJxU,20433
43
43
  iqm/station_control/interface/models/__init__.py,sha256=BP9iIwHi0nw8CUzScXOsu8bhxnE_rRulOsRVO5L1hx0,1989
44
- iqm/station_control/interface/models/dut.py,sha256=Hc_0XllXeIPGWhHsY7PC_jMpi7swpqo3jQQEQVnF3AM,1216
44
+ iqm/station_control/interface/models/dut.py,sha256=Jp8rgi5e6ecDbU0fw9cgxn_9JczeTPkxYb7oIBv31ko,1155
45
45
  iqm/station_control/interface/models/dynamic_quantum_architecture.py,sha256=3YlI9e1XxdbkBzlOdxmzYTccJ8AJRnRSIp-JoBf8Yyw,4698
46
46
  iqm/station_control/interface/models/jobs.py,sha256=MGo0MOg-mTw3rF7vNCYNGAns6-eyl30ubqiEQWCFJ9c,6876
47
47
  iqm/station_control/interface/models/monitor.py,sha256=ItlgxtBup1hHg64uKeMKiFE7MaRRqSYdVRttsFD_XeU,1352
@@ -49,11 +49,11 @@ iqm/station_control/interface/models/observation.py,sha256=IblYdzJN88BNlyxUVR_dI
49
49
  iqm/station_control/interface/models/observation_set.py,sha256=y6uqslVF2kO1zREPE6EtrvG9ZVrLo0S2Sk7ZhRL8pks,3993
50
50
  iqm/station_control/interface/models/run.py,sha256=uEuAMryG-AjAIBTchftw94GpoSBE5SQK2qmlZZ4tq5k,4097
51
51
  iqm/station_control/interface/models/sequence.py,sha256=boWlMfP3woVgVObW3OaNbxsUV_qHYP1DA-oIBWj6XIo,2723
52
- iqm/station_control/interface/models/static_quantum_architecture.py,sha256=gsfJKlYsfZVEK3dqEKXkBSIHiY14DGwNbhPJdNHMtNM,1435
52
+ iqm/station_control/interface/models/static_quantum_architecture.py,sha256=kt_rCExRd6zyatWVJCmCSf-gYdbEFfij3DfM0wBrPHI,2103
53
53
  iqm/station_control/interface/models/sweep.py,sha256=HFoFIrKhlYmHIBfGltY2O9_J28OvkkZILRbDHuqR0wc,2509
54
- iqm/station_control/interface/models/type_aliases.py,sha256=StsUwqwPp1N9wh79w40C6eEp7OmQ8E5AnJX7w2mqTnQ,1153
55
- iqm_station_control_client-11.1.0.dist-info/LICENSE.txt,sha256=R6Q7eUrLyoCQgWYorQ8WJmVmWKYU3dxA3jYUp0wwQAw,11332
56
- iqm_station_control_client-11.1.0.dist-info/METADATA,sha256=dy48AOJf3w-rbZY9rQ1rUfMnoFiMI6EQbe1Qfe2JncQ,14107
57
- iqm_station_control_client-11.1.0.dist-info/WHEEL,sha256=y4mX-SOX4fYIkonsAGA5N0Oy-8_gI4FXw5HNI1xqvWg,91
58
- iqm_station_control_client-11.1.0.dist-info/top_level.txt,sha256=NB4XRfyDS6_wG9gMsyX-9LTU7kWnTQxNvkbzIxGv3-c,4
59
- iqm_station_control_client-11.1.0.dist-info/RECORD,,
54
+ iqm/station_control/interface/models/type_aliases.py,sha256=HbHXNbY8UJ9eqk8BiVmogF-jHrgrcJxrWtUq6atwSg4,1219
55
+ iqm_station_control_client-11.2.0.dist-info/LICENSE.txt,sha256=R6Q7eUrLyoCQgWYorQ8WJmVmWKYU3dxA3jYUp0wwQAw,11332
56
+ iqm_station_control_client-11.2.0.dist-info/METADATA,sha256=EHr3eHm6e0JFKzoEpdaMq1gXfdyAEPMcVAFIJjctcDk,14107
57
+ iqm_station_control_client-11.2.0.dist-info/WHEEL,sha256=y4mX-SOX4fYIkonsAGA5N0Oy-8_gI4FXw5HNI1xqvWg,91
58
+ iqm_station_control_client-11.2.0.dist-info/top_level.txt,sha256=NB4XRfyDS6_wG9gMsyX-9LTU7kWnTQxNvkbzIxGv3-c,4
59
+ iqm_station_control_client-11.2.0.dist-info/RECORD,,