Skip to content

Commit c44b2be

Browse files
committed
brditems: Add support for options in custom padstack layers
1 parent d9bcafb commit c44b2be

2 files changed

Lines changed: 82 additions & 74 deletions

File tree

src/kiutils/footprint.py

Lines changed: 3 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
from os import path
2323

2424
from kiutils.items.zones import Zone
25-
from kiutils.items.brditems import Teardrops, PadStack
25+
from kiutils.items.brditems import Teardrops, PadStack, PadOptions
2626
from kiutils.items.common import Image, Coordinate, Net, Group, Font, EmbeddedFile
2727
from kiutils.items.dimensions import Dimension
2828
from kiutils.items.fpitems import *
@@ -368,77 +368,6 @@ def _to_sexpr_raw(self):
368368
return expr
369369

370370

371-
@dataclass
372-
class PadOptions:
373-
"""The ``options`` token attributes define the settings used for custom pads. This token is
374-
only used when a custom pad is defined.
375-
376-
Documentation:
377-
https://dev-docs.kicad.org/en/file-formats/sexpr-intro/index.html#_custom_pad_options
378-
"""
379-
380-
clearance: str = "outline"
381-
"""The ``clearance`` token defines the type of clearance used for a custom pad. Valid clearance
382-
types are ``outline`` and ``convexhull``."""
383-
384-
anchor: str = "rect"
385-
"""The ``anchor`` token defines the anchor pad shape of a custom pad. Valid anchor pad shapes
386-
are rect and circle."""
387-
388-
@classmethod
389-
def from_sexpr(cls, exp: list) -> PadOptions:
390-
"""Convert the given S-Expresstion into a PadOptions object
391-
392-
Args:
393-
- exp (list): Part of parsed S-Expression ``(options ...)``
394-
395-
Raises:
396-
- Exception: When given parameter's type is not a list
397-
- Exception: When the first item of the list is not options
398-
399-
Returns:
400-
- PadOptions: Object of the class initialized with the given S-Expression
401-
"""
402-
if not isinstance(exp, list):
403-
raise Exception("Expression does not have the correct type")
404-
405-
if exp[0] != "options":
406-
raise Exception("Expression does not have the correct type")
407-
408-
object = cls()
409-
for item in exp[1:]:
410-
if not isinstance(item, list):
411-
raise ValueError(
412-
f"Expected list property [key, value], got: {item}. Full expression: {exp}"
413-
)
414-
elif item[0] == "clearance":
415-
object.clearance = item[1]
416-
elif item[0] == "anchor":
417-
object.anchor = item[1]
418-
else:
419-
raise ValueError(
420-
f"Unrecognized property key: {item[0]}. Full expression: {item}"
421-
)
422-
423-
return object
424-
425-
def to_sexpr(self, indent: int = 0, newline: bool = False) -> str:
426-
"""Generate the S-Expression representing this object
427-
428-
Args:
429-
- indent (int): Number of whitespaces used to indent the output. Defaults to 0.
430-
- newline (bool): Adds a newline to the end of the output. Defaults to False.
431-
432-
Returns:
433-
- str: S-Expression of this object
434-
"""
435-
raw_expr = self._to_sexpr_raw()
436-
return sexp_to_string(raw_expr)
437-
438-
def _to_sexpr_raw(self):
439-
return ["options", ["clearance", self.clearance], ["anchor", self.anchor]]
440-
441-
442371
@dataclass
443372
class Pad:
444373
"""The ``pad`` token defines a pad in a footprint definition.
@@ -559,7 +488,8 @@ class Pad:
559488
with a thermal relief. If not set, the footprint thermal_gap setting is used."""
560489

561490
customPadOptions: Optional[PadOptions] = None
562-
"""The optional ``customPadOptions`` token defines the options when a custom pad is defined"""
491+
"""The optional ``customPadOptions`` token defines optional shape-specific parameters used to
492+
refine the pad's geometry or behavior."""
563493

564494
# Documentation seems wrong about primitives here. It seems like its just a list
565495
# of graphical objects, but the docu suggests, besides the list, two other params

src/kiutils/items/brditems.py

Lines changed: 79 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2093,6 +2093,77 @@ def _to_sexpr_raw(self):
20932093
return expr
20942094

20952095

2096+
@dataclass
2097+
class PadOptions:
2098+
"""The ``options`` token attributes define the settings used for custom pads. This token is
2099+
only used when a custom pad is defined.
2100+
2101+
Documentation:
2102+
https://dev-docs.kicad.org/en/file-formats/sexpr-intro/index.html#_custom_pad_options
2103+
"""
2104+
2105+
clearance: str = "outline"
2106+
"""The ``clearance`` token defines the type of clearance used for a custom pad. Valid clearance
2107+
types are ``outline`` and ``convexhull``."""
2108+
2109+
anchor: str = "rect"
2110+
"""The ``anchor`` token defines the anchor pad shape of a custom pad. Valid anchor pad shapes
2111+
are rect and circle."""
2112+
2113+
@classmethod
2114+
def from_sexpr(cls, exp: list) -> PadOptions:
2115+
"""Convert the given S-Expresstion into a PadOptions object
2116+
2117+
Args:
2118+
- exp (list): Part of parsed S-Expression ``(options ...)``
2119+
2120+
Raises:
2121+
- Exception: When given parameter's type is not a list
2122+
- Exception: When the first item of the list is not options
2123+
2124+
Returns:
2125+
- PadOptions: Object of the class initialized with the given S-Expression
2126+
"""
2127+
if not isinstance(exp, list):
2128+
raise Exception("Expression does not have the correct type")
2129+
2130+
if exp[0] != "options":
2131+
raise Exception("Expression does not have the correct type")
2132+
2133+
object = cls()
2134+
for item in exp[1:]:
2135+
if not isinstance(item, list):
2136+
raise ValueError(
2137+
f"Expected list property [key, value], got: {item}. Full expression: {exp}"
2138+
)
2139+
elif item[0] == "clearance":
2140+
object.clearance = item[1]
2141+
elif item[0] == "anchor":
2142+
object.anchor = item[1]
2143+
else:
2144+
raise ValueError(
2145+
f"Unrecognized property key: {item[0]}. Full expression: {item}"
2146+
)
2147+
2148+
return object
2149+
2150+
def to_sexpr(self, indent: int = 0, newline: bool = False) -> str:
2151+
"""Generate the S-Expression representing this object
2152+
2153+
Args:
2154+
- indent (int): Number of whitespaces used to indent the output. Defaults to 0.
2155+
- newline (bool): Adds a newline to the end of the output. Defaults to False.
2156+
2157+
Returns:
2158+
- str: S-Expression of this object
2159+
"""
2160+
raw_expr = self._to_sexpr_raw()
2161+
return sexp_to_string(raw_expr)
2162+
2163+
def _to_sexpr_raw(self):
2164+
return ["options", ["clearance", self.clearance], ["anchor", self.anchor]]
2165+
2166+
20962167
@dataclass
20972168
class PadStackLayer:
20982169
"""The ``padstacklayer`` token defines a pad's geometry and thermal/zoning
@@ -2137,6 +2208,10 @@ class PadStackLayer:
21372208
"""The optional ``primitives`` token defines the drawing objects and options used to define
21382209
a custom pad on this layer."""
21392210

2211+
options: Optional[PadOptions] = None
2212+
"""The optional ``options`` token defines optional shape-specific parameters used to
2213+
refine the pad's geometry or behavior on this layer."""
2214+
21402215
@classmethod
21412216
def from_sexpr(cls, exp: list) -> PadStackLayer:
21422217
"""Convert the given S-Expresstion into a PadStackLayer object
@@ -2183,6 +2258,8 @@ def from_sexpr(cls, exp: list) -> PadStackLayer:
21832258
object.clearance = item[1]
21842259
elif item[0] == "zone_connect":
21852260
object.zone_connect = item[1]
2261+
elif item[0] == "options":
2262+
object.options = PadOptions().from_sexpr(item)
21862263
elif item[0] == "primitives":
21872264
for primitive in item[1:]:
21882265
if primitive[0] == "gr_text":
@@ -2237,7 +2314,8 @@ def _to_sexpr_raw(self):
22372314
if self.offset[0] != 0 or self.offset[1] != 0:
22382315
expr.append(["offset", self.offset[0], self.offset[1]])
22392316

2240-
# TODO options
2317+
if self.options is not None:
2318+
expr.append(self.options._to_sexpr_raw())
22412319

22422320
if self.primitives is not None and len(self.primitives) > 0:
22432321
primitives = ["primitives"]

0 commit comments

Comments
 (0)