iqm-exa-common 25.30__py3-none-any.whl → 25.32__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.
Files changed (28) hide show
  1. exa/common/api/model/parameter_model.py +2 -3
  2. exa/common/api/model/setting_model.py +2 -3
  3. exa/common/api/model/setting_node_model.py +2 -3
  4. exa/common/api/proto_serialization/_parameter.py +0 -3
  5. exa/common/api/proto_serialization/array.py +3 -1
  6. exa/common/api/proto_serialization/datum.py +5 -3
  7. exa/common/api/proto_serialization/nd_sweep.py +1 -2
  8. exa/common/api/proto_serialization/sequence.py +7 -6
  9. exa/common/api/proto_serialization/setting_node.py +2 -2
  10. exa/common/control/sweep/exponential_sweep.py +1 -0
  11. exa/common/control/sweep/linear_sweep.py +1 -0
  12. exa/common/control/sweep/option/option_converter.py +1 -0
  13. exa/common/data/parameter.py +6 -1
  14. exa/common/data/setting_node.py +20 -14
  15. exa/common/errors/exa_error.py +1 -0
  16. exa/common/helpers/data_helper.py +1 -0
  17. exa/common/helpers/software_version_helper.py +3 -2
  18. exa/common/logger/logger.py +5 -5
  19. exa/common/qcm_data/chad_model.py +4 -0
  20. exa/common/qcm_data/chip_topology.py +20 -6
  21. exa/common/qcm_data/qcm_data_client.py +3 -1
  22. exa/common/sweep/database_serialization.py +11 -4
  23. exa/common/sweep/util.py +2 -0
  24. {iqm_exa_common-25.30.dist-info → iqm_exa_common-25.32.dist-info}/METADATA +3 -3
  25. {iqm_exa_common-25.30.dist-info → iqm_exa_common-25.32.dist-info}/RECORD +28 -28
  26. {iqm_exa_common-25.30.dist-info → iqm_exa_common-25.32.dist-info}/LICENSE.txt +0 -0
  27. {iqm_exa_common-25.30.dist-info → iqm_exa_common-25.32.dist-info}/WHEEL +0 -0
  28. {iqm_exa_common-25.30.dist-info → iqm_exa_common-25.32.dist-info}/top_level.txt +0 -0
@@ -23,9 +23,8 @@ from exa.common.data.parameter import CollectionType, DataType, Parameter
23
23
 
24
24
 
25
25
  class ParameterModel(BaseModel):
26
- """
27
- Pydantic parameter model
28
- """
26
+ """Pydantic parameter model
27
+ """ # noqa: D200
29
28
 
30
29
  name: str
31
30
  parent_name: Optional[str] = None
@@ -26,9 +26,8 @@ from exa.common.helpers.numpy_helper import coerce_numpy_type_to_native
26
26
 
27
27
 
28
28
  class SettingModel(BaseModel):
29
- """
30
- Pydantic setting model
31
- """
29
+ """Pydantic setting model
30
+ """ # noqa: D200
32
31
 
33
32
  parameter: ParameterModel
34
33
  value: Any = None
@@ -24,9 +24,8 @@ from exa.common.data.setting_node import SettingNode
24
24
 
25
25
 
26
26
  class SettingNodeModel(BaseModel):
27
- """
28
- Pydantic setting node model
29
- """
27
+ """Pydantic setting node model
28
+ """ # noqa: D200
30
29
 
31
30
  name: str
32
31
  settings: Dict[str, SettingModel]
@@ -17,9 +17,6 @@ import iqm.data_definitions.common.v1.parameter_pb2 as ppb
17
17
 
18
18
  from exa.common.data.parameter import CollectionType, DataType, Parameter
19
19
 
20
- # pylint: disable=no-member
21
-
22
-
23
20
  _COLLECTION_TYPES = {
24
21
  CollectionType.SCALAR: ppb.Parameter.CollectionType.COLLECTION_TYPE_SCALAR,
25
22
  CollectionType.LIST: ppb.Parameter.CollectionType.COLLECTION_TYPE_SEQUENCE,
@@ -14,7 +14,7 @@
14
14
 
15
15
  """Convert numpy arrays to protos and back."""
16
16
 
17
- # pylint: disable=no-member
17
+
18
18
  import iqm.data_definitions.common.v1.data_types_pb2 as dpb
19
19
  import numpy as np
20
20
 
@@ -27,6 +27,7 @@ def pack(array: np.ndarray) -> dpb.Array:
27
27
 
28
28
  Returns:
29
29
  A protobuf instance that encapsulates `array`.
30
+
30
31
  """
31
32
  target = dpb.Array()
32
33
  target.shape.MergeFrom(array.shape)
@@ -65,6 +66,7 @@ def unpack(source: dpb.Array) -> np.ndarray:
65
66
 
66
67
  Raises:
67
68
  ValueError or google.protobuf.message.DecodeError in case of invalid buffer
69
+
68
70
  """
69
71
  kind = source.WhichOneof("kind")
70
72
  if kind is None:
@@ -16,12 +16,10 @@
16
16
 
17
17
  from typing import Optional, Sequence, Union
18
18
 
19
- # pylint: disable=no-member
20
19
  import iqm.data_definitions.common.v1.data_types_pb2 as dpb
21
20
  import numpy as np
22
21
 
23
- import exa.common.api.proto_serialization.array as array
24
- import exa.common.api.proto_serialization.sequence as sequence
22
+ from exa.common.api.proto_serialization import array, sequence
25
23
 
26
24
 
27
25
  def pack(value: Union[None, bool, str, int, float, complex, np.ndarray, Sequence]) -> dpb.Datum:
@@ -43,6 +41,7 @@ def pack(value: Union[None, bool, str, int, float, complex, np.ndarray, Sequence
43
41
 
44
42
  Raises:
45
43
  TypeError in case of unsupported type.
44
+
46
45
  """
47
46
  if isinstance(value, np.number):
48
47
  raise TypeError(
@@ -78,6 +77,7 @@ def unpack(source: dpb.Datum) -> Union[None, str, bool, int, float, complex, np.
78
77
 
79
78
  Raises:
80
79
  TypeError or google.protobuf.message.DecodeError in case of invalid buffer
80
+
81
81
  """
82
82
  field_name = source.WhichOneof("kind")
83
83
  if field_name == "null_value":
@@ -107,6 +107,7 @@ def serialize(value: Union[None, bool, str, int, float, complex, np.ndarray, Seq
107
107
 
108
108
  Returns:
109
109
  Bitstring that encodes `value`.
110
+
110
111
  """
111
112
  return pack(value).SerializeToString()
112
113
 
@@ -119,6 +120,7 @@ def deserialize(source: bytes) -> Union[None, str, bool, int, float, complex, np
119
120
 
120
121
  Returns:
121
122
  Deserialized data.
123
+
122
124
  """
123
125
  proto = dpb.Datum()
124
126
  proto.ParseFromString(source)
@@ -13,7 +13,7 @@
13
13
  # limitations under the License.
14
14
 
15
15
  """Convert NdSweeps to protos and back."""
16
- # pylint: disable=no-member
16
+
17
17
  import iqm.data_definitions.common.v1.sweep_pb2 as spb
18
18
 
19
19
  from exa.common.api.proto_serialization import sequence
@@ -45,7 +45,6 @@ def unpack(proto: spb.CartesianSweep) -> NdSweep:
45
45
 
46
46
  Note: All sweeps will be of type :class:`.FixedSweep`.
47
47
  """
48
-
49
48
  nd_sweep = []
50
49
  for parallel_proto in reversed(proto.parallel_sweeps):
51
50
  parallel = tuple(_unpack_single_sweep(sweep) for sweep in parallel_proto.single_parameter_sweeps)
@@ -16,7 +16,6 @@
16
16
 
17
17
  from typing import Sequence
18
18
 
19
- # pylint: disable=no-member
20
19
  import iqm.data_definitions.common.v1.data_types_pb2 as dpb
21
20
  import numpy as np
22
21
 
@@ -32,23 +31,24 @@ def pack(values: Sequence) -> dpb.Sequence:
32
31
 
33
32
  Raises:
34
33
  ValueError in case of unsupported value.
34
+
35
35
  """
36
36
  target = dpb.Sequence()
37
37
  if not values:
38
38
  return target
39
39
  dtype = type(values[0])
40
- if dtype == complex:
40
+ if dtype == complex: # noqa: E721
41
41
  target_field = target.complex128_array
42
42
  target_field.real.MergeFrom(np.real(values))
43
43
  target_field.imag.MergeFrom(np.imag(values))
44
44
  return target
45
- if dtype == bool:
45
+ if dtype == bool: # noqa: E721
46
46
  target_field = target.bool_array
47
- elif dtype == int:
47
+ elif dtype == int: # noqa: E721
48
48
  target_field = target.int64_array
49
- elif dtype == float:
49
+ elif dtype == float: # noqa: E721
50
50
  target_field = target.float64_array
51
- elif dtype == str:
51
+ elif dtype == str: # noqa: E721
52
52
  target_field = target.string_array
53
53
  else:
54
54
  raise TypeError(f"Unsupported numpy array type {dtype} for a sequence.")
@@ -68,6 +68,7 @@ def unpack(source: dpb.Sequence) -> list:
68
68
 
69
69
  Raises:
70
70
  ValueError or google.protobuf.message.DecodeError in case of invalid buffer
71
+
71
72
  """
72
73
  kind = source.WhichOneof("kind")
73
74
  if kind is None:
@@ -21,8 +21,6 @@ from exa.common.data.parameter import DataType, Parameter
21
21
  from exa.common.data.setting_node import Setting, SettingNode
22
22
  from exa.common.helpers.numpy_helper import coerce_numpy_type_to_native
23
23
 
24
- # pylint: disable=no-member
25
-
26
24
 
27
25
  def _pack_setting(setting: Setting, optimize: bool) -> spb.SettingNode.Setting:
28
26
  """Convert a Setting into protobuf representation."""
@@ -66,6 +64,7 @@ def pack(node: SettingNode, minimal: bool) -> spb.SettingNode:
66
64
 
67
65
  Returns:
68
66
  Protobuf instance that represents `node`.
67
+
69
68
  """
70
69
  settings = {key: _pack_setting(item, minimal) for key, item in node.child_settings}
71
70
  nodes = {key: pack(item, minimal) for key, item in node.child_nodes}
@@ -81,6 +80,7 @@ def unpack(proto: spb.SettingNode) -> SettingNode:
81
80
  Returns:
82
81
  Unpacked SettingNode. In case `proto` only contains the parameter names (see ``optimize`` in
83
82
  :func:`.pack`), dummy Parameters are generated.
83
+
84
84
  """
85
85
  settings = {key: _unpack_setting(content) for key, content in proto.settings.items()}
86
86
  nodes = {key: unpack(content) for key, content in proto.subnodes.items()}
@@ -37,6 +37,7 @@ class ExponentialSweep(Sweep):
37
37
 
38
38
  Raises:
39
39
  ValueError: Error is raised if `options` is inconsistent.
40
+
40
41
  """
41
42
 
42
43
  logger: logging.Logger = field(init=False)
@@ -34,6 +34,7 @@ class LinearSweep(Sweep):
34
34
 
35
35
  Raises:
36
36
  ValueError: Error is raised if `options` is inconsistent.
37
+
37
38
  """
38
39
 
39
40
  def __post_init__(self):
@@ -45,6 +45,7 @@ def convert_to_options(config: Dict[str, Any]) -> SweepOptions:
45
45
 
46
46
  Raises:
47
47
  ValueError: Error is raised if config has unsupported structure
48
+
48
49
  """
49
50
  config = {k.lower(): v for k, v in config.items()}
50
51
  if {OPTIONS_TYPE.get("start"), OPTIONS_TYPE.get("stop")}.issubset(set(config)):
@@ -250,11 +250,12 @@ class Parameter:
250
250
  ``variables = [(par_x: [1,2,3])], extra_variables=[('y', 2)]`` yields the same 3-by-2 data. ``'y'`` will then be
251
251
  a "dimension without coordinate" in xarray terms.
252
252
 
253
- Args:
253
+ Args:
254
254
  variables: Coordinates of the set.
255
255
  data: Data Parameter and associated data as a possible nested list.
256
256
  attributes: metadata to attach to the whole Dataset.
257
257
  extra_variables: Valueless dimensions and their sizes.
258
+
258
259
  """
259
260
  variable_names = []
260
261
  variable_sizes = []
@@ -321,6 +322,7 @@ class Parameter:
321
322
 
322
323
  Returns:
323
324
  corresponding DataArray
325
+
324
326
  """
325
327
  if dimensions is None:
326
328
  if len(data.shape) == 1:
@@ -356,6 +358,7 @@ class Parameter:
356
358
 
357
359
  Raises:
358
360
  InvalidParameterValueError: If ``self`` is not collection-valued.
361
+
359
362
  """
360
363
  if self.collection_type is CollectionType.SCALAR:
361
364
  raise InvalidParameterValueError(
@@ -458,6 +461,7 @@ class Setting:
458
461
  Returns:
459
462
  A new set of Settings whose parameters are only found in `first`, and Settings in `first` whose
460
463
  values differ from their counterparts in `second`.
464
+
461
465
  """
462
466
  diff = first.difference(second)
463
467
  for s in first.intersection(second):
@@ -492,6 +496,7 @@ class Setting:
492
496
 
493
497
  Raises:
494
498
  ValueError: If ``self`` is not collection-valued.
499
+
495
500
  """
496
501
  return self.parameter.create_element_parameter_for(indices)
497
502
 
@@ -217,6 +217,7 @@ class SettingNode:
217
217
  children: The children given as keyword arguments. Each argument must be a :class:`.Setting`,
218
218
  :class:`.Parameter`, or a :class:`SettingNode`. The keywords are used as the names of the nodes.
219
219
  Parameters will be cast into Settings with the value ``None``.
220
+
220
221
  """
221
222
 
222
223
  def __init__(self, name: str, **children):
@@ -313,6 +314,7 @@ class SettingNode:
313
314
 
314
315
  Returns:
315
316
  Iterator that yields the filtered nodes.
317
+
316
318
  """
317
319
  node_types = node_types or (Setting, SettingNode)
318
320
  iterable = self if recursive else self.children.values()
@@ -328,6 +330,7 @@ class SettingNode:
328
330
 
329
331
  Raises:
330
332
  UnknownSettingError: If no setting is found in the children of this tree.
333
+
331
334
  """
332
335
 
333
336
  def list_assign(value, array, indices_list) -> None:
@@ -342,12 +345,11 @@ class SettingNode:
342
345
  if item.name == setting.name:
343
346
  branch[key] = setting.value
344
347
  return
345
- else:
346
- if isinstance(item, Setting) and item.name == setting.parent_name and item.element_indices is None:
347
- parent_value = item.value.copy()
348
- list_assign(setting.value, parent_value, setting.element_indices)
349
- branch[key] = parent_value
350
- return
348
+ elif isinstance(item, Setting) and item.name == setting.parent_name and item.element_indices is None:
349
+ parent_value = item.value.copy()
350
+ list_assign(setting.value, parent_value, setting.element_indices)
351
+ branch[key] = parent_value
352
+ return
351
353
  raise UnknownSettingError(
352
354
  f'No Setting with name {setting.name} was found in {self.__class__.__name__} "{self.name}".'
353
355
  )
@@ -384,6 +386,7 @@ class SettingNode:
384
386
 
385
387
  Returns:
386
388
  A SettingNode that has a child `name`.
389
+
387
390
  """
388
391
  for branch in self.nodes_by_type(SettingNode, recursive=True):
389
392
  for setting in branch.children.values():
@@ -399,6 +402,7 @@ class SettingNode:
399
402
 
400
403
  Returns:
401
404
  First found item, or None if nothing is found.
405
+
402
406
  """
403
407
  return next((item for item in self if item.name == name), None)
404
408
 
@@ -415,6 +419,7 @@ class SettingNode:
415
419
 
416
420
  Returns:
417
421
  A new SettingNode constructed from arguments.
422
+
418
423
  """
419
424
  new = second.copy()
420
425
  for key, item in first._settings.items():
@@ -462,12 +467,13 @@ class SettingNode:
462
467
 
463
468
  Args:
464
469
  levels: display this many levels, starting from the root.
470
+
465
471
  """
466
472
 
467
- def append_lines(key: str, node: SettingNode, lines: List[str], indents: List[bool]):
473
+ def append_lines(key: str, node: SettingNode, lines: List[str], indents: List[bool]): # noqa: F821
468
474
  indent = "".join([" ║ " if i else " " for i in indents])
469
475
  if len(indents) < levels:
470
- for key, setting in node._settings.items():
476
+ for key, setting in node._settings.items(): # noqa: PLR1704
471
477
  if setting.value is None:
472
478
  value = "None (automatic/unspecified)"
473
479
  elif setting.parameter.collection_type == CollectionType.NDARRAY:
@@ -509,6 +515,7 @@ class SettingNode:
509
515
 
510
516
  Return:
511
517
  A new SettingNode with the same structure as the original, but where node instances are of type `cls`.
518
+
512
519
  """
513
520
  new = cls(name=node.name, **node._settings)
514
521
  for key, subnode in node._subtrees.items():
@@ -525,6 +532,7 @@ class SettingNode:
525
532
 
526
533
  Raises:
527
534
  UnknownSettingError: If the condition of `strict` happens.
535
+
528
536
  """
529
537
  for key, value in dct.items():
530
538
  if key not in self.children:
@@ -536,7 +544,7 @@ class SettingNode:
536
544
  if isinstance(value, dict) and isinstance(self[key], SettingNode):
537
545
  self[key].set_from_dict(value)
538
546
  else:
539
- self[key] = self[key].parameter.data_type.cast(value) if type(value) == str else value
547
+ self[key] = self[key].parameter.data_type.cast(value) if type(value) == str else value # noqa: E721
540
548
 
541
549
  def setting_with_path_name(self, setting: Setting) -> Setting:
542
550
  """Get Setting from ``self`` where the name of the parameter is replaced with its path in ``self``.
@@ -553,6 +561,7 @@ class SettingNode:
553
561
 
554
562
  Raises:
555
563
  UnknownSettingError: If ``name`` is not found within ``self``.
564
+
556
565
  """
557
566
 
558
567
  def _search(settings: SettingNode, name: str, prefix: str) -> tuple[str, Setting] | tuple[None, None]:
@@ -566,7 +575,7 @@ class SettingNode:
566
575
 
567
576
  path, found_setting = _search(self, setting, "")
568
577
  if path is None:
569
- raise UnknownSettingError(f'{name} not found inside {self.__class__.__name__} "{self.name}".')
578
+ raise UnknownSettingError(f'{name} not found inside {self.__class__.__name__} "{self.name}".') # noqa: F821
570
579
  param = found_setting.parameter
571
580
  return Setting(
572
581
  Parameter(
@@ -593,12 +602,10 @@ class SettingNode:
593
602
 
594
603
  Returns:
595
604
  differences from ``self`` to ``other``, in depth-first order
596
- """
597
605
 
598
- # pylint: disable=too-many-branches
606
+ """
599
607
  def diff_settings(x: Setting, y: Setting, key: str) -> str:
600
608
  """Compare two settings, return the differences."""
601
-
602
609
  line = f"{key}:"
603
610
 
604
611
  def compare(x: Any, y: Any, tag: str) -> None:
@@ -669,7 +676,6 @@ class SettingNode:
669
676
 
670
677
  Unit must be a whitelisted SI base unit.
671
678
  """
672
-
673
679
  if not isinstance(val, numbers.Real):
674
680
  return val, unit
675
681
  if unit not in {"Hz", "rad", "s", "V"}:
@@ -3,6 +3,7 @@ class ExaError(Exception):
3
3
 
4
4
  Attributes:
5
5
  message: Error message.
6
+
6
7
  """
7
8
 
8
9
  def __init__(self, message: str, *args):
@@ -33,6 +33,7 @@ def add_data_array(ds: xr.Dataset, da: xr.DataArray, name: Optional[str] = None)
33
33
 
34
34
  Returns:
35
35
  The updated dataset.
36
+
36
37
  """
37
38
  if name is None:
38
39
  if da.name is not None:
@@ -44,8 +44,7 @@ def get_all_software_versions(reload_module: bool = False) -> dict[str, str]:
44
44
  it is disabled because reloading the module is not thread safe!
45
45
  This function should be called with ``reload_module=True`` when IPython autoreload is in use.
46
46
 
47
- Example:
48
-
47
+ Example:
49
48
  1. You have numpy==1.21.0 installed, and in the notebook you have executed the following IPython magic:
50
49
 
51
50
  .. code-block:: python
@@ -64,6 +63,7 @@ def get_all_software_versions(reload_module: bool = False) -> dict[str, str]:
64
63
  Returns: All software components in a dictionary that maps each package name to its version
65
64
  information. A package's version information contains the base version, and the string
66
65
  "(local editable)" in the case the package is a local editable installation.
66
+
67
67
  """
68
68
  python_version = platform.python_version()
69
69
  software_versions = {"python": python_version}
@@ -98,6 +98,7 @@ def get_vcs_description(root_directory: str) -> Optional[str]:
98
98
 
99
99
  Raises:
100
100
  If the command fails or timeouts, an exception will be raised directly from ``subprocess.check_output``.
101
+
101
102
  """
102
103
  # TODO does not seem very robust, consider using the full version number (e.g. 17.0.post1.dev9+g4748363.d20221003)
103
104
  # provided by setuptools_scm and accessed using importlib.metadata.version instead, if
@@ -19,7 +19,7 @@ from typing import Any, Callable, Optional
19
19
  BRIEF_DATEFMT = "%m-%d %H:%M:%S"
20
20
 
21
21
  BRIEF = "[{asctime};{levelname:.1}{extra_info}] {message}"
22
- VERBOSE = "[{asctime};{levelname};{processName}({process});{threadName}({thread});{name};{filename}:{lineno}:{funcName}{extra_info}] {message}" # pylint:disable=line-too-long
22
+ VERBOSE = "[{asctime};{levelname};{processName}({process});{threadName}({thread});{name};{filename}:{lineno}:{funcName}{extra_info}] {message}" # pylint:disable=line-too-long # noqa: E501
23
23
 
24
24
 
25
25
  class ExtraFormatter(logging.Formatter):
@@ -71,6 +71,7 @@ def init_loggers(
71
71
  verbose: If False, :const:``BRIEF`` format will be used for log messages, otherwise :const:``VERBOSE``.
72
72
  extra_info_getter: Optional callable to convey extra information to log messages. It will get called before
73
73
  each log message emission and the output will get appended to the log message.
74
+
74
75
  """
75
76
  loggers = loggers or {}
76
77
 
@@ -78,13 +79,12 @@ def init_loggers(
78
79
  loggers_config: dict[str, Any] = {}
79
80
  for logger_name, level in loggers.items():
80
81
  if not level:
81
- level = default_level
82
- level = level.upper()
82
+ level = default_level # noqa: PLW2901
83
+ level = level.upper() # noqa: PLW2901
83
84
  level_num = logging.getLevelName(level)
84
85
  if not isinstance(level_num, int):
85
86
  raise ValueError(f"Logger name '{logger_name}' has an incorrect level value '{level}'.")
86
- if level_num < lowest_level_num:
87
- lowest_level_num = level_num
87
+ lowest_level_num = min(level_num, lowest_level_num)
88
88
  loggers_config[logger_name] = {
89
89
  "level": level,
90
90
  "handlers": ["stdout", "stderr"],
@@ -150,6 +150,7 @@ class CHAD(ImmutableBaseModel):
150
150
  - Tuple of qubits and couplers mapped to their connected default operations.
151
151
  The data is in the form of a dict with the keys being `readout`, `drive`, and `flux`,
152
152
  and the values the list of component names having that particular operation.
153
+
153
154
  """
154
155
  self._validate_input(component_names)
155
156
 
@@ -190,6 +191,7 @@ class CHAD(ImmutableBaseModel):
190
191
 
191
192
  Raises:
192
193
  - ValueError: If the provided qubit name list contains duplicates.
194
+
193
195
  """
194
196
  self._validate_input(component_names)
195
197
 
@@ -208,6 +210,7 @@ class CHAD(ImmutableBaseModel):
208
210
 
209
211
  Args:
210
212
  component_names: The qubit names. May contain any number of qubits.
213
+
211
214
  """
212
215
  self._validate_input(component_names)
213
216
 
@@ -235,6 +238,7 @@ class CHAD(ImmutableBaseModel):
235
238
  Raises:
236
239
  - ValueError: If there were no couplers or more than one coupler connecting the component pair (the latter
237
240
  should not be possible in a realistic chip).
241
+
238
242
  """
239
243
  coupler_mapping = self.get_coupler_mapping_for([first_component, second_component])
240
244
  common_couplers = [
@@ -65,9 +65,9 @@ class ChipTopology:
65
65
  couplers: mapping from coupler name to names of chip components it connects to.
66
66
  probe_lines: mapping from probe line name to names of chip components it connects to.
67
67
  variant: identifier of the QPU design variant.
68
+
68
69
  """
69
70
 
70
- # pylint: disable=too-many-instance-attributes
71
71
  def __init__(
72
72
  self,
73
73
  qubits: Iterable[str],
@@ -143,8 +143,10 @@ class ChipTopology:
143
143
 
144
144
  Args:
145
145
  record: Record as returned by Station control.
146
+
146
147
  Returns:
147
148
  Corresponding chip topology
149
+
148
150
  """
149
151
  return cls.from_chad(CHAD(**record))
150
152
 
@@ -156,6 +158,7 @@ class ChipTopology:
156
158
  chad: parsed CHAD model
157
159
  Returns:
158
160
  corresponding chip topology
161
+
159
162
  """
160
163
  qubits = chad.qubit_names
161
164
  computational_resonators = chad.computational_resonator_names
@@ -178,6 +181,7 @@ class ChipTopology:
178
181
  components: some chip components, typically qubits and computational resonators
179
182
  Returns:
180
183
  couplers that connect to at least one of ``components``
184
+
181
185
  """
182
186
  couplers: set[str] = set()
183
187
  for component in components:
@@ -195,6 +199,7 @@ class ChipTopology:
195
199
  components: some chip components, typically qubits and computational resonators
196
200
  Returns:
197
201
  couplers that connect to only members of ``components``, and to at least two of them
202
+
198
203
  """
199
204
  connecting_couplers = set()
200
205
  for coupler in self.get_neighbor_couplers(components):
@@ -213,6 +218,7 @@ class ChipTopology:
213
218
  the common coupler
214
219
  Raises:
215
220
  ValueError: the given components have zero or more than one connecting coupler
221
+
216
222
  """
217
223
  connecting_couplers = self.get_connecting_couplers((component_1, component_2))
218
224
  if (n_couplers := len(connecting_couplers)) != 1:
@@ -226,6 +232,7 @@ class ChipTopology:
226
232
  components: some chip components, typically qubits and computational resonators
227
233
  Returns:
228
234
  components that are connected to ``components`` by a coupler, but not included in them
235
+
229
236
  """
230
237
  neighbor_components = set()
231
238
  for coupler in self.get_neighbor_couplers(components):
@@ -248,6 +255,7 @@ class ChipTopology:
248
255
 
249
256
  Returns:
250
257
  The input dictionary, but only with key-value pairs where the value intersects with `limit_to`.
258
+
251
259
  """
252
260
  return {key: values for key, values in dct.items() if any(v in limit_to for v in values)}
253
261
 
@@ -283,7 +291,8 @@ class ChipTopology:
283
291
  name: The name for the gate & implementation this locus mapping represents (typically in the format
284
292
  ``"<gate name>.<implementation name>"``).
285
293
  mapping: The locus mapping to be added.
286
- """
294
+
295
+ """ # noqa: E501
287
296
  self._validate_locus_mapping(mapping)
288
297
  self._locus_mappings[name] = mapping
289
298
 
@@ -311,6 +320,7 @@ class ChipTopology:
311
320
 
312
321
  Returns:
313
322
  The components mapped to the given locus or `None` if locus is not found in the given mapping.
323
+
314
324
  """
315
325
  if not name:
316
326
  if len(locus) == 1:
@@ -331,6 +341,7 @@ class ChipTopology:
331
341
 
332
342
  Returns:
333
343
  The locus mapped to the given components or `None` if the components are not mapped to any locus.
344
+
334
345
  """
335
346
  if name not in self._locus_mappings:
336
347
  return None
@@ -353,6 +364,7 @@ class ChipTopology:
353
364
 
354
365
  Returns:
355
366
  The loci associated with the given gate.
367
+
356
368
  """
357
369
  if name not in self._locus_mappings:
358
370
  if default_mapping_dimension == 1:
@@ -365,19 +377,20 @@ class ChipTopology:
365
377
  """Convenience method for getting the name of a computational resonator which is connected to both specified
366
378
  qubit components via tunable couplers.
367
379
 
368
- Args:
380
+ Args:
369
381
  first_qubit: The name of the first qubit.
370
382
  second_qubit: The name of the second qubit.
371
383
  The order of qubits does not matter, i.e. the `first_qubit` and `second_qubit` arguments are interchangeable.
372
384
 
373
- Returns:
385
+ Returns:
374
386
  - The name of the computational resonator that is connected to both inputted qubits via tunable couplers.
375
387
 
376
- Raises:
388
+ Raises:
377
389
  - ValueError: If no computational resonator was found that is connected to both qubits via tunable
378
390
  couplers.
391
+
379
392
  """
380
- neighbor_components = list(self.get_neighbor_locus_components([first_qubit, second_qubit]))
393
+ neighbor_components = list(self.get_neighbor_locus_components([first_qubit, second_qubit])) # noqa: F841
381
394
 
382
395
  resonators = [
383
396
  r
@@ -420,6 +433,7 @@ class ChipTopology:
420
433
 
421
434
  Returns:
422
435
  Names of the computational resonators neighboring all of ``qubits`` (can be an empty set).
436
+
423
437
  """
424
438
  if not qubits:
425
439
  return set()
@@ -42,6 +42,7 @@ class QCMDataClient:
42
42
  For example, CHAD files should be named {chip_label}.json, like M156_W531_A09_L09.json, and contain
43
43
  a list instead of a single object.
44
44
  fallback_root_url: Same as `root_url`, used if a query via `root_url` returns nothing.
45
+
45
46
  """
46
47
 
47
48
  def __init__(self, root_url: str, fallback_root_url: str = ""):
@@ -73,7 +74,7 @@ class QCMDataClient:
73
74
  Cache for :func:`get_chad` has to be reset when the URL changes.
74
75
  """
75
76
  if self._root_url != root_url:
76
- # pylint: disable=no-member
77
+
77
78
  self._root_url = root_url
78
79
 
79
80
  def get_chip_design_record(self, chip_label: str) -> dict:
@@ -84,6 +85,7 @@ class QCMDataClient:
84
85
 
85
86
  Returns:
86
87
  Data record matching the given chip label.
88
+
87
89
  """
88
90
  url_tail = f"/cheddars/{chip_label}?target=in-house"
89
91
  try:
@@ -39,6 +39,7 @@ def encode_nd_sweeps(sweeps: NdSweep, **kwargs) -> str:
39
39
 
40
40
  Returns:
41
41
  json as a string
42
+
42
43
  """
43
44
  kwargs.setdefault("cls", _SweepDataEncoder)
44
45
  return json.dumps(sweeps, **kwargs)
@@ -53,6 +54,7 @@ def encode_return_parameters_legacy(return_parameters: dict[Parameter, Optional[
53
54
 
54
55
  Returns:
55
56
  json as a string
57
+
56
58
  """
57
59
  kwargs.setdefault("cls", _SweepDataEncoder)
58
60
  return json.dumps(return_parameters, **kwargs)
@@ -67,6 +69,7 @@ def encode_return_parameters(return_parameters: dict[Parameter, Optional[NdSweep
67
69
 
68
70
  Returns:
69
71
  json as a string
72
+
70
73
  """
71
74
  kwargs.setdefault("cls", _SweepDataEncoder)
72
75
  listed_params = [{"parameter": param, "hard_sweeps": sweeps} for param, sweeps in return_parameters.items()]
@@ -84,6 +87,7 @@ def decode_and_validate_sweeps(sweeps_json: str) -> Sweeps:
84
87
 
85
88
  Raises:
86
89
  ValueError if decoded result is not expected return type
90
+
87
91
  """
88
92
  decoded = _loads(sweeps_json)
89
93
  if not isinstance(decoded, list):
@@ -118,6 +122,7 @@ def decode_return_parameters_legacy(json_str: str) -> dict[Parameter, Optional[N
118
122
 
119
123
  Return:
120
124
  a reconstituted, typed ``return_parameters`` structure
125
+
121
126
  """
122
127
 
123
128
  def decode_key(key: str) -> Parameter:
@@ -152,8 +157,8 @@ def decode_return_parameters(json_str: str) -> dict[Parameter, Optional[NdSweep]
152
157
 
153
158
  Return:
154
159
  a reconstituted, typed ``return_parameters`` structure
155
- """
156
160
 
161
+ """
157
162
  decoded = _loads(json_str)
158
163
  if not isinstance(decoded, list):
159
164
  raise ValueError(f"Outer type is not list type when decoding: {json_str}")
@@ -174,6 +179,7 @@ def decode_settings(json_str: str) -> SettingNode:
174
179
 
175
180
  Returns:
176
181
  deserialized settings
182
+
177
183
  """
178
184
  return SettingNodeModel(**json.loads(json_str)).decode()
179
185
 
@@ -189,6 +195,7 @@ def _legacy_return_parameters_to_new_format(
189
195
 
190
196
  Returns:
191
197
  `old` coerced to the new format.
198
+
192
199
  """
193
200
  new = {}
194
201
  for key, value in old.items():
@@ -217,6 +224,7 @@ def _loads(*args, **kwargs) -> Any:
217
224
  Returns:
218
225
  python data structure that recovers encoded structure of
219
226
  nested tuples and Sweep -objects
227
+
220
228
  """
221
229
 
222
230
  def _decode_json(obj: Any) -> Any:
@@ -231,7 +239,6 @@ def _loads(*args, **kwargs) -> Any:
231
239
  class _SweepDataEncoder(json.JSONEncoder):
232
240
  """Extension of json encoder to support handling of Sweep, Parameter, and tuples."""
233
241
 
234
- # pylint: disable=arguments-differ
235
242
  def default(self, obj: Any) -> Any:
236
243
  """Default encoder
237
244
 
@@ -240,6 +247,7 @@ class _SweepDataEncoder(json.JSONEncoder):
240
247
 
241
248
  Returns:
242
249
  encoded object
250
+
243
251
  """
244
252
  if isinstance(obj, Sweep):
245
253
  return json.loads(SweepModel.encode(obj).model_dump_json())
@@ -261,9 +269,8 @@ class _SweepDataEncoder(json.JSONEncoder):
261
269
 
262
270
  Returns:
263
271
  encoded object
264
- """
265
272
 
266
- # pylint: disable=arguments-differ
273
+ """
267
274
  def _encode_tuples(item):
268
275
  if isinstance(item, tuple):
269
276
  return get_json_encoder()[tuple](item)
exa/common/sweep/util.py CHANGED
@@ -51,6 +51,7 @@ def convert_sweeps_to_list_of_tuples(sweeps: Sweeps) -> NdSweep:
51
51
 
52
52
  Raises:
53
53
  ValueError if sweeps parameter does not follow the contract.
54
+
54
55
  """
55
56
  new_list = []
56
57
  for tuple_or_sweep in sweeps:
@@ -85,6 +86,7 @@ def linear_index_sweep(parameter: Parameter, length: int) -> list[tuple[LinearSw
85
86
  Returns:
86
87
  A linear sweep over a parameter whose name is ``parameter.name + _index`` and whose data ranges from 0 to
87
88
  `length` with steps of 1.
89
+
88
90
  """
89
91
  return [
90
92
  (
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: iqm-exa-common
3
- Version: 25.30
3
+ Version: 25.32
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
@@ -213,8 +213,8 @@ Classifier: Intended Audience :: Science/Research
213
213
  Requires-Python: >=3.11
214
214
  Description-Content-Type: text/x-rst
215
215
  License-File: LICENSE.txt
216
- Requires-Dist: iqm-data-definitions <3.0,>=2.4
217
- Requires-Dist: numpy <2.0,>=1.25.2
216
+ Requires-Dist: iqm-data-definitions <3.0,>=2.6
217
+ Requires-Dist: numpy <3.0,>=1.25.2
218
218
  Requires-Dist: pydantic <3.0,>=2.9.2
219
219
  Requires-Dist: python-dotenv ==0.21.1
220
220
  Requires-Dist: xarray ==2024.10.0
@@ -1,23 +1,23 @@
1
1
  exa/common/__init__.py,sha256=CCqrg7LHjBeIrjQJvw0nym_Ki6uxoZ7_WSbNDq_d0Lc,961
2
2
  exa/common/api/__init__.py,sha256=PAYujWNG8CtSQX_8U9gnubDh5cwGRhtOfLr0r0xGx3M,587
3
3
  exa/common/api/model/__init__.py,sha256=l3JxadYmX2p0ZcdwpdFZGumn9QFufWrGF36ePIqHA2I,635
4
- exa/common/api/model/parameter_model.py,sha256=vrnBKGFC6kDis8ovCWFfuYCxfwVvl4-7ueN7ZaFgkKM,3845
5
- exa/common/api/model/setting_model.py,sha256=7nNu7DQ3W3G3v3OU7Fq5k9Nu6W24fsBb5Hc0ixIMrms,2325
6
- exa/common/api/model/setting_node_model.py,sha256=BwKATLQbl9RlQdEbTFXz6Xjt1zFKKVZwAbbbos68evY,2653
4
+ exa/common/api/model/parameter_model.py,sha256=g2rDL8Pzjvlsy5wNd5p6mJPocKFnMSq74IaPsal_jgI,3854
5
+ exa/common/api/model/setting_model.py,sha256=6nwRSp_wdRarGgOdAUvxJCXvsXdoi5oX0KPi3YtJy9s,2334
6
+ exa/common/api/model/setting_node_model.py,sha256=Gr3_M1i4insutC3tmPbssAjh3uSn8404EKxtgfPEMak,2662
7
7
  exa/common/api/model/sweep_model.py,sha256=KQ95YwgYAbAp-BrqhKGkCnOS3H1TVImqKLcdwB3NeNQ,2454
8
8
  exa/common/api/proto_serialization/__init__.py,sha256=Vn2C79OqovFu5wJus9EHsMtK3Of1JLJDcpg2QZKmXsY,1565
9
- exa/common/api/proto_serialization/_parameter.py,sha256=StKUU9qsrg1E5QVZ7s3xjgOeERwyAn2NIRJdijb_hrY,2866
10
- exa/common/api/proto_serialization/array.py,sha256=HC17wqnolM17mDYhNUGvmPcaKJM8QaHtBtQR4cbcyEc,3136
11
- exa/common/api/proto_serialization/datum.py,sha256=E0N6HSUZmxHRDn1Z8pG1DPsPYky6GK0DrgRveCA635g,4909
12
- exa/common/api/proto_serialization/nd_sweep.py,sha256=cSdWnmgl6W9ZzIdnSxBwC-Ng1_xyUu6L3nxeS7PEBmQ,2894
13
- exa/common/api/proto_serialization/sequence.py,sha256=69ebCeTO95EBkfAianww8x7xMHF5WA7SaUhcopZJSBY,2403
14
- exa/common/api/proto_serialization/setting_node.py,sha256=LZ2hnSCVdAxwCbUAztrMnmHL16dBzR_sXD8EKsJO6nM,3726
9
+ exa/common/api/proto_serialization/_parameter.py,sha256=U7qUCZhtdKVe1yAiJgPwnYNHUC8b62cQ_dah1K8s2a8,2836
10
+ exa/common/api/proto_serialization/array.py,sha256=M5RVGjgdDLNB7bE6AMp11eTaBe3FKHTKjIU4UYQ6mlY,3111
11
+ exa/common/api/proto_serialization/datum.py,sha256=gFIAncWpOhy4V56DKYdKoasEIpGu1yUerSuRQf65unY,4828
12
+ exa/common/api/proto_serialization/nd_sweep.py,sha256=JfEOcISWZyfrVRaTvWkIwGRRlkSGKFwmOHVqbNlNKUw,2866
13
+ exa/common/api/proto_serialization/sequence.py,sha256=yIAxO6zdhsSkrUkJ5XonuLsf3nZQ-hHq8uzCwHkZaDU,2447
14
+ exa/common/api/proto_serialization/setting_node.py,sha256=eu2KwNtoxofthiVpdhCYowp7JTe1wdGRxMvn9bDr4Uo,3699
15
15
  exa/common/control/__init__.py,sha256=00T_xV0lL20QZcEt__vWq81N1oGF0KpJMhTitfAI4VI,629
16
16
  exa/common/control/sweep/__init__.py,sha256=GzKoQdQsLutcHhmrLPyPrW1n7Cpg766p3OWDHlRpuTs,607
17
- exa/common/control/sweep/exponential_sweep.py,sha256=wDhzyQLej9-3rgPWLVHR5tDFvVKXZOl63eEwAcpE410,3508
17
+ exa/common/control/sweep/exponential_sweep.py,sha256=kJbG2E8y4T4K0AlWknDv5LQotpk5whfu56KudjATpDY,3509
18
18
  exa/common/control/sweep/fixed_sweep.py,sha256=Cfcw2UgRml2XFxq9YjNEPUT3-Z8256y-J51ex4YMwE0,1472
19
19
  exa/common/control/sweep/function_sweep.py,sha256=1ce9cblpO6_jeTTkkaW91zSoLAhAVyseb9MboH8VFrI,1431
20
- exa/common/control/sweep/linear_sweep.py,sha256=aTPDZRpZU9Qpr_KJxtjIzW7i9pyztfPJ2ppgxjReg6k,3105
20
+ exa/common/control/sweep/linear_sweep.py,sha256=CDMo2lgTaeBlR49sEF3zPFXvtDoVr7lc6MDZ7aGbIXE,3106
21
21
  exa/common/control/sweep/sweep.py,sha256=nicqYN8_9k4RpD6DLoyom2XD_byjdc9TZvK2kAXJrFI,1531
22
22
  exa/common/control/sweep/utils.py,sha256=9moO0qnuF_xuvWkWuwYjLV2ejXnDXTogARVQz_jESo4,1610
23
23
  exa/common/control/sweep/option/__init__.py,sha256=R_KvrmH-FCC1K0ixtFr1QmOTiyS3lhIgFVDmCQBKSuU,951
@@ -26,34 +26,34 @@ exa/common/control/sweep/option/center_span_options.py,sha256=uqug4eP9bY0ucVcD97
26
26
  exa/common/control/sweep/option/constants.py,sha256=5elNQvsIvJ95WXSywadGqj-X74nuu3gNYaTHi2tsQNA,1422
27
27
  exa/common/control/sweep/option/fixed_options.py,sha256=qxgpsJupq5kwrYxO9D9656t3L4XIwJm6E0wzt03zjz8,930
28
28
  exa/common/control/sweep/option/function_options.py,sha256=9X21CndZK_pubfkKtDvFBIJCOgrBr_t8Jx3suutAb-o,930
29
- exa/common/control/sweep/option/option_converter.py,sha256=DDU7rspvOaG3hMPCnLr-kF8_omBFFhYqczLypDN65xg,3809
29
+ exa/common/control/sweep/option/option_converter.py,sha256=Jp_eK90wGW8inLxec_wHC_Mc-m_mSMrHBsL42dW2Vsk,3810
30
30
  exa/common/control/sweep/option/start_stop_base_options.py,sha256=gsB3w92kZCCy-hxXjV0BYGkqodpK20dyIBQyl0nBGXI,1835
31
31
  exa/common/control/sweep/option/start_stop_options.py,sha256=sFIQpAfh-gBdfeETEfg7axuCDo28R2-PckQ02DXWqHY,2497
32
32
  exa/common/control/sweep/option/sweep_options.py,sha256=ToyNX9FifKxa-_TTVCuFuTRZIdep8yBtPR86EgbtJrQ,698
33
33
  exa/common/data/__init__.py,sha256=F5SRe5QHBTjef4XJVQ63kO5Oxc_AiZnPbV560i7La0Y,644
34
- exa/common/data/parameter.py,sha256=XX6GHY8H9fMarMy0dfXGvLflPnRc8b_MRR567iOsOeM,20754
35
- exa/common/data/setting_node.py,sha256=8qibht7-25zNxlDjNWhphZwDozhr3CZIWho91OOG5Sc,26995
34
+ exa/common/data/parameter.py,sha256=mVLuXHa830FMWqAHIpYJNFQzA9pxX8zGNIURMRuFoXU,20758
35
+ exa/common/data/setting_node.py,sha256=NUTwF1vEvJKBF5GgCMG2za7-9C28MdeR0ei_cmhGjhw,26978
36
36
  exa/common/data/settingnode_v2.html.jinja2,sha256=1cADQhBi0c7xewh1ZxWXBQqvTI-jxZNJdEUgS44SPWU,3125
37
37
  exa/common/errors/__init__.py,sha256=ArMBdpmx1EUenBpzrSNG63kmUf7PM0gCqSYnaCnL9Qk,597
38
- exa/common/errors/exa_error.py,sha256=VApLIK-fxgFGzKuE_2CjuL1znYtXeSR923YenfnOUOs,974
38
+ exa/common/errors/exa_error.py,sha256=eB_c-Qp1OchcBMr3LSyYitity4SochQh-nAghZmGLJU,975
39
39
  exa/common/helpers/__init__.py,sha256=IgtVD3tojIFA4MTV2mT5uYM6jb2qny9kBIIhEZT2PuI,610
40
- exa/common/helpers/data_helper.py,sha256=KkNL-X4Cst5tn24OJ39PlYVyjE231vVFeC9OkLMRF-o,1933
40
+ exa/common/helpers/data_helper.py,sha256=vhzJ63g1S2JqnCj0WJJuqWcuiIwKATnQeHdWw_3gkZg,1934
41
41
  exa/common/helpers/json_helper.py,sha256=VTcYU8FRgv3tXPifuogUWmVAzt_4JoQ_laTHolyodtA,2672
42
42
  exa/common/helpers/numpy_helper.py,sha256=alzUdIHQJxDygvpLaTFCIOizFHo5wRY1eD8o8bnt1rU,1061
43
- exa/common/helpers/software_version_helper.py,sha256=8DFq7eHnWUsfbPKZauMlXVtJQQ7PoQaPXAzB42r5MgU,5169
43
+ exa/common/helpers/software_version_helper.py,sha256=kpuQer4p1p4cj9_CzwziBSCX7wuH-FvfNw8G8U-EI3Y,5162
44
44
  exa/common/logger/__init__.py,sha256=D_fMkDh4oXaoCNVV1sdusCv7W4G_81g-eBJOddEWSxo,685
45
- exa/common/logger/logger.py,sha256=7yIRbwI8-tft70J3m4nuClJM1B3qKZOvOyy1EaaUCgo,5689
45
+ exa/common/logger/logger.py,sha256=McZSKAl3JdfBnqd4RPJrO_mjN5mQ4XMJWSlEiq4fsCs,5716
46
46
  exa/common/qcm_data/__init__.py,sha256=VtsYkGoaniSjCkY0oQlqkcYJCtmC2sTDxfrIe_kpqZg,567
47
- exa/common/qcm_data/chad_model.py,sha256=xU2_CZB4OyOSuyVH_9bw0UT7xk3QdlkJ7DE4h7KrkOU,11218
48
- exa/common/qcm_data/chip_topology.py,sha256=dTTcfhlGy0gaN3bRqB6yl8Geddov2Sax5wUfO1GEx50,19338
47
+ exa/common/qcm_data/chad_model.py,sha256=9CkHU7lsoa-LEG9pstNaTslW4tuydTzzm9Dt2sB48PQ,11222
48
+ exa/common/qcm_data/chip_topology.py,sha256=voF2iJ3zKQ0wmTrD32oYs2sROAFGgombcyEvVuDwlB0,19327
49
49
  exa/common/qcm_data/file_adapter.py,sha256=cqjnRUK-arKWEP4N7wwmH8nUjVZsNhM7aXaLjAQvSoE,2530
50
50
  exa/common/qcm_data/immutable_base_model.py,sha256=QXmKIWQbsbWQvovXwKT1d9jtyf2LNJtjQquIwO52zOU,901
51
- exa/common/qcm_data/qcm_data_client.py,sha256=r--H5QAmYYbHcl5STsfNwr0TESGall-pscz7YtA4DSs,7713
51
+ exa/common/qcm_data/qcm_data_client.py,sha256=iYZfLc12yy1rQdxSgOVQyPmP5ConeqZ2G6VMSE6FMiI,7676
52
52
  exa/common/sweep/__init__.py,sha256=uEKk5AtzSgSnf8Y0geRPwUpqXIBIXpeCxsN64sX7F1o,591
53
- exa/common/sweep/database_serialization.py,sha256=z9jXM_nkn3V84Y3fAlF3HN9YLjigS0g1BV4AIZTEhRs,10033
54
- exa/common/sweep/util.py,sha256=46sDCs-tXRCnDY_xeLeDLZ_9918QQ5KreERa3KENkiM,3783
55
- iqm_exa_common-25.30.dist-info/LICENSE.txt,sha256=R6Q7eUrLyoCQgWYorQ8WJmVmWKYU3dxA3jYUp0wwQAw,11332
56
- iqm_exa_common-25.30.dist-info/METADATA,sha256=8Rr2ZqFbdJn3vvUEj4TzHo5L0ccXNimVEME3YzK2s6Q,14548
57
- iqm_exa_common-25.30.dist-info/WHEEL,sha256=y4mX-SOX4fYIkonsAGA5N0Oy-8_gI4FXw5HNI1xqvWg,91
58
- iqm_exa_common-25.30.dist-info/top_level.txt,sha256=Clphg2toaZ3_jSFRPhjMNEmLurkMNMc4lkK2EFYsSlM,4
59
- iqm_exa_common-25.30.dist-info/RECORD,,
53
+ exa/common/sweep/database_serialization.py,sha256=WHu2E4Ksewc_HiFp7OI8Q8cra73Kr4jhjdJuoOHHSug,9960
54
+ exa/common/sweep/util.py,sha256=1AW8lvuNnUG0sn4p0LKc-IlfGPXuVDAiSK6MIaw5FGM,3785
55
+ iqm_exa_common-25.32.dist-info/LICENSE.txt,sha256=R6Q7eUrLyoCQgWYorQ8WJmVmWKYU3dxA3jYUp0wwQAw,11332
56
+ iqm_exa_common-25.32.dist-info/METADATA,sha256=bhpYfq9MD7ECjNeip7x6Afyr5e3QQ3Oy1fiTFpwcDvY,14548
57
+ iqm_exa_common-25.32.dist-info/WHEEL,sha256=y4mX-SOX4fYIkonsAGA5N0Oy-8_gI4FXw5HNI1xqvWg,91
58
+ iqm_exa_common-25.32.dist-info/top_level.txt,sha256=Clphg2toaZ3_jSFRPhjMNEmLurkMNMc4lkK2EFYsSlM,4
59
+ iqm_exa_common-25.32.dist-info/RECORD,,