pyedb 0.56.0__py3-none-any.whl → 0.58.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 (110) hide show
  1. pyedb/__init__.py +1 -1
  2. pyedb/configuration/cfg_data.py +3 -0
  3. pyedb/configuration/cfg_pin_groups.py +2 -0
  4. pyedb/configuration/cfg_terminals.py +232 -0
  5. pyedb/configuration/configuration.py +146 -3
  6. pyedb/dotnet/clr_module.py +1 -2
  7. pyedb/dotnet/database/Variables.py +30 -22
  8. pyedb/dotnet/database/cell/hierarchy/component.py +2 -8
  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 +15 -19
  15. pyedb/dotnet/database/dotnet/database.py +1 -0
  16. pyedb/dotnet/database/edb_data/control_file.py +19 -8
  17. pyedb/dotnet/database/edb_data/nets_data.py +3 -3
  18. pyedb/dotnet/database/edb_data/padstacks_data.py +39 -14
  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/edb_data/sources.py +21 -2
  24. pyedb/dotnet/database/general.py +1 -6
  25. pyedb/dotnet/database/hfss.py +9 -8
  26. pyedb/dotnet/database/layout_validation.py +14 -3
  27. pyedb/dotnet/database/materials.py +1 -3
  28. pyedb/dotnet/database/modeler.py +7 -3
  29. pyedb/dotnet/database/nets.py +27 -19
  30. pyedb/dotnet/database/padstack.py +4 -2
  31. pyedb/dotnet/database/sim_setup_data/io/siwave.py +54 -1
  32. pyedb/dotnet/database/siwave.py +4 -3
  33. pyedb/dotnet/database/stackup.py +55 -58
  34. pyedb/dotnet/database/utilities/heatsink.py +0 -1
  35. pyedb/dotnet/database/utilities/hfss_simulation_setup.py +81 -0
  36. pyedb/dotnet/database/utilities/simulation_setup.py +7 -5
  37. pyedb/dotnet/database/utilities/siwave_cpa_simulation_setup.py +1 -0
  38. pyedb/dotnet/database/utilities/siwave_simulation_setup.py +264 -13
  39. pyedb/dotnet/edb.py +65 -47
  40. pyedb/exceptions.py +1 -2
  41. pyedb/extensions/create_cell_array.py +67 -49
  42. pyedb/generic/data_handlers.py +13 -23
  43. pyedb/generic/design_types.py +9 -35
  44. pyedb/generic/filesystem.py +4 -2
  45. pyedb/generic/general_methods.py +28 -41
  46. pyedb/generic/plot.py +8 -23
  47. pyedb/generic/process.py +78 -10
  48. pyedb/grpc/database/_typing.py +0 -0
  49. pyedb/grpc/database/components.py +14 -13
  50. pyedb/grpc/database/control_file.py +27 -40
  51. pyedb/grpc/database/definition/materials.py +1 -1
  52. pyedb/grpc/database/definition/package_def.py +6 -3
  53. pyedb/grpc/database/definition/padstack_def.py +14 -12
  54. pyedb/grpc/database/hfss.py +1 -4
  55. pyedb/grpc/database/hierarchy/component.py +5 -13
  56. pyedb/grpc/database/hierarchy/pingroup.py +16 -3
  57. pyedb/grpc/database/layers/layer.py +1 -2
  58. pyedb/grpc/database/layers/stackup_layer.py +42 -19
  59. pyedb/grpc/database/layout/layout.py +43 -27
  60. pyedb/grpc/database/layout/voltage_regulator.py +6 -1
  61. pyedb/grpc/database/layout_validation.py +5 -2
  62. pyedb/grpc/database/modeler.py +254 -252
  63. pyedb/grpc/database/net/differential_pair.py +9 -2
  64. pyedb/grpc/database/net/extended_net.py +24 -9
  65. pyedb/grpc/database/net/net.py +14 -5
  66. pyedb/grpc/database/net/net_class.py +24 -7
  67. pyedb/grpc/database/nets.py +11 -43
  68. pyedb/grpc/database/padstacks.py +67 -119
  69. pyedb/grpc/database/primitive/bondwire.py +3 -67
  70. pyedb/grpc/database/primitive/circle.py +42 -3
  71. pyedb/grpc/database/primitive/padstack_instance.py +58 -31
  72. pyedb/grpc/database/primitive/path.py +160 -11
  73. pyedb/grpc/database/primitive/polygon.py +73 -7
  74. pyedb/grpc/database/primitive/primitive.py +2 -2
  75. pyedb/grpc/database/primitive/rectangle.py +105 -4
  76. pyedb/grpc/database/simulation_setup/hfss_general_settings.py +0 -2
  77. pyedb/grpc/database/simulation_setup/hfss_settings_options.py +0 -4
  78. pyedb/grpc/database/simulation_setup/hfss_simulation_setup.py +79 -0
  79. pyedb/grpc/database/simulation_setup/siwave_cpa_simulation_setup.py +1 -0
  80. pyedb/grpc/database/simulation_setup/sweep_data.py +1 -3
  81. pyedb/grpc/database/siwave.py +6 -13
  82. pyedb/grpc/database/source_excitations.py +46 -63
  83. pyedb/grpc/database/stackup.py +55 -60
  84. pyedb/grpc/database/terminal/bundle_terminal.py +10 -3
  85. pyedb/grpc/database/terminal/padstack_instance_terminal.py +9 -11
  86. pyedb/grpc/database/terminal/pingroup_terminal.py +8 -1
  87. pyedb/grpc/database/terminal/point_terminal.py +30 -0
  88. pyedb/grpc/database/terminal/terminal.py +35 -10
  89. pyedb/grpc/database/utility/heat_sink.py +0 -1
  90. pyedb/grpc/database/utility/hfss_extent_info.py +2 -2
  91. pyedb/grpc/database/utility/xml_control_file.py +19 -8
  92. pyedb/grpc/edb.py +63 -32
  93. pyedb/grpc/edb_init.py +1 -0
  94. pyedb/ipc2581/ecad/cad_data/layer_feature.py +6 -2
  95. pyedb/ipc2581/ecad/cad_data/step.py +1 -1
  96. pyedb/ipc2581/ipc2581.py +8 -7
  97. pyedb/libraries/common.py +3 -4
  98. pyedb/libraries/rf_libraries/base_functions.py +7 -16
  99. pyedb/libraries/rf_libraries/planar_antennas.py +3 -21
  100. pyedb/misc/aedtlib_personalib_install.py +2 -2
  101. pyedb/misc/downloads.py +19 -3
  102. pyedb/misc/misc.py +5 -2
  103. pyedb/misc/siw_feature_config/emc_rule_checker_settings.py +3 -2
  104. pyedb/misc/siw_feature_config/xtalk_scan/scan_config.py +0 -1
  105. pyedb/misc/utilities.py +0 -1
  106. pyedb/modeler/geometry_operators.py +3 -2
  107. {pyedb-0.56.0.dist-info → pyedb-0.58.0.dist-info}/METADATA +6 -7
  108. {pyedb-0.56.0.dist-info → pyedb-0.58.0.dist-info}/RECORD +110 -108
  109. {pyedb-0.56.0.dist-info → pyedb-0.58.0.dist-info}/WHEEL +0 -0
  110. {pyedb-0.56.0.dist-info → pyedb-0.58.0.dist-info}/licenses/LICENSE +0 -0
pyedb/generic/process.py CHANGED
@@ -1,6 +1,6 @@
1
1
  import os.path
2
2
  from pathlib import Path
3
- import subprocess
3
+ import subprocess # nosec B404
4
4
 
5
5
  from pyedb.generic.general_methods import is_linux
6
6
 
@@ -23,7 +23,63 @@ class SiwaveSolve(object):
23
23
  full_path = Path(self._pedb.ansys_em_path) / executable
24
24
  return str(full_path)
25
25
 
26
+ def __create_exec(self, type):
27
+ base = os.path.splitext(self._pedb.edbpath)[0]
28
+ txt_path = base + ".txt"
29
+ exec_path = base + ".exec"
30
+ with open(txt_path, "w") as file:
31
+ if type:
32
+ if type == "DCIR":
33
+ file.write("ExecDcSim")
34
+ elif type == "SYZ":
35
+ file.write("ExecSyzSim")
36
+ elif type == "CPA":
37
+ file.write("ExecSentinelCpaSim")
38
+ elif type == "TimeCrosstalk":
39
+ file.write("ExecTimeDomainCrosstalkSim")
40
+ elif type == "FreqCrosstalk":
41
+ file.write("ExecCrosstalkSim")
42
+ elif type == "Impedance":
43
+ file.write("ExecZ0Sim")
44
+
45
+ os.rename(txt_path, exec_path)
46
+ return exec_path
47
+
48
+ def solve_siwave(self, edbpath, analysis_type):
49
+ """Solve an SIWave setup. Only non-graphical batch mode is supported.
50
+
51
+ Parameters
52
+ ----------
53
+ analysis_type: str
54
+ Type of SIWave analysis to perform. Available types are "SYZ", "DCIR", "CPA", "TimeCrosstalk",
55
+ "FreqCrosstalk", "Impedance".
56
+ edbpath: str
57
+ Full path to the .aedb folder, siw or siwz file to be solved.
58
+ siwave_ng: str, optinial
59
+ Path to the siwave_ng. Default is the SIWave installation path.
60
+ """
61
+
62
+ command = [
63
+ self.__siwave_ng_exe_path,
64
+ edbpath,
65
+ self.__create_exec(type=analysis_type),
66
+ "-formatOutput",
67
+ "-useSubdir",
68
+ ]
69
+ try:
70
+ subprocess.run(command, check=True)
71
+ except subprocess.CalledProcessError as e:
72
+ raise RuntimeError(f"An error occurred when launching the solver. Please check input paths") from e
73
+
26
74
  def solve(self, num_of_cores=4):
75
+ """Solve using siwave_ng.exe
76
+
77
+ .. warning::
78
+ Do not execute this function with untrusted function argument, environment
79
+ variables or pyedb global settings.
80
+ See the :ref:`security guide<ref_security_consideration>` for details.
81
+
82
+ """
27
83
  exec_file = os.path.splitext(self._pedb.edbpath)[0] + ".exec"
28
84
  if os.path.exists(exec_file):
29
85
  with open(exec_file, "r+") as f:
@@ -39,16 +95,21 @@ class SiwaveSolve(object):
39
95
  f = open(exec_file, "w")
40
96
  f.writelines(content)
41
97
  command = [self.__siwave_ng_exe_path, self._pedb.edbpath, exec_file, "-formatOutput -useSubdir"]
42
- command_ = command if os.name == "posix" else " ".join(command)
43
- # p = subprocess.Popen(command_)
44
- p = subprocess.Popen(command)
45
- p.wait()
98
+ try:
99
+ subprocess.run(command, check=True) # nosec
100
+ except subprocess.CalledProcessError as e: # nosec
101
+ raise RuntimeError("An error occurred while solving") from e
46
102
 
47
103
  def export_3d_cad(
48
104
  self, format_3d="Q3D", output_folder=None, net_list=None, num_cores=4, aedt_file_name=None, hidden=False
49
105
  ): # pragma: no cover
50
106
  """Export edb to Q3D or HFSS
51
107
 
108
+ .. warning::
109
+ Do not execute this function with untrusted function argument, environment
110
+ variables or pyedb global settings.
111
+ See the :ref:`security guide<ref_security_consideration>` for details.
112
+
52
113
  Parameters
53
114
  ----------
54
115
  format_3d : str, default ``Q3D``
@@ -97,10 +158,10 @@ class SiwaveSolve(object):
97
158
  command += ["-RunScriptAndExit", scriptname]
98
159
  print(command)
99
160
  try:
100
- result = subprocess.run(command, check=True, capture_output=True)
161
+ result = subprocess.run(command, check=True, capture_output=True) # nosec
101
162
  print(result.stdout.decode())
102
- except subprocess.CalledProcessError as e:
103
- print(f"Error occurred: {e.stderr.decode()}")
163
+ except subprocess.CalledProcessError as e: # nosec
164
+ raise RuntimeError("An error occurred while exporting 3D CAD") from e
104
165
  return os.path.join(output_folder, aedt_file_name)
105
166
 
106
167
  def export_dc_report(
@@ -119,6 +180,11 @@ class SiwaveSolve(object):
119
180
  ):
120
181
  """Close EDB and solve it with Siwave.
121
182
 
183
+ .. warning::
184
+ Do not execute this function with untrusted function argument, environment
185
+ variables or pyedb global settings.
186
+ See the :ref:`security guide<ref_security_consideration>` for details.
187
+
122
188
  Parameters
123
189
  ----------
124
190
  siwave_project : str
@@ -215,6 +281,8 @@ class SiwaveSolve(object):
215
281
  command.append("-RunScriptAndExit")
216
282
  command.append(scriptname)
217
283
  print(command)
218
- p = subprocess.Popen(command)
219
- p.wait()
284
+ try:
285
+ subprocess.run(command, check=True) # nosec
286
+ except subprocess.CalledProcessError as e: # nosec
287
+ raise RuntimeError("An error occurred while solving with Siwave") from e
220
288
  return output_list
File without changes
@@ -20,9 +20,8 @@
20
20
  # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
21
  # SOFTWARE.
22
22
 
23
- """This module contains the `Components` class.
23
+ """This module contains the `Components` class."""
24
24
 
25
- """
26
25
  import codecs
27
26
  import json
28
27
  import math
@@ -31,8 +30,7 @@ import re
31
30
  from typing import Any, Dict, List, Optional, Tuple, Union
32
31
  import warnings
33
32
 
34
- from ansys.edb.core.definition.die_property import DieOrientation as GrpDieOrientation
35
- from ansys.edb.core.definition.die_property import DieType as GrpcDieType
33
+ from ansys.edb.core.definition.die_property import DieOrientation as GrpDieOrientation, DieType as GrpcDieType
36
34
  from ansys.edb.core.definition.solder_ball_property import (
37
35
  SolderballShape as GrpcSolderballShape,
38
36
  )
@@ -996,8 +994,7 @@ class Components(object):
996
994
  """
997
995
  component_definition = ComponentDef.find(self._db, name)
998
996
  if component_definition.is_null:
999
- from ansys.edb.core.layout.cell import Cell as GrpcCell
1000
- from ansys.edb.core.layout.cell import CellType as GrpcCellType
997
+ from ansys.edb.core.layout.cell import Cell as GrpcCell, CellType as GrpcCellType
1001
998
 
1002
999
  foot_print_cell = GrpcCell.create(self._pedb.active_db, GrpcCellType.FOOTPRINT_CELL, name)
1003
1000
  component_definition = ComponentDef.create(self._db, name, fp=foot_print_cell)
@@ -1013,8 +1010,6 @@ class Components(object):
1013
1010
  if component_definition_pin.is_null:
1014
1011
  self._logger.error(f"Failed to create component definition pin {name}-{pin.name}")
1015
1012
  return None
1016
- else:
1017
- self._logger.warning("Found existing component definition for footprint {}".format(name))
1018
1013
  return component_definition
1019
1014
 
1020
1015
  def create(
@@ -1077,8 +1072,12 @@ class Components(object):
1077
1072
  if not compdef:
1078
1073
  return False
1079
1074
  new_cmp = GrpcComponentGroup.create(self._active_layout, component_name, compdef.name)
1075
+ if new_cmp.is_null:
1076
+ raise ValueError(f"Failed to create component {component_name}.")
1080
1077
  if hasattr(pins[0], "component") and pins[0].component:
1081
- hosting_component_location = pins[0].component.transform
1078
+ hosting_component_location = None
1079
+ if not pins[0].component.is_null:
1080
+ hosting_component_location = pins[0].component.transform
1082
1081
  else:
1083
1082
  hosting_component_location = None
1084
1083
  if not len(pins) == len(compdef.component_pins):
@@ -1470,13 +1469,15 @@ class Components(object):
1470
1469
  sball_shape = GrpcSolderballShape.SOLDERBALL_SPHEROID
1471
1470
 
1472
1471
  cmp_property = cmp.component_property
1473
- if cmp.type == GrpcComponentType.IC:
1472
+ if cmp.component_type == GrpcComponentType.IC:
1474
1473
  ic_die_prop = cmp_property.die_property
1475
1474
  ic_die_prop.die_type = GrpcDieType.FLIPCHIP
1475
+ if not cmp.placement_layer == list(self._pedb.stackup.layers.keys())[0]:
1476
+ chip_orientation = "chip_up"
1476
1477
  if chip_orientation.lower() == "chip_up":
1477
- ic_die_prop.orientation = GrpDieOrientation.CHIP_UP
1478
+ ic_die_prop.die_orientation = GrpDieOrientation.CHIP_UP
1478
1479
  else:
1479
- ic_die_prop.orientation = GrpDieOrientation.CHIP_DOWN
1480
+ ic_die_prop.die_orientation = GrpDieOrientation.CHIP_DOWN
1480
1481
  cmp_property.die_property = ic_die_prop
1481
1482
 
1482
1483
  solder_ball_prop = cmp_property.solder_ball_property
@@ -2228,7 +2229,7 @@ class Components(object):
2228
2229
  Examples
2229
2230
  --------
2230
2231
  >>> from pyedb import Edb
2231
- >>> edb_file = r'C:\my_edb_file.aedb'
2232
+ >>> edb_file = r"C:\my_edb_file.aedb"
2232
2233
  >>> edb = Edb(edb_file)
2233
2234
  >>> for cmp in list(edb.components.instances.keys()):
2234
2235
  >>> edb.components.deactivate_rlc_component(component=cmp, create_circuit_port=False)
@@ -23,10 +23,12 @@
23
23
  import copy
24
24
  import os
25
25
  import re
26
- import subprocess
26
+ import subprocess # nosec B404
27
27
  import sys
28
28
  from typing import Any, Dict, List, Optional, Union
29
29
 
30
+ from defusedxml.ElementTree import parse as defused_parse
31
+
30
32
  from pyedb.generic.general_methods import ET, env_path, env_value, is_linux
31
33
  from pyedb.generic.settings import settings
32
34
  from pyedb.misc.aedtlib_personalib_install import write_pretty_xml
@@ -36,6 +38,11 @@ from pyedb.misc.misc import list_installed_ansysem
36
38
  def convert_technology_file(tech_file, edbversion=None, control_file=None):
37
39
  """Convert a technology file to EDB control file (XML).
38
40
 
41
+ .. warning::
42
+ Do not execute this function with untrusted function argument, environment
43
+ variables or pyedb global settings.
44
+ See the :ref:`security guide<ref_security_consideration>` for details.
45
+
39
46
  Parameters
40
47
  ----------
41
48
  tech_file : str
@@ -58,40 +65,26 @@ def convert_technology_file(tech_file, edbversion=None, control_file=None):
58
65
  -------
59
66
  # Example 1: Converting a technology file to control file
60
67
  >>> converted_file = convert_technology_file(
61
- >>> tech_file="/path/to/tech.t",
62
- >>> edbversion="2025.2",
63
- >>> control_file="/path/to/output.xml"
64
- >>> )
68
+ ... tech_file="/path/to/tech.t", edbversion="2025.2", control_file="/path/to/output.xml"
69
+ ... )
65
70
  >>> if converted_file:
66
71
  >>> print(f"Converted to: {converted_file}")
67
72
 
68
73
  # Example 2: Creating a material
69
74
  >>> from pyedb import ControlFileMaterial
70
- >>> material = ControlFileMaterial(
71
- >>> "Copper",
72
- >>> {"Permittivity": 1.0, "Conductivity": 5.8e7}
73
- >>> )
75
+ >>> material = ControlFileMaterial("Copper", {"Permittivity": 1.0, "Conductivity": 5.8e7})
74
76
 
75
77
  # Example 3: Creating a dielectric layer
76
78
  >>> from pyedb import ControlFileDielectric
77
- >>> dielectric = ControlFileDielectric(
78
- >>> "Core",
79
- >>> {"Thickness": "0.2mm", "Material": "FR4"}
80
- >>> )
79
+ >>> dielectric = ControlFileDielectric("Core", {"Thickness": "0.2mm", "Material": "FR4"})
81
80
 
82
81
  # Example 4: Creating a signal layer
83
82
  >>> from pyedb import ControlFileLayer
84
- >>> signal_layer = ControlFileLayer(
85
- >>> "TopLayer",
86
- >>> {"Type": "signal", "Material": "Copper", "Thickness": "0.035mm"}
87
- >>> )
83
+ >>> signal_layer = ControlFileLayer("TopLayer", {"Type": "signal", "Material": "Copper", "Thickness": "0.035mm"})
88
84
 
89
85
  # Example 5: Creating a via layer
90
86
  >>> from pyedb import ControlFileVia
91
- >>> via_layer = ControlFileVia(
92
- >>> "Via1",
93
- >>> {"StartLayer": "TopLayer", "StopLayer": "BottomLayer"}
94
- >>> )
87
+ >>> via_layer = ControlFileVia("Via1", {"StartLayer": "TopLayer", "StopLayer": "BottomLayer"})
95
88
  >>> via_layer.create_via_group = True
96
89
  >>> via_layer.tolerance = "0.1mm"
97
90
 
@@ -111,11 +104,7 @@ def convert_technology_file(tech_file, edbversion=None, control_file=None):
111
104
 
112
105
  # Example 8: Setting up simulation extents
113
106
  >>> from pyedb import ControlExtent
114
- >>> extent = ControlExtent(
115
- >>> type="Conforming",
116
- >>> diel_hactor=0.3,
117
- >>> airbox_hfactor=0.5
118
- >>> )
107
+ >>> extent = ControlExtent(type="Conforming", diel_hactor=0.3, airbox_hfactor=0.5)
119
108
 
120
109
  # Example 9: Creating circuit ports
121
110
  >>> from pyedb import ControlCircuitPt
@@ -142,17 +131,11 @@ def convert_technology_file(tech_file, edbversion=None, control_file=None):
142
131
 
143
132
  # Example 13: Frequency sweep configuration
144
133
  >>> from pyedb import ControlFileSweep
145
- >>> sweep = ControlFileSweep(
146
- >>> "Sweep1", "1GHz", "10GHz", "0.1GHz",
147
- >>> "Interpolating", "LinearStep", True
148
- >>> )
134
+ >>> sweep = ControlFileSweep("Sweep1", "1GHz", "10GHz", "0.1GHz", "Interpolating", "LinearStep", True)
149
135
 
150
136
  # Example 14: Mesh operation setup
151
137
  >>> from pyedb import ControlFileMeshOp
152
- >>> mesh_op = ControlFileMeshOp(
153
- >>> "FineMesh", "Region1", "MeshOperationSkinDepth",
154
- >>> {"Net1": "TopLayer"}
155
- >>> )
138
+ >>> mesh_op = ControlFileMeshOp("FineMesh", "Region1", "MeshOperationSkinDepth", {"Net1": "TopLayer"})
156
139
  >>> mesh_op.skin_depth = "1um"
157
140
 
158
141
  # Example 15: Simulation setup configuration
@@ -236,10 +219,11 @@ def convert_technology_file(tech_file, edbversion=None, control_file=None):
236
219
  ]
237
220
  commands.append(command)
238
221
  commands.append(["rm", "-r", vlc_file_name + ".aedb"])
239
- my_env = os.environ.copy()
240
222
  for command in commands:
241
- p = subprocess.Popen(command, env=my_env)
242
- p.wait()
223
+ try:
224
+ subprocess.run(command, check=True) # nosec
225
+ except subprocess.CalledProcessError as e: # nosec
226
+ raise RuntimeError("An error occurred while converting a technology file to edb control file") from e
243
227
  if os.path.exists(control_file):
244
228
  settings.logger.info("XML file created.")
245
229
  return control_file
@@ -290,8 +274,11 @@ class ControlProperty:
290
274
  double.text = str(self.value)
291
275
  else:
292
276
  pass
293
- except:
294
- pass
277
+ except Exception as e:
278
+ settings.logger.error(
279
+ f"A(n) {type(e).__name__} error occurred while attempting to create a new sub-element {self.name} "
280
+ f"for element {root}: {str(e)}"
281
+ )
295
282
 
296
283
 
297
284
  class ControlFileMaterial:
@@ -1673,7 +1660,7 @@ class ControlFile:
1673
1660
  bool
1674
1661
  ``True`` if successful, ``False`` otherwise.
1675
1662
  """
1676
- tree = ET.parse(xml_input)
1663
+ tree = defused_parse(xml_input)
1677
1664
  root = tree.getroot()
1678
1665
  for el in root:
1679
1666
  if el.tag == "Stackup":
@@ -34,9 +34,9 @@ from ansys.edb.core.definition.djordjecvic_sarkar_model import (
34
34
  DjordjecvicSarkarModel as GrpcDjordjecvicSarkarModel,
35
35
  )
36
36
  from ansys.edb.core.definition.material_def import (
37
+ MaterialDef as GrpcMaterialDef,
37
38
  MaterialProperty as GrpcMaterialProperty,
38
39
  )
39
- from ansys.edb.core.definition.material_def import MaterialDef as GrpcMaterialDef
40
40
  from ansys.edb.core.definition.multipole_debye_model import (
41
41
  MultipoleDebyeModel as GrpcMultipoleDebyeModel,
42
42
  )
@@ -193,8 +193,11 @@ class PackageDef(GrpcPackageDef):
193
193
  """
194
194
  try:
195
195
  return HeatSink(self._pedb, super().heat_sink)
196
- except:
197
- pass
196
+ except Exception as e:
197
+ settings.logger.error(
198
+ f"A(n) {type(e).__name__} error occurred while attempting to access 'heatsink' "
199
+ f"property for object {self}: {str(e)}"
200
+ )
198
201
 
199
202
  @property
200
203
  @deprecated_property
@@ -222,9 +225,9 @@ class PackageDef(GrpcPackageDef):
222
225
  Fin thickness.
223
226
  """
224
227
  from ansys.edb.core.utility.heat_sink import (
228
+ HeatSink as GrpcHeatSink,
225
229
  HeatSinkFinOrientation as GrpcHeatSinkFinOrientation,
226
230
  )
227
- from ansys.edb.core.utility.heat_sink import HeatSink as GrpcHeatSink
228
231
 
229
232
  if fin_orientation == "x_oriented":
230
233
  fin_orientation = GrpcHeatSinkFinOrientation.X_ORIENTED
@@ -26,18 +26,16 @@ import warnings
26
26
  from ansys.edb.core.definition.padstack_def import PadstackDef as GrpcPadstackDef
27
27
  from ansys.edb.core.definition.padstack_def_data import (
28
28
  PadGeometryType as GrpcPadGeometryType,
29
- )
30
- from ansys.edb.core.definition.padstack_def_data import (
31
29
  PadstackHoleRange as GrpcPadstackHoleRange,
30
+ PadType as GrpcPadType,
32
31
  )
33
- from ansys.edb.core.definition.padstack_def_data import PadType as GrpcPadType
34
32
  import ansys.edb.core.geometry.polygon_data
35
33
  from ansys.edb.core.geometry.polygon_data import PolygonData as GrpcPolygonData
36
- from ansys.edb.core.hierarchy.structure3d import MeshClosure as GrpcMeshClosure
37
- from ansys.edb.core.hierarchy.structure3d import Structure3D as GrpcStructure3D
34
+ from ansys.edb.core.hierarchy.structure3d import MeshClosure as GrpcMeshClosure, Structure3D as GrpcStructure3D
38
35
  from ansys.edb.core.primitive.circle import Circle as GrpcCircle
39
36
 
40
37
  from pyedb.generic.general_methods import generate_unique_name
38
+ from pyedb.grpc.database.primitive.circle import Circle
41
39
  from pyedb.grpc.database.utility.value import Value
42
40
 
43
41
 
@@ -127,7 +125,7 @@ class PadProperties:
127
125
  self._update_pad_parameters_parameters(geom_type=GrpcPadGeometryType.PADGEOMTYPE_POLYGON)
128
126
  else:
129
127
  raise ValueError(
130
- f"Unsupported pad shape: {value}. Supported shapes are 'circle', " f"'rectangle', and 'polygon'."
128
+ f"Unsupported pad shape: {value}. Supported shapes are 'circle', 'rectangle', and 'polygon'."
131
129
  )
132
130
 
133
131
  @property
@@ -297,7 +295,11 @@ class PadstackDef(GrpcPadstackDef):
297
295
  List[:class:`PadstackInstance <pyedb.grpc.database.primitive.padstack_instance.PadstackInstance>`]
298
296
  List of PadstackInstance objects.
299
297
  """
300
- return [i for i in list(self._pedb.padstacks.instances.values()) if i.padstack_def.name == self.name]
298
+ return [
299
+ i
300
+ for i in list(self._pedb.padstacks.instances.values())
301
+ if not i.is_null and i.padstack_def.name == self.name
302
+ ]
301
303
 
302
304
  @property
303
305
  def layers(self) -> list[str]:
@@ -720,7 +722,7 @@ class PadstackDef(GrpcPadstackDef):
720
722
  net_name=via.net_name,
721
723
  )
722
724
  else:
723
- GrpcCircle.create(
725
+ Circle(self._pedb).create(
724
726
  layout,
725
727
  self.start_layer,
726
728
  via.net,
@@ -735,7 +737,7 @@ class PadstackDef(GrpcPadstackDef):
735
737
  net_name=via.net_name,
736
738
  )
737
739
  else:
738
- GrpcCircle.create(
740
+ Circle(self._pedb).create(
739
741
  layout,
740
742
  self.stop_layer,
741
743
  via.net,
@@ -748,7 +750,7 @@ class PadstackDef(GrpcPadstackDef):
748
750
  if layer_name == via.start_layer or started:
749
751
  start = layer_name
750
752
  stop = layer_names[layer_names.index(layer_name) + 1]
751
- cloned_circle = GrpcCircle.create(
753
+ cloned_circle = Circle(self._pedb).create(
752
754
  layout,
753
755
  start,
754
756
  via.net,
@@ -756,7 +758,7 @@ class PadstackDef(GrpcPadstackDef):
756
758
  Value(pos[1]),
757
759
  Value(rad1),
758
760
  )
759
- cloned_circle2 = GrpcCircle.create(
761
+ cloned_circle2 = Circle(self._pedb).create(
760
762
  layout,
761
763
  stop,
762
764
  via.net,
@@ -771,7 +773,7 @@ class PadstackDef(GrpcPadstackDef):
771
773
  s3d.add_member(cloned_circle2)
772
774
  if not self.data.material.value:
773
775
  self._pedb.logger.warning(
774
- f"Padstack definution {self.name} has no material defined." f"Defaulting to copper"
776
+ f"Padstack definution {self.name} has no material defined.Defaulting to copper"
775
777
  )
776
778
  self.data.material = "copper"
777
779
  s3d.set_material(self.data.material.value)
@@ -23,6 +23,7 @@
23
23
  """
24
24
  This module contains the ``EdbHfss`` class.
25
25
  """
26
+
26
27
  import math
27
28
  import warnings
28
29
 
@@ -1259,11 +1260,7 @@ class Hfss(object):
1259
1260
  )
1260
1261
  from ansys.edb.core.simulation_setup.simulation_setup import (
1261
1262
  Distribution as GrpcDistribution,
1262
- )
1263
- from ansys.edb.core.simulation_setup.simulation_setup import (
1264
1263
  FrequencyData as GrpcFrequencyData,
1265
- )
1266
- from ansys.edb.core.simulation_setup.simulation_setup import (
1267
1264
  SweepData as GrpcSweepData,
1268
1265
  )
1269
1266
 
@@ -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 (
@@ -49,7 +48,9 @@ from ansys.edb.core.terminal.padstack_instance_terminal import (
49
48
  PadstackInstanceTerminal as GrpcPadstackInstanceTerminal,
50
49
  )
51
50
  from ansys.edb.core.utility.rlc import Rlc as GrpcRlc
51
+ import numpy as np
52
52
 
53
+ from pyedb.generic.general_methods import get_filename_without_extension
53
54
  from pyedb.grpc.database.hierarchy.pin_pair_model import PinPairModel
54
55
  from pyedb.grpc.database.hierarchy.s_parameter_model import SparamModel
55
56
  from pyedb.grpc.database.hierarchy.spice_model import SpiceModel
@@ -60,15 +61,6 @@ from pyedb.grpc.database.terminal.padstack_instance_terminal import (
60
61
  )
61
62
  from pyedb.grpc.database.utility.value import Value
62
63
 
63
- try:
64
- import numpy as np
65
- except ImportError:
66
- warnings.warn(
67
- "The NumPy module is required to run some functionalities of EDB.\n"
68
- "Install with \n\npip install numpy\n\nRequires CPython."
69
- )
70
- from pyedb.generic.general_methods import get_filename_without_extension
71
-
72
64
 
73
65
  class Component(GrpcComponentGroup):
74
66
  """Manages EDB functionalities for components.
@@ -1102,7 +1094,7 @@ class Component(GrpcComponentGroup):
1102
1094
  return False
1103
1095
  if not reference_net:
1104
1096
  self._pedb.logger.warning(
1105
- f"No reference net provided for S parameter file {file_path}, net `GND` is " f"assigned by default"
1097
+ f"No reference net provided for S parameter file {file_path}, net `GND` is assigned by default"
1106
1098
  )
1107
1099
  reference_net = "GND"
1108
1100
  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):