pyedb 0.60.0__py3-none-any.whl → 0.61.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.

Potentially problematic release.


This version of pyedb might be problematic. Click here for more details.

Files changed (34) hide show
  1. pyedb/__init__.py +1 -1
  2. pyedb/configuration/cfg_components.py +35 -7
  3. pyedb/dotnet/database/cell/hierarchy/component.py +8 -6
  4. pyedb/dotnet/database/cell/hierarchy/model.py +1 -28
  5. pyedb/dotnet/database/cell/hierarchy/s_parameter_model.py +10 -14
  6. pyedb/dotnet/database/cell/hierarchy/spice_model.py +13 -7
  7. pyedb/dotnet/database/components.py +5 -1
  8. pyedb/dotnet/database/edb_data/padstacks_data.py +5 -3
  9. pyedb/dotnet/database/modeler.py +2 -1
  10. pyedb/dotnet/database/padstack.py +187 -1
  11. pyedb/dotnet/edb.py +70 -1
  12. pyedb/generic/general_methods.py +21 -0
  13. pyedb/grpc/database/definition/materials.py +1 -1
  14. pyedb/grpc/database/definition/padstack_def.py +16 -9
  15. pyedb/grpc/database/padstacks.py +201 -6
  16. pyedb/grpc/database/primitive/padstack_instance.py +90 -0
  17. pyedb/grpc/edb.py +70 -1
  18. pyedb/grpc/rpc_session.py +16 -3
  19. pyedb/workflows/__init__.py +21 -0
  20. pyedb/workflows/job_manager/__init__.py +21 -0
  21. pyedb/workflows/job_manager/backend/__init__.py +21 -0
  22. pyedb/workflows/job_manager/backend/job_manager_handler.py +910 -0
  23. pyedb/workflows/job_manager/backend/job_submission.py +1169 -0
  24. pyedb/workflows/job_manager/backend/service.py +1663 -0
  25. pyedb/workflows/job_manager/backend/start_service.py +86 -0
  26. pyedb/workflows/job_manager/backend/submit_job_on_scheduler.py +168 -0
  27. pyedb/workflows/job_manager/backend/submit_local_job.py +166 -0
  28. pyedb/workflows/utilities/__init__.py +21 -0
  29. pyedb/workflows/utilities/cutout.py +1 -1
  30. pyedb/workflows/utilities/hfss_log_parser.py +446 -0
  31. {pyedb-0.60.0.dist-info → pyedb-0.61.0.dist-info}/METADATA +7 -4
  32. {pyedb-0.60.0.dist-info → pyedb-0.61.0.dist-info}/RECORD +34 -24
  33. {pyedb-0.60.0.dist-info → pyedb-0.61.0.dist-info}/WHEEL +0 -0
  34. {pyedb-0.60.0.dist-info → pyedb-0.61.0.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,446 @@
1
+ # Copyright (C) 2023 - 2025 ANSYS, Inc. and/or its affiliates.
2
+ # SPDX-License-Identifier: MIT
3
+ #
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ # of this software and associated documentation files (the "Software"), to deal
7
+ # in the Software without restriction, including without limitation the rights
8
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ # copies of the Software, and to permit persons to whom the Software is
10
+ # furnished to do so, subject to the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be included in all
13
+ # copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ # SOFTWARE.
22
+
23
+
24
+ from __future__ import annotations
25
+
26
+ from dataclasses import dataclass
27
+ import math
28
+ from pathlib import Path
29
+ import re
30
+ from typing import Any, Dict, List, Optional
31
+
32
+
33
+ def _to_hz(text: str) -> float:
34
+ """
35
+ Convert a human-readable frequency string to hertz.
36
+
37
+ :param text: Frequency expression such as ``'3 GHz'``, ``'100 kHz'``, ``'10MHz'``.
38
+ :type text: str
39
+ :return: Numerical value in Hz. Returns :py:const:`math.nan` if the string
40
+ cannot be parsed.
41
+ :rtype: float
42
+ """
43
+ m = re.match(r"(?P<val>[\d.]+)\s*(?P<unit>[kMG]?Hz)", text, re.I)
44
+ if not m:
45
+ return math.nan
46
+ val, unit = float(m["val"]), m["unit"].lower()
47
+ scale = {"hz": 1, "khz": 1e3, "mhz": 1e6, "ghz": 1e9}
48
+ return val * scale[unit]
49
+
50
+
51
+ def _to_sec(mm_ss: str) -> int:
52
+ """
53
+ Convert an ANSYS time stamp to seconds.
54
+
55
+ Accepts ``MM:SS``, ``H:MM:SS`` or ``HH:MM:SS``.
56
+
57
+ :param mm_ss: Time stamp extracted from the log.
58
+ :type mm_ss: str
59
+ :return: Total elapsed seconds.
60
+ :rtype: int
61
+ """
62
+ parts = mm_ss.strip().split(":")
63
+ if len(parts) == 2: # MM:SS
64
+ return int(parts[0]) * 60 + int(parts[1])
65
+ if len(parts) == 3: # H:MM:SS or HH:MM:SS
66
+ return int(parts[0]) * 3600 + int(parts[1]) * 60 + int(parts[2])
67
+ return 0
68
+
69
+
70
+ def _as_dict(obj: Any) -> Any:
71
+ """Recursively convert dataclasses / lists / primitives to plain Python types."""
72
+ if hasattr(obj, "__dataclass_fields__"):
73
+ return {f: _as_dict(getattr(obj, f)) for f in obj.__dataclass_fields__}
74
+ if isinstance(obj, list):
75
+ return [_as_dict(i) for i in obj]
76
+ if isinstance(obj, Path):
77
+ return str(obj)
78
+ return obj
79
+
80
+
81
+ @dataclass(slots=True)
82
+ class ProjectInfo:
83
+ """
84
+ Basic meta-data extracted from the header of an HFSS batch log.
85
+
86
+ :ivar str name: Project name (without extension).
87
+ :ivar ~pathlib.Path file: Full path to the project file.
88
+ :ivar str design: Active design name (may be empty).
89
+ :ivar str user: OS user that launched the solve.
90
+ :ivar str cmd_line: Exact command line used for the run.
91
+ """
92
+
93
+ name: str
94
+ file: Path
95
+ design: str = ""
96
+ user: str = ""
97
+ cmd_line: str = ""
98
+
99
+
100
+ @dataclass(slots=True)
101
+ class InitMesh:
102
+ """
103
+ Statistics reported during the initial tetrahedral meshing phase.
104
+
105
+ :ivar int tetrahedra: Number of tetrahedra created.
106
+ :ivar float memory_mb: Peak memory consumption in megabytes.
107
+ :ivar int real_time_sec: Wall clock time in seconds.
108
+ :ivar int cpu_time_sec: CPU time in seconds.
109
+ """
110
+
111
+ tetrahedra: int
112
+ memory_mb: float
113
+ real_time_sec: int
114
+ cpu_time_sec: int
115
+
116
+
117
+ @dataclass(slots=True)
118
+ class AdaptivePass:
119
+ """
120
+ Single adaptive solution pass (frequency, delta-S, memory, …).
121
+
122
+ :ivar int pass_nr: 1-based pass index.
123
+ :ivar float freq_hz: Target frequency in hertz.
124
+ :ivar int tetrahedra: Number of tetrahedra at *end* of pass.
125
+ :ivar int matrix_size: Order of the FEM matrix.
126
+ :ivar float memory_mb: Memory used in megabytes.
127
+ :ivar float delta_s: Maximum |ΔS| observed (``None`` until reported).
128
+ :ivar bool converged: ``True`` if this pass triggered convergence.
129
+ :ivar int elapsed_sec: Wall time spent in this pass.
130
+ """
131
+
132
+ pass_nr: int
133
+ freq_hz: float
134
+ tetrahedra: int
135
+ matrix_size: int
136
+ memory_mb: float
137
+ delta_s: Optional[float]
138
+ converged: bool
139
+ elapsed_sec: int
140
+
141
+
142
+ @dataclass(slots=True)
143
+ class Sweep:
144
+ """
145
+ Frequency-sweep summary block.
146
+
147
+ :ivar str type: Sweep algorithm: ``Interpolating``, ``Discrete`` or ``Fast``.
148
+ :ivar int frequencies: Total number of frequency points requested.
149
+ :ivar list[float] solved: List of frequencies (Hz) actually solved.
150
+ :ivar int elapsed_sec: Wall clock time for the entire sweep.
151
+ """
152
+
153
+ type: str
154
+ frequencies: int
155
+ solved: List[float]
156
+ elapsed_sec: int
157
+
158
+
159
+ class BlockParser:
160
+ """Base class for a single block parser."""
161
+
162
+ def __init__(self, lines: List[str]) -> None:
163
+ self.lines = lines
164
+
165
+ def parse(self) -> Any:
166
+ raise NotImplementedError
167
+
168
+
169
+ class ProjectBlockParser(BlockParser):
170
+ """
171
+ Extract project meta-data from the log header.
172
+
173
+ Example::
174
+
175
+ >>> block = ProjectBlockParser(lines)
176
+ >>> info = block.parse()
177
+ >>> info.name
178
+ 'Patch_Antenna'
179
+ """
180
+
181
+ def parse(self) -> ProjectInfo:
182
+ """
183
+ Parse the stored lines and return a :class:`ProjectInfo` instance.
184
+
185
+ :return: Populated data object.
186
+ :rtype: ProjectInfo
187
+ :raises ValueError: If mandatory fields (project name or file path)
188
+ cannot be located.
189
+ """
190
+ proj, design, user, cmd = "", "", "", ""
191
+ for line in self.lines:
192
+ if m := re.search(r"Project:(?P<proj>[^,]+),\s*Design:(?P<des>[^,]+)", line):
193
+ proj, design = m["proj"].strip(), m["des"].strip()
194
+ if m := re.search(r"Running as user\s*:\s*(?P<user>.+)", line):
195
+ user = m["user"].strip()
196
+ if m := re.search(r'Using command line:\s*(?P<cmd>".+")', line):
197
+ cmd = m["cmd"]
198
+ # file is the batch-solve argument
199
+ file = Path(re.search(r"Batch Solve/Save:\s*(?P<file>.+)", "\n".join(self.lines))["file"])
200
+ return ProjectInfo(name=proj, file=file, design=design, user=user, cmd_line=cmd)
201
+
202
+
203
+ class InitMeshBlockParser(BlockParser):
204
+ def parse(self) -> InitMesh:
205
+ tet = mem = rt = ct = None
206
+ for idx, line in enumerate(self.lines):
207
+ if "[PROFILE] Initial Meshing" in line:
208
+ # scan forward up to 10 lines for the pieces
209
+ for future in self.lines[idx : idx + 10]:
210
+ if m := re.search(r"Tetrahedra: (?P<tet>\d+)", future):
211
+ tet = int(m["tet"])
212
+ if m := re.search(r"Memory (?P<mem>[\d.]+) M", future):
213
+ mem = float(m["mem"])
214
+ if m := re.search(r"Real Time (?P<rt>[\d:]+)", future):
215
+ rt = _to_sec(m["rt"])
216
+ if m := re.search(r"CPU Time (?P<ct>[\d:]+)", future):
217
+ ct = _to_sec(m["ct"])
218
+ if all(v is not None for v in (tet, mem, rt, ct)):
219
+ return InitMesh(tetrahedra=tet, memory_mb=mem, real_time_sec=rt, cpu_time_sec=ct)
220
+ break
221
+ raise ValueError("Initial mesh block not found")
222
+
223
+
224
+ class AdaptiveBlockParser(BlockParser):
225
+ """
226
+ Build a list of :class:`AdaptivePass` objects from the adaptive section.
227
+ """
228
+
229
+ def parse(self) -> List[AdaptivePass]:
230
+ """
231
+ Parse every adaptive pass and determine which one triggered convergence.
232
+
233
+ :return: Ordered list of passes (pass_nr always increases).
234
+ :rtype: list[AdaptivePass]
235
+ """
236
+ passes: List[AdaptivePass] = []
237
+ current: Optional[AdaptivePass] = None
238
+ last_converge_pass: Optional[int] = None
239
+ adaptive_converged_line_found = False
240
+
241
+ for lineno, line in enumerate(self.lines, 1):
242
+ # ---- Check for "Adaptive Passes converged" literal string (check every line) ----
243
+ if "Adaptive Passes converged" in line:
244
+ adaptive_converged_line_found = True
245
+
246
+ # ---- new adaptive pass ----------------------------------
247
+ if m := re.search(r"Adaptive Pass (?P<n>\d+).*Frequency: (?P<f>[\d.kMGHz]+)", line, re.I):
248
+ current = AdaptivePass(
249
+ pass_nr=int(m["n"]),
250
+ freq_hz=_to_hz(m["f"]),
251
+ tetrahedra=0,
252
+ matrix_size=0,
253
+ memory_mb=0.0,
254
+ delta_s=None,
255
+ converged=False,
256
+ elapsed_sec=0,
257
+ )
258
+
259
+ if not current:
260
+ continue
261
+
262
+ # ---- collect details ------------------------------------
263
+ if m := re.search(r"Tetrahedra: (?P<tet>\d+)", line):
264
+ current.tetrahedra = int(m["tet"])
265
+ if m := re.search(r"Matrix size: (?P<sz>\d+)", line):
266
+ current.matrix_size = int(m["sz"])
267
+ if m := re.search(r"Memory (?P<mem>[\d.]+) M", line):
268
+ current.memory_mb = float(m["mem"])
269
+ if m := re.search(r"Max Mag\. Delta S:\s*(?P<ds>[\d.]+)", line):
270
+ current.delta_s = float(m["ds"])
271
+ if m := re.search(r"Elapsed time.*:\s*(?P<et>[\d:]+)", line):
272
+ current.elapsed_sec = _to_sec(m["et"])
273
+
274
+ # ---- store pass when [CONVERGE] appears -----------------
275
+ if m := re.search(r"\[CONVERGE].*pass number\D+(?P<n>\d+)", line, re.I):
276
+ passes.append(current)
277
+ last_converge_pass = int(m["n"])
278
+ current = None
279
+
280
+ # ---- final decision ----------------------------------------
281
+ if adaptive_converged_line_found and last_converge_pass is not None:
282
+ for p in passes:
283
+ p.converged = p.pass_nr == last_converge_pass
284
+ return passes
285
+
286
+
287
+ class SweepBlockParser(BlockParser):
288
+ """
289
+ Extract frequency-sweep summary (if present).
290
+ """
291
+
292
+ def parse(self) -> Optional[Sweep]:
293
+ """
294
+ Return sweep information or ``None`` if the log contains no sweep block.
295
+
296
+ :return: Sweep summary object.
297
+ :rtype: Sweep | None
298
+ """
299
+ sweep_type, freqs, solved, elapsed = "", 0, [], 0
300
+ for line in self.lines:
301
+ if m := re.search(r"Interpolating|Discrete|Fast", line):
302
+ sweep_type = m.group(0)
303
+ if m := re.search(r"(?P<n>\d+)\s*Frequencies", line):
304
+ freqs = int(m["n"])
305
+ if m := re.search(r"Frequency - (?P<f>[\d.kMGHz]+)", line, re.I):
306
+ solved.append(_to_hz(m["f"]))
307
+ if m := re.search(r"Elapsed time.*:\s*(?P<et>[\d:]+)", line):
308
+ elapsed = _to_sec(m["et"])
309
+ if freqs:
310
+ return Sweep(type=sweep_type or "Interpolating", frequencies=freqs, solved=solved, elapsed_sec=elapsed)
311
+ return None
312
+
313
+
314
+ class HFSSLogParser:
315
+ """
316
+ High-level façade that orchestrates all block parsers.
317
+
318
+ Typical usage::
319
+
320
+ >>> log = HFSSLogParser("/tmp/project.aedt.batchinfo.1234/hfss.log")
321
+ >>> data = log.parse()
322
+ >>> data.is_converged()
323
+ True
324
+ """
325
+
326
+ BLOCK_MAP: Dict[str, type[BlockParser]] = {
327
+ "project": ProjectBlockParser,
328
+ "init_mesh": InitMeshBlockParser,
329
+ "adaptive": AdaptiveBlockParser,
330
+ "sweep": SweepBlockParser,
331
+ }
332
+
333
+ def __init__(self, log_path: str | Path):
334
+ self.path = Path(log_path)
335
+
336
+ def parse(self) -> ParsedLog:
337
+ """
338
+ Execute all sub-parsers and return a unified object.
339
+
340
+ :return: Structured representation of the entire log.
341
+ :rtype: ParsedLog
342
+ :raises FileNotFoundError: If *log_path* does not exist.
343
+ :raises ValueError: If a mandatory block cannot be parsed.
344
+ """
345
+ text = self.path.read_text(encoding="utf-8", errors="ignore")
346
+ lines = text.splitlines()
347
+
348
+ project = ProjectBlockParser(lines).parse()
349
+ init_mesh = InitMeshBlockParser(lines).parse()
350
+ adaptive = AdaptiveBlockParser(lines).parse()
351
+ sweep = SweepBlockParser(lines).parse()
352
+
353
+ return ParsedLog(
354
+ project=project,
355
+ init_mesh=init_mesh,
356
+ adaptive=adaptive,
357
+ sweep=sweep,
358
+ )
359
+
360
+
361
+ @dataclass(slots=True)
362
+ class ParsedLog:
363
+ """
364
+ Root container returned by :meth:`HFSSLogParser.parse`.
365
+
366
+ :ivar ProjectInfo project: Project meta-data.
367
+ :ivar InitMesh init_mesh: Initial-mesh metrics.
368
+ :ivar list[AdaptivePass] adaptive: Adaptive passes in chronological order.
369
+ :ivar Sweep | None sweep: Frequency-sweep summary (``None`` if absent).
370
+ """
371
+
372
+ project: ProjectInfo
373
+ init_mesh: InitMesh
374
+ adaptive: List[AdaptivePass]
375
+ sweep: Optional[Sweep]
376
+
377
+ def to_dict(self) -> dict:
378
+ """
379
+ Deep-convert the entire object to JSON-serialisable primitives.
380
+
381
+ :return: Plain ``dict`` / ``list`` / scalar structure.
382
+ :rtype: dict[str, Any]
383
+ """
384
+ return _as_dict(self)
385
+
386
+ def is_converged(self) -> bool:
387
+ """
388
+ Return ``True`` if the adaptive solver declared convergence.
389
+
390
+ :rtype: bool
391
+ """
392
+ return self.adaptive[-1].converged if self.adaptive else False
393
+
394
+ def adaptive_passes(self) -> List[AdaptivePass]:
395
+ """Alias to keep API explicit."""
396
+ return self.adaptive
397
+
398
+ def memory_on_convergence(self) -> float:
399
+ """
400
+ Memory (MB) consumed by the *last* converged adaptive pass.
401
+
402
+ :return: Megabytes, or :py:const:`math.nan` if no pass converged.
403
+ :rtype: float
404
+ """
405
+ for p in reversed(self.adaptive):
406
+ if p.converged:
407
+ return p.memory_mb
408
+ return math.nan
409
+
410
+ def is_completed(self) -> bool:
411
+ """
412
+ Heuristic indicating a successful end-to-end solve.
413
+
414
+ A simulation is considered complete when **both** of the following
415
+ conditions are satisfied:
416
+
417
+ 1. At least one adaptive pass converged.
418
+ 2. A frequency-sweep block exists with elapsed time greater than zero.
419
+
420
+ :rtype: bool
421
+ """
422
+ return self.is_converged() and self.sweep is not None and self.sweep.elapsed_sec > 0
423
+
424
+ def errors(self) -> List[str]:
425
+ """
426
+ Extract only **error** lines (warnings are ignored).
427
+
428
+ ANSYS marks errors with ``[error]`` or ``*** ERROR ***``.
429
+
430
+ :return: List of stripped error lines (empty if none).
431
+ :rtype: list[str]
432
+ """
433
+ errs: List[str] = []
434
+ # we keep the raw lines inside the ProjectBlockParser – expose them
435
+ raw = self._raw_lines # added below
436
+ for line in raw:
437
+ if re.search(r"\[error\]|\*\*\* ERROR \*\*\*", line, re.I):
438
+ errs.append(line.strip())
439
+ return errs
440
+
441
+ @property
442
+ def _raw_lines(self) -> List[str]:
443
+ # cache lazily
444
+ if not hasattr(self, "__raw"):
445
+ self.__raw = self.project.file.with_suffix(".log").read_text(encoding="utf-8", errors="ignore").splitlines()
446
+ return self.__raw
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pyedb
3
- Version: 0.60.0
3
+ Version: 0.61.0
4
4
  Summary: Higher-Level Pythonic Ansys Electronics Data Base
5
5
  Author-email: "ANSYS, Inc." <pyansys.core@ansys.com>
6
6
  Maintainer-email: PyEDB developers <simon.vandenbrouck@ansys.com>
@@ -22,7 +22,7 @@ Requires-Dist: ansys-pythonnet >= 3.1.0rc4
22
22
  Requires-Dist: dotnetcore2 ==3.1.23;platform_system=='Linux'
23
23
  Requires-Dist: numpy>=1.20.0,<3
24
24
  Requires-Dist: pandas>=1.1.0,<2.4
25
- Requires-Dist: pydantic>=2.6.4,<2.12
25
+ Requires-Dist: pydantic>=2.6.4,<2.13
26
26
  Requires-Dist: Rtree >= 1.2.0
27
27
  Requires-Dist: toml == 0.10.2
28
28
  Requires-Dist: shapely
@@ -31,15 +31,18 @@ Requires-Dist: ansys-edb-core>=0.2.0
31
31
  Requires-Dist: psutil
32
32
  Requires-Dist: defusedxml>=0.7,<8.0
33
33
  Requires-Dist: matplotlib>=3.5.0,<3.11
34
+ Requires-Dist: aiohttp>=3.8
35
+ Requires-Dist: python-socketio>=5.10
36
+ Requires-Dist: requests>=2.32,<3.0
34
37
  Requires-Dist: ansys-sphinx-theme>=1.0.0,<1.5 ; extra == "doc"
35
38
  Requires-Dist: imageio>=2.30.0,<2.38 ; extra == "doc"
36
39
  Requires-Dist: ipython>=8.13.0,<8.32 ; extra == "doc"
37
40
  Requires-Dist: jupyterlab>=4.0.0,<4.5 ; extra == "doc"
38
- Requires-Dist: jupytext>=1.16.0,<1.18 ; extra == "doc"
41
+ Requires-Dist: jupytext>=1.16.0,<1.19 ; extra == "doc"
39
42
  Requires-Dist: matplotlib>=3.5.0,<3.11 ; extra == "doc"
40
43
  Requires-Dist: nbsphinx>=0.9.0,<0.10 ; extra == "doc"
41
44
  Requires-Dist: nbconvert < 7.17 ; extra == "doc"
42
- Requires-Dist: numpydoc>=1.5.0,<1.9 ; extra == "doc"
45
+ Requires-Dist: numpydoc==1.5.0 ; extra == "doc"
43
46
  Requires-Dist: pypandoc>=1.10.0,<1.16 ; extra == "doc"
44
47
  Requires-Dist: recommonmark ; extra == "doc"
45
48
  Requires-Dist: Sphinx>=7.1.0,<8.2 ; extra == "doc"
@@ -1,4 +1,4 @@
1
- pyedb/__init__.py,sha256=G_ee9nnIb6Tawc3UpvP8dLeQ3Sek_yEiHAW58Bvy2AE,2481
1
+ pyedb/__init__.py,sha256=Esfzb0UubxBroa2b0u_R9mdYjRChzcJ9lK2OolPTH0g,2481
2
2
  pyedb/edb_logger.py,sha256=2BSlxqLoCGsTXj8lATyS5I0K7lcsJDb6QMmJKrT76Ng,14497
3
3
  pyedb/exceptions.py,sha256=0k9el_FHZ4n4NqOPxGYwucM2gNxFg0wsA5eTgBJvusw,1265
4
4
  pyedb/siwave.py,sha256=3FOmv2qJ715Ge4hLtn2eIp7ev5PUjHD-pbmbbiWnTH4,18890
@@ -9,7 +9,7 @@ pyedb/component_libraries/ansys_components.py,sha256=lTbhR1vWYKg8Vo-wFzTkbdH34RM
9
9
  pyedb/configuration/__init__.py,sha256=OJ9mR_iVLyrBuMpwX5V4aJbJI3eD3PC6iJ5u4UzbQUU,1153
10
10
  pyedb/configuration/cfg_boundaries.py,sha256=XJS8WcG-QGBKXOaxIBD64MpAqrZBlEfYHi2PC7uBYwA,6438
11
11
  pyedb/configuration/cfg_common.py,sha256=hmg0zPuYT1lhaypdgwGdAeTjMp0BfTHBiTgMhvIuDmc,2414
12
- pyedb/configuration/cfg_components.py,sha256=RR9JWW51Qkkg39hBNateNKAg4-d5_AbYKu4_zBUc9J0,12701
12
+ pyedb/configuration/cfg_components.py,sha256=n92did3VCHnuYu1d3ugn1YvSPfjrpo7_YSpwY6Toh-o,13941
13
13
  pyedb/configuration/cfg_data.py,sha256=bUjbuzxzgxvWOHXnVPrPC_vHrwEZvWNVqbTs62LF_mE,3998
14
14
  pyedb/configuration/cfg_general.py,sha256=xbYqWHEOK-Me49R3qaRe9EREOOxe8nWZS2z3-NRWsYo,2273
15
15
  pyedb/configuration/cfg_modeler.py,sha256=UkZ6yPIRWcLLEa8sy2cwwCUlD0MDZx3QSgcJcrs_Pp0,6411
@@ -27,19 +27,19 @@ pyedb/configuration/cfg_terminals.py,sha256=RZ37oFxAyRwfl2zqz4pR-ZM0LSC7lptByJAl
27
27
  pyedb/configuration/configuration.py,sha256=sX_2gUuis4KQuw-6OIuzx4O813lx-hvDIw3NuDw0BAA,33071
28
28
  pyedb/dotnet/__init__.py,sha256=OJ9mR_iVLyrBuMpwX5V4aJbJI3eD3PC6iJ5u4UzbQUU,1153
29
29
  pyedb/dotnet/clr_module.py,sha256=lmDEAC_mCKHQniHc6LukqFY8uLDR_r7YeKesi_9hIs4,6625
30
- pyedb/dotnet/edb.py,sha256=lK2KXirq0OOsIyCnWbjapAvlgkleqmAGLcCriIUzqM0,190275
30
+ pyedb/dotnet/edb.py,sha256=rGCltchWvlLrQFhSGNHZ9I_u3Vr1OwLE0JcSGFVMnn8,192890
31
31
  pyedb/dotnet/database/Variables.py,sha256=PsvRAvPk75xc0RAAjFKPh96kZf0VbQ42h5J09_-ChMY,78441
32
32
  pyedb/dotnet/database/__init__.py,sha256=D3-syE4lEq7JSW7w_HW8W7uNg2SBuggKdQLGIiK9DBk,1206
33
- pyedb/dotnet/database/components.py,sha256=FBVta-7IMU_FHuZy9yQjBJDJ17EJm8hbJqANEL9Y_-M,111533
33
+ pyedb/dotnet/database/components.py,sha256=Lr_fK561uPTsanb9rGfjiNKtwHDu71mw2EBatar4Fio,111693
34
34
  pyedb/dotnet/database/general.py,sha256=pG2gt1JdYREZBSyWCIfSHo9n5221SMHJV7d5_2v8F3Q,4693
35
35
  pyedb/dotnet/database/hfss.py,sha256=rf1VY0D7qHriEMUB5J6ohI4v9BpNmIPHnNyaTRl3euc,69079
36
36
  pyedb/dotnet/database/layout_obj_instance.py,sha256=68c_dQsSDQvCwkoUgweIp_TuouT7zVEeLq22jxTzPZE,1407
37
37
  pyedb/dotnet/database/layout_validation.py,sha256=8G6YtswzBSRtSz1VFE9ZRO80aBD3HgmRXZhbKQ5_Lzc,13921
38
38
  pyedb/dotnet/database/materials.py,sha256=c5ydASjoJDtynqxmtqD4BUfVpMQxMiy6yfQF-igEg-4,47979
39
- pyedb/dotnet/database/modeler.py,sha256=rpPUoqBd_msGmvj7bSRaWAt3vBJE0EjCwgCNPBEJXTA,57564
39
+ pyedb/dotnet/database/modeler.py,sha256=COeJcyf_m2DlYEQJ1wLE3yrL6cExwG7qbo2VYo1J55w,57582
40
40
  pyedb/dotnet/database/net_class.py,sha256=zT-Z9JeYUfp3zkc7jTuoZ7sh1RlAvsDKPKycRaBi79o,11354
41
41
  pyedb/dotnet/database/nets.py,sha256=DXg4M_9a_0JTQxWKWL8N7cALVhXfWQsWd6XA4PoCEog,25893
42
- pyedb/dotnet/database/padstack.py,sha256=2EwOQIDi81KyvQ9K5b7bsMdyAhd6cu4p2VsmKh4aPso,79017
42
+ pyedb/dotnet/database/padstack.py,sha256=TikMBaHlsuT6eStyqWcdsWHqgcXgJg-qc3skYJsfXaI,88156
43
43
  pyedb/dotnet/database/siwave.py,sha256=h3mxggtzovXuoVRd0UEClR1XU0x2lOaGo9kzxw8EixI,64780
44
44
  pyedb/dotnet/database/stackup.py,sha256=D6ZuGWeocyEV3rCObp4jF1CuFFZh5mrzih_pOLsC5Qw,119219
45
45
  pyedb/dotnet/database/cell/__init__.py,sha256=OJ9mR_iVLyrBuMpwX5V4aJbJI3eD3PC6iJ5u4UzbQUU,1153
@@ -48,13 +48,13 @@ pyedb/dotnet/database/cell/layout.py,sha256=VBrc1LdEl4Ik8LzSazLWKrvaMvy9IIrzG0vd
48
48
  pyedb/dotnet/database/cell/layout_obj.py,sha256=yICKGRmMfCHmPe47d7MlVZlZmBV35spDreWXu7dP4rM,2746
49
49
  pyedb/dotnet/database/cell/voltage_regulator.py,sha256=DE9u6FKi2hjUB0CTZFScg_6iq4LHpq0BmI0icQAy9A0,4526
50
50
  pyedb/dotnet/database/cell/hierarchy/__init__.py,sha256=OJ9mR_iVLyrBuMpwX5V4aJbJI3eD3PC6iJ5u4UzbQUU,1153
51
- pyedb/dotnet/database/cell/hierarchy/component.py,sha256=9mbWWlxoR4qDfLcZkNkpIbwdEOaFdIetK6_ppEZzIrA,36438
51
+ pyedb/dotnet/database/cell/hierarchy/component.py,sha256=JCtL0vCj8-7jcmFoGn8gQ6U4FEYe-2YzHyXMd89q35Y,36563
52
52
  pyedb/dotnet/database/cell/hierarchy/hierarchy_obj.py,sha256=NmaSQ8eBOZZGQLoKErSz26w1C-xkdqPX6h0tOxVWgyg,2160
53
- pyedb/dotnet/database/cell/hierarchy/model.py,sha256=iUO7mL-ddO75iFhySYy_NbF2VLrDWXQQw--TUETxzUg,3195
53
+ pyedb/dotnet/database/cell/hierarchy/model.py,sha256=uGrZdFqHtAXz_w0AHAwu1nAYahFBPEYArrzucB71odo,2551
54
54
  pyedb/dotnet/database/cell/hierarchy/netlist_model.py,sha256=WgM2l2J_JxUx2KO-tPETt8R1eG-hfqtx2qTPOqbpi3U,1356
55
55
  pyedb/dotnet/database/cell/hierarchy/pin_pair_model.py,sha256=lccHcPdVV52I7iSoIDdVwFfXu4bfbRWjyHEWMq8lnfA,3792
56
- pyedb/dotnet/database/cell/hierarchy/s_parameter_model.py,sha256=xhDxEx2UqihbyQuuuy_9qcYyCS7NAm1FG4DRrYKHGXo,1624
57
- pyedb/dotnet/database/cell/hierarchy/spice_model.py,sha256=7v0oYZEPoaNqRy_oQTIoNOYAKHP-4ZslGMKy2z6CvFg,1443
56
+ pyedb/dotnet/database/cell/hierarchy/s_parameter_model.py,sha256=Rt5QTkT4Jo2uwJatcxSjaZBObq1OrPu_kNwBjULlzOs,1561
57
+ pyedb/dotnet/database/cell/hierarchy/spice_model.py,sha256=-EJyAnNqi3qQnYDIVqH6H7Gkc0vQL7jOwI5vVfgtt-c,1618
58
58
  pyedb/dotnet/database/cell/primitive/__init__.py,sha256=7NPaGZGMsJCO1-oSV9ParBV6Mn3nf8rvGZwdtv7TJRI,1212
59
59
  pyedb/dotnet/database/cell/primitive/bondwire.py,sha256=11guTOqFmQXASuJ1KK8y9BYz_it8XMWrdvb5Lbr4HUM,7322
60
60
  pyedb/dotnet/database/cell/primitive/path.py,sha256=hRC3IZgLaX0aKH3OwMdPMtqr5TzL5qEHS1HKYODwICI,13091
@@ -82,7 +82,7 @@ pyedb/dotnet/database/edb_data/edbvalue.py,sha256=7UEtow-5f4ZE4k9IsAe6ReOBVqaRzj
82
82
  pyedb/dotnet/database/edb_data/hfss_extent_info.py,sha256=wf3DuUuTPrMVk8UhppLUvNvrooBMZOHkKjwUcuyhJgI,12974
83
83
  pyedb/dotnet/database/edb_data/layer_data.py,sha256=dWGf-EajSQRZKI-mca6LqW03cDNpFvE6s4XHeMkwqPg,34348
84
84
  pyedb/dotnet/database/edb_data/nets_data.py,sha256=9CAJ-_nohS8En6RV5xsBUeIhh4cZ7VOQ-WH-GjMAtmQ,10012
85
- pyedb/dotnet/database/edb_data/padstacks_data.py,sha256=GaBW7TXy-6B60rAEdE-tZuW3BMr8DVxTFaaxYaA05Wc,83784
85
+ pyedb/dotnet/database/edb_data/padstacks_data.py,sha256=FCwGQLiQFvST_5SaPsOcMe99bM6ME2v3kF6Ki7TRtMA,83929
86
86
  pyedb/dotnet/database/edb_data/ports.py,sha256=pTfaz91heFdXRmACgCbQiRzSoO-8AXUZ6Mah-cqSMwg,6741
87
87
  pyedb/dotnet/database/edb_data/primitives_data.py,sha256=ONdtV0J105bCV_iW0UDmz_izF7aNyb4YdDbeduhRV-A,16893
88
88
  pyedb/dotnet/database/edb_data/raptor_x_simulation_setup_data.py,sha256=ToaXAvo8io8M4zEW4gJmhe11pESMGAlH-wuxDDsYQ9Y,20819
@@ -120,15 +120,15 @@ pyedb/generic/constants.py,sha256=2yBSTCuXuKn-x_hBzTXnTT8XMTRb2EC2f00PiaamG6g,28
120
120
  pyedb/generic/data_handlers.py,sha256=KpnHWVFOHOgGyTL70NCE9hzQSKnuSOw6k1i1e0Ph8PM,7691
121
121
  pyedb/generic/design_types.py,sha256=x7K6hogLGTLjF14xoocRVhr_gCY9ZoMcs_T2RN6EDNo,11561
122
122
  pyedb/generic/filesystem.py,sha256=3aOqVAKINeBwk0ffN7Jmozq7foHGpWFBQ7mVeCT1XPI,5049
123
- pyedb/generic/general_methods.py,sha256=Mfb6eKkLji7Cizi4weM2jlg5vKE1z5e7LoHGdCOCPjY,37994
123
+ pyedb/generic/general_methods.py,sha256=7Bl7ISS2W9c0n_tJwxZJxdYzfIX6Hbct7hFqSDZt38I,38672
124
124
  pyedb/generic/grpc_warnings.py,sha256=Adt8x_1yGppQmFkC3ycfeC6oKVVC8xczIwftsF7Ot8w,1431
125
125
  pyedb/generic/plot.py,sha256=RsKcoWGKaZrXNknBRy9my1rEWE9f6ScIXUflXPzOG0w,5382
126
126
  pyedb/generic/process.py,sha256=fe3sJms-tLruW6CPDkUwa-TG2rgAplNHgeo-RbPF4rQ,13575
127
127
  pyedb/generic/settings.py,sha256=TMoOy33yB8pQe2tUuhqLzB0sb57S-d3RJnIBEbt9Qks,12122
128
128
  pyedb/grpc/__init__.py,sha256=OJ9mR_iVLyrBuMpwX5V4aJbJI3eD3PC6iJ5u4UzbQUU,1153
129
- pyedb/grpc/edb.py,sha256=DwehFgdTX0rADPAA7zlzc9oBk0xgHThmlZ0Q3ByVee8,119816
129
+ pyedb/grpc/edb.py,sha256=QwNCF8K_CMZXQiqWjOuXuOZefz83KlqorW3vniIc7Dc,122367
130
130
  pyedb/grpc/edb_init.py,sha256=MkBVAo21c4nSHDXS_-eLoHEdWYfSbCUAFqgm798CmDc,15447
131
- pyedb/grpc/rpc_session.py,sha256=wD6v98es7IGMheDsWMQ3dhzYakln6FkSKqiVTUnavpg,7157
131
+ pyedb/grpc/rpc_session.py,sha256=kUvxLCcjjMrvTSJZiPlKDozQzlayq0gWhnbTPVTBX60,7545
132
132
  pyedb/grpc/database/__init__.py,sha256=OJ9mR_iVLyrBuMpwX5V4aJbJI3eD3PC6iJ5u4UzbQUU,1153
133
133
  pyedb/grpc/database/_typing.py,sha256=OJ9mR_iVLyrBuMpwX5V4aJbJI3eD3PC6iJ5u4UzbQUU,1153
134
134
  pyedb/grpc/database/components.py,sha256=-n1lnwj0gdTrbj5gRkfPhVnnwavP3GezueApTfppMCk,83127
@@ -139,7 +139,7 @@ pyedb/grpc/database/hfss.py,sha256=Xl7aWXhLSQuYaDeJ6fV42GN9dqwAQYbsMNOktpWSqf0,4
139
139
  pyedb/grpc/database/layout_validation.py,sha256=R94Vk1owrpJItmzyH77fRwpjzSQ9b0-oxjc2iktTPIY,15960
140
140
  pyedb/grpc/database/modeler.py,sha256=wMiUxiB8ShLIS5jud0ZZI_kC6E9fh6S0Tsfg_mIlqg0,55865
141
141
  pyedb/grpc/database/nets.py,sha256=0H-g9Ene8uqGw8tFDXJqfs08bZ2foR4oEYJR32a2kvQ,30748
142
- pyedb/grpc/database/padstacks.py,sha256=LTYG6vUTvExjCrIZaGW4o_eg-8Sbbf2Nq1_SVAQ6N9c,74223
142
+ pyedb/grpc/database/padstacks.py,sha256=4F57052vzhkHx7CK4UAPIRT_VVNpEaQf0ZhVTD1neCE,83742
143
143
  pyedb/grpc/database/siwave.py,sha256=oEjAF6VapKAv3RH6T5CrfPs3i2ViSNKWofPWGCWpGoA,36631
144
144
  pyedb/grpc/database/source_excitations.py,sha256=QaUgO4FsG0CplAAYOgi_ZzKJgACn_QRtErHWaquagCs,129419
145
145
  pyedb/grpc/database/stackup.py,sha256=oHMLSi1ftY_JEMsQw9pBU8iGfYG7pUPVKUSc4-a2xUw,114139
@@ -147,10 +147,10 @@ pyedb/grpc/database/definition/__init__.py,sha256=OJ9mR_iVLyrBuMpwX5V4aJbJI3eD3P
147
147
  pyedb/grpc/database/definition/component_def.py,sha256=bac0XP9j0_MUTZVGnV2-3wkYleedEiBA72Y2wkdbHZ4,7579
148
148
  pyedb/grpc/database/definition/component_model.py,sha256=i00gkEZwDatx2-Al90eE7z-O8LPHYJVw7qMoDEwQv4s,1689
149
149
  pyedb/grpc/database/definition/component_pin.py,sha256=E7Jr-G0SiiHAWrbPQKm4lgJ0NyOmifOssFsnsRp1ogw,1493
150
- pyedb/grpc/database/definition/materials.py,sha256=KtGOY4nAqr8_WetYWqeAblFCwrejpQVvMTnvAFwx4-Y,45291
150
+ pyedb/grpc/database/definition/materials.py,sha256=4nywbkZqEUA3RGqK45njJsLfheCVCR8ZtDxhZ5DIBik,45312
151
151
  pyedb/grpc/database/definition/n_port_component_model.py,sha256=OYvvmiBvUV0i9C9MvqGMFxbToh83BDxF8mB5I_cC0D0,1543
152
152
  pyedb/grpc/database/definition/package_def.py,sha256=tK8Srl5Si0GqQ4Ukcn5YyO0xb43XSSO7RWNu1mS8LAU,8266
153
- pyedb/grpc/database/definition/padstack_def.py,sha256=gK7wMhd3UIdImDTRaaRZUiBpKITIYaUhV7iv2RHbDS4,31356
153
+ pyedb/grpc/database/definition/padstack_def.py,sha256=t5IBHAwPffi_4_0j-P4I3eKleGoS6MapzjRG9SqCYds,31468
154
154
  pyedb/grpc/database/geometry/__init__.py,sha256=OJ9mR_iVLyrBuMpwX5V4aJbJI3eD3PC6iJ5u4UzbQUU,1153
155
155
  pyedb/grpc/database/geometry/arc_data.py,sha256=ZyfxeRLxOveUpCcTCngeGOxrkLHB3vGgVbTukIir7dA,2794
156
156
  pyedb/grpc/database/geometry/point_3d_data.py,sha256=pp9lIh9dK6zAN7WBn93ktIzTJmNOxrBdtHSpDAgETbY,2174
@@ -181,7 +181,7 @@ pyedb/grpc/database/ports/ports.py,sha256=ftwXCttMOdVWw2agDJ0Brmk4w0KsTDo5ulMk8C
181
181
  pyedb/grpc/database/primitive/__init__.py,sha256=7NPaGZGMsJCO1-oSV9ParBV6Mn3nf8rvGZwdtv7TJRI,1212
182
182
  pyedb/grpc/database/primitive/bondwire.py,sha256=bUaHwjfa0kasCL0bNpLqejqsLYFAzPjpdpsHiOAaD6w,3984
183
183
  pyedb/grpc/database/primitive/circle.py,sha256=Zws0l_9M9kee6uv1if-Z5gvHCjPNRrNakEZ2giVPCkc,3846
184
- pyedb/grpc/database/primitive/padstack_instance.py,sha256=GjsGDwCpCtHplq8ieM0icuJ4GElW7GEtdCqBwbQaLi8,46197
184
+ pyedb/grpc/database/primitive/padstack_instance.py,sha256=xcj1SVtM4hqtzjcAxcitp7E46-pmZMpf-A7x3kkNc5o,49300
185
185
  pyedb/grpc/database/primitive/path.py,sha256=kiEQ51GeUjQbYS8rQc9u-qJJn2gnjBVCU2ACZfCVwNU,17509
186
186
  pyedb/grpc/database/primitive/polygon.py,sha256=iwgrmUfLtHnmCFEIVzsPpxsUrgi2mO3YymFetRHahY4,12221
187
187
  pyedb/grpc/database/primitive/primitive.py,sha256=Ec-lZXHSk5iqofb80_L8oIgvCZW46OA09Z2q67Cz20A,24957
@@ -299,10 +299,20 @@ pyedb/siwave_core/icepak.py,sha256=bix1re40QdDleHFycoe0QvBg2DRVxlbIH7xKHpGcgbo,5
299
299
  pyedb/siwave_core/product_properties.py,sha256=0-IJORsDXjox2novDQj9A_g9uDJ6oSQYw8JxcsW9WE4,6815
300
300
  pyedb/siwave_core/cpa/__init__.py,sha256=OJ9mR_iVLyrBuMpwX5V4aJbJI3eD3PC6iJ5u4UzbQUU,1153
301
301
  pyedb/siwave_core/cpa/simulation_setup_data_model.py,sha256=Rwqt1E6zjBxGnjOHbANTcfHQtuzEGCGztQY1XxrfAh0,6731
302
+ pyedb/workflows/__init__.py,sha256=OJ9mR_iVLyrBuMpwX5V4aJbJI3eD3PC6iJ5u4UzbQUU,1153
303
+ pyedb/workflows/job_manager/__init__.py,sha256=OJ9mR_iVLyrBuMpwX5V4aJbJI3eD3PC6iJ5u4UzbQUU,1153
304
+ pyedb/workflows/job_manager/backend/__init__.py,sha256=OJ9mR_iVLyrBuMpwX5V4aJbJI3eD3PC6iJ5u4UzbQUU,1153
305
+ pyedb/workflows/job_manager/backend/job_manager_handler.py,sha256=Qa6IjX6OV1vNXVNZjKD9ZwNfFiJdGlUTh4gpiJmd0XM,30553
306
+ pyedb/workflows/job_manager/backend/job_submission.py,sha256=QEo621hYOli1axs0bRMTryvr4yvhANHANnkJNiNOsSk,43142
307
+ pyedb/workflows/job_manager/backend/service.py,sha256=HlPsyW7xQq-qgICaeEzWjuF_tuudwL1i8Df0w_bwLzw,61274
308
+ pyedb/workflows/job_manager/backend/start_service.py,sha256=V4mEG_fbw0_uaxcl18o33BliagThXehN3kgBfJ9iOgA,2725
309
+ pyedb/workflows/job_manager/backend/submit_job_on_scheduler.py,sha256=lfPueAp6bXaLJ2E_xKLkN0xgeoqXPQbECK0ewyTQL3M,5503
310
+ pyedb/workflows/job_manager/backend/submit_local_job.py,sha256=TzobXqrN11OxCMTNmK7QIiiPnqWz3ugcSXs-qOvBBcw,5580
302
311
  pyedb/workflows/sipi/hfss_auto_configuration.py,sha256=k7dYnPxhOuMlv3MECY6fXoiDMPhANwHpQH-TWKRqPTk,28307
303
- pyedb/workflows/utilities/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
304
- pyedb/workflows/utilities/cutout.py,sha256=APqPfkkCaqmQ61ds_Lsm8lLZVrQ05PoURWK14xtFbKg,62446
305
- pyedb-0.60.0.dist-info/licenses/LICENSE,sha256=EYDaskLuQxdNNOubsr9Xmgf_0bebDOEcd1ewKBOLCnQ,1098
306
- pyedb-0.60.0.dist-info/WHEEL,sha256=G2gURzTEtmeR8nrdXUJfNiB3VYVxigPQ-bEQujpNiNs,82
307
- pyedb-0.60.0.dist-info/METADATA,sha256=XPwi4VEXnw0aV2JOTW3L-FNfO3bLkUx4NEDhD6Mana0,8653
308
- pyedb-0.60.0.dist-info/RECORD,,
312
+ pyedb/workflows/utilities/__init__.py,sha256=OJ9mR_iVLyrBuMpwX5V4aJbJI3eD3PC6iJ5u4UzbQUU,1153
313
+ pyedb/workflows/utilities/cutout.py,sha256=AuMca1GQB74rrqcpP-rwKr1jB9Ib5LuhgeWghOc41Jk,62446
314
+ pyedb/workflows/utilities/hfss_log_parser.py,sha256=1ha7vwF1k8aMLsHOGTHOmnLKToOkgy72eYmsyaTLj5k,15340
315
+ pyedb-0.61.0.dist-info/licenses/LICENSE,sha256=EYDaskLuQxdNNOubsr9Xmgf_0bebDOEcd1ewKBOLCnQ,1098
316
+ pyedb-0.61.0.dist-info/WHEEL,sha256=G2gURzTEtmeR8nrdXUJfNiB3VYVxigPQ-bEQujpNiNs,82
317
+ pyedb-0.61.0.dist-info/METADATA,sha256=DJR2MgorMiJ0KOEIz1UIneAsV9CK4KNFXV8zReV0XIY,8748
318
+ pyedb-0.61.0.dist-info/RECORD,,
File without changes