Source code for kicadfiles.footprint_library
"""Footprint library elements for KiCad S-expressions - footprint management and properties."""
from dataclasses import dataclass, field
from typing import List, Optional, Union
from .advanced_graphics import FpArc, FpCircle, FpCurve, FpLine, FpPoly, FpRect, FpText
from .base_element import (
KiCadFloat,
KiCadInt,
KiCadObject,
KiCadStr,
OptionalFlag,
ParseStrictness,
)
from .base_types import At, Layer, Property, Uuid, Xyz
from .pad_and_drill import Pad
[docs]
@dataclass
class FileData(KiCadObject):
"""Data definition token for embedded files.
The 'data' token defines base64 encoded file data in the format::
(data |DATA_LINE1|
|DATA_LINE2|
...)
Args:
lines: List of base64 encoded data lines
"""
__token_name__ = "data"
lines: List[str] = field(
default_factory=list,
metadata={"description": "List of base64 encoded data lines"},
)
[docs]
@dataclass
class EmbeddedFile(KiCadObject):
"""Embedded file definition token.
The 'file' token defines an embedded file in the format::
(file
(name "FILENAME")
(type TYPE)
[(data |DATA|)]
[(checksum "CHECKSUM")]
)
Args:
name: File name token
type: File type token
data: Base64 encoded file data token (optional)
checksum: File checksum token (optional)
"""
__token_name__ = "file"
name: KiCadStr = field(
default_factory=lambda: KiCadStr("name", ""),
metadata={"description": "File name token"},
)
type: KiCadStr = field(
default_factory=lambda: KiCadStr("type", ""),
metadata={"description": "File type token"},
)
data: Optional[FileData] = field(
default=None,
metadata={"description": "Base64 encoded file data token", "required": False},
)
checksum: Optional[KiCadStr] = field(
default_factory=lambda: KiCadStr("checksum", "", required=False),
metadata={"description": "File checksum token", "required": False},
)
[docs]
@dataclass
class EmbeddedFiles(KiCadObject):
"""Embedded files container definition token.
The 'embedded_files' token defines a container for embedded files in the format::
(embedded_files
(file ...)
...
)
Args:
files: List of embedded files
"""
__token_name__ = "embedded_files"
files: List[EmbeddedFile] = field(
default_factory=list, metadata={"description": "List of embedded files"}
)
[docs]
@dataclass
class Attr(KiCadObject):
"""Footprint attributes definition token.
The 'attr' token defines footprint attributes in the format::
(attr
TYPE
[board_only]
[exclude_from_pos_files]
[exclude_from_bom]
)
Args:
type: Footprint type (smd | through_hole)
board_only: Whether footprint is only defined in board (optional)
exclude_from_pos_files: Whether to exclude from position files (optional)
exclude_from_bom: Whether to exclude from BOM files (optional)
"""
__token_name__ = "attr"
type: str = field(
default="", metadata={"description": "Footprint type (smd | through_hole)"}
)
board_only: Optional[OptionalFlag] = field(
default_factory=lambda: OptionalFlag.create_bool_flag("board_only"),
metadata={
"description": "Whether footprint is only defined in board",
"required": False,
},
)
exclude_from_pos_files: Optional[OptionalFlag] = field(
default_factory=lambda: OptionalFlag.create_bool_flag("exclude_from_pos_files"),
metadata={
"description": "Whether to exclude from position files",
"required": False,
},
)
exclude_from_bom: Optional[OptionalFlag] = field(
default_factory=lambda: OptionalFlag.create_bool_flag("exclude_from_bom"),
metadata={
"description": "Whether to exclude from BOM files",
"required": False,
},
)
[docs]
@dataclass
class NetTiePadGroups(KiCadObject):
"""Net tie pad groups definition token.
The 'net_tie_pad_groups' token defines groups of pads that are connected in the format::
(net_tie_pad_groups "PAD_LIST" "PAD_LIST" ...)
Args:
groups: List of pad group strings
"""
__token_name__ = "net_tie_pad_groups"
groups: List[str] = field(
default_factory=list, metadata={"description": "List of pad group strings"}
)
[docs]
@dataclass
class ModelAt(KiCadObject):
"""3D model position definition token.
The 'at' token for 3D models in the format:
(at (xyz X Y Z))
Args:
xyz: 3D coordinates for model position
"""
__token_name__ = "at"
xyz: Xyz = field(
default_factory=lambda: Xyz(),
metadata={"description": "3D coordinates for model position"},
)
[docs]
@dataclass
class ModelScale(KiCadObject):
"""3D model scale definition token.
The 'scale' token for 3D models in the format:
(scale (xyz X Y Z))
Args:
xyz: 3D scale factors for model
"""
__token_name__ = "scale"
xyz: Xyz = field(
default_factory=lambda: Xyz(x=1.0, y=1.0, z=1.0),
metadata={"description": "3D scale factors for model"},
)
[docs]
@dataclass
class ModelRotate(KiCadObject):
"""3D model rotation definition token.
The 'rotate' token for 3D models in the format:
(rotate (xyz X Y Z))
Args:
xyz: 3D rotation angles for model
"""
__token_name__ = "rotate"
xyz: Xyz = field(
default_factory=lambda: Xyz(),
metadata={"description": "3D rotation angles for model"},
)
[docs]
@dataclass
class ModelOffset(KiCadObject):
"""3D model offset definition token.
The 'offset' token for 3D models in the format:
(offset (xyz X Y Z))
Args:
xyz: 3D offset coordinates for model
"""
__token_name__ = "offset"
xyz: Xyz = field(
default_factory=lambda: Xyz(),
metadata={"description": "3D offset coordinates for model"},
)
[docs]
@dataclass
class Model(KiCadObject):
"""3D model definition token for footprints.
The 'model' token defines a 3D model associated with a footprint in the format::
(model
"3D_MODEL_FILE"
(at (xyz X Y Z))
(scale (xyz X Y Z))
(rotate (xyz X Y Z))
)
Args:
path: Path and file name of the 3D model
at: 3D position coordinates relative to the footprint (optional)
scale: Model scale factor for each 3D axis (optional)
rotate: Model rotation for each 3D axis relative to the footprint (optional)
offset: Model offset coordinates (optional)
"""
__token_name__ = "model"
path: str = field(
default="", metadata={"description": "Path and file name of the 3D model"}
)
at: Optional[ModelAt] = field(
default=None,
metadata={
"description": "3D position coordinates relative to the footprint",
"required": False,
},
)
scale: Optional[ModelScale] = field(
default=None,
metadata={
"description": "Model scale factor for each 3D axis",
"required": False,
},
)
rotate: Optional[ModelRotate] = field(
default=None,
metadata={
"description": "Model rotation for each 3D axis relative to the footprint",
"required": False,
},
)
offset: Optional[ModelOffset] = field(
default=None,
metadata={"description": "Model offset coordinates", "required": False},
)
[docs]
@dataclass
class Footprint(KiCadObject):
"""Footprint definition token that defines a complete footprint.
The 'footprint' token defines a footprint with all its elements in the format::
(footprint
["LIBRARY_LINK"]
[locked]
[placed]
(layer LAYER_DEFINITIONS)
(tedit TIME_STAMP)
[(uuid UUID)]
[POSITION_IDENTIFIER]
[(descr "DESCRIPTION")]
[(tags "NAME")]
[(property "KEY" "VALUE") ...]
(path "PATH")
[(autoplace_cost90 COST)]
[(autoplace_cost180 COST)]
[(solder_mask_margin MARGIN)]
[(solder_paste_margin MARGIN)]
[(solder_paste_ratio RATIO)]
[(clearance CLEARANCE)]
[(zone_connect CONNECTION_TYPE)]
[(thermal_width WIDTH)]
[(thermal_gap DISTANCE)]
[ATTRIBUTES]
[(private_layers LAYER_DEFINITIONS)]
[(net_tie_pad_groups PAD_GROUP_DEFINITIONS)]
GRAPHIC_ITEMS...
PADS...
ZONES...
GROUPS...
3D_MODEL
)
Args:
library_link: Link to footprint library (optional)
version: File format version (optional)
generator: Generator application (optional)
generator_version: Generator version (optional)
locked: Whether the footprint cannot be edited (optional)
placed: Whether the footprint has been placed (optional)
layer: Layer the footprint is placed on
tedit: Last edit timestamp (optional)
uuid: Unique identifier for board footprints (optional)
at: Position and rotation coordinates (optional)
descr: Description of the footprint (optional)
tags: Search tags for the footprint (optional)
properties: List of footprint properties (optional)
path: Hierarchical path of linked schematic symbol (optional)
attr: Footprint attributes (optional)
autoplace_cost90: Vertical cost for automatic placement (optional)
autoplace_cost180: Horizontal cost for automatic placement (optional)
solder_mask_margin: Solder mask distance from pads (optional)
solder_paste_margin: Solder paste distance from pads (optional)
solder_paste_ratio: Percentage of pad size for solder paste (optional)
clearance: Clearance to board copper objects (optional)
zone_connect: How pads connect to filled zones (optional)
thermal_width: Thermal relief spoke width (optional)
thermal_gap: Distance from pad to zone for thermal relief (optional)
private_layers: List of private layers (optional)
net_tie_pad_groups: Net tie pad groups (optional)
pads: List of pads (optional)
models: List of 3D models (optional)
fp_elements: List of footprint graphical elements (optional)
embedded_fonts: Embedded fonts settings (optional)
embedded_files: Embedded files container (optional)
"""
__token_name__ = "footprint"
__legacy_token_names__ = ["module"]
library_link: Optional[str] = field(
default=None,
metadata={"description": "Link to footprint library", "required": False},
)
version: Optional[KiCadInt] = field(
default_factory=lambda: KiCadInt("version", 0, required=False),
metadata={"description": "File format version", "required": False},
)
generator: Optional[KiCadStr] = field(
default_factory=lambda: KiCadStr("generator", "", required=False),
metadata={"description": "Generator application", "required": False},
)
generator_version: Optional[KiCadStr] = field(
default_factory=lambda: KiCadStr("generator_version", "", required=False),
metadata={"description": "Generator version", "required": False},
)
locked: Optional[OptionalFlag] = field(
default_factory=lambda: OptionalFlag.create_bool_flag("locked"),
metadata={
"description": "Whether the footprint cannot be edited",
"required": False,
},
)
placed: Optional[OptionalFlag] = field(
default_factory=lambda: OptionalFlag.create_bool_flag("placed"),
metadata={
"description": "Whether the footprint has been placed",
"required": False,
},
)
layer: Layer = field(
default_factory=lambda: Layer(),
metadata={"description": "Layer the footprint is placed on"},
)
tedit: Optional[KiCadStr] = field(
default_factory=lambda: KiCadStr("tedit", "0", required=False),
metadata={"description": "Last edit timestamp", "required": False},
)
uuid: Optional[Uuid] = field(
default=None,
metadata={
"description": "Unique identifier for board footprints",
"required": False,
},
)
at: Optional[At] = field(
default=None,
metadata={
"description": "Position and rotation coordinates",
"required": False,
},
)
descr: Optional[KiCadStr] = field(
default_factory=lambda: KiCadStr("descr", "", required=False),
metadata={"description": "Description of the footprint", "required": False},
)
tags: Optional[KiCadStr] = field(
default_factory=lambda: KiCadStr("tags", "", required=False),
metadata={"description": "Search tags for the footprint", "required": False},
)
properties: Optional[List[Property]] = field(
default_factory=list,
metadata={"description": "List of footprint properties", "required": False},
)
path: Optional[str] = field(
default=None,
metadata={
"description": "Hierarchical path of linked schematic symbol",
"required": False,
},
)
attr: Optional[Attr] = field(
default=None,
metadata={"description": "Footprint attributes", "required": False},
)
autoplace_cost90: Optional[int] = field(
default=None,
metadata={
"description": "Vertical cost for automatic placement",
"required": False,
},
)
autoplace_cost180: Optional[int] = field(
default=None,
metadata={
"description": "Horizontal cost for automatic placement",
"required": False,
},
)
solder_mask_margin: Optional[float] = field(
default=None,
metadata={"description": "Solder mask distance from pads", "required": False},
)
solder_paste_margin: Optional[float] = field(
default=None,
metadata={"description": "Solder paste distance from pads", "required": False},
)
solder_paste_ratio: Optional[float] = field(
default=None,
metadata={
"description": "Percentage of pad size for solder paste",
"required": False,
},
)
clearance: Optional[KiCadFloat] = field(
default_factory=lambda: KiCadFloat("clearance", 0.0, required=False),
metadata={
"description": "Clearance to board copper objects",
"required": False,
},
)
zone_connect: Optional[int] = field(
default=None,
metadata={"description": "How pads connect to filled zones", "required": False},
)
thermal_width: Optional[KiCadFloat] = field(
default_factory=lambda: KiCadFloat("thermal_width", 0.0, required=False),
metadata={"description": "Thermal relief spoke width", "required": False},
)
thermal_gap: Optional[KiCadFloat] = field(
default_factory=lambda: KiCadFloat("thermal_gap", 0.0, required=False),
metadata={
"description": "Distance from pad to zone for thermal relief",
"required": False,
},
)
private_layers: Optional[List[str]] = field(
default_factory=list,
metadata={"description": "List of private layers", "required": False},
)
net_tie_pad_groups: Optional[NetTiePadGroups] = field(
default=None, metadata={"description": "Net tie pad groups", "required": False}
)
pads: Optional[List[Pad]] = field(
default_factory=list,
metadata={"description": "List of pads", "required": False},
)
models: Optional[List[Model]] = field(
default_factory=list,
metadata={"description": "List of 3D models", "required": False},
)
fp_elements: Optional[
List[Union[FpArc, FpCircle, FpCurve, FpLine, FpPoly, FpRect, FpText]]
] = field(
default_factory=list,
metadata={
"description": "List of footprint graphical elements",
"required": False,
},
)
embedded_fonts: Optional[OptionalFlag] = field(
default_factory=lambda: OptionalFlag.create_bool_flag("embedded_fonts"),
metadata={"description": "Embedded fonts settings", "required": False},
)
embedded_files: Optional[EmbeddedFiles] = field(
default=None,
metadata={"description": "Embedded files container", "required": False},
)
[docs]
@classmethod
def from_file(
cls,
file_path: str,
strictness: ParseStrictness = ParseStrictness.STRICT,
encoding: str = "utf-8",
) -> "Footprint":
"""Parse from S-expression file - convenience method for footprint operations."""
if not file_path.endswith(".kicad_mod"):
raise ValueError("Unsupported file extension. Expected: .kicad_mod")
with open(file_path, "r", encoding=encoding) as f:
content = f.read()
return cls.from_str(content, strictness)
[docs]
def save_to_file(self, file_path: str, encoding: str = "utf-8") -> None:
"""Save to .kicad_mod file format.
Args:
file_path: Path to write the .kicad_mod file
encoding: File encoding (default: utf-8)
"""
if not file_path.endswith(".kicad_mod"):
raise ValueError("Unsupported file extension. Expected: .kicad_mod")
content = self.to_sexpr_str()
with open(file_path, "w", encoding=encoding) as f:
f.write(content)
[docs]
@dataclass
class Footprints(KiCadObject):
"""Footprints container token.
The 'footprints' token defines a container for multiple footprints in the format::
(footprints
(footprint ...)
...
)
Args:
footprints: List of footprints
"""
__token_name__ = "footprints"
footprints: List[Footprint] = field(
default_factory=list, metadata={"description": "List of footprints"}
)