Examples ======== This section provides practical examples of using KiCadFiles in real-world scenarios. Basic Usage Examples -------------------- Parsing KiCad Files ~~~~~~~~~~~~~~~~~~~ .. code-block:: python from kicadfiles import ( KicadPcb, KicadSch, Footprint, KicadSymbolLib, KicadWks, KicadProject, KiCadDesignRules, FpLibTable, SymLibTable, ParseStrictness ) # Parse a PCB file pcb = KicadPcb.from_file("tests/fixtures/pcb/minimal.kicad_pcb", ParseStrictness.STRICT) print(f"Board has {len(pcb.footprints)} footprints") # Parse a schematic file schematic = KicadSch.from_file("tests/fixtures/schematic/minimal.kicad_sch", ParseStrictness.STRICT) symbol_count = len(schematic.lib_symbols.symbols) if schematic.lib_symbols else 0 print(f"Schematic has {symbol_count} symbols") # Parse a footprint file footprint = Footprint.from_file("tests/fixtures/footprints/small.kicad_mod", ParseStrictness.STRICT) print(f"Footprint has {len(footprint.pads)} pads") # Parse a symbol library file symbol_lib = KicadSymbolLib.from_file("tests/fixtures/symbols/small.kicad_sym", ParseStrictness.STRICT) print(f"Library has {len(symbol_lib.symbols)} symbols") # Parse a worksheet/template file worksheet = KicadWks.from_file("tests/fixtures/worksheets/small.kicad_wks", ParseStrictness.STRICT) print(f"Worksheet loaded successfully") # Parse a project file (JSON format) project = KicadProject.from_file("tests/fixtures/projects/minimal.kicad_pro", ParseStrictness.STRICT) print(f"Project loaded successfully") # Parse design rules file design_rules = KiCadDesignRules.from_file("tests/fixtures/design_rules/minimal.kicad_dru", ParseStrictness.STRICT) print(f"Design rules loaded") # Footprint library table fp_lib_table = FpLibTable.from_file("tests/fixtures/tables/fp-lib-table", ParseStrictness.STRICT) print(f"Footprint library tables loaded") # Symbol library table sym_lib_table = SymLibTable.from_file("tests/fixtures/tables/sym-lib-table", ParseStrictness.STRICT) print(f"Symbol library tables loaded") Creating Objects Programmatically ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. code-block:: python from kicadfiles import At, Size, ParseStrictness # Create basic objects programmatically position = At(x=10.0, y=20.0, angle=90.0) size = Size(width=1.0, height=0.5) print(f"Position: {position}") print(f"Size: {size}") # Convert simple objects to S-expression position_sexpr = position.to_sexpr_str() print(f"Position S-expression: {position_sexpr}") # Parse from S-expression at_obj = At.from_sexpr("(at 10.0 20.0 90.0)", ParseStrictness.STRICT) print(f"Parsed position: {at_obj}") Error Handling Strategies ~~~~~~~~~~~~~~~~~~~~~~~~~ .. code-block:: python from kicadfiles import KicadPcb, ParseStrictness import logging # Configure logging to see warnings logging.basicConfig(level=logging.WARNING) # Test different strictness modes with a valid file # STRICT mode - raises exceptions on errors try: pcb = KicadPcb.from_file("tests/fixtures/pcb/minimal.kicad_pcb", ParseStrictness.STRICT) print("STRICT mode: File parsed successfully") except ValueError as e: print(f"Parsing failed: {e}") # FAILSAFE mode - logs warnings, uses defaults for problems pcb = KicadPcb.from_file("tests/fixtures/pcb/minimal.kicad_pcb", ParseStrictness.FAILSAFE) print("FAILSAFE mode: File parsed with warnings logged for any issues") # SILENT mode - uses defaults without warnings pcb = KicadPcb.from_file("tests/fixtures/pcb/minimal.kicad_pcb", ParseStrictness.SILENT) print("SILENT mode: File parsed silently, using defaults for any problems") Advanced Usage Examples ----------------------- Modifying PCB Files ~~~~~~~~~~~~~~~~~~~ .. code-block:: python from kicadfiles import KicadPcb, Footprint, At, ParseStrictness # Load existing PCB pcb = KicadPcb.from_file("tests/fixtures/pcb/minimal.kicad_pcb", ParseStrictness.STRICT) # Example: Move all footprints by 5mm to the right for footprint in pcb.footprints: if footprint.at: footprint.at.x += 5.0 # Move 5mm to the right print(f"Moved footprint to ({footprint.at.x}, {footprint.at.y})") # Save modified PCB (uncomment to actually save) # pcb.save_to_file("output.kicad_pcb") print("PCB modifications complete") Working with Symbols ~~~~~~~~~~~~~~~~~~~~ .. code-block:: python from kicadfiles import KicadSymbolLib, Symbol, Pin, At, ParseStrictness # Load symbol library lib = KicadSymbolLib.from_file("tests/fixtures/symbols/small.kicad_sym", ParseStrictness.STRICT) # Examine all symbols in the library for i, symbol in enumerate(lib.symbols): pin_count = len(symbol.pins) if symbol.pins else 0 print(f"Symbol {i+1}: {pin_count} pins") # List first few pins (to avoid too much output) if symbol.pins: for j, pin in enumerate(symbol.pins[:3]): pin_name = pin.name.name if pin.name else "unnamed" pin_number = pin.number.number if pin.number else "?" print(f" Pin {pin_number}: {pin_name} at ({pin.at.x}, {pin.at.y})") if len(symbol.pins) > 3: print(f" ... and {len(symbol.pins) - 3} more pins") # Create a new symbol from kicadfiles import Number, PinName from kicadfiles.enums import PinElectricalType, PinGraphicStyle new_symbol = Symbol( library_id="my_new_component", pins=[ Pin( at=At(x=0, y=2.54), electrical_type=PinElectricalType.POWER_IN, graphic_style=PinGraphicStyle.LINE, length=2.54, number=Number(number="1"), name=PinName(name="VCC") ), Pin( at=At(x=0, y=-2.54), electrical_type=PinElectricalType.POWER_IN, graphic_style=PinGraphicStyle.LINE, length=2.54, number=Number(number="2"), name=PinName(name="GND") ) ] ) # Add to library and save (uncomment to actually save) lib.symbols.append(new_symbol) # lib.save_to_file("modified_library.kicad_sym") print(f"Added new symbol, library now has {len(lib.symbols)} symbols") Batch Processing ~~~~~~~~~~~~~~~~ .. code-block:: python import os from pathlib import Path from kicadfiles import Footprint, ParseStrictness # Process all footprints in the fixtures directory footprint_dir = Path("tests/fixtures/footprints/") for footprint_file in footprint_dir.glob("*.kicad_mod"): try: footprint = Footprint.from_file(str(footprint_file), ParseStrictness.STRICT) # Analyze footprint pad_count = len(footprint.pads) if footprint.pads else 0 print(f"{footprint_file.name}: {pad_count} pads") # Example: Add metadata if footprint.properties is None: footprint.properties = [] # Save with modifications (uncomment to actually save) # output_file = Path("processed") / footprint_file.name # footprint.save_to_file(output_file) print(f" Processed footprint with {pad_count} pads") except Exception as e: print(f"Error processing {footprint_file}: {e}") Round-trip Verification ~~~~~~~~~~~~~~~~~~~~~~~ .. code-block:: python from kicadfiles import KicadPcb, ParseStrictness # Load, convert to S-expression, and parse again original_pcb = KicadPcb.from_file("tests/fixtures/pcb/minimal.kicad_pcb", ParseStrictness.STRICT) # Convert to S-expression string sexpr_string = original_pcb.to_sexpr_str() # Parse the S-expression back to object reconstructed_pcb = KicadPcb.from_sexpr(sexpr_string, ParseStrictness.STRICT) # Verify complete equality assert original_pcb.footprints == reconstructed_pcb.footprints assert original_pcb.nets == reconstructed_pcb.nets assert original_pcb.layers == reconstructed_pcb.layers # test the complete object assert original_pcb == reconstructed_pcb print("Round-trip verification successful - objects are identical!")