Refactor print statements for consistency and clarity across multiple files; remove unnecessary imports and improve code readability in pin_locator.py, routing.py, symbol_creator.py, wire_manager.py, factory.py, ipc_backend.py, kicad_interface.py, resource_definitions.py, test_ipc_backend.py, kicad_process.py, platform_helper.py, test_platform_helper.py. Add French README for KiCAD MCP Server with detailed features, installation instructions, and usage examples.
This commit is contained in:
@@ -5,7 +5,7 @@ Board view command implementations for KiCAD interface
|
||||
import os
|
||||
import pcbnew
|
||||
import logging
|
||||
from typing import Dict, Any, Optional, List, Tuple
|
||||
from typing import Dict, Any, Optional
|
||||
from PIL import Image
|
||||
import io
|
||||
import base64
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
Component-related command implementations for KiCAD interface
|
||||
"""
|
||||
|
||||
import os
|
||||
import pcbnew
|
||||
import logging
|
||||
import math
|
||||
@@ -1519,11 +1518,11 @@ class ComponentCommands:
|
||||
# Convert spacing to nm
|
||||
unit = start_position.get("unit", "mm")
|
||||
scale = 1000000 if unit == "mm" else 25400000 # mm or inch to nm
|
||||
spacing_x_nm = int(spacing_x * scale)
|
||||
spacing_y_nm = int(spacing_y * scale)
|
||||
int(spacing_x * scale)
|
||||
int(spacing_y * scale)
|
||||
|
||||
# Get layer ID
|
||||
layer_id = self.board.GetLayerID(layer)
|
||||
self.board.GetLayerID(layer)
|
||||
|
||||
for row in range(rows):
|
||||
for col in range(columns):
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
from skip import Schematic
|
||||
import os
|
||||
import uuid
|
||||
import logging
|
||||
from pathlib import Path
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
from skip import Schematic
|
||||
import os
|
||||
import logging
|
||||
from pathlib import Path
|
||||
from typing import Optional
|
||||
@@ -261,7 +260,7 @@ class ConnectionManager:
|
||||
# Create wire stub using WireManager
|
||||
wire_success = WireManager.add_wire(schematic_path, pin_loc, stub_end)
|
||||
if not wire_success:
|
||||
logger.error(f"Failed to create wire stub for net connection")
|
||||
logger.error("Failed to create wire stub for net connection")
|
||||
return False
|
||||
|
||||
# Add label at the end of the stub using WireManager
|
||||
|
||||
@@ -5,7 +5,7 @@ Design rules command implementations for KiCAD interface
|
||||
import os
|
||||
import pcbnew
|
||||
import logging
|
||||
from typing import Dict, Any, Optional, List, Tuple
|
||||
from typing import Dict, Any, Optional, Tuple
|
||||
import json
|
||||
|
||||
logger = logging.getLogger("kicad_interface")
|
||||
@@ -185,8 +185,6 @@ class DesignRuleCommands:
|
||||
import subprocess
|
||||
import json
|
||||
import tempfile
|
||||
import platform
|
||||
import shutil
|
||||
|
||||
try:
|
||||
if not self.board:
|
||||
|
||||
@@ -12,7 +12,7 @@ import re
|
||||
import uuid
|
||||
import logging
|
||||
from pathlib import Path
|
||||
from typing import Dict, List, Optional, Tuple
|
||||
from typing import List, Optional
|
||||
|
||||
logger = logging.getLogger("kicad_interface")
|
||||
|
||||
@@ -575,6 +575,6 @@ if __name__ == "__main__":
|
||||
if block and "LM2596S-12" in block:
|
||||
print(f" OK: LM2596S-5 includes parent LM2596S-12 ({len(block)} chars)")
|
||||
else:
|
||||
print(f" FAIL: extends not resolved")
|
||||
print(" FAIL: extends not resolved")
|
||||
|
||||
print("\nAll tests passed!")
|
||||
|
||||
@@ -5,8 +5,7 @@ Export command implementations for KiCAD interface
|
||||
import os
|
||||
import pcbnew
|
||||
import logging
|
||||
from typing import Dict, Any, Optional, List, Tuple
|
||||
import base64
|
||||
from typing import Dict, Any, Optional, List
|
||||
import subprocess
|
||||
|
||||
logger = logging.getLogger("kicad_interface")
|
||||
@@ -322,8 +321,6 @@ class ExportCommands:
|
||||
def export_3d(self, params: Dict[str, Any]) -> Dict[str, Any]:
|
||||
"""Export 3D model files using kicad-cli (KiCAD 9.0 compatible)"""
|
||||
import subprocess
|
||||
import platform
|
||||
import shutil
|
||||
|
||||
try:
|
||||
if not self.board:
|
||||
|
||||
@@ -107,9 +107,9 @@ class FootprintCreator:
|
||||
# ---- header ----
|
||||
lines.append(f'(footprint "{name}"')
|
||||
lines.append(f' (version {KICAD9_FOOTPRINT_VERSION})')
|
||||
lines.append(f' (generator "kicad-mcp")')
|
||||
lines.append(f' (generator_version "9.0")')
|
||||
lines.append(f' (layer "F.Cu")')
|
||||
lines.append(' (generator "kicad-mcp")')
|
||||
lines.append(' (generator_version "9.0")')
|
||||
lines.append(' (layer "F.Cu")')
|
||||
if description:
|
||||
lines.append(f' (descr "{_esc(description)}")')
|
||||
if tags:
|
||||
@@ -125,22 +125,22 @@ class FootprintCreator:
|
||||
lines.append(
|
||||
f' (property "Reference" "REF**" (at {_fmt(ref_x)} {_fmt(ref_y)} 0)'
|
||||
)
|
||||
lines.append(f' (layer "F.SilkS")')
|
||||
lines.append(' (layer "F.SilkS")')
|
||||
lines.append(f' (uuid "{_new_uuid()}")')
|
||||
lines.append(f' (effects (font (size 1 1) (thickness 0.15)))')
|
||||
lines.append(f' )')
|
||||
lines.append(' (effects (font (size 1 1) (thickness 0.15)))')
|
||||
lines.append(' )')
|
||||
lines.append(
|
||||
f' (property "Value" "{_esc(name)}" (at {_fmt(val_x)} {_fmt(val_y)} 0)'
|
||||
)
|
||||
lines.append(f' (layer "F.Fab")')
|
||||
lines.append(' (layer "F.Fab")')
|
||||
lines.append(f' (uuid "{_new_uuid()}")')
|
||||
lines.append(f' (effects (font (size 1 1) (thickness 0.15)))')
|
||||
lines.append(f' )')
|
||||
lines.append(f' (property "Datasheet" "" (at 0 0 0)')
|
||||
lines.append(f' (layer "F.Fab")')
|
||||
lines.append(' (effects (font (size 1 1) (thickness 0.15)))')
|
||||
lines.append(' )')
|
||||
lines.append(' (property "Datasheet" "" (at 0 0 0)')
|
||||
lines.append(' (layer "F.Fab")')
|
||||
lines.append(f' (uuid "{_new_uuid()}")')
|
||||
lines.append(f' (effects (font (size 1 1) (thickness 0.15)))')
|
||||
lines.append(f' )')
|
||||
lines.append(' (effects (font (size 1 1) (thickness 0.15)))')
|
||||
lines.append(' )')
|
||||
lines.append("")
|
||||
|
||||
# ---- courtyard ----
|
||||
@@ -483,7 +483,7 @@ def _pad_lines(pad: Dict[str, Any]) -> List[str]:
|
||||
lines.append(f" (roundrect_rratio {_fmt(rr_ratio)})")
|
||||
|
||||
lines.append(f' (uuid "{_new_uuid()}")')
|
||||
lines.append(f" )")
|
||||
lines.append(" )")
|
||||
return lines
|
||||
|
||||
|
||||
@@ -494,13 +494,13 @@ def _rect_lines(rect: Dict[str, Any], layer: str, default_width: float = 0.05) -
|
||||
y2 = _fmt(rect.get("y2", 1.0))
|
||||
w = _fmt(rect.get("width", default_width))
|
||||
return [
|
||||
f' (fp_rect',
|
||||
' (fp_rect',
|
||||
f' (start {x1} {y1})',
|
||||
f' (end {x2} {y2})',
|
||||
f' (stroke (width {w}) (type default))',
|
||||
f' (fill none)',
|
||||
' (fill none)',
|
||||
f' (layer "{layer}")',
|
||||
f' (uuid "{_new_uuid()}")',
|
||||
f' )',
|
||||
' )',
|
||||
"",
|
||||
]
|
||||
|
||||
@@ -16,7 +16,6 @@ import string
|
||||
import base64
|
||||
import json
|
||||
from typing import Optional, Dict, List, Callable
|
||||
from pathlib import Path
|
||||
|
||||
logger = logging.getLogger('kicad_interface')
|
||||
|
||||
@@ -260,7 +259,7 @@ def test_jlcpcb_connection(app_id: Optional[str] = None, access_key: Optional[st
|
||||
try:
|
||||
client = JLCPCBClient(app_id, access_key, secret_key)
|
||||
# Test by fetching first page
|
||||
data = client.fetch_parts_page()
|
||||
client.fetch_parts_page()
|
||||
logger.info("JLCPCB API connection test successful")
|
||||
return True
|
||||
except Exception as e:
|
||||
@@ -283,7 +282,7 @@ if __name__ == '__main__':
|
||||
print(f"✓ Retrieved {len(parts)} parts in first page")
|
||||
|
||||
if parts:
|
||||
print(f"\nExample part:")
|
||||
print("\nExample part:")
|
||||
part = parts[0]
|
||||
print(f" LCSC: {part.get('componentCode')}")
|
||||
print(f" MFR Part: {part.get('componentModelEn')}")
|
||||
|
||||
@@ -501,7 +501,7 @@ if __name__ == '__main__':
|
||||
|
||||
# Get stats
|
||||
stats = manager.get_database_stats()
|
||||
print(f"\nDatabase Statistics:")
|
||||
print("\nDatabase Statistics:")
|
||||
print(f" Total parts: {stats['total_parts']}")
|
||||
print(f" Basic parts: {stats['basic_parts']}")
|
||||
print(f" Extended parts: {stats['extended_parts']}")
|
||||
|
||||
@@ -234,7 +234,7 @@ if __name__ == '__main__':
|
||||
print(f"✓ Found {len(resistors)} resistors")
|
||||
|
||||
if resistors:
|
||||
print(f"\nExample resistor:")
|
||||
print("\nExample resistor:")
|
||||
r = resistors[0]
|
||||
print(f" LCSC: C{r.get('lcsc')}")
|
||||
print(f" MFR: {r.get('mfr')}")
|
||||
|
||||
@@ -10,7 +10,6 @@ import re
|
||||
import logging
|
||||
from pathlib import Path
|
||||
from typing import Dict, List, Optional, Tuple
|
||||
import glob
|
||||
|
||||
logger = logging.getLogger("kicad_interface")
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
from skip import Schematic
|
||||
# Symbol class might not be directly importable in the current version
|
||||
import os
|
||||
import glob
|
||||
@@ -75,7 +74,7 @@ class LibraryManager:
|
||||
# 3. Filtering symbols based on the query
|
||||
|
||||
# For now, this is a placeholder implementation
|
||||
libraries = LibraryManager.list_available_libraries(search_paths)
|
||||
LibraryManager.list_available_libraries(search_paths)
|
||||
|
||||
results = []
|
||||
print(f"Searched for symbols matching '{query}'. This requires advanced implementation.")
|
||||
|
||||
@@ -656,7 +656,6 @@ class SymbolLibraryCommands:
|
||||
|
||||
if __name__ == '__main__':
|
||||
# Test the symbol library manager
|
||||
import json
|
||||
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
|
||||
|
||||
@@ -439,7 +439,7 @@ if __name__ == "__main__":
|
||||
if r1_pin1 and c1_pin1:
|
||||
# R1 is not rotated, pins should be at y offset from symbol center
|
||||
# C1 is rotated 90°, pins should be at x offset from symbol center
|
||||
print(f"\n Pin offset analysis:")
|
||||
print("\n Pin offset analysis:")
|
||||
print(f" R1 (0°): pin 1 y-offset = {r1_pin1[1] - 100}")
|
||||
print(f" C1 (90°): pin 1 x-offset = {c1_pin1[0] - 150}")
|
||||
|
||||
|
||||
@@ -2,11 +2,10 @@
|
||||
Routing-related command implementations for KiCAD interface
|
||||
"""
|
||||
|
||||
import os
|
||||
import pcbnew
|
||||
import logging
|
||||
import math
|
||||
from typing import Dict, Any, Optional, List, Tuple
|
||||
from typing import Dict, Any, Optional
|
||||
|
||||
logger = logging.getLogger("kicad_interface")
|
||||
|
||||
@@ -844,7 +843,7 @@ class RoutingCommands:
|
||||
offset_y = target_pos.y - source_pos.y
|
||||
|
||||
# Build mapping from source refs to target refs
|
||||
ref_mapping = dict(zip(source_refs, target_refs))
|
||||
dict(zip(source_refs, target_refs))
|
||||
|
||||
# Collect all nets connected to source components
|
||||
source_nets = set()
|
||||
|
||||
@@ -332,7 +332,7 @@ class SymbolCreator:
|
||||
board_str = "yes" if on_board else "no"
|
||||
|
||||
lines.append(f' (symbol "{name}"')
|
||||
lines.append(f' (exclude_from_sim no)')
|
||||
lines.append(' (exclude_from_sim no)')
|
||||
lines.append(f' (in_bom {bom_str})')
|
||||
lines.append(f' (on_board {board_str})')
|
||||
|
||||
@@ -351,15 +351,15 @@ class SymbolCreator:
|
||||
lines.extend(_rect_sym_lines(rect))
|
||||
for pl in polylines:
|
||||
lines.extend(_polyline_lines(pl))
|
||||
lines.append(f' )')
|
||||
lines.append(' )')
|
||||
|
||||
# Sub-symbol _1_1: pins
|
||||
lines.append(f' (symbol "{name}_1_1"')
|
||||
for pin in pins:
|
||||
lines.extend(_pin_lines(pin))
|
||||
lines.append(f' )')
|
||||
lines.append(' )')
|
||||
|
||||
lines.append(f' )')
|
||||
lines.append(' )')
|
||||
return "\n".join(lines)
|
||||
|
||||
def _remove_symbol(self, content: str, name: str) -> str:
|
||||
@@ -397,10 +397,10 @@ def _property_block(
|
||||
return [
|
||||
f' (property "{_esc(key)}" "{_esc(value)}"',
|
||||
f' (at {_fmt(x)} {_fmt(y)} 0)',
|
||||
f' (effects',
|
||||
f' (font (size 1.27 1.27))',
|
||||
' (effects',
|
||||
' (font (size 1.27 1.27))',
|
||||
f' ){hide}',
|
||||
f' )',
|
||||
' )',
|
||||
]
|
||||
|
||||
|
||||
@@ -412,12 +412,12 @@ def _rect_sym_lines(rect: Dict[str, Any]) -> List[str]:
|
||||
w = _fmt(rect.get("width", 0.254))
|
||||
fill = rect.get("fill", "background")
|
||||
return [
|
||||
f' (rectangle',
|
||||
' (rectangle',
|
||||
f' (start {x1} {y1})',
|
||||
f' (end {x2} {y2})',
|
||||
f' (stroke (width {w}) (type default))',
|
||||
f' (fill (type {fill}))',
|
||||
f' )',
|
||||
' )',
|
||||
]
|
||||
|
||||
|
||||
@@ -426,16 +426,16 @@ def _polyline_lines(pl: Dict[str, Any]) -> List[str]:
|
||||
w = _fmt(pl.get("width", 0.254))
|
||||
fill = pl.get("fill", "none")
|
||||
lines = [
|
||||
f' (polyline',
|
||||
f' (pts',
|
||||
' (polyline',
|
||||
' (pts',
|
||||
]
|
||||
for pt in pts:
|
||||
lines.append(f' (xy {_fmt(pt["x"])} {_fmt(pt["y"])})')
|
||||
lines += [
|
||||
f' )',
|
||||
' )',
|
||||
f' (stroke (width {w}) (type default))',
|
||||
f' (fill (type {fill}))',
|
||||
f' )',
|
||||
' )',
|
||||
]
|
||||
return lines
|
||||
|
||||
@@ -456,10 +456,10 @@ def _pin_lines(pin: Dict[str, Any]) -> List[str]:
|
||||
f' (at {x} {y} {angle})',
|
||||
f' (length {length})',
|
||||
f' (name "{_esc(pin_name)}"',
|
||||
f' (effects (font (size 1.27 1.27)))',
|
||||
f' )',
|
||||
' (effects (font (size 1.27 1.27)))',
|
||||
' )',
|
||||
f' (number "{_esc(pin_number)}"',
|
||||
f' (effects (font (size 1.27 1.27)))',
|
||||
f' )',
|
||||
f' )',
|
||||
' (effects (font (size 1.27 1.27)))',
|
||||
' )',
|
||||
' )',
|
||||
]
|
||||
|
||||
@@ -8,10 +8,9 @@ manipulate the .kicad_sch file directly.
|
||||
|
||||
import uuid
|
||||
import logging
|
||||
import math
|
||||
import tempfile
|
||||
from pathlib import Path
|
||||
from typing import List, Tuple, Optional, Dict
|
||||
from typing import List
|
||||
import sexpdata
|
||||
from sexpdata import Symbol
|
||||
|
||||
@@ -423,7 +422,7 @@ if __name__ == '__main__':
|
||||
from skip import Schematic
|
||||
sch = Schematic(str(test_path))
|
||||
wire_count = len(list(sch.wire)) if hasattr(sch, 'wire') else 0
|
||||
print(f" ✓ Loaded successfully")
|
||||
print(" ✓ Loaded successfully")
|
||||
print(f" ✓ Wire count: {wire_count}")
|
||||
except Exception as e:
|
||||
print(f" ✗ Failed: {e}")
|
||||
|
||||
@@ -6,7 +6,6 @@ Auto-detects available backends and provides fallback mechanism.
|
||||
import os
|
||||
import logging
|
||||
from typing import Optional
|
||||
from pathlib import Path
|
||||
|
||||
from kicad_api.base import KiCADBackend, APINotAvailableError
|
||||
|
||||
|
||||
@@ -582,7 +582,7 @@ class IPCBoardAPI(BoardAPI):
|
||||
|
||||
# Get the pcbnew board instance
|
||||
# We need to get the actual board file path
|
||||
project = board.get_project()
|
||||
board.get_project()
|
||||
board_path = None
|
||||
|
||||
# Try to get the board path from kipy
|
||||
@@ -1089,7 +1089,7 @@ class IPCBoardAPI(BoardAPI):
|
||||
"""
|
||||
try:
|
||||
from kipy.board_types import Zone, ZoneFillMode, ZoneType
|
||||
from kipy.geometry import PolyLine, PolyLineNode, Vector2
|
||||
from kipy.geometry import PolyLine, PolyLineNode
|
||||
from kipy.util.units import from_mm
|
||||
from kipy.proto.board.board_types_pb2 import BoardLayer
|
||||
|
||||
@@ -1174,7 +1174,6 @@ class IPCBoardAPI(BoardAPI):
|
||||
def get_zones(self) -> List[Dict[str, Any]]:
|
||||
"""Get all zones on the board."""
|
||||
try:
|
||||
from kipy.util.units import to_mm
|
||||
|
||||
board = self._get_board()
|
||||
zones = board.get_zones()
|
||||
|
||||
@@ -152,7 +152,7 @@ if KICAD_BACKEND in ("auto", "ipc"):
|
||||
ipc_backend = IPCBackend()
|
||||
if ipc_backend.connect():
|
||||
USE_IPC_BACKEND = True
|
||||
logger.info(f"✓ Using IPC backend - real-time UI sync enabled!")
|
||||
logger.info("✓ Using IPC backend - real-time UI sync enabled!")
|
||||
logger.info(f" KiCAD version: {ipc_backend.get_version()}")
|
||||
else:
|
||||
logger.info("IPC backend available but KiCAD not running with IPC enabled")
|
||||
|
||||
@@ -6,8 +6,7 @@ read-only access to project data for LLM context.
|
||||
"""
|
||||
|
||||
import json
|
||||
import base64
|
||||
from typing import Dict, Any, List, Optional
|
||||
from typing import Dict, Any
|
||||
import logging
|
||||
|
||||
logger = logging.getLogger('kicad_interface')
|
||||
|
||||
@@ -42,7 +42,7 @@ def test_connection():
|
||||
print("✓ IPCBackend created")
|
||||
|
||||
if backend.connect():
|
||||
print(f"✓ Connected to KiCAD via IPC")
|
||||
print("✓ Connected to KiCAD via IPC")
|
||||
print(f" Version: {backend.get_version()}")
|
||||
return backend
|
||||
else:
|
||||
|
||||
@@ -3,7 +3,6 @@ KiCAD Process Management Utilities
|
||||
|
||||
Detects if KiCAD is running and provides auto-launch functionality.
|
||||
"""
|
||||
import os
|
||||
import subprocess
|
||||
import logging
|
||||
import platform
|
||||
|
||||
@@ -82,9 +82,9 @@ class PlatformHelper:
|
||||
# Check system Python dist-packages (modern KiCAD 9+ on Ubuntu/Debian)
|
||||
# This is where pcbnew.py typically lives on modern systems
|
||||
candidates.extend([
|
||||
Path(f"/usr/lib/python3/dist-packages"),
|
||||
Path("/usr/lib/python3/dist-packages"),
|
||||
Path(f"/usr/lib/python{py_version}/dist-packages"),
|
||||
Path(f"/usr/local/lib/python3/dist-packages"),
|
||||
Path("/usr/local/lib/python3/dist-packages"),
|
||||
Path(f"/usr/local/lib/python{py_version}/dist-packages"),
|
||||
])
|
||||
|
||||
|
||||
Reference in New Issue
Block a user