Skip to content

Commit 2eabfe1

Browse files
committed
boolean cast and sourcefile level searches
1 parent fa55c3c commit 2eabfe1

File tree

5 files changed

+146
-5
lines changed

5 files changed

+146
-5
lines changed

src/skip/collection.py

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,9 @@ def append(self, element):
3838

3939
def _coordinates_for(self, el):
4040
coords = None
41-
if hasattr(el, 'at'):
41+
if hasattr(el, 'at') and el.at is not None:
4242
coords = el.at.value
43-
elif hasattr(el, 'location'):
43+
elif hasattr(el, 'location') and el.location is not None:
4444
coords = el.location.value
4545
return coords
4646

@@ -65,7 +65,28 @@ def within_reach_of(self, element, distance:float):
6565
coords = self._coordinates_for(element)
6666
return list(filter(lambda e: e!=element, self.within_circle(coords[0], coords[1], distance)))
6767

68+
def within_rectangle(self, x1coord:float, y1coord:float, x2coord:float, y2coord:float):
69+
'''
70+
Find all elements of this collection that are within the
71+
rectangle bounded by (x1,y1) - (x2,y2)
72+
'''
73+
retvals = []
74+
if not len(self._elements):
75+
return retvals
6876

77+
xrange = [x1coord, x2coord] if x1coord < x2coord else [x2coord, x1coord]
78+
yrange = [y1coord, y2coord] if y1coord < y2coord else [y2coord, y1coord]
79+
80+
for el in self:
81+
coords = self._coordinates_for(el)
82+
if coords is None:
83+
continue
84+
85+
if coords[0] >= xrange[0] and coords[0] <= xrange[1]:
86+
if coords[1] >= yrange[0] and coords[1] <= yrange[1]:
87+
retvals.append(el)
88+
89+
return retvals
6990
def within_circle(self, xcoord:float, ycoord:float, radius:float):
7091
'''
7192
Find all elements of this collection that are within the
@@ -92,6 +113,20 @@ def within_circle(self, xcoord:float, ycoord:float, radius:float):
92113

93114
return retvals
94115

116+
def between_elements(self, positionedElement1, positionedElement2):
117+
'''
118+
return a list of all elements, between these two, i.e. located
119+
in the rectangle comprised by each of their locations.
120+
121+
@param positionedElement1: some parsed value with an 'at' or 'location'
122+
@param positionedElement2: some parsed value with an 'at' or 'location'
123+
'''
124+
coords1 = self._coordinates_for(positionedElement1)
125+
coords2 = self._coordinates_for(positionedElement2)
126+
if coords1 is None or coords2 is None:
127+
return []
128+
return self.within_rectangle(coords1[0], coords1[1], coords2[0], coords2[1])
129+
95130

96131
def __getitem__(self, index:int):
97132
return self._elements[index]

src/skip/eeschema/lib_symbol.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ def name(self):
6868
return self.wrapped_parsed_value.name
6969

7070
def __repr__(self):
71-
return f"<Pin '{self.name.value}' ({self.number.value}) >"
71+
return f'<Pin {self.number.value} "{self.name.value}">'
7272

7373

7474
class LibSymbolElementWithPins(NamedElementCollection):

src/skip/eeschema/schematic/schematic.py

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,93 @@ def dedicated_wrapper_type_for(self, entity_type:str):
108108

109109
return None
110110

111+
112+
113+
114+
115+
def _searchable_collections(self):
116+
possible_collections = ['symbol', 'label', 'global_label']
117+
colls = []
118+
for pc in possible_collections:
119+
if hasattr(self, pc):
120+
colls.append(getattr(self, pc))
121+
122+
return colls
123+
124+
125+
def within_reach_of(self, element, distance:float):
126+
'''
127+
Find all elements of this collection that are within
128+
reach of passed element.
129+
130+
@param element: element in question, must have .at or .location
131+
132+
@param distance: maximal distance, in coord units
133+
134+
@note: only works for elements that have a
135+
suitable 'at' or 'location' attribute
136+
137+
'''
138+
retvals = []
139+
for col in self._searchable_collections():
140+
retvals.extend(col.within_reach_of(element, distance))
141+
return retvals
142+
143+
def within_rectangle(self, x1coord:float, y1coord:float, x2coord:float, y2coord:float):
144+
'''
145+
Find all elements of this collection that are within the
146+
rectangle bounded by (x1,y1) - (x2,y2)
147+
'''
148+
149+
retvals = []
150+
for col in self._searchable_collections():
151+
retvals.extend(col.within_rectangle(x1coord, y1coord, x2coord, y2coord))
152+
return retvals
153+
154+
155+
def within_circle(self, xcoord:float, ycoord:float, radius:float):
156+
'''
157+
Find all elements of this collection that are within the
158+
circle of radius radius, centered on xcoord, ycoord.
159+
160+
@note: only works for elements that have a
161+
suitable 'at' or 'location' attribute
162+
163+
'''
164+
retvals = []
165+
for col in self._searchable_collections():
166+
retvals.extend(col.within_circle(xcoord, ycoord, radius))
167+
return retvals
168+
169+
def between_elements(self, positionedElement1, positionedElement2):
170+
'''
171+
return a list of all elements, between these two, i.e. located
172+
in the rectangle comprised by each of their locations.
173+
174+
@param positionedElement1: some parsed value with an 'at' or 'location'
175+
@param positionedElement2: some parsed value with an 'at' or 'location'
176+
'''
177+
178+
retvals = []
179+
for col in self._searchable_collections():
180+
retvals.extend(col.between_elements(positionedElement1, positionedElement2))
181+
return retvals
182+
183+
184+
185+
186+
187+
188+
189+
190+
191+
192+
193+
194+
195+
196+
197+
111198
def __str__(self):
112199
if hasattr(self,'title_block'):
113200
return f"{self.__repr__()}\n{str(self.title_block)}"

src/skip/eeschema/schematic/symbol.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,13 @@ def attached_symbols(self):
272272
return all_symbols
273273

274274

275+
@property
276+
def attached_all(self):
277+
all_attached = self.attached_symbols
278+
all_attached.extend(self.attached_global_labels)
279+
all_attached.extend(self.attached_labels)
280+
return all_attached
281+
275282

276283

277284
@property
@@ -410,6 +417,13 @@ def attached_symbols(self):
410417

411418
return all_syms
412419

420+
@property
421+
def attached_all(self):
422+
all_attached = self.attached_symbols
423+
all_attached.extend(self.attached_global_labels)
424+
all_attached.extend(self.attached_labels)
425+
return all_attached
426+
413427

414428
def __str__(self):
415429
return self.__repr__()

src/skip/sexp/parser.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,9 @@ def value(self):
155155
as_bool = self._as_boolean(self._value)
156156
if as_bool is not None:
157157
return as_bool
158-
158+
159+
if isinstance(self._value, sexpdata.Symbol):
160+
return self._value.value()
159161
return self._value
160162

161163
@value.setter
@@ -452,7 +454,10 @@ def _crawlForElementsByType(self, tp:str, elements:list):
452454
return retVal
453455

454456

455-
457+
def __bool__(self):
458+
if self._is_bool_symbol(self._value):
459+
return self._as_boolean(self._value)
460+
return self._value
456461
def _is_bool_symbol(self, v):
457462
if not isinstance(self._value, sexpdata.Symbol):
458463
return False

0 commit comments

Comments
 (0)