@@ -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
20972168class 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