Source code for kicadfiles.base_types

"""Base types for KiCad S-expressions - fundamental elements with no cross-dependencies."""

from dataclasses import dataclass, field
from typing import Any, ClassVar, List, Optional

from .base_element import NamedFloat, NamedObject, NamedString, TokenFlag, UnquotedToken
from .enums import PadShape, StrokeType
from .sexpr_parser import SExpr


[docs] @dataclass class Anchor(NamedObject): """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__: ClassVar[str] = "anchor" pad_shape: PadShape = field( default=PadShape.RECT, metadata={"description": "Anchor pad shape (rect or circle)"}, )
[docs] @dataclass class Xy(NamedObject): """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__: ClassVar[str] = "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(NamedObject): """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__: ClassVar[str] = "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(NamedObject): """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__: ClassVar[str] = "pts" points: List[Xy] = field( default_factory=list, metadata={"description": "List of 2D coordinate points"} )
[docs] def xy(self, x: float, y: float) -> "Pts": """Add a coordinate point to the list. Args: x: X coordinate y: Y coordinate Returns: Pts: Self (for method chaining) """ self.points.append(Xy(x=x, y=y)) return self
[docs] @dataclass class AtXY(NamedObject): """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__: ClassVar[str] = "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] def xy(self, x: float, y: float) -> "AtXY": """Set X and Y coordinates. Args: x: Horizontal position y: Vertical position Returns: AtXY: Self (for method chaining) """ self.x = x self.y = y return self
[docs] @dataclass class At(NamedObject): """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__: ClassVar[str] = "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(NamedObject): """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__: ClassVar[str] = "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(NamedObject): """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__: ClassVar[str] = "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(NamedObject): """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__: ClassVar[str] = "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(NamedObject): """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__: ClassVar[str] = "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(NamedObject): """Type definition token. The 'type' token defines a type value in the format: (type VALUE) Args: value: Type value """ __token_name__: ClassVar[str] = "type" value: str = field(default="", metadata={"description": "Type value"})
[docs] def to_sexpr(self) -> SExpr: """Serialize with unquoted value.""" return [self.__token_name__, UnquotedToken(self.value)]
[docs] @dataclass class Fill(NamedObject): """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__: ClassVar[str] = "fill" type: Type = field( default_factory=lambda: Type(value="none"), metadata={"description": "Fill type specification", "required": False}, ) color: Color = field( default_factory=lambda: Color(), metadata={"description": "Fill color specification", "required": False}, )
[docs] @dataclass class Layer(NamedObject): """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__: ClassVar[str] = "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(NamedObject): """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__: ClassVar[str] = "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(NamedObject): """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__: ClassVar[str] = "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(NamedObject): """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__: ClassVar[str] = "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(NamedObject): """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__: ClassVar[str] = "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(NamedObject): """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__: ClassVar[str] = "stroke" width: NamedFloat = field( default_factory=lambda: NamedFloat("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: Color = field( default_factory=lambda: Color(), metadata={"description": "Line color specification", "required": False}, )
[docs] @dataclass class Uuid(NamedObject): """UUID identifier token. The 'uuid' token defines a universally unique identifier in the format: (uuid UUID_VALUE) Args: value: UUID value """ __token_name__: ClassVar[str] = "uuid" value: str = field(default="", metadata={"description": "UUID value"})
[docs] def new_id(self) -> "Uuid": """Generate a new UUID identifier and update this instance. Returns: Uuid: Self (for method chaining) """ import uuid self.value = str(uuid.uuid4()) return self
[docs] @classmethod def create(cls) -> "Uuid": """Create a new UUID identifier (factory method). Returns: Uuid: New Uuid object with a generated UUID value """ import uuid return cls(value=str(uuid.uuid4()))
[docs] @dataclass class Font(NamedObject): """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__: ClassVar[str] = "font" face: NamedString = field( default_factory=lambda: NamedString("face", ""), metadata={"description": "Font face specification", "required": False}, ) size: Optional[Size] = field( default_factory=lambda: Size(1.27, 1.27), metadata={"description": "Font size", "required": False}, ) thickness: NamedFloat = field( default_factory=lambda: NamedFloat("thickness", 0.0), metadata={"description": "Font thickness", "required": False}, ) bold: TokenFlag = field( default_factory=lambda: TokenFlag("bold"), metadata={"description": "Bold flag", "required": False}, ) italic: TokenFlag = field( default_factory=lambda: TokenFlag("italic"), metadata={"description": "Italic flag", "required": False}, ) color: Color = field( default_factory=lambda: Color(), metadata={"description": "Font color", "required": False}, )
[docs] @dataclass class Justify(NamedObject): """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__: ClassVar[str] = "justify" # Horizontal justification flags left: TokenFlag = field( default_factory=lambda: TokenFlag("left"), metadata={ "description": "Left horizontal justification flag", "required": False, }, ) right: TokenFlag = field( default_factory=lambda: TokenFlag("right"), metadata={ "description": "Right horizontal justification flag", "required": False, }, ) # Vertical justification flags top: TokenFlag = field( default_factory=lambda: TokenFlag("top"), metadata={"description": "Top vertical justification flag", "required": False}, ) bottom: TokenFlag = field( default_factory=lambda: TokenFlag("bottom"), metadata={ "description": "Bottom vertical justification flag", "required": False, }, ) # Center can be horizontal or vertical - ambiguous in S-expression center: TokenFlag = field( default_factory=lambda: TokenFlag("center"), metadata={ "description": "Center justification flag (horizontal or vertical)", "required": False, }, ) # Mirror flag mirror: TokenFlag = field( default_factory=lambda: TokenFlag("mirror"), metadata={"description": "Mirror text flag", "required": False}, )
[docs] @dataclass class Effects(NamedObject): """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__: ClassVar[str] = "effects" font: Font = field( default_factory=lambda: Font(), metadata={"description": "Font definition", "required": False}, ) justify: Justify = field( default_factory=lambda: Justify(), metadata={"description": "Text justification", "required": False}, ) hide: TokenFlag = field( default_factory=lambda: TokenFlag("hide"), metadata={"description": "Whether text is hidden", "required": False}, ) href: NamedString = field( default_factory=lambda: NamedString("href", ""), metadata={"description": "Hyperlink reference", "required": False}, )
[docs] @dataclass class Text(NamedObject): """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__: ClassVar[str] = "text" content: str = field(default="", metadata={"description": "Text content"}) at: At = field( default_factory=lambda: At(), metadata={"description": "Position and rotation", "required": False}, ) effects: Effects = field( default_factory=lambda: Effects(), metadata={"description": "Text effects", "required": False}, ) exclude_from_sim: TokenFlag = field( default_factory=lambda: TokenFlag("exclude_from_sim"), metadata={ "description": "Whether to exclude from simulation", "required": False, }, ) uuid: Uuid = field( default_factory=lambda: Uuid(), metadata={"description": "Unique identifier", "required": False}, )
[docs] @dataclass class Property(NamedObject): """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__: ClassVar[str] = "property" key: str = field( default="", metadata={"description": "Property key name (must be unique)"} ) value: str = field(default="", metadata={"description": "Property value"}) id: NamedString = field( default_factory=lambda: NamedString("id", ""), metadata={"description": "Property ID", "required": False}, ) at: At = field( default_factory=lambda: At(), metadata={"description": "Position and rotation", "required": False}, ) effects: Effects = field( default_factory=lambda: Effects(), metadata={"description": "Text effects", "required": False}, ) unlocked: TokenFlag = field( default_factory=lambda: TokenFlag("unlocked"), metadata={"description": "Whether property is unlocked", "required": False}, ) layer: Layer = field( default_factory=lambda: Layer(), metadata={"description": "Layer assignment", "required": False}, ) uuid: Uuid = field( default_factory=lambda: Uuid(), metadata={"description": "Unique identifier", "required": False}, ) hide: TokenFlag = field( default_factory=lambda: TokenFlag("hide"), metadata={"description": "Hide property flag", "required": False}, )
[docs] @dataclass class LayerDefinition: """Board layer definition entry (no token name). Individual layer definition within a 'layers' token in PCB files:: (0 "F.Cu" signal) (9 "F.Adhes" user "F.Adhesive") (31 "F.CrtYd" user "F.Courtyard") Stores the raw list internally and provides properties for access. Args: data: Raw layer data as list [ordinal, name, type, user_name?] """ data: List[Any] = field(default_factory=list)
[docs] def __init__(self, *args: Any, **kwargs: Any) -> None: """Initialize from list or individual parameters.""" if len(args) == 1 and isinstance(args[0], list): self.data = args[0] elif args: self.data = list(args) else: self.data = []
@property def ordinal(self) -> int: """Layer ordinal number.""" return int(self.data[0]) if len(self.data) > 0 else 0 @property def canonical_name(self) -> str: """Canonical layer name.""" return self.data[1] if len(self.data) > 1 else "" @property def layer_type(self) -> str: """Layer type (signal, user, power, mixed, jumper).""" return self.data[2] if len(self.data) > 2 else "signal" @property def user_name(self) -> Optional[str]: """User-defined layer name (optional).""" return self.data[3] if len(self.data) > 3 else None
[docs] @dataclass class BoardLayers(NamedObject): """Board layer definitions for kicad_pcb files. Stores layer definitions as raw lists:: (layers (0 "F.Cu" signal) (2 "B.Cu" signal) ...) Use get_layer(index) to parse a specific layer as LayerDefinition if needed. """ __token_name__: ClassVar[str] = "layers" layer_defs: List[LayerDefinition] = field(default_factory=list) @classmethod def _parse_recursive(cls, cursor: Any) -> "BoardLayers": """Parse and store layer definitions as LayerDefinition objects.""" layer_defs = [ LayerDefinition([str(v) for v in item]) for item in cursor.sexpr[1:] if isinstance(item, list) ] for i in range(1, len(cursor.sexpr)): cursor.parser.mark_used(i) return cls(layer_defs=layer_defs)
[docs] def to_sexpr(self) -> SExpr: """Convert to S-expression format.""" return [self.__token_name__] + [ld.data for ld in self.layer_defs]
[docs] @dataclass class Layers(NamedObject): """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__: ClassVar[str] = "layers" layers: List[str] = field( default_factory=list, metadata={"description": "List of layer names"} )