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/grpc/edb.py CHANGED
@@ -60,7 +60,7 @@ from itertools import combinations
60
60
  import os
61
61
  import re
62
62
  import shutil
63
- import subprocess
63
+ import subprocess # nosec B404
64
64
  import sys
65
65
  import tempfile
66
66
  import time
@@ -658,8 +658,7 @@ class Edb(EdbInit):
658
658
  bool
659
659
  True if successful, False otherwise.
660
660
  """
661
- from ansys.edb.core.layout.cell import Cell as GrpcCell
662
- from ansys.edb.core.layout.cell import CellType as GrpcCellType
661
+ from ansys.edb.core.layout.cell import Cell as GrpcCell, CellType as GrpcCellType
663
662
 
664
663
  self.standalone = self.standalone
665
664
  n_try = 10
@@ -762,6 +761,11 @@ class Edb(EdbInit):
762
761
 
763
762
  This function supports all AEDT formats, including DXF, GDS, SML (IPC2581), BRD, MCM, SIP, ZIP and TGZ.
764
763
 
764
+ .. warning::
765
+ Do not execute this function with untrusted function argument, environment
766
+ variables or pyedb global settings.
767
+ See the :ref:`security guide<ref_security_consideration>` for details.
768
+
765
769
  Parameters
766
770
  ----------
767
771
  input_file : str
@@ -804,16 +808,16 @@ class Edb(EdbInit):
804
808
  self._nets = None
805
809
  aedb_name = os.path.splitext(os.path.basename(input_file))[0] + ".aedb"
806
810
  if anstranslator_full_path and os.path.exists(anstranslator_full_path):
807
- command = anstranslator_full_path
811
+ executable_path = anstranslator_full_path
808
812
  else:
809
- command = os.path.join(self.base_path, "anstranslator")
813
+ executable_path = os.path.join(self.base_path, "anstranslator")
810
814
  if is_windows:
811
- command += ".exe"
815
+ executable_path += ".exe"
812
816
 
813
817
  if not working_dir:
814
818
  working_dir = os.path.dirname(input_file)
815
819
  cmd_translator = [
816
- command,
820
+ executable_path,
817
821
  input_file,
818
822
  os.path.join(working_dir, aedb_name),
819
823
  "-l={}".format(os.path.join(working_dir, "Translator.log")),
@@ -831,7 +835,10 @@ class Edb(EdbInit):
831
835
  cmd_translator.append('-t="{}"'.format(tech_file))
832
836
  if layer_filter:
833
837
  cmd_translator.append('-f="{}"'.format(layer_filter))
834
- subprocess.run(cmd_translator)
838
+ try:
839
+ subprocess.run(cmd_translator, check=True) # nosec
840
+ except subprocess.CalledProcessError as e: # nosec
841
+ raise RuntimeError("An error occurred while translating board file to ``edb.def`` file") from e
835
842
  if not os.path.exists(os.path.join(working_dir, aedb_name)):
836
843
  self.logger.error("Translator failed to translate.")
837
844
  return False
@@ -1191,7 +1198,7 @@ class Edb(EdbInit):
1191
1198
  continue
1192
1199
  except:
1193
1200
  self.logger.warning(
1194
- f"Failed to find connected objects on layout_obj " f"{layout_object_instance.layout_obj.id}, skipping."
1201
+ f"Failed to find connected objects on layout_obj {layout_object_instance.layout_obj.id}, skipping."
1195
1202
  )
1196
1203
  pass
1197
1204
  return temp
@@ -1341,6 +1348,11 @@ class Edb(EdbInit):
1341
1348
  ):
1342
1349
  """Import GDS file.
1343
1350
 
1351
+ .. warning::
1352
+ Do not execute this function with untrusted function argument, environment
1353
+ variables or pyedb global settings.
1354
+ See the :ref:`security guide<ref_security_consideration>` for details.
1355
+
1344
1356
  Parameters
1345
1357
  ----------
1346
1358
  inputGDS : str
@@ -1399,14 +1411,17 @@ class Edb(EdbInit):
1399
1411
  command = [
1400
1412
  anstranslator_full_path,
1401
1413
  inputGDS,
1402
- f'-o="{control_file_temp}"' f'-t="{tech_file}"',
1414
+ f'-o="{control_file_temp}"-t="{tech_file}"',
1403
1415
  f'-g="{map_file}"',
1404
1416
  f'-f="{layer_filter}"',
1405
1417
  ]
1406
1418
 
1407
- result = subprocess.run(command, capture_output=True, text=True, shell=True)
1408
- print(result.stdout)
1409
- print(command)
1419
+ try:
1420
+ result = subprocess.run(command, capture_output=True, text=True, check=True) # nosec
1421
+ print(result.stdout)
1422
+ print(command)
1423
+ except subprocess.CalledProcessError as e: # nosec
1424
+ raise RuntimeError("An error occurred while converting file") from e
1410
1425
  temp_inputGDS = inputGDS.split(".gds")[0]
1411
1426
  self.edbpath = temp_inputGDS + ".aedb"
1412
1427
  return self.open()
@@ -1568,8 +1583,11 @@ class Edb(EdbInit):
1568
1583
  voids_poly.append(void_polydata)
1569
1584
  if voids_poly:
1570
1585
  obj_data = obj_data[0].subtract(list(obj_data), voids_poly)
1571
- except:
1572
- pass
1586
+ except Exception as e:
1587
+ self.logger.error(
1588
+ f"A(n) {type(e).__name__} error occurred in method _create_conformal of "
1589
+ f"class Edb at iteration {k} for data {i}: {str(e)}"
1590
+ )
1573
1591
  finally:
1574
1592
  unite_polys.extend(list(obj_data))
1575
1593
  _poly_unite = GrpcPolygonData.unite(unite_polys)
@@ -1734,7 +1752,7 @@ class Edb(EdbInit):
1734
1752
  >>> # Create a basic cutout:
1735
1753
  >>> edb.cutout(signal_list=["Net1"], reference_list=["GND"])
1736
1754
  >>> # Create cutout with custom polygon:
1737
- >>> custom_poly = [[0,0], [10e-3,0], [10e-3,10e-3], [0,10e-3]]
1755
+ >>> custom_poly = [[0, 0], [10e-3, 0], [10e-3, 10e-3], [0, 10e-3]]
1738
1756
  >>> edb.cutout(custom_extent=custom_poly)
1739
1757
  """
1740
1758
  if expansion_factor > 0:
@@ -1940,8 +1958,8 @@ class Edb(EdbInit):
1940
1958
  if os.path.exists(source) and not os.path.exists(target):
1941
1959
  try:
1942
1960
  shutil.copy(source, target)
1943
- except:
1944
- pass
1961
+ except Exception as e:
1962
+ self.logger.error(f"Failed to copy {source} to {target} - {type(e).__name__}: {str(e)}")
1945
1963
  elif open_cutout_at_end:
1946
1964
  self._active_cell = _cutout
1947
1965
  self._init_objects()
@@ -2419,8 +2437,8 @@ class Edb(EdbInit):
2419
2437
  try:
2420
2438
  shutil.copy(source, target)
2421
2439
  self.logger.warning("aedb def file manually created.")
2422
- except:
2423
- pass
2440
+ except Exception as e:
2441
+ self.logger.error(f"Failed to copy {source} to {target} - {type(e).__name__}: {str(e)}")
2424
2442
  return [[Value(pt.x), Value(pt.y)] for pt in polygon_data.without_arcs().points]
2425
2443
 
2426
2444
  @staticmethod
@@ -2599,8 +2617,10 @@ class Edb(EdbInit):
2599
2617
  process = SiwaveSolve(self)
2600
2618
  try:
2601
2619
  self.close()
2602
- except:
2603
- pass
2620
+ except Exception as e:
2621
+ self.logger.warning(
2622
+ f"A(n) {type(e).__name__} error occurred while attempting to close the database {self}: {str(e)}"
2623
+ )
2604
2624
  process.solve()
2605
2625
  return self.edbpath[:-5] + ".siw"
2606
2626
 
@@ -2650,8 +2670,10 @@ class Edb(EdbInit):
2650
2670
  process = SiwaveSolve(self)
2651
2671
  try:
2652
2672
  self.close()
2653
- except:
2654
- pass
2673
+ except Exception as e:
2674
+ self.logger.warning(
2675
+ f"A(n) {type(e).__name__} error occurred while attempting to close the database {self}: {str(e)}"
2676
+ )
2655
2677
  return process.export_dc_report(
2656
2678
  siwave_project,
2657
2679
  solution_name,
@@ -3009,7 +3031,7 @@ class Edb(EdbInit):
3009
3031
  Use :func:`pyedb.grpc.core.hfss.add_setup` instead.
3010
3032
  """
3011
3033
  warnings.warn(
3012
- "`create_hfss_setup` is deprecated and is now located here " "`pyedb.grpc.core.hfss.add_setup` instead.",
3034
+ "`create_hfss_setup` is deprecated and is now located here `pyedb.grpc.core.hfss.add_setup` instead.",
3013
3035
  DeprecationWarning,
3014
3036
  )
3015
3037
  return self._hfss.add_setup(
@@ -3757,8 +3779,7 @@ class Edb(EdbInit):
3757
3779
  ]
3758
3780
  if not polys:
3759
3781
  self.logger.error(
3760
- f"No polygon found with voids on layer {reference_layer} during model creation for "
3761
- f"arbitrary wave ports"
3782
+ f"No polygon found with voids on layer {reference_layer} during model creation for arbitrary wave ports"
3762
3783
  )
3763
3784
  return False
3764
3785
  void_padstacks = []
@@ -3771,7 +3792,7 @@ class Edb(EdbInit):
3771
3792
 
3772
3793
  if not void_padstacks:
3773
3794
  self.logger.error(
3774
- "No padstack instances found inside evaluated voids during model creation for arbitrary" "waveports"
3795
+ "No padstack instances found inside evaluated voids during model creation for arbitrary waveports"
3775
3796
  )
3776
3797
  return False
3777
3798
  cloned_edb = Edb(edbpath=output_edb, edbversion=self.edbversion, restart_rpc_server=True)
@@ -3903,6 +3924,11 @@ class Edb(EdbInit):
3903
3924
  def compare(self, input_file, results=""):
3904
3925
  """Compares current open database with another one.
3905
3926
 
3927
+ .. warning::
3928
+ Do not execute this function with untrusted function argument, environment
3929
+ variables or pyedb global settings.
3930
+ See the :ref:`security guide<ref_security_consideration>` for details.
3931
+
3906
3932
  Parameters
3907
3933
  ----------
3908
3934
  input_file : str
@@ -3919,13 +3945,18 @@ class Edb(EdbInit):
3919
3945
  if not results:
3920
3946
  results = self.edbpath[:-5] + "_compare_results"
3921
3947
  os.mkdir(results)
3922
- command = os.path.join(self.base_path, "EDBDiff.exe")
3948
+ executable_path = os.path.join(self.base_path, "EDBDiff.exe")
3923
3949
  if is_linux:
3924
3950
  mono_path = os.path.join(self.base_path, "common/mono/Linux64/bin/mono")
3925
- cmd_input = [mono_path, command, input_file, self.edbpath, results]
3951
+ command = [mono_path, executable_path, input_file, self.edbpath, results]
3926
3952
  else:
3927
- cmd_input = [command, input_file, self.edbpath, results]
3928
- subprocess.run(cmd_input)
3953
+ command = [executable_path, input_file, self.edbpath, results]
3954
+ try:
3955
+ subprocess.run(command, check=True) # nosec
3956
+ except subprocess.CalledProcessError as e: # nosec
3957
+ raise RuntimeError(
3958
+ "EDBDiff.exe execution failed. Please check if the executable is present in the base path."
3959
+ )
3929
3960
 
3930
3961
  if not os.path.exists(os.path.join(results, "EDBDiff.csv")):
3931
3962
  self.logger.error("Comparison execution failed")
pyedb/grpc/edb_init.py CHANGED
@@ -22,6 +22,7 @@
22
22
 
23
23
 
24
24
  """Database."""
25
+
25
26
  import atexit
26
27
  import os
27
28
  import signal
@@ -23,6 +23,7 @@
23
23
  import math
24
24
 
25
25
  from pyedb.generic.general_methods import ET
26
+ from pyedb.generic.settings import settings
26
27
  from pyedb.ipc2581.ecad.cad_data.feature import Feature, FeatureType
27
28
 
28
29
 
@@ -99,8 +100,11 @@ class LayerFeature(object):
99
100
  )
100
101
  )
101
102
  self.features.append(feature)
102
- except:
103
- pass
103
+ except Exception as e:
104
+ settings.logger.warning(
105
+ f"A(n) {type(e).__name__} error occurred while attempting to append IPC2581 "
106
+ f"feature {feature} to features of object {self}: {str(e)}"
107
+ )
104
108
 
105
109
  def add_drill_feature(self, via, diameter=0.0): # pragma no cover
106
110
  feature = Feature(self._ipc, self._pedb)
@@ -262,7 +262,7 @@ class Step(object):
262
262
  start_layer, stop_layer = padstack_instance.get_layer_range()
263
263
  for layer_name in self.layer_ranges(start_layer, stop_layer):
264
264
  if layer_name not in layers:
265
- layer_feature = LayerFeature(self._ipc)
265
+ layer_feature = LayerFeature(self._ipc, self._pedb)
266
266
  layer_feature.layer_name = layer_name
267
267
  # layer_feature.color = self._ipc._pedb.stackup[layer_name].color
268
268
  layer_feature.color = layer_colors[layer_name]
pyedb/ipc2581/ipc2581.py CHANGED
@@ -89,9 +89,9 @@ class Ipc2581(object):
89
89
  self.from_meter_to_units(pad.parameters_values[0], self.units)
90
90
  )
91
91
  if not primitive_ref in self.content.standard_geometries_dict.standard_circ_dict:
92
- self.content.standard_geometries_dict.standard_circ_dict[
93
- primitive_ref
94
- ] = self.from_meter_to_units(pad.parameters_values[0], self.units)
92
+ self.content.standard_geometries_dict.standard_circ_dict[primitive_ref] = (
93
+ self.from_meter_to_units(pad.parameters_values[0], self.units)
94
+ )
95
95
  elif pad.geometry_type == 2:
96
96
  primitive_ref = "RECT_{}_{}".format(
97
97
  self.from_meter_to_units(pad.parameters_values[0], self.units),
@@ -135,9 +135,9 @@ class Ipc2581(object):
135
135
  self.from_meter_to_units(antipad.parameters_values[0], self.units)
136
136
  )
137
137
  if not primitive_ref in self.content.standard_geometries_dict.standard_circ_dict:
138
- self.content.standard_geometries_dict.standard_circ_dict[
139
- primitive_ref
140
- ] = self.from_meter_to_units(antipad.parameters_values[0], self.units)
138
+ self.content.standard_geometries_dict.standard_circ_dict[primitive_ref] = (
139
+ self.from_meter_to_units(antipad.parameters_values[0], self.units)
140
+ )
141
141
  elif antipad.geometry_type == 2:
142
142
  primitive_ref = "RECT_{}_{}".format(
143
143
  self.from_meter_to_units(antipad.parameters_values[0], self.units),
@@ -336,7 +336,8 @@ class Ipc2581(object):
336
336
  padstack_defs = {i: k for i, k in self._pedb.padstacks.definitions.items()}
337
337
  polys = {i: j for i, j in self._pedb.modeler.primitives_by_layer.items()}
338
338
  for layer_name, layer in layers.items():
339
- self.ecad.cad_data.cad_data_step.add_layer_feature(layer, polys[layer_name])
339
+ if layer_name in polys:
340
+ self.ecad.cad_data.cad_data_step.add_layer_feature(layer, polys[layer_name])
340
341
  self.ecad.cad_data.cad_data_step.add_padstack_instances(padstack_instances, padstack_defs)
341
342
 
342
343
  def add_drills(self):
pyedb/libraries/common.py CHANGED
@@ -45,8 +45,7 @@ class Substrate:
45
45
 
46
46
  Examples
47
47
  --------
48
- >>> sub = Substrate(h=1.6e-3, er=4.4, tan_d=0.02,
49
- ... name="FR4", size=(10e-3, 15e-3))
48
+ >>> sub = Substrate(h=1.6e-3, er=4.4, tan_d=0.02, name="FR4", size=(10e-3, 15e-3))
50
49
  >>> sub.h
51
50
  0.0016
52
51
  """
@@ -84,7 +83,7 @@ class Material:
84
83
  >>> m = Material(edb, "MyMaterial")
85
84
  >>> m.name
86
85
  'MyMaterial'
87
- >>> edb.materials["MyMaterial"] # now exists in the database
86
+ >>> edb.materials["MyMaterial"] # now exists in the database
88
87
  <Material object at ...>
89
88
  """
90
89
 
@@ -125,7 +124,7 @@ class Conductor(Material):
125
124
  >>> cu = Conductor(edb, "Copper", conductivity=5.8e7)
126
125
  >>> cu.conductivity
127
126
  58000000.0
128
- >>> cu.conductivity = 3.5e7 # update on-the-fly
127
+ >>> cu.conductivity = 3.5e7 # update on-the-fly
129
128
  >>> edb.materials["Copper"].conductivity
130
129
  35000000.0
131
130
  """
@@ -50,8 +50,7 @@ class HatchGround:
50
50
 
51
51
  Examples
52
52
  --------
53
- >>> hatch = HatchGround(pitch=0.5e-3, width=0.2e-3,
54
- ... fill_target=70, board_size=5e-3)
53
+ >>> hatch = HatchGround(pitch=0.5e-3, width=0.2e-3, fill_target=70, board_size=5e-3)
55
54
  >>> edb = Edb("demo.aedb")
56
55
  >>> hatch._edb = edb
57
56
  >>> hatch.create()
@@ -164,8 +163,7 @@ class Meander:
164
163
 
165
164
  Examples
166
165
  --------
167
- >>> m = Meander(pitch=0.2e-3, trace_width=0.15e-3,
168
- ... amplitude=2e-3, num_turns=4)
166
+ >>> m = Meander(pitch=0.2e-3, trace_width=0.15e-3, amplitude=2e-3, num_turns=4)
169
167
  >>> edb = Edb("meander.aedb")
170
168
  >>> m._pedb = edb
171
169
  >>> m.create()
@@ -293,7 +291,7 @@ class MIMCapacitor:
293
291
  >>> edb = Edb("mim.aedb")
294
292
  >>> cap._pedb = edb
295
293
  >>> cap.create()
296
- >>> f"{cap.capacitance_f*1e12:.2f} pF"
294
+ >>> f"{cap.capacitance_f * 1e12:.2f} pF"
297
295
  '1.45 pF'
298
296
  """
299
297
 
@@ -383,8 +381,7 @@ class SpiralInductor:
383
381
 
384
382
  Examples
385
383
  --------
386
- >>> sp = SpiralInductor(turns=3.5, trace_width=25e-6,
387
- ... inner_diameter=80e-6)
384
+ >>> sp = SpiralInductor(turns=3.5, trace_width=25e-6, inner_diameter=80e-6)
388
385
  >>> edb = Edb("spiral.aedb")
389
386
  >>> sp._pedb = edb
390
387
  >>> sp.create()
@@ -769,7 +766,7 @@ class RatRace:
769
766
  >>> edb = Edb("ratrace.aedb")
770
767
  >>> rr._pedb = edb
771
768
  >>> rr.create()
772
- >>> f"{rr.circumference*1e3:.2f} mm"
769
+ >>> f"{rr.circumference * 1e3:.2f} mm"
773
770
  '45.00 mm'
774
771
  """
775
772
 
@@ -958,9 +955,7 @@ class InterdigitalCapacitor:
958
955
 
959
956
  Examples
960
957
  --------
961
- >>> idc = InterdigitalCapacitor(fingers=10,
962
- ... finger_length="0.5mm",
963
- ... gap="0.03mm")
958
+ >>> idc = InterdigitalCapacitor(fingers=10, finger_length="0.5mm", gap="0.03mm")
964
959
  >>> edb = Edb("idc.aedb")
965
960
  >>> idc._pedb = edb
966
961
  >>> idc.create()
@@ -1104,11 +1099,7 @@ class DifferentialTLine:
1104
1099
 
1105
1100
  Examples
1106
1101
  --------
1107
- >>> diff = DifferentialTLine(Edb("diff.aedb"),
1108
- ... length=5e-3,
1109
- ... width=0.15e-3,
1110
- ... spacing=0.1e-3,
1111
- ... angle=math.pi/4)
1102
+ >>> diff = DifferentialTLine(Edb("diff.aedb"), length=5e-3, width=0.15e-3, spacing=0.1e-3, angle=math.pi / 4)
1112
1103
  >>> traces = diff.create()
1113
1104
  >>> f"{diff.diff_impedance:.1f} Ω"
1114
1105
  '95.6 Ω'
@@ -66,13 +66,7 @@ class RectangularPatch:
66
66
  Build a 5.8 GHz patch on a 0.787 mm Rogers RO4350B substrate:
67
67
 
68
68
  >>> edb = pyedb.Edb()
69
- >>> patch = RectangularPatch(
70
- ... edb_cell=edb,
71
- ... freq="5.8GHz",
72
- ... inset="4.2mm",
73
- ... layer="TOP",
74
- ... bottom_layer="GND"
75
- ... )
69
+ >>> patch = RectangularPatch(edb_cell=edb, freq="5.8GHz", inset="4.2mm", layer="TOP", bottom_layer="GND")
76
70
  >>> patch.substrate.er = 3.66
77
71
  >>> patch.substrate.tand = 0.0037
78
72
  >>> patch.substrate.h = 0.000787
@@ -248,13 +242,7 @@ class CircularPatch:
248
242
  Build a 5.8 GHz circular patch on a 0.787 mm Rogers RO4350B substrate:
249
243
 
250
244
  >>> edb = pyedb.Edb()
251
- >>> patch = CircularPatch(
252
- ... edb_cell=edb,
253
- ... freq="5.8GHz",
254
- ... probe_offset="6.4mm",
255
- ... layer="TOP",
256
- ... bottom_layer="GND"
257
- ... )
245
+ >>> patch = CircularPatch(edb_cell=edb, freq="5.8GHz", probe_offset="6.4mm", layer="TOP", bottom_layer="GND")
258
246
  >>> patch.substrate.er = 3.66
259
247
  >>> patch.substrate.tand = 0.0037
260
248
  >>> patch.substrate.h = 0.000787
@@ -425,13 +413,7 @@ class TriangularPatch:
425
413
  Build a 5.8 GHz triangular patch on a 0.787 mm Rogers RO4350B substrate:
426
414
 
427
415
  >>> edb = pyedb.Edb()
428
- >>> patch = TriangularPatch(
429
- ... edb_cell=edb,
430
- ... freq="5.8GHz",
431
- ... probe_offset="5.6mm",
432
- ... layer="TOP",
433
- ... bottom_layer="GND"
434
- ... )
416
+ >>> patch = TriangularPatch(edb_cell=edb, freq="5.8GHz", probe_offset="5.6mm", layer="TOP", bottom_layer="GND")
435
417
  >>> patch.substrate.er = 3.66
436
418
  >>> patch.substrate.tand = 0.0037
437
419
  >>> patch.substrate.h = 0.000787
@@ -20,8 +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
- from xml.dom.minidom import parseString
24
- import xml.etree.ElementTree as ET
23
+ import defusedxml.ElementTree as ET
24
+ from defusedxml.minidom import parseString
25
25
 
26
26
 
27
27
  def write_pretty_xml(root, file_path):
pyedb/misc/downloads.py CHANGED
@@ -21,8 +21,10 @@
21
21
  # SOFTWARE.
22
22
 
23
23
  """Download example datasets from https://github.com/pyansys/example-data"""
24
+
24
25
  import os
25
26
  import shutil
27
+ import subprocess # nosec B404
26
28
  import tempfile
27
29
  import urllib.request
28
30
  import zipfile
@@ -47,7 +49,18 @@ def _get_file_url(directory, filename=None):
47
49
 
48
50
 
49
51
  def _retrieve_file(url, filename, directory, destination=None, local_paths=[]): # pragma: no cover
50
- """Download a file from a url"""
52
+ """Download a file from a url
53
+
54
+ .. warning::
55
+ Do not execute this function with untrusted function argument, environment
56
+ variables or pyedb global settings.
57
+ See the :ref:`security guide<ref_security_consideration>` for details.
58
+
59
+ """
60
+ # Check that provided url is pointing to pyaedt-example repo
61
+ if not url.startswith(EXAMPLE_REPO):
62
+ raise ValueError(f"Attempting to download file(s) from url {url} not pointing the to example-data repo.")
63
+
51
64
  # First check if file has already been downloaded
52
65
  if not destination:
53
66
  destination = EXAMPLES_PATH
@@ -63,8 +76,11 @@ def _retrieve_file(url, filename, directory, destination=None, local_paths=[]):
63
76
  os.makedirs(destination_dir)
64
77
  # Perform download
65
78
  if is_linux:
66
- command = "wget {} -O {}".format(url, local_path)
67
- os.system(command)
79
+ command = ["wget", url, "-O", local_path]
80
+ try:
81
+ subprocess.run(command, check=True) # nosec
82
+ except subprocess.CalledProcessError as e: # nosec
83
+ raise RuntimeError("An error occurred while downloading wget") from e
68
84
  else:
69
85
  _, resp = urlretrieve(url, local_path)
70
86
  local_paths.append(local_path)
pyedb/misc/misc.py CHANGED
@@ -21,9 +21,12 @@
21
21
  # SOFTWARE.
22
22
 
23
23
  """Miscellaneous Methods for PyEDB."""
24
+
24
25
  import os
25
26
  import warnings
26
27
 
28
+ from pyedb.generic.settings import settings
29
+
27
30
 
28
31
  def list_installed_ansysem():
29
32
  """Return a list of installed AEDT versions on ``ANSYSEM_ROOT``."""
@@ -68,8 +71,8 @@ def installed_versions():
68
71
  else:
69
72
  v_key = "20{0}.{1}".format(version, release)
70
73
  return_dict[v_key] = os.environ[version_env_var]
71
- except: # pragma: no cover
72
- pass
74
+ except Exception: # pragma: no cover
75
+ settings.logger.debug(f"Failed to parse version and release from {current_version_id}")
73
76
  return return_dict
74
77
 
75
78
 
@@ -23,6 +23,7 @@
23
23
  from copy import deepcopy as copy
24
24
  import json
25
25
 
26
+ from defusedxml.ElementTree import parse as defused_parse
26
27
  import numpy as np
27
28
 
28
29
  from pyedb.generic.general_methods import ET
@@ -66,7 +67,7 @@ class EMCRuleCheckerSettings:
66
67
  tree = ET.ElementTree(root)
67
68
  try:
68
69
  ET.indent(tree, space="\t", level=0)
69
- except: # pragma no cover
70
+ except AttributeError: # pragma no cover
70
71
  pass
71
72
  return tree
72
73
 
@@ -78,7 +79,7 @@ class EMCRuleCheckerSettings:
78
79
  fpath: str
79
80
  Path to file.
80
81
  """
81
- tree = ET.parse(fpath)
82
+ tree = defused_parse(fpath)
82
83
  root = tree.getroot()
83
84
 
84
85
  self.tag_library = TagLibrary(root.find("TagLibrary"))
@@ -22,7 +22,6 @@
22
22
 
23
23
  from enum import Enum
24
24
  import os
25
- import xml.etree as ET
26
25
 
27
26
  from pyedb.generic.general_methods import ET
28
27
  from pyedb.misc.siw_feature_config.xtalk_scan.fd_xtalk_scan_config import (
pyedb/misc/utilities.py CHANGED
@@ -22,7 +22,6 @@
22
22
 
23
23
  """Module gathering utility functions for PyEDB modules."""
24
24
 
25
-
26
25
  import math
27
26
 
28
27
 
@@ -62,12 +62,12 @@ class GeometryOperators(object):
62
62
  Parse `'"2mm"'`.
63
63
 
64
64
  >>> from pyedb.modeler.geometry_operators import GeometryOperators as go
65
- >>> go.parse_dim_arg('2mm')
65
+ >>> go.parse_dim_arg("2mm")
66
66
  >>> 0.002
67
67
 
68
68
  Use the optional argument ``scale_to_unit`` to specify the destination unit.
69
69
 
70
- >>> go.parse_dim_arg('2mm', scale_to_unit='mm')
70
+ >>> go.parse_dim_arg("2mm", scale_to_unit="mm")
71
71
  >>> 2.0
72
72
 
73
73
  """
@@ -1588,6 +1588,7 @@ class GeometryOperators(object):
1588
1588
  ``True`` if the segments are intersecting.
1589
1589
  ``False`` otherwise.
1590
1590
  """
1591
+
1591
1592
  # fmt: off
1592
1593
  def on_segment(p, q, r):
1593
1594
  # Given three collinear points p, q, r, the function checks if point q lies on line-segment 'pr'
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pyedb
3
- Version: 0.56.0
3
+ Version: 0.58.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>
@@ -16,7 +16,7 @@ Classifier: Programming Language :: Python :: 3.9
16
16
  Classifier: Programming Language :: Python :: 3.10
17
17
  Classifier: Programming Language :: Python :: 3.11
18
18
  License-File: LICENSE
19
- Requires-Dist: cffi>=1.16.0,<1.18; platform_system=='Linux'
19
+ Requires-Dist: cffi>=1.16.0,<2.1; platform_system=='Linux'
20
20
  Requires-Dist: pywin32 >= 303;platform_system=='Windows'
21
21
  Requires-Dist: ansys-pythonnet >= 3.1.0rc4
22
22
  Requires-Dist: dotnetcore2 ==3.1.23;platform_system=='Linux'
@@ -29,6 +29,8 @@ Requires-Dist: shapely
29
29
  Requires-Dist: scikit-rf
30
30
  Requires-Dist: ansys-edb-core>=0.2.0
31
31
  Requires-Dist: psutil
32
+ Requires-Dist: defusedxml>=0.7,<8.0
33
+ Requires-Dist: matplotlib>=3.5.0,<3.11
32
34
  Requires-Dist: ansys-sphinx-theme>=1.0.0,<1.5 ; extra == "doc"
33
35
  Requires-Dist: imageio>=2.30.0,<2.38 ; extra == "doc"
34
36
  Requires-Dist: ipython>=8.13.0,<8.32 ; extra == "doc"
@@ -41,18 +43,16 @@ Requires-Dist: numpydoc>=1.5.0,<1.9 ; extra == "doc"
41
43
  Requires-Dist: pypandoc>=1.10.0,<1.16 ; extra == "doc"
42
44
  Requires-Dist: recommonmark ; extra == "doc"
43
45
  Requires-Dist: Sphinx>=7.1.0,<8.2 ; extra == "doc"
44
- Requires-Dist: sphinx-autobuild==2021.3.14 ; extra == "doc" and ( python_version == '3.8')
46
+ Requires-Dist: sphinx-autobuild==2024.10.3 ; extra == "doc" and ( python_version == '3.8')
45
47
  Requires-Dist: sphinx-autobuild==2024.10.3 ; extra == "doc" and ( python_version > '3.8')
46
48
  Requires-Dist: sphinx-copybutton>=0.5.0,<0.6 ; extra == "doc"
47
49
  Requires-Dist: sphinx-gallery>=0.14.0,<0.20 ; extra == "doc"
48
50
  Requires-Dist: sphinx_design>=0.4.0,<0.7 ; extra == "doc"
49
51
  Requires-Dist: shapely ; extra == "doc"
50
- Requires-Dist: matplotlib>=3.5.0,<3.11 ; extra == "full"
51
- Requires-Dist: shapely ; extra == "full"
52
52
  Requires-Dist: matplotlib>=3.5.0,<3.11 ; extra == "tests"
53
53
  Requires-Dist: mock>=5.1.0,<5.3 ; extra == "tests"
54
54
  Requires-Dist: pytest>=7.4.0,<8.5 ; extra == "tests"
55
- Requires-Dist: pytest-cov>=4.0.0,<6.3 ; extra == "tests"
55
+ Requires-Dist: pytest-cov>=4.0.0,<7.1 ; extra == "tests"
56
56
  Requires-Dist: pytest-xdist>=3.5.0,<3.7 ; extra == "tests"
57
57
  Requires-Dist: scikit-rf ; extra == "tests"
58
58
  Requires-Dist: shapely ; extra == "tests"
@@ -62,7 +62,6 @@ Project-URL: Documentation, https://edb.docs.pyansys.com
62
62
  Project-URL: Releases, https://github.com/ansys/pyedb/releases
63
63
  Project-URL: Source, https://github.com/ansys/pyedb
64
64
  Provides-Extra: doc
65
- Provides-Extra: full
66
65
  Provides-Extra: tests
67
66
 
68
67
  <!-- -->