shepherd-core 2025.4.1__py3-none-any.whl → 2025.4.2__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 (55) hide show
  1. shepherd_core/calibration_hw_def.py +11 -11
  2. shepherd_core/commons.py +4 -4
  3. shepherd_core/data_models/base/cal_measurement.py +10 -11
  4. shepherd_core/data_models/base/calibration.py +7 -6
  5. shepherd_core/data_models/base/content.py +1 -1
  6. shepherd_core/data_models/base/shepherd.py +6 -7
  7. shepherd_core/data_models/base/wrapper.py +2 -2
  8. shepherd_core/data_models/content/energy_environment.py +4 -3
  9. shepherd_core/data_models/content/firmware.py +9 -7
  10. shepherd_core/data_models/content/virtual_harvester.py +30 -22
  11. shepherd_core/data_models/content/virtual_source.py +16 -15
  12. shepherd_core/data_models/experiment/experiment.py +13 -13
  13. shepherd_core/data_models/experiment/observer_features.py +7 -8
  14. shepherd_core/data_models/experiment/target_config.py +12 -12
  15. shepherd_core/data_models/task/__init__.py +5 -5
  16. shepherd_core/data_models/task/emulation.py +13 -14
  17. shepherd_core/data_models/task/firmware_mod.py +11 -11
  18. shepherd_core/data_models/task/harvest.py +7 -6
  19. shepherd_core/data_models/task/observer_tasks.py +7 -7
  20. shepherd_core/data_models/task/programming.py +11 -11
  21. shepherd_core/data_models/task/testbed_tasks.py +8 -8
  22. shepherd_core/data_models/testbed/cape.py +7 -6
  23. shepherd_core/data_models/testbed/gpio.py +8 -7
  24. shepherd_core/data_models/testbed/mcu.py +8 -7
  25. shepherd_core/data_models/testbed/observer.py +9 -7
  26. shepherd_core/data_models/testbed/target.py +9 -7
  27. shepherd_core/data_models/testbed/testbed.py +11 -10
  28. shepherd_core/decoder_waveform/uart.py +5 -5
  29. shepherd_core/fw_tools/converter.py +4 -3
  30. shepherd_core/fw_tools/patcher.py +14 -15
  31. shepherd_core/fw_tools/validation.py +3 -2
  32. shepherd_core/inventory/__init__.py +6 -6
  33. shepherd_core/inventory/python.py +1 -1
  34. shepherd_core/inventory/system.py +11 -8
  35. shepherd_core/inventory/target.py +3 -3
  36. shepherd_core/logger.py +2 -2
  37. shepherd_core/reader.py +37 -39
  38. shepherd_core/testbed_client/client_abc_fix.py +20 -13
  39. shepherd_core/testbed_client/client_web.py +18 -11
  40. shepherd_core/testbed_client/fixtures.py +19 -16
  41. shepherd_core/testbed_client/user_model.py +6 -5
  42. shepherd_core/version.py +1 -1
  43. shepherd_core/vsource/target_model.py +3 -3
  44. shepherd_core/vsource/virtual_converter_model.py +3 -3
  45. shepherd_core/vsource/virtual_harvester_model.py +7 -9
  46. shepherd_core/vsource/virtual_harvester_simulation.py +6 -5
  47. shepherd_core/vsource/virtual_source_model.py +6 -5
  48. shepherd_core/vsource/virtual_source_simulation.py +7 -6
  49. shepherd_core/writer.py +32 -34
  50. {shepherd_core-2025.4.1.dist-info → shepherd_core-2025.4.2.dist-info}/METADATA +2 -3
  51. shepherd_core-2025.4.2.dist-info/RECORD +81 -0
  52. {shepherd_core-2025.4.1.dist-info → shepherd_core-2025.4.2.dist-info}/WHEEL +1 -1
  53. shepherd_core-2025.4.1.dist-info/RECORD +0 -81
  54. {shepherd_core-2025.4.1.dist-info → shepherd_core-2025.4.2.dist-info}/top_level.txt +0 -0
  55. {shepherd_core-2025.4.1.dist-info → shepherd_core-2025.4.2.dist-info}/zip-safe +0 -0
@@ -16,10 +16,8 @@ Compromises:
16
16
 
17
17
  """
18
18
 
19
- from typing import Tuple
20
-
21
- from ..data_models.content.virtual_harvester import HarvesterPRUConfig
22
- from ..logger import logger
19
+ from shepherd_core.data_models.content.virtual_harvester import HarvesterPRUConfig
20
+ from shepherd_core.logger import logger
23
21
 
24
22
 
25
23
  class VirtualHarvesterModel:
@@ -94,7 +92,7 @@ class VirtualHarvesterModel:
94
92
  self.voltage_nxt: int = 0
95
93
  self.current_nxt: int = 0
96
94
 
97
- def ivcurve_sample(self, _voltage_uV: int, _current_nA: int) -> Tuple[int, int]:
95
+ def ivcurve_sample(self, _voltage_uV: int, _current_nA: int) -> tuple[int, int]:
98
96
  if self._cfg.window_size <= 1:
99
97
  return _voltage_uV, _current_nA
100
98
  if self._cfg.algorithm >= self.HRV_MPPT_OPT:
@@ -108,7 +106,7 @@ class VirtualHarvesterModel:
108
106
  # next line is only implied in C
109
107
  return _voltage_uV, _current_nA
110
108
 
111
- def ivcurve_2_cv(self, _voltage_uV: int, _current_nA: int) -> Tuple[int, int]:
109
+ def ivcurve_2_cv(self, _voltage_uV: int, _current_nA: int) -> tuple[int, int]:
112
110
  compare_now = _voltage_uV < self.voltage_set_uV
113
111
  step_size_now = abs(_voltage_uV - self.voltage_last)
114
112
  distance_now = abs(_voltage_uV - self.voltage_set_uV)
@@ -146,7 +144,7 @@ class VirtualHarvesterModel:
146
144
  self.compare_last = compare_now
147
145
  return self.voltage_hold, self.current_hold
148
146
 
149
- def ivcurve_2_mppt_voc(self, _voltage_uV: int, _current_nA: int) -> Tuple[int, int]:
147
+ def ivcurve_2_mppt_voc(self, _voltage_uV: int, _current_nA: int) -> tuple[int, int]:
150
148
  self.interval_step = self.interval_step + 1
151
149
  if self.interval_step >= self._cfg.interval_n:
152
150
  self.interval_step = 0
@@ -176,7 +174,7 @@ class VirtualHarvesterModel:
176
174
 
177
175
  return _voltage_uV, _current_nA
178
176
 
179
- def ivcurve_2_mppt_po(self, _voltage_uV: int, _current_nA: int) -> Tuple[int, int]:
177
+ def ivcurve_2_mppt_po(self, _voltage_uV: int, _current_nA: int) -> tuple[int, int]:
180
178
  self.interval_step = self.interval_step + 1
181
179
  if self.interval_step >= self._cfg.interval_n:
182
180
  self.interval_step = 0
@@ -220,7 +218,7 @@ class VirtualHarvesterModel:
220
218
 
221
219
  return _voltage_uV, _current_nA
222
220
 
223
- def ivcurve_2_mppt_opt(self, _voltage_uV: int, _current_nA: int) -> Tuple[int, int]:
221
+ def ivcurve_2_mppt_opt(self, _voltage_uV: int, _current_nA: int) -> tuple[int, int]:
224
222
  self.age_now += 1
225
223
  self.age_nxt += 1
226
224
 
@@ -13,11 +13,12 @@ from typing import Optional
13
13
 
14
14
  from tqdm import tqdm
15
15
 
16
- from .. import CalibrationHarvester
17
- from .. import Reader
18
- from .. import Writer
19
- from ..data_models.content.virtual_harvester import HarvesterPRUConfig
20
- from ..data_models.content.virtual_harvester import VirtualHarvesterConfig
16
+ from shepherd_core.data_models.base.calibration import CalibrationHarvester
17
+ from shepherd_core.data_models.content.virtual_harvester import HarvesterPRUConfig
18
+ from shepherd_core.data_models.content.virtual_harvester import VirtualHarvesterConfig
19
+ from shepherd_core.reader import Reader
20
+ from shepherd_core.writer import Writer
21
+
21
22
  from .virtual_harvester_model import VirtualHarvesterModel
22
23
 
23
24
 
@@ -12,11 +12,12 @@ NOTE: DO NOT OPTIMIZE -> stay close to original code-base
12
12
 
13
13
  from typing import Optional
14
14
 
15
- from ..data_models import CalibrationEmulator
16
- from ..data_models import EnergyDType
17
- from ..data_models import VirtualSourceConfig
18
- from ..data_models.content.virtual_harvester import HarvesterPRUConfig
19
- from ..data_models.content.virtual_source import ConverterPRUConfig
15
+ from shepherd_core.data_models.base.calibration import CalibrationEmulator
16
+ from shepherd_core.data_models.content.energy_environment import EnergyDType
17
+ from shepherd_core.data_models.content.virtual_harvester import HarvesterPRUConfig
18
+ from shepherd_core.data_models.content.virtual_source import ConverterPRUConfig
19
+ from shepherd_core.data_models.content.virtual_source import VirtualSourceConfig
20
+
20
21
  from .virtual_converter_model import PruCalibration
21
22
  from .virtual_converter_model import VirtualConverterModel
22
23
  from .virtual_harvester_model import VirtualHarvesterModel
@@ -14,13 +14,14 @@ from typing import Optional
14
14
  import numpy as np
15
15
  from tqdm import tqdm
16
16
 
17
- from .. import CalibrationEmulator
18
- from .. import Reader
19
- from .. import Writer
20
- from ..data_models import VirtualSourceConfig
21
- from ..logger import logger
22
- from . import VirtualSourceModel
17
+ from shepherd_core.data_models.base.calibration import CalibrationEmulator
18
+ from shepherd_core.data_models.content.virtual_source import VirtualSourceConfig
19
+ from shepherd_core.logger import logger
20
+ from shepherd_core.reader import Reader
21
+ from shepherd_core.writer import Writer
22
+
23
23
  from .target_model import TargetABC
24
+ from .virtual_source_model import VirtualSourceModel
24
25
 
25
26
 
26
27
  def simulate_source(
shepherd_core/writer.py CHANGED
@@ -3,14 +3,13 @@
3
3
  import logging
4
4
  import math
5
5
  import pathlib
6
+ from collections.abc import Mapping
6
7
  from datetime import timedelta
7
8
  from itertools import product
8
9
  from pathlib import Path
9
10
  from types import TracebackType
10
11
  from typing import Any
11
- from typing import Mapping
12
12
  from typing import Optional
13
- from typing import Type
14
13
  from typing import Union
15
14
 
16
15
  import h5py
@@ -18,11 +17,10 @@ import numpy as np
18
17
  import yaml
19
18
  from pydantic import validate_call
20
19
  from typing_extensions import Self
21
- from yaml import Dumper
20
+ from yaml import Node
22
21
  from yaml import SafeDumper
23
- from yaml import ScalarNode
24
22
 
25
- from .commons import samplerate_sps_default
23
+ from .commons import SAMPLERATE_SPS_DEFAULT
26
24
  from .data_models.base.calibration import CalibrationEmulator as CalEmu
27
25
  from .data_models.base.calibration import CalibrationHarvester as CalHrv
28
26
  from .data_models.base.calibration import CalibrationSeries as CalSeries
@@ -34,13 +32,13 @@ from .reader import Reader
34
32
 
35
33
  # copy of core/models/base/shepherd - needed also here
36
34
  def path2str(
37
- dumper: Dumper, data: Union[pathlib.Path, pathlib.WindowsPath, pathlib.PosixPath]
38
- ) -> ScalarNode:
35
+ dumper: SafeDumper, data: Union[pathlib.Path, pathlib.WindowsPath, pathlib.PosixPath]
36
+ ) -> Node:
39
37
  """Add a yaml-representation for a specific datatype."""
40
38
  return dumper.represent_scalar("tag:yaml.org,2002:str", str(data.as_posix()))
41
39
 
42
40
 
43
- def time2int(dumper: Dumper, data: timedelta) -> ScalarNode:
41
+ def time2int(dumper: SafeDumper, data: timedelta) -> Node:
44
42
  """Add a yaml-representation for a specific datatype."""
45
43
  return dumper.represent_scalar("tag:yaml.org,2002:int", str(int(data.total_seconds())))
46
44
 
@@ -93,11 +91,10 @@ class Writer(Reader):
93
91
 
94
92
  """
95
93
 
96
- comp_default: int = 1
97
- mode_default: str = "harvester"
98
- datatype_default: EnergyDType = EnergyDType.ivsample
94
+ MODE_DEFAULT: str = "harvester"
95
+ DATATYPE_DEFAULT: EnergyDType = EnergyDType.ivsample
99
96
 
100
- _chunk_shape: tuple = (Reader.samples_per_buffer,)
97
+ _CHUNK_SHAPE: tuple = (Reader.BUFFER_SAMPLES_N,)
101
98
 
102
99
  @validate_call
103
100
  def __init__(
@@ -111,7 +108,7 @@ class Writer(Reader):
111
108
  *,
112
109
  modify_existing: bool = False,
113
110
  force_overwrite: bool = False,
114
- verbose: Optional[bool] = True,
111
+ verbose: bool = True,
115
112
  ) -> None:
116
113
  self._modify = modify_existing
117
114
  if compression is not None:
@@ -124,41 +121,42 @@ class Writer(Reader):
124
121
  # -> logger gets configured in reader()
125
122
 
126
123
  if self._modify or force_overwrite or not file_path.exists():
127
- self.file_path: Path = file_path.resolve()
128
- self._logger.info("Storing data to '%s'", self.file_path)
124
+ file_path = file_path.resolve()
125
+ self._logger.info("Storing data to '%s'", file_path)
129
126
  elif file_path.exists() and not file_path.is_file():
130
127
  msg = f"Path is not a file ({file_path})"
131
128
  raise TypeError(msg)
132
129
  else:
133
130
  base_dir = file_path.resolve().parents[0]
134
- self.file_path = unique_path(base_dir / file_path.stem, file_path.suffix)
131
+ file_path_new = unique_path(base_dir / file_path.stem, file_path.suffix)
135
132
  self._logger.warning(
136
133
  "File '%s' already exists -> storing under '%s' instead",
137
134
  file_path,
138
- self.file_path.name,
135
+ file_path_new.name,
139
136
  )
137
+ file_path = file_path_new
140
138
 
141
139
  # open file
142
140
  if self._modify:
143
- self.h5file = h5py.File(self.file_path, "r+") # = rw
141
+ self.h5file = h5py.File(file_path, "r+") # = rw
144
142
  else:
145
- if not self.file_path.parent.exists():
146
- self.file_path.parent.mkdir(parents=True)
147
- self.h5file = h5py.File(self.file_path, "w")
143
+ if not file_path.parent.exists():
144
+ file_path.parent.mkdir(parents=True)
145
+ self.h5file = h5py.File(file_path, "w")
148
146
  # ⤷ write, truncate if exist
149
147
  self._create_skeleton()
150
148
 
151
149
  # Handle Mode
152
- if isinstance(mode, str) and mode not in self.mode_dtype_dict:
153
- msg = f"Can't handle mode '{mode}' (choose one of {self.mode_dtype_dict})"
150
+ if isinstance(mode, str) and mode not in self.MODE_TO_DTYPE:
151
+ msg = f"Can't handle mode '{mode}' (choose one of {self.MODE_TO_DTYPE})"
154
152
  raise ValueError(msg)
155
153
 
156
154
  if mode is not None:
157
155
  self.h5file.attrs["mode"] = mode
158
156
  if "mode" not in self.h5file.attrs:
159
- self.h5file.attrs["mode"] = self.mode_default
157
+ self.h5file.attrs["mode"] = self.MODE_DEFAULT
160
158
 
161
- _dtypes = self.mode_dtype_dict[self.get_mode()]
159
+ _dtypes = self.MODE_TO_DTYPE[self.get_mode()]
162
160
 
163
161
  # Handle Datatype
164
162
  if isinstance(datatype, str):
@@ -170,7 +168,7 @@ class Writer(Reader):
170
168
  if isinstance(datatype, EnergyDType):
171
169
  self.h5file["data"].attrs["datatype"] = datatype.name
172
170
  if "datatype" not in self.h5file["data"].attrs:
173
- self.h5file["data"].attrs["datatype"] = self.datatype_default.name
171
+ self.h5file["data"].attrs["datatype"] = self.DATATYPE_DEFAULT.name
174
172
  if self.get_datatype() not in _dtypes:
175
173
  msg = (
176
174
  f"Can't handle value '{self.get_datatype()}' of datatype (choose one of {_dtypes})"
@@ -204,7 +202,7 @@ class Writer(Reader):
204
202
  settings = list(self.h5file.id.get_access_plist().get_cache())
205
203
  self._logger.debug("H5Py Cache_setting=%s (_mdc, _nslots, _nbytes, _w0)", settings)
206
204
 
207
- super().__init__(file_path=None, verbose=verbose)
205
+ super().__init__(file_path=file_path, verbose=verbose)
208
206
 
209
207
  def __enter__(self) -> Self:
210
208
  super().__enter__()
@@ -212,7 +210,7 @@ class Writer(Reader):
212
210
 
213
211
  def __exit__(
214
212
  self,
215
- typ: Optional[Type[BaseException]] = None,
213
+ typ: Optional[type[BaseException]] = None,
216
214
  exc: Optional[BaseException] = None,
217
215
  tb: Optional[TracebackType] = None,
218
216
  extra_arg: int = 0,
@@ -251,7 +249,7 @@ class Writer(Reader):
251
249
  (0,),
252
250
  dtype="u8",
253
251
  maxshape=(None,),
254
- chunks=self._chunk_shape,
252
+ chunks=self._CHUNK_SHAPE,
255
253
  compression=self._compression,
256
254
  )
257
255
  grp_data["time"].attrs["unit"] = "s"
@@ -262,7 +260,7 @@ class Writer(Reader):
262
260
  (0,),
263
261
  dtype="u4",
264
262
  maxshape=(None,),
265
- chunks=self._chunk_shape,
263
+ chunks=self._CHUNK_SHAPE,
266
264
  compression=self._compression,
267
265
  )
268
266
  grp_data["current"].attrs["unit"] = "A"
@@ -273,7 +271,7 @@ class Writer(Reader):
273
271
  (0,),
274
272
  dtype="u4",
275
273
  maxshape=(None,),
276
- chunks=self._chunk_shape,
274
+ chunks=self._CHUNK_SHAPE,
277
275
  compression=self._compression,
278
276
  )
279
277
  grp_data["voltage"].attrs["unit"] = "V"
@@ -347,10 +345,10 @@ class Writer(Reader):
347
345
  def _align(self) -> None:
348
346
  """Align datasets with buffer-size of shepherd."""
349
347
  self._refresh_file_stats()
350
- n_buff = self.ds_voltage.size / self.samples_per_buffer
351
- size_new = int(math.floor(n_buff) * self.samples_per_buffer)
348
+ n_buff = self.ds_voltage.size / self.BUFFER_SAMPLES_N
349
+ size_new = int(math.floor(n_buff) * self.BUFFER_SAMPLES_N)
352
350
  if size_new < self.ds_voltage.size:
353
- if self.samplerate_sps != samplerate_sps_default:
351
+ if self.samplerate_sps != SAMPLERATE_SPS_DEFAULT:
354
352
  self._logger.debug("skipped alignment due to altered samplerate")
355
353
  return
356
354
  self._logger.info(
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: shepherd_core
3
- Version: 2025.4.1
3
+ Version: 2025.4.2
4
4
  Summary: Programming- and CLI-Interface for the h5-dataformat of the Shepherd-Testbed
5
5
  Author-email: Ingmar Splitt <ingmar.splitt@tu-dresden.de>
6
6
  Maintainer-email: Ingmar Splitt <ingmar.splitt@tu-dresden.de>
@@ -18,7 +18,6 @@ Classifier: Development Status :: 5 - Production/Stable
18
18
  Classifier: Intended Audience :: Developers
19
19
  Classifier: Intended Audience :: Information Technology
20
20
  Classifier: Intended Audience :: Science/Research
21
- Classifier: Programming Language :: Python :: 3.8
22
21
  Classifier: Programming Language :: Python :: 3.9
23
22
  Classifier: Programming Language :: Python :: 3.10
24
23
  Classifier: Programming Language :: Python :: 3.11
@@ -27,7 +26,7 @@ Classifier: Programming Language :: Python :: 3.13
27
26
  Classifier: License :: OSI Approved :: MIT License
28
27
  Classifier: Operating System :: OS Independent
29
28
  Classifier: Natural Language :: English
30
- Requires-Python: >=3.8
29
+ Requires-Python: >=3.9
31
30
  Description-Content-Type: text/markdown
32
31
  Requires-Dist: h5py
33
32
  Requires-Dist: numpy
@@ -0,0 +1,81 @@
1
+ shepherd_core/__init__.py,sha256=fCld2mcl0y0h6kRyPal3DP-sWXnKl_0aYWYBdg4QuUk,1270
2
+ shepherd_core/calibration_hw_def.py,sha256=aL94bA1Sf14L5A3PLdVvQVYtGi28S4NUWA65wbim8bw,2895
3
+ shepherd_core/commons.py,sha256=rTxtndtiJ4cOHYRPRbdZdqp6T90CKFFN-I-YAFzhm4Q,200
4
+ shepherd_core/logger.py,sha256=i8j3alm8icAx_h1_IZ6SgVgC9W5J7S-bDc31mPDWl-w,1812
5
+ shepherd_core/reader.py,sha256=Xu_MSADsR4Xzh8YH-N50mKIHZlhPyFigv8umQSsYsJ0,28320
6
+ shepherd_core/version.py,sha256=dd_uzGz0uQwh1pttFJSjXzIKovnBzMAXJGgpRa5QR34,76
7
+ shepherd_core/writer.py,sha256=HRiCnJRM4hIBT6UBZJZ5ZOZ79OyBpBN4a2kX-XmOYRE,14574
8
+ shepherd_core/data_models/__init__.py,sha256=bnHSP_HBOYm4WuoiHs_vyiRsWlvkyDjsarMNfKedN-Q,1836
9
+ shepherd_core/data_models/readme.md,sha256=DHPVmkWqDksWomRHRTVWVHy9wXF9oMJrITgKs4Pnz2g,2494
10
+ shepherd_core/data_models/virtual_source_doc.txt,sha256=KizMcfGKj7BnHIbaJHT7KeTF01SV__UXv01qV_DGHSs,6057
11
+ shepherd_core/data_models/base/__init__.py,sha256=PSJ6acWViqBm0Eiom8DIgKfFVrp5lzYr8OsDvP79vwI,94
12
+ shepherd_core/data_models/base/cal_measurement.py,sha256=c-vjACNxsQY8LU2Msw0COrsTY-8pToJ5ZWkOztJ9tVY,3380
13
+ shepherd_core/data_models/base/calibration.py,sha256=oUTfY6iUWUbBbOw5aMCRkdEfHzIV8aUrhwqek0QzPJM,10849
14
+ shepherd_core/data_models/base/content.py,sha256=t3hw5Aes4-tVrWGOMSBGpcD642VM1RAWIo9jtbXifd0,2452
15
+ shepherd_core/data_models/base/shepherd.py,sha256=P1xW10_vIbGNyQ3Ary67vyovw9kmDtXhN-yPFYR-0Is,6085
16
+ shepherd_core/data_models/base/timezone.py,sha256=2T6E46hJ1DAvmqKfu6uIgCK3RSoAKjGXRyzYNaqKyjY,665
17
+ shepherd_core/data_models/base/wrapper.py,sha256=7QwvI30GuORH7WmyGLnRMsZ3xkRRkXIAvZ-pYRAL-WI,755
18
+ shepherd_core/data_models/content/__init__.py,sha256=69aiNG0h5t1OF7HsLg_ke5eaQKsKyMK8o6Kfaby5vlY,525
19
+ shepherd_core/data_models/content/_external_fixtures.yaml,sha256=0CH7YSWT_hzL-jcg4JjgN9ryQOzbS8S66_pd6GbMnHw,12259
20
+ shepherd_core/data_models/content/energy_environment.py,sha256=emlVFbcPA0-_jgpYI0Xwebm81_gWLYD8Tex0XVtJr4c,1618
21
+ shepherd_core/data_models/content/energy_environment_fixture.yaml,sha256=UBXTdGT7MK98zx5w_RBCu-f9uNCKxRgiFBQFbmDUxPc,1301
22
+ shepherd_core/data_models/content/firmware.py,sha256=KLByo1GuUMJ8ZbM6WccB8IJArorNetBxqOpuUb2_QIE,5926
23
+ shepherd_core/data_models/content/firmware_datatype.py,sha256=XPU9LOoT3h5qFOlE8WU0vAkw-vymNxzor9kVFyEqsWg,255
24
+ shepherd_core/data_models/content/virtual_harvester.py,sha256=PQ3CykoMgMoklmb_vypRdU512BuVhV-KjPTmBPKTzCM,11227
25
+ shepherd_core/data_models/content/virtual_harvester_fixture.yaml,sha256=LZe5ue1xYhXZwB3a32sva-L4uKhkQA5AtG9JzW4B2hQ,4564
26
+ shepherd_core/data_models/content/virtual_source.py,sha256=ftCcWCYKHw854lGwuxLf_ZIOY6O9vLixHHC77BqcSQA,15441
27
+ shepherd_core/data_models/content/virtual_source_fixture.yaml,sha256=1o-31mGgn7eyCNidKoOUp9vZh3K4Al0kJgmz54Q2DAE,11191
28
+ shepherd_core/data_models/experiment/__init__.py,sha256=lorsx0M-JWPIrt_UZfexsLwaITv5slFb3krBOt0idm8,618
29
+ shepherd_core/data_models/experiment/experiment.py,sha256=h24HaZltat0mKbOT1h9O58B5noTIUcGQbBIzmPi4oo8,4232
30
+ shepherd_core/data_models/experiment/observer_features.py,sha256=u6nJthpluZrxw9ym_rvkTrlOQTKlc1TY5b1HPqbO4Jg,5185
31
+ shepherd_core/data_models/experiment/target_config.py,sha256=ZODI4_MwBLxKTQ1DwFrLZAuKprxDiLyg5-JYOQxXp_w,3808
32
+ shepherd_core/data_models/task/__init__.py,sha256=3wTIJ1L5wcRDLR6JRaT0bNh7vABckSoOd5erPwhhCGI,3331
33
+ shepherd_core/data_models/task/emulation.py,sha256=PfSWci9V47EWpJRTKyHBxQZodHs3yQXMce0Mslm_-Ns,6665
34
+ shepherd_core/data_models/task/firmware_mod.py,sha256=WLmevU9-Q5QnyANbkrSCdFbnVuSi8N8fXdQ2l_Um9e8,3034
35
+ shepherd_core/data_models/task/harvest.py,sha256=rQ5Aq40m4WHpEFfiwn309GjLIPu4aKzF4Fvbo4j7PLs,3470
36
+ shepherd_core/data_models/task/observer_tasks.py,sha256=icUPtoIqic8IpE0U9Fc7btMj4CpYx1PoAu_wAqqZkU8,3608
37
+ shepherd_core/data_models/task/programming.py,sha256=6UHb8rT1M3bglt_3fHql6MsHE8sTvi9ii7Uhug5O4PM,2552
38
+ shepherd_core/data_models/task/testbed_tasks.py,sha256=J3aOSVVG1KvEI_83j0TK0gc5rN_v_T-URFRhrEs8czY,2176
39
+ shepherd_core/data_models/testbed/__init__.py,sha256=t9nwml5pbu7ZWghimOyZ8ujMIgnRgFkl23pNb5d_KdU,581
40
+ shepherd_core/data_models/testbed/cape.py,sha256=vfS05D0rC1-_wMiHeLw69VE9PxXC6PHl9ndtrv219_k,1396
41
+ shepherd_core/data_models/testbed/cape_fixture.yaml,sha256=uwZxe6hsqvofn5tzg4sffjbVtTVUkextL1GCri_z2A4,2197
42
+ shepherd_core/data_models/testbed/gpio.py,sha256=pOY_7Zs32sRGuqJZrZDrjvr69QkFXC8iXgav7kk2heY,2334
43
+ shepherd_core/data_models/testbed/gpio_fixture.yaml,sha256=yXvoXAau2hancKi2yg1xIkErPWQa6gIxNUG3y8JuF9Y,3076
44
+ shepherd_core/data_models/testbed/mcu.py,sha256=fuq2AWbVFbbzPRPCgIeMNFhJhVNCIsmpjFagnOXkjbY,1514
45
+ shepherd_core/data_models/testbed/mcu_fixture.yaml,sha256=lRZMLs27cTeERSFGkbMt5xgxbn11Gh9G1mQqOZK136I,522
46
+ shepherd_core/data_models/testbed/observer.py,sha256=RO7i9TmHcxx69P-EHN59M9MAJetoHZg5qJUD5SEtrcg,3386
47
+ shepherd_core/data_models/testbed/observer_fixture.yaml,sha256=jqAatTebWrShXBlhqkCUQIrtVqEjl7RVDR9mosS2LJQ,4807
48
+ shepherd_core/data_models/testbed/target.py,sha256=W7U9nCz_xWMRCCgaGuqOV4dGi4ZeQ1SAp7W2FqCkanU,1978
49
+ shepherd_core/data_models/testbed/target_fixture.old1,sha256=ivH9uTgC2Z4L_J4KDHAyIHZnB7iy9EUu1yM3M0s1lQQ,3675
50
+ shepherd_core/data_models/testbed/target_fixture.yaml,sha256=LyOJa7yH17tHIGC25jlkLJ_DKnbFSoGhD-6Uh6q_HqQ,4132
51
+ shepherd_core/data_models/testbed/testbed.py,sha256=K6llqMTn-AU18XXRXdhzibIx-n4CQjtrXnLwqxOQesI,3828
52
+ shepherd_core/data_models/testbed/testbed_fixture.yaml,sha256=LaaU8mXLQboYWYNPpA3CWmMPy2w6T6cve6gLgDaA3l0,717
53
+ shepherd_core/decoder_waveform/__init__.py,sha256=-ohGz0fA2tKxUJk4FAQXKtI93d6YGdy0CrkdhOod1QU,120
54
+ shepherd_core/decoder_waveform/uart.py,sha256=vuw9fKwZb_1mMtQ5fdiZN8Cr1YWSgYKar9FIMK8Bogo,11084
55
+ shepherd_core/fw_tools/__init__.py,sha256=D9GGj9TzLWZfPjG_iV2BsF-Q1TGTYTgEzWTUI5ReVAA,2090
56
+ shepherd_core/fw_tools/converter.py,sha256=F06iJlYYG2w-OCKayrgeO870lOX87xWVTYTAi1X3UPU,3604
57
+ shepherd_core/fw_tools/converter_elf.py,sha256=GQDVqIqMW4twNMvZIV3sowFMezhs2TN-IYREjRP7Xt4,1089
58
+ shepherd_core/fw_tools/patcher.py,sha256=ISbnA2ZLTIV2JZh_b3GorNDGNrLaBN0fFnFnyh-smNU,3946
59
+ shepherd_core/fw_tools/validation.py,sha256=GWm_T3xmRde-jQ8cf27kPosBTFTK3E2M2LSb24pT2g8,4732
60
+ shepherd_core/inventory/__init__.py,sha256=yQxP55yV61xXWfZSSzekQQYopPZCspFpHSyG7VTqtpg,3819
61
+ shepherd_core/inventory/python.py,sha256=pvugNgLZaDllIXX_KiuvpcWUWlJtD2IUKYDRjcTGQss,1262
62
+ shepherd_core/inventory/system.py,sha256=qFTRVXClQZoCeV2KM8RAbst8XL7IaJwwV0pGHPZSJs4,3325
63
+ shepherd_core/inventory/target.py,sha256=zLUNQs2FE7jMDsiRtbeAwqRVcit4e2F1UUOF04xw-XY,520
64
+ shepherd_core/testbed_client/__init__.py,sha256=QtbsBUzHwOoM6rk0qa21ywuz63YV7af1fwUtWW8Vg_4,234
65
+ shepherd_core/testbed_client/cache_path.py,sha256=tS0er9on5fw8wddMCt1jkc2uyYOdSTvX_UmfmYJf6tY,445
66
+ shepherd_core/testbed_client/client_abc_fix.py,sha256=3oDg2RSEP88mygtX820Y-685kYKvqQK_hwp2iFylLUU,4265
67
+ shepherd_core/testbed_client/client_web.py,sha256=zqY4MGMWfTl2_0T1qrQl5Vz9SPjl-wMj8O5yMMQyo9I,6044
68
+ shepherd_core/testbed_client/fixtures.py,sha256=OyL50wEuJ8336RPtinxOFbUsIVtLrgyO2_ROOyiBTEE,9317
69
+ shepherd_core/testbed_client/user_model.py,sha256=f4WZ8IvSCt3s1RG_Bhi43ojiJQsZYyolJ3Ft8HNRYas,2175
70
+ shepherd_core/vsource/__init__.py,sha256=vTvFWuJn4eurPNzEiMd15c1Rd6o3DTWzCfbhOomflZU,771
71
+ shepherd_core/vsource/target_model.py,sha256=BjOlwX_gIOJ91e4OOLB4_OsCpuhq9vm57ERjM-iBhAM,5129
72
+ shepherd_core/vsource/virtual_converter_model.py,sha256=jUnJwP-FFDMtXm1NCLUJfZTvImYH4_A9rc_lXVAZ33I,11628
73
+ shepherd_core/vsource/virtual_harvester_model.py,sha256=8uPTMDth4KI5XarkX9EJtMRZ_8eWUeWCZxgmx4be3Fs,9763
74
+ shepherd_core/vsource/virtual_harvester_simulation.py,sha256=H4m9lB4Hk_sskGi3LoFYARBpq1uY3WsJj-ktF3nk2Ck,2558
75
+ shepherd_core/vsource/virtual_source_model.py,sha256=-8RwBrkIdO0g4zpo7XHnqv8F_qNh_qf5hxEUJoIuAmg,3164
76
+ shepherd_core/vsource/virtual_source_simulation.py,sha256=6FKbaO-zaODp0nf-ksnl-nRAVpFKGQrpxpIBrGIhD0I,5284
77
+ shepherd_core-2025.4.2.dist-info/METADATA,sha256=SD_1RcpaF_Pb-IbG2uAh7xkWHJv8TOaqy8c0zQI7Q1o,7756
78
+ shepherd_core-2025.4.2.dist-info/WHEEL,sha256=lTU6B6eIfYoiQJTZNc-fyaR6BpL6ehTzU3xGYxn2n8k,91
79
+ shepherd_core-2025.4.2.dist-info/top_level.txt,sha256=wy-t7HRBrKARZxa-Y8_j8d49oVHnulh-95K9ikxVhew,14
80
+ shepherd_core-2025.4.2.dist-info/zip-safe,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
81
+ shepherd_core-2025.4.2.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (78.1.0)
2
+ Generator: setuptools (78.1.1)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -1,81 +0,0 @@
1
- shepherd_core/__init__.py,sha256=fCld2mcl0y0h6kRyPal3DP-sWXnKl_0aYWYBdg4QuUk,1270
2
- shepherd_core/calibration_hw_def.py,sha256=_nMzgNzSnYyqcLnVCGd4tfA2e0avUXbccjmNpFhiDgo,2830
3
- shepherd_core/commons.py,sha256=vymKXWcy_1bz7ChzzEATUkJ4p3czCzjIdsSehVjJOY8,218
4
- shepherd_core/logger.py,sha256=4Q4hTI-nccOZ1_A68fo4UEctfu3pJx3IeHfa9VuDDEo,1804
5
- shepherd_core/reader.py,sha256=tgETZPFSPzBk2BYHZ3NyWpY9j6j23FUWv1e3oCQhc6A,28401
6
- shepherd_core/version.py,sha256=Tb2EjULatpKtVFMAniZ_AGEWDFfyFO0ffsW-t24FgFU,76
7
- shepherd_core/writer.py,sha256=TD5oXuOFz_PUMWYeXfePz9x2O01DLRBVNMaLcngNjFc,14666
8
- shepherd_core/data_models/__init__.py,sha256=bnHSP_HBOYm4WuoiHs_vyiRsWlvkyDjsarMNfKedN-Q,1836
9
- shepherd_core/data_models/readme.md,sha256=DHPVmkWqDksWomRHRTVWVHy9wXF9oMJrITgKs4Pnz2g,2494
10
- shepherd_core/data_models/virtual_source_doc.txt,sha256=KizMcfGKj7BnHIbaJHT7KeTF01SV__UXv01qV_DGHSs,6057
11
- shepherd_core/data_models/base/__init__.py,sha256=PSJ6acWViqBm0Eiom8DIgKfFVrp5lzYr8OsDvP79vwI,94
12
- shepherd_core/data_models/base/cal_measurement.py,sha256=YScPG7QLynbUHdjcznYqU8O5KRh0XiROGxGSk9BETMk,3357
13
- shepherd_core/data_models/base/calibration.py,sha256=-eiN9QbuZhw1CLzmyijeMgMVzzDE85p-Q5KryFoo5x8,10788
14
- shepherd_core/data_models/base/content.py,sha256=13j7GSgT73xn27jgDP508thUEJR4U-nCb5n7CJ50c9Y,2463
15
- shepherd_core/data_models/base/shepherd.py,sha256=DNrx59o1VBuy_liJuUzZRzmTTYB73D_pUWiNyMQyjYY,6112
16
- shepherd_core/data_models/base/timezone.py,sha256=2T6E46hJ1DAvmqKfu6uIgCK3RSoAKjGXRyzYNaqKyjY,665
17
- shepherd_core/data_models/base/wrapper.py,sha256=Izp17HFCKNAS3TnWcPn3MM9fWdc3A-F7eDyAsYlyWCw,755
18
- shepherd_core/data_models/content/__init__.py,sha256=69aiNG0h5t1OF7HsLg_ke5eaQKsKyMK8o6Kfaby5vlY,525
19
- shepherd_core/data_models/content/_external_fixtures.yaml,sha256=0CH7YSWT_hzL-jcg4JjgN9ryQOzbS8S66_pd6GbMnHw,12259
20
- shepherd_core/data_models/content/energy_environment.py,sha256=WuXMkKqnibGzM2WeW1_m2DAsc0fDqE9CkBYYPSw-7eA,1540
21
- shepherd_core/data_models/content/energy_environment_fixture.yaml,sha256=UBXTdGT7MK98zx5w_RBCu-f9uNCKxRgiFBQFbmDUxPc,1301
22
- shepherd_core/data_models/content/firmware.py,sha256=rH74sJPAjUUheVv0y2Y93BeT63CeKqdSEo8HZgHGlMo,5813
23
- shepherd_core/data_models/content/firmware_datatype.py,sha256=XPU9LOoT3h5qFOlE8WU0vAkw-vymNxzor9kVFyEqsWg,255
24
- shepherd_core/data_models/content/virtual_harvester.py,sha256=cf-DrSacZsct9e8eGoR4PX7S7RXlbxQfJHVsLR9njlM,10749
25
- shepherd_core/data_models/content/virtual_harvester_fixture.yaml,sha256=LZe5ue1xYhXZwB3a32sva-L4uKhkQA5AtG9JzW4B2hQ,4564
26
- shepherd_core/data_models/content/virtual_source.py,sha256=EnkjLlh14YBUnoS4yILXraLN0qdnVoEzddJY0N1w3xk,15351
27
- shepherd_core/data_models/content/virtual_source_fixture.yaml,sha256=1o-31mGgn7eyCNidKoOUp9vZh3K4Al0kJgmz54Q2DAE,11191
28
- shepherd_core/data_models/experiment/__init__.py,sha256=lorsx0M-JWPIrt_UZfexsLwaITv5slFb3krBOt0idm8,618
29
- shepherd_core/data_models/experiment/experiment.py,sha256=79iHh2Dr_w4N4Bfq_g0KDr6wMpS_T7x-JIGHZCagEGo,4080
30
- shepherd_core/data_models/experiment/observer_features.py,sha256=qxnb7anuQz9ZW5IUlPdUXYPIl5U7O9uXkJqZtMnAb0Y,5156
31
- shepherd_core/data_models/experiment/target_config.py,sha256=XIsjbbo7yn_A4q3GMxWbiNzEGA0Kk5gH7-XfQQ7Kg0E,3674
32
- shepherd_core/data_models/task/__init__.py,sha256=vOsSeB5IBYYwzOLKom8-XuZyjF86m_svtCsw-agiV7o,3295
33
- shepherd_core/data_models/task/emulation.py,sha256=tLb5auHOgdoG-e4hFljAYT49z7lMEaiimOy4UVZONi4,6440
34
- shepherd_core/data_models/task/firmware_mod.py,sha256=Rw_TA1ykQ7abUd_U0snqZlpZyrS8Nx6f4BEax1Xnji0,2818
35
- shepherd_core/data_models/task/harvest.py,sha256=HHnqWwRsJupaZJxuohs7NrK6VaDyoRzGOaG2h9y3s1Y,3360
36
- shepherd_core/data_models/task/observer_tasks.py,sha256=XlH_-EGRrdodTn0c2pjGvpcauc0a9NOnLhysKw8iRwk,3511
37
- shepherd_core/data_models/task/programming.py,sha256=hjzsxqqB0WXb0qY5gKk4iZ-Is3-OZNFnGehAxzA_0TI,2323
38
- shepherd_core/data_models/task/testbed_tasks.py,sha256=zvIitq0Ek1Ae7baWiBkSQN8nRugyw0N2P4SeVoj_QaY,2090
39
- shepherd_core/data_models/testbed/__init__.py,sha256=t9nwml5pbu7ZWghimOyZ8ujMIgnRgFkl23pNb5d_KdU,581
40
- shepherd_core/data_models/testbed/cape.py,sha256=D23ZKXpZRPIIOMn6LCoJrwHiRbSaYg-y7B6fAt1ap64,1246
41
- shepherd_core/data_models/testbed/cape_fixture.yaml,sha256=uwZxe6hsqvofn5tzg4sffjbVtTVUkextL1GCri_z2A4,2197
42
- shepherd_core/data_models/testbed/gpio.py,sha256=m4U8-KotpZbdSkRkXm2GqoADiubr_1-3BWOT1qlgQic,2195
43
- shepherd_core/data_models/testbed/gpio_fixture.yaml,sha256=yXvoXAau2hancKi2yg1xIkErPWQa6gIxNUG3y8JuF9Y,3076
44
- shepherd_core/data_models/testbed/mcu.py,sha256=pUyT8gwPcqh18I7FC6iE6gYYISo69TvDfuq2zSwfmxs,1375
45
- shepherd_core/data_models/testbed/mcu_fixture.yaml,sha256=lRZMLs27cTeERSFGkbMt5xgxbn11Gh9G1mQqOZK136I,522
46
- shepherd_core/data_models/testbed/observer.py,sha256=hlj6buDzUQKYnlhCJZyxnrAPYKoL4zq9y14sKtYofOU,3246
47
- shepherd_core/data_models/testbed/observer_fixture.yaml,sha256=jqAatTebWrShXBlhqkCUQIrtVqEjl7RVDR9mosS2LJQ,4807
48
- shepherd_core/data_models/testbed/target.py,sha256=KeJaLradQ3oHeeowCg_X0lDHDqyi3R3La0YPKC5Rv90,1838
49
- shepherd_core/data_models/testbed/target_fixture.old1,sha256=ivH9uTgC2Z4L_J4KDHAyIHZnB7iy9EUu1yM3M0s1lQQ,3675
50
- shepherd_core/data_models/testbed/target_fixture.yaml,sha256=LyOJa7yH17tHIGC25jlkLJ_DKnbFSoGhD-6Uh6q_HqQ,4132
51
- shepherd_core/data_models/testbed/testbed.py,sha256=0uJ3OwqCKDn78OCJOaMa2XWxTLF1ultjmpHVSx3LyhE,3695
52
- shepherd_core/data_models/testbed/testbed_fixture.yaml,sha256=LaaU8mXLQboYWYNPpA3CWmMPy2w6T6cve6gLgDaA3l0,717
53
- shepherd_core/decoder_waveform/__init__.py,sha256=-ohGz0fA2tKxUJk4FAQXKtI93d6YGdy0CrkdhOod1QU,120
54
- shepherd_core/decoder_waveform/uart.py,sha256=sHsXHOsDU1j9zMSZO7CCMTMinT4U_S5NgsEkl1lJK1U,11029
55
- shepherd_core/fw_tools/__init__.py,sha256=D9GGj9TzLWZfPjG_iV2BsF-Q1TGTYTgEzWTUI5ReVAA,2090
56
- shepherd_core/fw_tools/converter.py,sha256=3igRT33tghrBCao5njuPmePS-Y_lSa6EUHvwCakMo2s,3539
57
- shepherd_core/fw_tools/converter_elf.py,sha256=GQDVqIqMW4twNMvZIV3sowFMezhs2TN-IYREjRP7Xt4,1089
58
- shepherd_core/fw_tools/patcher.py,sha256=D6MHaCvKRRVQYSZozODAp_l7UnqxVsvnulPzpkfXWW8,4108
59
- shepherd_core/fw_tools/validation.py,sha256=dOweyWwVMq0b4Liha39mGUOiblD7Nz5kSFVrlxUx41o,4707
60
- shepherd_core/inventory/__init__.py,sha256=nyDBAE7kdDeh1McyavMWH1cY0WqphjFS1NL4XRAyzUw,3841
61
- shepherd_core/inventory/python.py,sha256=OWNnyEt0IDPW9XGW-WloU0FExwgZzYNA05VpRj4cZGc,1250
62
- shepherd_core/inventory/system.py,sha256=Q_mtM2zhUsTvzELgpEVxSxL9aFS1RSGcCX6RFpyZ-r8,3155
63
- shepherd_core/inventory/target.py,sha256=Lq11j25tWieXheOxIDaQb-lc-2omxYVex5P6uGiLUyk,507
64
- shepherd_core/testbed_client/__init__.py,sha256=QtbsBUzHwOoM6rk0qa21ywuz63YV7af1fwUtWW8Vg_4,234
65
- shepherd_core/testbed_client/cache_path.py,sha256=tS0er9on5fw8wddMCt1jkc2uyYOdSTvX_UmfmYJf6tY,445
66
- shepherd_core/testbed_client/client_abc_fix.py,sha256=BsSkpvJHURRejlS-YPF1f6QRPC_X0fYEsJpinzsx6Jc,4079
67
- shepherd_core/testbed_client/client_web.py,sha256=rOg0Gf-s3S8U0z2ssh9_bNnq4aRQINfuuVHionPf38M,5788
68
- shepherd_core/testbed_client/fixtures.py,sha256=W8trHZXyuD0xzb28ZW-2BQ3ZDU2tI3LC4mjrbOUX57E,9215
69
- shepherd_core/testbed_client/user_model.py,sha256=5M3vWkAGBwdGDUYAanAjrZwpzMBlh3XLOVvNYWiLmms,2107
70
- shepherd_core/vsource/__init__.py,sha256=vTvFWuJn4eurPNzEiMd15c1Rd6o3DTWzCfbhOomflZU,771
71
- shepherd_core/vsource/target_model.py,sha256=LaB5ppi2-IIpIepDqDvOliR-BupzccJl44yRxjlF-ms,5113
72
- shepherd_core/vsource/virtual_converter_model.py,sha256=3TyxphUMunoGhMda7AWCHZQU8pjRSvxB-9R8lfZFnok,11592
73
- shepherd_core/vsource/virtual_harvester_model.py,sha256=GyA0uGl3r42t5c4roYtEaj22b0-b5DAHUr2e9DuNn-c,9765
74
- shepherd_core/vsource/virtual_harvester_simulation.py,sha256=MFT583s73BJZYyhcqgnDUGTPr9s_lN_lKafzJG6kueE,2457
75
- shepherd_core/vsource/virtual_source_model.py,sha256=9tiOzgrEgdEH5Uuhd8hjmmIkquNDuaNjLlblvInIlzg,3036
76
- shepherd_core/vsource/virtual_source_simulation.py,sha256=ZOnFd2uPawY2G1salCiLGx9o1OBG99_-EHBtDjx4ZUo,5140
77
- shepherd_core-2025.4.1.dist-info/METADATA,sha256=3IZbuK5skDrSs1QRlY9uA8MJLsUx0NSYALft4GwVfeQ,7806
78
- shepherd_core-2025.4.1.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
79
- shepherd_core-2025.4.1.dist-info/top_level.txt,sha256=wy-t7HRBrKARZxa-Y8_j8d49oVHnulh-95K9ikxVhew,14
80
- shepherd_core-2025.4.1.dist-info/zip-safe,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
81
- shepherd_core-2025.4.1.dist-info/RECORD,,