pyedb 0.55.0__py3-none-any.whl → 0.57.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 (107) hide show
  1. pyedb/__init__.py +1 -1
  2. pyedb/configuration/cfg_data.py +3 -0
  3. pyedb/configuration/cfg_operations.py +2 -2
  4. pyedb/configuration/cfg_ports_sources.py +1 -1
  5. pyedb/configuration/cfg_terminals.py +232 -0
  6. pyedb/configuration/configuration.py +146 -3
  7. pyedb/dotnet/clr_module.py +1 -2
  8. pyedb/dotnet/database/Variables.py +56 -41
  9. pyedb/dotnet/database/cell/layout.py +5 -1
  10. pyedb/dotnet/database/cell/primitive/primitive.py +2 -2
  11. pyedb/dotnet/database/cell/terminal/bundle_terminal.py +12 -0
  12. pyedb/dotnet/database/cell/terminal/pingroup_terminal.py +1 -1
  13. pyedb/dotnet/database/cell/terminal/terminal.py +38 -0
  14. pyedb/dotnet/database/components.py +55 -52
  15. pyedb/dotnet/database/dotnet/database.py +1 -0
  16. pyedb/dotnet/database/edb_data/control_file.py +6 -3
  17. pyedb/dotnet/database/edb_data/nets_data.py +3 -3
  18. pyedb/dotnet/database/edb_data/padstacks_data.py +5 -2
  19. pyedb/dotnet/database/edb_data/ports.py +0 -25
  20. pyedb/dotnet/database/edb_data/primitives_data.py +3 -3
  21. pyedb/dotnet/database/edb_data/raptor_x_simulation_setup_data.py +18 -19
  22. pyedb/dotnet/database/edb_data/simulation_configuration.py +3 -3
  23. pyedb/dotnet/database/hfss.py +9 -8
  24. pyedb/dotnet/database/layout_validation.py +6 -3
  25. pyedb/dotnet/database/materials.py +1 -3
  26. pyedb/dotnet/database/modeler.py +7 -3
  27. pyedb/dotnet/database/nets.py +27 -19
  28. pyedb/dotnet/database/padstack.py +91 -2
  29. pyedb/dotnet/database/sim_setup_data/io/siwave.py +1 -1
  30. pyedb/dotnet/database/siwave.py +4 -3
  31. pyedb/dotnet/database/stackup.py +50 -26
  32. pyedb/dotnet/database/utilities/heatsink.py +0 -1
  33. pyedb/dotnet/database/utilities/simulation_setup.py +7 -5
  34. pyedb/dotnet/database/utilities/siwave_cpa_simulation_setup.py +1 -0
  35. pyedb/dotnet/database/utilities/siwave_simulation_setup.py +5 -2
  36. pyedb/dotnet/edb.py +41 -36
  37. pyedb/exceptions.py +1 -2
  38. pyedb/extensions/create_cell_array.py +408 -0
  39. pyedb/generic/data_handlers.py +17 -28
  40. pyedb/generic/design_types.py +25 -38
  41. pyedb/generic/filesystem.py +9 -4
  42. pyedb/generic/general_methods.py +6 -7
  43. pyedb/generic/plot.py +2 -2
  44. pyedb/generic/settings.py +4 -0
  45. pyedb/grpc/database/_typing.py +0 -0
  46. pyedb/grpc/database/components.py +30 -11
  47. pyedb/grpc/database/control_file.py +14 -35
  48. pyedb/grpc/database/definition/materials.py +1 -1
  49. pyedb/grpc/database/definition/package_def.py +6 -3
  50. pyedb/grpc/database/definition/padstack_def.py +4 -7
  51. pyedb/grpc/database/hfss.py +1 -4
  52. pyedb/grpc/database/hierarchy/component.py +3 -4
  53. pyedb/grpc/database/hierarchy/pingroup.py +16 -3
  54. pyedb/grpc/database/layers/layer.py +1 -2
  55. pyedb/grpc/database/layers/stackup_layer.py +42 -19
  56. pyedb/grpc/database/layout/layout.py +117 -28
  57. pyedb/grpc/database/layout/voltage_regulator.py +6 -1
  58. pyedb/grpc/database/layout_validation.py +7 -4
  59. pyedb/grpc/database/modeler.py +241 -256
  60. pyedb/grpc/database/net/differential_pair.py +9 -2
  61. pyedb/grpc/database/net/extended_net.py +24 -9
  62. pyedb/grpc/database/net/net.py +14 -5
  63. pyedb/grpc/database/net/net_class.py +24 -7
  64. pyedb/grpc/database/nets.py +11 -43
  65. pyedb/grpc/database/padstacks.py +92 -16
  66. pyedb/grpc/database/primitive/bondwire.py +3 -67
  67. pyedb/grpc/database/primitive/circle.py +42 -3
  68. pyedb/grpc/database/primitive/padstack_instance.py +17 -19
  69. pyedb/grpc/database/primitive/path.py +154 -5
  70. pyedb/grpc/database/primitive/polygon.py +75 -9
  71. pyedb/grpc/database/primitive/primitive.py +2 -2
  72. pyedb/grpc/database/primitive/rectangle.py +105 -4
  73. pyedb/grpc/database/simulation_setup/hfss_general_settings.py +0 -2
  74. pyedb/grpc/database/simulation_setup/hfss_settings_options.py +0 -4
  75. pyedb/grpc/database/simulation_setup/siwave_cpa_simulation_setup.py +4 -2
  76. pyedb/grpc/database/simulation_setup/sweep_data.py +1 -3
  77. pyedb/grpc/database/siwave.py +6 -13
  78. pyedb/grpc/database/source_excitations.py +49 -57
  79. pyedb/grpc/database/stackup.py +50 -27
  80. pyedb/grpc/database/terminal/bundle_terminal.py +10 -3
  81. pyedb/grpc/database/terminal/pingroup_terminal.py +8 -1
  82. pyedb/grpc/database/terminal/terminal.py +19 -8
  83. pyedb/grpc/database/utility/heat_sink.py +0 -1
  84. pyedb/grpc/database/utility/hfss_extent_info.py +2 -2
  85. pyedb/grpc/database/utility/value.py +1 -0
  86. pyedb/grpc/database/utility/xml_control_file.py +6 -3
  87. pyedb/grpc/edb.py +33 -24
  88. pyedb/grpc/edb_init.py +1 -0
  89. pyedb/grpc/rpc_session.py +4 -3
  90. pyedb/ipc2581/ecad/cad_data/layer_feature.py +6 -2
  91. pyedb/ipc2581/ecad/cad_data/step.py +1 -1
  92. pyedb/ipc2581/ipc2581.py +8 -7
  93. pyedb/libraries/common.py +3 -4
  94. pyedb/libraries/rf_libraries/base_functions.py +7 -16
  95. pyedb/libraries/rf_libraries/planar_antennas.py +3 -21
  96. pyedb/misc/downloads.py +1 -0
  97. pyedb/misc/misc.py +5 -2
  98. pyedb/misc/siw_feature_config/emc_rule_checker_settings.py +1 -1
  99. pyedb/misc/utilities.py +0 -1
  100. pyedb/modeler/geometry_operators.py +9 -8
  101. pyedb/siwave.py +4 -6
  102. pyedb/siwave_core/__init__.py +0 -0
  103. pyedb/siwave_core/cpa/__init__.py +0 -0
  104. {pyedb-0.55.0.dist-info → pyedb-0.57.0.dist-info}/METADATA +3 -3
  105. {pyedb-0.55.0.dist-info → pyedb-0.57.0.dist-info}/RECORD +107 -102
  106. {pyedb-0.55.0.dist-info → pyedb-0.57.0.dist-info}/WHEEL +0 -0
  107. {pyedb-0.55.0.dist-info → pyedb-0.57.0.dist-info}/licenses/LICENSE +0 -0
@@ -28,14 +28,13 @@ import warnings
28
28
  from ansys.edb.core.definition.component_model import (
29
29
  NPortComponentModel as GrpcNPortComponentModel,
30
30
  )
31
- from ansys.edb.core.definition.die_property import DieOrientation as GrpcDieOrientation
32
- from ansys.edb.core.definition.die_property import DieType as GrpcDieType
31
+ from ansys.edb.core.definition.die_property import DieOrientation as GrpcDieOrientation, DieType as GrpcDieType
33
32
  from ansys.edb.core.definition.solder_ball_property import SolderballShape
34
33
  from ansys.edb.core.geometry.polygon_data import PolygonData as GrpcPolygonData
35
34
  from ansys.edb.core.hierarchy.component_group import (
36
35
  ComponentGroup as GrpcComponentGroup,
36
+ ComponentType as GrpcComponentType,
37
37
  )
38
- from ansys.edb.core.hierarchy.component_group import ComponentType as GrpcComponentType
39
38
  from ansys.edb.core.hierarchy.netlist_model import NetlistModel as GrpcNetlistModel
40
39
  from ansys.edb.core.hierarchy.pin_pair_model import PinPairModel as GrpcPinPairModel
41
40
  from ansys.edb.core.hierarchy.sparameter_model import (
@@ -1102,7 +1101,7 @@ class Component(GrpcComponentGroup):
1102
1101
  return False
1103
1102
  if not reference_net:
1104
1103
  self._pedb.logger.warning(
1105
- f"No reference net provided for S parameter file {file_path}, net `GND` is " f"assigned by default"
1104
+ f"No reference net provided for S parameter file {file_path}, net `GND` is assigned by default"
1106
1105
  )
1107
1106
  reference_net = "GND"
1108
1107
  n_port_model = GrpcNPortComponentModel.find_by_name(self.component_def, name)
@@ -20,16 +20,20 @@
20
20
  # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
21
  # SOFTWARE.
22
22
 
23
+ from __future__ import annotations
23
24
 
25
+ from typing import TYPE_CHECKING
26
+
27
+ if TYPE_CHECKING:
28
+ from pyedb.grpc.database.hierarchy.component import Component
29
+ from pyedb.grpc.database.net.net import Net
30
+ from pyedb.grpc.database.primitive.padstack_instance import PadstackInstance
24
31
  from typing import Union
25
32
 
26
33
  from ansys.edb.core.hierarchy.pin_group import PinGroup as GrpcPinGroup
27
34
  from ansys.edb.core.terminal.terminal import BoundaryType as GrpcBoundaryType
28
35
 
29
36
  from pyedb.generic.general_methods import generate_unique_name
30
- from pyedb.grpc.database.hierarchy.component import Component
31
- from pyedb.grpc.database.net.net import Net
32
- from pyedb.grpc.database.primitive.padstack_instance import PadstackInstance
33
37
  from pyedb.grpc.database.terminal.pingroup_terminal import PinGroupTerminal
34
38
  from pyedb.grpc.database.utility.value import Value
35
39
 
@@ -63,10 +67,13 @@ class PinGroup(GrpcPinGroup):
63
67
  :class:`Component <pyedb.grpc.database.hierarchy.component.Component>`
64
68
  Pin group component.
65
69
  """
70
+
66
71
  return Component(self._pedb, super().component)
67
72
 
68
73
  @component.setter
69
74
  def component(self, value):
75
+ from pyedb.grpc.database.hierarchy.component import Component
76
+
70
77
  if isinstance(value, Component):
71
78
  super(PinGroup, self.__class__).component.__set__(self, value)
72
79
 
@@ -78,6 +85,8 @@ class PinGroup(GrpcPinGroup):
78
85
  -------
79
86
  Dict[:class:`PadstackInstance <pyedb.grpc.database.primitive.padstack_instance.PadstackInstance>`].
80
87
  """
88
+ from pyedb.grpc.database.primitive.padstack_instance import PadstackInstance
89
+
81
90
  return {i.name: PadstackInstance(self._pedb, i) for i in super().pins}
82
91
 
83
92
  @property
@@ -88,10 +97,14 @@ class PinGroup(GrpcPinGroup):
88
97
  -------
89
98
  :class:`Net <ansys.edb.core.net.net.Net>`.
90
99
  """
100
+ from pyedb.grpc.database.net.net import Net
101
+
91
102
  return Net(self._pedb, super().net)
92
103
 
93
104
  @net.setter
94
105
  def net(self, value):
106
+ from pyedb.grpc.database.net.net import Net
107
+
95
108
  if isinstance(value, Net):
96
109
  super(PinGroup, self.__class__).net.__set__(self, value)
97
110
 
@@ -6,8 +6,7 @@
6
6
 
7
7
  from __future__ import absolute_import
8
8
 
9
- from ansys.edb.core.layer.layer import Layer as GrpcLayer
10
- from ansys.edb.core.layer.layer import LayerType as GrpcLayerType
9
+ from ansys.edb.core.layer.layer import Layer as GrpcLayer, LayerType as GrpcLayerType
11
10
 
12
11
 
13
12
  class Layer(GrpcLayer):
@@ -23,8 +23,7 @@
23
23
  from __future__ import absolute_import
24
24
 
25
25
  from ansys.edb.core.layer.layer import LayerType as GrpcLayerType
26
- from ansys.edb.core.layer.stackup_layer import RoughnessRegion as GrpcRoughnessRegion
27
- from ansys.edb.core.layer.stackup_layer import StackupLayer as GrpcStackupLayer
26
+ from ansys.edb.core.layer.stackup_layer import RoughnessRegion as GrpcRoughnessRegion, StackupLayer as GrpcStackupLayer
28
27
 
29
28
  from pyedb.grpc.database.utility.value import Value
30
29
 
@@ -354,8 +353,11 @@ class StackupLayer(GrpcStackupLayer):
354
353
  if len(top_roughness_model) == 2:
355
354
  top_roughness_model[0] = Value(value)
356
355
  self.set_roughness_model(top_roughness_model, GrpcRoughnessRegion.TOP)
357
- except:
358
- pass
356
+ except Exception as e:
357
+ self._pedb.logger.error(
358
+ f"Failed to update property top_hallhuray_nodule_radius with value {value} "
359
+ f"- {type(e).__name__}: {str(e)}"
360
+ )
359
361
 
360
362
  @property
361
363
  def top_hallhuray_surface_ratio(self) -> float:
@@ -382,8 +384,11 @@ class StackupLayer(GrpcStackupLayer):
382
384
  if len(top_roughness_model) == 2:
383
385
  top_roughness_model[1] = Value(value)
384
386
  self.set_roughness_model(top_roughness_model, GrpcRoughnessRegion.TOP)
385
- except:
386
- pass
387
+ except Exception as e:
388
+ self._pedb.logger.error(
389
+ f"Failed to update property top_hallhuray_surface_ratio with value {value} "
390
+ f"- {type(e).__name__}: {str(e)}"
391
+ )
387
392
 
388
393
  @property
389
394
  def bottom_hallhuray_nodule_radius(self) -> float:
@@ -410,8 +415,11 @@ class StackupLayer(GrpcStackupLayer):
410
415
  if len(bottom_roughness_model) == 2:
411
416
  bottom_roughness_model[0] = Value(value)
412
417
  self.set_roughness_model(bottom_roughness_model, GrpcRoughnessRegion.BOTTOM)
413
- except:
414
- pass
418
+ except Exception as e:
419
+ self._pedb.logger.error(
420
+ f"Failed to update property bottom_hallhuray_nodule_radius with value {value} "
421
+ f"- {type(e).__name__}: {str(e)}"
422
+ )
415
423
 
416
424
  @property
417
425
  def bottom_hallhuray_surface_ratio(self) -> float:
@@ -438,8 +446,11 @@ class StackupLayer(GrpcStackupLayer):
438
446
  if len(bottom_roughness_model) == 2:
439
447
  bottom_roughness_model[1] = Value(value)
440
448
  self.set_roughness_model(bottom_roughness_model, GrpcRoughnessRegion.BOTTOM)
441
- except:
442
- pass
449
+ except Exception as e:
450
+ self._pedb.logger.error(
451
+ f"Failed to update property bottom_hallhuray_surface_ratio with value {value} "
452
+ f"- {type(e).__name__}: {str(e)}"
453
+ )
443
454
 
444
455
  @property
445
456
  def side_hallhuray_nodule_radius(self) -> float:
@@ -466,8 +477,11 @@ class StackupLayer(GrpcStackupLayer):
466
477
  if len(side_roughness_model) == 2:
467
478
  side_roughness_model[0] = Value(value)
468
479
  self.set_roughness_model(side_roughness_model, GrpcRoughnessRegion.SIDE)
469
- except:
470
- pass
480
+ except Exception as e:
481
+ self._pedb.logger.error(
482
+ f"Failed to update property side_hallhuray_nodule_radius with value {value} "
483
+ f"- {type(e).__name__}: {str(e)}"
484
+ )
471
485
 
472
486
  @property
473
487
  def side_hallhuray_surface_ratio(self) -> float:
@@ -493,8 +507,11 @@ class StackupLayer(GrpcStackupLayer):
493
507
  if len(side_roughness_model) == 2:
494
508
  side_roughness_model[1] = Value(value)
495
509
  self.set_roughness_model(side_roughness_model, GrpcRoughnessRegion.SIDE)
496
- except:
497
- pass
510
+ except Exception as e:
511
+ self._pedb.logger.error(
512
+ f"Failed to update property side_hallhuray_surface_ratio with value {value} "
513
+ f"- {type(e).__name__}: {str(e)}"
514
+ )
498
515
 
499
516
  @property
500
517
  def top_groisse_roughness(self) -> float:
@@ -521,8 +538,10 @@ class StackupLayer(GrpcStackupLayer):
521
538
  if isinstance(top_roughness_model, Value):
522
539
  top_roughness_model = Value(value)
523
540
  self.set_roughness_model(top_roughness_model, GrpcRoughnessRegion.TOP)
524
- except:
525
- pass
541
+ except Exception as e:
542
+ self._pedb.logger.error(
543
+ f"Failed to update property top_groisse_roughness with value {value} - {type(e).__name__}: {str(e)}"
544
+ )
526
545
 
527
546
  @property
528
547
  def bottom_groisse_roughness(self) -> float:
@@ -549,8 +568,10 @@ class StackupLayer(GrpcStackupLayer):
549
568
  if isinstance(bottom_roughness_model, Value):
550
569
  bottom_roughness_model = Value(value)
551
570
  self.set_roughness_model(bottom_roughness_model, GrpcRoughnessRegion.BOTTOM)
552
- except:
553
- pass
571
+ except Exception as e:
572
+ self._pedb.logger.error(
573
+ f"Failed to update property bottom_groisse_roughness with value {value} - {type(e).__name__}: {str(e)}"
574
+ )
554
575
 
555
576
  @property
556
577
  def side_groisse_roughness(self) -> float:
@@ -578,7 +599,9 @@ class StackupLayer(GrpcStackupLayer):
578
599
  side_roughness_model = Value(value)
579
600
  self.set_roughness_model(side_roughness_model, GrpcRoughnessRegion.BOTTOM)
580
601
  except Exception as e:
581
- self._pedb.logger.error(e)
602
+ self._pedb.logger.error(
603
+ f"Failed to update property side_groisse_roughness with value {value} - {type(e).__name__}: {str(e)}"
604
+ )
582
605
 
583
606
  def assign_roughness_model(
584
607
  self,
@@ -23,30 +23,25 @@
23
23
  """
24
24
  This module contains these classes: `EdbLayout` and `Shape`.
25
25
  """
26
- from typing import Dict, Union
26
+
27
+ from __future__ import annotations
28
+
29
+ from typing import TYPE_CHECKING
30
+
31
+ if TYPE_CHECKING:
32
+ from pyedb.grpc.database.hierarchy.component import Component
33
+ from pyedb.grpc.database.net.net import Net
34
+ from pyedb.grpc.database.primitive.padstack_instance import PadstackInstance
35
+ from typing import Dict, List, Union
27
36
 
28
37
  from ansys.edb.core.layout.layout import Layout as GrpcLayout
29
- import ansys.edb.core.primitive.bondwire
30
- import ansys.edb.core.primitive.circle
31
- import ansys.edb.core.primitive.padstack_instance
32
- import ansys.edb.core.primitive.path
33
- import ansys.edb.core.primitive.polygon
34
- import ansys.edb.core.primitive.primitive
35
- import ansys.edb.core.primitive.rectangle
36
-
37
- from pyedb.grpc.database.hierarchy.component import Component
38
+
38
39
  from pyedb.grpc.database.hierarchy.pingroup import PinGroup
39
40
  from pyedb.grpc.database.layout.voltage_regulator import VoltageRegulator
40
41
  from pyedb.grpc.database.net.differential_pair import DifferentialPair
41
42
  from pyedb.grpc.database.net.extended_net import ExtendedNet
42
- from pyedb.grpc.database.net.net import Net
43
43
  from pyedb.grpc.database.net.net_class import NetClass
44
44
  from pyedb.grpc.database.primitive.bondwire import Bondwire
45
- from pyedb.grpc.database.primitive.circle import Circle
46
- from pyedb.grpc.database.primitive.padstack_instance import PadstackInstance
47
- from pyedb.grpc.database.primitive.path import Path
48
- from pyedb.grpc.database.primitive.polygon import Polygon
49
- from pyedb.grpc.database.primitive.rectangle import Rectangle
50
45
  from pyedb.grpc.database.terminal.bundle_terminal import BundleTerminal
51
46
  from pyedb.grpc.database.terminal.edge_terminal import EdgeTerminal
52
47
  from pyedb.grpc.database.terminal.padstack_instance_terminal import (
@@ -55,6 +50,30 @@ from pyedb.grpc.database.terminal.padstack_instance_terminal import (
55
50
  from pyedb.grpc.database.terminal.pingroup_terminal import PinGroupTerminal
56
51
  from pyedb.grpc.database.terminal.point_terminal import PointTerminal
57
52
 
53
+ _PRIMITIVE_TYPE_MAP = {
54
+ "Path": ("pyedb.grpc.database.primitive.path", "Path"),
55
+ "Polygon": ("pyedb.grpc.database.primitive.polygon", "Polygon"),
56
+ "PadstackInstance": ("pyedb.grpc.database.primitive.padstack_instance", "PadstackInstance"),
57
+ "Rectangle": ("pyedb.grpc.database.primitive.rectangle", "Rectangle"),
58
+ "Circle": ("pyedb.grpc.database.primitive.circle", "Circle"),
59
+ "Bondwire": ("pyedb.grpc.database.primitive.bondwire", "Bondwire"),
60
+ }
61
+
62
+ # Cache wrapper classes after first import
63
+ _WRAPPER_CLASS_CACHE = {}
64
+
65
+
66
+ def _get_wrapper_class(prim_type: str):
67
+ """Cached wrapper class retrieval"""
68
+ if prim_type not in _WRAPPER_CLASS_CACHE:
69
+ if prim_type in _PRIMITIVE_TYPE_MAP:
70
+ module_path, class_name = _PRIMITIVE_TYPE_MAP[prim_type]
71
+ # Import only once per type
72
+ module = __import__(module_path, fromlist=[class_name])
73
+ _WRAPPER_CLASS_CACHE[prim_type] = getattr(module, class_name)
74
+
75
+ return _WRAPPER_CLASS_CACHE.get(prim_type)
76
+
58
77
 
59
78
  class Layout(GrpcLayout):
60
79
  """Manage Layout class."""
@@ -78,18 +97,9 @@ class Layout(GrpcLayout):
78
97
  primitives = super().primitives
79
98
  self.__primitives = []
80
99
  for prim in primitives:
81
- if isinstance(prim, ansys.edb.core.primitive.path.Path):
82
- self.__primitives.append(Path(self._pedb, prim))
83
- elif isinstance(prim, ansys.edb.core.primitive.polygon.Polygon):
84
- self.__primitives.append(Polygon(self._pedb, prim))
85
- elif isinstance(prim, ansys.edb.core.primitive.padstack_instance.PadstackInstance):
86
- self.__primitives.append(PadstackInstance(self._pedb, prim))
87
- elif isinstance(prim, ansys.edb.core.primitive.rectangle.Rectangle):
88
- self.__primitives.append(Rectangle(self._pedb, prim))
89
- elif isinstance(prim, ansys.edb.core.primitive.circle.Circle):
90
- self.__primitives.append(Circle(self._pedb, prim))
91
- elif isinstance(prim, ansys.edb.core.primitive.bondwire.Bondwire):
92
- self.__primitives.append(Bondwire(self._pedb, prim))
100
+ wrapper_class = _get_wrapper_class(prim.__class__.__name__)
101
+ if wrapper_class:
102
+ self.__primitives.append(wrapper_class(self._pedb, prim))
93
103
  return self.__primitives
94
104
 
95
105
  @property
@@ -124,6 +134,8 @@ class Layout(GrpcLayout):
124
134
  List[:class:`Net <pyedb.grpc.database.net.net.Net>`]
125
135
  List of Net.
126
136
  """
137
+ from pyedb.grpc.database.net.net import Net
138
+
127
139
  return [Net(self._pedb, net) for net in super().nets]
128
140
 
129
141
  @property
@@ -147,6 +159,8 @@ class Layout(GrpcLayout):
147
159
  List of Component.
148
160
 
149
161
  """
162
+ from pyedb.grpc.database.hierarchy.component import Component
163
+
150
164
  return [Component(self._pedb, g) for g in self._pedb.active_cell.layout.groups]
151
165
 
152
166
  @property
@@ -200,6 +214,8 @@ class Layout(GrpcLayout):
200
214
  @property
201
215
  def padstack_instances(self) -> Dict[int, PadstackInstance]:
202
216
  """Get all padstack instances in a list."""
217
+ from pyedb.grpc.database.primitive.padstack_instance import PadstackInstance
218
+
203
219
  pad_stack_inst = super().padstack_instances
204
220
  self.__padstack_instances = {i.edb_uid: PadstackInstance(self._pedb, i) for i in pad_stack_inst}
205
221
  return self.__padstack_instances
@@ -243,3 +259,76 @@ class Layout(GrpcLayout):
243
259
  prims = [i for i in prims if i.layer_name in layer_name] if layer_name is not None else prims
244
260
  prims = [i for i in prims if i.net_name in net_name] if net_name is not None else prims
245
261
  return prims
262
+
263
+ def find_padstack_instances(
264
+ self,
265
+ aedt_name: Union[str, List[str]] = None,
266
+ component_name: Union[str, List[str]] = None,
267
+ component_pin_name: Union[str, List[str]] = None,
268
+ net_name: Union[str, List[str]] = None,
269
+ instance_id: Union[int, List[int]] = None,
270
+ ) -> List:
271
+ """
272
+ Finds padstack instances matching the specified criteria.
273
+
274
+ This method filters the available padstack instances based on specified attributes such as
275
+ `aedt_name`, `component_name`, `component_pin_name`, `net_name`, or `instance_id`. Criteria
276
+ can be passed as individual values or as a list of values. If no padstack instances match
277
+ the criteria, an error is raised.
278
+
279
+ Parameters
280
+ ----------
281
+ aedt_name : Union[str, List[str]], optional
282
+ Name(s) of the AEDT padstack instance(s) to filter.
283
+ component_name : Union[str, List[str]], optional
284
+ Name(s) of the component(s) to filter padstack instances by.
285
+ component_pin_name : Union[str, List[str]], optional
286
+ Name(s) of the component pin(s) to filter padstack instances by.
287
+ net_name : Union[str, List[str]], optional
288
+ Name(s) of the net(s) to filter padstack instances by.
289
+ instance_id : Union[int, List[int]], optional
290
+ ID(s) of the padstack instance(s) to filter.
291
+
292
+ Returns
293
+ -------
294
+ List
295
+ A list of padstack instances matching the specified criteria.
296
+ """
297
+ padstacks = self.padstack_instances
298
+ instances_found = []
299
+ if instance_id is not None:
300
+ instance_ids = instance_id if isinstance(instance_id, list) else [instance_id]
301
+ if instance_id in instance_ids:
302
+ instances_found.append(padstacks[instance_id])
303
+
304
+ if aedt_name is not None:
305
+ name = aedt_name if isinstance(aedt_name, list) else [aedt_name]
306
+ [instances_found.append(i) for i in list(padstacks.values()) if i.aedt_name in name]
307
+
308
+ if component_name is not None:
309
+ value = component_name if isinstance(component_name, list) else [component_name]
310
+ for inst in padstacks.values():
311
+ if inst.component:
312
+ if inst.component.name in value:
313
+ instances_found.append(inst)
314
+
315
+ if net_name is not None:
316
+ value = net_name if isinstance(net_name, list) else [net_name]
317
+ for inst in padstacks.values():
318
+ if inst.net:
319
+ if inst.net.name in value:
320
+ instances_found.append(inst)
321
+
322
+ if component_pin_name is not None:
323
+ value = component_pin_name if isinstance(component_name, list) else [component_pin_name]
324
+ for inst in padstacks.values():
325
+ if inst.component:
326
+ if hasattr(inst, "name"):
327
+ if inst.name in value:
328
+ instances_found.append(inst)
329
+ if not instances_found: # pragma: no cover
330
+ raise ValueError(
331
+ f"Failed to find padstack instances with aedt_name={aedt_name}, component_name={component_name}, "
332
+ f"net_name={net_name}, component_pin_name={component_pin_name}"
333
+ )
334
+ return instances_found
@@ -20,11 +20,16 @@
20
20
  # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
21
  # SOFTWARE.
22
22
 
23
+ from __future__ import annotations
24
+
25
+ from typing import TYPE_CHECKING
26
+
27
+ if TYPE_CHECKING:
28
+ from pyedb.grpc.database.primitive.padstack_instance import PadstackInstance
23
29
  from ansys.edb.core.layout.voltage_regulator import (
24
30
  VoltageRegulator as GrpcVoltageRegulator,
25
31
  )
26
32
 
27
- from pyedb.grpc.database.primitive.padstack_instance import PadstackInstance
28
33
  from pyedb.grpc.database.utility.value import Value
29
34
 
30
35
 
@@ -224,8 +224,11 @@ class LayoutValidation:
224
224
  if el.layout_obj.obj_type.value == 0:
225
225
  if not el.is_void:
226
226
  sum += el.area()
227
- except:
228
- pass
227
+ except Exception as e:
228
+ self._pedb._logger.warning(
229
+ f"A(n) {type(e).__name__} error occurred while calculating area "
230
+ f"for element {elem} - Default value of 0 is used: {str(e)}"
231
+ )
229
232
  return sum
230
233
 
231
234
  if order_by_area:
@@ -354,7 +357,7 @@ class LayoutValidation:
354
357
  temp = []
355
358
  for k, v in inductors.items():
356
359
  model = v.component_property.model
357
- if not len(model.pin_pairs): # pragma: no cover
360
+ if not len(model.pin_pairs()): # pragma: no cover
358
361
  temp.append(k)
359
362
  if fix:
360
363
  v.rlc_values = [0, 1, 0]
@@ -373,7 +376,7 @@ class LayoutValidation:
373
376
  >>> # Automatically assign names to unnamed padstacks
374
377
  >>> edb.layout_validation.padstacks_no_name(fix=True)
375
378
  """
376
- pds = self._pedb.layout.padstack_instances
379
+ pds = list(self._pedb.layout.padstack_instances.values())
377
380
  counts = 0
378
381
  via_count = 1
379
382
  for obj in pds: