kicad-sch-api 0.3.4__py3-none-any.whl → 0.3.5__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 kicad-sch-api might be problematic. Click here for more details.
- kicad_sch_api/collections/__init__.py +21 -0
- kicad_sch_api/collections/base.py +296 -0
- kicad_sch_api/collections/components.py +422 -0
- kicad_sch_api/collections/junctions.py +378 -0
- kicad_sch_api/collections/labels.py +412 -0
- kicad_sch_api/collections/wires.py +407 -0
- kicad_sch_api/core/labels.py +348 -0
- kicad_sch_api/core/nets.py +310 -0
- kicad_sch_api/core/no_connects.py +274 -0
- kicad_sch_api/core/schematic.py +136 -2
- kicad_sch_api/core/texts.py +343 -0
- kicad_sch_api/core/types.py +12 -0
- kicad_sch_api/geometry/symbol_bbox.py +26 -32
- kicad_sch_api/interfaces/__init__.py +17 -0
- kicad_sch_api/interfaces/parser.py +76 -0
- kicad_sch_api/interfaces/repository.py +70 -0
- kicad_sch_api/interfaces/resolver.py +117 -0
- kicad_sch_api/parsers/__init__.py +14 -0
- kicad_sch_api/parsers/base.py +148 -0
- kicad_sch_api/parsers/label_parser.py +254 -0
- kicad_sch_api/parsers/registry.py +153 -0
- kicad_sch_api/parsers/symbol_parser.py +227 -0
- kicad_sch_api/parsers/wire_parser.py +99 -0
- kicad_sch_api/symbols/__init__.py +18 -0
- kicad_sch_api/symbols/cache.py +470 -0
- kicad_sch_api/symbols/resolver.py +367 -0
- kicad_sch_api/symbols/validators.py +453 -0
- {kicad_sch_api-0.3.4.dist-info → kicad_sch_api-0.3.5.dist-info}/METADATA +1 -1
- kicad_sch_api-0.3.5.dist-info/RECORD +58 -0
- kicad_sch_api-0.3.4.dist-info/RECORD +0 -34
- {kicad_sch_api-0.3.4.dist-info → kicad_sch_api-0.3.5.dist-info}/WHEEL +0 -0
- {kicad_sch_api-0.3.4.dist-info → kicad_sch_api-0.3.5.dist-info}/entry_points.txt +0 -0
- {kicad_sch_api-0.3.4.dist-info → kicad_sch_api-0.3.5.dist-info}/licenses/LICENSE +0 -0
- {kicad_sch_api-0.3.4.dist-info → kicad_sch_api-0.3.5.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
"""
|
|
2
|
+
No-connect element management for KiCAD schematics.
|
|
3
|
+
|
|
4
|
+
This module provides collection classes for managing no-connect elements,
|
|
5
|
+
featuring fast lookup, bulk operations, and validation.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import logging
|
|
9
|
+
import uuid
|
|
10
|
+
from typing import Any, Callable, Dict, Iterator, List, Optional, Tuple, Union
|
|
11
|
+
|
|
12
|
+
from ..utils.validation import SchematicValidator, ValidationError, ValidationIssue
|
|
13
|
+
from .types import Point, NoConnect
|
|
14
|
+
|
|
15
|
+
logger = logging.getLogger(__name__)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class NoConnectElement:
|
|
19
|
+
"""
|
|
20
|
+
Enhanced wrapper for schematic no-connect elements with modern API.
|
|
21
|
+
|
|
22
|
+
Provides intuitive access to no-connect properties and operations
|
|
23
|
+
while maintaining exact format preservation.
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
def __init__(self, no_connect_data: NoConnect, parent_collection: "NoConnectCollection"):
|
|
27
|
+
"""
|
|
28
|
+
Initialize no-connect element wrapper.
|
|
29
|
+
|
|
30
|
+
Args:
|
|
31
|
+
no_connect_data: Underlying no-connect data
|
|
32
|
+
parent_collection: Parent collection for updates
|
|
33
|
+
"""
|
|
34
|
+
self._data = no_connect_data
|
|
35
|
+
self._collection = parent_collection
|
|
36
|
+
self._validator = SchematicValidator()
|
|
37
|
+
|
|
38
|
+
# Core properties with validation
|
|
39
|
+
@property
|
|
40
|
+
def uuid(self) -> str:
|
|
41
|
+
"""No-connect element UUID."""
|
|
42
|
+
return self._data.uuid
|
|
43
|
+
|
|
44
|
+
@property
|
|
45
|
+
def position(self) -> Point:
|
|
46
|
+
"""No-connect position."""
|
|
47
|
+
return self._data.position
|
|
48
|
+
|
|
49
|
+
@position.setter
|
|
50
|
+
def position(self, value: Union[Point, Tuple[float, float]]):
|
|
51
|
+
"""Set no-connect position."""
|
|
52
|
+
if isinstance(value, tuple):
|
|
53
|
+
value = Point(value[0], value[1])
|
|
54
|
+
elif not isinstance(value, Point):
|
|
55
|
+
raise ValidationError(f"Position must be Point or tuple, got {type(value)}")
|
|
56
|
+
self._data.position = value
|
|
57
|
+
self._collection._mark_modified()
|
|
58
|
+
|
|
59
|
+
def validate(self) -> List[ValidationIssue]:
|
|
60
|
+
"""Validate this no-connect element."""
|
|
61
|
+
return self._validator.validate_no_connect(self._data.__dict__)
|
|
62
|
+
|
|
63
|
+
def to_dict(self) -> Dict[str, Any]:
|
|
64
|
+
"""Convert no-connect element to dictionary representation."""
|
|
65
|
+
return {
|
|
66
|
+
"uuid": self.uuid,
|
|
67
|
+
"position": {"x": self.position.x, "y": self.position.y},
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
def __str__(self) -> str:
|
|
71
|
+
"""String representation."""
|
|
72
|
+
return f"<NoConnect @ {self.position}>"
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
class NoConnectCollection:
|
|
76
|
+
"""
|
|
77
|
+
Collection class for efficient no-connect element management.
|
|
78
|
+
|
|
79
|
+
Provides fast lookup, filtering, and bulk operations for schematic no-connect elements.
|
|
80
|
+
"""
|
|
81
|
+
|
|
82
|
+
def __init__(self, no_connects: List[NoConnect] = None):
|
|
83
|
+
"""
|
|
84
|
+
Initialize no-connect collection.
|
|
85
|
+
|
|
86
|
+
Args:
|
|
87
|
+
no_connects: Initial list of no-connect data
|
|
88
|
+
"""
|
|
89
|
+
self._no_connects: List[NoConnectElement] = []
|
|
90
|
+
self._uuid_index: Dict[str, NoConnectElement] = {}
|
|
91
|
+
self._position_index: Dict[Tuple[float, float], List[NoConnectElement]] = {}
|
|
92
|
+
self._modified = False
|
|
93
|
+
|
|
94
|
+
# Add initial no-connects
|
|
95
|
+
if no_connects:
|
|
96
|
+
for no_connect_data in no_connects:
|
|
97
|
+
self._add_to_indexes(NoConnectElement(no_connect_data, self))
|
|
98
|
+
|
|
99
|
+
logger.debug(f"NoConnectCollection initialized with {len(self._no_connects)} no-connects")
|
|
100
|
+
|
|
101
|
+
def add(
|
|
102
|
+
self,
|
|
103
|
+
position: Union[Point, Tuple[float, float]],
|
|
104
|
+
no_connect_uuid: Optional[str] = None,
|
|
105
|
+
) -> NoConnectElement:
|
|
106
|
+
"""
|
|
107
|
+
Add a new no-connect element to the schematic.
|
|
108
|
+
|
|
109
|
+
Args:
|
|
110
|
+
position: No-connect position
|
|
111
|
+
no_connect_uuid: Specific UUID for no-connect (auto-generated if None)
|
|
112
|
+
|
|
113
|
+
Returns:
|
|
114
|
+
Newly created NoConnectElement
|
|
115
|
+
|
|
116
|
+
Raises:
|
|
117
|
+
ValidationError: If no-connect data is invalid
|
|
118
|
+
"""
|
|
119
|
+
# Validate inputs
|
|
120
|
+
if isinstance(position, tuple):
|
|
121
|
+
position = Point(position[0], position[1])
|
|
122
|
+
elif not isinstance(position, Point):
|
|
123
|
+
raise ValidationError(f"Position must be Point or tuple, got {type(position)}")
|
|
124
|
+
|
|
125
|
+
# Generate UUID if not provided
|
|
126
|
+
if not no_connect_uuid:
|
|
127
|
+
no_connect_uuid = str(uuid.uuid4())
|
|
128
|
+
|
|
129
|
+
# Check for duplicate UUID
|
|
130
|
+
if no_connect_uuid in self._uuid_index:
|
|
131
|
+
raise ValidationError(f"NoConnect UUID {no_connect_uuid} already exists")
|
|
132
|
+
|
|
133
|
+
# Create no-connect data
|
|
134
|
+
no_connect_data = NoConnect(
|
|
135
|
+
uuid=no_connect_uuid,
|
|
136
|
+
position=position,
|
|
137
|
+
)
|
|
138
|
+
|
|
139
|
+
# Create wrapper and add to collection
|
|
140
|
+
no_connect_element = NoConnectElement(no_connect_data, self)
|
|
141
|
+
self._add_to_indexes(no_connect_element)
|
|
142
|
+
self._mark_modified()
|
|
143
|
+
|
|
144
|
+
logger.debug(f"Added no-connect: {no_connect_element}")
|
|
145
|
+
return no_connect_element
|
|
146
|
+
|
|
147
|
+
def get(self, no_connect_uuid: str) -> Optional[NoConnectElement]:
|
|
148
|
+
"""Get no-connect by UUID."""
|
|
149
|
+
return self._uuid_index.get(no_connect_uuid)
|
|
150
|
+
|
|
151
|
+
def remove(self, no_connect_uuid: str) -> bool:
|
|
152
|
+
"""
|
|
153
|
+
Remove no-connect by UUID.
|
|
154
|
+
|
|
155
|
+
Args:
|
|
156
|
+
no_connect_uuid: UUID of no-connect to remove
|
|
157
|
+
|
|
158
|
+
Returns:
|
|
159
|
+
True if no-connect was removed, False if not found
|
|
160
|
+
"""
|
|
161
|
+
no_connect_element = self._uuid_index.get(no_connect_uuid)
|
|
162
|
+
if not no_connect_element:
|
|
163
|
+
return False
|
|
164
|
+
|
|
165
|
+
# Remove from indexes
|
|
166
|
+
self._remove_from_indexes(no_connect_element)
|
|
167
|
+
self._mark_modified()
|
|
168
|
+
|
|
169
|
+
logger.debug(f"Removed no-connect: {no_connect_element}")
|
|
170
|
+
return True
|
|
171
|
+
|
|
172
|
+
def find_at_position(self, position: Union[Point, Tuple[float, float]], tolerance: float = 0.1) -> List[NoConnectElement]:
|
|
173
|
+
"""
|
|
174
|
+
Find no-connects at or near a position.
|
|
175
|
+
|
|
176
|
+
Args:
|
|
177
|
+
position: Position to search around
|
|
178
|
+
tolerance: Search tolerance in mm
|
|
179
|
+
|
|
180
|
+
Returns:
|
|
181
|
+
List of matching no-connect elements
|
|
182
|
+
"""
|
|
183
|
+
if isinstance(position, tuple):
|
|
184
|
+
position = Point(position[0], position[1])
|
|
185
|
+
|
|
186
|
+
matches = []
|
|
187
|
+
for no_connect_element in self._no_connects:
|
|
188
|
+
distance = no_connect_element.position.distance_to(position)
|
|
189
|
+
if distance <= tolerance:
|
|
190
|
+
matches.append(no_connect_element)
|
|
191
|
+
return matches
|
|
192
|
+
|
|
193
|
+
def filter(self, predicate: Callable[[NoConnectElement], bool]) -> List[NoConnectElement]:
|
|
194
|
+
"""
|
|
195
|
+
Filter no-connects by predicate function.
|
|
196
|
+
|
|
197
|
+
Args:
|
|
198
|
+
predicate: Function that returns True for no-connects to include
|
|
199
|
+
|
|
200
|
+
Returns:
|
|
201
|
+
List of no-connects matching predicate
|
|
202
|
+
"""
|
|
203
|
+
return [no_connect for no_connect in self._no_connects if predicate(no_connect)]
|
|
204
|
+
|
|
205
|
+
def bulk_update(self, criteria: Callable[[NoConnectElement], bool], updates: Dict[str, Any]):
|
|
206
|
+
"""
|
|
207
|
+
Update multiple no-connects matching criteria.
|
|
208
|
+
|
|
209
|
+
Args:
|
|
210
|
+
criteria: Function to select no-connects to update
|
|
211
|
+
updates: Dictionary of property updates
|
|
212
|
+
"""
|
|
213
|
+
updated_count = 0
|
|
214
|
+
for no_connect_element in self._no_connects:
|
|
215
|
+
if criteria(no_connect_element):
|
|
216
|
+
for prop, value in updates.items():
|
|
217
|
+
if hasattr(no_connect_element, prop):
|
|
218
|
+
setattr(no_connect_element, prop, value)
|
|
219
|
+
updated_count += 1
|
|
220
|
+
|
|
221
|
+
if updated_count > 0:
|
|
222
|
+
self._mark_modified()
|
|
223
|
+
logger.debug(f"Bulk updated {updated_count} no-connect properties")
|
|
224
|
+
|
|
225
|
+
def clear(self):
|
|
226
|
+
"""Remove all no-connects from collection."""
|
|
227
|
+
self._no_connects.clear()
|
|
228
|
+
self._uuid_index.clear()
|
|
229
|
+
self._position_index.clear()
|
|
230
|
+
self._mark_modified()
|
|
231
|
+
|
|
232
|
+
def _add_to_indexes(self, no_connect_element: NoConnectElement):
|
|
233
|
+
"""Add no-connect to internal indexes."""
|
|
234
|
+
self._no_connects.append(no_connect_element)
|
|
235
|
+
self._uuid_index[no_connect_element.uuid] = no_connect_element
|
|
236
|
+
|
|
237
|
+
# Add to position index
|
|
238
|
+
pos_key = (no_connect_element.position.x, no_connect_element.position.y)
|
|
239
|
+
if pos_key not in self._position_index:
|
|
240
|
+
self._position_index[pos_key] = []
|
|
241
|
+
self._position_index[pos_key].append(no_connect_element)
|
|
242
|
+
|
|
243
|
+
def _remove_from_indexes(self, no_connect_element: NoConnectElement):
|
|
244
|
+
"""Remove no-connect from internal indexes."""
|
|
245
|
+
self._no_connects.remove(no_connect_element)
|
|
246
|
+
del self._uuid_index[no_connect_element.uuid]
|
|
247
|
+
|
|
248
|
+
# Remove from position index
|
|
249
|
+
pos_key = (no_connect_element.position.x, no_connect_element.position.y)
|
|
250
|
+
if pos_key in self._position_index:
|
|
251
|
+
self._position_index[pos_key].remove(no_connect_element)
|
|
252
|
+
if not self._position_index[pos_key]:
|
|
253
|
+
del self._position_index[pos_key]
|
|
254
|
+
|
|
255
|
+
def _mark_modified(self):
|
|
256
|
+
"""Mark collection as modified."""
|
|
257
|
+
self._modified = True
|
|
258
|
+
|
|
259
|
+
# Collection interface methods
|
|
260
|
+
def __len__(self) -> int:
|
|
261
|
+
"""Return number of no-connects."""
|
|
262
|
+
return len(self._no_connects)
|
|
263
|
+
|
|
264
|
+
def __iter__(self) -> Iterator[NoConnectElement]:
|
|
265
|
+
"""Iterate over no-connects."""
|
|
266
|
+
return iter(self._no_connects)
|
|
267
|
+
|
|
268
|
+
def __getitem__(self, index: int) -> NoConnectElement:
|
|
269
|
+
"""Get no-connect by index."""
|
|
270
|
+
return self._no_connects[index]
|
|
271
|
+
|
|
272
|
+
def __bool__(self) -> bool:
|
|
273
|
+
"""Return True if collection has no-connects."""
|
|
274
|
+
return len(self._no_connects) > 0
|
kicad_sch_api/core/schematic.py
CHANGED
|
@@ -18,13 +18,18 @@ from ..utils.validation import SchematicValidator, ValidationError, ValidationIs
|
|
|
18
18
|
from .components import ComponentCollection
|
|
19
19
|
from .formatter import ExactFormatter
|
|
20
20
|
from .junctions import JunctionCollection
|
|
21
|
+
from .labels import LabelCollection
|
|
22
|
+
from .nets import NetCollection
|
|
23
|
+
from .no_connects import NoConnectCollection
|
|
21
24
|
from .parser import SExpressionParser
|
|
25
|
+
from .texts import TextCollection
|
|
22
26
|
from .types import (
|
|
23
27
|
HierarchicalLabelShape,
|
|
24
28
|
Junction,
|
|
25
29
|
Label,
|
|
26
30
|
LabelType,
|
|
27
31
|
Net,
|
|
32
|
+
NoConnect,
|
|
28
33
|
Point,
|
|
29
34
|
SchematicSymbol,
|
|
30
35
|
Sheet,
|
|
@@ -136,6 +141,97 @@ class Schematic:
|
|
|
136
141
|
junctions.append(junction)
|
|
137
142
|
self._junctions = JunctionCollection(junctions)
|
|
138
143
|
|
|
144
|
+
# Initialize text collection
|
|
145
|
+
text_data = self._data.get("texts", [])
|
|
146
|
+
texts = []
|
|
147
|
+
for text_dict in text_data:
|
|
148
|
+
if isinstance(text_dict, dict):
|
|
149
|
+
# Convert dict to Text object
|
|
150
|
+
position = text_dict.get("position", {"x": 0, "y": 0})
|
|
151
|
+
if isinstance(position, dict):
|
|
152
|
+
pos = Point(position["x"], position["y"])
|
|
153
|
+
elif isinstance(position, (list, tuple)):
|
|
154
|
+
pos = Point(position[0], position[1])
|
|
155
|
+
else:
|
|
156
|
+
pos = position
|
|
157
|
+
|
|
158
|
+
text = Text(
|
|
159
|
+
uuid=text_dict.get("uuid", str(uuid.uuid4())),
|
|
160
|
+
position=pos,
|
|
161
|
+
text=text_dict.get("text", ""),
|
|
162
|
+
rotation=text_dict.get("rotation", 0.0),
|
|
163
|
+
size=text_dict.get("size", 1.27),
|
|
164
|
+
exclude_from_sim=text_dict.get("exclude_from_sim", False),
|
|
165
|
+
)
|
|
166
|
+
texts.append(text)
|
|
167
|
+
self._texts = TextCollection(texts)
|
|
168
|
+
|
|
169
|
+
# Initialize label collection
|
|
170
|
+
label_data = self._data.get("labels", [])
|
|
171
|
+
labels = []
|
|
172
|
+
for label_dict in label_data:
|
|
173
|
+
if isinstance(label_dict, dict):
|
|
174
|
+
# Convert dict to Label object
|
|
175
|
+
position = label_dict.get("position", {"x": 0, "y": 0})
|
|
176
|
+
if isinstance(position, dict):
|
|
177
|
+
pos = Point(position["x"], position["y"])
|
|
178
|
+
elif isinstance(position, (list, tuple)):
|
|
179
|
+
pos = Point(position[0], position[1])
|
|
180
|
+
else:
|
|
181
|
+
pos = position
|
|
182
|
+
|
|
183
|
+
label = Label(
|
|
184
|
+
uuid=label_dict.get("uuid", str(uuid.uuid4())),
|
|
185
|
+
position=pos,
|
|
186
|
+
text=label_dict.get("text", ""),
|
|
187
|
+
label_type=LabelType(label_dict.get("label_type", "local")),
|
|
188
|
+
rotation=label_dict.get("rotation", 0.0),
|
|
189
|
+
size=label_dict.get("size", 1.27),
|
|
190
|
+
shape=HierarchicalLabelShape(label_dict.get("shape")) if label_dict.get("shape") else None,
|
|
191
|
+
)
|
|
192
|
+
labels.append(label)
|
|
193
|
+
self._labels = LabelCollection(labels)
|
|
194
|
+
|
|
195
|
+
# Initialize hierarchical labels collection (filter from labels)
|
|
196
|
+
hierarchical_labels = [label for label in labels if label.label_type == LabelType.HIERARCHICAL]
|
|
197
|
+
self._hierarchical_labels = LabelCollection(hierarchical_labels)
|
|
198
|
+
|
|
199
|
+
# Initialize no-connect collection
|
|
200
|
+
no_connect_data = self._data.get("no_connects", [])
|
|
201
|
+
no_connects = []
|
|
202
|
+
for no_connect_dict in no_connect_data:
|
|
203
|
+
if isinstance(no_connect_dict, dict):
|
|
204
|
+
# Convert dict to NoConnect object
|
|
205
|
+
position = no_connect_dict.get("position", {"x": 0, "y": 0})
|
|
206
|
+
if isinstance(position, dict):
|
|
207
|
+
pos = Point(position["x"], position["y"])
|
|
208
|
+
elif isinstance(position, (list, tuple)):
|
|
209
|
+
pos = Point(position[0], position[1])
|
|
210
|
+
else:
|
|
211
|
+
pos = position
|
|
212
|
+
|
|
213
|
+
no_connect = NoConnect(
|
|
214
|
+
uuid=no_connect_dict.get("uuid", str(uuid.uuid4())),
|
|
215
|
+
position=pos,
|
|
216
|
+
)
|
|
217
|
+
no_connects.append(no_connect)
|
|
218
|
+
self._no_connects = NoConnectCollection(no_connects)
|
|
219
|
+
|
|
220
|
+
# Initialize net collection
|
|
221
|
+
net_data = self._data.get("nets", [])
|
|
222
|
+
nets = []
|
|
223
|
+
for net_dict in net_data:
|
|
224
|
+
if isinstance(net_dict, dict):
|
|
225
|
+
# Convert dict to Net object
|
|
226
|
+
net = Net(
|
|
227
|
+
name=net_dict.get("name", ""),
|
|
228
|
+
components=net_dict.get("components", []),
|
|
229
|
+
wires=net_dict.get("wires", []),
|
|
230
|
+
labels=net_dict.get("labels", []),
|
|
231
|
+
)
|
|
232
|
+
nets.append(net)
|
|
233
|
+
self._nets = NetCollection(nets)
|
|
234
|
+
|
|
139
235
|
# Track modifications for save optimization
|
|
140
236
|
self._modified = False
|
|
141
237
|
self._last_save_time = None
|
|
@@ -145,7 +241,10 @@ class Schematic:
|
|
|
145
241
|
self._total_operation_time = 0.0
|
|
146
242
|
|
|
147
243
|
logger.debug(
|
|
148
|
-
f"Schematic initialized with {len(self._components)} components, {len(self._wires)} wires,
|
|
244
|
+
f"Schematic initialized with {len(self._components)} components, {len(self._wires)} wires, "
|
|
245
|
+
f"{len(self._junctions)} junctions, {len(self._texts)} texts, {len(self._labels)} labels, "
|
|
246
|
+
f"{len(self._hierarchical_labels)} hierarchical labels, {len(self._no_connects)} no-connects, "
|
|
247
|
+
f"and {len(self._nets)} nets"
|
|
149
248
|
)
|
|
150
249
|
|
|
151
250
|
@classmethod
|
|
@@ -276,7 +375,42 @@ class Schematic:
|
|
|
276
375
|
@property
|
|
277
376
|
def modified(self) -> bool:
|
|
278
377
|
"""Whether schematic has been modified since last save."""
|
|
279
|
-
return
|
|
378
|
+
return (
|
|
379
|
+
self._modified
|
|
380
|
+
or self._components._modified
|
|
381
|
+
or self._wires._modified
|
|
382
|
+
or self._junctions._modified
|
|
383
|
+
or self._texts._modified
|
|
384
|
+
or self._labels._modified
|
|
385
|
+
or self._hierarchical_labels._modified
|
|
386
|
+
or self._no_connects._modified
|
|
387
|
+
or self._nets._modified
|
|
388
|
+
)
|
|
389
|
+
|
|
390
|
+
@property
|
|
391
|
+
def texts(self) -> TextCollection:
|
|
392
|
+
"""Collection of all text elements in the schematic."""
|
|
393
|
+
return self._texts
|
|
394
|
+
|
|
395
|
+
@property
|
|
396
|
+
def labels(self) -> LabelCollection:
|
|
397
|
+
"""Collection of all label elements in the schematic."""
|
|
398
|
+
return self._labels
|
|
399
|
+
|
|
400
|
+
@property
|
|
401
|
+
def hierarchical_labels(self) -> LabelCollection:
|
|
402
|
+
"""Collection of all hierarchical label elements in the schematic."""
|
|
403
|
+
return self._hierarchical_labels
|
|
404
|
+
|
|
405
|
+
@property
|
|
406
|
+
def no_connects(self) -> NoConnectCollection:
|
|
407
|
+
"""Collection of all no-connect elements in the schematic."""
|
|
408
|
+
return self._no_connects
|
|
409
|
+
|
|
410
|
+
@property
|
|
411
|
+
def nets(self) -> NetCollection:
|
|
412
|
+
"""Collection of all electrical nets in the schematic."""
|
|
413
|
+
return self._nets
|
|
280
414
|
|
|
281
415
|
# Pin positioning methods (migrated from circuit-synth)
|
|
282
416
|
def get_component_pin_position(self, reference: str, pin_number: str) -> Optional[Point]:
|