"""Base types for KiCad S-expressions - fundamental elements with no cross-dependencies."""
from dataclasses import dataclass, field
from typing import List, Optional
from .base_element import KiCadFloat, KiCadObject, KiCadStr, OptionalFlag
from .enums import PadShape, StrokeType
from .sexpr_parser import SExpr
[docs]
@dataclass
class Anchor(KiCadObject):
"""Anchor pad shape definition for custom pads.
The 'anchor' token defines the anchor pad shape of a custom pad in the format::
(anchor PAD_SHAPE)
Args:
pad_shape: Anchor pad shape (rect or circle)
"""
__token_name__ = "anchor"
pad_shape: PadShape = field(
default=PadShape.RECT,
metadata={"description": "Anchor pad shape (rect or circle)"},
)
[docs]
@dataclass
class Xy(KiCadObject):
"""2D coordinate definition token.
The 'xy' token defines a 2D coordinate point in the format:
(xy X Y)
Args:
x: Horizontal coordinate
y: Vertical coordinate
"""
__token_name__ = "xy"
x: float = field(default=0.0, metadata={"description": "Horizontal coordinate"})
y: float = field(default=0.0, metadata={"description": "Vertical coordinate"})
[docs]
@dataclass
class Xyz(KiCadObject):
"""3D coordinate definition token.
The 'xyz' token defines 3D coordinates in the format:
(xyz X Y Z)
Args:
x: X coordinate
y: Y coordinate
z: Z coordinate
"""
__token_name__ = "xyz"
x: float = field(default=0.0, metadata={"description": "X coordinate"})
y: float = field(default=0.0, metadata={"description": "Y coordinate"})
z: float = field(default=0.0, metadata={"description": "Z coordinate"})
[docs]
@dataclass
class Pts(KiCadObject):
"""Coordinate point list definition token.
The 'pts' token defines a list of coordinate points in the format:
(pts
(xy X Y)
...
(xy X Y)
)
Where each xy token defines a single X and Y coordinate pair.
The number of points is determined by the object type.
Args:
points: List of 2D coordinate points
"""
__token_name__ = "pts"
points: List[Xy] = field(
default_factory=list, metadata={"description": "List of 2D coordinate points"}
)
[docs]
@dataclass
class AtXY(KiCadObject):
"""Position identifier token for elements that only use X and Y coordinates.
The 'at' token defines positional coordinates in the format:
(at X Y)
Used for elements like junctions that don't have rotation.
Args:
x: Horizontal position of the object
y: Vertical position of the object
"""
__token_name__ = "at"
x: float = field(
default=0.0,
metadata={"description": "Horizontal position of the object"},
)
y: float = field(
default=0.0, metadata={"description": "Vertical position of the object"}
)
[docs]
@dataclass
class At(KiCadObject):
"""Position identifier token that defines positional coordinates and rotation of an object.
The 'at' token defines the positional coordinates in the format:
(at X Y [ANGLE])
Note:
Symbol text ANGLEs are stored in tenth's of a degree. All other ANGLEs are stored in degrees.
For 3D model positioning, use ModelAt class which supports (at (xyz X Y Z)) format.
Args:
x: Horizontal position of the object
y: Vertical position of the object
angle: Rotational angle of the object
"""
__token_name__ = "at"
x: float = field(
default=0.0,
metadata={"description": "Horizontal position of the object"},
)
y: float = field(
default=0.0, metadata={"description": "Vertical position of the object"}
)
angle: Optional[float] = field(
default=0.0,
metadata={"description": "Rotational angle of the object"},
)
[docs]
@dataclass
class Center(KiCadObject):
"""Center point definition token.
The 'center' token defines a center point in the format::
(center X Y)
Args:
x: Horizontal position of the center point
y: Vertical position of the center point
"""
__token_name__ = "center"
x: float = field(
default=0.0, metadata={"description": "Horizontal position of the center point"}
)
y: float = field(
default=0.0, metadata={"description": "Vertical position of the center point"}
)
[docs]
@dataclass
class Color(KiCadObject):
"""Color definition token.
The 'color' token defines color values in the format::
(color R G B A)
Args:
r: Red color component (0-255)
g: Green color component (0-255)
b: Blue color component (0-255)
a: Alpha component (0-255)
"""
__token_name__ = "color"
r: int = field(default=0, metadata={"description": "Red color component (0-255)"})
g: int = field(default=0, metadata={"description": "Green color component (0-255)"})
b: int = field(default=0, metadata={"description": "Blue color component (0-255)"})
a: int = field(default=0, metadata={"description": "Alpha component (0-255)"})
[docs]
@dataclass
class End(KiCadObject):
"""End point definition token.
The 'end' token defines an end point in the format::
(end X Y)
Args:
x: Horizontal position of the end point
y: Vertical position of the end point
corner: Corner reference (optional)
"""
__token_name__ = "end"
x: float = field(
default=0.0, metadata={"description": "Horizontal position of the end point"}
)
y: float = field(
default=0.0, metadata={"description": "Vertical position of the end point"}
)
corner: Optional[str] = field(
default=None, metadata={"description": "Corner reference", "required": False}
)
[docs]
@dataclass
class Mid(KiCadObject):
"""Mid point definition token.
The 'mid' token defines a mid point in the format::
(mid X Y)
Args:
x: Horizontal position of the mid point
y: Vertical position of the mid point
"""
__token_name__ = "mid"
x: float = field(
default=0.0, metadata={"description": "Horizontal position of the mid point"}
)
y: float = field(
default=0.0, metadata={"description": "Vertical position of the mid point"}
)
[docs]
@dataclass
class Type(KiCadObject):
"""Type definition token.
The 'type' token defines a type value in the format:
(type VALUE)
Args:
value: Type value
"""
__token_name__ = "type"
value: str = field(default="", metadata={"description": "Type value"})
[docs]
def to_sexpr(self) -> SExpr:
"""Custom serialization to ensure type values are never quoted."""
return [self.__token_name__, self.value]
[docs]
@dataclass
class Fill(KiCadObject):
"""Fill definition token.
The 'fill' token defines how schematic and symbol library graphical items are filled in the format:
(fill
(type none | outline | background)
(color R G B A)
)
This represents the nested structure exactly as it appears in the S-expression files.
Args:
type: Fill type specification (optional)
color: Fill color specification (optional)
"""
__token_name__ = "fill"
type: Optional[Type] = field(
default=None,
metadata={"description": "Fill type specification", "required": False},
)
color: Optional[Color] = field(
default=None,
metadata={"description": "Fill color specification", "required": False},
)
[docs]
@dataclass
class Layer(KiCadObject):
"""Layer definition token.
The 'layer' token defines layer information in the format::
(layer "NAME" | dielectric NUMBER (type "DESCRIPTION")
[(color "COLOR")] [(thickness THICKNESS)]
[(material "MATERIAL")] [(epsilon_r VALUE)]
[(loss_tangent VALUE)])
For simple layer references:
(layer "LAYER_NAME")
Args:
name: Layer name or 'dielectric'
number: Layer stack number (optional)
type: Layer type description (optional)
color: Layer color as string (optional)
thickness: Layer thickness value (optional)
material: Material name (optional)
epsilon_r: Dielectric constant value (optional)
loss_tangent: Loss tangent value (optional)
"""
__token_name__ = "layer"
name: str = field(
default="", metadata={"description": "Layer name or 'dielectric'"}
)
number: Optional[int] = field(
default=None, metadata={"description": "Layer stack number", "required": False}
)
type: Optional[str] = field(
default=None,
metadata={"description": "Layer type description", "required": False},
)
color: Optional[str] = field(
default=None,
metadata={"description": "Layer color as string", "required": False},
)
thickness: Optional[float] = field(
default=None,
metadata={"description": "Layer thickness value", "required": False},
)
material: Optional[str] = field(
default=None, metadata={"description": "Material name", "required": False}
)
epsilon_r: Optional[float] = field(
default=None, # 4,5 nomally
metadata={"description": "Dielectric constant value", "required": False},
)
loss_tangent: Optional[float] = field(
default=None, metadata={"description": "Loss tangent value", "required": False}
)
[docs]
@dataclass
class Offset(KiCadObject):
"""Offset definition token.
The 'offset' token defines an offset position in the format:
(offset X Y)
Args:
x: Horizontal offset coordinate
y: Vertical offset coordinate
"""
__token_name__ = "offset"
x: float = field(
default=0.0, metadata={"description": "Horizontal offset coordinate"}
)
y: float = field(
default=0.0, metadata={"description": "Vertical offset coordinate"}
)
[docs]
@dataclass
class Pos(KiCadObject):
"""Position definition token.
The 'pos' token defines a position in the format:
(pos X Y)
Args:
x: Horizontal position coordinate
y: Vertical position coordinate
corner: Corner reference (optional)
"""
__token_name__ = "pos"
x: float = field(
default=0.0, metadata={"description": "Horizontal position coordinate"}
)
y: float = field(
default=0.0, metadata={"description": "Vertical position coordinate"}
)
corner: Optional[str] = field(
default=None, metadata={"description": "Corner reference", "required": False}
)
[docs]
@dataclass
class Size(KiCadObject):
"""Size definition token.
The 'size' token defines width and height dimensions in the format:
(size WIDTH HEIGHT)
Args:
width: Width dimension
height: Height dimension
"""
__token_name__ = "size"
width: float = field(default=0.0, metadata={"description": "Width dimension"})
height: float = field(default=0.0, metadata={"description": "Height dimension"})
[docs]
@dataclass
class Start(KiCadObject):
"""Start point definition token.
The 'start' token defines a start point in the format:
(start X Y)
Args:
x: Horizontal position of the start point
y: Vertical position of the start point
corner: Corner reference (optional)
"""
__token_name__ = "start"
x: float = field(
default=0.0, metadata={"description": "Horizontal position of the start point"}
)
y: float = field(
default=0.0, metadata={"description": "Vertical position of the start point"}
)
corner: Optional[str] = field(
default=None, metadata={"description": "Corner reference", "required": False}
)
[docs]
@dataclass
class Stroke(KiCadObject):
"""Stroke definition token.
The 'stroke' token defines how the outlines of graphical objects are drawn in the format:
(stroke
(width WIDTH)
(type TYPE)
(color R G B A)
)
This represents the nested structure exactly as it appears in the S-expression files.
Args:
width: Line width specification
type: Stroke line style specification
color: Line color specification (optional)
"""
__token_name__ = "stroke"
width: KiCadFloat = field(
default_factory=lambda: KiCadFloat("width", 0.0),
metadata={"description": "Line width specification"},
)
type: Type = field(
default_factory=lambda: Type(value=StrokeType.SOLID.value),
metadata={"description": "Stroke line style specification"},
)
color: Optional[Color] = field(
default=None,
metadata={"description": "Line color specification", "required": False},
)
[docs]
@dataclass
class Text(KiCadObject):
"""Text content definition token.
The 'text' token defines text content in the format:
(text "TEXT_CONTENT"
(at X Y [ANGLE])
(effects EFFECTS)
)
Args:
content: Text content
at: Position and rotation (optional)
effects: Text effects (optional)
exclude_from_sim: Whether to exclude from simulation (optional)
uuid: Unique identifier (optional)
"""
__token_name__ = "text"
content: str = field(default="", metadata={"description": "Text content"})
at: Optional[At] = field(
default=None,
metadata={"description": "Position and rotation", "required": False},
)
effects: Optional["Effects"] = field(
default=None, metadata={"description": "Text effects", "required": False}
)
exclude_from_sim: Optional[OptionalFlag] = field(
default_factory=lambda: OptionalFlag.create_bool_flag("exclude_from_sim"),
metadata={
"description": "Whether to exclude from simulation",
"required": False,
},
)
uuid: Optional["Uuid"] = field(
default=None,
metadata={"description": "Unique identifier", "required": False},
)
[docs]
@dataclass
class Uuid(KiCadObject):
"""UUID identifier token.
The 'uuid' token defines a universally unique identifier in the format:
(uuid UUID_VALUE)
Args:
value: UUID value
"""
__token_name__ = "uuid"
value: str = field(default="", metadata={"description": "UUID value"})
[docs]
@classmethod
def new_id(cls) -> "Uuid":
"""Generate a new UUID identifier.
Returns:
Uuid: New Uuid object with a generated UUID value
"""
import uuid
return cls(value=str(uuid.uuid4()))
[docs]
@dataclass
class Font(KiCadObject):
"""Font definition token.
The 'font' token defines font properties in the format:
(font [face "FONT_NAME"] [size WIDTH HEIGHT] [thickness THICKNESS] [bold] [italic])
Args:
face: Font face specification (optional)
size: Font size (optional)
thickness: Font thickness (optional)
bold: Bold flag (optional)
italic: Italic flag (optional)
color: Font color (optional)
"""
__token_name__ = "font"
face: Optional[KiCadStr] = field(
default_factory=lambda: KiCadStr("face", "", required=False),
metadata={"description": "Font face specification", "required": False},
)
size: Optional[Size] = field(
default=None, metadata={"description": "Font size", "required": False}
)
thickness: Optional[KiCadFloat] = field(
default_factory=lambda: KiCadFloat("thickness", 0.0, required=False),
metadata={"description": "Font thickness", "required": False},
)
bold: Optional[OptionalFlag] = field(
default_factory=lambda: OptionalFlag.create_bool_flag("bold"),
metadata={"description": "Bold flag", "required": False},
)
italic: Optional[OptionalFlag] = field(
default_factory=lambda: OptionalFlag.create_bool_flag("italic"),
metadata={"description": "Italic flag", "required": False},
)
color: Optional[Color] = field(
default=None,
metadata={"description": "Font color", "required": False},
)
[docs]
@dataclass
class Justify(KiCadObject):
"""Text justification definition token.
The 'justify' token defines text alignment and mirroring in the format::
(justify [left | right | center] [top | bottom | center] [mirror])
Args:
left: Left horizontal justification flag (optional)
right: Right horizontal justification flag (optional)
top: Top vertical justification flag (optional)
bottom: Bottom vertical justification flag (optional)
center: Center justification flag (horizontal or vertical) (optional)
mirror: Mirror text flag (optional)
"""
__token_name__ = "justify"
# Horizontal justification flags
left: Optional[OptionalFlag] = field(
default_factory=lambda: OptionalFlag.create_bool_flag("left"),
metadata={
"description": "Left horizontal justification flag",
"required": False,
},
)
right: Optional[OptionalFlag] = field(
default_factory=lambda: OptionalFlag.create_bool_flag("right"),
metadata={
"description": "Right horizontal justification flag",
"required": False,
},
)
# Vertical justification flags
top: Optional[OptionalFlag] = field(
default_factory=lambda: OptionalFlag.create_bool_flag("top"),
metadata={"description": "Top vertical justification flag", "required": False},
)
bottom: Optional[OptionalFlag] = field(
default_factory=lambda: OptionalFlag.create_bool_flag("bottom"),
metadata={
"description": "Bottom vertical justification flag",
"required": False,
},
)
# Center can be horizontal or vertical - ambiguous in S-expression
center: Optional[OptionalFlag] = field(
default_factory=lambda: OptionalFlag.create_bool_flag("center"),
metadata={
"description": "Center justification flag (horizontal or vertical)",
"required": False,
},
)
# Mirror flag
mirror: Optional[OptionalFlag] = field(
default_factory=lambda: OptionalFlag.create_bool_flag("mirror"),
metadata={"description": "Mirror text flag", "required": False},
)
[docs]
@dataclass
class Effects(KiCadObject):
"""Text effects definition token.
The 'effects' token defines text formatting effects in the format::
(effects
(font [size SIZE] [thickness THICKNESS] [bold] [italic])
[(justify JUSTIFY)]
[hide]
)
Args:
font: Font definition (optional)
justify: Text justification (optional)
hide: Whether text is hidden (optional)
href: Hyperlink reference (optional)
"""
__token_name__ = "effects"
font: Optional[Font] = field(
default=None, metadata={"description": "Font definition", "required": False}
)
justify: Optional[Justify] = field(
default=None,
metadata={"description": "Text justification", "required": False},
)
hide: Optional[OptionalFlag] = field(
default_factory=lambda: OptionalFlag.create_bool_flag("hide"),
metadata={"description": "Whether text is hidden", "required": False},
)
href: Optional[KiCadStr] = field(
default_factory=lambda: KiCadStr("href", "", required=False),
metadata={"description": "Hyperlink reference", "required": False},
)
[docs]
@dataclass
class Property(KiCadObject):
"""Property definition token.
The 'property' token defines properties in two formats:
General properties::
(property "KEY" "VALUE")
Symbol properties::
(property
"KEY"
"VALUE"
(id N)
POSITION_IDENTIFIER
TEXT_EFFECTS
)
Args:
key: Property key name (must be unique)
value: Property value
id: Property ID (optional)
at: Position and rotation (optional)
effects: Text effects (optional)
unlocked: Whether property is unlocked (optional)
layer: Layer assignment (optional)
uuid: Unique identifier (optional)
hide: Hide property flag (optional)
"""
__token_name__ = "property"
key: str = field(
default="", metadata={"description": "Property key name (must be unique)"}
)
value: str = field(default="", metadata={"description": "Property value"})
id: Optional[KiCadStr] = field(
default_factory=lambda: KiCadStr("id", "", required=False),
metadata={"description": "Property ID", "required": False},
)
at: Optional[At] = field(
default=None,
metadata={"description": "Position and rotation", "required": False},
)
effects: Optional[Effects] = field(
default=None, metadata={"description": "Text effects", "required": False}
)
unlocked: Optional[OptionalFlag] = field(
default_factory=lambda: OptionalFlag.create_bool_flag("unlocked"),
metadata={"description": "Whether property is unlocked", "required": False},
)
layer: Optional[Layer] = field(
default=None, metadata={"description": "Layer assignment", "required": False}
)
uuid: Optional[Uuid] = field(
default=None, metadata={"description": "Unique identifier", "required": False}
)
hide: Optional[OptionalFlag] = field(
default_factory=lambda: OptionalFlag.create_bool_flag("hide"),
metadata={"description": "Hide property flag", "required": False},
)
[docs]
@dataclass
class Layers(KiCadObject):
"""Layer list definition token.
The 'layers' token defines a list of layer names in the format::
(layers "F.Cu" "F.Paste" "F.Mask")
(layers "*.Cu" "*.Mask" "F.SilkS")
Used for pad layers, via layers, and other layer specifications.
Attributes:
layers (List[str]): List of layer names
Args:
layers: List of layer names
"""
__token_name__ = "layers"
layers: List[str] = field(
default_factory=list, metadata={"description": "List of layer names"}
)