style: sort Python imports with isort
Add isort configuration (profile=black, line_length=100) to pyproject.toml, add isort pre-commit hook, and auto-sort imports across all Python source files. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -2,12 +2,12 @@
|
||||
KiCAD command implementations package
|
||||
"""
|
||||
|
||||
from .project import ProjectCommands
|
||||
from .board import BoardCommands
|
||||
from .component import ComponentCommands
|
||||
from .routing import RoutingCommands
|
||||
from .design_rules import DesignRuleCommands
|
||||
from .export import ExportCommands
|
||||
from .project import ProjectCommands
|
||||
from .routing import RoutingCommands
|
||||
|
||||
__all__ = [
|
||||
"ProjectCommands",
|
||||
|
||||
@@ -2,14 +2,16 @@
|
||||
Board-related command implementations for KiCAD interface
|
||||
"""
|
||||
|
||||
import pcbnew
|
||||
import logging
|
||||
from typing import Dict, Any, Optional
|
||||
from typing import Any, Dict, Optional
|
||||
|
||||
import pcbnew
|
||||
|
||||
from .layers import BoardLayerCommands
|
||||
from .outline import BoardOutlineCommands
|
||||
|
||||
# Import specialized modules
|
||||
from .size import BoardSizeCommands
|
||||
from .layers import BoardLayerCommands
|
||||
from .outline import BoardOutlineCommands
|
||||
from .view import BoardViewCommands
|
||||
|
||||
logger = logging.getLogger("kicad_interface")
|
||||
|
||||
@@ -2,9 +2,10 @@
|
||||
Board layer command implementations for KiCAD interface
|
||||
"""
|
||||
|
||||
import pcbnew
|
||||
import logging
|
||||
from typing import Dict, Any, Optional
|
||||
from typing import Any, Dict, Optional
|
||||
|
||||
import pcbnew
|
||||
|
||||
logger = logging.getLogger("kicad_interface")
|
||||
|
||||
|
||||
@@ -2,10 +2,11 @@
|
||||
Board outline command implementations for KiCAD interface
|
||||
"""
|
||||
|
||||
import pcbnew
|
||||
import logging
|
||||
import math
|
||||
from typing import Dict, Any, Optional
|
||||
from typing import Any, Dict, Optional
|
||||
|
||||
import pcbnew
|
||||
|
||||
logger = logging.getLogger("kicad_interface")
|
||||
|
||||
|
||||
@@ -2,9 +2,10 @@
|
||||
Board size command implementations for KiCAD interface
|
||||
"""
|
||||
|
||||
import pcbnew
|
||||
import logging
|
||||
from typing import Dict, Any, Optional
|
||||
from typing import Any, Dict, Optional
|
||||
|
||||
import pcbnew
|
||||
|
||||
logger = logging.getLogger("kicad_interface")
|
||||
|
||||
|
||||
@@ -2,13 +2,14 @@
|
||||
Board view command implementations for KiCAD interface
|
||||
"""
|
||||
|
||||
import os
|
||||
import pcbnew
|
||||
import logging
|
||||
from typing import Dict, Any, Optional, List, Tuple
|
||||
from PIL import Image
|
||||
import io
|
||||
import base64
|
||||
import io
|
||||
import logging
|
||||
import os
|
||||
from typing import Any, Dict, List, Optional, Tuple
|
||||
|
||||
import pcbnew
|
||||
from PIL import Image
|
||||
|
||||
logger = logging.getLogger("kicad_interface")
|
||||
|
||||
|
||||
@@ -2,12 +2,13 @@
|
||||
Component-related command implementations for KiCAD interface
|
||||
"""
|
||||
|
||||
import os
|
||||
import pcbnew
|
||||
import base64
|
||||
import logging
|
||||
import math
|
||||
from typing import Dict, Any, Optional, List, Tuple
|
||||
import base64
|
||||
import os
|
||||
from typing import Any, Dict, List, Optional, Tuple
|
||||
|
||||
import pcbnew
|
||||
from commands.library import LibraryManager
|
||||
|
||||
logger = logging.getLogger("kicad_interface")
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
from skip import Schematic
|
||||
import logging
|
||||
import os
|
||||
import uuid
|
||||
import logging
|
||||
from pathlib import Path
|
||||
from typing import Optional
|
||||
|
||||
from skip import Schematic
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
# Import dynamic symbol loader
|
||||
@@ -350,9 +351,9 @@ class ComponentManager:
|
||||
|
||||
if __name__ == "__main__":
|
||||
# Example Usage (for testing)
|
||||
from schematic import (
|
||||
from schematic import ( # Assuming schematic.py is in the same directory
|
||||
SchematicManager,
|
||||
) # Assuming schematic.py is in the same directory
|
||||
)
|
||||
|
||||
# Create a new schematic
|
||||
test_sch = SchematicManager.create_schematic("ComponentTestSchematic")
|
||||
|
||||
@@ -1,15 +1,16 @@
|
||||
from skip import Schematic
|
||||
import os
|
||||
import logging
|
||||
import os
|
||||
from pathlib import Path
|
||||
from typing import Optional
|
||||
|
||||
from skip import Schematic
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
# Import new wire and pin managers
|
||||
try:
|
||||
from commands.wire_manager import WireManager
|
||||
from commands.pin_locator import PinLocator
|
||||
from commands.wire_manager import WireManager
|
||||
|
||||
WIRE_MANAGER_AVAILABLE = True
|
||||
except ImportError:
|
||||
|
||||
@@ -9,8 +9,8 @@ URL schema: https://www.lcsc.com/datasheet/{LCSC#}.pdf
|
||||
No API key required.
|
||||
"""
|
||||
|
||||
import re
|
||||
import logging
|
||||
import re
|
||||
from pathlib import Path
|
||||
from typing import Dict, List, Optional
|
||||
|
||||
|
||||
@@ -2,10 +2,11 @@
|
||||
Design rules command implementations for KiCAD interface
|
||||
"""
|
||||
|
||||
import os
|
||||
import pcbnew
|
||||
import logging
|
||||
from typing import Dict, Any, Optional, List, Tuple
|
||||
import os
|
||||
from typing import Any, Dict, List, Optional, Tuple
|
||||
|
||||
import pcbnew
|
||||
|
||||
logger = logging.getLogger("kicad_interface")
|
||||
|
||||
@@ -171,11 +172,11 @@ class DesignRuleCommands:
|
||||
|
||||
def run_drc(self, params: Dict[str, Any]) -> Dict[str, Any]:
|
||||
"""Run Design Rule Check using kicad-cli"""
|
||||
import subprocess
|
||||
import json
|
||||
import tempfile
|
||||
import platform
|
||||
import shutil
|
||||
import subprocess
|
||||
import tempfile
|
||||
|
||||
try:
|
||||
if not self.board:
|
||||
|
||||
@@ -7,10 +7,10 @@ on-the-fly using TEXT MANIPULATION (not sexpdata) to preserve file formatting.
|
||||
This enables access to all ~10,000+ KiCad symbols dynamically.
|
||||
"""
|
||||
|
||||
import logging
|
||||
import os
|
||||
import re
|
||||
import uuid
|
||||
import logging
|
||||
from pathlib import Path
|
||||
from typing import Dict, List, Optional, Tuple
|
||||
|
||||
|
||||
@@ -2,13 +2,14 @@
|
||||
Export command implementations for KiCAD interface
|
||||
"""
|
||||
|
||||
import os
|
||||
import pcbnew
|
||||
import logging
|
||||
from typing import Dict, Any, Optional, List, Tuple
|
||||
import base64
|
||||
import logging
|
||||
import os
|
||||
import shutil
|
||||
from datetime import datetime
|
||||
from typing import Any, Dict, List, Optional, Tuple
|
||||
|
||||
import pcbnew
|
||||
|
||||
logger = logging.getLogger("kicad_interface")
|
||||
|
||||
@@ -321,9 +322,9 @@ 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
|
||||
import subprocess
|
||||
|
||||
try:
|
||||
if not self.board:
|
||||
@@ -608,8 +609,8 @@ class ExportCommands:
|
||||
Returns:
|
||||
Path to kicad-cli executable, or None if not found
|
||||
"""
|
||||
import shutil
|
||||
import platform
|
||||
import shutil
|
||||
|
||||
# Try system PATH first
|
||||
cli_path = shutil.which("kicad-cli")
|
||||
|
||||
@@ -8,9 +8,9 @@ KiCAD 9 .kicad_mod format reference:
|
||||
https://dev-docs.kicad.org/en/file-formats/sexpr-footprint/
|
||||
"""
|
||||
|
||||
import logging
|
||||
import os
|
||||
import re
|
||||
import logging
|
||||
from pathlib import Path
|
||||
from typing import Any, Dict, List, Optional
|
||||
|
||||
|
||||
@@ -9,13 +9,13 @@ Supports two execution modes:
|
||||
- Docker: docker run eclipse-temurin:21-jre (requires Docker)
|
||||
"""
|
||||
|
||||
import os
|
||||
import subprocess
|
||||
import shutil
|
||||
import time
|
||||
import logging
|
||||
import os
|
||||
import shutil
|
||||
import subprocess
|
||||
import time
|
||||
from pathlib import Path
|
||||
from typing import Dict, Any, Optional, List
|
||||
from typing import Any, Dict, List, Optional
|
||||
|
||||
logger = logging.getLogger("kicad_interface")
|
||||
|
||||
|
||||
@@ -5,18 +5,19 @@ Handles authentication and downloading the JLCPCB parts library
|
||||
for integration with KiCAD component selection.
|
||||
"""
|
||||
|
||||
import os
|
||||
import logging
|
||||
import requests
|
||||
import time
|
||||
import hmac
|
||||
import base64
|
||||
import hashlib
|
||||
import hmac
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
import secrets
|
||||
import string
|
||||
import base64
|
||||
import json
|
||||
from typing import Optional, Dict, List, Callable
|
||||
import time
|
||||
from pathlib import Path
|
||||
from typing import Callable, Dict, List, Optional
|
||||
|
||||
import requests
|
||||
|
||||
logger = logging.getLogger("kicad_interface")
|
||||
|
||||
|
||||
@@ -5,13 +5,13 @@ Manages local SQLite database of JLCPCB parts for fast searching
|
||||
and component selection.
|
||||
"""
|
||||
|
||||
import os
|
||||
import sqlite3
|
||||
import json
|
||||
import logging
|
||||
from pathlib import Path
|
||||
from typing import List, Dict, Optional
|
||||
import os
|
||||
import sqlite3
|
||||
from datetime import datetime
|
||||
from pathlib import Path
|
||||
from typing import Dict, List, Optional
|
||||
|
||||
logger = logging.getLogger("kicad_interface")
|
||||
|
||||
|
||||
@@ -6,9 +6,10 @@ jlcsearch service at https://jlcsearch.tscircuit.com/
|
||||
"""
|
||||
|
||||
import logging
|
||||
import requests
|
||||
from typing import Optional, Dict, List, Callable
|
||||
import time
|
||||
from typing import Callable, Dict, List, Optional
|
||||
|
||||
import requests
|
||||
|
||||
logger = logging.getLogger("kicad_interface")
|
||||
|
||||
|
||||
@@ -5,12 +5,12 @@ Handles parsing fp-lib-table files, discovering footprints,
|
||||
and providing search functionality for component placement.
|
||||
"""
|
||||
|
||||
import glob
|
||||
import logging
|
||||
import os
|
||||
import re
|
||||
import logging
|
||||
from pathlib import Path
|
||||
from typing import Dict, List, Optional, Tuple
|
||||
import glob
|
||||
|
||||
logger = logging.getLogger("kicad_interface")
|
||||
|
||||
@@ -522,9 +522,10 @@ class LibraryCommands:
|
||||
|
||||
# Attempt to enrich with parsed .kicad_mod data
|
||||
try:
|
||||
from parsers.kicad_mod_parser import parse_kicad_mod
|
||||
from pathlib import Path as _Path
|
||||
|
||||
from parsers.kicad_mod_parser import parse_kicad_mod
|
||||
|
||||
mod_file = str(_Path(library_path) / f"{footprint_name}.kicad_mod")
|
||||
parsed = parse_kicad_mod(mod_file)
|
||||
if parsed:
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
from skip import Schematic
|
||||
import glob
|
||||
|
||||
# Symbol class might not be directly importable in the current version
|
||||
import os
|
||||
import glob
|
||||
|
||||
from skip import Schematic
|
||||
|
||||
|
||||
class LibraryManager:
|
||||
|
||||
@@ -5,12 +5,12 @@ Handles parsing sym-lib-table files, discovering symbols,
|
||||
and providing search functionality for component selection.
|
||||
"""
|
||||
|
||||
import logging
|
||||
import os
|
||||
import re
|
||||
import logging
|
||||
from dataclasses import asdict, dataclass
|
||||
from pathlib import Path
|
||||
from typing import Dict, List, Optional
|
||||
from dataclasses import dataclass, asdict
|
||||
|
||||
logger = logging.getLogger("kicad_interface")
|
||||
|
||||
|
||||
@@ -9,7 +9,8 @@ import logging
|
||||
import math
|
||||
import tempfile
|
||||
from pathlib import Path
|
||||
from typing import List, Tuple, Optional, Dict
|
||||
from typing import Dict, List, Optional, Tuple
|
||||
|
||||
import sexpdata
|
||||
from sexpdata import Symbol
|
||||
from skip import Schematic
|
||||
@@ -396,12 +397,12 @@ class PinLocator:
|
||||
|
||||
if __name__ == "__main__":
|
||||
# Test pin location discovery
|
||||
import shutil
|
||||
import sys
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
from commands.component_schematic import ComponentManager
|
||||
from commands.schematic import SchematicManager
|
||||
import shutil
|
||||
|
||||
sys.path.insert(0, str(Path(__file__).parent.parent))
|
||||
|
||||
|
||||
@@ -2,11 +2,12 @@
|
||||
Project-related command implementations for KiCAD interface
|
||||
"""
|
||||
|
||||
import os
|
||||
import pcbnew # type: ignore
|
||||
import logging
|
||||
import os
|
||||
import shutil
|
||||
from typing import Dict, Any, Optional
|
||||
from typing import Any, Dict, Optional
|
||||
|
||||
import pcbnew # type: ignore
|
||||
|
||||
logger = logging.getLogger("kicad_interface")
|
||||
|
||||
|
||||
@@ -2,11 +2,12 @@
|
||||
Routing-related command implementations for KiCAD interface
|
||||
"""
|
||||
|
||||
import os
|
||||
import pcbnew
|
||||
import logging
|
||||
import math
|
||||
from typing import Dict, Any, Optional, List, Tuple
|
||||
import os
|
||||
from typing import Any, Dict, List, Optional, Tuple
|
||||
|
||||
import pcbnew
|
||||
|
||||
logger = logging.getLogger("kicad_interface")
|
||||
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
from skip import Schematic
|
||||
import logging
|
||||
import os
|
||||
import shutil
|
||||
import logging
|
||||
import uuid
|
||||
|
||||
from skip import Schematic
|
||||
|
||||
logger = logging.getLogger("kicad_interface")
|
||||
|
||||
|
||||
|
||||
@@ -8,12 +8,11 @@ and checking connectivity in KiCad schematic files.
|
||||
import logging
|
||||
import math
|
||||
from pathlib import Path
|
||||
from typing import Dict, List, Tuple, Optional, Any, Set
|
||||
from typing import Any, Dict, List, Optional, Set, Tuple
|
||||
|
||||
import sexpdata
|
||||
from sexpdata import Symbol
|
||||
|
||||
from commands.pin_locator import PinLocator
|
||||
from sexpdata import Symbol
|
||||
|
||||
logger = logging.getLogger("kicad_interface")
|
||||
|
||||
|
||||
@@ -15,13 +15,13 @@ Supported SVG elements:
|
||||
SVG coordinate system: Y increases downward (same as KiCAD mm), so no Y-flip needed.
|
||||
"""
|
||||
|
||||
import re
|
||||
import math
|
||||
import uuid
|
||||
import os
|
||||
import logging
|
||||
from typing import List, Tuple, Dict, Any, Optional
|
||||
import math
|
||||
import os
|
||||
import re
|
||||
import uuid
|
||||
import xml.etree.ElementTree as ET
|
||||
from typing import Any, Dict, List, Optional, Tuple
|
||||
|
||||
logger = logging.getLogger("kicad_interface")
|
||||
|
||||
|
||||
@@ -12,9 +12,9 @@ KiCAD 9 .kicad_sym format:
|
||||
- All coordinates in mm, 2.54mm grid typical for schematic symbols
|
||||
"""
|
||||
|
||||
import logging
|
||||
import os
|
||||
import re
|
||||
import logging
|
||||
from pathlib import Path
|
||||
from typing import Any, Dict, List, Optional
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ coordinate matching, mirroring KiCad's own connectivity algorithm.
|
||||
import logging
|
||||
from pathlib import Path
|
||||
from typing import Dict, List, Optional, Set, Tuple
|
||||
|
||||
from commands.pin_locator import PinLocator
|
||||
|
||||
logger = logging.getLogger("kicad_interface")
|
||||
|
||||
@@ -6,12 +6,13 @@ kicad-skip's wire API doesn't support creating wires with standard parameters, s
|
||||
manipulate the .kicad_sch file directly.
|
||||
"""
|
||||
|
||||
import uuid
|
||||
import logging
|
||||
import math
|
||||
import tempfile
|
||||
import uuid
|
||||
from pathlib import Path
|
||||
from typing import List, Tuple, Optional
|
||||
from typing import List, Optional, Tuple
|
||||
|
||||
import sexpdata
|
||||
from sexpdata import Symbol
|
||||
|
||||
@@ -671,10 +672,9 @@ class WireManager:
|
||||
|
||||
if __name__ == "__main__":
|
||||
# Test wire creation
|
||||
import sys
|
||||
|
||||
from pathlib import Path
|
||||
import shutil
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
sys.path.insert(0, str(Path(__file__).parent.parent))
|
||||
|
||||
|
||||
@@ -20,8 +20,8 @@ Usage:
|
||||
board.set_size(100, 80)
|
||||
"""
|
||||
|
||||
from kicad_api.factory import create_backend
|
||||
from kicad_api.base import KiCADBackend
|
||||
from kicad_api.factory import create_backend
|
||||
|
||||
__all__ = ["create_backend", "KiCADBackend"]
|
||||
__version__ = "2.0.0-alpha.1"
|
||||
|
||||
@@ -4,10 +4,10 @@ Abstract base class for KiCAD API backends
|
||||
Defines the interface that all KiCAD backends must implement.
|
||||
"""
|
||||
|
||||
import logging
|
||||
from abc import ABC, abstractmethod
|
||||
from pathlib import Path
|
||||
from typing import Optional, Dict, Any, List
|
||||
import logging
|
||||
from typing import Any, Dict, List, Optional
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@@ -4,12 +4,12 @@ Backend factory for creating appropriate KiCAD API backend
|
||||
Auto-detects available backends and provides fallback mechanism.
|
||||
"""
|
||||
|
||||
import os
|
||||
import logging
|
||||
from typing import Optional
|
||||
import os
|
||||
from pathlib import Path
|
||||
from typing import Optional
|
||||
|
||||
from kicad_api.base import KiCADBackend, APINotAvailableError
|
||||
from kicad_api.base import APINotAvailableError, KiCADBackend
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@@ -18,9 +18,9 @@ import logging
|
||||
import os
|
||||
import platform
|
||||
from pathlib import Path
|
||||
from typing import Optional, Dict, Any, List, Callable
|
||||
from typing import Any, Callable, Dict, List, Optional
|
||||
|
||||
from kicad_api.base import KiCADBackend, BoardAPI, ConnectionError, APINotAvailableError
|
||||
from kicad_api.base import APINotAvailableError, BoardAPI, ConnectionError, KiCADBackend
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -317,8 +317,8 @@ class IPCBoardAPI(BoardAPI):
|
||||
try:
|
||||
from kipy.board_types import BoardRectangle
|
||||
from kipy.geometry import Vector2
|
||||
from kipy.util.units import from_mm
|
||||
from kipy.proto.board.board_types_pb2 import BoardLayer
|
||||
from kipy.util.units import from_mm
|
||||
|
||||
board = self._get_board()
|
||||
|
||||
@@ -655,9 +655,9 @@ class IPCBoardAPI(BoardAPI):
|
||||
"""
|
||||
try:
|
||||
from kipy.board_types import Footprint
|
||||
from kipy.geometry import Vector2, Angle
|
||||
from kipy.util.units import from_mm
|
||||
from kipy.geometry import Angle, Vector2
|
||||
from kipy.proto.board.board_types_pb2 import BoardLayer
|
||||
from kipy.util.units import from_mm
|
||||
|
||||
board = self._get_board()
|
||||
|
||||
@@ -708,7 +708,7 @@ class IPCBoardAPI(BoardAPI):
|
||||
) -> bool:
|
||||
"""Move a component to a new position (updates UI immediately)."""
|
||||
try:
|
||||
from kipy.geometry import Vector2, Angle
|
||||
from kipy.geometry import Angle, Vector2
|
||||
from kipy.util.units import from_mm
|
||||
|
||||
board = self._get_board()
|
||||
@@ -795,8 +795,8 @@ class IPCBoardAPI(BoardAPI):
|
||||
try:
|
||||
from kipy.board_types import Track
|
||||
from kipy.geometry import Vector2
|
||||
from kipy.util.units import from_mm
|
||||
from kipy.proto.board.board_types_pb2 import BoardLayer
|
||||
from kipy.util.units import from_mm
|
||||
|
||||
board = self._get_board()
|
||||
|
||||
@@ -863,8 +863,8 @@ class IPCBoardAPI(BoardAPI):
|
||||
try:
|
||||
from kipy.board_types import Via
|
||||
from kipy.geometry import Vector2
|
||||
from kipy.util.units import from_mm
|
||||
from kipy.proto.board.board_types_pb2 import ViaType
|
||||
from kipy.util.units import from_mm
|
||||
|
||||
board = self._get_board()
|
||||
|
||||
@@ -925,9 +925,9 @@ class IPCBoardAPI(BoardAPI):
|
||||
"""Add text to the board."""
|
||||
try:
|
||||
from kipy.board_types import BoardText
|
||||
from kipy.geometry import Vector2, Angle
|
||||
from kipy.util.units import from_mm
|
||||
from kipy.geometry import Angle, Vector2
|
||||
from kipy.proto.board.board_types_pb2 import BoardLayer
|
||||
from kipy.util.units import from_mm
|
||||
|
||||
board = self._get_board()
|
||||
|
||||
@@ -1072,8 +1072,8 @@ class IPCBoardAPI(BoardAPI):
|
||||
try:
|
||||
from kipy.board_types import Zone, ZoneFillMode, ZoneType
|
||||
from kipy.geometry import PolyLine, PolyLineNode, Vector2
|
||||
from kipy.util.units import from_mm
|
||||
from kipy.proto.board.board_types_pb2 import BoardLayer
|
||||
from kipy.util.units import from_mm
|
||||
|
||||
board = self._get_board()
|
||||
|
||||
|
||||
@@ -11,9 +11,9 @@ WARNING: SWIG bindings are deprecated as of KiCAD 9.0
|
||||
|
||||
import logging
|
||||
from pathlib import Path
|
||||
from typing import Optional, Dict, Any, List
|
||||
from typing import Any, Dict, List, Optional
|
||||
|
||||
from kicad_api.base import KiCADBackend, BoardAPI, ConnectionError, APINotAvailableError
|
||||
from kicad_api.base import APINotAvailableError, BoardAPI, ConnectionError, KiCADBackend
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@@ -7,16 +7,17 @@ and KiCAD's Python API (pcbnew). It receives commands via stdin as
|
||||
JSON and returns responses via stdout also as JSON.
|
||||
"""
|
||||
|
||||
import sys
|
||||
import json
|
||||
import traceback
|
||||
import logging
|
||||
import os
|
||||
from typing import Dict, Any, Optional
|
||||
import sys
|
||||
import traceback
|
||||
from typing import Any, Dict, Optional
|
||||
|
||||
from resources.resource_definitions import RESOURCE_DEFINITIONS, handle_resource_read
|
||||
|
||||
# Import tool schemas and resource definitions
|
||||
from schemas.tool_schemas import TOOL_SCHEMAS
|
||||
from resources.resource_definitions import RESOURCE_DEFINITIONS, handle_resource_read
|
||||
|
||||
# Configure logging
|
||||
log_dir = os.path.join(os.path.expanduser("~"), ".kicad-mcp", "logs")
|
||||
@@ -80,9 +81,10 @@ utils_dir = os.path.join(os.path.dirname(__file__))
|
||||
if utils_dir not in sys.path:
|
||||
sys.path.insert(0, utils_dir)
|
||||
|
||||
from utils.kicad_process import KiCADProcessManager, check_and_launch_kicad
|
||||
|
||||
# Import platform helper and add KiCAD paths
|
||||
from utils.platform_helper import PlatformHelper
|
||||
from utils.kicad_process import check_and_launch_kicad, KiCADProcessManager
|
||||
|
||||
logger.info(f"Detecting KiCAD Python paths for {PlatformHelper.get_platform_name()}...")
|
||||
paths_added = PlatformHelper.add_kicad_to_python_path()
|
||||
@@ -202,27 +204,27 @@ elif KICAD_BACKEND == "ipc" and not USE_IPC_BACKEND:
|
||||
# Import command handlers
|
||||
try:
|
||||
logger.info("Importing command handlers...")
|
||||
from commands.project import ProjectCommands
|
||||
from commands.board import BoardCommands
|
||||
from commands.component import ComponentCommands
|
||||
from commands.routing import RoutingCommands
|
||||
from commands.design_rules import DesignRuleCommands
|
||||
from commands.export import ExportCommands
|
||||
from commands.schematic import SchematicManager
|
||||
from commands.component_schematic import ComponentManager
|
||||
from commands.connection_schematic import ConnectionManager
|
||||
from commands.library_schematic import LibraryManager as SchematicLibraryManager
|
||||
from commands.library import (
|
||||
LibraryManager as FootprintLibraryManager,
|
||||
LibraryCommands,
|
||||
)
|
||||
from commands.library_symbol import SymbolLibraryManager, SymbolLibraryCommands
|
||||
from commands.datasheet_manager import DatasheetManager
|
||||
from commands.design_rules import DesignRuleCommands
|
||||
from commands.export import ExportCommands
|
||||
from commands.footprint import FootprintCreator
|
||||
from commands.freerouting import FreeroutingCommands
|
||||
from commands.jlcpcb import JLCPCBClient, test_jlcpcb_connection
|
||||
from commands.jlcpcb_parts import JLCPCBPartsManager
|
||||
from commands.datasheet_manager import DatasheetManager
|
||||
from commands.footprint import FootprintCreator
|
||||
from commands.library import (
|
||||
LibraryCommands,
|
||||
)
|
||||
from commands.library import LibraryManager as FootprintLibraryManager
|
||||
from commands.library_schematic import LibraryManager as SchematicLibraryManager
|
||||
from commands.library_symbol import SymbolLibraryCommands, SymbolLibraryManager
|
||||
from commands.project import ProjectCommands
|
||||
from commands.routing import RoutingCommands
|
||||
from commands.schematic import SchematicManager
|
||||
from commands.symbol_creator import SymbolCreator
|
||||
from commands.freerouting import FreeroutingCommands
|
||||
|
||||
logger.info("Successfully imported all command handlers")
|
||||
except ImportError as e:
|
||||
@@ -682,6 +684,7 @@ class KiCADInterface:
|
||||
logger.info("Adding component to schematic")
|
||||
try:
|
||||
from pathlib import Path
|
||||
|
||||
from commands.dynamic_symbol_loader import DynamicSymbolLoader
|
||||
|
||||
schematic_path = params.get("schematicPath")
|
||||
@@ -733,8 +736,8 @@ class KiCADInterface:
|
||||
"""Remove a placed symbol from a schematic using text-based manipulation (no skip writes)"""
|
||||
logger.info("Deleting schematic component")
|
||||
try:
|
||||
from pathlib import Path
|
||||
import re
|
||||
from pathlib import Path
|
||||
|
||||
schematic_path = params.get("schematicPath")
|
||||
reference = params.get("reference")
|
||||
@@ -841,8 +844,8 @@ class KiCADInterface:
|
||||
"""
|
||||
logger.info("Editing schematic component")
|
||||
try:
|
||||
from pathlib import Path
|
||||
import re
|
||||
from pathlib import Path
|
||||
|
||||
schematic_path = params.get("schematicPath")
|
||||
reference = params.get("reference")
|
||||
@@ -992,8 +995,8 @@ class KiCADInterface:
|
||||
"""Return full component info: position and all field values with their (at x y angle) positions."""
|
||||
logger.info("Getting schematic component info")
|
||||
try:
|
||||
from pathlib import Path
|
||||
import re
|
||||
from pathlib import Path
|
||||
|
||||
schematic_path = params.get("schematicPath")
|
||||
reference = params.get("reference")
|
||||
@@ -1116,6 +1119,7 @@ class KiCADInterface:
|
||||
logger.info("Adding wire to schematic")
|
||||
try:
|
||||
from pathlib import Path
|
||||
|
||||
from commands.wire_manager import WireManager
|
||||
|
||||
schematic_path = params.get("schematicPath")
|
||||
@@ -1239,6 +1243,7 @@ class KiCADInterface:
|
||||
logger.info("Adding junction to schematic")
|
||||
try:
|
||||
from pathlib import Path
|
||||
|
||||
from commands.wire_manager import WireManager
|
||||
|
||||
schematic_path = params.get("schematicPath")
|
||||
@@ -1472,6 +1477,7 @@ class KiCADInterface:
|
||||
logger.info("Adding net label to schematic")
|
||||
try:
|
||||
from pathlib import Path
|
||||
|
||||
from commands.wire_manager import WireManager
|
||||
|
||||
schematic_path = params.get("schematicPath")
|
||||
@@ -1591,6 +1597,7 @@ class KiCADInterface:
|
||||
logger.info("Getting schematic pin locations")
|
||||
try:
|
||||
from pathlib import Path
|
||||
|
||||
from commands.pin_locator import PinLocator
|
||||
|
||||
schematic_path = params.get("schematicPath")
|
||||
@@ -1643,9 +1650,9 @@ class KiCADInterface:
|
||||
def _handle_get_schematic_view(self, params):
|
||||
"""Get a rasterised image of the schematic (SVG export → optional PNG conversion)"""
|
||||
logger.info("Getting schematic view")
|
||||
import base64
|
||||
import subprocess
|
||||
import tempfile
|
||||
import base64
|
||||
|
||||
try:
|
||||
schematic_path = params.get("schematicPath")
|
||||
@@ -1734,6 +1741,7 @@ class KiCADInterface:
|
||||
logger.info("Listing schematic components")
|
||||
try:
|
||||
from pathlib import Path
|
||||
|
||||
from commands.pin_locator import PinLocator
|
||||
|
||||
schematic_path = params.get("schematicPath")
|
||||
@@ -2185,6 +2193,7 @@ class KiCADInterface:
|
||||
return {"success": False, "message": "schematicPath is required"}
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
from commands.wire_manager import WireManager
|
||||
|
||||
start_point = [start.get("x", 0), start.get("y", 0)]
|
||||
@@ -2218,6 +2227,7 @@ class KiCADInterface:
|
||||
}
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
from commands.wire_manager import WireManager
|
||||
|
||||
pos_list = None
|
||||
@@ -2240,9 +2250,9 @@ class KiCADInterface:
|
||||
def _handle_export_schematic_svg(self, params):
|
||||
"""Export schematic to SVG using kicad-cli"""
|
||||
logger.info("Exporting schematic SVG")
|
||||
import subprocess
|
||||
import glob
|
||||
import shutil
|
||||
import subprocess
|
||||
|
||||
try:
|
||||
schematic_path = params.get("schematicPath")
|
||||
@@ -2381,9 +2391,9 @@ class KiCADInterface:
|
||||
def _handle_run_erc(self, params):
|
||||
"""Run Electrical Rules Check on a schematic via kicad-cli"""
|
||||
logger.info("Running ERC on schematic")
|
||||
import os
|
||||
import subprocess
|
||||
import tempfile
|
||||
import os
|
||||
|
||||
try:
|
||||
schematic_path = params.get("schematicPath")
|
||||
@@ -2619,10 +2629,10 @@ class KiCADInterface:
|
||||
def _handle_get_schematic_view_region(self, params):
|
||||
"""Export a cropped region of the schematic as an image"""
|
||||
logger.info("Exporting schematic view region")
|
||||
import base64
|
||||
import os
|
||||
import subprocess
|
||||
import tempfile
|
||||
import os
|
||||
import base64
|
||||
|
||||
try:
|
||||
schematic_path = params.get("schematicPath")
|
||||
@@ -2736,6 +2746,7 @@ class KiCADInterface:
|
||||
logger.info("Finding overlapping elements in schematic")
|
||||
try:
|
||||
from pathlib import Path
|
||||
|
||||
from commands.schematic_analysis import find_overlapping_elements
|
||||
|
||||
schematic_path = params.get("schematicPath")
|
||||
@@ -2761,6 +2772,7 @@ class KiCADInterface:
|
||||
logger.info("Getting elements in schematic region")
|
||||
try:
|
||||
from pathlib import Path
|
||||
|
||||
from commands.schematic_analysis import get_elements_in_region
|
||||
|
||||
schematic_path = params.get("schematicPath")
|
||||
@@ -2790,6 +2802,7 @@ class KiCADInterface:
|
||||
logger.info("Finding wires crossing symbols in schematic")
|
||||
try:
|
||||
from pathlib import Path
|
||||
|
||||
from commands.schematic_analysis import find_wires_crossing_symbols
|
||||
|
||||
schematic_path = params.get("schematicPath")
|
||||
@@ -3009,7 +3022,9 @@ class KiCADInterface:
|
||||
zone_count = self.board.GetAreaCount() if hasattr(self.board, "GetAreaCount") else 0
|
||||
|
||||
# Run pcbnew zone fill in an isolated subprocess to prevent crashes
|
||||
import subprocess, sys, textwrap
|
||||
import subprocess
|
||||
import sys
|
||||
import textwrap
|
||||
|
||||
script = textwrap.dedent(f"""
|
||||
import pcbnew, sys
|
||||
@@ -3437,8 +3452,8 @@ print("ok")
|
||||
try:
|
||||
from kipy.board_types import BoardSegment
|
||||
from kipy.geometry import Vector2
|
||||
from kipy.util.units import from_mm
|
||||
from kipy.proto.board.board_types_pb2 import BoardLayer
|
||||
from kipy.util.units import from_mm
|
||||
|
||||
board = self.ipc_board_api._get_board()
|
||||
|
||||
@@ -3488,8 +3503,8 @@ print("ok")
|
||||
try:
|
||||
from kipy.board_types import BoardCircle
|
||||
from kipy.geometry import Vector2
|
||||
from kipy.util.units import from_mm
|
||||
from kipy.proto.board.board_types_pb2 import BoardLayer
|
||||
from kipy.util.units import from_mm
|
||||
|
||||
board = self.ipc_board_api._get_board()
|
||||
|
||||
|
||||
@@ -15,8 +15,8 @@ KiCad S-expression file format reference:
|
||||
https://dev-docs.kicad.org/en/file-formats/sexpr-intro/index.html#_footprint
|
||||
"""
|
||||
|
||||
import re
|
||||
import logging
|
||||
import re
|
||||
from pathlib import Path
|
||||
from typing import Any, Dict, List, Optional, Tuple
|
||||
|
||||
|
||||
@@ -5,10 +5,10 @@ Resources follow the MCP 2025-06-18 specification, providing
|
||||
read-only access to project data for LLM context.
|
||||
"""
|
||||
|
||||
import json
|
||||
import base64
|
||||
from typing import Dict, Any, List, Optional
|
||||
import json
|
||||
import logging
|
||||
from typing import Any, Dict, List, Optional
|
||||
|
||||
logger = logging.getLogger("kicad_interface")
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ Each tool includes:
|
||||
- outputSchema: Optional JSON Schema for return values (structured content)
|
||||
"""
|
||||
|
||||
from typing import Dict, Any
|
||||
from typing import Any, Dict
|
||||
|
||||
# =============================================================================
|
||||
# PROJECT TOOLS
|
||||
|
||||
@@ -14,8 +14,8 @@ Usage:
|
||||
./venv/bin/python python/test_ipc_backend.py
|
||||
"""
|
||||
|
||||
import sys
|
||||
import os
|
||||
import sys
|
||||
|
||||
# Add parent directory to path
|
||||
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
|
||||
|
||||
@@ -15,12 +15,11 @@ from pathlib import Path
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
import pytest
|
||||
|
||||
from commands.freerouting import (
|
||||
FreeroutingCommands,
|
||||
_find_java,
|
||||
_find_docker,
|
||||
_docker_available,
|
||||
_find_docker,
|
||||
_find_java,
|
||||
_java_version_ok,
|
||||
)
|
||||
|
||||
|
||||
@@ -6,11 +6,11 @@ Integration tests parse real .kicad_sch files via sexpdata.
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
import shutil
|
||||
import sys
|
||||
import tempfile
|
||||
from pathlib import Path
|
||||
from unittest.mock import patch, MagicMock
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
import pytest
|
||||
import sexpdata
|
||||
@@ -20,23 +20,23 @@ from sexpdata import Symbol
|
||||
sys.path.insert(0, str(Path(__file__).resolve().parent.parent))
|
||||
|
||||
from commands.schematic_analysis import (
|
||||
_parse_wires,
|
||||
_parse_labels,
|
||||
_parse_symbols,
|
||||
_load_sexp,
|
||||
_extract_lib_symbols,
|
||||
_parse_lib_symbol_graphics,
|
||||
_transform_local_point,
|
||||
_line_segment_intersects_aabb,
|
||||
_point_in_rect,
|
||||
_distance,
|
||||
_aabb_overlap,
|
||||
_check_wire_overlap,
|
||||
_compute_symbol_bbox_direct,
|
||||
_distance,
|
||||
_extract_lib_symbols,
|
||||
_line_segment_intersects_aabb,
|
||||
_load_sexp,
|
||||
_parse_labels,
|
||||
_parse_lib_symbol_graphics,
|
||||
_parse_symbols,
|
||||
_parse_wires,
|
||||
_point_in_rect,
|
||||
_transform_local_point,
|
||||
compute_symbol_bbox,
|
||||
find_overlapping_elements,
|
||||
get_elements_in_region,
|
||||
find_wires_crossing_symbols,
|
||||
get_elements_in_region,
|
||||
)
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
@@ -3,8 +3,8 @@ Tests for get_schematic_component and edit_schematic_component fieldPositions su
|
||||
"""
|
||||
|
||||
import re
|
||||
import sys
|
||||
import shutil
|
||||
import sys
|
||||
import tempfile
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
@@ -268,7 +268,8 @@ def _make_handler_under_test(handler_name: str):
|
||||
This works because every _handle_* method starts with a params dict check
|
||||
before doing any file I/O or heavy imports.
|
||||
"""
|
||||
import importlib.util, types
|
||||
import importlib.util
|
||||
import types
|
||||
|
||||
# We monkey-patch sys.modules to avoid pcbnew/skip side effects
|
||||
stubs = {}
|
||||
@@ -301,8 +302,8 @@ class TestHandlerParamValidation:
|
||||
|
||||
def _make_iface_stub(self):
|
||||
"""Return a stub that exposes only the handler methods under test."""
|
||||
import types
|
||||
import importlib
|
||||
import types
|
||||
|
||||
# Build a minimal namespace that satisfies the imports inside each handler
|
||||
stub_mod = types.ModuleType("_handler_stubs")
|
||||
|
||||
@@ -119,7 +119,8 @@ class TestHandlerDispatch:
|
||||
@pytest.fixture(autouse=True)
|
||||
def load_handler_map(self):
|
||||
# Import only the dispatch table without initialising KiCAD connections
|
||||
import importlib, types
|
||||
import importlib
|
||||
import types
|
||||
|
||||
# Patch heavy imports before loading kicad_interface
|
||||
for mod in ["pcbnew", "skip"]:
|
||||
@@ -334,6 +335,7 @@ class TestPinSnapping:
|
||||
|
||||
# Re-import so the patched skip.Schematic is used
|
||||
import importlib
|
||||
|
||||
import kicad_interface
|
||||
|
||||
importlib.reload(kicad_interface)
|
||||
|
||||
@@ -4,15 +4,15 @@ KiCAD Process Management Utilities
|
||||
Detects if KiCAD is running and provides auto-launch functionality.
|
||||
"""
|
||||
|
||||
import os
|
||||
import subprocess
|
||||
import logging
|
||||
import platform
|
||||
import time
|
||||
import ctypes
|
||||
import logging
|
||||
import os
|
||||
import platform
|
||||
import subprocess
|
||||
import time
|
||||
from ctypes import wintypes
|
||||
from pathlib import Path
|
||||
from typing import Optional, List
|
||||
from typing import List, Optional
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@@ -5,12 +5,12 @@ This module provides helpers for detecting the current platform and
|
||||
getting appropriate paths for KiCAD, configuration, logs, etc.
|
||||
"""
|
||||
|
||||
import logging
|
||||
import os
|
||||
import platform
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from typing import List, Optional
|
||||
import logging
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user