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