From a71fef6f13dac11be9904b76bc59e80558639b7d Mon Sep 17 00:00:00 2001 From: Billy Huddleston Date: Wed, 31 Dec 2025 13:21:14 -0500 Subject: [PATCH] CAM: Remove colons from labels, fix lint, and update imports Removed explicit colons from all form labels. Fixed lint warnings and replaced wildcard imports with explicit imports for clarity and maintainability. src/Mod/CAM/Path/Machine/ui/editor/machine_editor.py: - Removed ':' from all form labels - Fixed lint warnings (missing docstrings, empty except, etc.) - Replaced wildcard imports with explicit imports src/Mod/CAM/Path/Machine/models/__init__.py: - Updated __all__ and imports for explicit API src/Mod/CAM/Path/Tool/assets/ui/preferences.py: - Updated imports to use package-level import src/Mod/CAM/Path/Machine/models/machine.py: - Added explanatory comments to empty except blocks - Fixed duplicate variable assignment - Added missing class docstrings src/Mod/CAM/CAMTests/TestMachine.py: - Fixed unused variable warning by using returned filepath --- src/Mod/CAM/CAMTests/TestMachine.py | 4 +- src/Mod/CAM/Path/Machine/models/__init__.py | 28 ++++++++ src/Mod/CAM/Path/Machine/models/machine.py | 32 +++++----- .../Path/Machine/ui/editor/machine_editor.py | 64 +++++++++---------- .../CAM/Path/Tool/assets/ui/preferences.py | 3 +- 5 files changed, 77 insertions(+), 54 deletions(-) diff --git a/src/Mod/CAM/CAMTests/TestMachine.py b/src/Mod/CAM/CAMTests/TestMachine.py index f4f179b92a..5ff6364d22 100644 --- a/src/Mod/CAM/CAMTests/TestMachine.py +++ b/src/Mod/CAM/CAMTests/TestMachine.py @@ -11,10 +11,8 @@ # *************************************************************************** import FreeCAD -import unittest import tempfile import pathlib -import json import CAMTests.PathTestUtils as PathTestUtils from Path.Machine.models.machine import ( Machine, @@ -406,7 +404,7 @@ class TestMachineFactory(PathTestUtils.PathTestBase): # Save and load filepath = MachineFactory.save_configuration(machine, "complex.fcm") - loaded = MachineFactory.load_configuration("complex.fcm") + loaded = MachineFactory.load_configuration(filepath) # Verify all components self.assertEqual(loaded.name, machine.name) diff --git a/src/Mod/CAM/Path/Machine/models/__init__.py b/src/Mod/CAM/Path/Machine/models/__init__.py index 0e2dc0e8a2..1287852469 100644 --- a/src/Mod/CAM/Path/Machine/models/__init__.py +++ b/src/Mod/CAM/Path/Machine/models/__init__.py @@ -20,3 +20,31 @@ # * . * # * * # *************************************************************************** + +from .machine import ( + Machine, + MachineFactory, + LinearAxis, + RotaryAxis, + Spindle, + MachineUnits, + MotionMode, + OutputUnits, + OutputOptions, + GCodeBlocks, + ProcessingOptions, +) + +__all__ = [ + "Machine", + "MachineFactory", + "LinearAxis", + "RotaryAxis", + "Spindle", + "MachineUnits", + "MotionMode", + "OutputUnits", + "OutputOptions", + "GCodeBlocks", + "ProcessingOptions", +] diff --git a/src/Mod/CAM/Path/Machine/models/machine.py b/src/Mod/CAM/Path/Machine/models/machine.py index 0baed3fc83..350ba65349 100644 --- a/src/Mod/CAM/Path/Machine/models/machine.py +++ b/src/Mod/CAM/Path/Machine/models/machine.py @@ -349,6 +349,14 @@ class Spindle: @dataclass class Machine: + """Represents a CNC machine configuration with axes, spindles, and output settings. + + This class encapsulates all machine parameters including linear and rotary axes, + spindles, post-processor settings, and G-code generation options. It provides + methods for serialization to/from JSON and various factory methods for common + machine configurations (3-axis, 4-axis, 5-axis). + """ + def __init__( self, name: str = "Default Machine", configuration_units: str = "metric", **kwargs ): @@ -947,22 +955,6 @@ class Machine: return data - def _initialize_3axis_config(self) -> None: - """Initialize as a standard 3-axis XYZ configuration (no rotary axes)""" - self.name = self.name or "3-Axis XYZ Configuration" - self.linear_axes = { - "X": LinearAxis("X", FreeCAD.Vector(1, 0, 0)), - "Y": LinearAxis("Y", FreeCAD.Vector(0, 1, 0)), - "Z": LinearAxis("Z", FreeCAD.Vector(0, 0, 1)), - } - - @classmethod - def create_3axis_config(cls) -> "Machine": - """Create standard 3-axis XYZ configuration (no rotary axes)""" - config = cls("3-Axis XYZ Configuration") - config._initialize_3axis_config() - return config - def _initialize_3axis_config(self) -> None: """Initialize as a standard 3-axis XYZ configuration (no rotary axes)""" self.linear_axes = { @@ -975,6 +967,13 @@ class Machine: self.secondary_rotary_axis = None self.compound_moves = True + @classmethod + def create_3axis_config(cls) -> "Machine": + """Create standard 3-axis XYZ configuration (no rotary axes)""" + config = cls("3-Axis XYZ Configuration") + config._initialize_3axis_config() + return config + def _initialize_4axis_A_config(self, a_limits=(-120, 120)) -> None: """Initialize as a 4-axis XYZA configuration (rotary table around X)""" self._initialize_3axis_config() @@ -1320,6 +1319,7 @@ class MachineFactory: name = cls.get_machine_display_name(p.name) machines.append((name, p.name)) except Exception: + # Failed to access machine directory or read files, return default list only pass return machines diff --git a/src/Mod/CAM/Path/Machine/ui/editor/machine_editor.py b/src/Mod/CAM/Path/Machine/ui/editor/machine_editor.py index 2dec6e594a..1d7b073e03 100644 --- a/src/Mod/CAM/Path/Machine/ui/editor/machine_editor.py +++ b/src/Mod/CAM/Path/Machine/ui/editor/machine_editor.py @@ -22,11 +22,12 @@ # *************************************************************************** from PySide import QtGui, QtCore import FreeCAD +import Path import json -from typing import Optional, Dict, Any, get_type_hints, get_origin, get_args -from dataclasses import fields, is_dataclass +from typing import Optional, Dict, Any, get_origin, get_args +from dataclasses import fields from enum import Enum -from ...models.machine import * +from ...models import Machine, MachineFactory, LinearAxis, RotaryAxis, Spindle from ....Main.Gui.Editor import CodeEditor from Path.Post.Processor import PostProcessorFactory import re @@ -241,7 +242,7 @@ class DataclassGUIGenerator: ) label = DataclassGUIGenerator.get_field_label(field.name) - layout.addRow(label + ":", widget) + layout.addRow(label, widget) widgets[field.name] = widget return group, widgets @@ -615,34 +616,34 @@ class MachineEditorDialog(QtGui.QDialog): self.name_edit = QtGui.QLineEdit() self.name_edit.textChanged.connect(self._on_name_changed) - layout.addRow(translate("CAM_MachineEditor", "Name:"), self.name_edit) + layout.addRow(translate("CAM_MachineEditor", "Name"), self.name_edit) self.manufacturer_edit = QtGui.QLineEdit() self.manufacturer_edit.textChanged.connect(self._on_manufacturer_changed) - layout.addRow(translate("CAM_MachineEditor", "Manufacturer:"), self.manufacturer_edit) + layout.addRow(translate("CAM_MachineEditor", "Manufacturer"), self.manufacturer_edit) self.description_edit = QtGui.QLineEdit() self.description_edit.textChanged.connect(self._on_description_changed) - layout.addRow(translate("CAM_MachineEditor", "Description:"), self.description_edit) + layout.addRow(translate("CAM_MachineEditor", "Description"), self.description_edit) self.units_combo = QtGui.QComboBox() self.units_combo.addItem(translate("CAM_MachineEditor", "Metric"), "metric") self.units_combo.addItem(translate("CAM_MachineEditor", "Imperial"), "imperial") self.units_combo.currentIndexChanged.connect(self._on_units_changed) - layout.addRow(translate("CAM_MachineEditor", "Units:"), self.units_combo) + layout.addRow(translate("CAM_MachineEditor", "Units"), self.units_combo) self.type_combo = QtGui.QComboBox() for key, value in self.MACHINE_TYPES.items(): self.type_combo.addItem(value["name"], key) self.type_combo.currentIndexChanged.connect(self._on_type_changed) - layout.addRow(translate("CAM_MachineEditor", "Type:"), self.type_combo) + layout.addRow(translate("CAM_MachineEditor", "Type"), self.type_combo) self.spindle_count_combo = QtGui.QComboBox() for i in range(1, 10): # 1 to 9 spindles self.spindle_count_combo.addItem(str(i), i) self.spindle_count_combo.currentIndexChanged.connect(self.update_spindles) layout.addRow( - translate("CAM_MachineEditor", "Number of Spindles:"), self.spindle_count_combo + translate("CAM_MachineEditor", "Number of Spindles"), self.spindle_count_combo ) # Axes group @@ -743,14 +744,14 @@ class MachineEditorDialog(QtGui.QDialog): ) axis_layout = QtGui.QHBoxLayout() - axis_layout.addWidget(QtGui.QLabel("Min:")) + axis_layout.addWidget(QtGui.QLabel("Min")) axis_layout.addWidget(min_edit) - axis_layout.addWidget(QtGui.QLabel("Max:")) + axis_layout.addWidget(QtGui.QLabel("Max")) axis_layout.addWidget(max_edit) - axis_layout.addWidget(QtGui.QLabel("Max Vel:")) + axis_layout.addWidget(QtGui.QLabel("Max Vel")) axis_layout.addWidget(vel_edit) - linear_layout.addRow(f"{axis}:", axis_layout) + linear_layout.addRow(f"{axis}", axis_layout) self.axis_edits[axis] = { "min": min_edit, "max": max_edit, @@ -832,22 +833,22 @@ class MachineEditorDialog(QtGui.QDialog): axis_grid = QtGui.QGridLayout() # Row 0: Min, Max, Vel - axis_grid.addWidget(QtGui.QLabel("Min:"), 0, 0, QtCore.Qt.AlignRight) + axis_grid.addWidget(QtGui.QLabel("Min"), 0, 0, QtCore.Qt.AlignRight) axis_grid.addWidget(min_edit, 0, 1) - axis_grid.addWidget(QtGui.QLabel("Max:"), 0, 2, QtCore.Qt.AlignRight) + axis_grid.addWidget(QtGui.QLabel("Max"), 0, 2, QtCore.Qt.AlignRight) axis_grid.addWidget(max_edit, 0, 3) - axis_grid.addWidget(QtGui.QLabel("Max Vel:"), 0, 4, QtCore.Qt.AlignRight) + axis_grid.addWidget(QtGui.QLabel("Max Vel"), 0, 4, QtCore.Qt.AlignRight) axis_grid.addWidget(vel_edit, 0, 5) # Row 1: Sequence, Joint, Prefer+ - axis_grid.addWidget(QtGui.QLabel("Sequence:"), 1, 0, QtCore.Qt.AlignRight) + axis_grid.addWidget(QtGui.QLabel("Sequence"), 1, 0, QtCore.Qt.AlignRight) axis_grid.addWidget(sequence_spin, 1, 1) - axis_grid.addWidget(QtGui.QLabel("Joint:"), 1, 2, QtCore.Qt.AlignRight) + axis_grid.addWidget(QtGui.QLabel("Joint"), 1, 2, QtCore.Qt.AlignRight) axis_grid.addWidget(joint_combo, 1, 3) - axis_grid.addWidget(QtGui.QLabel("Prefer+:"), 1, 4, QtCore.Qt.AlignRight) + axis_grid.addWidget(QtGui.QLabel("Prefer+"), 1, 4, QtCore.Qt.AlignRight) axis_grid.addWidget(prefer_positive, 1, 5) - rotary_layout.addRow(f"{axis}:", axis_grid) + rotary_layout.addRow(f"{axis}", axis_grid) self.axis_edits[axis] = { "min": min_edit, "max": max_edit, @@ -926,14 +927,14 @@ class MachineEditorDialog(QtGui.QDialog): name_edit.textChanged.connect( lambda text, idx=i: self._on_spindle_field_changed(idx, "name", text) ) - layout.addRow("Name:", name_edit) + layout.addRow("Name", name_edit) id_edit = QtGui.QLineEdit() id_edit.setText(spindle.id if spindle and spindle.id else f"spindle{i+1}") id_edit.textChanged.connect( lambda text, idx=i: self._on_spindle_field_changed(idx, "id", text) ) - layout.addRow("ID:", id_edit) + layout.addRow("ID", id_edit) max_power_edit = QtGui.QDoubleSpinBox() max_power_edit.setRange(0, 100) @@ -941,7 +942,7 @@ class MachineEditorDialog(QtGui.QDialog): max_power_edit.valueChanged.connect( lambda value, idx=i: self._on_spindle_field_changed(idx, "max_power_kw", value) ) - layout.addRow("Max Power (kW):", max_power_edit) + layout.addRow("Max Power (kW)", max_power_edit) max_rpm_edit = QtGui.QSpinBox() max_rpm_edit.setRange(0, 100000) @@ -949,7 +950,7 @@ class MachineEditorDialog(QtGui.QDialog): max_rpm_edit.valueChanged.connect( lambda value, idx=i: self._on_spindle_field_changed(idx, "max_rpm", value) ) - layout.addRow("Max RPM:", max_rpm_edit) + layout.addRow("Max RPM", max_rpm_edit) min_rpm_edit = QtGui.QSpinBox() min_rpm_edit.setRange(0, 100000) @@ -957,7 +958,7 @@ class MachineEditorDialog(QtGui.QDialog): min_rpm_edit.valueChanged.connect( lambda value, idx=i: self._on_spindle_field_changed(idx, "min_rpm", value) ) - layout.addRow("Min RPM:", min_rpm_edit) + layout.addRow("Min RPM", min_rpm_edit) tool_change_combo = QtGui.QComboBox() tool_change_combo.addItem("Manual", "manual") @@ -1016,7 +1017,7 @@ class MachineEditorDialog(QtGui.QDialog): ) self.postProcessorDefaultTooltip = translate("CAM_MachineEditor", "Select a post processor") self.post_processor_combo.setToolTip(self.postProcessorDefaultTooltip) - pp_layout.addRow("Post Processor:", self.post_processor_combo) + pp_layout.addRow("Post Processor", self.post_processor_combo) self.post_widgets["postprocessor_file_name"] = self.post_processor_combo self.post_processor_args_edit = QtGui.QLineEdit() @@ -1027,7 +1028,7 @@ class MachineEditorDialog(QtGui.QDialog): "CAM_MachineEditor", "Additional arguments" ) self.post_processor_args_edit.setToolTip(self.postProcessorArgsDefaultTooltip) - pp_layout.addRow("Arguments:", self.post_processor_args_edit) + pp_layout.addRow("Arguments", self.post_processor_args_edit) self.post_widgets["postprocessor_args"] = self.post_processor_args_edit layout.addWidget(pp_group) @@ -1301,10 +1302,6 @@ class MachineEditorDialog(QtGui.QDialog): # Get units for suffixes in populate units = self.units_combo.itemData(self.units_combo.currentIndex()) - length_suffix = " mm" if units == "metric" else " in" - vel_suffix = " mm/min" if units == "metric" else " in/min" - angle_suffix = " deg" - angle_vel_suffix = " deg/min" # Update axes UI after loading machine data self.update_axes() @@ -1432,7 +1429,8 @@ class MachineEditorDialog(QtGui.QDialog): current_name = current_machine.name.lower() if machine_name_lower == current_name: current_name_allowed = True - except: + except Exception: + # Failed to load current machine configuration, assume name is not allowed pass if machine_name_lower in existing_names_lower and not current_name_allowed: diff --git a/src/Mod/CAM/Path/Tool/assets/ui/preferences.py b/src/Mod/CAM/Path/Tool/assets/ui/preferences.py index f51bb90fa3..ad6b751bc8 100644 --- a/src/Mod/CAM/Path/Tool/assets/ui/preferences.py +++ b/src/Mod/CAM/Path/Tool/assets/ui/preferences.py @@ -25,10 +25,9 @@ import pathlib import tempfile import FreeCAD import Path -import json from PySide import QtGui, QtCore from ....Machine.ui.editor import MachineEditorDialog -from ....Machine.models.machine import MachineFactory +from ....Machine.models import MachineFactory translate = FreeCAD.Qt.translate