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:
Eugene Mikhantyev
2026-03-29 13:02:24 +01:00
parent 75cead0860
commit c44bd9205d
50 changed files with 226 additions and 179 deletions

View File

@@ -16,3 +16,9 @@ repos:
- id: black
language_version: python3
args: [--config=pyproject.toml]
- repo: https://github.com/pycqa/isort
rev: 8.0.1
hooks:
- id: isort
args: [--settings-path=pyproject.toml]

View File

@@ -6,3 +6,7 @@ requires-python = ">=3.10"
[tool.black]
line-length = 100
target-version = ["py310"]
[tool.isort]
profile = "black"
line_length = 100

View File

@@ -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",

View File

@@ -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")

View File

@@ -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")

View File

@@ -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")

View File

@@ -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")

View File

@@ -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")

View File

@@ -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")

View File

@@ -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")

View File

@@ -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:

View File

@@ -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

View File

@@ -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:

View File

@@ -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

View File

@@ -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")

View File

@@ -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

View File

@@ -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")

View File

@@ -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")

View File

@@ -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")

View File

@@ -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")

View File

@@ -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:

View File

@@ -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:

View File

@@ -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")

View File

@@ -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))

View File

@@ -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")

View File

@@ -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")

View File

@@ -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")

View File

@@ -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")

View File

@@ -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")

View File

@@ -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

View File

@@ -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")

View File

@@ -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))

View File

@@ -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"

View File

@@ -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__)

View File

@@ -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__)

View File

@@ -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()

View File

@@ -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__)

View File

@@ -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()

View File

@@ -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

View File

@@ -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")

View File

@@ -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

View File

@@ -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__)))

View 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,
)

View File

@@ -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,
)
# ---------------------------------------------------------------------------

View File

@@ -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

View File

@@ -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")

View File

@@ -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)

View File

@@ -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__)

View File

@@ -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__)

View File

@@ -4,11 +4,12 @@ Tests for platform_helper utility
These are unit tests that work on all platforms.
"""
import pytest
import platform
from pathlib import Path
import sys
import os
import platform
import sys
from pathlib import Path
import pytest
# Add parent directory to path to import utils
sys.path.insert(0, str(Path(__file__).parent.parent / "python"))