diff --git a/src/Mod/CAM/CAMTests/TestRefactoredCentroidPost.py b/src/Mod/CAM/CAMTests/TestRefactoredCentroidPost.py index 0d172d24b3..a545fb2966 100644 --- a/src/Mod/CAM/CAMTests/TestRefactoredCentroidPost.py +++ b/src/Mod/CAM/CAMTests/TestRefactoredCentroidPost.py @@ -141,14 +141,14 @@ G53 G00 G17 G21 ;Begin operation G54 -;End operation: Fixture +;End operation ;Begin operation ;TC: Default Tool ;Begin toolchange M6 T1 -;End operation: TC: Default Tool +;End operation ;Begin operation -;End operation: Profile +;End operation ;Begin postamble M5 M25 diff --git a/src/Mod/CAM/CAMTests/TestRefactoredTestDressupPost.py b/src/Mod/CAM/CAMTests/TestRefactoredTestDressupPost.py new file mode 100644 index 0000000000..6b57bbea1c --- /dev/null +++ b/src/Mod/CAM/CAMTests/TestRefactoredTestDressupPost.py @@ -0,0 +1,155 @@ +# -*- coding: utf-8 -*- +# *************************************************************************** +# * Copyright (c) 2022 sliptonic * +# * Copyright (c) 2022-2025 Larry Woestman * +# * * +# * This program is free software; you can redistribute it and/or modify * +# * it under the terms of the GNU Lesser General Public License (LGPL) * +# * as published by the Free Software Foundation; either version 2 of * +# * the License, or (at your option) any later version. * +# * for detail see the LICENCE text file. * +# * * +# * This program is distributed in the hope that it will be useful, * +# * but WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +# * GNU Library General Public License for more details. * +# * * +# * You should have received a copy of the GNU Library General Public * +# * License along with this program; if not, write to the Free Software * +# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * +# * USA * +# * * +# *************************************************************************** + +import FreeCAD + +import Path +import CAMTests.PathTestUtils as PathTestUtils +from Path.Post.Processor import PostProcessorFactory +import Path.Dressup.Utils as PathDressup + + +Path.Log.setLevel(Path.Log.Level.DEBUG, Path.Log.thisModule()) +Path.Log.trackModule(Path.Log.thisModule()) + + +class TestRefactoredTestDressupPost(PathTestUtils.PathTestBase): + """Test the refactored_test_post.py postprocessor command line arguments.""" + + @classmethod + def setUpClass(cls): + """setUpClass()... + + This method is called upon instantiation of this test class. Add code + and objects here that are needed for the duration of the test() methods + in this class. In other words, set up the 'global' test environment + here; use the `setUp()` method to set up a 'local' test environment. + This method does not have access to the class `self` reference, but it + is able to call static methods within this same class. + """ + FreeCAD.ConfigSet("SuppressRecomputeRequiredDialog", "True") + cls.doc = FreeCAD.open(FreeCAD.getHomePath() + "/Mod/CAM/CAMTests/dressuptest.FCStd") + cls.job = cls.doc.getObject("Job") + cls.post = PostProcessorFactory.get_post_processor(cls.job, "refactored_test") + + # there are 4 operations in dressuptest.FCStd + # every operation uses a different ToolController + # each operation uses one more dressup to check nested dressups also work correctly + + cls.ops = cls.job.Operations.Group + + @classmethod + def tearDownClass(cls): + """tearDownClass()... + + This method is called prior to destruction of this test class. Add + code and objects here that cleanup the test environment after the + test() methods in this class have been executed. This method does + not have access to the class `self` reference. This method is able + to call static methods within this same class. + """ + FreeCAD.closeDocument(cls.doc.Name) + FreeCAD.ConfigSet("SuppressRecomputeRequiredDialog", "") + + # Setup and tear down methods called before and after each unit test + + def setUp(self): + """setUp()... + + This method is called prior to each `test()` method. Add code and + objects here that are needed for multiple `test()` methods. + """ + # allow a full length "diff" if an error occurs + self.maxDiff = None + # + # reinitialize the postprocessor data structures between tests + # + self.post.reinitialize() + + def tearDown(self): + """tearDown()... + + This method is called after each test() method. Add cleanup instructions here. + Such cleanup instructions will likely undo those in the setUp() method. + """ + pass + + def test001(self): + # test handling of Active state in postprocessor and nested dressups + + self.post.values["OUTPUT_COMMENTS"] = True + self.post.values["SHOW_OPERATION_LABELS"] = True + + # set all operations to Active = False + + for op in self.ops: + PathDressup.baseOp(op).Active = False + + # check that none of the operations is in the output + + gcode = self.post.export()[0][1].splitlines() + + for op in self.ops: + expected = "(Begin operation: " + op.Label + ")" + self.assertNotIn(expected, gcode) + + # set all operations back to Active = True + + for op in self.ops: + PathDressup.baseOp(op).Active = True + + # check that all operations are in the output + + gcode = self.post.export()[0][1].splitlines() + + for op in self.ops: + expected = "(Begin operation: " + op.Label + ")" + self.assertIn(expected, gcode) + + def test002(self): + # test handling of ToolController in postprocessor and nested dressups + + self.post.values["OUTPUT_TOOL_CHANGE"] = True + + gcode = self.post.export()[0][1].splitlines() + + self.assertIn("M6 T1", gcode) + self.assertIn("M6 T2", gcode) + self.assertIn("M6 T3", gcode) + self.assertIn("M6 T4", gcode) + + def test003(self): + # test handling of CoolantMode in postprocessor and nested dressups + + self.post.values["ENABLE_COOLANT"] = True + + for op in self.ops: + base = PathDressup.baseOp(op) + base.CoolantMode = "Mist" + + gcode = self.post.export()[0][1].splitlines() + + self.assertIn("M7", gcode) + self.assertIn("M9", gcode) + + base.CoolantMode = "None" diff --git a/src/Mod/CAM/CAMTests/TestRefactoredTestPost.py b/src/Mod/CAM/CAMTests/TestRefactoredTestPost.py index 58b05f44a6..d58ad8a0a9 100644 --- a/src/Mod/CAM/CAMTests/TestRefactoredTestPost.py +++ b/src/Mod/CAM/CAMTests/TestRefactoredTestPost.py @@ -306,15 +306,15 @@ G90 G21 (Begin operation) G54 -(Finish operation: Fixture) +(Finish operation) (Begin operation) (TC: Default Tool) (Begin toolchange) (M6 T1) -(Finish operation: TC: Default Tool) +(Finish operation) (Begin operation) (comment with spaces) -(Finish operation: Profile) +(Finish operation) (Begin postamble) """, "--command_space=' ' --comments", @@ -326,15 +326,15 @@ G90 G21 (Begin operation) G54 -(Finish operation: Fixture) +(Finish operation) (Begin operation) (TC: Default Tool) (Begin toolchange) (M6T1) -(Finish operation: TC: Default Tool) +(Finish operation) (Begin operation) (comment with spaces) -(Finish operation: Profile) +(Finish operation) (Begin postamble) """, "--command_space='' --comments", @@ -352,15 +352,15 @@ G90 G21 (Begin operation) G54 -(Finish operation: Fixture) +(Finish operation) (Begin operation) (TC: Default Tool) (Begin toolchange) (M6 T1) -(Finish operation: TC: Default Tool) +(Finish operation) (Begin operation) (comment with spaces) -(Finish operation: Profile) +(Finish operation) (Begin postamble) """, "--comments", @@ -372,15 +372,15 @@ G90 G21 ;Begin operation G54 -;Finish operation: Fixture +;Finish operation ;Begin operation ;TC: Default Tool ;Begin toolchange ;M6 T1 -;Finish operation: TC: Default Tool +;Finish operation ;Begin operation ;comment with spaces -;Finish operation: Profile +;Finish operation ;Begin postamble """, "--comment_symbol=';' --comments", @@ -392,15 +392,15 @@ G90 G21 !Begin operation G54 -!Finish operation: Fixture +!Finish operation !Begin operation !TC: Default Tool !Begin toolchange !M6 T1 -!Finish operation: TC: Default Tool +!Finish operation !Begin operation !comment with spaces -!Finish operation: Profile +!Finish operation !Begin postamble """, "--comment_symbol='!' --comments", @@ -471,14 +471,14 @@ G54 self.assertEqual(split_gcode[6], "G21") self.assertEqual(split_gcode[7], "(Begin operation)") self.assertEqual(split_gcode[8], "G54") - self.assertEqual(split_gcode[9], "(Finish operation: Fixture)") + self.assertEqual(split_gcode[9], "(Finish operation)") self.assertEqual(split_gcode[10], "(Begin operation)") self.assertEqual(split_gcode[11], "(TC: Default Tool)") self.assertEqual(split_gcode[12], "(Begin toolchange)") self.assertEqual(split_gcode[13], "(M6 T1)") - self.assertEqual(split_gcode[14], "(Finish operation: TC: Default Tool)") + self.assertEqual(split_gcode[14], "(Finish operation)") self.assertEqual(split_gcode[15], "(Begin operation)") - self.assertEqual(split_gcode[16], "(Finish operation: Profile)") + self.assertEqual(split_gcode[16], "(Finish operation)") self.assertEqual(split_gcode[17], "(Begin postamble)") # Test with comments without header. @@ -487,14 +487,14 @@ G90 G21 (Begin operation) G54 -(Finish operation: Fixture) +(Finish operation) (Begin operation) (TC: Default Tool) (Begin toolchange) (M6 T1) -(Finish operation: TC: Default Tool) +(Finish operation) (Begin operation) -(Finish operation: Profile) +(Finish operation) (Begin postamble) """ self.job.PostProcessorArgs = "--comments --no-header" diff --git a/src/Mod/CAM/CAMTests/TestRefactoredTestPostGCodes.py b/src/Mod/CAM/CAMTests/TestRefactoredTestPostGCodes.py index aff6c073de..93788b8737 100644 --- a/src/Mod/CAM/CAMTests/TestRefactoredTestPostGCodes.py +++ b/src/Mod/CAM/CAMTests/TestRefactoredTestPostGCodes.py @@ -768,12 +768,12 @@ G90 G21 (Begin operation) G54 -(Finish operation: Fixture) +(Finish operation) (Begin operation) (TC: Default Tool) (Begin toolchange) (M6 T1) -(Finish operation: TC: Default Tool) +(Finish operation) (Begin operation) G0 X1.000 Y2.000 G0 Z8.000 @@ -795,7 +795,7 @@ G1 Z0.000 F7380.000 G0 Z5.000 (G80) G90 -(Finish operation: Profile) +(Finish operation) (Begin postamble) """, "--comments --translate_drill", @@ -865,12 +865,12 @@ G90 G21 (Begin operation) G54 -(Finish operation: Fixture) +(Finish operation) (Begin operation) (TC: Default Tool) (Begin toolchange) (M6 T1) -(Finish operation: TC: Default Tool) +(Finish operation) (Begin operation) G0 X1.000 Y2.000 G0 Z8.000 @@ -894,7 +894,7 @@ G0 Z13.000 G91 (G80) G90 -(Finish operation: Profile) +(Finish operation) (Begin postamble) """, "--comments --translate_drill", @@ -951,12 +951,12 @@ G90 G21 (Begin operation) G54 -(Finish operation: Fixture) +(Finish operation) (Begin operation) (TC: Default Tool) (Begin toolchange) (M6 T1) -(Finish operation: TC: Default Tool) +(Finish operation) (Begin operation) G0 X1.000 Y2.000 G0 Z8.000 @@ -969,7 +969,7 @@ G1 Z0.000 F7380.000 G0 Z5.000 (G80) G90 -(Finish operation: Profile) +(Finish operation) (Begin postamble) """, "--comments --translate_drill", @@ -1030,12 +1030,12 @@ G90 G21 (Begin operation) G54 -(Finish operation: Fixture) +(Finish operation) (Begin operation) (TC: Default Tool) (Begin toolchange) (M6 T1) -(Finish operation: TC: Default Tool) +(Finish operation) (Begin operation) G0 X1.000 Y2.000 G0 Z8.000 @@ -1050,7 +1050,7 @@ G0 Z13.000 G91 (G80) G90 -(Finish operation: Profile) +(Finish operation) (Begin postamble) """, "--comments --translate_drill", @@ -1108,12 +1108,12 @@ G90 G21 (Begin operation) G54 -(Finish operation: Fixture) +(Finish operation) (Begin operation) (TC: Default Tool) (Begin toolchange) (M6 T1) -(Finish operation: TC: Default Tool) +(Finish operation) (Begin operation) G0 X1.000 Y2.000 G0 Z8.000 @@ -1127,7 +1127,7 @@ G4 P1.23456 G0 Z5.000 (G80) G90 -(Finish operation: Profile) +(Finish operation) (Begin postamble) """, "--comments --translate_drill", @@ -1189,12 +1189,12 @@ G90 G21 (Begin operation) G54 -(Finish operation: Fixture) +(Finish operation) (Begin operation) (TC: Default Tool) (Begin toolchange) (M6 T1) -(Finish operation: TC: Default Tool) +(Finish operation) (Begin operation) G0 X1.000 Y2.000 G0 Z8.000 @@ -1210,7 +1210,7 @@ G0 Z13.000 G91 (G80) G90 -(Finish operation: Profile) +(Finish operation) (Begin postamble) """, "--comments --translate_drill", @@ -1276,12 +1276,12 @@ G90 G21 (Begin operation) G54 -(Finish operation: Fixture) +(Finish operation) (Begin operation) (TC: Default Tool) (Begin toolchange) (M6 T1) -(Finish operation: TC: Default Tool) +(Finish operation) (Begin operation) G0 X1.000 Y2.000 G0 Z8.000 @@ -1303,7 +1303,7 @@ G1 Z0.000 F7380.000 G0 Z5.000 (G80) G90 -(Finish operation: Profile) +(Finish operation) (Begin postamble) """, "--comments --translate_drill", @@ -1373,12 +1373,12 @@ G90 G21 (Begin operation) G54 -(Finish operation: Fixture) +(Finish operation) (Begin operation) (TC: Default Tool) (Begin toolchange) (M6 T1) -(Finish operation: TC: Default Tool) +(Finish operation) (Begin operation) G0 X1.000 Y2.000 G0 Z8.000 @@ -1402,7 +1402,7 @@ G0 Z13.000 G91 (G80) G90 -(Finish operation: Profile) +(Finish operation) (Begin postamble) """, "--comments --translate_drill", diff --git a/src/Mod/CAM/CAMTests/dressuptest.FCStd b/src/Mod/CAM/CAMTests/dressuptest.FCStd new file mode 100644 index 0000000000..f41fc81bc7 Binary files /dev/null and b/src/Mod/CAM/CAMTests/dressuptest.FCStd differ diff --git a/src/Mod/CAM/CMakeLists.txt b/src/Mod/CAM/CMakeLists.txt index daab112b11..06312b6300 100644 --- a/src/Mod/CAM/CMakeLists.txt +++ b/src/Mod/CAM/CMakeLists.txt @@ -301,6 +301,7 @@ SET(Tests_SRCS CAMTests/__init__.py CAMTests/boxtest.fcstd CAMTests/boxtest1.fcstd + CAMTests/dressuptest.FCStd CAMTests/Drilling_1.FCStd CAMTests/drill_test1.FCStd CAMTests/FilePathTestUtils.py @@ -355,6 +356,7 @@ SET(Tests_SRCS CAMTests/TestRefactoredLinuxCNCPost.py CAMTests/TestRefactoredMach3Mach4Post.py CAMTests/TestRefactoredMassoG3Post.py + CAMTests/TestRefactoredTestDressupPost.py CAMTests/TestRefactoredTestPost.py CAMTests/TestRefactoredTestPostGCodes.py CAMTests/TestRefactoredTestPostMCodes.py diff --git a/src/Mod/CAM/Path/Base/Util.py b/src/Mod/CAM/Path/Base/Util.py index 3de8266d5f..999da0a6c7 100644 --- a/src/Mod/CAM/Path/Base/Util.py +++ b/src/Mod/CAM/Path/Base/Util.py @@ -118,13 +118,13 @@ def isSolid(obj): return not shape.isNull() and shape.Volume and shape.isClosed() -def opProperty(op, prop): +def opProperty(op, prop, default=None): """opProperty(op, prop) ... return the value of property prop of the underlying operation (or None if prop does not exist)""" if hasattr(op, prop): return getattr(op, prop) if hasattr(op, "Base"): - return opProperty(op.Base, prop) - return None + return opProperty(op.Base, prop, default) + return default def toolControllerForOp(op): @@ -134,6 +134,20 @@ def toolControllerForOp(op): return opProperty(op, "ToolController") +def coolantModeForOp(op): + """coolantModeForOp(op) ... return the coolant mode used by the op. + If the op doesn't have its own coolant mode but has a Base object, return its coolant mode. + Otherwise return "None".""" + return opProperty(op, "CoolantMode", "None") + + +def activeForOp(op): + """activeForOp(op) ... return the active property used by the op. + If the op doesn't have its own active property but has a Base object, return its active property. + Otherwise return True.""" + return opProperty(op, "Active", True) + + def getPublicObject(obj): """getPublicObject(obj) ... returns the object which should be used to reference a feature of the given object.""" if hasattr(obj, "getParentGeoFeatureGroup"): diff --git a/src/Mod/CAM/Path/Post/Processor.py b/src/Mod/CAM/Path/Post/Processor.py index 9dbecca733..1c153c309a 100644 --- a/src/Mod/CAM/Path/Post/Processor.py +++ b/src/Mod/CAM/Path/Post/Processor.py @@ -195,7 +195,7 @@ class PostProcessor: # Now generate the gcode for obj in self._job.Operations.Group: tc = PathUtil.toolControllerForOp(obj) - if tc is not None and PathUtil.opProperty(obj, "Active"): + if tc is not None and PathUtil.activeForOp(obj): if tc.ToolNumber != currTool: sublist.append(tc) Path.Log.debug(f"Appending TC: {tc.Name}") @@ -227,7 +227,7 @@ class PostProcessor: Path.Log.track(obj.Label) # check if the operation is active - if not getattr(obj, "Active", True): + if not PathUtil.activeForOp(obj): Path.Log.track() continue @@ -276,7 +276,7 @@ class PostProcessor: for obj in self._job.Operations.Group: # check if the operation is active - if not getattr(obj, "Active", True): + if not PathUtil.activeForOp(obj): continue sublist = [] diff --git a/src/Mod/CAM/Path/Post/UtilsArguments.py b/src/Mod/CAM/Path/Post/UtilsArguments.py index 7896d0a16d..94314bc38e 100644 --- a/src/Mod/CAM/Path/Post/UtilsArguments.py +++ b/src/Mod/CAM/Path/Post/UtilsArguments.py @@ -587,7 +587,8 @@ def init_shared_values(values: Values) -> None: # values["SHOW_MACHINE_UNITS"] = True # - # If True then the current operation label is output just before the PRE_OPERATION. + # If True then the current operation label is output just before the PRE_OPERATION + # and just before the POST_OPERATION. # values["SHOW_OPERATION_LABELS"] = True # diff --git a/src/Mod/CAM/Path/Post/UtilsExport.py b/src/Mod/CAM/Path/Post/UtilsExport.py index a9529c80b1..71e929a010 100644 --- a/src/Mod/CAM/Path/Post/UtilsExport.py +++ b/src/Mod/CAM/Path/Post/UtilsExport.py @@ -32,6 +32,7 @@ import os from typing import Any, Dict, List import FreeCAD +import Path.Base.Util as PathUtil import Path.Post.Utils as PostUtils import Path.Post.UtilsParse as PostUtilsParse import Path.Tool.Controller as PathToolController @@ -50,15 +51,6 @@ def check_canned_cycles(values: Values) -> None: values["SUPPRESS_COMMANDS"] += ["G99", "G98", "G80"] -def determine_coolant_mode(obj) -> str: - """Determine the coolant mode.""" - if hasattr(obj, "CoolantMode") or hasattr(obj, "Base") and hasattr(obj.Base, "CoolantMode"): - if hasattr(obj, "CoolantMode"): - return obj.CoolantMode - return obj.Base.CoolantMode - return "None" - - def output_coolant_off(values: Values, gcode: Gcode, coolant_mode: str) -> None: """Output the commands to turn coolant off if necessary.""" comment: str @@ -162,9 +154,12 @@ def output_postop(values: Values, gcode: Gcode, obj) -> None: nl: str = "\n" if values["OUTPUT_COMMENTS"]: - comment = PostUtilsParse.create_comment( - values, f'{values["FINISH_LABEL"]} operation: {obj.Label}' - ) + if values["SHOW_OPERATION_LABELS"]: + comment = PostUtilsParse.create_comment( + values, f'{values["FINISH_LABEL"]} operation: {obj.Label}' + ) + else: + comment = PostUtilsParse.create_comment(values, f'{values["FINISH_LABEL"]} operation') gcode.append(f"{PostUtilsParse.linenumber(values)}{comment}{nl}") for line in values["POST_OPERATION"].splitlines(False): gcode.append(f"{PostUtilsParse.linenumber(values)}{line}{nl}") @@ -314,11 +309,9 @@ def export_common(values: Values, objectslist, filename: str) -> str: for obj in objectslist: # Skip inactive operations - if hasattr(obj, "Active") and not obj.Active: + if not PathUtil.activeForOp(obj): continue - if hasattr(obj, "Base") and hasattr(obj.Base, "Active") and not obj.Base.Active: - continue - coolant_mode = determine_coolant_mode(obj) + coolant_mode = PathUtil.coolantModeForOp(obj) output_start_bcnc(values, gcode, obj) output_preop(values, gcode, obj) output_coolant_on(values, gcode, coolant_mode) diff --git a/src/Mod/CAM/Path/Post/scripts/dynapath_4060_post.py b/src/Mod/CAM/Path/Post/scripts/dynapath_4060_post.py index f7861567f3..84704c7611 100644 --- a/src/Mod/CAM/Path/Post/scripts/dynapath_4060_post.py +++ b/src/Mod/CAM/Path/Post/scripts/dynapath_4060_post.py @@ -31,6 +31,7 @@ import Path import argparse import datetime import shlex +import Path.Base.Util as PathUtil import Path.Post.Utils as PostUtils import PathScripts.PathUtils as PathUtils from builtins import open as pyopen @@ -171,7 +172,7 @@ def processArguments(argstring): SHOW_EDITOR = False print("Show editor = %r" % (SHOW_EDITOR)) if args.precision is not None: - PRECISION = args.precision + PRECISION = int(args.precision) if args.preamble is not None: PREAMBLE = args.preamble.replace("\\n", "\n") if args.postamble is not None: @@ -232,12 +233,9 @@ def export(objectslist, filename, argstring): for obj in objectslist: # Skip inactive operations - if hasattr(obj, "Active"): - if not obj.Active: - continue - if hasattr(obj, "Base") and hasattr(obj.Base, "Active"): - if not obj.Base.Active: - continue + if not PathUtil.activeForOp(obj): + continue + if hasattr(obj, "ClearanceHeight"): clearanceHeight = obj.ClearanceHeight.Value @@ -257,12 +255,7 @@ def export(objectslist, filename, argstring): ) # get coolant mode - coolantMode = "None" - if hasattr(obj, "CoolantMode") or hasattr(obj, "Base") and hasattr(obj.Base, "CoolantMode"): - if hasattr(obj, "CoolantMode"): - coolantMode = obj.CoolantMode - else: - coolantMode = obj.Base.CoolantMode + coolantMode = PathUtil.coolantModeForOp(obj) # turn coolant on if required if OUTPUT_COMMENTS: diff --git a/src/Mod/CAM/Path/Post/scripts/estlcam_post.py b/src/Mod/CAM/Path/Post/scripts/estlcam_post.py index 2a571766a1..070bfa64fb 100644 --- a/src/Mod/CAM/Path/Post/scripts/estlcam_post.py +++ b/src/Mod/CAM/Path/Post/scripts/estlcam_post.py @@ -263,7 +263,7 @@ def export(objectslist, filename, argstring): continue # Skip inactive operations - if PathUtil.opProperty(obj, "Active") is False: + if not PathUtil.activeForOp(obj): continue # do the pre_op @@ -273,12 +273,7 @@ def export(objectslist, filename, argstring): gcode += linenumber() + line # get coolant mode - coolantMode = "None" - if hasattr(obj, "CoolantMode") or hasattr(obj, "Base") and hasattr(obj.Base, "CoolantMode"): - if hasattr(obj, "CoolantMode"): - coolantMode = obj.CoolantMode - else: - coolantMode = obj.Base.CoolantMode + coolantMode = PathUtil.coolantModeForOp(obj) # turn coolant on if required if OUTPUT_COMMENTS: diff --git a/src/Mod/CAM/Path/Post/scripts/fangling_post.py b/src/Mod/CAM/Path/Post/scripts/fangling_post.py index c6938c66b5..636bd2bc8b 100644 --- a/src/Mod/CAM/Path/Post/scripts/fangling_post.py +++ b/src/Mod/CAM/Path/Post/scripts/fangling_post.py @@ -38,6 +38,7 @@ import datetime import shlex # from PathScripts import PostUtils +import Path.Base.Util as PathUtil import Path.Post.Utils as PostUtils from PathScripts import PathUtils from builtins import open as pyopen @@ -216,12 +217,8 @@ def export(objectslist, filename, argstring): for obj in objectslist: # Skip inactive operations - if hasattr(obj, "Active"): - if not obj.Active: - continue - if hasattr(obj, "Base") and hasattr(obj.Base, "Active"): - if not obj.Base.Active: - continue + if not PathUtil.activeForOp(obj): + continue # fetch machine details job = PathUtils.findParentJob(obj) diff --git a/src/Mod/CAM/Path/Post/scripts/fanuc_post.py b/src/Mod/CAM/Path/Post/scripts/fanuc_post.py index 4487f70457..b708d51a9b 100644 --- a/src/Mod/CAM/Path/Post/scripts/fanuc_post.py +++ b/src/Mod/CAM/Path/Post/scripts/fanuc_post.py @@ -29,6 +29,7 @@ import argparse import datetime import shlex import os.path +import Path.Base.Util as PathUtil import Path.Post.Utils as PostUtils import PathScripts.PathUtils as PathUtils from builtins import open as pyopen @@ -227,12 +228,8 @@ def export(objectslist, filename, argstring): for obj in objectslist: # Skip inactive operations - if hasattr(obj, "Active"): - if not obj.Active: - continue - if hasattr(obj, "Base") and hasattr(obj.Base, "Active"): - if not obj.Base.Active: - continue + if not PathUtil.activeForOp(obj): + continue # do the pre_op if OUTPUT_COMMENTS: @@ -242,12 +239,7 @@ def export(objectslist, filename, argstring): gcode += linenumber() + line # get coolant mode - coolantMode = "None" - if hasattr(obj, "CoolantMode") or hasattr(obj, "Base") and hasattr(obj.Base, "CoolantMode"): - if hasattr(obj, "CoolantMode"): - coolantMode = obj.CoolantMode - else: - coolantMode = obj.Base.CoolantMode + coolantMode = PathUtil.coolantModeForOp(obj) # turn coolant on if required if OUTPUT_COMMENTS: diff --git a/src/Mod/CAM/Path/Post/scripts/grbl_post.py b/src/Mod/CAM/Path/Post/scripts/grbl_post.py index 3dd7f267af..497da87a57 100644 --- a/src/Mod/CAM/Path/Post/scripts/grbl_post.py +++ b/src/Mod/CAM/Path/Post/scripts/grbl_post.py @@ -315,7 +315,7 @@ def export(objectslist, filename, argstring): return # Skip inactive operations - if PathUtil.opProperty(obj, "Active") is False: + if not PathUtil.activeForOp(obj): continue # do the pre_op @@ -329,12 +329,7 @@ def export(objectslist, filename, argstring): gcode += linenumber() + line # get coolant mode - coolantMode = "None" - if hasattr(obj, "CoolantMode") or hasattr(obj, "Base") and hasattr(obj.Base, "CoolantMode"): - if hasattr(obj, "CoolantMode"): - coolantMode = obj.CoolantMode - else: - coolantMode = obj.Base.CoolantMode + coolantMode = PathUtil.coolantModeForOp(obj) # turn coolant on if required if OUTPUT_COMMENTS: diff --git a/src/Mod/CAM/Path/Post/scripts/linuxcnc_post.py b/src/Mod/CAM/Path/Post/scripts/linuxcnc_post.py index 5a0e676936..358eefe4bf 100644 --- a/src/Mod/CAM/Path/Post/scripts/linuxcnc_post.py +++ b/src/Mod/CAM/Path/Post/scripts/linuxcnc_post.py @@ -27,6 +27,7 @@ import Path import argparse import datetime import shlex +import Path.Base.Util as PathUtil import Path.Post.Utils as PostUtils import PathScripts.PathUtils as PathUtils from builtins import open as pyopen @@ -203,12 +204,8 @@ def export(objectslist, filename, argstring): for obj in objectslist: # Skip inactive operations - if hasattr(obj, "Active"): - if not obj.Active: - continue - if hasattr(obj, "Base") and hasattr(obj.Base, "Active"): - if not obj.Base.Active: - continue + if not PathUtil.activeForOp(obj): + continue # do the pre_op if OUTPUT_COMMENTS: @@ -218,12 +215,7 @@ def export(objectslist, filename, argstring): gcode += linenumber() + line # get coolant mode - coolantMode = "None" - if hasattr(obj, "CoolantMode") or hasattr(obj, "Base") and hasattr(obj.Base, "CoolantMode"): - if hasattr(obj, "CoolantMode"): - coolantMode = obj.CoolantMode - else: - coolantMode = obj.Base.CoolantMode + coolantMode = PathUtil.coolantModeForOp(obj) # turn coolant on if required if OUTPUT_COMMENTS: diff --git a/src/Mod/CAM/Path/Post/scripts/mach3_mach4_post.py b/src/Mod/CAM/Path/Post/scripts/mach3_mach4_post.py index a450895333..c0eb947fd3 100644 --- a/src/Mod/CAM/Path/Post/scripts/mach3_mach4_post.py +++ b/src/Mod/CAM/Path/Post/scripts/mach3_mach4_post.py @@ -27,6 +27,7 @@ import Path import argparse import datetime import shlex +import Path.Base.Util as PathUtil import Path.Post.Utils as PostUtils import PathScripts.PathUtils as PathUtils from builtins import open as pyopen @@ -203,12 +204,8 @@ def export(objectslist, filename, argstring): for obj in objectslist: # Skip inactive operations - if hasattr(obj, "Active"): - if not obj.Active: - continue - if hasattr(obj, "Base") and hasattr(obj.Base, "Active"): - if not obj.Base.Active: - continue + if not PathUtil.activeForOp(obj): + continue # do the pre_op if OUTPUT_COMMENTS: @@ -221,12 +218,7 @@ def export(objectslist, filename, argstring): gcode += linenumber() + line # get coolant mode - coolantMode = "None" - if hasattr(obj, "CoolantMode") or hasattr(obj, "Base") and hasattr(obj.Base, "CoolantMode"): - if hasattr(obj, "CoolantMode"): - coolantMode = obj.CoolantMode - else: - coolantMode = obj.Base.CoolantMode + coolantMode = PathUtil.coolantModeForOp(obj) # turn coolant on if required if OUTPUT_COMMENTS: diff --git a/src/Mod/CAM/Path/Post/scripts/marlin_post.py b/src/Mod/CAM/Path/Post/scripts/marlin_post.py index 6705a84797..eee6f05b5c 100644 --- a/src/Mod/CAM/Path/Post/scripts/marlin_post.py +++ b/src/Mod/CAM/Path/Post/scripts/marlin_post.py @@ -36,6 +36,7 @@ import Path import Path.Base.Util as PathUtil import Path.Post.Utils as PostUtils import PathScripts.PathUtils as PathUtils +from builtins import open as pyopen Revised = "2020-11-03" # Revision date for this file. @@ -357,7 +358,7 @@ def export(objectslist, filename, argstring): return # Skip inactive operations: - if PathUtil.opProperty(obj, "Active") is False: + if not PathUtil.activeForOp(obj): continue # Do the pre_op: @@ -371,12 +372,7 @@ def export(objectslist, filename, argstring): gcode += linenumber() + line # Get coolant mode: - coolantMode = "None" # None is the word returned from the operation - if hasattr(obj, "CoolantMode") or hasattr(obj, "Base") and hasattr(obj.Base, "CoolantMode"): - if hasattr(obj, "CoolantMode"): - coolantMode = obj.CoolantMode - else: - coolantMode = obj.Base.CoolantMode + coolantMode = PathUtil.coolantModeForOp(obj) # Turn coolant on if required: if OUTPUT_COMMENTS: @@ -455,8 +451,10 @@ def export(objectslist, filename, argstring): print("Done postprocessing.") # Write the file: - with open(filename, "w") as fp: - fp.write(final) + if not filename == "-": + gfile = pyopen(filename, "w") + gfile.write(final) + gfile.close() return final diff --git a/src/Mod/CAM/Path/Post/scripts/rrf_post.py b/src/Mod/CAM/Path/Post/scripts/rrf_post.py index d578a9b17f..9023aaafb4 100644 --- a/src/Mod/CAM/Path/Post/scripts/rrf_post.py +++ b/src/Mod/CAM/Path/Post/scripts/rrf_post.py @@ -35,6 +35,7 @@ import Path import Path.Base.Util as PathUtil import Path.Post.Utils as PostUtils import PathScripts.PathUtils as PathUtils +from builtins import open as pyopen Revised = "2021-10-21" # Revision date for this file. @@ -355,7 +356,7 @@ def export(objectslist, filename, argstring): return # Skip inactive operations: - if PathUtil.opProperty(obj, "Active") is False: + if not PathUtil.activeForOp(obj): continue # Do the pre_op: @@ -369,12 +370,7 @@ def export(objectslist, filename, argstring): gcode += linenumber() + line # Get coolant mode: - coolantMode = "None" # None is the word returned from the operation - if hasattr(obj, "CoolantMode") or hasattr(obj, "Base") and hasattr(obj.Base, "CoolantMode"): - if hasattr(obj, "CoolantMode"): - coolantMode = obj.CoolantMode - else: - coolantMode = obj.Base.CoolantMode + coolantMode = PathUtil.coolantModeForOp(obj) # Turn coolant on if required: if OUTPUT_COMMENTS: @@ -448,8 +444,12 @@ def export(objectslist, filename, argstring): print("Done postprocessing.") # Write the file: - with open(filename, "w") as fp: - fp.write(final) + if not filename == "-": + gfile = pyopen(filename, "w") + gfile.write(final) + gfile.close() + + return final def linenumber(): diff --git a/src/Mod/CAM/Path/Post/scripts/snapmaker_post.py b/src/Mod/CAM/Path/Post/scripts/snapmaker_post.py index 57ae690605..1881a012cf 100644 --- a/src/Mod/CAM/Path/Post/scripts/snapmaker_post.py +++ b/src/Mod/CAM/Path/Post/scripts/snapmaker_post.py @@ -31,6 +31,7 @@ from typing import Any, List, Tuple import FreeCAD import Path +import Path.Base.Util as PathUtil import Path.Post.Processor import Path.Post.UtilsArguments import Path.Post.UtilsExport @@ -773,11 +774,9 @@ class Snapmaker(Path.Post.Processor.PostProcessor): for obj in objects: # Skip inactive operations - if hasattr(obj, "Active") and not obj.Active: + if not PathUtil.activeForOp(obj): continue - if hasattr(obj, "Base") and hasattr(obj.Base, "Active") and not obj.Base.Active: - continue - coolant_mode = Path.Post.UtilsExport.determine_coolant_mode(obj) + coolant_mode = PathUtil.coolantModeForOp(obj) Path.Post.UtilsExport.output_start_bcnc(self.values, gcode, obj) Path.Post.UtilsExport.output_preop(self.values, gcode, obj) Path.Post.UtilsExport.output_coolant_on(self.values, gcode, coolant_mode) diff --git a/src/Mod/CAM/Path/Post/scripts/uccnc_post.py b/src/Mod/CAM/Path/Post/scripts/uccnc_post.py index b44a77c506..bad70ad181 100644 --- a/src/Mod/CAM/Path/Post/scripts/uccnc_post.py +++ b/src/Mod/CAM/Path/Post/scripts/uccnc_post.py @@ -33,6 +33,7 @@ import FreeCAD from FreeCAD import Units import Path +import Path.Base.Util as PathUtil import PathScripts.PathUtils as PathUtils import argparse import datetime @@ -451,6 +452,10 @@ def export(objectslist, filename, argstring): # write the code body for obj in objectslist: + # Skip inactive operations + if not PathUtil.activeForOp(obj): + continue + # pre_op if OUTPUT_COMMENTS: gcode += append("(operation initialise: %s)\n" % obj.Label) @@ -458,18 +463,17 @@ def export(objectslist, filename, argstring): gcode += append(line) # turn coolant on if required - if hasattr(obj, "CoolantMode"): - coolantMode = obj.CoolantMode - if coolantMode == "Mist": - if OUTPUT_COMMENTS: - gcode += append("M7 (coolant: mist on)\n") - else: - gcode += append("M7\n") - if coolantMode == "Flood": - if OUTPUT_COMMENTS: - gcode += append("M8 (coolant: flood on)\n") - else: - gcode += append("M8\n") + coolantMode = PathUtil.coolantModeForOp(obj) + if coolantMode == "Mist": + if OUTPUT_COMMENTS: + gcode += append("M7 (coolant: mist on)\n") + else: + gcode += append("M7\n") + if coolantMode == "Flood": + if OUTPUT_COMMENTS: + gcode += append("M8 (coolant: flood on)\n") + else: + gcode += append("M8\n") # process the operation gcode if OUTPUT_COMMENTS: @@ -483,13 +487,12 @@ def export(objectslist, filename, argstring): gcode += append(line) # turn coolant off if required - if hasattr(obj, "CoolantMode"): - coolantMode = obj.CoolantMode - if not coolantMode == "None": - if OUTPUT_COMMENTS: - gcode += append("M9 (coolant: off)\n") - else: - gcode += append("M9\n") + if not coolantMode == "None": + if OUTPUT_COMMENTS: + gcode += append("M9 (coolant: off)\n") + else: + gcode += append("M9\n") + if OUTPUT_COMMENTS: gcode += append("(operation finalised: %s)\n" % obj.Label) diff --git a/src/Mod/CAM/Path/Post/scripts/wedm_post.py b/src/Mod/CAM/Path/Post/scripts/wedm_post.py index 1b9396f8b9..fc745ba8e1 100644 --- a/src/Mod/CAM/Path/Post/scripts/wedm_post.py +++ b/src/Mod/CAM/Path/Post/scripts/wedm_post.py @@ -30,6 +30,7 @@ import Path import argparse import datetime import shlex +import Path.Base.Util as PathUtil import Path.Post.Utils as PostUtils import PathScripts.PathUtils as PathUtils from builtins import open as pyopen @@ -279,12 +280,8 @@ def export(objectslist, filename, argstring): for obj in objectslist: # Skip inactive operations - if hasattr(obj, "Active"): - if not obj.Active: - continue - if hasattr(obj, "Base") and hasattr(obj.Base, "Active"): - if not obj.Base.Active: - continue + if not PathUtil.activeForOp(obj): + continue # fetch machine details job = PathUtils.findParentJob(obj) @@ -319,12 +316,7 @@ def export(objectslist, filename, argstring): gcode += linenumber() + line # get coolant mode - coolantMode = "None" - if hasattr(obj, "CoolantMode") or hasattr(obj, "Base") and hasattr(obj.Base, "CoolantMode"): - if hasattr(obj, "CoolantMode"): - coolantMode = obj.CoolantMode - else: - coolantMode = obj.Base.CoolantMode + coolantMode = PathUtil.coolantModeForOp(obj) # turn coolant on if required if OUTPUT_COMMENTS: diff --git a/src/Mod/CAM/TestCAMApp.py b/src/Mod/CAM/TestCAMApp.py index da31bb3255..a8e993541f 100644 --- a/src/Mod/CAM/TestCAMApp.py +++ b/src/Mod/CAM/TestCAMApp.py @@ -77,6 +77,7 @@ from CAMTests.TestRefactoredGrblPost import TestRefactoredGrblPost from CAMTests.TestRefactoredLinuxCNCPost import TestRefactoredLinuxCNCPost from CAMTests.TestRefactoredMassoG3Post import TestRefactoredMassoG3Post from CAMTests.TestRefactoredMach3Mach4Post import TestRefactoredMach3Mach4Post +from CAMTests.TestRefactoredTestDressupPost import TestRefactoredTestDressupPost from CAMTests.TestRefactoredTestPost import TestRefactoredTestPost from CAMTests.TestRefactoredTestPostGCodes import TestRefactoredTestPostGCodes from CAMTests.TestRefactoredTestPostMCodes import TestRefactoredTestPostMCodes @@ -134,6 +135,7 @@ False if TestRefactoredGrblPost.__name__ else True False if TestRefactoredLinuxCNCPost.__name__ else True False if TestRefactoredMassoG3Post.__name__ else True False if TestRefactoredMach3Mach4Post.__name__ else True +False if TestRefactoredTestDressupPost.__name__ else True False if TestRefactoredTestPost.__name__ else True False if TestRefactoredTestPostGCodes.__name__ else True False if TestRefactoredTestPostMCodes.__name__ else True