style: apply Black formatting to all Python files

Add [tool.black] config to pyproject.toml and Black hook to
.pre-commit-config.yaml (rev 26.3.1), then auto-format all Python
source and test files with line-length=100, target-version=py310.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Eugene Mikhantyev
2026-03-29 13:01:08 +01:00
parent eee5bfb9ed
commit 75cead0860
53 changed files with 1847 additions and 2394 deletions

View File

@@ -10,12 +10,15 @@ from typing import Dict, Any, Optional, List, Tuple
import base64
from commands.library import LibraryManager
logger = logging.getLogger('kicad_interface')
logger = logging.getLogger("kicad_interface")
class ComponentCommands:
"""Handles component-related KiCAD operations"""
def __init__(self, board: Optional[pcbnew.BOARD] = None, library_manager: Optional[LibraryManager] = None):
def __init__(
self, board: Optional[pcbnew.BOARD] = None, library_manager: Optional[LibraryManager] = None
):
"""Initialize with optional board instance and library manager"""
self.board = board
self.library_manager = library_manager or LibraryManager()
@@ -27,7 +30,7 @@ class ComponentCommands:
return {
"success": False,
"message": "No board is loaded",
"errorDetails": "Load or create a board first"
"errorDetails": "Load or create a board first",
}
# Get parameters
@@ -43,7 +46,7 @@ class ComponentCommands:
return {
"success": False,
"message": "Missing parameters",
"errorDetails": "componentId and position are required"
"errorDetails": "componentId and position are required",
}
# Find footprint using library manager
@@ -55,13 +58,14 @@ class ComponentCommands:
suggestions = self.library_manager.search_footprints(f"*{component_id}*", limit=5)
suggestion_text = ""
if suggestions:
suggestion_text = "\n\nDid you mean one of these?\n" + \
"\n".join([f" - {s['full_name']}" for s in suggestions])
suggestion_text = "\n\nDid you mean one of these?\n" + "\n".join(
[f" - {s['full_name']}" for s in suggestions]
)
return {
"success": False,
"message": "Footprint not found",
"errorDetails": f"Could not find footprint: {component_id}{suggestion_text}"
"errorDetails": f"Could not find footprint: {component_id}{suggestion_text}",
}
library_path, footprint_name = footprint_result
@@ -78,7 +82,7 @@ class ComponentCommands:
return {
"success": False,
"message": "Internal error",
"errorDetails": "Could not determine library nickname"
"errorDetails": "Could not determine library nickname",
}
# Load the footprint
@@ -87,7 +91,7 @@ class ComponentCommands:
return {
"success": False,
"message": "Failed to load footprint",
"errorDetails": f"Could not load footprint from {library_path}/{footprint_name}"
"errorDetails": f"Could not load footprint from {library_path}/{footprint_name}",
}
# Set position
@@ -145,14 +149,10 @@ class ComponentCommands:
"component": {
"reference": module.GetReference(),
"value": module.GetValue(),
"position": {
"x": position["x"],
"y": position["y"],
"unit": position["unit"]
},
"position": {"x": position["x"], "y": position["y"], "unit": position["unit"]},
"rotation": rotation,
"layer": layer
}
"layer": layer,
},
}
except Exception as e:
@@ -160,7 +160,7 @@ class ComponentCommands:
return {
"success": False,
"message": "Failed to place component",
"errorDetails": str(e)
"errorDetails": str(e),
}
def move_component(self, params: Dict[str, Any]) -> Dict[str, Any]:
@@ -170,7 +170,7 @@ class ComponentCommands:
return {
"success": False,
"message": "No board is loaded",
"errorDetails": "Load or create a board first"
"errorDetails": "Load or create a board first",
}
reference = params.get("reference")
@@ -182,7 +182,7 @@ class ComponentCommands:
return {
"success": False,
"message": "Missing parameters",
"errorDetails": "reference and position are required"
"errorDetails": "reference and position are required",
}
# Find the component
@@ -191,7 +191,7 @@ class ComponentCommands:
return {
"success": False,
"message": "Component not found",
"errorDetails": f"Could not find component: {reference}"
"errorDetails": f"Could not find component: {reference}",
}
# Set new position
@@ -218,23 +218,17 @@ class ComponentCommands:
"message": f"Moved component: {reference}",
"component": {
"reference": reference,
"position": {
"x": position["x"],
"y": position["y"],
"unit": position["unit"]
},
"rotation": rotation if rotation is not None else module.GetOrientation().AsDegrees(),
"layer": self.board.GetLayerName(module.GetLayer())
}
"position": {"x": position["x"], "y": position["y"], "unit": position["unit"]},
"rotation": (
rotation if rotation is not None else module.GetOrientation().AsDegrees()
),
"layer": self.board.GetLayerName(module.GetLayer()),
},
}
except Exception as e:
logger.error(f"Error moving component: {str(e)}")
return {
"success": False,
"message": "Failed to move component",
"errorDetails": str(e)
}
return {"success": False, "message": "Failed to move component", "errorDetails": str(e)}
def rotate_component(self, params: Dict[str, Any]) -> Dict[str, Any]:
"""Rotate an existing component"""
@@ -243,7 +237,7 @@ class ComponentCommands:
return {
"success": False,
"message": "No board is loaded",
"errorDetails": "Load or create a board first"
"errorDetails": "Load or create a board first",
}
reference = params.get("reference")
@@ -253,7 +247,7 @@ class ComponentCommands:
return {
"success": False,
"message": "Missing parameters",
"errorDetails": "reference and angle are required"
"errorDetails": "reference and angle are required",
}
# Find the component
@@ -262,7 +256,7 @@ class ComponentCommands:
return {
"success": False,
"message": "Component not found",
"errorDetails": f"Could not find component: {reference}"
"errorDetails": f"Could not find component: {reference}",
}
# Set rotation
@@ -272,10 +266,7 @@ class ComponentCommands:
return {
"success": True,
"message": f"Rotated component: {reference}",
"component": {
"reference": reference,
"rotation": angle
}
"component": {"reference": reference, "rotation": angle},
}
except Exception as e:
@@ -283,7 +274,7 @@ class ComponentCommands:
return {
"success": False,
"message": "Failed to rotate component",
"errorDetails": str(e)
"errorDetails": str(e),
}
def delete_component(self, params: Dict[str, Any]) -> Dict[str, Any]:
@@ -293,7 +284,7 @@ class ComponentCommands:
return {
"success": False,
"message": "No board is loaded",
"errorDetails": "Load or create a board first"
"errorDetails": "Load or create a board first",
}
reference = params.get("reference")
@@ -301,7 +292,7 @@ class ComponentCommands:
return {
"success": False,
"message": "Missing reference",
"errorDetails": "reference parameter is required"
"errorDetails": "reference parameter is required",
}
# Find the component
@@ -310,23 +301,20 @@ class ComponentCommands:
return {
"success": False,
"message": "Component not found",
"errorDetails": f"Could not find component: {reference}"
"errorDetails": f"Could not find component: {reference}",
}
# Remove from board
self.board.Remove(module)
return {
"success": True,
"message": f"Deleted component: {reference}"
}
return {"success": True, "message": f"Deleted component: {reference}"}
except Exception as e:
logger.error(f"Error deleting component: {str(e)}")
return {
"success": False,
"message": "Failed to delete component",
"errorDetails": str(e)
"errorDetails": str(e),
}
def edit_component(self, params: Dict[str, Any]) -> Dict[str, Any]:
@@ -336,7 +324,7 @@ class ComponentCommands:
return {
"success": False,
"message": "No board is loaded",
"errorDetails": "Load or create a board first"
"errorDetails": "Load or create a board first",
}
reference = params.get("reference")
@@ -348,7 +336,7 @@ class ComponentCommands:
return {
"success": False,
"message": "Missing reference",
"errorDetails": "reference parameter is required"
"errorDetails": "reference parameter is required",
}
# Find the component
@@ -357,7 +345,7 @@ class ComponentCommands:
return {
"success": False,
"message": "Component not found",
"errorDetails": f"Could not find component: {reference}"
"errorDetails": f"Could not find component: {reference}",
}
# Update properties
@@ -385,17 +373,13 @@ class ComponentCommands:
"component": {
"reference": new_reference or reference,
"value": value or module.GetValue(),
"footprint": footprint or module.GetFPIDAsString()
}
"footprint": footprint or module.GetFPIDAsString(),
},
}
except Exception as e:
logger.error(f"Error editing component: {str(e)}")
return {
"success": False,
"message": "Failed to edit component",
"errorDetails": str(e)
}
return {"success": False, "message": "Failed to edit component", "errorDetails": str(e)}
def get_component_properties(self, params: Dict[str, Any]) -> Dict[str, Any]:
"""Get detailed properties of a component"""
@@ -404,7 +388,7 @@ class ComponentCommands:
return {
"success": False,
"message": "No board is loaded",
"errorDetails": "Load or create a board first"
"errorDetails": "Load or create a board first",
}
reference = params.get("reference")
@@ -412,7 +396,7 @@ class ComponentCommands:
return {
"success": False,
"message": "Missing reference",
"errorDetails": "reference parameter is required"
"errorDetails": "reference parameter is required",
}
# Find the component
@@ -421,7 +405,7 @@ class ComponentCommands:
return {
"success": False,
"message": "Component not found",
"errorDetails": f"Could not find component: {reference}"
"errorDetails": f"Could not find component: {reference}",
}
# Get position in mm
@@ -435,19 +419,15 @@ class ComponentCommands:
"reference": module.GetReference(),
"value": module.GetValue(),
"footprint": module.GetFPIDAsString(),
"position": {
"x": x_mm,
"y": y_mm,
"unit": "mm"
},
"position": {"x": x_mm, "y": y_mm, "unit": "mm"},
"rotation": module.GetOrientation().AsDegrees(),
"layer": self.board.GetLayerName(module.GetLayer()),
"attributes": {
"smd": module.GetAttributes() & pcbnew.FP_SMD,
"through_hole": module.GetAttributes() & pcbnew.FP_THROUGH_HOLE,
"board_only": module.GetAttributes() & pcbnew.FP_BOARD_ONLY
}
}
"board_only": module.GetAttributes() & pcbnew.FP_BOARD_ONLY,
},
},
}
except Exception as e:
@@ -455,7 +435,7 @@ class ComponentCommands:
return {
"success": False,
"message": "Failed to get component properties",
"errorDetails": str(e)
"errorDetails": str(e),
}
def get_component_list(self, params: Dict[str, Any]) -> Dict[str, Any]:
@@ -465,7 +445,7 @@ class ComponentCommands:
return {
"success": False,
"message": "No board is loaded",
"errorDetails": "Load or create a board first"
"errorDetails": "Load or create a board first",
}
components = []
@@ -474,30 +454,25 @@ class ComponentCommands:
x_mm = pos.x / 1000000
y_mm = pos.y / 1000000
components.append({
"reference": module.GetReference(),
"value": module.GetValue(),
"footprint": module.GetFPIDAsString(),
"position": {
"x": x_mm,
"y": y_mm,
"unit": "mm"
},
"rotation": module.GetOrientation().AsDegrees(),
"layer": self.board.GetLayerName(module.GetLayer())
})
components.append(
{
"reference": module.GetReference(),
"value": module.GetValue(),
"footprint": module.GetFPIDAsString(),
"position": {"x": x_mm, "y": y_mm, "unit": "mm"},
"rotation": module.GetOrientation().AsDegrees(),
"layer": self.board.GetLayerName(module.GetLayer()),
}
)
return {
"success": True,
"components": components
}
return {"success": True, "components": components}
except Exception as e:
logger.error(f"Error getting component list: {str(e)}")
return {
"success": False,
"message": "Failed to get component list",
"errorDetails": str(e)
"errorDetails": str(e),
}
def find_component(self, params: Dict[str, Any]) -> Dict[str, Any]:
@@ -507,7 +482,7 @@ class ComponentCommands:
return {
"success": False,
"message": "No board is loaded",
"errorDetails": "Load or create a board first"
"errorDetails": "Load or create a board first",
}
# Get search parameters
@@ -519,7 +494,7 @@ class ComponentCommands:
return {
"success": False,
"message": "Missing search criteria",
"errorDetails": "At least one of reference, value, or footprint pattern is required"
"errorDetails": "At least one of reference, value, or footprint pattern is required",
}
matches = []
@@ -539,31 +514,25 @@ class ComponentCommands:
if match:
pos = module.GetPosition()
matches.append({
"reference": module.GetReference(),
"value": module.GetValue(),
"footprint": module.GetFPIDAsString(),
"position": {
"x": pos.x / 1000000,
"y": pos.y / 1000000,
"unit": "mm"
},
"rotation": module.GetOrientation().AsDegrees(),
"layer": self.board.GetLayerName(module.GetLayer())
})
matches.append(
{
"reference": module.GetReference(),
"value": module.GetValue(),
"footprint": module.GetFPIDAsString(),
"position": {"x": pos.x / 1000000, "y": pos.y / 1000000, "unit": "mm"},
"rotation": module.GetOrientation().AsDegrees(),
"layer": self.board.GetLayerName(module.GetLayer()),
}
)
return {
"success": True,
"matchCount": len(matches),
"components": matches
}
return {"success": True, "matchCount": len(matches), "components": matches}
except Exception as e:
logger.error(f"Error finding components: {str(e)}")
return {
"success": False,
"message": "Failed to find components",
"errorDetails": str(e)
"errorDetails": str(e),
}
def get_component_pads(self, params: Dict[str, Any]) -> Dict[str, Any]:
@@ -573,7 +542,7 @@ class ComponentCommands:
return {
"success": False,
"message": "No board is loaded",
"errorDetails": "Load or create a board first"
"errorDetails": "Load or create a board first",
}
reference = params.get("reference")
@@ -581,7 +550,7 @@ class ComponentCommands:
return {
"success": False,
"message": "Missing reference",
"errorDetails": "reference parameter is required"
"errorDetails": "reference parameter is required",
}
# Find the component
@@ -590,7 +559,7 @@ class ComponentCommands:
return {
"success": False,
"message": "Component not found",
"errorDetails": f"Could not find component: {reference}"
"errorDetails": f"Could not find component: {reference}",
}
pads = []
@@ -606,7 +575,7 @@ class ComponentCommands:
pcbnew.PAD_SHAPE_TRAPEZOID: "trapezoid",
pcbnew.PAD_SHAPE_ROUNDRECT: "roundrect",
pcbnew.PAD_SHAPE_CHAMFERED_RECT: "chamfered_rect",
pcbnew.PAD_SHAPE_CUSTOM: "custom"
pcbnew.PAD_SHAPE_CUSTOM: "custom",
}
shape = shape_map.get(pad.GetShape(), "unknown")
@@ -615,29 +584,25 @@ class ComponentCommands:
pcbnew.PAD_ATTRIB_PTH: "through_hole",
pcbnew.PAD_ATTRIB_SMD: "smd",
pcbnew.PAD_ATTRIB_CONN: "connector",
pcbnew.PAD_ATTRIB_NPTH: "npth"
pcbnew.PAD_ATTRIB_NPTH: "npth",
}
pad_type = type_map.get(pad.GetAttribute(), "unknown")
pads.append({
"name": pad.GetName(),
"number": pad.GetNumber(),
"position": {
"x": pos.x / 1000000,
"y": pos.y / 1000000,
"unit": "mm"
},
"net": pad.GetNetname(),
"netCode": pad.GetNetCode(),
"shape": shape,
"type": pad_type,
"size": {
"x": size.x / 1000000,
"y": size.y / 1000000,
"unit": "mm"
},
"drillSize": pad.GetDrillSize().x / 1000000 if pad.GetDrillSize().x > 0 else None
})
pads.append(
{
"name": pad.GetName(),
"number": pad.GetNumber(),
"position": {"x": pos.x / 1000000, "y": pos.y / 1000000, "unit": "mm"},
"net": pad.GetNetname(),
"netCode": pad.GetNetCode(),
"shape": shape,
"type": pad_type,
"size": {"x": size.x / 1000000, "y": size.y / 1000000, "unit": "mm"},
"drillSize": (
pad.GetDrillSize().x / 1000000 if pad.GetDrillSize().x > 0 else None
),
}
)
# Get component position for reference
comp_pos = module.GetPosition()
@@ -648,10 +613,10 @@ class ComponentCommands:
"componentPosition": {
"x": comp_pos.x / 1000000,
"y": comp_pos.y / 1000000,
"unit": "mm"
"unit": "mm",
},
"padCount": len(pads),
"pads": pads
"pads": pads,
}
except Exception as e:
@@ -659,7 +624,7 @@ class ComponentCommands:
return {
"success": False,
"message": "Failed to get component pads",
"errorDetails": str(e)
"errorDetails": str(e),
}
def get_pad_position(self, params: Dict[str, Any]) -> Dict[str, Any]:
@@ -669,7 +634,7 @@ class ComponentCommands:
return {
"success": False,
"message": "No board is loaded",
"errorDetails": "Load or create a board first"
"errorDetails": "Load or create a board first",
}
reference = params.get("reference")
@@ -679,13 +644,13 @@ class ComponentCommands:
return {
"success": False,
"message": "Missing reference",
"errorDetails": "reference parameter is required"
"errorDetails": "reference parameter is required",
}
if not pad_name:
return {
"success": False,
"message": "Missing pad identifier",
"errorDetails": "padName or padNumber parameter is required"
"errorDetails": "padName or padNumber parameter is required",
}
# Find the component
@@ -694,7 +659,7 @@ class ComponentCommands:
return {
"success": False,
"message": "Component not found",
"errorDetails": f"Could not find component: {reference}"
"errorDetails": f"Could not find component: {reference}",
}
# Find the specific pad
@@ -705,7 +670,7 @@ class ComponentCommands:
return {
"success": False,
"message": "Pad not found",
"errorDetails": f"Pad '{pad_name}' not found on {reference}. Available pads: {', '.join(available_pads)}"
"errorDetails": f"Pad '{pad_name}' not found on {reference}. Available pads: {', '.join(available_pads)}",
}
pos = pad.GetPosition()
@@ -715,18 +680,10 @@ class ComponentCommands:
"success": True,
"reference": reference,
"padName": pad.GetNumber(),
"position": {
"x": pos.x / 1000000,
"y": pos.y / 1000000,
"unit": "mm"
},
"position": {"x": pos.x / 1000000, "y": pos.y / 1000000, "unit": "mm"},
"net": pad.GetNetname(),
"netCode": pad.GetNetCode(),
"size": {
"x": size.x / 1000000,
"y": size.y / 1000000,
"unit": "mm"
}
"size": {"x": size.x / 1000000, "y": size.y / 1000000, "unit": "mm"},
}
except Exception as e:
@@ -734,7 +691,7 @@ class ComponentCommands:
return {
"success": False,
"message": "Failed to get pad position",
"errorDetails": str(e)
"errorDetails": str(e),
}
def place_component_array(self, params: Dict[str, Any]) -> Dict[str, Any]:
@@ -744,7 +701,7 @@ class ComponentCommands:
return {
"success": False,
"message": "No board is loaded",
"errorDetails": "Load or create a board first"
"errorDetails": "Load or create a board first",
}
component_id = params.get("componentId")
@@ -757,7 +714,7 @@ class ComponentCommands:
return {
"success": False,
"message": "Missing parameters",
"errorDetails": "componentId and count are required"
"errorDetails": "componentId and count are required",
}
if pattern == "grid":
@@ -773,14 +730,14 @@ class ComponentCommands:
return {
"success": False,
"message": "Missing grid parameters",
"errorDetails": "For grid pattern, startPosition, rows, columns, spacingX, and spacingY are required"
"errorDetails": "For grid pattern, startPosition, rows, columns, spacingX, and spacingY are required",
}
if rows * columns != count:
return {
"success": False,
"message": "Invalid grid parameters",
"errorDetails": "rows * columns must equal count"
"errorDetails": "rows * columns must equal count",
}
placed_components = self._place_grid_array(
@@ -793,7 +750,7 @@ class ComponentCommands:
reference_prefix,
value,
rotation,
layer
layer,
)
elif pattern == "circular":
@@ -808,7 +765,7 @@ class ComponentCommands:
return {
"success": False,
"message": "Missing circular parameters",
"errorDetails": "For circular pattern, center, radius, and angleStep are required"
"errorDetails": "For circular pattern, center, radius, and angleStep are required",
}
placed_components = self._place_circular_array(
@@ -821,20 +778,20 @@ class ComponentCommands:
reference_prefix,
value,
rotation_offset,
layer
layer,
)
else:
return {
"success": False,
"message": "Invalid pattern",
"errorDetails": "Pattern must be 'grid' or 'circular'"
"errorDetails": "Pattern must be 'grid' or 'circular'",
}
return {
"success": True,
"message": f"Placed {count} components in {pattern} pattern",
"components": placed_components
"components": placed_components,
}
except Exception as e:
@@ -842,7 +799,7 @@ class ComponentCommands:
return {
"success": False,
"message": "Failed to place component array",
"errorDetails": str(e)
"errorDetails": str(e),
}
def align_components(self, params: Dict[str, Any]) -> Dict[str, Any]:
@@ -852,7 +809,7 @@ class ComponentCommands:
return {
"success": False,
"message": "No board is loaded",
"errorDetails": "Load or create a board first"
"errorDetails": "Load or create a board first",
}
references = params.get("references", [])
@@ -864,7 +821,7 @@ class ComponentCommands:
return {
"success": False,
"message": "Missing references",
"errorDetails": "At least two component references are required"
"errorDetails": "At least two component references are required",
}
# Find all referenced components
@@ -875,7 +832,7 @@ class ComponentCommands:
return {
"success": False,
"message": "Component not found",
"errorDetails": f"Could not find component: {ref}"
"errorDetails": f"Could not find component: {ref}",
}
components.append(module)
@@ -890,36 +847,34 @@ class ComponentCommands:
return {
"success": False,
"message": "Missing edge parameter",
"errorDetails": "Edge parameter is required for edge alignment"
"errorDetails": "Edge parameter is required for edge alignment",
}
self._align_components_to_edge(components, edge)
else:
return {
"success": False,
"message": "Invalid alignment option",
"errorDetails": "Alignment must be 'horizontal', 'vertical', or 'edge'"
"errorDetails": "Alignment must be 'horizontal', 'vertical', or 'edge'",
}
# Prepare result data
aligned_components = []
for module in components:
pos = module.GetPosition()
aligned_components.append({
"reference": module.GetReference(),
"position": {
"x": pos.x / 1000000,
"y": pos.y / 1000000,
"unit": "mm"
},
"rotation": module.GetOrientation().AsDegrees()
})
aligned_components.append(
{
"reference": module.GetReference(),
"position": {"x": pos.x / 1000000, "y": pos.y / 1000000, "unit": "mm"},
"rotation": module.GetOrientation().AsDegrees(),
}
)
return {
"success": True,
"message": f"Aligned {len(components)} components",
"alignment": alignment,
"distribution": distribution,
"components": aligned_components
"components": aligned_components,
}
except Exception as e:
@@ -927,7 +882,7 @@ class ComponentCommands:
return {
"success": False,
"message": "Failed to align components",
"errorDetails": str(e)
"errorDetails": str(e),
}
def duplicate_component(self, params: Dict[str, Any]) -> Dict[str, Any]:
@@ -937,7 +892,7 @@ class ComponentCommands:
return {
"success": False,
"message": "No board is loaded",
"errorDetails": "Load or create a board first"
"errorDetails": "Load or create a board first",
}
reference = params.get("reference")
@@ -949,7 +904,7 @@ class ComponentCommands:
return {
"success": False,
"message": "Missing parameters",
"errorDetails": "reference and newReference are required"
"errorDetails": "reference and newReference are required",
}
# Find the source component
@@ -958,7 +913,7 @@ class ComponentCommands:
return {
"success": False,
"message": "Component not found",
"errorDetails": f"Could not find component: {reference}"
"errorDetails": f"Could not find component: {reference}",
}
# Check if new reference already exists
@@ -966,7 +921,7 @@ class ComponentCommands:
return {
"success": False,
"message": "Reference already exists",
"errorDetails": f"A component with reference {new_reference} already exists"
"errorDetails": f"A component with reference {new_reference} already exists",
}
# Create new footprint with the same properties
@@ -1014,14 +969,10 @@ class ComponentCommands:
"reference": new_reference,
"value": new_module.GetValue(),
"footprint": new_module.GetFPIDAsString(),
"position": {
"x": pos.x / 1000000,
"y": pos.y / 1000000,
"unit": "mm"
},
"position": {"x": pos.x / 1000000, "y": pos.y / 1000000, "unit": "mm"},
"rotation": new_module.GetOrientation().AsDegrees(),
"layer": self.board.GetLayerName(new_module.GetLayer())
}
"layer": self.board.GetLayerName(new_module.GetLayer()),
},
}
except Exception as e:
@@ -1029,12 +980,22 @@ class ComponentCommands:
return {
"success": False,
"message": "Failed to duplicate component",
"errorDetails": str(e)
"errorDetails": str(e),
}
def _place_grid_array(self, component_id: str, start_position: Dict[str, Any],
rows: int, columns: int, spacing_x: float, spacing_y: float,
reference_prefix: str, value: str, rotation: float, layer: str) -> List[Dict[str, Any]]:
def _place_grid_array(
self,
component_id: str,
start_position: Dict[str, Any],
rows: int,
columns: int,
spacing_x: float,
spacing_y: float,
reference_prefix: str,
value: str,
rotation: float,
layer: str,
) -> List[Dict[str, Any]]:
"""Place components in a grid pattern and return the list of placed components"""
placed = []
@@ -1058,24 +1019,35 @@ class ComponentCommands:
component_reference = f"{reference_prefix}{index}"
# Place component
result = self.place_component({
"componentId": component_id,
"position": {"x": x, "y": y, "unit": unit},
"reference": component_reference,
"value": value,
"rotation": rotation,
"layer": layer
})
result = self.place_component(
{
"componentId": component_id,
"position": {"x": x, "y": y, "unit": unit},
"reference": component_reference,
"value": value,
"rotation": rotation,
"layer": layer,
}
)
if result["success"]:
placed.append(result["component"])
return placed
def _place_circular_array(self, component_id: str, center: Dict[str, Any],
radius: float, count: int, angle_start: float,
angle_step: float, reference_prefix: str,
value: str, rotation_offset: float, layer: str) -> List[Dict[str, Any]]:
def _place_circular_array(
self,
component_id: str,
center: Dict[str, Any],
radius: float,
count: int,
angle_start: float,
angle_step: float,
reference_prefix: str,
value: str,
rotation_offset: float,
layer: str,
) -> List[Dict[str, Any]]:
"""Place components in a circular pattern and return the list of placed components"""
placed = []
@@ -1098,22 +1070,25 @@ class ComponentCommands:
component_rotation = angle + rotation_offset
# Place component
result = self.place_component({
"componentId": component_id,
"position": {"x": x, "y": y, "unit": unit},
"reference": component_reference,
"value": value,
"rotation": component_rotation,
"layer": layer
})
result = self.place_component(
{
"componentId": component_id,
"position": {"x": x, "y": y, "unit": unit},
"reference": component_reference,
"value": value,
"rotation": component_rotation,
"layer": layer,
}
)
if result["success"]:
placed.append(result["component"])
return placed
def _align_components_horizontally(self, components: List[pcbnew.FOOTPRINT],
distribution: str, spacing: Optional[float]) -> None:
def _align_components_horizontally(
self, components: List[pcbnew.FOOTPRINT], distribution: str, spacing: Optional[float]
) -> None:
"""Align components horizontally and optionally distribute them"""
if not components:
return
@@ -1157,8 +1132,9 @@ class ComponentCommands:
x_current += spacing_nm
components[i].SetPosition(pcbnew.VECTOR2I(x_current, pos.y))
def _align_components_vertically(self, components: List[pcbnew.FOOTPRINT],
distribution: str, spacing: Optional[float]) -> None:
def _align_components_vertically(
self, components: List[pcbnew.FOOTPRINT], distribution: str, spacing: Optional[float]
) -> None:
"""Align components vertically and optionally distribute them"""
if not components:
return