pyedb 0.2.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.
- pyedb/__init__.py +17 -0
- pyedb/dotnet/__init__.py +0 -0
- pyedb/dotnet/application/Variables.py +2261 -0
- pyedb/dotnet/application/__init__.py +0 -0
- pyedb/dotnet/clr_module.py +103 -0
- pyedb/dotnet/edb.py +4237 -0
- pyedb/dotnet/edb_core/__init__.py +1 -0
- pyedb/dotnet/edb_core/cell/__init__.py +0 -0
- pyedb/dotnet/edb_core/cell/hierarchy/__init__.py +0 -0
- pyedb/dotnet/edb_core/cell/hierarchy/model.py +66 -0
- pyedb/dotnet/edb_core/components.py +2669 -0
- pyedb/dotnet/edb_core/configuration.py +423 -0
- pyedb/dotnet/edb_core/definition/__init__.py +0 -0
- pyedb/dotnet/edb_core/definition/component_def.py +166 -0
- pyedb/dotnet/edb_core/definition/component_model.py +30 -0
- pyedb/dotnet/edb_core/definition/definition_obj.py +18 -0
- pyedb/dotnet/edb_core/definition/definitions.py +12 -0
- pyedb/dotnet/edb_core/dotnet/__init__.py +0 -0
- pyedb/dotnet/edb_core/dotnet/database.py +1218 -0
- pyedb/dotnet/edb_core/dotnet/layout.py +238 -0
- pyedb/dotnet/edb_core/dotnet/primitive.py +1517 -0
- pyedb/dotnet/edb_core/edb_data/__init__.py +0 -0
- pyedb/dotnet/edb_core/edb_data/components_data.py +938 -0
- pyedb/dotnet/edb_core/edb_data/connectable.py +113 -0
- pyedb/dotnet/edb_core/edb_data/control_file.py +1268 -0
- pyedb/dotnet/edb_core/edb_data/design_options.py +35 -0
- pyedb/dotnet/edb_core/edb_data/edbvalue.py +45 -0
- pyedb/dotnet/edb_core/edb_data/hfss_extent_info.py +330 -0
- pyedb/dotnet/edb_core/edb_data/hfss_simulation_setup_data.py +1607 -0
- pyedb/dotnet/edb_core/edb_data/layer_data.py +576 -0
- pyedb/dotnet/edb_core/edb_data/nets_data.py +281 -0
- pyedb/dotnet/edb_core/edb_data/obj_base.py +19 -0
- pyedb/dotnet/edb_core/edb_data/padstacks_data.py +2080 -0
- pyedb/dotnet/edb_core/edb_data/ports.py +287 -0
- pyedb/dotnet/edb_core/edb_data/primitives_data.py +1397 -0
- pyedb/dotnet/edb_core/edb_data/simulation_configuration.py +2914 -0
- pyedb/dotnet/edb_core/edb_data/simulation_setup.py +716 -0
- pyedb/dotnet/edb_core/edb_data/siwave_simulation_setup_data.py +1205 -0
- pyedb/dotnet/edb_core/edb_data/sources.py +514 -0
- pyedb/dotnet/edb_core/edb_data/terminals.py +632 -0
- pyedb/dotnet/edb_core/edb_data/utilities.py +148 -0
- pyedb/dotnet/edb_core/edb_data/variables.py +91 -0
- pyedb/dotnet/edb_core/general.py +181 -0
- pyedb/dotnet/edb_core/hfss.py +1646 -0
- pyedb/dotnet/edb_core/layout.py +1244 -0
- pyedb/dotnet/edb_core/layout_validation.py +272 -0
- pyedb/dotnet/edb_core/materials.py +939 -0
- pyedb/dotnet/edb_core/net_class.py +335 -0
- pyedb/dotnet/edb_core/nets.py +1215 -0
- pyedb/dotnet/edb_core/padstack.py +1389 -0
- pyedb/dotnet/edb_core/siwave.py +1427 -0
- pyedb/dotnet/edb_core/stackup.py +2703 -0
- pyedb/edb_logger.py +396 -0
- pyedb/generic/__init__.py +0 -0
- pyedb/generic/constants.py +1063 -0
- pyedb/generic/data_handlers.py +320 -0
- pyedb/generic/design_types.py +104 -0
- pyedb/generic/filesystem.py +150 -0
- pyedb/generic/general_methods.py +1535 -0
- pyedb/generic/plot.py +1840 -0
- pyedb/generic/process.py +285 -0
- pyedb/generic/settings.py +224 -0
- pyedb/ipc2581/__init__.py +0 -0
- pyedb/ipc2581/bom/__init__.py +0 -0
- pyedb/ipc2581/bom/bom.py +21 -0
- pyedb/ipc2581/bom/bom_item.py +32 -0
- pyedb/ipc2581/bom/characteristics.py +37 -0
- pyedb/ipc2581/bom/refdes.py +16 -0
- pyedb/ipc2581/content/__init__.py +0 -0
- pyedb/ipc2581/content/color.py +38 -0
- pyedb/ipc2581/content/content.py +55 -0
- pyedb/ipc2581/content/dictionary_color.py +29 -0
- pyedb/ipc2581/content/dictionary_fill.py +28 -0
- pyedb/ipc2581/content/dictionary_line.py +30 -0
- pyedb/ipc2581/content/entry_color.py +13 -0
- pyedb/ipc2581/content/entry_line.py +14 -0
- pyedb/ipc2581/content/fill.py +15 -0
- pyedb/ipc2581/content/layer_ref.py +10 -0
- pyedb/ipc2581/content/standard_geometries_dictionary.py +72 -0
- pyedb/ipc2581/ecad/__init__.py +0 -0
- pyedb/ipc2581/ecad/cad_data/__init__.py +0 -0
- pyedb/ipc2581/ecad/cad_data/assembly_drawing.py +26 -0
- pyedb/ipc2581/ecad/cad_data/cad_data.py +37 -0
- pyedb/ipc2581/ecad/cad_data/component.py +41 -0
- pyedb/ipc2581/ecad/cad_data/drill.py +30 -0
- pyedb/ipc2581/ecad/cad_data/feature.py +54 -0
- pyedb/ipc2581/ecad/cad_data/layer.py +41 -0
- pyedb/ipc2581/ecad/cad_data/layer_feature.py +151 -0
- pyedb/ipc2581/ecad/cad_data/logical_net.py +32 -0
- pyedb/ipc2581/ecad/cad_data/outline.py +25 -0
- pyedb/ipc2581/ecad/cad_data/package.py +104 -0
- pyedb/ipc2581/ecad/cad_data/padstack_def.py +38 -0
- pyedb/ipc2581/ecad/cad_data/padstack_hole_def.py +24 -0
- pyedb/ipc2581/ecad/cad_data/padstack_instance.py +62 -0
- pyedb/ipc2581/ecad/cad_data/padstack_pad_def.py +26 -0
- pyedb/ipc2581/ecad/cad_data/path.py +89 -0
- pyedb/ipc2581/ecad/cad_data/phy_net.py +80 -0
- pyedb/ipc2581/ecad/cad_data/pin.py +31 -0
- pyedb/ipc2581/ecad/cad_data/polygon.py +169 -0
- pyedb/ipc2581/ecad/cad_data/profile.py +40 -0
- pyedb/ipc2581/ecad/cad_data/stackup.py +31 -0
- pyedb/ipc2581/ecad/cad_data/stackup_group.py +42 -0
- pyedb/ipc2581/ecad/cad_data/stackup_layer.py +21 -0
- pyedb/ipc2581/ecad/cad_data/step.py +275 -0
- pyedb/ipc2581/ecad/cad_header.py +33 -0
- pyedb/ipc2581/ecad/ecad.py +19 -0
- pyedb/ipc2581/ecad/spec.py +46 -0
- pyedb/ipc2581/history_record.py +37 -0
- pyedb/ipc2581/ipc2581.py +387 -0
- pyedb/ipc2581/logistic_header.py +25 -0
- pyedb/misc/__init__.py +0 -0
- pyedb/misc/aedtlib_personalib_install.py +14 -0
- pyedb/misc/downloads.py +322 -0
- pyedb/misc/misc.py +67 -0
- pyedb/misc/pyedb.runtimeconfig.json +13 -0
- pyedb/misc/siw_feature_config/__init__.py +0 -0
- pyedb/misc/siw_feature_config/emc/__init__.py +0 -0
- pyedb/misc/siw_feature_config/emc/component_tags.py +46 -0
- pyedb/misc/siw_feature_config/emc/net_tags.py +37 -0
- pyedb/misc/siw_feature_config/emc/tag_library.py +62 -0
- pyedb/misc/siw_feature_config/emc/xml_generic.py +78 -0
- pyedb/misc/siw_feature_config/emc_rule_checker_settings.py +179 -0
- pyedb/misc/utilities.py +27 -0
- pyedb/modeler/geometry_operators.py +2082 -0
- pyedb-0.2.0.dist-info/LICENSE +21 -0
- pyedb-0.2.0.dist-info/METADATA +208 -0
- pyedb-0.2.0.dist-info/RECORD +128 -0
- pyedb-0.2.0.dist-info/WHEEL +4 -0
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import math
|
|
2
|
+
|
|
3
|
+
from pyedb.generic.general_methods import ET, pyedb_function_handler
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class Polygon(object):
|
|
7
|
+
def __init__(self, ipc):
|
|
8
|
+
self._ipc = ipc
|
|
9
|
+
self.is_void = False
|
|
10
|
+
self.poly_steps = []
|
|
11
|
+
self.solid_fill_id = ""
|
|
12
|
+
self.cutout = []
|
|
13
|
+
|
|
14
|
+
@pyedb_function_handler()
|
|
15
|
+
def add_poly_step(self, polygon=None): # pragma no cover
|
|
16
|
+
if polygon:
|
|
17
|
+
polygon_data = polygon.GetPolygonData()
|
|
18
|
+
if polygon_data.IsClosed():
|
|
19
|
+
arcs = polygon_data.GetArcData()
|
|
20
|
+
if not arcs:
|
|
21
|
+
return
|
|
22
|
+
# begin
|
|
23
|
+
new_segment_tep = PolyStep()
|
|
24
|
+
new_segment_tep.poly_type = PolyType.Segment
|
|
25
|
+
new_segment_tep.x = arcs[0].Start.X.ToDouble()
|
|
26
|
+
new_segment_tep.y = arcs[0].Start.Y.ToDouble()
|
|
27
|
+
self.poly_steps.append(new_segment_tep)
|
|
28
|
+
for arc in arcs:
|
|
29
|
+
if arc.Height == 0:
|
|
30
|
+
new_segment_tep = PolyStep()
|
|
31
|
+
new_segment_tep.poly_type = PolyType.Segment
|
|
32
|
+
new_segment_tep.x = arc.End.X.ToDouble()
|
|
33
|
+
new_segment_tep.y = arc.End.Y.ToDouble()
|
|
34
|
+
self.poly_steps.append(new_segment_tep)
|
|
35
|
+
else:
|
|
36
|
+
arc_center = arc.GetCenter()
|
|
37
|
+
new_poly_step = PolyStep()
|
|
38
|
+
new_poly_step.poly_type = PolyType.Curve
|
|
39
|
+
new_poly_step.center_X = arc_center.X.ToDouble()
|
|
40
|
+
new_poly_step.center_y = arc_center.Y.ToDouble()
|
|
41
|
+
new_poly_step.x = arc.End.X.ToDouble()
|
|
42
|
+
new_poly_step.y = arc.End.Y.ToDouble()
|
|
43
|
+
new_poly_step.clock_wise = not arc.IsCCW()
|
|
44
|
+
self.poly_steps.append(new_poly_step)
|
|
45
|
+
for void in polygon.voids:
|
|
46
|
+
void_polygon_data = void.GetPolygonData()
|
|
47
|
+
if void_polygon_data.IsClosed():
|
|
48
|
+
void_arcs = void_polygon_data.GetArcData()
|
|
49
|
+
if not void_arcs:
|
|
50
|
+
return
|
|
51
|
+
void_polygon = Cutout(self._ipc)
|
|
52
|
+
self.cutout.append(void_polygon)
|
|
53
|
+
# begin
|
|
54
|
+
new_segment_tep = PolyStep()
|
|
55
|
+
new_segment_tep.poly_type = PolyType.Segment
|
|
56
|
+
new_segment_tep.x = void_arcs[0].Start.X.ToDouble()
|
|
57
|
+
new_segment_tep.y = void_arcs[0].Start.Y.ToDouble()
|
|
58
|
+
void_polygon.poly_steps.append(new_segment_tep)
|
|
59
|
+
for void_arc in void_arcs:
|
|
60
|
+
if void_arc.Height == 0:
|
|
61
|
+
new_segment_tep = PolyStep()
|
|
62
|
+
new_segment_tep.poly_type = PolyType.Segment
|
|
63
|
+
new_segment_tep.x = void_arc.End.X.ToDouble()
|
|
64
|
+
new_segment_tep.y = void_arc.End.Y.ToDouble()
|
|
65
|
+
void_polygon.poly_steps.append(new_segment_tep)
|
|
66
|
+
else:
|
|
67
|
+
arc_center = void_arc.GetCenter()
|
|
68
|
+
new_poly_step = PolyStep()
|
|
69
|
+
new_poly_step.poly_type = PolyType.Curve
|
|
70
|
+
new_poly_step.center_X = arc_center.X.ToDouble()
|
|
71
|
+
new_poly_step.center_y = arc_center.Y.ToDouble()
|
|
72
|
+
new_poly_step.x = void_arc.End.X.ToDouble()
|
|
73
|
+
new_poly_step.y = void_arc.End.Y.ToDouble()
|
|
74
|
+
new_poly_step.clock_wise = not void_arc.IsCCW()
|
|
75
|
+
void_polygon.poly_steps.append(new_poly_step)
|
|
76
|
+
|
|
77
|
+
@pyedb_function_handler()
|
|
78
|
+
def add_cutout(self, cutout): # pragma no cover
|
|
79
|
+
if not isinstance(cutout, Cutout):
|
|
80
|
+
return False
|
|
81
|
+
self.cutout.append(cutout)
|
|
82
|
+
|
|
83
|
+
@pyedb_function_handler()
|
|
84
|
+
def write_xml(self, root_net): # pragma no cover
|
|
85
|
+
if not self.poly_steps:
|
|
86
|
+
return
|
|
87
|
+
feature = ET.SubElement(root_net, "Features")
|
|
88
|
+
location = ET.SubElement(feature, "Location")
|
|
89
|
+
location.set("x", str(0))
|
|
90
|
+
location.set("y", str(0))
|
|
91
|
+
contour = ET.SubElement(feature, "Contour")
|
|
92
|
+
polygon = ET.SubElement(contour, "Polygon")
|
|
93
|
+
polygon_begin = ET.SubElement(polygon, "PolyBegin")
|
|
94
|
+
polygon_begin.set("x", str(self._ipc.from_meter_to_units(self.poly_steps[0].x, self._ipc.units)))
|
|
95
|
+
polygon_begin.set("y", str(self._ipc.from_meter_to_units(self.poly_steps[0].y, self._ipc.units)))
|
|
96
|
+
for poly_step in self.poly_steps[1:]:
|
|
97
|
+
poly_step.write_xml(polygon, self._ipc)
|
|
98
|
+
for cutout in self.cutout:
|
|
99
|
+
cutout.write_xml(contour, self._ipc)
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
class Cutout(object):
|
|
103
|
+
def __init__(self, ipc):
|
|
104
|
+
self._ipc = ipc
|
|
105
|
+
self.poly_steps = []
|
|
106
|
+
|
|
107
|
+
@pyedb_function_handler()
|
|
108
|
+
def write_xml(self, contour, ipc): # pragma no cover
|
|
109
|
+
cutout = ET.SubElement(contour, "Cutout")
|
|
110
|
+
cutout_begin = ET.SubElement(cutout, "PolyBegin")
|
|
111
|
+
cutout_begin.set("x", str(ipc.from_meter_to_units(self.poly_steps[0].x, ipc.units)))
|
|
112
|
+
cutout_begin.set("y", str(ipc.from_meter_to_units(self.poly_steps[0].y, ipc.units)))
|
|
113
|
+
for poly_step in self.poly_steps[1:]:
|
|
114
|
+
if poly_step.poly_type == 0:
|
|
115
|
+
poly = ET.SubElement(cutout, "PolyStepSegment")
|
|
116
|
+
poly.set("x", str(ipc.from_meter_to_units(poly_step.x, ipc.units)))
|
|
117
|
+
poly.set("y", str(ipc.from_meter_to_units(poly_step.y, ipc.units)))
|
|
118
|
+
elif poly_step.poly_type == 1:
|
|
119
|
+
poly = ET.SubElement(cutout, "PolyStepCurve")
|
|
120
|
+
poly.set("x", str(ipc.from_meter_to_units(poly_step.x, ipc.units)))
|
|
121
|
+
poly.set("y", str(ipc.from_meter_to_units(poly_step.y, ipc.units)))
|
|
122
|
+
poly.set("centerX", str(ipc.from_meter_to_units(poly_step.center_X, ipc.units)))
|
|
123
|
+
poly.set("centerY", str(ipc.from_meter_to_units(poly_step.center_y, ipc.units)))
|
|
124
|
+
poly.set("clockwise", str(poly_step.clock_wise).lower())
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
class PolyStep(object):
|
|
128
|
+
def __init__(self):
|
|
129
|
+
self.poly_type = PolyType().Segment
|
|
130
|
+
self.x = 0.0
|
|
131
|
+
self.y = 0.0
|
|
132
|
+
self.center_X = 0.0
|
|
133
|
+
self.center_y = 0.0
|
|
134
|
+
self.clock_wise = False
|
|
135
|
+
|
|
136
|
+
@pyedb_function_handler()
|
|
137
|
+
def write_xml(self, polygon, ipc): # pragma no cover
|
|
138
|
+
if self.poly_type == 0:
|
|
139
|
+
poly = ET.SubElement(polygon, "PolyStepSegment")
|
|
140
|
+
poly.set("x", str(ipc.from_meter_to_units(self.x, ipc.units)))
|
|
141
|
+
poly.set("y", str(ipc.from_meter_to_units(self.y, ipc.units)))
|
|
142
|
+
elif self.poly_type == 1:
|
|
143
|
+
poly = ET.SubElement(polygon, "PolyStepCurve")
|
|
144
|
+
poly.set("x", str(ipc.from_meter_to_units(self.x, ipc.units)))
|
|
145
|
+
poly.set("y", str(ipc.from_meter_to_units(self.y, ipc.units)))
|
|
146
|
+
poly.set("centerX", str(ipc.from_meter_to_units(self.center_X, ipc.units)))
|
|
147
|
+
poly.set("centerY", str(ipc.from_meter_to_units(self.center_y, ipc.units)))
|
|
148
|
+
poly.set("clockwise", str(self.clock_wise).lower())
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
class PolyType(object):
|
|
152
|
+
(Segment, Curve) = range(0, 2)
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
class Curve(object):
|
|
156
|
+
def __init__(self):
|
|
157
|
+
self.center_X = 0.0
|
|
158
|
+
self.center_y = 0.0
|
|
159
|
+
self.clock_wise = False
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
class Arc(object):
|
|
163
|
+
@staticmethod
|
|
164
|
+
def get_arc_radius_angle(h, c): # pragma no cover
|
|
165
|
+
if not isinstance(h, float) and isinstance(c, float):
|
|
166
|
+
return False
|
|
167
|
+
r = h / 2 + math.pow(c, 2) / (8 * h)
|
|
168
|
+
theta = 2 * math.asin(c / (2 * r))
|
|
169
|
+
return r, theta
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
from pyedb.generic.general_methods import ET
|
|
2
|
+
from pyedb.ipc2581.ecad.cad_data.layer_feature import LayerFeature
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class Profile(object):
|
|
6
|
+
def __init__(self, ipc):
|
|
7
|
+
self._profile = []
|
|
8
|
+
self._ipc = ipc
|
|
9
|
+
|
|
10
|
+
@property
|
|
11
|
+
def profile(self):
|
|
12
|
+
return self._profile
|
|
13
|
+
|
|
14
|
+
@profile.setter
|
|
15
|
+
def profile(self, value): # pragma no cover
|
|
16
|
+
if isinstance(value, list):
|
|
17
|
+
if len([poly for poly in value if isinstance(poly, LayerFeature)]) == len(value):
|
|
18
|
+
self._profile = value
|
|
19
|
+
|
|
20
|
+
def add_polygon(self, polygon): # pragma no cover
|
|
21
|
+
if isinstance(polygon, LayerFeature):
|
|
22
|
+
self._profile.append(polygon)
|
|
23
|
+
|
|
24
|
+
def xml_writer(self, step): # pragma no cover
|
|
25
|
+
profile = ET.SubElement(step, "Profile")
|
|
26
|
+
for poly in self.profile:
|
|
27
|
+
for feature in poly.features:
|
|
28
|
+
if feature.feature_type == 0:
|
|
29
|
+
polygon = ET.SubElement(profile, "Polygon")
|
|
30
|
+
polygon_begin = ET.SubElement(polygon, "PolyBegin")
|
|
31
|
+
polygon_begin.set(
|
|
32
|
+
"x", str(self._ipc.from_meter_to_units(feature.polygon.poly_steps[0].x, self._ipc.units))
|
|
33
|
+
)
|
|
34
|
+
polygon_begin.set(
|
|
35
|
+
"y", str(self._ipc.from_meter_to_units(feature.polygon.poly_steps[0].y, self._ipc.units))
|
|
36
|
+
)
|
|
37
|
+
for poly_step in feature.polygon.poly_steps[1:]:
|
|
38
|
+
poly_step.write_xml(polygon, self._ipc)
|
|
39
|
+
for cutout in feature.polygon.cutout:
|
|
40
|
+
cutout.write_xml(profile, self._ipc)
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
from pyedb.generic.general_methods import ET
|
|
2
|
+
from pyedb.ipc2581.ecad.cad_data.stackup_group import StackupGroup
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class Stackup(object):
|
|
6
|
+
def __init__(self):
|
|
7
|
+
self.name = "PRIMARY"
|
|
8
|
+
self.total_thickness = 0.0
|
|
9
|
+
self.tol_plus = 0.0
|
|
10
|
+
self.tol_min = 0.0
|
|
11
|
+
self.where_measured = "METAL"
|
|
12
|
+
self._stackup_group = StackupGroup()
|
|
13
|
+
|
|
14
|
+
@property
|
|
15
|
+
def stackup_group(self):
|
|
16
|
+
return self._stackup_group
|
|
17
|
+
|
|
18
|
+
@stackup_group.setter
|
|
19
|
+
def stackup_group(self, value): # pragma no cover
|
|
20
|
+
if isinstance(value, list):
|
|
21
|
+
if len([stack_grp for stack_grp in value if isinstance(stack_grp, StackupGroup)]):
|
|
22
|
+
self._stackup_group = value
|
|
23
|
+
|
|
24
|
+
def write_xml(self, cad_data): # pragma no cover
|
|
25
|
+
stackup = ET.SubElement(cad_data, "Stackup")
|
|
26
|
+
stackup.set("name", self.name)
|
|
27
|
+
stackup.set("overallThickness", str(self.total_thickness))
|
|
28
|
+
stackup.set("tolPlus", str(self.tol_plus))
|
|
29
|
+
stackup.set("tolMinus", str(self.tol_min))
|
|
30
|
+
stackup.set("whereMeasured", self.where_measured)
|
|
31
|
+
self.stackup_group.write_xml(stackup)
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
from pyedb.generic.general_methods import ET
|
|
2
|
+
from pyedb.ipc2581.ecad.cad_data.layer import Layer
|
|
3
|
+
from pyedb.ipc2581.ecad.cad_data.stackup_layer import StackupLayer
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class StackupGroup(object):
|
|
7
|
+
def __init__(self):
|
|
8
|
+
self.name = "GROUP_PRIMARY"
|
|
9
|
+
self.thickness = 0
|
|
10
|
+
self.tol_plus = 0
|
|
11
|
+
self.tol_minus = 0
|
|
12
|
+
self._stackup_layers = []
|
|
13
|
+
|
|
14
|
+
@property
|
|
15
|
+
def stackup_layers(self):
|
|
16
|
+
return self._stackup_layers
|
|
17
|
+
|
|
18
|
+
@stackup_layers.setter
|
|
19
|
+
def stackup_layers(self, value): # pragma no cover
|
|
20
|
+
if isinstance(value, list):
|
|
21
|
+
if len([lay for lay in value if isinstance(lay, Layer)]):
|
|
22
|
+
self._stackup_layers = value
|
|
23
|
+
|
|
24
|
+
def add_stackup_layer(
|
|
25
|
+
self, layer_name="", thickness="", tol_minus="0.0", tol_plus="0.0", sequence=""
|
|
26
|
+
): # pragma no cover
|
|
27
|
+
stackup_layer = StackupLayer()
|
|
28
|
+
stackup_layer.layer_name = layer_name
|
|
29
|
+
stackup_layer.thickness = thickness
|
|
30
|
+
stackup_layer.tol_plus = tol_plus
|
|
31
|
+
stackup_layer.tol_minus = tol_minus
|
|
32
|
+
stackup_layer.sequence = sequence
|
|
33
|
+
self._stackup_layers.append(stackup_layer)
|
|
34
|
+
|
|
35
|
+
def write_xml(self, stackup): # pragma no cover
|
|
36
|
+
stackup_group = ET.SubElement(stackup, "StackupGroup")
|
|
37
|
+
stackup_group.set("name", "GROUP_PRIMARY")
|
|
38
|
+
stackup_group.set("thickness", str(self.thickness))
|
|
39
|
+
stackup_group.set("tolPlus", str(self.tol_plus))
|
|
40
|
+
stackup_group.set("tolMinus", str(self.tol_minus))
|
|
41
|
+
for layer in self.stackup_layers:
|
|
42
|
+
layer.write_xml(stackup_group)
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
from pyedb.generic.general_methods import ET
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class StackupLayer(object):
|
|
5
|
+
def __init__(self):
|
|
6
|
+
self.layer_name = ""
|
|
7
|
+
self.thickness = 0
|
|
8
|
+
self.tol_minus = 0
|
|
9
|
+
self.tol_plus = 0
|
|
10
|
+
self.sequence = ""
|
|
11
|
+
self.spec_ref = "SPEC_{}".format(self.layer_name)
|
|
12
|
+
|
|
13
|
+
def write_xml(self, stackup_group): # pragma no cover
|
|
14
|
+
stackup_layer = ET.SubElement(stackup_group, "StackupLayer")
|
|
15
|
+
stackup_layer.set("layerOrGroupRef", self.layer_name)
|
|
16
|
+
stackup_layer.set("thickness", str(self.thickness))
|
|
17
|
+
stackup_layer.set("tolPlus", str(self.tol_plus))
|
|
18
|
+
stackup_layer.set("tolMinus", str(self.tol_minus))
|
|
19
|
+
stackup_layer.set("sequence", self.sequence)
|
|
20
|
+
spec_ref = ET.SubElement(stackup_layer, "SpecRef")
|
|
21
|
+
spec_ref.set("id", self.layer_name)
|
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
import math
|
|
2
|
+
|
|
3
|
+
from pyedb.generic.general_methods import ET, pyedb_function_handler
|
|
4
|
+
from pyedb.ipc2581.ecad.cad_data.component import Component
|
|
5
|
+
from pyedb.ipc2581.ecad.cad_data.layer_feature import LayerFeature
|
|
6
|
+
from pyedb.ipc2581.ecad.cad_data.logical_net import LogicalNet
|
|
7
|
+
from pyedb.ipc2581.ecad.cad_data.package import Package
|
|
8
|
+
from pyedb.ipc2581.ecad.cad_data.padstack_def import PadstackDef
|
|
9
|
+
from pyedb.ipc2581.ecad.cad_data.phy_net import PhyNet
|
|
10
|
+
from pyedb.ipc2581.ecad.cad_data.profile import Profile
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class Step(object):
|
|
14
|
+
def __init__(self, caddata, edb, units, ipc):
|
|
15
|
+
self.design_name = caddata.design_name
|
|
16
|
+
self._pedb = edb
|
|
17
|
+
self._ipc = ipc
|
|
18
|
+
self.units = units
|
|
19
|
+
self._cad_data = caddata
|
|
20
|
+
self._padstack_defs = {}
|
|
21
|
+
self._profile = Profile(ipc)
|
|
22
|
+
self._packages = {}
|
|
23
|
+
self._components = []
|
|
24
|
+
self._logical_nets = []
|
|
25
|
+
self._physical_nets = []
|
|
26
|
+
self._layer_features = []
|
|
27
|
+
|
|
28
|
+
@property
|
|
29
|
+
def padstack_defs(self):
|
|
30
|
+
return self._padstack_defs
|
|
31
|
+
|
|
32
|
+
@padstack_defs.setter
|
|
33
|
+
def padstack_defs(self, value): # pragma no cover
|
|
34
|
+
if isinstance(value, list):
|
|
35
|
+
if len([pad for pad in value if isinstance(pad, PadstackDef)]) == len(value):
|
|
36
|
+
self._padstack_defs = value
|
|
37
|
+
|
|
38
|
+
@property
|
|
39
|
+
def packages(self):
|
|
40
|
+
return self._packages
|
|
41
|
+
|
|
42
|
+
@packages.setter
|
|
43
|
+
def packages(self, value): # pragma no cover
|
|
44
|
+
if isinstance(value, list):
|
|
45
|
+
if len([pkg for pkg in value if isinstance(pkg, Package)]) == len(value):
|
|
46
|
+
self._packages = value
|
|
47
|
+
|
|
48
|
+
@property
|
|
49
|
+
def profile(self):
|
|
50
|
+
return self._profile
|
|
51
|
+
|
|
52
|
+
@property
|
|
53
|
+
def components(self):
|
|
54
|
+
return self._components
|
|
55
|
+
|
|
56
|
+
@components.setter
|
|
57
|
+
def components(self, value): # pragma no cover
|
|
58
|
+
if isinstance(value, list):
|
|
59
|
+
if len([cmp for cmp in value if isinstance(cmp, Component)]) == len(value):
|
|
60
|
+
self._components = value
|
|
61
|
+
|
|
62
|
+
@property
|
|
63
|
+
def logical_nets(self):
|
|
64
|
+
return self._logical_nets
|
|
65
|
+
|
|
66
|
+
@pyedb_function_handler()
|
|
67
|
+
def add_logical_net(self, net=None): # pragma no cover
|
|
68
|
+
net_name = net.name
|
|
69
|
+
logical_net = LogicalNet()
|
|
70
|
+
logical_net.name = net_name
|
|
71
|
+
net_pins = list(net.PadstackInstances)
|
|
72
|
+
for pin in net_pins:
|
|
73
|
+
new_pin_ref = logical_net.get_pin_ref_def()
|
|
74
|
+
new_pin_ref.pin = pin.GetName()
|
|
75
|
+
new_pin_ref.component_ref = pin.GetComponent().GetName()
|
|
76
|
+
logical_net.pin_ref.append(new_pin_ref)
|
|
77
|
+
self.logical_nets.append(logical_net)
|
|
78
|
+
|
|
79
|
+
@property
|
|
80
|
+
def layer_features(self):
|
|
81
|
+
return self._layer_features
|
|
82
|
+
|
|
83
|
+
@layer_features.setter
|
|
84
|
+
def layer_features(self, value): # pragma no cover
|
|
85
|
+
if isinstance(value, list):
|
|
86
|
+
if len(
|
|
87
|
+
[
|
|
88
|
+
feat
|
|
89
|
+
for feat in value
|
|
90
|
+
if isinstance(
|
|
91
|
+
feat,
|
|
92
|
+
)
|
|
93
|
+
]
|
|
94
|
+
):
|
|
95
|
+
self._layer_features = value
|
|
96
|
+
|
|
97
|
+
@property
|
|
98
|
+
def physical_nets(self):
|
|
99
|
+
return self._physical_nets
|
|
100
|
+
|
|
101
|
+
@physical_nets.setter
|
|
102
|
+
def physical_nets(self, value): # pragma no cover
|
|
103
|
+
if isinstance(value, list):
|
|
104
|
+
if len([phy_net for phy_net in value if isinstance(phy_net, PhyNet)]) == len(value):
|
|
105
|
+
self._physical_nets = value
|
|
106
|
+
|
|
107
|
+
@pyedb_function_handler()
|
|
108
|
+
def add_physical_net(self, phy_net=None): # pragma no cover
|
|
109
|
+
if isinstance(phy_net, PhyNet):
|
|
110
|
+
self._physical_nets.append(phy_net)
|
|
111
|
+
return True
|
|
112
|
+
return False
|
|
113
|
+
|
|
114
|
+
@pyedb_function_handler()
|
|
115
|
+
def add_padstack_def(self, padstackdef=None): # pragma no cover
|
|
116
|
+
if isinstance(padstackdef, PadstackDef):
|
|
117
|
+
self._padstack_defs.append(padstackdef)
|
|
118
|
+
|
|
119
|
+
@pyedb_function_handler()
|
|
120
|
+
def add_component(self, component=None): # pragma no cover
|
|
121
|
+
# adding component add package in Step
|
|
122
|
+
if component:
|
|
123
|
+
if not component.part_name in self._packages:
|
|
124
|
+
package = Package(self._ipc)
|
|
125
|
+
package.add_component_outline(component)
|
|
126
|
+
package.name = component.part_name
|
|
127
|
+
package.height = ""
|
|
128
|
+
package.type = component.type
|
|
129
|
+
pin_number = 0
|
|
130
|
+
for _, pin in component.pins.items():
|
|
131
|
+
geometry_type, pad_parameters, pos_x, pos_y, rot = self._pedb.padstacks.get_pad_parameters(
|
|
132
|
+
pin._edb_padstackinstance, component.placement_layer, 0
|
|
133
|
+
)
|
|
134
|
+
if pad_parameters:
|
|
135
|
+
position = pin._position if pin._position else pin.position
|
|
136
|
+
pin_pos_x = self._ipc.from_meter_to_units(position[0], self.units)
|
|
137
|
+
pin_pos_y = self._ipc.from_meter_to_units(position[1], self.units)
|
|
138
|
+
primitive_ref = ""
|
|
139
|
+
if geometry_type == 1:
|
|
140
|
+
primitive_ref = "CIRC_{}".format(pad_parameters[0])
|
|
141
|
+
elif geometry_type == 2:
|
|
142
|
+
primitive_ref = "RECT_{}_{}".format(pad_parameters[0], pad_parameters[0])
|
|
143
|
+
elif geometry_type == 3:
|
|
144
|
+
primitive_ref = "RECT_{}_{}".format(pad_parameters[0], pad_parameters[1])
|
|
145
|
+
elif geometry_type == 4:
|
|
146
|
+
primitive_ref = "OVAL_{}_{}_{}".format(
|
|
147
|
+
pad_parameters[0], pad_parameters[1], pad_parameters[2]
|
|
148
|
+
)
|
|
149
|
+
if primitive_ref:
|
|
150
|
+
package.add_pin(
|
|
151
|
+
number=pin_number, x=pin_pos_x, y=pin_pos_y, rotation=rot, primitive_ref=primitive_ref
|
|
152
|
+
)
|
|
153
|
+
pin_number += 1
|
|
154
|
+
self.packages[package.name] = package
|
|
155
|
+
ipc_component = Component()
|
|
156
|
+
ipc_component.type = component.type
|
|
157
|
+
try:
|
|
158
|
+
ipc_component.value = component.value
|
|
159
|
+
except:
|
|
160
|
+
pass
|
|
161
|
+
ipc_component.refdes = component.refdes
|
|
162
|
+
center = component.center
|
|
163
|
+
ipc_component.location = [
|
|
164
|
+
self._ipc.from_meter_to_units(center[0], self.units),
|
|
165
|
+
self._ipc.from_meter_to_units(center[1], self.units),
|
|
166
|
+
]
|
|
167
|
+
ipc_component.rotation = component.rotation * 180 / math.pi
|
|
168
|
+
ipc_component.part = ipc_component.package_ref = component.part_name
|
|
169
|
+
ipc_component.layer_ref = component.placement_layer
|
|
170
|
+
self.components.append(ipc_component)
|
|
171
|
+
|
|
172
|
+
def layer_ranges(
|
|
173
|
+
self,
|
|
174
|
+
start_layer,
|
|
175
|
+
stop_layer,
|
|
176
|
+
): # pragma no cover
|
|
177
|
+
started = False
|
|
178
|
+
start_layer_name = start_layer.GetName()
|
|
179
|
+
stop_layer_name = stop_layer.GetName()
|
|
180
|
+
layer_list = []
|
|
181
|
+
for layer_name in self._ipc.layers_name:
|
|
182
|
+
if started:
|
|
183
|
+
layer_list.append(layer_name)
|
|
184
|
+
if layer_name == stop_layer_name or layer_name == start_layer_name:
|
|
185
|
+
break
|
|
186
|
+
elif layer_name == start_layer_name:
|
|
187
|
+
started = True
|
|
188
|
+
layer_list.append(layer_name)
|
|
189
|
+
if layer_name == stop_layer_name:
|
|
190
|
+
break
|
|
191
|
+
elif layer_name == stop_layer_name:
|
|
192
|
+
started = True
|
|
193
|
+
layer_list.append(layer_name)
|
|
194
|
+
if layer_name == start_layer_name:
|
|
195
|
+
break
|
|
196
|
+
return layer_list
|
|
197
|
+
|
|
198
|
+
@pyedb_function_handler()
|
|
199
|
+
def add_layer_feature(self, layer, polys): # pragma no cover
|
|
200
|
+
layer_name = layer.name
|
|
201
|
+
layer_feature = LayerFeature(self._ipc)
|
|
202
|
+
layer_feature.layer_name = layer_name
|
|
203
|
+
layer_feature.color = layer.color
|
|
204
|
+
|
|
205
|
+
for poly in polys:
|
|
206
|
+
if not poly.is_void:
|
|
207
|
+
layer_feature.add_feature(poly)
|
|
208
|
+
self._ipc.ecad.cad_data.cad_data_step.layer_features.append(layer_feature)
|
|
209
|
+
|
|
210
|
+
@pyedb_function_handler()
|
|
211
|
+
def add_profile(self, poly): # pragma no cover
|
|
212
|
+
profile = LayerFeature(self._ipc)
|
|
213
|
+
profile.layer_name = "profile"
|
|
214
|
+
if poly:
|
|
215
|
+
if not poly.is_void:
|
|
216
|
+
profile.add_feature(poly)
|
|
217
|
+
self.profile.add_polygon(profile)
|
|
218
|
+
|
|
219
|
+
@pyedb_function_handler()
|
|
220
|
+
def add_padstack_instances(self, padstack_instances, padstack_defs): # pragma no cover
|
|
221
|
+
top_bottom_layers = self._ipc.top_bottom_layers
|
|
222
|
+
layers = {j.layer_name: j for j in self._ipc.ecad.cad_data.cad_data_step.layer_features}
|
|
223
|
+
|
|
224
|
+
for padstack_instance in padstack_instances:
|
|
225
|
+
_, start_layer, stop_layer = padstack_instance._edb_padstackinstance.GetLayerRange()
|
|
226
|
+
for layer_name in self.layer_ranges(start_layer, stop_layer):
|
|
227
|
+
if layer_name not in layers:
|
|
228
|
+
layer_feature = LayerFeature(self._ipc)
|
|
229
|
+
layer_feature.layer_name = layer_name
|
|
230
|
+
layer_feature.color = self._ipc._pedb.stackup[layer_name].color
|
|
231
|
+
self._ipc.ecad.cad_data.cad_data_step.layer_features.append(layer_feature)
|
|
232
|
+
layers[layer_name] = self._ipc.ecad.cad_data.cad_data_step.layer_features[-1]
|
|
233
|
+
pdef_name = (
|
|
234
|
+
padstack_instance._pdef if padstack_instance._pdef else padstack_instance.padstack_definition
|
|
235
|
+
)
|
|
236
|
+
if pdef_name in padstack_defs:
|
|
237
|
+
padstack_def = padstack_defs[pdef_name]
|
|
238
|
+
comp_name = padstack_instance.GetComponent().GetName()
|
|
239
|
+
if padstack_instance.is_pin and comp_name:
|
|
240
|
+
component_inst = self._pedb.components.components[comp_name]
|
|
241
|
+
layers[layer_name].add_component_padstack_instance_feature(
|
|
242
|
+
component_inst, padstack_instance, top_bottom_layers, padstack_def
|
|
243
|
+
)
|
|
244
|
+
else:
|
|
245
|
+
layers[layer_name].add_via_instance_feature(padstack_instance, padstack_def, layer_name)
|
|
246
|
+
|
|
247
|
+
@pyedb_function_handler()
|
|
248
|
+
def add_drill_layer_feature(self, via_list=None, layer_feature_name=""): # pragma no cover
|
|
249
|
+
if via_list:
|
|
250
|
+
drill_layer_feature = LayerFeature(self._ipc)
|
|
251
|
+
drill_layer_feature.is_drill_feature = True
|
|
252
|
+
drill_layer_feature.layer_name = layer_feature_name
|
|
253
|
+
for via in via_list:
|
|
254
|
+
try:
|
|
255
|
+
via_diameter = via.pin.GetPadstackDef().GetData().GetHoleParameters()[2][0]
|
|
256
|
+
drill_layer_feature.add_drill_feature(via, via_diameter)
|
|
257
|
+
except:
|
|
258
|
+
pass
|
|
259
|
+
self.layer_features.append(drill_layer_feature)
|
|
260
|
+
|
|
261
|
+
@pyedb_function_handler()
|
|
262
|
+
def write_xml(self, cad_data): # pragma no cover
|
|
263
|
+
step = ET.SubElement(cad_data, "Step")
|
|
264
|
+
step.set("name", self._ipc.design_name)
|
|
265
|
+
for padsatck_def in list(self.padstack_defs.values()):
|
|
266
|
+
padsatck_def.write_xml(step)
|
|
267
|
+
self.profile.xml_writer(step)
|
|
268
|
+
for package in list(self.packages.values()):
|
|
269
|
+
package.write_xml(step)
|
|
270
|
+
for component in self.components:
|
|
271
|
+
component.write_xml(step)
|
|
272
|
+
for logical_net in self.logical_nets:
|
|
273
|
+
logical_net.write_xml(step)
|
|
274
|
+
for layer_feature in self.layer_features:
|
|
275
|
+
layer_feature.write_xml(step)
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
from pyedb.generic.general_methods import ET
|
|
2
|
+
from pyedb.ipc2581.ecad.spec import Spec
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class CadHeader(object):
|
|
6
|
+
"""Class describing a layer stackup."""
|
|
7
|
+
|
|
8
|
+
def __init__(self):
|
|
9
|
+
self._specs = []
|
|
10
|
+
self.units = ""
|
|
11
|
+
|
|
12
|
+
@property
|
|
13
|
+
def specs(self):
|
|
14
|
+
return self._specs
|
|
15
|
+
|
|
16
|
+
def add_spec(
|
|
17
|
+
self, name="", material="", layer_type="", conductivity="", dielectric_constant="", loss_tg="", embedded=""
|
|
18
|
+
): # pragma no cover
|
|
19
|
+
spec = Spec()
|
|
20
|
+
spec.name = name
|
|
21
|
+
spec.material = material
|
|
22
|
+
spec.conductivity = conductivity
|
|
23
|
+
spec.dielectric_constant = dielectric_constant
|
|
24
|
+
spec.layer_type = layer_type
|
|
25
|
+
spec.loss_tangent = loss_tg
|
|
26
|
+
spec.embedded = embedded
|
|
27
|
+
self.specs.append(spec)
|
|
28
|
+
|
|
29
|
+
def write_xml(self, ecad): # pragma no cover
|
|
30
|
+
cad_header = ET.SubElement(ecad, "CadHeader")
|
|
31
|
+
cad_header.set("units", self.units)
|
|
32
|
+
for spec in self.specs:
|
|
33
|
+
spec.write_xml(cad_header)
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
from pyedb.generic.general_methods import ET
|
|
2
|
+
from pyedb.ipc2581.ecad.cad_data.cad_data import CadData
|
|
3
|
+
from pyedb.ipc2581.ecad.cad_header import CadHeader
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class Ecad(object):
|
|
7
|
+
def __init__(self, ipc, edb, units):
|
|
8
|
+
self.design_name = "Design"
|
|
9
|
+
self.units = units
|
|
10
|
+
self.cad_header = CadHeader()
|
|
11
|
+
self._ipc = ipc
|
|
12
|
+
self.cad_data = CadData(self, edb, units, self._ipc)
|
|
13
|
+
self._pedb = edb
|
|
14
|
+
|
|
15
|
+
def write_xml(self, root): # pragma no cover
|
|
16
|
+
ecad = ET.SubElement(root, "Ecad")
|
|
17
|
+
ecad.set("name", self.design_name)
|
|
18
|
+
self.cad_header.write_xml(ecad)
|
|
19
|
+
self.cad_data.write_xml(ecad)
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
from pyedb.generic.general_methods import ET
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class Spec(object):
|
|
5
|
+
"""Class describing a layer."""
|
|
6
|
+
|
|
7
|
+
def __init__(self):
|
|
8
|
+
self.name = ""
|
|
9
|
+
self.material = ""
|
|
10
|
+
self.layer_type = ""
|
|
11
|
+
self.conductivity = ""
|
|
12
|
+
self.dielectric_constant = ""
|
|
13
|
+
self.loss_tangent = ""
|
|
14
|
+
self.embedded = ""
|
|
15
|
+
|
|
16
|
+
def write_xml(self, ecad_header): # pragma no cover
|
|
17
|
+
spec = ET.SubElement(ecad_header, "Spec")
|
|
18
|
+
spec.set("name", self.name)
|
|
19
|
+
material = ET.SubElement(spec, "General")
|
|
20
|
+
material.set("type", "MATERIAL")
|
|
21
|
+
material_set = ET.SubElement(material, "Property")
|
|
22
|
+
material_set.set("text", self.material)
|
|
23
|
+
layer_type = ET.SubElement(spec, "General")
|
|
24
|
+
layer_type.set("type", "OTHER")
|
|
25
|
+
layer_type.set("comment", "LAYER_TYPE")
|
|
26
|
+
layer_type_set = ET.SubElement(layer_type, "Property")
|
|
27
|
+
layer_type_set.set("text", self.layer_type)
|
|
28
|
+
conductivity = ET.SubElement(spec, "Conductor")
|
|
29
|
+
conductivity.set("type", "CONDUCTIVITY")
|
|
30
|
+
conductivity_set = ET.SubElement(conductivity, "Property")
|
|
31
|
+
conductivity_set.set("value", self.conductivity)
|
|
32
|
+
conductivity_set.set("unit", "MHO/CM")
|
|
33
|
+
dielectric = ET.SubElement(spec, "Dielectric")
|
|
34
|
+
dielectric.set("type", "DIELECTRIC_CONSTANT")
|
|
35
|
+
dielectric_set = ET.SubElement(dielectric, "Property")
|
|
36
|
+
dielectric_set.set("value", self.dielectric_constant)
|
|
37
|
+
loss_tg = ET.SubElement(spec, "Dielectric")
|
|
38
|
+
loss_tg.set("type", "LOSS_TANGENT")
|
|
39
|
+
loss_tg_set = ET.SubElement(loss_tg, "Property")
|
|
40
|
+
loss_tg_set.set("value", self.loss_tangent)
|
|
41
|
+
if self.layer_type == "CONDUCTOR":
|
|
42
|
+
embedded = ET.SubElement(spec, "General")
|
|
43
|
+
embedded.set("type", "OTHER")
|
|
44
|
+
embedded.set("comment", "LAYER_EMBEDDED_STATUS")
|
|
45
|
+
embedded_set = ET.SubElement(embedded, "Property")
|
|
46
|
+
embedded_set.set("text", self.embedded)
|