iqm-exa-common 26.26.0__py3-none-any.whl → 26.28.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.
@@ -14,36 +14,36 @@
14
14
 
15
15
  """Pack and unpack parameters to protos and back."""
16
16
 
17
- import iqm.data_definitions.common.v1.parameter_pb2 as ppb
17
+ from iqm.data_definitions.common.v1.parameter_pb2 import Parameter as ppb_Parameter
18
18
 
19
19
  from exa.common.data.parameter import CollectionType, DataType, Parameter
20
20
 
21
21
  _COLLECTION_TYPES = {
22
- CollectionType.SCALAR: ppb.Parameter.CollectionType.COLLECTION_TYPE_SCALAR,
23
- CollectionType.LIST: ppb.Parameter.CollectionType.COLLECTION_TYPE_SEQUENCE,
24
- CollectionType.NDARRAY: ppb.Parameter.CollectionType.COLLECTION_TYPE_ARRAY,
22
+ CollectionType.SCALAR: ppb_Parameter.CollectionType.COLLECTION_TYPE_SCALAR,
23
+ CollectionType.LIST: ppb_Parameter.CollectionType.COLLECTION_TYPE_SEQUENCE,
24
+ CollectionType.NDARRAY: ppb_Parameter.CollectionType.COLLECTION_TYPE_ARRAY,
25
25
  }
26
26
  _collection_types_inv = {v: k for k, v in _COLLECTION_TYPES.items()}
27
27
 
28
28
  _DATA_TYPES = {
29
- DataType.ANYTHING: ppb.Parameter.DataType.DATA_TYPE_UNSPECIFIED,
30
- DataType.NUMBER: ppb.Parameter.DataType.DATA_TYPE_FLOAT64, # Deprecated
31
- DataType.STRING: ppb.Parameter.DataType.DATA_TYPE_STRING,
32
- DataType.COMPLEX: ppb.Parameter.DataType.DATA_TYPE_COMPLEX128,
33
- DataType.BOOLEAN: ppb.Parameter.DataType.DATA_TYPE_BOOL,
34
- DataType.INT: ppb.Parameter.DataType.DATA_TYPE_INT64,
35
- DataType.FLOAT: ppb.Parameter.DataType.DATA_TYPE_FLOAT64,
29
+ DataType.ANYTHING: ppb_Parameter.DataType.DATA_TYPE_UNSPECIFIED,
30
+ DataType.NUMBER: ppb_Parameter.DataType.DATA_TYPE_FLOAT64, # Deprecated
31
+ DataType.STRING: ppb_Parameter.DataType.DATA_TYPE_STRING,
32
+ DataType.COMPLEX: ppb_Parameter.DataType.DATA_TYPE_COMPLEX128,
33
+ DataType.BOOLEAN: ppb_Parameter.DataType.DATA_TYPE_BOOL,
34
+ DataType.INT: ppb_Parameter.DataType.DATA_TYPE_INT64,
35
+ DataType.FLOAT: ppb_Parameter.DataType.DATA_TYPE_FLOAT64,
36
36
  }
37
37
  _data_types_inv = {v: k for k, v in _DATA_TYPES.items() if k != DataType.NUMBER}
38
38
 
39
39
 
40
- def pack(parameter: Parameter) -> ppb.Parameter:
40
+ def pack(parameter: Parameter) -> ppb_Parameter:
41
41
  """Convert Parameter into protobuf representation."""
42
- return ppb.Parameter(
42
+ return ppb_Parameter(
43
43
  name=parameter.name,
44
44
  label=parameter.label,
45
45
  unit=parameter.unit,
46
- data_type=_DATA_TYPES.get(parameter.data_type, ppb.Parameter.DataType.DATA_TYPE_UNSPECIFIED),
46
+ data_type=_DATA_TYPES.get(parameter.data_type, ppb_Parameter.DataType.DATA_TYPE_UNSPECIFIED), # type: ignore[arg-type]
47
47
  collection_type=_COLLECTION_TYPES[parameter.collection_type],
48
48
  element_indices=parameter.element_indices,
49
49
  parent_name=parameter.parent_name,
@@ -51,21 +51,21 @@ def pack(parameter: Parameter) -> ppb.Parameter:
51
51
  )
52
52
 
53
53
 
54
- def unpack(proto: ppb.Parameter) -> Parameter:
54
+ def unpack(proto: ppb_Parameter) -> Parameter:
55
55
  """Convert protobuf representation into a Parameter."""
56
56
  if not proto.element_indices:
57
57
  return Parameter(
58
58
  name=proto.name,
59
59
  label=proto.label,
60
60
  unit=proto.unit,
61
- data_type=_data_types_inv.get(proto.data_type),
62
- collection_type=_collection_types_inv.get(proto.collection_type),
61
+ data_type=_data_types_inv.get(proto.data_type), # type: ignore[arg-type]
62
+ collection_type=_collection_types_inv.get(proto.collection_type), # type: ignore[arg-type]
63
63
  )
64
64
  return Parameter(
65
65
  name=proto.parent_name,
66
66
  label=proto.parent_label,
67
67
  unit=proto.unit,
68
- data_type=_data_types_inv.get(proto.data_type),
69
- collection_type=_collection_types_inv.get(proto.collection_type),
68
+ data_type=_data_types_inv.get(proto.data_type), # type: ignore[arg-type]
69
+ collection_type=_collection_types_inv.get(proto.collection_type), # type: ignore[arg-type]
70
70
  element_indices=list(proto.element_indices),
71
71
  )
@@ -14,11 +14,11 @@
14
14
 
15
15
  """Convert numpy arrays to protos and back."""
16
16
 
17
- import iqm.data_definitions.common.v1.data_types_pb2 as dpb
17
+ from iqm.data_definitions.common.v1.data_types_pb2 import Array as dpb_Array
18
18
  import numpy as np
19
19
 
20
20
 
21
- def pack(array: np.ndarray) -> dpb.Array:
21
+ def pack(array: np.ndarray) -> dpb_Array:
22
22
  """Packs a numeric numpy array into protobuf format.
23
23
 
24
24
  Args:
@@ -28,7 +28,7 @@ def pack(array: np.ndarray) -> dpb.Array:
28
28
  A protobuf instance that encapsulates `array`.
29
29
 
30
30
  """
31
- target = dpb.Array()
31
+ target = dpb_Array()
32
32
  target.shape.MergeFrom(array.shape)
33
33
  if not array.size: # MergeFrom throws with 0-sized iterables
34
34
  return target
@@ -54,7 +54,7 @@ def pack(array: np.ndarray) -> dpb.Array:
54
54
  return target
55
55
 
56
56
 
57
- def unpack(source: dpb.Array) -> np.ndarray:
57
+ def unpack(source: dpb_Array) -> np.ndarray:
58
58
  """Unpacks protobuf to array. Reverse operation of :func:`.pack`.
59
59
 
60
60
  Args:
@@ -16,13 +16,14 @@
16
16
 
17
17
  from collections.abc import Sequence
18
18
 
19
- import iqm.data_definitions.common.v1.data_types_pb2 as dpb
19
+ from iqm.data_definitions.common.v1.data_types_pb2 import Complex128 as dpb_Complex128
20
+ from iqm.data_definitions.common.v1.data_types_pb2 import Datum as dpb_Datum
20
21
  import numpy as np
21
22
 
22
23
  from exa.common.api.proto_serialization import array, sequence
23
24
 
24
25
 
25
- def pack(value: None | bool | str | int | float | complex | np.ndarray | Sequence) -> dpb.Datum:
26
+ def pack(value: None | bool | str | int | float | complex | np.ndarray | Sequence) -> dpb_Datum:
26
27
  """Packs a string, numerical value, or an array thereof into protobuf format.
27
28
 
28
29
  Supported data types are:
@@ -48,25 +49,25 @@ def pack(value: None | bool | str | int | float | complex | np.ndarray | Sequenc
48
49
  f"Encoding of numpy type '{type(value)}' is not supported. Cast the value into a native type first."
49
50
  )
50
51
  if value is None:
51
- return dpb.Datum(null_value=True)
52
+ return dpb_Datum(null_value=True)
52
53
  if isinstance(value, bool):
53
- return dpb.Datum(bool_value=value)
54
+ return dpb_Datum(bool_value=value)
54
55
  if isinstance(value, str):
55
- return dpb.Datum(string_value=value)
56
+ return dpb_Datum(string_value=value)
56
57
  if isinstance(value, int):
57
- return dpb.Datum(sint64_value=value)
58
+ return dpb_Datum(sint64_value=value)
58
59
  if isinstance(value, float):
59
- return dpb.Datum(float64_value=value)
60
+ return dpb_Datum(float64_value=value)
60
61
  if isinstance(value, complex):
61
- return dpb.Datum(complex128_value=dpb.Complex128(real=value.real, imag=value.imag))
62
+ return dpb_Datum(complex128_value=dpb_Complex128(real=value.real, imag=value.imag))
62
63
  if isinstance(value, np.ndarray):
63
- return dpb.Datum(array=array.pack(value))
64
+ return dpb_Datum(array=array.pack(value))
64
65
  if isinstance(value, Sequence):
65
- return dpb.Datum(sequence=sequence.pack(value))
66
+ return dpb_Datum(sequence=sequence.pack(value))
66
67
  raise TypeError(f"Encoding of type '{type(value)}' is not supported.")
67
68
 
68
69
 
69
- def unpack(source: dpb.Datum) -> None | str | bool | int | float | complex | np.ndarray | list:
70
+ def unpack(source: dpb_Datum) -> None | str | bool | int | float | complex | np.ndarray | list:
70
71
  """Unpacks a protobuf into a native Python type or a numpy array. Reverse operation of :func:`.pack`.
71
72
 
72
73
  Args:
@@ -122,19 +123,19 @@ def deserialize(source: bytes) -> None | str | bool | int | float | complex | np
122
123
  Deserialized data.
123
124
 
124
125
  """
125
- proto = dpb.Datum()
126
+ proto = dpb_Datum()
126
127
  proto.ParseFromString(source)
127
128
  return unpack(proto)
128
129
 
129
130
 
130
- def _pack_complex128(value: np.complex128 | complex, target: dpb.Complex128 | None = None) -> dpb.Complex128:
131
+ def _pack_complex128(value: np.complex128 | complex, target: dpb_Complex128 | None = None) -> dpb_Complex128:
131
132
  """Packs a numpy complex128 to the respective protobuf type."""
132
- target = target or dpb.Complex128()
133
+ target = target or dpb_Complex128()
133
134
  target.real = value.real
134
135
  target.imag = value.imag
135
136
  return target
136
137
 
137
138
 
138
- def _unpack_complex128_value(complex128_value: dpb.Complex128) -> complex:
139
+ def _unpack_complex128_value(complex128_value: dpb_Complex128) -> complex:
139
140
  """Unpack a protobuf to a native complex number."""
140
141
  return complex(complex128_value.real, complex128_value.imag)
@@ -14,7 +14,9 @@
14
14
 
15
15
  """Convert NdSweeps to protos and back."""
16
16
 
17
- import iqm.data_definitions.common.v1.sweep_pb2 as spb
17
+ from iqm.data_definitions.common.v1.sweep_pb2 import CartesianSweep as spb_CartesianSweep
18
+ from iqm.data_definitions.common.v1.sweep_pb2 import ParallelSweep as spb_ParallelSweep
19
+ from iqm.data_definitions.common.v1.sweep_pb2 import SingleParameterSweep as spb_SingleParameterSweep
18
20
 
19
21
  from exa.common.api.proto_serialization import sequence
20
22
  import exa.common.api.proto_serialization._parameter as param_proto
@@ -23,22 +25,22 @@ from exa.common.data.parameter import DataType, Parameter
23
25
  from exa.common.sweep.util import NdSweep
24
26
 
25
27
 
26
- def pack(nd_sweep: NdSweep, minimal: bool = True) -> spb.CartesianSweep:
28
+ def pack(nd_sweep: NdSweep, minimal: bool = True) -> spb_CartesianSweep:
27
29
  """Convert an NdSweep into protobuf representation.
28
30
 
29
31
  Note: The protobuf does not make any distinction between different types of Sweeps, so the type information is lost.
30
32
  """
31
33
  parallels = []
32
34
  for parallel in nd_sweep:
33
- parallel_proto = spb.ParallelSweep()
35
+ parallel_proto = spb_ParallelSweep()
34
36
  parallel_proto.single_parameter_sweeps.MergeFrom((_pack_single_sweep(sweep, minimal) for sweep in parallel))
35
37
  parallels.append(parallel_proto)
36
- proto = spb.CartesianSweep()
38
+ proto = spb_CartesianSweep()
37
39
  proto.parallel_sweeps.MergeFrom(reversed(parallels)) # In data-definitions, order is outermost loop first
38
40
  return proto
39
41
 
40
42
 
41
- def unpack(proto: spb.CartesianSweep) -> NdSweep:
43
+ def unpack(proto: spb_CartesianSweep) -> NdSweep:
42
44
  """Convert protobuf representation into a NdSweep. Reverse operation of :func:`.pack`."""
43
45
  nd_sweep = []
44
46
  for parallel_proto in reversed(proto.parallel_sweeps):
@@ -47,14 +49,14 @@ def unpack(proto: spb.CartesianSweep) -> NdSweep:
47
49
  return nd_sweep
48
50
 
49
51
 
50
- def _pack_single_sweep(sweep: Sweep, minimal: bool) -> spb.SingleParameterSweep:
51
- kwargs = {"parameter_name": sweep.parameter.name, "values": sequence.pack(sweep.data)}
52
+ def _pack_single_sweep(sweep: Sweep, minimal: bool) -> spb_SingleParameterSweep:
53
+ kwargs = {"parameter_name": sweep.parameter.name, "values": sequence.pack(sweep.data)} # type: ignore[arg-type]
52
54
  if not minimal:
53
55
  kwargs["parameter"] = param_proto.pack(sweep.parameter)
54
- return spb.SingleParameterSweep(**kwargs)
56
+ return spb_SingleParameterSweep(**kwargs)
55
57
 
56
58
 
57
- def _unpack_single_sweep(proto: spb.SingleParameterSweep) -> Sweep:
59
+ def _unpack_single_sweep(proto: spb_SingleParameterSweep) -> Sweep:
58
60
  sweep_values = sequence.unpack(proto.values)
59
61
  if proto.HasField("parameter"):
60
62
  parameter = param_proto.unpack(proto.parameter)
@@ -16,11 +16,11 @@
16
16
 
17
17
  from collections.abc import Sequence
18
18
 
19
- import iqm.data_definitions.common.v1.data_types_pb2 as dpb
19
+ from iqm.data_definitions.common.v1.data_types_pb2 import Sequence as dpb_Sequence
20
20
  import numpy as np
21
21
 
22
22
 
23
- def pack(values: Sequence) -> dpb.Sequence:
23
+ def pack(values: Sequence) -> dpb_Sequence:
24
24
  """Packs a sequence of native Python types into protobuf format.
25
25
 
26
26
  Args:
@@ -33,7 +33,7 @@ def pack(values: Sequence) -> dpb.Sequence:
33
33
  ValueError in case of unsupported value.
34
34
 
35
35
  """
36
- target = dpb.Sequence()
36
+ target = dpb_Sequence()
37
37
  if not values:
38
38
  return target
39
39
  dtype = type(values[0])
@@ -57,7 +57,7 @@ def pack(values: Sequence) -> dpb.Sequence:
57
57
  return target
58
58
 
59
59
 
60
- def unpack(source: dpb.Sequence) -> list:
60
+ def unpack(source: dpb_Sequence) -> list:
61
61
  """Unpacks protobuf to list. Reverse operation of :func:`.pack`.
62
62
 
63
63
  Args:
@@ -14,7 +14,7 @@
14
14
 
15
15
  """Convert SettingNodes to protos and back."""
16
16
 
17
- import iqm.data_definitions.common.v1.setting_pb2 as spb
17
+ from iqm.data_definitions.common.v1.setting_pb2 import SettingNode as spb_SettingNode
18
18
 
19
19
  from exa.common.api.proto_serialization import datum
20
20
  import exa.common.api.proto_serialization._parameter as param_proto
@@ -23,7 +23,7 @@ from exa.common.data.setting_node import Setting, SettingNode
23
23
  from exa.common.helpers.numpy_helper import coerce_numpy_type_to_native
24
24
 
25
25
 
26
- def _pack_setting(setting: Setting, optimize: bool) -> spb.SettingNode.Setting:
26
+ def _pack_setting(setting: Setting, optimize: bool) -> spb_SettingNode.Setting:
27
27
  """Convert a Setting into protobuf representation."""
28
28
  value = coerce_numpy_type_to_native(setting.value)
29
29
  try:
@@ -33,11 +33,11 @@ def _pack_setting(setting: Setting, optimize: bool) -> spb.SettingNode.Setting:
33
33
  f"Failed to convert a value to protobuf. Value={setting.value}, Parameter={setting.parameter}."
34
34
  ) from err
35
35
  if optimize:
36
- return spb.SettingNode.Setting(parameter_name=setting.name, value=packed)
37
- return spb.SettingNode.Setting(parameter=param_proto.pack(setting.parameter), value=packed)
36
+ return spb_SettingNode.Setting(parameter_name=setting.name, value=packed)
37
+ return spb_SettingNode.Setting(parameter=param_proto.pack(setting.parameter), value=packed)
38
38
 
39
39
 
40
- def _unpack_setting(proto: spb.SettingNode.Setting) -> Setting:
40
+ def _unpack_setting(proto: spb_SettingNode.Setting) -> Setting:
41
41
  """Convert protobuf representation into a Setting."""
42
42
  if proto.WhichOneof("parameter_desc") == "parameter":
43
43
  parameter = param_proto.unpack(proto.parameter)
@@ -48,10 +48,10 @@ def _unpack_setting(proto: spb.SettingNode.Setting) -> Setting:
48
48
  except Exception as err:
49
49
  raise AttributeError(f"Unpacking of {parameter} {proto.value} failed.") from err
50
50
 
51
- return Setting(parameter, value)
51
+ return Setting(parameter, value) # type: ignore[arg-type]
52
52
 
53
53
 
54
- def pack(node: SettingNode, minimal: bool) -> spb.SettingNode:
54
+ def pack(node: SettingNode, minimal: bool) -> spb_SettingNode:
55
55
  """Convert a SettingNode into protobuf representation.
56
56
 
57
57
  Silently coerces some datatypes to be compatible with the proto definition of ``Datum``:
@@ -69,10 +69,10 @@ def pack(node: SettingNode, minimal: bool) -> spb.SettingNode:
69
69
  """
70
70
  settings = {key: _pack_setting(item, minimal) for key, item in node.child_settings}
71
71
  nodes = {key: pack(item, minimal) for key, item in node.child_nodes}
72
- return spb.SettingNode(name=node.name, settings=settings, subnodes=nodes)
72
+ return spb_SettingNode(name=node.name, settings=settings, subnodes=nodes)
73
73
 
74
74
 
75
- def unpack(proto: spb.SettingNode) -> SettingNode:
75
+ def unpack(proto: spb_SettingNode) -> SettingNode:
76
76
  """Convert protobuf representation into a SettingNode. Reverse operation of :func:`.pack`
77
77
 
78
78
  Args:
@@ -87,4 +87,4 @@ def unpack(proto: spb.SettingNode) -> SettingNode:
87
87
  nodes = {key: unpack(content) for key, content in proto.subnodes.items()}
88
88
  # Names are currently NEVER aligned with the paths when deserializing. This is safe to do, since currently nothing
89
89
  # in the server-side assumes path==name, but if such logic is added this needs to be reconsidered.
90
- return SettingNode(name=proto.name, **(settings | nodes), align_name=False)
90
+ return SettingNode(name=proto.name, **(settings | nodes), align_name=False) # type: ignore[arg-type] # type: ignore[arg-type] # type: ignore[arg-type]
@@ -57,4 +57,4 @@ class CenterSpanBaseOptions(SweepOptions):
57
57
  start = self.center - (self.span / 2)
58
58
  stop = self.center + (self.span / 2)
59
59
  (start, stop) = (start, stop) if self.asc else (stop, start)
60
- return StartStopBaseOptions(start, stop, count=self.count, base=self.base).data
60
+ return StartStopBaseOptions(start, stop, count=self.count, base=self.base).data # type:ignore[arg-type,return-value]
@@ -14,14 +14,12 @@
14
14
 
15
15
  """Helper constants for SweepOptions classes."""
16
16
 
17
- from typing import Any
18
-
19
17
  #: Default value for `count` value in options.
20
18
  DEFAULT_COUNT: int = 101
21
19
  #: Default value for `base` value in options.
22
20
  DEFAULT_BASE: int = 10
23
21
  #: Dictionary with all possible types of options
24
- OPTIONS_TYPE: dict[str, Any] = {
22
+ OPTIONS_TYPE: dict[str, str | list[str]] = {
25
23
  "start": "start",
26
24
  "stop": "stop",
27
25
  "center": "center",
@@ -45,24 +45,24 @@ def convert_to_options(config: dict[str, Any]) -> SweepOptions:
45
45
 
46
46
  """
47
47
  config = {k.lower(): v for k, v in config.items()}
48
- if {OPTIONS_TYPE.get("start"), OPTIONS_TYPE.get("stop")}.issubset(set(config)):
49
- updated_config = __update_config(config, OPTIONS_TYPE.get("start_stop_list"))
48
+ if {OPTIONS_TYPE.get("start"), OPTIONS_TYPE.get("stop")}.issubset(set(config)): # type:ignore[arg-type]
49
+ updated_config = __update_config(config, OPTIONS_TYPE.get("start_stop_list")) # type:ignore[arg-type]
50
50
  return StartStopOptions(**updated_config)
51
- elif {OPTIONS_TYPE.get("start_exp"), OPTIONS_TYPE.get("stop_exp")}.issubset(set(config)):
52
- __rename_key(config, OPTIONS_TYPE.get("start_exp"), OPTIONS_TYPE.get("start"))
53
- __rename_key(config, OPTIONS_TYPE.get("stop_exp"), OPTIONS_TYPE.get("stop"))
54
- updated_config = __update_config(config, OPTIONS_TYPE.get("start_stop_base_list"))
51
+ elif {OPTIONS_TYPE.get("start_exp"), OPTIONS_TYPE.get("stop_exp")}.issubset(set(config)): # type:ignore[arg-type]
52
+ __rename_key(config, OPTIONS_TYPE.get("start_exp"), OPTIONS_TYPE.get("start")) # type:ignore[arg-type]
53
+ __rename_key(config, OPTIONS_TYPE.get("stop_exp"), OPTIONS_TYPE.get("stop")) # type:ignore[arg-type]
54
+ updated_config = __update_config(config, OPTIONS_TYPE.get("start_stop_base_list")) # type:ignore[arg-type]
55
55
  return StartStopBaseOptions(**updated_config)
56
- elif {OPTIONS_TYPE.get("center"), OPTIONS_TYPE.get("span")}.issubset(set(config)):
57
- updated_config = __update_config(config, OPTIONS_TYPE.get("center_span_list"))
56
+ elif {OPTIONS_TYPE.get("center"), OPTIONS_TYPE.get("span")}.issubset(set(config)): # type:ignore[arg-type]
57
+ updated_config = __update_config(config, OPTIONS_TYPE.get("center_span_list")) # type:ignore[arg-type]
58
58
  return CenterSpanOptions(**updated_config)
59
- elif {OPTIONS_TYPE.get("center_exp"), OPTIONS_TYPE.get("span_exp")}.issubset(set(config)):
60
- __rename_key(config, OPTIONS_TYPE.get("center_exp"), OPTIONS_TYPE.get("center"))
61
- __rename_key(config, OPTIONS_TYPE.get("span_exp"), OPTIONS_TYPE.get("span"))
62
- updated_config = __update_config(config, OPTIONS_TYPE.get("center_span_base_list"))
59
+ elif {OPTIONS_TYPE.get("center_exp"), OPTIONS_TYPE.get("span_exp")}.issubset(set(config)): # type:ignore[arg-type]
60
+ __rename_key(config, OPTIONS_TYPE.get("center_exp"), OPTIONS_TYPE.get("center")) # type:ignore[arg-type]
61
+ __rename_key(config, OPTIONS_TYPE.get("span_exp"), OPTIONS_TYPE.get("span")) # type:ignore[arg-type]
62
+ updated_config = __update_config(config, OPTIONS_TYPE.get("center_span_base_list")) # type:ignore[arg-type]
63
63
  return CenterSpanBaseOptions(**updated_config)
64
64
  elif OPTIONS_TYPE.get("fixed") in set(config):
65
- updated_config = __update_config(config, OPTIONS_TYPE.get("fixed"))
65
+ updated_config = __update_config(config, OPTIONS_TYPE.get("fixed")) # type:ignore[arg-type]
66
66
  return FixedOptions(**updated_config)
67
67
  else:
68
68
  raise ValueError(f"Config {config} cannot be converted to range options")
@@ -66,7 +66,7 @@ class StartStopOptions(SweepOptions):
66
66
  data = self._generate_by_count(count)
67
67
  else:
68
68
  data = self._generate_by_count(self.count if self.count is not None else DEFAULT_COUNT)
69
- return data
69
+ return data # type: ignore[return-value]
70
70
 
71
71
  def _generate_by_count(self, count: int) -> SweepValues:
72
72
  return np.linspace(self.start, self.stop, count, endpoint=True).tolist()
@@ -55,7 +55,7 @@ class Sweep(BaseModel):
55
55
  else:
56
56
  data = options.data
57
57
 
58
- super().__init__(parameter=parameter, data=data, **kwargs)
58
+ super().__init__(parameter=parameter, data=data, **kwargs) # type: ignore[call-arg] # type: ignore[call-arg]
59
59
 
60
60
  def model_post_init(self, __context: Any) -> None:
61
61
  if not all(self.parameter.validate(value) for value in self.data):
@@ -71,7 +71,7 @@ class Sweep(BaseModel):
71
71
  def __from_start_stop(cls, parameter: Parameter, options: StartStopOptions) -> SweepValues:
72
72
  cls._validate_value(parameter, options.start, "start")
73
73
  cls._validate_value(parameter, options.stop, "stop")
74
- cls._validate_value(parameter, options.step, "step")
74
+ cls._validate_value(parameter, options.step, "step") # type: ignore[arg-type]
75
75
  return options.data
76
76
 
77
77
  @staticmethod
@@ -12,6 +12,8 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
+ # mypy: ignore-errors
16
+
15
17
  """Physical quantities and instrument settings.
16
18
 
17
19
  A basic data structure in EXA is the :class:`~exa.common.data.parameter.Parameter`, which represents
@@ -61,7 +63,7 @@ import ast
61
63
  from collections.abc import Hashable
62
64
  import copy
63
65
  from enum import IntEnum
64
- from typing import Any, Self
66
+ from typing import Any, Self, TypeAlias
65
67
  import warnings
66
68
 
67
69
  import numpy as np
@@ -73,7 +75,9 @@ from exa.common.data.base_model import BaseModel
73
75
  from exa.common.data.value import ObservationValue
74
76
  from exa.common.errors.station_control_errors import ValidationError
75
77
 
76
- CastType = str | list["CastType"] | None
78
+ CastType: TypeAlias = str | list["CastType"] | None
79
+ SourceType: TypeAlias = None | BaseModel | dict[str, Any]
80
+ """Type for Setting sources."""
77
81
 
78
82
 
79
83
  class DataType(IntEnum):
@@ -135,7 +139,7 @@ class DataType(IntEnum):
135
139
  raise TypeError("Boolean data types can only be 'false', 'true, '0' or '1' (case-insensitive)")
136
140
  elif self is DataType.STRING:
137
141
  return value
138
- else:
142
+ else: # TODO: can this be removed?
139
143
  try:
140
144
  return ast.literal_eval(value)
141
145
  except (SyntaxError, ValueError): # if the value can not be evaluated, return the original value
@@ -407,12 +411,19 @@ class Setting(BaseModel):
407
411
  path: str = ""
408
412
  """Path in the settings tree (starting from the root ``SettingNode``) for this setting."""
409
413
 
414
+ _source: SourceType = None
415
+ """The source for this Setting value. May contain an observation (ObservationDefinition or ObservationData)
416
+ or a source-dict (e.g. ``{"type": "configuration_source", "configurator": "defaults_from_yml"}``). By default,
417
+ ``None``, which denotes the source not being specified (e.g. hardcoded defaults). The source is stored in a private
418
+ attribute and thus is never serialized (the source field can contain non-serializable data such as Callables)."""
419
+
410
420
  def __init__(
411
421
  self,
412
422
  parameter: Parameter | None = None,
413
423
  value: ObservationValue | None = None,
414
424
  read_only: bool = False,
415
425
  path: str = "",
426
+ source: SourceType = None,
416
427
  **kwargs,
417
428
  ) -> None:
418
429
  super().__init__(
@@ -422,6 +433,7 @@ class Setting(BaseModel):
422
433
  path=path,
423
434
  **kwargs,
424
435
  )
436
+ self._source = source
425
437
 
426
438
  @model_validator(mode="after")
427
439
  def validate_parameter_value_after(self) -> Self:
@@ -435,8 +447,17 @@ class Setting(BaseModel):
435
447
  raise ValidationError(f"Invalid value '{self.value}' for parameter '{self.parameter}'.")
436
448
  return self
437
449
 
438
- def update(self, value: ObservationValue) -> Setting:
439
- """Create a new setting object with updated `value`."""
450
+ def update(self, value: ObservationValue, source: SourceType = None) -> Setting:
451
+ """Create a new setting object with updated value and source.
452
+
453
+ Args:
454
+ value: New value for the setting.
455
+ source: New source for the setting.
456
+
457
+ Returns:
458
+ Copy of ``self`` with modified properties.
459
+
460
+ """
440
461
  if self.read_only:
441
462
  raise ValueError(
442
463
  f"Can't update the value of {self.parameter.name} to {value} since the setting is read-only."
@@ -445,7 +466,7 @@ class Setting(BaseModel):
445
466
  value = np.array(value)
446
467
  # Need to create a new Setting here instead of using Pydantic model_copy().
447
468
  # model_copy() can't handle backdoor settings without errors, i.e. values with a list of 2 elements.
448
- return Setting(self.parameter, value, self.read_only, self.path)
469
+ return Setting(self.parameter, value, self.read_only, self.path, source=source)
449
470
 
450
471
  @property
451
472
  def name(self):
@@ -477,6 +498,11 @@ class Setting(BaseModel):
477
498
  """Element-wise indices of the parameter in ``self``."""
478
499
  return self.parameter.element_indices
479
500
 
501
+ @property
502
+ def source(self) -> SourceType:
503
+ """Return the source for this Setting's value."""
504
+ return self._source
505
+
480
506
  @staticmethod
481
507
  def get_by_name(name: str, values: set[Setting]) -> Setting | None:
482
508
  return next((setting for setting in values if setting.parameter.name == name), None)
@@ -12,6 +12,8 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
+ # mypy: ignore-errors
16
+
15
17
  """A tree-structured container for :class:`Settings <exa.common.data.parameter.Setting>`.
16
18
 
17
19
  The :class:`.SettingNode` class combines a bunch of Settings together.
@@ -217,7 +219,7 @@ import jinja2
217
219
  import numpy as np
218
220
 
219
221
  from exa.common.data.base_model import BaseModel
220
- from exa.common.data.parameter import CollectionType, Parameter, Setting
222
+ from exa.common.data.parameter import CollectionType, Parameter, Setting, SourceType
221
223
  from exa.common.errors.exa_error import UnknownSettingError
222
224
  from exa.common.qcm_data.chip_topology import sort_components
223
225
 
@@ -603,7 +605,7 @@ class SettingNode(BaseModel):
603
605
  """
604
606
  for key, item in other.settings.items():
605
607
  if key in self.settings and (prioritize_other or (self[key].value is None)):
606
- self.settings[key] = Setting(self.settings[key].parameter, item.value)
608
+ self.settings[key] = Setting(self.settings[key].parameter, item.value, source=self.settings[key].source)
607
609
  for key, item in other.subtrees.items():
608
610
  if key in self.subtrees:
609
611
  self.subtrees[key].merge_values(copy(item), prioritize_other)
@@ -678,16 +680,22 @@ class SettingNode(BaseModel):
678
680
  new.subtrees[key] = cls.transform_node_types(subnode)
679
681
  return new
680
682
 
681
- def set_from_dict(self, dct: dict[str, Any], strict: bool = False) -> None:
683
+ def set_from_dict(
684
+ self,
685
+ dct: dict[str, Any],
686
+ strict: bool = False,
687
+ source: SourceType = None,
688
+ ) -> None:
682
689
  """Recursively set values to Settings, taking values from a dictionary that has similar tree structure.
683
- Keys that are not found in self are ignored, unless `strict` is True.
690
+ Keys that are not found in self are ignored, unless ``strict`` is True.
684
691
 
685
692
  Args:
686
693
  dct: Dictionary containing the new values to use.
687
- strict: If True, will raise error if `dct` contains a setting that is not found in `self`.
694
+ strict: If True, will raise error if ``dct`` contains a setting that is not found in ``self``.
695
+ source: Source for the settings (this same source is applied to all settings from the dict).
688
696
 
689
697
  Raises:
690
- UnknownSettingError: If the condition of `strict` happens.
698
+ UnknownSettingError: If the condition of ``strict`` happens.
691
699
 
692
700
  """
693
701
  for key, value in dct.items():
@@ -704,9 +712,10 @@ class SettingNode(BaseModel):
704
712
  self.settings[key].name,
705
713
  self.settings[key].parameter.data_type.cast(value),
706
714
  path=self.settings[key].path,
715
+ source=source,
707
716
  )
708
717
  else:
709
- self.settings[key] = self.settings[key].update(value)
718
+ self.settings[key] = self.settings[key].update(value, source=source)
710
719
 
711
720
  def setting_with_path_name(self, setting: Setting) -> Setting | None:
712
721
  """Get a copy of a setting with its name replaced with the path name."""
@@ -858,6 +867,7 @@ class SettingNode(BaseModel):
858
867
  nodes: Iterable[Setting | Parameter | SettingNode] | dict[str, Setting | Parameter | SettingNode],
859
868
  path: str,
860
869
  override_values: dict[str, Any] | None = None,
870
+ override_source: SourceType = None,
861
871
  ) -> None:
862
872
  """Add nodes to ``self`` while creating the missing nodes in-between.
863
873
 
@@ -873,6 +883,8 @@ class SettingNode(BaseModel):
873
883
  found in self, the associated nodes will be created automatically.
874
884
  override_values: Optionally override the values for the `Settings` corresponding to ``nodes``. This dict
875
885
  should have the same structure as ``nodes``, including matching names.
886
+ override_source: Optionally override the source for the ``Settings`` corresponding to ``nodes``. All the
887
+ settings will then have this same source.
876
888
 
877
889
  """
878
890
  override_values = override_values or {}
@@ -899,9 +911,10 @@ class SettingNode(BaseModel):
899
911
  latest_node[key] = node
900
912
  else:
901
913
  default_value = node.value if isinstance(node, Setting) else None
914
+ source = override_source or (node.source if isinstance(node, Setting) else None)
902
915
  parameter = node.parameter if isinstance(node, Setting) else node
903
916
  value = override_values.get(node.name) if override_values.get(node.name) is not None else default_value
904
- latest_node[key] = Setting(parameter, value)
917
+ latest_node[key] = Setting(parameter, value, source=source)
905
918
 
906
919
  def get_default_implementation_name(self, gate: str, locus: str | Iterable[str]) -> str:
907
920
  """Get the default implementation name for a given gate and locus.
@@ -1034,6 +1047,20 @@ class SettingNode(BaseModel):
1034
1047
 
1035
1048
  raise ValueError(f"Locus {locus} cannot be found in the gate properties characterization settings.")
1036
1049
 
1050
+ def set_source(self, source: SourceType, ignore_nones: bool = True) -> None:
1051
+ """Set source recursively to all Settings in ``self``.
1052
+
1053
+ Args:
1054
+ source: The source to set.
1055
+ ignore_nones: If ``True``, the source will not be set for Settings with ``None`` value.
1056
+
1057
+ """
1058
+ for setting in self.settings.values():
1059
+ if not ignore_nones or setting.value is not None:
1060
+ setting._source = source
1061
+ for subtree in self.subtrees.values():
1062
+ subtree.set_source(source, ignore_nones=ignore_nones)
1063
+
1037
1064
  def _get_symmetric_loci(self, gate: str, implementation: str, locus: str | Iterable[str]) -> list[str]:
1038
1065
  if not isinstance(locus, str):
1039
1066
  if self.gate_definitions[gate][implementation].symmetric.value:
@@ -38,7 +38,7 @@ def add_data_array(ds: xr.Dataset, da: xr.DataArray, name: Hashable | None = Non
38
38
  """
39
39
  if name is None:
40
40
  if da.name is not None:
41
- name = da.name
41
+ name = da.name # type: ignore[assignment]
42
42
  else:
43
43
  raise ValueError("No name was given to the dataArray.")
44
44
  # Attributes of Dataset coordinates are dropped/replaced when adding a DataArray
@@ -18,7 +18,7 @@ import os
18
18
  import platform
19
19
  import subprocess
20
20
 
21
- import pkg_resources
21
+ import pkg_resources # type:ignore[import-untyped]
22
22
 
23
23
 
24
24
  def _is_editable(pkg_name: str) -> bool:
exa/common/py.typed ADDED
File without changes
@@ -168,7 +168,7 @@ class CHAD(ImmutableBaseModel):
168
168
  launchers = {launcher.name: launcher for launcher in self.components.launchers}
169
169
 
170
170
  component: Qubit | Coupler
171
- for component in [*self.components.qubits, *self.components.couplers]:
171
+ for component in [*self.components.qubits, *self.components.couplers]: # type:ignore[assignment]
172
172
  component_type = "qubit" if isinstance(component, Qubit) else "coupler"
173
173
  if component.name in component_names:
174
174
  for connection in component.connections:
@@ -12,6 +12,8 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
+ # mypy: ignore-errors
16
+
15
17
  """Chip topology class for parsing CHAD and other QPU related data into human-usable form."""
16
18
 
17
19
  from __future__ import annotations
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: iqm-exa-common
3
- Version: 26.26.0
3
+ Version: 26.28.0
4
4
  Summary: Framework for control and measurement of superconducting qubits: common library
5
5
  Author-email: IQM Finland Oy <info@meetiqm.com>
6
6
  License: Apache License
@@ -219,9 +219,12 @@ Requires-Dist: pydantic <3.0,>=2.10.4
219
219
  Requires-Dist: python-dotenv ==0.21.1
220
220
  Requires-Dist: xarray ==2024.10.0
221
221
  Requires-Dist: requests ==2.32.3
222
+ Requires-Dist: types-requests
222
223
  Requires-Dist: ruamel-yaml ==0.17.32
223
224
  Requires-Dist: ruamel-yaml-clib ==0.2.8
224
225
  Requires-Dist: jinja2 ==3.0.3
226
+ Requires-Dist: six ==1.16.0
227
+ Requires-Dist: types-six
225
228
 
226
229
  EXA-common
227
230
  ==========
@@ -1,57 +1,58 @@
1
1
  exa/common/__init__.py,sha256=AqxwNht57urLqMxFblY7SgxjzkQYW7pRRUUPS1j1Gck,962
2
+ exa/common/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
3
  exa/common/api/__init__.py,sha256=PAYujWNG8CtSQX_8U9gnubDh5cwGRhtOfLr0r0xGx3M,587
3
4
  exa/common/api/proto_serialization/__init__.py,sha256=Vn2C79OqovFu5wJus9EHsMtK3Of1JLJDcpg2QZKmXsY,1565
4
- exa/common/api/proto_serialization/_parameter.py,sha256=W0EBrVs3uZ-jX1HnlOrAB7_PKrzi8D_qNM0_SBht8XY,2895
5
- exa/common/api/proto_serialization/array.py,sha256=iht5WlfGEkzXM3PcOFDXxd2TgXWFyYNyPt44CMqXnl8,3110
6
- exa/common/api/proto_serialization/datum.py,sha256=i4Ri8VMfbCPV_d6763DDUdHX72tEWxpiOhvIr0lfSlY,4811
7
- exa/common/api/proto_serialization/nd_sweep.py,sha256=B36KY32wTNFJE3Bk2QlN4BeMO0Se7AtwOectlIh5SCM,2661
8
- exa/common/api/proto_serialization/sequence.py,sha256=mcjquVqVquQmhE5G7cbC3vRax9EkOS6iJk2QXBu1MoQ,2545
9
- exa/common/api/proto_serialization/setting_node.py,sha256=KCNpwgwIrgyuXsgt-rAm3oEQqKlIxtN8JBUDFaQTJ48,3940
5
+ exa/common/api/proto_serialization/_parameter.py,sha256=d_LHc_Tl3OqiQmTGe6Y6mkHvQkknzFl5KPEJauPEKPM,3050
6
+ exa/common/api/proto_serialization/array.py,sha256=CvuOV5jNyFAAdqrYsh_z4DeQA6kYvfidW9bEv_M7Ugo,3127
7
+ exa/common/api/proto_serialization/datum.py,sha256=x9PJi3iiqAcG7aMUhBaho6vTNBQsm7pzY0HCFxB_zfM,4915
8
+ exa/common/api/proto_serialization/nd_sweep.py,sha256=5Wi_iz4XqQE9GgSzt3vUTpYKwO5uCPGBa2OqwOMOXcQ,2912
9
+ exa/common/api/proto_serialization/sequence.py,sha256=4yQgdTUenbsY8yNu7JqSQSq2Ushd1zlzuciaqmyP7OY,2568
10
+ exa/common/api/proto_serialization/setting_node.py,sha256=oAlJOmkQTmMSd6wpofoDLz3YIlkiqxX7kY84WnZZ4b4,4073
10
11
  exa/common/control/__init__.py,sha256=00T_xV0lL20QZcEt__vWq81N1oGF0KpJMhTitfAI4VI,629
11
12
  exa/common/control/sweep/__init__.py,sha256=GzKoQdQsLutcHhmrLPyPrW1n7Cpg766p3OWDHlRpuTs,607
12
13
  exa/common/control/sweep/exponential_sweep.py,sha256=OIGqSifkAgQcS2EdffDpIjibB80XteLVF82kS63vPro,2121
13
14
  exa/common/control/sweep/fixed_sweep.py,sha256=QXO5lrllHHlhLiA95s8iTE82QkAEzgjJ2dA0flRJLhs,1493
14
15
  exa/common/control/sweep/linear_sweep.py,sha256=fX7OuZDYtUSGcAJLsGTVHcCIRkUHkZNLy5YSe_kgb8M,1966
15
- exa/common/control/sweep/sweep.py,sha256=0ZzhbzcAQaByiX7dz5jDH0r1zmyEiW2B-v8edIyTDs8,3442
16
+ exa/common/control/sweep/sweep.py,sha256=CeCd7-nh0nIlaay4ggMICu61anVxlg3MISGhkK44-VQ,3520
16
17
  exa/common/control/sweep/sweep_values.py,sha256=c868qpnh3SP6DYN3eAt0SLaePuzzQwxTWYwnQwL4A-I,2277
17
18
  exa/common/control/sweep/option/__init__.py,sha256=Z01JS0FpchMvR8zfWBCs3jcPjh2H8X29YkN0SFxWLTY,906
18
- exa/common/control/sweep/option/center_span_base_options.py,sha256=8F2HqHeq9RSMqEms6icuUqLlzkL6jT991eeRrKgikM8,2520
19
+ exa/common/control/sweep/option/center_span_base_options.py,sha256=uHWt4euQVF7EVXJid8wnIXo8PtJnyUdydxxAXPEMnV4,2558
19
20
  exa/common/control/sweep/option/center_span_options.py,sha256=WJ9tNaORsnSYojwx5qy3mSoHRmsV2cKMXP6LTRU41Zo,2482
20
- exa/common/control/sweep/option/constants.py,sha256=vdYrbi3EBlIST5mO498W2F6s-xqyoEVBAZ6zQEiHmmY,1417
21
+ exa/common/control/sweep/option/constants.py,sha256=pHWOLQicxL-qX0iHQXlhPVNBGHPjvxZ9JBIZQDxEpCY,1405
21
22
  exa/common/control/sweep/option/fixed_options.py,sha256=SyGSiEanD3xz4Wcy1rd9r2wj7hNaG3lQYH67WQDc72I,1047
22
- exa/common/control/sweep/option/option_converter.py,sha256=RGNNQHNl8gTZUHO85IZseoo065s_kQSWP-AfrYhGbn4,3649
23
+ exa/common/control/sweep/option/option_converter.py,sha256=CsiMY8-pnvdLsD7iLHPIkjbLUnfTnhZY8UxEdWuOaN4,3974
23
24
  exa/common/control/sweep/option/start_stop_base_options.py,sha256=09P03pexASngGWSSltVh8Ty-BsBmRkQ3iYODsr0ij5I,2145
24
- exa/common/control/sweep/option/start_stop_options.py,sha256=NAOCJgXvL5J4zewNvsIHMb6L-Bu_2drfwqifqT6z5Uk,3083
25
+ exa/common/control/sweep/option/start_stop_options.py,sha256=vJottC6QX80MhVyg9_R9UFx6W1ijSHOVRzU9fDO3FLA,3113
25
26
  exa/common/control/sweep/option/sweep_options.py,sha256=BhKB7RHP0VXJ9iUQKVzeQOM4j_x9AsMhRJgoR3gkiaY,933
26
27
  exa/common/data/__init__.py,sha256=F5SRe5QHBTjef4XJVQ63kO5Oxc_AiZnPbV560i7La0Y,644
27
28
  exa/common/data/base_model.py,sha256=U508YCtvZabBGnKe1fqUimunmwGulOTM6DOKTUqnYp8,1835
28
- exa/common/data/parameter.py,sha256=GI-BJcXe53Mf2PXPzvftCV7L2kd_uC-hOjH_J__1MLc,23313
29
- exa/common/data/setting_node.py,sha256=obA9Rl3uSQ-pOoAAMzSQvzbRPygSIaFOM4W4foxKKKk,43344
29
+ exa/common/data/parameter.py,sha256=AQxeTvItMjOvT2QUvhKCn9aK5ibrfaN8LI_Oc68ZzII,24420
30
+ exa/common/data/setting_node.py,sha256=yZU8lltzK5qV4L5Xte3AOcG85Tgdg-3mrxCiTpwbW7Q,44548
30
31
  exa/common/data/settingnode_v2.html.jinja2,sha256=mo-rlLLmU-Xxf6znJAisispAZK8sbV-2C13byKAtj_Q,3166
31
32
  exa/common/data/value.py,sha256=mtMws5UPGx1pCADK6Q2Tx4BwCXznvVRSNQRfcQ3NMmY,1853
32
33
  exa/common/errors/__init__.py,sha256=ArMBdpmx1EUenBpzrSNG63kmUf7PM0gCqSYnaCnL9Qk,597
33
34
  exa/common/errors/exa_error.py,sha256=iw8ueZgqx1JXkfjRoJfPUsSE7cfhzIWpdDaFuka9Ss0,990
34
35
  exa/common/errors/station_control_errors.py,sha256=NEVW9QC-jJM36CQ8b9IIg9hZv5Utph9LXirxk5ZiuNM,4122
35
36
  exa/common/helpers/__init__.py,sha256=IgtVD3tojIFA4MTV2mT5uYM6jb2qny9kBIIhEZT2PuI,610
36
- exa/common/helpers/data_helper.py,sha256=1fd-k7k4Y5mD9xqjHwvfiHRvTAA5fttMHrempjke-Tw,1973
37
+ exa/common/helpers/data_helper.py,sha256=-AP0vwrf7WgyumLsicDtNP2VP5rhG4_oiOZgG4alNb4,2001
37
38
  exa/common/helpers/deprecation.py,sha256=nY8484iun63JOBfBeh49Q6VD5xZ4_gT9fjPmH1RAXoI,397
38
39
  exa/common/helpers/json_helper.py,sha256=LoTrL6FREML1o0X3Zznf1baI4kn0kh03NE1nqBHgYss,2699
39
40
  exa/common/helpers/numpy_helper.py,sha256=KKKyZ_fD0O1gn7_InEQROYnX3WGMA6C1qHh8KzzjtUI,1062
40
- exa/common/helpers/software_version_helper.py,sha256=Spx_buLnzTawjU8KrGJcW0BJEvgv8W2cG8FxEDzIOSM,5143
41
+ exa/common/helpers/software_version_helper.py,sha256=BUozde38-7X_NVh0lRY8VR2fvTEPLTz3nyEwSopEJEU,5174
41
42
  exa/common/helpers/yaml_helper.py,sha256=wLy-7Nyit597FoWBemduUilYP2VCk_aDDT8y62i3ox8,1626
42
43
  exa/common/logger/__init__.py,sha256=1bIsGxHzfujXlkgtcAnWToKMkw3dpU5PEd_7LE_NpgQ,686
43
44
  exa/common/logger/logger.py,sha256=0aSjkx4pXy_CCKtspOnFgwMmhZVFAZUlopQ6HUjBMko,5689
44
45
  exa/common/qcm_data/__init__.py,sha256=VtsYkGoaniSjCkY0oQlqkcYJCtmC2sTDxfrIe_kpqZg,567
45
- exa/common/qcm_data/chad_model.py,sha256=EVzEdN1uImbM2gAE9FCk7eBQrIrCxgDmVOLvESi8yyM,11236
46
- exa/common/qcm_data/chip_topology.py,sha256=qUBr4eDMy76RoOc1DX2sZ9vYzh3ubByEK1CZtr-LYcU,20004
46
+ exa/common/qcm_data/chad_model.py,sha256=s8p9zaQsoo1douqXAuLbAV5hjOCbrhEJFNzi5Yq9y98,11263
47
+ exa/common/qcm_data/chip_topology.py,sha256=-IsWh0hev_vnAWs0z3iWBvProe6LypgKs1Erp8HCb0M,20027
47
48
  exa/common/qcm_data/file_adapter.py,sha256=U1XZm_PEswkW7kAztbWFLMufz4mPKPupWbh5yJXdZCI,2263
48
49
  exa/common/qcm_data/immutable_base_model.py,sha256=QXmKIWQbsbWQvovXwKT1d9jtyf2LNJtjQquIwO52zOU,901
49
50
  exa/common/qcm_data/qcm_data_client.py,sha256=Rze6yQd0xUeH6eUMv3wduYbiDCTP3C4WECtCe7ONmyc,6061
50
51
  exa/common/sweep/__init__.py,sha256=uEKk5AtzSgSnf8Y0geRPwUpqXIBIXpeCxsN64sX7F1o,591
51
52
  exa/common/sweep/database_serialization.py,sha256=NUu1umxRQZpKtRmw1vNDsSbnofqbHvKFg_xQ2mdhY6k,7469
52
53
  exa/common/sweep/util.py,sha256=-QE2AaH-WDkYAVH5-Z-30leLgY0x4efmby4kc1JTCgY,3732
53
- iqm_exa_common-26.26.0.dist-info/LICENSE.txt,sha256=R6Q7eUrLyoCQgWYorQ8WJmVmWKYU3dxA3jYUp0wwQAw,11332
54
- iqm_exa_common-26.26.0.dist-info/METADATA,sha256=iD1DF1AEmak_PpscF39c2mw4n3OH3lAvZe4lZ74m1ww,14659
55
- iqm_exa_common-26.26.0.dist-info/WHEEL,sha256=y4mX-SOX4fYIkonsAGA5N0Oy-8_gI4FXw5HNI1xqvWg,91
56
- iqm_exa_common-26.26.0.dist-info/top_level.txt,sha256=Clphg2toaZ3_jSFRPhjMNEmLurkMNMc4lkK2EFYsSlM,4
57
- iqm_exa_common-26.26.0.dist-info/RECORD,,
54
+ iqm_exa_common-26.28.0.dist-info/LICENSE.txt,sha256=R6Q7eUrLyoCQgWYorQ8WJmVmWKYU3dxA3jYUp0wwQAw,11332
55
+ iqm_exa_common-26.28.0.dist-info/METADATA,sha256=KISV_HQf4F7z7rwX36K7ux-nHUrpqSqZRS72K9YlnA8,14742
56
+ iqm_exa_common-26.28.0.dist-info/WHEEL,sha256=y4mX-SOX4fYIkonsAGA5N0Oy-8_gI4FXw5HNI1xqvWg,91
57
+ iqm_exa_common-26.28.0.dist-info/top_level.txt,sha256=Clphg2toaZ3_jSFRPhjMNEmLurkMNMc4lkK2EFYsSlM,4
58
+ iqm_exa_common-26.28.0.dist-info/RECORD,,