From 2d32ca58edff23e202a558061f02b7c3f28ba89a Mon Sep 17 00:00:00 2001 From: Hans Unzner Date: Thu, 8 Jan 2026 14:16:22 +0100 Subject: [PATCH 01/24] gmoccapy: use now ..._SPINDLE_0_... instead of ..._SPINDLE_... using qt_istat --- configs/sim/gmoccapy/gmoccapy.ini | 9 +++------ src/emc/usr_intf/gmoccapy/getiniinfo.py | 23 ----------------------- src/emc/usr_intf/gmoccapy/gmoccapy.py | 8 ++++---- 3 files changed, 7 insertions(+), 33 deletions(-) diff --git a/configs/sim/gmoccapy/gmoccapy.ini b/configs/sim/gmoccapy/gmoccapy.ini index 217ae378d61..d8f05c993da 100644 --- a/configs/sim/gmoccapy/gmoccapy.ini +++ b/configs/sim/gmoccapy/gmoccapy.ini @@ -23,21 +23,18 @@ CYCLE_TIME = 100 # Values that will be allowed for override, 1.0 = 100% MAX_FEED_OVERRIDE = 1.5 -MAX_SPINDLE_OVERRIDE = 1.2 -MIN_SPINDLE_OVERRIDE = 0.5 +MIN_SPINDLE_0_OVERRIDE = 0.5 +MAX_SPINDLE_0_OVERRIDE = 1.2 # Initial value for spindle speed -DEFAULT_SPINDLE_SPEED = 450 +DEFAULT_SPINDLE_0_SPEED = 450 # The following are not used, added here to suppress warnings (from qt_istat/logger). DEFAULT_LINEAR_VELOCITY = 35 MIN_LINEAR_VELOCITY = 0 MAX_LINEAR_VELOCITY = 234 -DEFAULT_SPINDLE_0_SPEED = 500 MIN_SPINDLE_0_SPEED = 0 MAX_SPINDLE_0_SPEED = 3000 -MAX_SPINDLE_0_OVERRIDE = 1.2 -MIN_SPINDLE_0_OVERRIDE = 0.5 # Prefix to be used PROGRAM_PREFIX = ../../nc_files/ diff --git a/src/emc/usr_intf/gmoccapy/getiniinfo.py b/src/emc/usr_intf/gmoccapy/getiniinfo.py index 20be167976e..c1b6dda8aed 100644 --- a/src/emc/usr_intf/gmoccapy/getiniinfo.py +++ b/src/emc/usr_intf/gmoccapy/getiniinfo.py @@ -268,29 +268,6 @@ def get_min_ang_jog_vel(self): LOG.warning("No MIN_ANGULAR_VELOCITY entry found in [DISPLAY] of INI file. Using default value of 0.1 degree / min.") return temp - def get_default_spindle_speed(self): - # check for default spindle speed settings - temp = self.inifile.getreal("DISPLAY", "DEFAULT_SPINDLE_SPEED") - if not temp: - temp = 300.0 - LOG.warning("No DEFAULT_SPINDLE_SPEED entry found in [DISPLAY] of INI file") - return temp - - def get_max_spindle_override(self): - # check for override settings - temp = self.inifile.getreal("DISPLAY", "MAX_SPINDLE_OVERRIDE") - if not temp: - temp = 1.0 - LOG.warning("No MAX_SPINDLE_OVERRIDE entry found in [DISPLAY] of INI file") - return temp - - def get_min_spindle_override(self): - temp = self.inifile.getreal("DISPLAY", "MIN_SPINDLE_OVERRIDE") - if not temp: - temp = 0.1 - LOG.warning("No MIN_SPINDLE_OVERRIDE entry found in [DISPLAY] of INI file") - return temp - def get_max_feed_override(self): temp = self.inifile.getreal("DISPLAY", "MAX_FEED_OVERRIDE") if not temp: diff --git a/src/emc/usr_intf/gmoccapy/gmoccapy.py b/src/emc/usr_intf/gmoccapy/gmoccapy.py index c7afde2fcbf..8849f9cf87f 100644 --- a/src/emc/usr_intf/gmoccapy/gmoccapy.py +++ b/src/emc/usr_intf/gmoccapy/gmoccapy.py @@ -198,7 +198,7 @@ def __init__(self, argv): self.error_channel.poll() # set INI path for INI info class before widgets are loaded - INFO = Info(ini=argv[2]) + self.INI = Info(ini=argv[2]) self.builder = Gtk.Builder() # translation of the glade file will be done with @@ -606,8 +606,8 @@ def _get_ini_data(self): self.rabbit_jog = self.get_ini_info.get_jog_vel() self.jog_rate_max = self.get_ini_info.get_max_jog_vel() - self.spindle_override_max = self.get_ini_info.get_max_spindle_override() - self.spindle_override_min = self.get_ini_info.get_min_spindle_override() + self.spindle_override_max = self.INI.MAX_SPINDLE_OVERRIDE/100 + self.spindle_override_min = self.INI.MIN_SPINDLE_OVERRIDE/100 self.feed_override_max = self.get_ini_info.get_max_feed_override() self.dro_actual = self.get_ini_info.get_position_feedback_actual() @@ -651,7 +651,7 @@ def _get_pref_data(self): # if there is a INI Entry for default spindle speed, we will use that one as default # but if there is a setting in our preference file, that one will beet the INI entry - default_spindle_speed = self.get_ini_info.get_default_spindle_speed() + default_spindle_speed = self.INI.DEFAULT_SPINDLE_0_SPEED self.spindle_start_rpm = self.prefs.getpref( 'spindle_start_rpm', default_spindle_speed, float ) self.kbd_height = self.prefs.getpref("kbd_height", 250, int) From bbbafdbc102a9d9b589e8c0f50b6d0a5ccb4ee52 Mon Sep 17 00:00:00 2001 From: Hans Unzner Date: Thu, 8 Jan 2026 14:17:19 +0100 Subject: [PATCH 02/24] gmoccapy: use MAX_FEED_OVERRIDE using qt_istat --- src/emc/usr_intf/gmoccapy/getiniinfo.py | 7 ------- src/emc/usr_intf/gmoccapy/gmoccapy.py | 2 +- 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/src/emc/usr_intf/gmoccapy/getiniinfo.py b/src/emc/usr_intf/gmoccapy/getiniinfo.py index c1b6dda8aed..63b97c0757b 100644 --- a/src/emc/usr_intf/gmoccapy/getiniinfo.py +++ b/src/emc/usr_intf/gmoccapy/getiniinfo.py @@ -268,13 +268,6 @@ def get_min_ang_jog_vel(self): LOG.warning("No MIN_ANGULAR_VELOCITY entry found in [DISPLAY] of INI file. Using default value of 0.1 degree / min.") return temp - def get_max_feed_override(self): - temp = self.inifile.getreal("DISPLAY", "MAX_FEED_OVERRIDE") - if not temp: - temp = 1.0 - LOG.warning("No MAX_FEED_OVERRIDE entry found in [DISPLAY] of INI file") - return temp - def get_embedded_tabs(self): # Check INI file for embed commands # NAME is used as the tab label if a notebook is used diff --git a/src/emc/usr_intf/gmoccapy/gmoccapy.py b/src/emc/usr_intf/gmoccapy/gmoccapy.py index 8849f9cf87f..e7874e2ce5e 100644 --- a/src/emc/usr_intf/gmoccapy/gmoccapy.py +++ b/src/emc/usr_intf/gmoccapy/gmoccapy.py @@ -608,7 +608,7 @@ def _get_ini_data(self): self.spindle_override_max = self.INI.MAX_SPINDLE_OVERRIDE/100 self.spindle_override_min = self.INI.MIN_SPINDLE_OVERRIDE/100 - self.feed_override_max = self.get_ini_info.get_max_feed_override() + self.feed_override_max = self.INI.MAX_FEED_OVERRIDE/100 self.dro_actual = self.get_ini_info.get_position_feedback_actual() def _get_pref_data(self): From bc866a1e55030158ab889831a2c4aaf6070b5f13 Mon Sep 17 00:00:00 2001 From: Hans Unzner Date: Thu, 8 Jan 2026 14:23:32 +0100 Subject: [PATCH 03/24] gmoccapy: {MIN, MAX, DEFAULT}_ANGULAR_JOG_VEL from qt_istat --- src/emc/usr_intf/gmoccapy/getiniinfo.py | 24 ------------------------ src/emc/usr_intf/gmoccapy/gmoccapy.py | 6 +++--- 2 files changed, 3 insertions(+), 27 deletions(-) diff --git a/src/emc/usr_intf/gmoccapy/getiniinfo.py b/src/emc/usr_intf/gmoccapy/getiniinfo.py index 63b97c0757b..861f1a01ed9 100644 --- a/src/emc/usr_intf/gmoccapy/getiniinfo.py +++ b/src/emc/usr_intf/gmoccapy/getiniinfo.py @@ -244,30 +244,6 @@ def get_max_jog_vel(self): LOG.warning("No MAX_LINEAR_VELOCITY entry found in [TRAJ] of INI file. Using default value of 600 units / min.") return temp * 60 - def get_default_ang_jog_vel(self): - # get default angular jog velocity - temp = self.inifile.getreal("DISPLAY", "DEFAULT_ANGULAR_VELOCITY") - if not temp: - temp = 360.0 - LOG.warning("No DEFAULT_ANGULAR_VELOCITY entry found in [DISPLAY] of INI file. Using default value of 360 degree / min.") - return temp - - def get_max_ang_jog_vel(self): - # get max angular velocity - temp = self.inifile.getreal("DISPLAY", "MAX_ANGULAR_VELOCITY") - if not temp: - temp = 3600.0 - LOG.warning("No MAX_ANGULAR_VELOCITY entry found in [DISPLAY] of INI file. Using default value of 3600 degree / min.") - return temp - - def get_min_ang_jog_vel(self): - # get min angular velocity - temp = self.inifile.getreal("DISPLAY", "MIN_ANGULAR_VELOCITY") - if not temp: - temp = 0.1 - LOG.warning("No MIN_ANGULAR_VELOCITY entry found in [DISPLAY] of INI file. Using default value of 0.1 degree / min.") - return temp - def get_embedded_tabs(self): # Check INI file for embed commands # NAME is used as the tab label if a notebook is used diff --git a/src/emc/usr_intf/gmoccapy/gmoccapy.py b/src/emc/usr_intf/gmoccapy/gmoccapy.py index e7874e2ce5e..6ec1c126325 100644 --- a/src/emc/usr_intf/gmoccapy/gmoccapy.py +++ b/src/emc/usr_intf/gmoccapy/gmoccapy.py @@ -1791,9 +1791,9 @@ def _init_preferences(self): if not "a" in self.axis_list and not "b" in self.axis_list and not "c" in self.axis_list: self.widgets.spc_ang_jog_vel.hide() else: - self.widgets.spc_ang_jog_vel.set_property("min", self.get_ini_info.get_min_ang_jog_vel()) - self.widgets.spc_ang_jog_vel.set_property("max", self.get_ini_info.get_max_ang_jog_vel()) - self.widgets.spc_ang_jog_vel.set_value(self.get_ini_info.get_default_ang_jog_vel()) + self.widgets.spc_ang_jog_vel.set_property("min", self.INI.MIN_ANGULAR_JOG_VEL) + self.widgets.spc_ang_jog_vel.set_property("max", self.INI.MAX_ANGULAR_JOG_VEL) + self.widgets.spc_ang_jog_vel.set_value(self.INI.DEFAULT_ANGULAR_JOG_VEL) font = self.prefs.getpref("gcodeview_font", "monospace 10", str) font_desc = Pango.FontDescription.from_string(font) From 3a5d4f2a2ca166109061f1c782824292173d74b8 Mon Sep 17 00:00:00 2001 From: Hans Unzner Date: Sat, 17 Jan 2026 08:38:11 +0100 Subject: [PATCH 04/24] sample-configs/axis: move MIN_LINEAR_VELOCITY from TRAJ to DISPLAY There is no MIN_LINEAR_VELOCITY in the TRAJ section. --- configs/sim/axis/pentapod/pentapod.ini | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/configs/sim/axis/pentapod/pentapod.ini b/configs/sim/axis/pentapod/pentapod.ini index 943a62c0c2d..36d59c3b40d 100644 --- a/configs/sim/axis/pentapod/pentapod.ini +++ b/configs/sim/axis/pentapod/pentapod.ini @@ -17,6 +17,8 @@ PYVCP = panel.xml GEOMETRY = XYZ-AB INCREMENTS = 10 mm, 1 mm, 0.1 mm +MIN_LINEAR_VELOCITY = 0.100000 + [FILTER] PROGRAM_EXTENSION = .png,.gif,.jpg Grayscale Depth Image PROGRAM_EXTENSION = .py Python Script @@ -61,7 +63,6 @@ CYCLE_TIME = 0.010 DEFAULT_VELOCITY = 5.00 DEFAULT_LINEAR_VELOCITY = 50.000000 MAX_LINEAR_VELOCITY = 100.000000 -MIN_LINEAR_VELOCITY = 0.100000 DEFAULT_ANGULAR_VELOCITY = 1.000000 MAX_ANGULAR_VELOCITY = 10.000000 MIN_ANGULAR_VELOCITY = 0.100000 From 424723af695bc0a7011750b18d9450ac955fa55b Mon Sep 17 00:00:00 2001 From: Hans Unzner Date: Sat, 17 Jan 2026 08:40:30 +0100 Subject: [PATCH 05/24] docs: remove [TRAJ] MIN_VELOCITY --- docs/src/config/ini-config.adoc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/docs/src/config/ini-config.adoc b/docs/src/config/ini-config.adoc index 8f1e8d09d56..4967b686a3b 100644 --- a/docs/src/config/ini-config.adoc +++ b/docs/src/config/ini-config.adoc @@ -391,9 +391,8 @@ See <> document for GMOCCAPY details. ==== * `DEFAULT_LINEAR_VELOCITY = .25` - The default velocity for linear jogs, in <> per second. -* `MIN_VELOCITY = .01` - The approximate lowest value the jog slider. +* `MIN_LINEAR_VELOCITY = .01` - The minimum velocity for linear jogs, in machine units per second. * `MAX_LINEAR_VELOCITY = 1.0` - The maximum velocity for linear jogs, in machine units per second. -* `MIN_LINEAR_VELOCITY = .01` - The approximate lowest value the jog slider. * `DEFAULT_ANGULAR_VELOCITY = .25` - The default velocity for angular jogs, in machine units per second. * `MIN_ANGULAR_VELOCITY = .01` - The approximate lowest value the angular jog slider. * `MAX_ANGULAR_VELOCITY = 1.0` - The maximum velocity for angular jogs, in machine units per second. From 8f5b01a0aca54c61e8afd3d953c73a62bb523bf8 Mon Sep 17 00:00:00 2001 From: Hans Unzner Date: Thu, 8 Jan 2026 14:56:31 +0100 Subject: [PATCH 06/24] gmoccapy: use spindle min, max and default directly from INI file (#3497) --- configs/sim/gmoccapy/gmoccapy.ini | 7 +- docs/src/gui/gmoccapy.adoc | 43 +++---- src/emc/usr_intf/gmoccapy/gmoccapy.glade | 154 +---------------------- src/emc/usr_intf/gmoccapy/gmoccapy.py | 27 +--- 4 files changed, 29 insertions(+), 202 deletions(-) diff --git a/configs/sim/gmoccapy/gmoccapy.ini b/configs/sim/gmoccapy/gmoccapy.ini index d8f05c993da..472d550c2cc 100644 --- a/configs/sim/gmoccapy/gmoccapy.ini +++ b/configs/sim/gmoccapy/gmoccapy.ini @@ -26,15 +26,16 @@ MAX_FEED_OVERRIDE = 1.5 MIN_SPINDLE_0_OVERRIDE = 0.5 MAX_SPINDLE_0_OVERRIDE = 1.2 -# Initial value for spindle speed +# Spindel start speed DEFAULT_SPINDLE_0_SPEED = 450 +# Scaling of spindle speed bar +MIN_SPINDLE_0_SPEED = 0 +MAX_SPINDLE_0_SPEED = 3000 # The following are not used, added here to suppress warnings (from qt_istat/logger). DEFAULT_LINEAR_VELOCITY = 35 MIN_LINEAR_VELOCITY = 0 MAX_LINEAR_VELOCITY = 234 -MIN_SPINDLE_0_SPEED = 0 -MAX_SPINDLE_0_SPEED = 3000 # Prefix to be used PROGRAM_PREFIX = ../../nc_files/ diff --git a/docs/src/gui/gmoccapy.adoc b/docs/src/gui/gmoccapy.adoc index 25caed8e1bb..4539885010b 100644 --- a/docs/src/gui/gmoccapy.adoc +++ b/docs/src/gui/gmoccapy.adoc @@ -104,9 +104,11 @@ So let us take a closer look at the INI file and what you need to include to use DISPLAY = gmoccapy PREFERENCE_FILE_PATH = gmoccapy_preferences MAX_FEED_OVERRIDE = 1.5 -MAX_SPINDLE_OVERRIDE = 1.2 -MIN_SPINDLE_OVERRIDE = 0.5 -DEFAULT_SPINDLE_SPEED = 500 +MIN_SPINDLE_0_OVERRIDE = 0.5 +MAX_SPINDLE_0_OVERRIDE = 1.2 +DEFAULT_SPINDLE_0_SPEED = 500 +MIN_SPINDLE_0_SPEED = 0 +MAX_SPINDLE_0_SPEED = 3000 LATHE = 1 BACK_TOOL_LATHE = 1 PROGRAM_PREFIX = ../../nc_files/ @@ -129,10 +131,10 @@ If you only want to use one file for several machines, you need to include `PREF [NOTE] If no value is given, it will be set to 1.0. -- _MIN_SPINDLE_OVERRIDE = 0.5_ and _MAX_SPINDLE_OVERRIDE = 1.2_ - Will allow you to change the spindle override within a limit from 50% to 120%. +- _MIN_SPINDLE_0_OVERRIDE = 0.5_ and _MAX_SPINDLE_0_OVERRIDE = 1.2_ - Will allow you to change the spindle override within a limit from 80% to 120%. + [NOTE] -If no values are given, MIN will be set to 0.1 and MAX to 1.0. +If no values are given, MIN will be set to 0.5 and MAX to 1.0. - _LATHE = 1_ - Set the screen layout to control a lathe. - _BACK_TOOL_LATHE = 1_ - Is optional and will switch the X axis in a way you need for a back tool lathe. @@ -148,7 +150,14 @@ See also the <>. If not specified, GMOCCAPY will look in the following order for NGC files: First `linuxcnc/nc_files` and then the users home directory. -- _DEFAULT_SPINDLE_SPEED_ - Start value for <> if value not present in preferences file or file is not present. Will have no effect with valid preferences file. +- _DEFAULT_SPINDLE_0_SPEED_ - Sets the rpm to be used if the spindle is started and no S value has been set. Defaults to 200. +- _MIN_SPINDLE_0_SPEED_ - Sets the lower limit of the spindle bar shown in the spindle frame on the main screen. Defaults to 100. +- _MAX_SPINDLE_0_SPEED_ - Sets the upper limit of the spindle bar shown in the spindle frame on the main screen. Defaults to 2500. + +[NOTE] +It is no error giving values that didn't match the minimum and maximum speed of the spindle. +If you set _Spindle bar max_ to 2000 and your spindle makes 4000 RPM, only the bar level will be wrong on higher speeds than 2000 RPM. + - _MIN_ANGULAR_VELOCITY_ - Sets the minimal jog velocity of the machine for rotary axes. - _MAX_ANGULAR_VELOCITY_ - Sets the maximal jog velocity of the machine for rotary axes. @@ -494,9 +503,10 @@ DISPLAY = gmoccapy using these parameters: ---- Log level +VERBOSE -v DEBUG -d INFO -i -VERBOSE -v +WARNING -w ERROR -q ---- @@ -1402,25 +1412,6 @@ By default all scales are set using the calculation: (MAX - MIN)/100 ---- -[[gmoccapy-settings-spindle]] -.Spindle -* _Starting RPM_ - Sets the rpm to be used if the spindle is started and no S value has been set. -+ -[NOTE] -This value will be presetted according to your settings in `[DISPLAY] DEFAULT_SPINDLE_SPEED` of your INI file. -If you change the settings on the settings page, that value will be default from that moment, your INI file will not be modified. - -* _Spindle bar min_ and _Spindle bar max_ - Sets the limits of the spindle bar shown in the INFO frame on the main screen. -+ -==== -Default values are: + -MIN = 0 + -MAX = 6000 -==== -+ -[NOTE] -It is no error giving wrong values. -If you give a maximum of 2000 and your spindle makes 4000 RPM, only the bar level will be wrong on higher speeds than 2000 RPM. .Unlock settings diff --git a/src/emc/usr_intf/gmoccapy/gmoccapy.glade b/src/emc/usr_intf/gmoccapy/gmoccapy.glade index 049c965ed4f..d82213b69e3 100644 --- a/src/emc/usr_intf/gmoccapy/gmoccapy.glade +++ b/src/emc/usr_intf/gmoccapy/gmoccapy.glade @@ -111,24 +111,6 @@ 100 1 - - 100000 - 6000 - 50 - - - - 20000 - 50 - - - - 50 - 20000 - 300 - 25 - - 1 100 @@ -5918,137 +5900,6 @@ to test your settings. 0 - - - True - False - 0.5 - - - - True - False - 6 - 6 - 5 - 5 - False - 2 - 3 - - - True - False - True - Starting RPM - 0 - - - 0 - 0 - - - - - True - False - True - Spindle bar min - 0 - - - 0 - 1 - - - - - True - False - True - Spindle bar max - 0 - - - 0 - 2 - - - - - True - True - - True - 1 - etched-in - False - False - adj_start_spindle_RPM - 1 - True - - - 1 - 0 - - - - - True - True - - True - 1 - etched-in - False - False - adj_spindle_bar_min - 1 - True - - - 1 - 1 - - - - - True - True - - True - 7 - 1 - etched-in - False - False - adj_spindle_bar_max - 1 - True - - - 1 - 2 - - - - - - - True - False - <b>Spindle</b> - True - - - - - False - True - 1 - - True @@ -6128,7 +5979,7 @@ to test your settings. False False - 2 + 1 @@ -6146,6 +5997,9 @@ to test your settings. + + + True diff --git a/src/emc/usr_intf/gmoccapy/gmoccapy.py b/src/emc/usr_intf/gmoccapy/gmoccapy.py index 6ec1c126325..fa2e06acad6 100644 --- a/src/emc/usr_intf/gmoccapy/gmoccapy.py +++ b/src/emc/usr_intf/gmoccapy/gmoccapy.py @@ -386,8 +386,6 @@ def __init__(self, argv): self.widgets["ntb_button"].show() # the velocity settings - self.widgets.adj_spindle_bar_min.set_value(self.min_spindle_rev) - self.widgets.adj_spindle_bar_max.set_value(self.max_spindle_rev) self.widgets.spindle_feedback_bar.set_property("min", float(self.min_spindle_rev)) self.widgets.spindle_feedback_bar.set_property("max", float(self.max_spindle_rev)) @@ -481,7 +479,6 @@ def __init__(self, argv): self.widgets.chk_toggle_readout.set_active(self.toggle_readout) - self.widgets.adj_start_spindle_RPM.set_value(self.spindle_start_rpm) self.widgets.gcode_view.set_editable(False) self.widgets.ntb_user_tabs.remove_page(0) @@ -639,8 +636,9 @@ def _get_pref_data(self): self.scale_rapid_override = self.prefs.getpref("scale_rapid_override", 1, float) # the velocity settings - self.min_spindle_rev = self.prefs.getpref("spindle_bar_min", 0.0, float) - self.max_spindle_rev = self.prefs.getpref("spindle_bar_max", 6000.0, float) + self.spindle_start_rpm = self.INI.DEFAULT_SPINDLE_0_SPEED + self.min_spindle_rev = self.INI.MIN_SPINDLE_0_SPEED + self.max_spindle_rev = self.INI.MAX_SPINDLE_0_SPEED self.turtle_jog_factor = self.prefs.getpref('turtle_jog_factor', 20, int) self.hide_turtle_jog_button = self.prefs.getpref("hide_turtle_jog_button", False, bool) @@ -649,10 +647,7 @@ def _get_pref_data(self): self.toggle_readout = self.prefs.getpref("toggle_readout", True, bool) - # if there is a INI Entry for default spindle speed, we will use that one as default - # but if there is a setting in our preference file, that one will beet the INI entry - default_spindle_speed = self.INI.DEFAULT_SPINDLE_0_SPEED - self.spindle_start_rpm = self.prefs.getpref( 'spindle_start_rpm', default_spindle_speed, float ) + self.spindle_start_rpm = self.INI.DEFAULT_SPINDLE_0_SPEED self.kbd_height = self.prefs.getpref("kbd_height", 250, int) self.kbd_width = self.prefs.getpref("kbd_width", 880, int) @@ -4629,20 +4624,6 @@ def on_spc_spindle_value_changed(self, widget, data=None): except: pass - def on_adj_start_spindle_RPM_value_changed(self, widget, data=None): - self.spindle_start_rpm = widget.get_value() - self.prefs.putpref("spindle_start_rpm", self.spindle_start_rpm, float) - - def on_adj_spindle_bar_min_value_changed(self, widget, data=None): - self.min_spindle_rev = widget.get_value() - self.prefs.putpref("spindle_bar_min", self.min_spindle_rev, float) - self.widgets.spindle_feedback_bar.set_property("min", self.min_spindle_rev) - - def on_adj_spindle_bar_max_value_changed(self, widget, data=None): - self.max_spindle_rev = widget.get_value() - self.prefs.putpref("spindle_bar_max", self.max_spindle_rev, float) - self.widgets.spindle_feedback_bar.set_property("max", self.max_spindle_rev) - # ========================================================= # Coolant an mist coolant button def on_tbtn_flood_toggled(self, widget, data=None): From 100ff695165a1a80df959854364f3b9c005c21d1 Mon Sep 17 00:00:00 2001 From: Hans Unzner Date: Mon, 9 Feb 2026 21:29:50 +0100 Subject: [PATCH 07/24] gscreen: use DEFAULT_LINEAR_VELOCITY from DISPLAY instead TRAJ --- share/gscreen/skins/silverdragon/silverdragon_handler.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/share/gscreen/skins/silverdragon/silverdragon_handler.py b/share/gscreen/skins/silverdragon/silverdragon_handler.py index 8f5a96c96f6..9ca9fd934ec 100644 --- a/share/gscreen/skins/silverdragon/silverdragon_handler.py +++ b/share/gscreen/skins/silverdragon/silverdragon_handler.py @@ -201,7 +201,7 @@ def initialize_preferences(self): default_spindle_speed = self.gscreen.inifile.getreal("DISPLAY", "DEFAULT_SPINDLE_SPEED") self.spindle_start_rpm = self.gscreen.prefs.getpref( 'spindle_start_rpm', default_spindle_speed, float ) # get the values for the sliders - default_jog_vel = self.gscreen.inifile.getreal("TRAJ", "DEFAULT_LINEAR_VELOCITY") + default_jog_vel = self.gscreen.inifile.getreal("DISPLAY", "DEFAULT_LINEAR_VELOCITY") self.fast_jog = default_jog_vel self.slow_jog = default_jog_vel / self.slow_jog_factor self.jog_rate_max = self.gscreen.inifile.getreal("TRAJ", "MAX_LINEAR_VELOCITY") From c7075a144154d10d66066c49625badd0c7169eba Mon Sep 17 00:00:00 2001 From: Hans Unzner Date: Mon, 2 Feb 2026 22:27:25 +0100 Subject: [PATCH 08/24] gmoccapy: DEFAULT_LINEAR_VELOCITY + MAX_LINEAR_VELOCITY from qt_istat (TRAJ --> DISPLAY) --- src/emc/usr_intf/gmoccapy/getiniinfo.py | 23 ----------------------- src/emc/usr_intf/gmoccapy/gmoccapy.py | 4 ++-- 2 files changed, 2 insertions(+), 25 deletions(-) diff --git a/src/emc/usr_intf/gmoccapy/getiniinfo.py b/src/emc/usr_intf/gmoccapy/getiniinfo.py index 861f1a01ed9..1183c852dc4 100644 --- a/src/emc/usr_intf/gmoccapy/getiniinfo.py +++ b/src/emc/usr_intf/gmoccapy/getiniinfo.py @@ -221,29 +221,6 @@ def get_backtool_lathe(self): def get_lathe_wear_offsets(self): return self.inifile.getbool("DISPLAY", "LATHE_WEAR_OFFSETS", fallback=False) - def get_jog_vel(self): - # get default jog velocity - # must convert from INI's units per second to gmoccapy's units per minute - temp = self.inifile.getreal("TRAJ", "DEFAULT_LINEAR_VELOCITY") - if not temp: - temp = self.inifile.getreal("TRAJ", "MAX_LINEAR_VELOCITY" ) - if temp: - temp = temp / 2 - LOG.warning("No DEFAULT_LINEAR_VELOCITY entry found in [TRAJ] of INI file. Using half on MAX_LINEAR_VELOCITY.") - else: - temp = 3.0 - LOG.warning("No DEFAULT_LINEAR_VELOCITY entry found in [TRAJ] of INI file. Using default value of 180 units / min.") - return temp * 60 - - def get_max_jog_vel(self): - # get max jog velocity - # must convert from INI's units per second to gmoccapy's units per minute - temp = self.inifile.getreal("TRAJ", "MAX_LINEAR_VELOCITY") - if not temp: - temp = 10.0 - LOG.warning("No MAX_LINEAR_VELOCITY entry found in [TRAJ] of INI file. Using default value of 600 units / min.") - return temp * 60 - def get_embedded_tabs(self): # Check INI file for embed commands # NAME is used as the tab label if a notebook is used diff --git a/src/emc/usr_intf/gmoccapy/gmoccapy.py b/src/emc/usr_intf/gmoccapy/gmoccapy.py index fa2e06acad6..360ac0c58c6 100644 --- a/src/emc/usr_intf/gmoccapy/gmoccapy.py +++ b/src/emc/usr_intf/gmoccapy/gmoccapy.py @@ -600,8 +600,8 @@ def _get_ini_data(self): self.no_force_homing = self.get_ini_info.get_no_force_homing() # get the values for the sliders - self.rabbit_jog = self.get_ini_info.get_jog_vel() - self.jog_rate_max = self.get_ini_info.get_max_jog_vel() + self.rabbit_jog = self.INI.DEFAULT_LINEAR_JOG_VEL + self.jog_rate_max = self.INI.MAX_LINEAR_JOG_VEL self.spindle_override_max = self.INI.MAX_SPINDLE_OVERRIDE/100 self.spindle_override_min = self.INI.MIN_SPINDLE_OVERRIDE/100 From 11dfab3401dc20a50a5669d12e03e640f24c8214 Mon Sep 17 00:00:00 2001 From: Hans Unzner Date: Tue, 27 Jan 2026 21:44:54 +0100 Subject: [PATCH 09/24] gmoccapy: change SPINDLE => SPINDLE_0 in *.ini files --- configs/sim/gmoccapy/6_axis.ini | 9 +++++---- configs/sim/gmoccapy/7_axis.ini | 9 +++++---- configs/sim/gmoccapy/7_axis_tool.ini | 9 +++++---- configs/sim/gmoccapy/8_axis.ini | 9 +++++---- configs/sim/gmoccapy/9_axis.ini | 7 ++++--- configs/sim/gmoccapy/gmoccapy.ini | 2 +- configs/sim/gmoccapy/gmoccapy_4_axis.ini | 7 +++++-- configs/sim/gmoccapy/gmoccapy_800x600.ini | 8 +++++--- configs/sim/gmoccapy/gmoccapy_XYZAB.ini | 7 +++++-- configs/sim/gmoccapy/gmoccapy_XYZAC.ini | 7 +++++-- configs/sim/gmoccapy/gmoccapy_XYZCW.ini | 9 ++++++--- configs/sim/gmoccapy/gmoccapy_blockdelete.ini | 8 +++++--- configs/sim/gmoccapy/gmoccapy_left_panel.ini | 7 +++++-- configs/sim/gmoccapy/gmoccapy_messages.ini | 7 +++++-- configs/sim/gmoccapy/gmoccapy_pedant.ini | 7 +++++-- configs/sim/gmoccapy/gmoccapy_pyngcgui.ini | 8 +++++--- configs/sim/gmoccapy/gmoccapy_pyngcgui_gcmc.ini | 8 +++++--- configs/sim/gmoccapy/gmoccapy_qt_messages.ini | 8 +++++--- configs/sim/gmoccapy/gmoccapy_right_panel.ini | 7 +++++-- .../gmoccapy/gmoccapy_sim_hardware_button.ini | 7 +++++-- configs/sim/gmoccapy/gmoccapy_tool_sensor.ini | 7 ++++--- .../sim/gmoccapy/gmoccapy_with_user_tabs.ini | 7 +++++-- src/emc/usr_intf/pncconf/build_INI.py | 17 ++++++++++++++++- 23 files changed, 121 insertions(+), 60 deletions(-) diff --git a/configs/sim/gmoccapy/6_axis.ini b/configs/sim/gmoccapy/6_axis.ini index 4a1a0179f8c..77f288f9a61 100644 --- a/configs/sim/gmoccapy/6_axis.ini +++ b/configs/sim/gmoccapy/6_axis.ini @@ -1,6 +1,6 @@ [EMC] VERSION = 1.1 -MACHINE = gmoccapy_9_axis +MACHINE = gmoccapy_6_axis DEBUG = 0 [DISPLAY] @@ -15,10 +15,11 @@ GEOMETRY = XYZABC # Values that will be allowed for override, 1.0 = 100% MAX_FEED_OVERRIDE = 1.5 -MAX_SPINDLE_OVERRIDE = 1.2 -MIN_SPINDLE_OVERRIDE = 0.5 +MAX_SPINDLE_0_OVERRIDE = 1.2 +MIN_SPINDLE_0_OVERRIDE = 0.5 -DEFAULT_SPINDLE_SPEED = 500 +# Start value for spindle speed +DEFAULT_SPINDLE_0_SPEED = 500 # list of selectable jog increments INCREMENTS = 1.000 mm, 0.100 mm, 0.010 mm, 0.001 mm ,1.2345 in diff --git a/configs/sim/gmoccapy/7_axis.ini b/configs/sim/gmoccapy/7_axis.ini index e5d25e7fddb..7a3eab53627 100644 --- a/configs/sim/gmoccapy/7_axis.ini +++ b/configs/sim/gmoccapy/7_axis.ini @@ -1,6 +1,6 @@ [EMC] VERSION = 1.1 -MACHINE = gmoccapy_9_axis +MACHINE = gmoccapy_7_axis DEBUG = 0 [DISPLAY] @@ -15,10 +15,11 @@ GEOMETRY = XYZABCUVW # Values that will be allowed for override, 1.0 = 100% MAX_FEED_OVERRIDE = 1.5 -MAX_SPINDLE_OVERRIDE = 1.2 -MIN_SPINDLE_OVERRIDE = 0.5 +MAX_SPINDLE_0_OVERRIDE = 1.2 +MIN_SPINDLE_0_OVERRIDE = 0.5 -DEFAULT_SPINDLE_SPEED = 500 +# Start value for spindle speed +DEFAULT_SPINDLE_0_SPEED = 500 # list of selectable jog increments INCREMENTS = 1.000 mm, 0.100 mm, 0.010 mm, 0.001 mm ,1.2345 in diff --git a/configs/sim/gmoccapy/7_axis_tool.ini b/configs/sim/gmoccapy/7_axis_tool.ini index 62c9b2578a3..2cf7737448c 100644 --- a/configs/sim/gmoccapy/7_axis_tool.ini +++ b/configs/sim/gmoccapy/7_axis_tool.ini @@ -1,6 +1,6 @@ [EMC] VERSION = 1.1 -MACHINE = gmoccapy_9_axis +MACHINE = gmoccapy_7_axis_tool DEBUG = 0 [DISPLAY] @@ -15,10 +15,11 @@ GEOMETRY = XYZABCUVW # Values that will be allowed for override, 1.0 = 100% MAX_FEED_OVERRIDE = 1.5 -MAX_SPINDLE_OVERRIDE = 1.2 -MIN_SPINDLE_OVERRIDE = 0.5 +MAX_SPINDLE_0_OVERRIDE = 1.2 +MIN_SPINDLE_0_OVERRIDE = 0.5 -DEFAULT_SPINDLE_SPEED = 500 +# Start value for spindle speed +DEFAULT_SPINDLE_0_SPEED = 500 # list of selectable jog increments INCREMENTS = 1.000 mm, 0.100 mm, 0.010 mm, 0.001 mm ,1.2345 in diff --git a/configs/sim/gmoccapy/8_axis.ini b/configs/sim/gmoccapy/8_axis.ini index bbfd5b65dde..93f72294e45 100644 --- a/configs/sim/gmoccapy/8_axis.ini +++ b/configs/sim/gmoccapy/8_axis.ini @@ -1,6 +1,6 @@ [EMC] VERSION = 1.1 -MACHINE = gmoccapy_9_axis +MACHINE = gmoccapy_8_axis DEBUG = 0 [DISPLAY] @@ -15,10 +15,11 @@ GEOMETRY = XYZABCUVW # Values that will be allowed for override, 1.0 = 100% MAX_FEED_OVERRIDE = 1.5 -MAX_SPINDLE_OVERRIDE = 1.2 -MIN_SPINDLE_OVERRIDE = 0.5 +MAX_SPINDLE_0_OVERRIDE = 1.2 +MIN_SPINDLE_0_OVERRIDE = 0.5 -DEFAULT_SPINDLE_SPEED = 500 +# Start value for spindle speed +DEFAULT_SPINDLE_0_SPEED = 500 # list of selectable jog increments INCREMENTS = 1.000 mm, 0.100 mm, 0.010 mm, 0.001 mm ,1.2345 in diff --git a/configs/sim/gmoccapy/9_axis.ini b/configs/sim/gmoccapy/9_axis.ini index 33fac9bce8d..9d099d0bfbd 100644 --- a/configs/sim/gmoccapy/9_axis.ini +++ b/configs/sim/gmoccapy/9_axis.ini @@ -15,10 +15,11 @@ GEOMETRY = XYZABCUVW # Values that will be allowed for override, 1.0 = 100% MAX_FEED_OVERRIDE = 1.5 -MAX_SPINDLE_OVERRIDE = 1.2 -MIN_SPINDLE_OVERRIDE = 0.5 +MAX_SPINDLE_0_OVERRIDE = 1.2 +MIN_SPINDLE_0_OVERRIDE = 0.5 -DEFAULT_SPINDLE_SPEED = 500 +# Start value for spindle speed +DEFAULT_SPINDLE_0_SPEED = 500 # list of selectable jog increments INCREMENTS = 1.000 mm, 0.100 mm, 0.010 mm, 0.001 mm ,1.2345 in diff --git a/configs/sim/gmoccapy/gmoccapy.ini b/configs/sim/gmoccapy/gmoccapy.ini index 472d550c2cc..ddb8238eabc 100644 --- a/configs/sim/gmoccapy/gmoccapy.ini +++ b/configs/sim/gmoccapy/gmoccapy.ini @@ -26,7 +26,7 @@ MAX_FEED_OVERRIDE = 1.5 MIN_SPINDLE_0_OVERRIDE = 0.5 MAX_SPINDLE_0_OVERRIDE = 1.2 -# Spindel start speed +# Spindle start speed DEFAULT_SPINDLE_0_SPEED = 450 # Scaling of spindle speed bar MIN_SPINDLE_0_SPEED = 0 diff --git a/configs/sim/gmoccapy/gmoccapy_4_axis.ini b/configs/sim/gmoccapy/gmoccapy_4_axis.ini index 34e0bd18085..0d476b03e6b 100644 --- a/configs/sim/gmoccapy/gmoccapy_4_axis.ini +++ b/configs/sim/gmoccapy/gmoccapy_4_axis.ini @@ -13,8 +13,11 @@ CYCLE_TIME = 100 # Highest value that will be allowed for feed override, 1.0 = 100% MAX_FEED_OVERRIDE = 1.5 -MAX_SPINDLE_OVERRIDE = 1.2 -MIN_SPINDLE_OVERRIDE = .5 +MAX_SPINDLE_0_OVERRIDE = 1.2 +MIN_SPINDLE_0_OVERRIDE = .5 + +# Start value for spindle speed +DEFAULT_SPINDLE_0_SPEED = 450 # Prefix to be used PROGRAM_PREFIX = ../../nc_files/ diff --git a/configs/sim/gmoccapy/gmoccapy_800x600.ini b/configs/sim/gmoccapy/gmoccapy_800x600.ini index 8c2f29bdca9..63a20c4b30f 100644 --- a/configs/sim/gmoccapy/gmoccapy_800x600.ini +++ b/configs/sim/gmoccapy/gmoccapy_800x600.ini @@ -22,14 +22,16 @@ CYCLE_TIME = 100 # Values that will be allowed for override, 1.0 = 100% MAX_FEED_OVERRIDE = 1.5 -MAX_SPINDLE_OVERRIDE = 1.2 -MIN_SPINDLE_OVERRIDE = 0.5 +MAX_SPINDLE_0_OVERRIDE = 1.2 +MIN_SPINDLE_0_OVERRIDE = 0.5 + +# Start value for spindle speed +DEFAULT_SPINDLE_0_SPEED = 450 # Max and default jog speeds in units per second MAX_LINEAR_VELOCITY = 166 DEFAULT_LINEAR_VELOCITY = 100 MAX_ANGULAR_VELOCITY = 234 -DEFAULT_SPINDLE_SPEED = 450 # Prefix to be used PROGRAM_PREFIX = ../../nc_files/ diff --git a/configs/sim/gmoccapy/gmoccapy_XYZAB.ini b/configs/sim/gmoccapy/gmoccapy_XYZAB.ini index 75c0997fcd4..d4b679ff6ba 100644 --- a/configs/sim/gmoccapy/gmoccapy_XYZAB.ini +++ b/configs/sim/gmoccapy/gmoccapy_XYZAB.ini @@ -35,8 +35,11 @@ CYCLE_TIME = 100 # Highest value that will be allowed for feed override, 1.0 = 100% MAX_FEED_OVERRIDE = 1.5 -MAX_SPINDLE_OVERRIDE = 1.2 -MIN_SPINDLE_OVERRIDE = .5 +MAX_SPINDLE_0_OVERRIDE = 1.2 +MIN_SPINDLE_0_OVERRIDE = .5 + +# Start value for spindle speed +DEFAULT_SPINDLE_0_SPEED = 450 # Max and default jog speeds in units per second MAX_LINEAR_VELOCITY = 166 diff --git a/configs/sim/gmoccapy/gmoccapy_XYZAC.ini b/configs/sim/gmoccapy/gmoccapy_XYZAC.ini index 1b9348e4742..37aa862479b 100644 --- a/configs/sim/gmoccapy/gmoccapy_XYZAC.ini +++ b/configs/sim/gmoccapy/gmoccapy_XYZAC.ini @@ -26,8 +26,11 @@ CYCLE_TIME = 100 # Highest value that will be allowed for feed override, 1.0 = 100% MAX_FEED_OVERRIDE = 1.5 -MAX_SPINDLE_OVERRIDE = 1.2 -MIN_SPINDLE_OVERRIDE = .5 +MAX_SPINDLE_0_OVERRIDE = 1.2 +MIN_SPINDLE_0_OVERRIDE = .5 + +# Start value for spindle speed +DEFAULT_SPINDLE_0_SPEED = 450 # Max and default jog speeds in units per second MAX_LINEAR_VELOCITY = 166 diff --git a/configs/sim/gmoccapy/gmoccapy_XYZCW.ini b/configs/sim/gmoccapy/gmoccapy_XYZCW.ini index 9fbb984d4f7..fe8fb4e2a43 100644 --- a/configs/sim/gmoccapy/gmoccapy_XYZCW.ini +++ b/configs/sim/gmoccapy/gmoccapy_XYZCW.ini @@ -9,7 +9,7 @@ [EMC] VERSION = 1.1 -MACHINE = gmoccapy XYZAB +MACHINE = gmoccapy XYZCW DEBUG = 0 #DEBUG = 0x7FFFFFFF @@ -22,8 +22,11 @@ CYCLE_TIME = 100 # Highest value that will be allowed for feed override, 1.0 = 100% MAX_FEED_OVERRIDE = 1.5 -MAX_SPINDLE_OVERRIDE = 1.2 -MIN_SPINDLE_OVERRIDE = .5 +MAX_SPINDLE_0_OVERRIDE = 1.2 +MIN_SPINDLE_0_OVERRIDE = .5 + +# Start value for spindle speed +DEFAULT_SPINDLE_0_SPEED = 450 # Max and default jog speeds in units per second MAX_LINEAR_VELOCITY = 166 diff --git a/configs/sim/gmoccapy/gmoccapy_blockdelete.ini b/configs/sim/gmoccapy/gmoccapy_blockdelete.ini index 4043aa966d9..c734a61fa40 100644 --- a/configs/sim/gmoccapy/gmoccapy_blockdelete.ini +++ b/configs/sim/gmoccapy/gmoccapy_blockdelete.ini @@ -22,14 +22,16 @@ CYCLE_TIME = 100 # Values that will be allowed for override, 1.0 = 100% MAX_FEED_OVERRIDE = 1.5 -MAX_SPINDLE_OVERRIDE = 1.2 -MIN_SPINDLE_OVERRIDE = 0.5 +MAX_SPINDLE_0_OVERRIDE = 1.2 +MIN_SPINDLE_0_OVERRIDE = 0.5 + +# Start value for spindle speed +DEFAULT_SPINDLE_0_SPEED = 450 # Max and default jog speeds in units per second MAX_LINEAR_VELOCITY = 166 DEFAULT_LINEAR_VELOCITY = 100 MAX_ANGULAR_VELOCITY = 234 -DEFAULT_SPINDLE_SPEED = 450 # Prefix to be used PROGRAM_PREFIX = ../../nc_files/ diff --git a/configs/sim/gmoccapy/gmoccapy_left_panel.ini b/configs/sim/gmoccapy/gmoccapy_left_panel.ini index 52c9d8b3a30..381b3ccfa26 100644 --- a/configs/sim/gmoccapy/gmoccapy_left_panel.ini +++ b/configs/sim/gmoccapy/gmoccapy_left_panel.ini @@ -22,8 +22,11 @@ CYCLE_TIME = 100 # Highest value that will be allowed for feed override, 1.0 = 100% MAX_FEED_OVERRIDE = 1.5 -MAX_SPINDLE_OVERRIDE = 1.2 -MIN_SPINDLE_OVERRIDE = .5 +MAX_SPINDLE_0_OVERRIDE = 1.2 +MIN_SPINDLE_0_OVERRIDE = .5 + +# Start value for spindle speed +DEFAULT_SPINDLE_0_SPEED = 450 # Prefix to be used PROGRAM_PREFIX = ../../nc_files/ diff --git a/configs/sim/gmoccapy/gmoccapy_messages.ini b/configs/sim/gmoccapy/gmoccapy_messages.ini index 705f051028f..d7be57ad358 100644 --- a/configs/sim/gmoccapy/gmoccapy_messages.ini +++ b/configs/sim/gmoccapy/gmoccapy_messages.ini @@ -18,8 +18,11 @@ CYCLE_TIME = 100 # Highest value that will be allowed for feed override, 1.0 = 100% MAX_FEED_OVERRIDE = 1.5 -MAX_SPINDLE_OVERRIDE = 1.2 -MIN_SPINDLE_OVERRIDE = .5 +MAX_SPINDLE_0_OVERRIDE = 1.2 +MIN_SPINDLE_0_OVERRIDE = .5 + +# Start value for spindle speed +DEFAULT_SPINDLE_0_SPEED = 450 # Max and default jog speeds in units per second MAX_LINEAR_VELOCITY = 166 diff --git a/configs/sim/gmoccapy/gmoccapy_pedant.ini b/configs/sim/gmoccapy/gmoccapy_pedant.ini index 8ca75a3fd8c..b3c79520439 100644 --- a/configs/sim/gmoccapy/gmoccapy_pedant.ini +++ b/configs/sim/gmoccapy/gmoccapy_pedant.ini @@ -22,8 +22,11 @@ CYCLE_TIME = 100 # Highest value that will be allowed for feed override, 1.0 = 100% MAX_FEED_OVERRIDE = 1.5 -MAX_SPINDLE_OVERRIDE = 1.2 -MIN_SPINDLE_OVERRIDE = .5 +MAX_SPINDLE_0_OVERRIDE = 1.2 +MIN_SPINDLE_0_OVERRIDE = .5 + +# Start value for spindle speed +DEFAULT_SPINDLE_0_SPEED = 450 # Prefix to be used PROGRAM_PREFIX = /home/emcmesa/linuxcnc/nc_files diff --git a/configs/sim/gmoccapy/gmoccapy_pyngcgui.ini b/configs/sim/gmoccapy/gmoccapy_pyngcgui.ini index 6bfc5c446a9..90a80661775 100644 --- a/configs/sim/gmoccapy/gmoccapy_pyngcgui.ini +++ b/configs/sim/gmoccapy/gmoccapy_pyngcgui.ini @@ -50,14 +50,16 @@ CYCLE_TIME = 100 # Values that will be allowed for override, 1.0 = 100% MAX_FEED_OVERRIDE = 1.5 -MAX_SPINDLE_OVERRIDE = 1.2 -MIN_SPINDLE_OVERRIDE = 0.5 +MAX_SPINDLE_0_OVERRIDE = 1.2 +MIN_SPINDLE_0_OVERRIDE = 0.5 + +# Start value for spindle speed +DEFAULT_SPINDLE_0_SPEED = 450 # Max and default jog speeds in units per second MAX_LINEAR_VELOCITY = 166 DEFAULT_LINEAR_VELOCITY = 100 MAX_ANGULAR_VELOCITY = 234 -DEFAULT_SPINDLE_SPEED = 450 # Prefix to be used PROGRAM_PREFIX = ../../nc_files/ diff --git a/configs/sim/gmoccapy/gmoccapy_pyngcgui_gcmc.ini b/configs/sim/gmoccapy/gmoccapy_pyngcgui_gcmc.ini index de4a5e50836..04af5caed68 100644 --- a/configs/sim/gmoccapy/gmoccapy_pyngcgui_gcmc.ini +++ b/configs/sim/gmoccapy/gmoccapy_pyngcgui_gcmc.ini @@ -62,14 +62,16 @@ CYCLE_TIME = 100 # Values that will be allowed for override, 1.0 = 100% MAX_FEED_OVERRIDE = 1.5 -MAX_SPINDLE_OVERRIDE = 1.2 -MIN_SPINDLE_OVERRIDE = 0.5 +MAX_SPINDLE_0_OVERRIDE = 1.2 +MIN_SPINDLE_0_OVERRIDE = 0.5 + +# Start value for spindle speed +DEFAULT_SPINDLE_0_SPEED = 450 # Max and default jog speeds in units per second MAX_LINEAR_VELOCITY = 166 DEFAULT_LINEAR_VELOCITY = 100 MAX_ANGULAR_VELOCITY = 234 -DEFAULT_SPINDLE_SPEED = 450 # Introductory graphic INTRO_GRAPHIC = linuxcnc.gif diff --git a/configs/sim/gmoccapy/gmoccapy_qt_messages.ini b/configs/sim/gmoccapy/gmoccapy_qt_messages.ini index d15480633da..79593704ef7 100644 --- a/configs/sim/gmoccapy/gmoccapy_qt_messages.ini +++ b/configs/sim/gmoccapy/gmoccapy_qt_messages.ini @@ -22,14 +22,16 @@ CYCLE_TIME = 100 # Values that will be allowed for override, 1.0 = 100% MAX_FEED_OVERRIDE = 1.5 -MAX_SPINDLE_OVERRIDE = 1.2 -MIN_SPINDLE_OVERRIDE = 0.5 +MAX_SPINDLE_0_OVERRIDE = 1.2 +MIN_SPINDLE_0_OVERRIDE = 0.5 + +# Start value for spindle speed +DEFAULT_SPINDLE_0_SPEED = 450 # Max and default jog speeds in units per second MAX_LINEAR_VELOCITY = 166 DEFAULT_LINEAR_VELOCITY = 100 MAX_ANGULAR_VELOCITY = 234 -DEFAULT_SPINDLE_SPEED = 450 # Prefix to be used PROGRAM_PREFIX = ../../nc_files/ diff --git a/configs/sim/gmoccapy/gmoccapy_right_panel.ini b/configs/sim/gmoccapy/gmoccapy_right_panel.ini index 62213d687d5..a416b950e7d 100644 --- a/configs/sim/gmoccapy/gmoccapy_right_panel.ini +++ b/configs/sim/gmoccapy/gmoccapy_right_panel.ini @@ -18,8 +18,11 @@ CYCLE_TIME = 100 # Highest value that will be allowed for feed override, 1.0 = 100% MAX_FEED_OVERRIDE = 1.5 -MAX_SPINDLE_OVERRIDE = 1.2 -MIN_SPINDLE_OVERRIDE = .5 +MAX_SPINDLE_0_OVERRIDE = 1.2 +MIN_SPINDLE_0_OVERRIDE = .5 + +# Start value for spindle speed +DEFAULT_SPINDLE_0_SPEED = 450 # Prefix to be used PROGRAM_PREFIX = ../../nc_files/ diff --git a/configs/sim/gmoccapy/gmoccapy_sim_hardware_button.ini b/configs/sim/gmoccapy/gmoccapy_sim_hardware_button.ini index 704e64d796d..f8ff45703dd 100644 --- a/configs/sim/gmoccapy/gmoccapy_sim_hardware_button.ini +++ b/configs/sim/gmoccapy/gmoccapy_sim_hardware_button.ini @@ -25,8 +25,11 @@ CYCLE_TIME = 100 # Highest value that will be allowed for feed override, 1.0 = 100% MAX_FEED_OVERRIDE = 1.5 -MAX_SPINDLE_OVERRIDE = 1.2 -MIN_SPINDLE_OVERRIDE = .5 +MAX_SPINDLE_0_OVERRIDE = 1.2 +MIN_SPINDLE_0_OVERRIDE = .5 + +# Start value for spindle speed +DEFAULT_SPINDLE_0_SPEED = 450 # Prefix to be used PROGRAM_PREFIX = ../../nc_files/ diff --git a/configs/sim/gmoccapy/gmoccapy_tool_sensor.ini b/configs/sim/gmoccapy/gmoccapy_tool_sensor.ini index 37daf107549..588ced46485 100644 --- a/configs/sim/gmoccapy/gmoccapy_tool_sensor.ini +++ b/configs/sim/gmoccapy/gmoccapy_tool_sensor.ini @@ -30,10 +30,11 @@ CYCLE_TIME = 100 # Highest value that will be allowed for feed override, 1.0 = 100% MAX_FEED_OVERRIDE = 1.5 -MAX_SPINDLE_OVERRIDE = 1.2 -MIN_SPINDLE_OVERRIDE = .5 +MAX_SPINDLE_0_OVERRIDE = 1.2 +MIN_SPINDLE_0_OVERRIDE = .5 -DEFAULT_SPINDLE_SPEED = 450 +# Start value for spindle speed +DEFAULT_SPINDLE_0_SPEED = 450 # Prefix to be used PROGRAM_PREFIX = ../../../nc_files/ diff --git a/configs/sim/gmoccapy/gmoccapy_with_user_tabs.ini b/configs/sim/gmoccapy/gmoccapy_with_user_tabs.ini index 9ac53efa54b..78b06595109 100644 --- a/configs/sim/gmoccapy/gmoccapy_with_user_tabs.ini +++ b/configs/sim/gmoccapy/gmoccapy_with_user_tabs.ini @@ -42,8 +42,11 @@ CYCLE_TIME = 100 # Highest value that will be allowed for feed override, 1.0 = 100% MAX_FEED_OVERRIDE = 1.5 -MAX_SPINDLE_OVERRIDE = 1.2 -MIN_SPINDLE_OVERRIDE = .5 +MAX_SPINDLE_0_OVERRIDE = 1.2 +MIN_SPINDLE_0_OVERRIDE = .5 + +# Start value for spindle speed +DEFAULT_SPINDLE_0_SPEED = 450 # Prefix to be used PROGRAM_PREFIX = ../../nc_files/ diff --git a/src/emc/usr_intf/pncconf/build_INI.py b/src/emc/usr_intf/pncconf/build_INI.py index 379978a4cff..55e924d78d9 100644 --- a/src/emc/usr_intf/pncconf/build_INI.py +++ b/src/emc/usr_intf/pncconf/build_INI.py @@ -91,12 +91,17 @@ def write_inifile(self, base): if self.d.position_feedback == 1: temp ="ACTUAL" else: temp = "COMMANDED" print("POSITION_FEEDBACK = %s"% temp, file=file) + print(file=file) + print("# Highest value that will be allowed for feed override, 1.0 = 100%", file=file) print("MAX_FEED_OVERRIDE = %f"% self.d.max_feed_override, file=file) - if self.d.frontend == _PD._QTDRAGON: + if self.d.frontend == _PD._QTDRAGON or self.d.frontend == _PD._GMOCCAPY: print("MAX_SPINDLE_0_OVERRIDE = %f"% self.d.max_spindle_override, file=file) print("MIN_SPINDLE_0_OVERRIDE = %f"% self.d.min_spindle_override, file=file) + print(file=file) + print("# Spindle start speed", file=file) print("DEFAULT_SPINDLE_0_SPEED = 500", file=file) + print(file=file) print("MIN_SPINDLE_0_SPEED = 100", file=file) print("MAX_SPINDLE_0_SPEED = 2500", file=file) # qtplasmac doesn't use spindle override @@ -104,13 +109,20 @@ def write_inifile(self, base): print("MAX_SPINDLE_OVERRIDE = %f"% self.d.max_spindle_override, file=file) print("MIN_SPINDLE_OVERRIDE = %f"% self.d.min_spindle_override, file=file) + print(file=file) + print("# Introductory graphic", file=file) print("INTRO_GRAPHIC = linuxcnc.gif", file=file) print("INTRO_TIME = 5", file=file) + print(file=file) + print("# Prefix to be used", file=file) print("PROGRAM_PREFIX = %s" % \ os.path.expanduser("~/linuxcnc/nc_files"), file=file) + print(file=file) if self.d.pyvcp: print("PYVCP = pyvcp-panel.xml", file=file) + print(file=file) # these are for AXIS GUI and QtPlasmaC + print("# list of selectable jog increments", file=file) if self.d.units == _PD._METRIC: if self.d.frontend == _PD._QTPLASMAC: print("INCREMENTS = %s"% self.d.increments_metric_qtplasmac, file=file) @@ -121,6 +133,7 @@ def write_inifile(self, base): print("INCREMENTS = %s"% self.d.increments_imperial_qtplasmac, file=file) else: print("INCREMENTS = %s"% self.d.increments_imperial, file=file) + print(file=file) if self.d.axes == 2: print("LATHE = 1", file=file) print("POSITION_FEEDBACK = %s"% temp, file=file) @@ -134,6 +147,8 @@ def write_inifile(self, base): if self.d.frontend != _PD._QTPLASMAC: print("EDITOR = %s"% self.d.editor, file=file) print("GEOMETRY = %s"% self.d.geometry, file=file) + print(file=file) + print("# Cycle time, in milliseconds, that display will sleep between polls", file=file) print("CYCLE_TIME = 100", file=file) # set up MDI macro buttons From 83291921c44ad0ba9acb1d5569b9c4eb5aaf90a7 Mon Sep 17 00:00:00 2001 From: Hans Unzner Date: Wed, 4 Feb 2026 12:27:14 +0100 Subject: [PATCH 10/24] update_ini: basic steps for updating 1.1 -> 1.2 --- scripts/linuxcnc.in | 2 +- src/emc/ini/update_ini.py | 167 +++++++++++++++++++++++++++----------- 2 files changed, 120 insertions(+), 49 deletions(-) diff --git a/scripts/linuxcnc.in b/scripts/linuxcnc.in index 789b9de0eca..5fb9be27d6b 100644 --- a/scripts/linuxcnc.in +++ b/scripts/linuxcnc.in @@ -476,7 +476,7 @@ function GetFromIniEx { # 2.1.5 check version GetFromIni VERSION EMC -if [ "$retval" != "1.1" ]; then +if [ "$retval" != "1.2" ]; then if [ -z "$DISPLAY" ]; then echo "INI file [EMC]VERSION indicates update is needed, but the update GUI can't run without an X display" exit 1 diff --git a/src/emc/ini/update_ini.py b/src/emc/ini/update_ini.py index 5ddc9ec2206..0d4264f2c9e 100755 --- a/src/emc/ini/update_ini.py +++ b/src/emc/ini/update_ini.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 -THIS_VERSION = "1.1" +THIS_VERSION = "1.2" import sys import os @@ -21,7 +21,7 @@ def copysection(block): newini.write(section.group(1)) all_sections.remove(block) else: - newini.write("\n#No Content\n") + newini.write("\n#No Content\n") def writeifexists(file, section, src_item, dest_item = "None"): #Writes a new entry to the file, but only if it exists @@ -62,25 +62,6 @@ def writeifexists(file, section, src_item, dest_item = "None"): print(t) exit() -if dialogs: - ret = messagebox._show("Confirm automatic update", - "This version of LinuxCNC separates the concepts of Axes and " - "Joints which necessitates changes to the INI and HAL files. " - "The changes required are described here:\n" - "http://linuxcnc.org/docs/2.9/html/ in the section " - "'Getting Started with LinuxCNC' -> 'Updating LinuxCNC'\n" - "The [EMC]VERSION data in your INI file indicates that your " - "configuration requires update.\n" - "A script exists that can attempt to automatically " - "reconfigure your configuration files.\nPress 'Yes' to perform " - "the conversion, 'No' to continue with the current configuration " - "files or 'Cancel' to exit LinuxCNC.\n" - "The process can not be automatically reversed, though a " - "backup version of your entire existing config will be created.", - messagebox.QUESTION, messagebox.YESNOCANCEL) - if ret == 'cancel': exit(42) - elif ret == 'no': exit(0) - # We want to work with the base INI file here, not the expanded version if #include is used filename = re.sub(r'\.expanded', '', filename) @@ -109,20 +90,44 @@ def writeifexists(file, section, src_item, dest_item = "None"): print(t) exit() -if ini.find('KINS', 'JOINTS') and not force and not version == "1.0": - if dialogs: - if messagebox.askquestion("Already Converted", - "The supplied INI file already has a [KINS] section. this probably " - "means that it was previously converted by hand. Continue conversion?" - "(Change [EMC]VERSION to %s to suppress these messages) " - % THIS_VERSION) != 'yes': - exit(0) - else: - if input("The supplied INI file already has a [KINS] section." - "this probably means that it was previously converted by hand. " - "Continue y/N? (Change [EMC]VERSION to %s to suppress these messages) " - % THIS_VERSION) != "y": - exit(0) +# Show start message with abort option +if dialogs: + ret = '' + if version == "1.0": + ret = messagebox._show("Confirm automatic update", + "This version of LinuxCNC separates the concepts of Axes and " + "Joints which necessitates changes to the INI and HAL files. " + "The changes required are described here:\n" + "http://linuxcnc.org/docs/2.9/html/ in the section " + "'Getting Started with LinuxCNC' -> 'Updating LinuxCNC'\n" + "The [EMC]VERSION data in your INI file indicates that your " + "configuration requires update.\n" + "A script exists that can attempt to automatically " + "reconfigure your configuration files.\nPress 'Yes' to perform " + "the conversion, 'No' to continue with the current configuration " + "files or 'Cancel' to exit LinuxCNC.\n" + "The process can not be automatically reversed, though a " + "backup version of your entire existing config will be created.", + messagebox.QUESTION, messagebox.YESNOCANCEL) + if ret == 'cancel': exit(42) + elif ret == 'no': exit(0) + +# Version specific message +if version == "1.0": + if ini.find('KINS', 'JOINTS') and not force and not version == "1.0": + if dialogs: + if messagebox.askquestion("Already Converted", + "The supplied INI file already has a [KINS] section. This probably " + "means that it was previously converted by hand. Continue conversion?" + "(Change [EMC]VERSION to %s to suppress these messages) " + % THIS_VERSION) != 'yes': + exit(0) + else: + if input("The supplied INI file already has a [KINS] section." + "This probably means that it was previously converted by hand. " + "Continue y/N? (Change [EMC]VERSION to %s to suppress these messages) " + % THIS_VERSION) != "y": + exit(0) # Looks like we are good to go, so first let's put the original configs # somewhere safe. @@ -165,16 +170,14 @@ def writeifexists(file, section, src_item, dest_item = "None"): print("halpaths = ", halpaths) -if version == "1.0": - #Just update the version in the INI - inistring = open(filename,'r').read() - newini = open(filename, 'w') - inistring = re.sub("VERSION *= *(.*)", "VERSION = %s" % THIS_VERSION, inistring) - newini.write(inistring) - newini.close() +########################################### +############ Convert INI files ############ +########################################### -if version == "$Revision$" or version < "1.0": - +def ini_preamble(): + """ + The part which is equal for the conversions up from version 1.1 + """ inistring = open(filename,'r').read() newini = open(filename, 'w') # Get a list of all sections @@ -198,7 +201,7 @@ def writeifexists(file, section, src_item, dest_item = "None"): all_sections.remove("EMC") section = re.search(r"\[EMC\](.+?)\n\[", inistring, re.DOTALL) if section: section = section.group(1) - newini.write("[EMC]\n") + newini.write("[EMC]") if section != None: if version != "0.0": section = re.sub("VERSION (.+)", "VERSION = %s" % THIS_VERSION, section) @@ -209,6 +212,18 @@ def writeifexists(file, section, src_item, dest_item = "None"): else: newini.write("VERSION = %s\n" % THIS_VERSION) + return inistring, newini, all_sections + +if version == "1.0": + #Just update the version in the INI + inistring = open(filename,'r').read() + newini = open(filename, 'w') + inistring = re.sub("VERSION *= *(.*)", "VERSION = %s" % THIS_VERSION, inistring) + newini.write(inistring) + newini.close() + +if version == "$Revision$" or version < "1.0": + inistring, newini, all_sections = ini_preamble() #These sections don't need any work. copysection("DISPLAY") copysection("FILTER") @@ -416,11 +431,67 @@ def writeifexists(file, section, src_item, dest_item = "None"): #That's the INI file done: newini.close() +if version < "1.2": + inistring, newini, all_sections = ini_preamble() + + all_sections.remove("DISPLAY") + section = re.search(r"\[DISPLAY\](.+?)\n\[", inistring, re.DOTALL) + if section: section = section.group(1) + newini.write("\n[DISPLAY]\n") + if section != None: + if re.search("MIN_SPINDLE_OVERRIDE", section): + section = re.sub("MIN_SPINDLE_OVERRIDE", "MIN_SPINDLE_0_OVERRIDE", section) + if re.search("MAX_SPINDLE_OVERRIDE", section): + section = re.sub("MAX_SPINDLE_OVERRIDE", "MAX_SPINDLE_0_OVERRIDE", section) + if re.search("DEFAULT_SPINDLE_SPEED", section): + section = re.sub("DEFAULT_SPINDLE_SPEED", "DEFAULT_SPINDLE_0_SPEED", section) + if re.search("MIN_SPINDLE_SPEED", section): + section = re.sub("MIN_SPINDLE_SPEED", "MIN_SPINDLE_0_SPEED", section) + if re.search("MAX_SPINDLE_SPEED", section): + section = re.sub("MAX_SPINDLE_SPEED", "MAX_SPINDLE_0_SPEED", section) + if re.search("MIN_VELOCITY", section): + section = re.sub("MIN_VELOCITY", "MIN_LINEAR_VELOCITY", section) + newini.write(section) + + # TODO update-ini 1.1 --> 1.2: + # + # [DISPLAY] + # MIN_SPINDLE_OVERRIDE -> MIN_SPINDLE_0_OVERRIDE + # MAX_SPINDLE_OVERRIDE -> MAX_SPINDLE_0_OVERRIDE + # DEFAULT_SPINDLE_SPEED -> DEFAULT_SPINDLE_0_SPEED + # MIN_SPINDLE_SPEED -> MIN_SPINDLE_0_SPEED + # MAX_SPINDLE_SPEED -> MAX_SPINDLE_0_SPEED + # + # copy [TRAJ]DEFAULT_LINEAR_VELOCITY -> [DISPLAY]DEFAULT_LINEAR_VELOCITY + # move [TRAJ]MIN_LINEAR_VELOCITY -> [DISPLAY]MIN_LINEAR_VELOCITY + # rename [TRAJ, DISPLAY]MIN_VELOCITY --> MIN_LINEAR_VELOCITY + # copy [TRAJ]MAX_LINEAR_VELOCITY -> [DISPLAY]MAX_LINEAR_VELOCITY + + #These sections don't need any work. + copysection("FILTER") + copysection("RS274NGC") + copysection("PYTHON") + copysection("EMCMOT") + copysection("TASK") + copysection("HAL") + copysection("HALUI") + copysection("TRAJ") + copysection("EMCIO") + + # If there were any custom sections, tag them on the end. + while all_sections: + copysection(all_sections[0]) + + #That's the INI file done: + newini.close() - # Now change all the pin names etc in the linked HAL files. - # Any machine can be jogged in world mode (in theory) but joint-mode jog-enable - # is not auto-linked for safety. +########################################### +############ Convert HAL files ############ +########################################### +# Now change all the pin names etc in the linked HAL files. +# Any machine can be jogged in world mode (in theory) +# but joint-mode jog-enable is not auto-linked for safety. if version == "$Revision$" or version < "1.0": From 6bce89ea7aa21b21fd6b7bfa3e430ec3cc7b86a3 Mon Sep 17 00:00:00 2001 From: Hans Unzner Date: Wed, 4 Feb 2026 14:13:47 +0100 Subject: [PATCH 11/24] update_ini: fix keep emtpy lines at the end of a section --- src/emc/ini/update_ini.py | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/emc/ini/update_ini.py b/src/emc/ini/update_ini.py index 0d4264f2c9e..5d7a4988828 100755 --- a/src/emc/ini/update_ini.py +++ b/src/emc/ini/update_ini.py @@ -14,14 +14,14 @@ def copysection(block): #Just makes a straight copy of blocks that don't need any work - regex = r"^\s*\[%s\](.+?)(?:^\s*\[|\Z)" % block - section = re.search(regex, inistring, re.M | re.DOTALL) - newini.write("\n[%s]" % block) - if section != None: + regex = r"^\s*\[%s\](\n(?:^(?!\[).*\n?)*)" % block + section = re.search(regex, inistring, re.M) + newini.write("[%s]" % block) + if section is not None: newini.write(section.group(1)) all_sections.remove(block) else: - newini.write("\n#No Content\n") + newini.write("\n#No Content\n\n") def writeifexists(file, section, src_item, dest_item = "None"): #Writes a new entry to the file, but only if it exists @@ -435,9 +435,10 @@ def ini_preamble(): inistring, newini, all_sections = ini_preamble() all_sections.remove("DISPLAY") - section = re.search(r"\[DISPLAY\](.+?)\n\[", inistring, re.DOTALL) + section = re.search(r"\[DISPLAY\](.+?\n)(?=\[)", inistring, re.DOTALL) + if section: section = section.group(1) - newini.write("\n[DISPLAY]\n") + newini.write("\n[DISPLAY]") if section != None: if re.search("MIN_SPINDLE_OVERRIDE", section): section = re.sub("MIN_SPINDLE_OVERRIDE", "MIN_SPINDLE_0_OVERRIDE", section) From 5259950906a95fe2891a765354a5cacea37e9521 Mon Sep 17 00:00:00 2001 From: Hans Unzner Date: Mon, 9 Feb 2026 00:38:31 +0100 Subject: [PATCH 12/24] update_ini: fix/improve regex for finding the DISPLAY section --- src/emc/ini/update_ini.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/emc/ini/update_ini.py b/src/emc/ini/update_ini.py index 5d7a4988828..fea6a4716f4 100755 --- a/src/emc/ini/update_ini.py +++ b/src/emc/ini/update_ini.py @@ -435,7 +435,7 @@ def ini_preamble(): inistring, newini, all_sections = ini_preamble() all_sections.remove("DISPLAY") - section = re.search(r"\[DISPLAY\](.+?\n)(?=\[)", inistring, re.DOTALL) + section = re.search(r"(?:^|\n)[ \t]*(?!#)\[DISPLAY\](.+?\n)(?=\[|$)", inistring, re.DOTALL) if section: section = section.group(1) newini.write("\n[DISPLAY]") @@ -467,7 +467,7 @@ def ini_preamble(): # move [TRAJ]MIN_LINEAR_VELOCITY -> [DISPLAY]MIN_LINEAR_VELOCITY # rename [TRAJ, DISPLAY]MIN_VELOCITY --> MIN_LINEAR_VELOCITY # copy [TRAJ]MAX_LINEAR_VELOCITY -> [DISPLAY]MAX_LINEAR_VELOCITY - + #These sections don't need any work. copysection("FILTER") copysection("RS274NGC") From 4a70de498a1ea86d5160932af1fd5ecc202d948f Mon Sep 17 00:00:00 2001 From: Hans Unzner Date: Sat, 7 Feb 2026 20:22:37 +0100 Subject: [PATCH 13/24] update_ini: copy values from TRAJ to DISPLAY --- src/emc/ini/update_ini.py | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/src/emc/ini/update_ini.py b/src/emc/ini/update_ini.py index fea6a4716f4..50e8f4ce110 100755 --- a/src/emc/ini/update_ini.py +++ b/src/emc/ini/update_ini.py @@ -28,6 +28,17 @@ def writeifexists(file, section, src_item, dest_item = "None"): if dest_item == 'None': dest_item = src_item val = ini.find(section, src_item) if val: file.write("%s = %s\n" % (dest_item, val)) + +def insert_after(key, new_line, section): + match = re.search(key, section) + if match: + # Find the end of the line that contains the match + line_end = section.find("\n", match.end()) + if line_end == -1: line_end = len(section) # match is on the last line + else: + line_end = len(section) # place it at the end + new_line += "\n" + return section[:line_end + 1] + new_line + section[line_end + 1:] force = 0 dialogs = 0 @@ -452,6 +463,22 @@ def ini_preamble(): section = re.sub("MAX_SPINDLE_SPEED", "MAX_SPINDLE_0_SPEED", section) if re.search("MIN_VELOCITY", section): section = re.sub("MIN_VELOCITY", "MIN_LINEAR_VELOCITY", section) + + + # Copy values from TRAJ + if not re.search("DEFAULT_LINEAR_VELOCITY", section): + val = ini.find("TRAJ", "DEFAULT_LINEAR_VELOCITY") + if val: + section = insert_after("MAX_LINEAR_VELOCITY", f"DEFAULT_LINEAR_VELOCITY = {val}\n" , section) + if not re.search("MIN_LINEAR_VELOCITY", section): + val = ini.find("TRAJ", "MIN_LINEAR_VELOCITY") + if val: + section = insert_after("MAX_LINEAR_VELOCITY", f"MIN_LINEAR_VELOCITY = {val}\n" , section) + if not re.search("MAX_LINEAR_VELOCITY", section): + val = ini.find("TRAJ", "MAX_LINEAR_VELOCITY") + if val: + section = insert_after("MIN_LINEAR_VELOCITY", f"MAX_LINEAR_VELOCITY = {val}\n" , section) + newini.write(section) # TODO update-ini 1.1 --> 1.2: @@ -465,7 +492,7 @@ def ini_preamble(): # # copy [TRAJ]DEFAULT_LINEAR_VELOCITY -> [DISPLAY]DEFAULT_LINEAR_VELOCITY # move [TRAJ]MIN_LINEAR_VELOCITY -> [DISPLAY]MIN_LINEAR_VELOCITY - # rename [TRAJ, DISPLAY]MIN_VELOCITY --> MIN_LINEAR_VELOCITY + # ~rename [TRAJ, DISPLAY]MIN_VELOCITY --> MIN_LINEAR_VELOCITY~ # copy [TRAJ]MAX_LINEAR_VELOCITY -> [DISPLAY]MAX_LINEAR_VELOCITY #These sections don't need any work. From b3b20e3ee911bdbd5a46439e4daa78e5b4513707 Mon Sep 17 00:00:00 2001 From: Hans Unzner Date: Mon, 9 Feb 2026 01:12:56 +0100 Subject: [PATCH 14/24] update_ini: remove MIN_LINEAR_VELOCITY from TRAJ --- src/emc/ini/update_ini.py | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/src/emc/ini/update_ini.py b/src/emc/ini/update_ini.py index 50e8f4ce110..248c0c82994 100755 --- a/src/emc/ini/update_ini.py +++ b/src/emc/ini/update_ini.py @@ -40,6 +40,11 @@ def insert_after(key, new_line, section): new_line += "\n" return section[:line_end + 1] + new_line + section[line_end + 1:] +def find_section(section, inistring): + section = re.search(r"(?:^|\n)[ \t]*(?!#)\[{}\](.+?\n)(?=\[|$)".format(section), inistring, re.DOTALL) + if section: section = section.group(1) + return section + force = 0 dialogs = 0 subs = {} @@ -446,9 +451,7 @@ def ini_preamble(): inistring, newini, all_sections = ini_preamble() all_sections.remove("DISPLAY") - section = re.search(r"(?:^|\n)[ \t]*(?!#)\[DISPLAY\](.+?\n)(?=\[|$)", inistring, re.DOTALL) - - if section: section = section.group(1) + section = find_section("DISPLAY", inistring) newini.write("\n[DISPLAY]") if section != None: if re.search("MIN_SPINDLE_OVERRIDE", section): @@ -463,8 +466,6 @@ def ini_preamble(): section = re.sub("MAX_SPINDLE_SPEED", "MAX_SPINDLE_0_SPEED", section) if re.search("MIN_VELOCITY", section): section = re.sub("MIN_VELOCITY", "MIN_LINEAR_VELOCITY", section) - - # Copy values from TRAJ if not re.search("DEFAULT_LINEAR_VELOCITY", section): val = ini.find("TRAJ", "DEFAULT_LINEAR_VELOCITY") @@ -472,13 +473,14 @@ def ini_preamble(): section = insert_after("MAX_LINEAR_VELOCITY", f"DEFAULT_LINEAR_VELOCITY = {val}\n" , section) if not re.search("MIN_LINEAR_VELOCITY", section): val = ini.find("TRAJ", "MIN_LINEAR_VELOCITY") + if val is None: + val = ini.find("TRAJ", "MIN_VELOCITY") if val: section = insert_after("MAX_LINEAR_VELOCITY", f"MIN_LINEAR_VELOCITY = {val}\n" , section) if not re.search("MAX_LINEAR_VELOCITY", section): val = ini.find("TRAJ", "MAX_LINEAR_VELOCITY") if val: section = insert_after("MIN_LINEAR_VELOCITY", f"MAX_LINEAR_VELOCITY = {val}\n" , section) - newini.write(section) # TODO update-ini 1.1 --> 1.2: @@ -503,10 +505,17 @@ def ini_preamble(): copysection("TASK") copysection("HAL") copysection("HALUI") - copysection("TRAJ") - copysection("EMCIO") - - # If there were any custom sections, tag them on the end. + # copysection("TRAJ") + all_sections.remove("TRAJ") + section = find_section("TRAJ", inistring) + if re.search("MIN_LINEAR_VELOCITY", section): + section = re.sub("MIN_LINEAR_VELOCITY.*\n?", "# moved MIN_LINEAR_VELOCITY to [DISPLAY]\n", section) + if re.search("MIN_VELOCITY", section): + section = re.sub("MIN_VELOCITY.*\n?", "# moved MIN_VELOCITY to DISPLAY]MIN_LINEAR_VELOCITY\n", section) + newini.write("\n[TRAJ]") + newini.write(section) + + # Copy the remaining sections while all_sections: copysection(all_sections[0]) From 0c7a3c3458686eaf3b99ff97f745517f43f37051 Mon Sep 17 00:00:00 2001 From: Hans Unzner Date: Wed, 11 Feb 2026 01:58:45 +0100 Subject: [PATCH 15/24] update_ini: fix \n to work also from upgrading <1.0 --- src/emc/ini/update_ini.py | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/src/emc/ini/update_ini.py b/src/emc/ini/update_ini.py index 248c0c82994..9ec1eadbfa3 100755 --- a/src/emc/ini/update_ini.py +++ b/src/emc/ini/update_ini.py @@ -14,9 +14,9 @@ def copysection(block): #Just makes a straight copy of blocks that don't need any work - regex = r"^\s*\[%s\](\n(?:^(?!\[).*\n?)*)" % block + regex = r"^\s*\[%s\](\n(?:^(?!\[).*(?:\n(?=^(?!\[))|$))*)" % block section = re.search(regex, inistring, re.M) - newini.write("[%s]" % block) + newini.write("\n[%s]" % block) if section is not None: newini.write(section.group(1)) all_sections.remove(block) @@ -41,7 +41,7 @@ def insert_after(key, new_line, section): return section[:line_end + 1] + new_line + section[line_end + 1:] def find_section(section, inistring): - section = re.search(r"(?:^|\n)[ \t]*(?!#)\[{}\](.+?\n)(?=\[|$)".format(section), inistring, re.DOTALL) + section = re.search(r"^\s*\[%s\](\n(?:^(?!\[).*(?:\n(?=^(?!\[))|$))*)" % section, inistring, re.M) if section: section = section.group(1) return section @@ -190,7 +190,7 @@ def find_section(section, inistring): ############ Convert INI files ############ ########################################### -def ini_preamble(): +def ini_preamble(version): """ The part which is equal for the conversions up from version 1.1 """ @@ -220,26 +220,18 @@ def ini_preamble(): newini.write("[EMC]") if section != None: if version != "0.0": - section = re.sub("VERSION (.+)", "VERSION = %s" % THIS_VERSION, section) + section = re.sub("VERSION (.+)", "VERSION = %s" % version, section) else: newini.write("# The version string for this INI file.\n") - newini.write("VERSION = %s\n" % THIS_VERSION) + newini.write("VERSION = %s\n" % version) newini.write(section) else: - newini.write("VERSION = %s\n" % THIS_VERSION) + newini.write("VERSION = %s\n" % version) return inistring, newini, all_sections -if version == "1.0": - #Just update the version in the INI - inistring = open(filename,'r').read() - newini = open(filename, 'w') - inistring = re.sub("VERSION *= *(.*)", "VERSION = %s" % THIS_VERSION, inistring) - newini.write(inistring) - newini.close() - if version == "$Revision$" or version < "1.0": - inistring, newini, all_sections = ini_preamble() + inistring, newini, all_sections = ini_preamble("1.0") #These sections don't need any work. copysection("DISPLAY") copysection("FILTER") @@ -447,8 +439,16 @@ def ini_preamble(): #That's the INI file done: newini.close() +if version == "1.0": + #Just update the version in the INI + inistring = open(filename,'r').read() + newini = open(filename, 'w') + inistring = re.sub("VERSION *= *(.*)", "VERSION = 1.1", inistring) + newini.write(inistring) + newini.close() + if version < "1.2": - inistring, newini, all_sections = ini_preamble() + inistring, newini, all_sections = ini_preamble("1.2") all_sections.remove("DISPLAY") section = find_section("DISPLAY", inistring) From d9bc65b76e6546ce19697de64badd7dec6f342c4 Mon Sep 17 00:00:00 2001 From: Hans Unzner Date: Wed, 11 Feb 2026 02:25:38 +0100 Subject: [PATCH 16/24] update_ini: show info for each version step in one message box --- src/emc/ini/update_ini.py | 51 ++++++++++++++++++++++++++------------- 1 file changed, 34 insertions(+), 17 deletions(-) diff --git a/src/emc/ini/update_ini.py b/src/emc/ini/update_ini.py index 9ec1eadbfa3..0fb621f2544 100755 --- a/src/emc/ini/update_ini.py +++ b/src/emc/ini/update_ini.py @@ -108,23 +108,40 @@ def find_section(section, inistring): # Show start message with abort option if dialogs: - ret = '' - if version == "1.0": - ret = messagebox._show("Confirm automatic update", - "This version of LinuxCNC separates the concepts of Axes and " - "Joints which necessitates changes to the INI and HAL files. " - "The changes required are described here:\n" - "http://linuxcnc.org/docs/2.9/html/ in the section " - "'Getting Started with LinuxCNC' -> 'Updating LinuxCNC'\n" - "The [EMC]VERSION data in your INI file indicates that your " - "configuration requires update.\n" - "A script exists that can attempt to automatically " - "reconfigure your configuration files.\nPress 'Yes' to perform " - "the conversion, 'No' to continue with the current configuration " - "files or 'Cancel' to exit LinuxCNC.\n" - "The process can not be automatically reversed, though a " - "backup version of your entire existing config will be created.", - messagebox.QUESTION, messagebox.YESNOCANCEL) + message = "" + if version == "$Revision$" or version < "1.0": + message += "LinuxCNC 2.8: This version of LinuxCNC separates the concepts of Axes and "\ + "Joints which necessitates changes to the INI and HAL files. "\ + "The changes required are described here:\n"\ + "http://linuxcnc.org/docs/2.8/html/ in the section "\ + "'Getting Started with LinuxCNC' -> 'Updating LinuxCNC'\n\n" + + if version < "1.1": + message += "LinuxCNC 2.9: This version of LinuxCNC adds support for multiple spindles "\ + "which necessitates changes to the HAL files. "\ + "The changes required are described here:\n"\ + "http://linuxcnc.org/docs/2.9/html/ in the section "\ + "'Getting Started with LinuxCNC' -> 'Updating LinuxCNC'\n\n" + + if version < "1.2": + message += "LinuxCNC 2.10: In this version of LinuxCNC some names in "\ + "the configuration files have changed "\ + "which necessitates changes to the INI files. "\ + "The changes required are described here:\n"\ + "http://linuxcnc.org/docs/2.10/html/ in the section "\ + "'Getting Started with LinuxCNC' -> 'Updating LinuxCNC'\n\n" + + message += "The [EMC]VERSION data in your INI file indicates that your "\ + "configuration requires update.\n"\ + "A script exists that can attempt to automatically "\ + "reconfigure your configuration files.\nPress 'Yes' to perform "\ + "the conversion, 'No' to continue with the current configuration "\ + "files or 'Cancel' to exit LinuxCNC.\n"\ + "The process can not be automatically reversed, though a "\ + "backup version of your entire existing config will be created." + + ret = messagebox._show("Confirm automatic update", message, + messagebox.QUESTION, messagebox.YESNOCANCEL) if ret == 'cancel': exit(42) elif ret == 'no': exit(0) From d8d590419fd66c0e2f474fb4f41aa1e12e25f250 Mon Sep 17 00:00:00 2001 From: Hans Unzner Date: Wed, 11 Feb 2026 09:38:07 +0100 Subject: [PATCH 17/24] update_ini: remove warning if no changes in HAL files --- src/emc/ini/update_ini.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/emc/ini/update_ini.py b/src/emc/ini/update_ini.py index 0fb621f2544..dc5302fe830 100755 --- a/src/emc/ini/update_ini.py +++ b/src/emc/ini/update_ini.py @@ -675,10 +675,7 @@ def ini_preamble(version): 'halui.spindle.override.value' : 'halui.spindle.0.override.value' }) -if subs == {}: - print("""This file does not need converting, and furthermore execution - should never have reached this spot""") -else: +if subs: for halfile in halpaths: halstring = open(halfile,'r').read() for sub in subs: From 1928c17ccc8ff84941fd620a06e405b4ab2d61c4 Mon Sep 17 00:00:00 2001 From: Hans Unzner Date: Wed, 11 Feb 2026 09:52:19 +0100 Subject: [PATCH 18/24] docs: update "updating to 2.10" --- .../getting-started/updating-linuxcnc.adoc | 31 ++++++++++++++++--- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/docs/src/getting-started/updating-linuxcnc.adoc b/docs/src/getting-started/updating-linuxcnc.adoc index 006f8f233ea..40766c3e04c 100644 --- a/docs/src/getting-started/updating-linuxcnc.adoc +++ b/docs/src/getting-started/updating-linuxcnc.adoc @@ -218,11 +218,34 @@ HOME_SEARCH_VELOCITY = 100 - Accepted but currently does nothing HOME_SEQUENCE = 0 - Accepted but currently does nothing -== Updating Configuration Files for 2.10.y +== Updating Configuration Files for 2.10 -Touchy: the Touchy MACRO entries should now be placed in a [MACROS] -section of the INI rather than in the [TOUCHY] section. This is part of -a process of commonising the INI setting between GUIs. + +=== Spindle names + +Some names in the [DISPLAY] section of the INI file have changed: + +- `MIN_SPINDLE_OVERRIDE -> MIN_SPINDLE_0_OVERRIDE` +- `MAX_SPINDLE_OVERRIDE -> MAX_SPINDLE_0_OVERRIDE` +- `DEFAULT_SPINDLE_SPEED -> DEFAULT_SPINDLE_0_SPEED` +- `MIN_SPINDLE_SPEED -> MIN_SPINDLE_0_SPEED` +- `MAX_SPINDLE_SPEED -> MAX_SPINDLE_0_SPEED` + +=== Gmoccapy + +- The spindle settings are now defined in the INI-file instead of the gmoccapy preferences: +[source,{ini}] +---- +[DISPLAY] +DEFAULT_SPINDLE_0_SPEED = 450 +MIN_SPINDLE_0_SPEED = 0 +MAX_SPINDLE_0_SPEED = 3000 +---- + +==== Touchy + +The Touchy MACRO entries should now be placed in a [MACROS] +section of the INI rather than in the [TOUCHY] section. This is part of a process of commonising the INI setting between GUIs. == New HAL components From 7e24a9168de80e301f8c70eee7f2d35f7fa5ce02 Mon Sep 17 00:00:00 2001 From: Hans Unzner Date: Wed, 10 Jun 2026 23:29:20 +0200 Subject: [PATCH 19/24] update_ini: get the included files in the INI file --- src/emc/ini/update_ini.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/emc/ini/update_ini.py b/src/emc/ini/update_ini.py index dc5302fe830..62fe0e814e6 100755 --- a/src/emc/ini/update_ini.py +++ b/src/emc/ini/update_ini.py @@ -81,6 +81,18 @@ def find_section(section, inistring): # We want to work with the base INI file here, not the expanded version if #include is used filename = re.sub(r'\.expanded', '', filename) +# Search for included files +base_dir = os.path.dirname(filename) +included_files = [] +# included_files.append(filename) +pattern = re.compile(r"^#INCLUDE[ \t]+(\S+)") +with open(filename, "r", encoding="utf-8") as f: + for line in f: + match = pattern.match(line.strip()) + if match: + file = os.path.join(base_dir, match.group(1)) + included_files.append(file) + try: ini = linuxcnc.ini(filename) except: From 01b9084f18f2ae212e50645f0a2463dcf899ff1c Mon Sep 17 00:00:00 2001 From: Hans Unzner Date: Thu, 11 Jun 2026 10:10:15 +0200 Subject: [PATCH 20/24] update_ini -includes: going through all included --- src/emc/ini/update_ini.py | 623 ++++++++++++++++++++------------------ 1 file changed, 325 insertions(+), 298 deletions(-) diff --git a/src/emc/ini/update_ini.py b/src/emc/ini/update_ini.py index 62fe0e814e6..099473e38ef 100755 --- a/src/emc/ini/update_ini.py +++ b/src/emc/ini/update_ini.py @@ -84,14 +84,14 @@ def find_section(section, inistring): # Search for included files base_dir = os.path.dirname(filename) included_files = [] -# included_files.append(filename) +included_files.append(filename) pattern = re.compile(r"^#INCLUDE[ \t]+(\S+)") with open(filename, "r", encoding="utf-8") as f: for line in f: match = pattern.match(line.strip()) if match: - file = os.path.join(base_dir, match.group(1)) - included_files.append(file) + included_file = os.path.join(base_dir, match.group(1)) + included_files.append(included_file) try: ini = linuxcnc.ini(filename) @@ -219,12 +219,12 @@ def find_section(section, inistring): ############ Convert INI files ############ ########################################### -def ini_preamble(version): +def ini_preamble(version, file): """ The part which is equal for the conversions up from version 1.1 """ - inistring = open(filename,'r').read() - newini = open(filename, 'w') + inistring = open(file,'r').read() + newini = open(file, 'w') # Get a list of all sections all_sections = re.findall(r"^\s*\[(.+)\]", inistring, re.MULTILINE) @@ -243,313 +243,339 @@ def ini_preamble(version): newini.write(section.group(1)) #[EMC] Section, change the version number - all_sections.remove("EMC") - section = re.search(r"\[EMC\](.+?)\n\[", inistring, re.DOTALL) - if section: section = section.group(1) - newini.write("[EMC]") - if section != None: - if version != "0.0": - section = re.sub("VERSION (.+)", "VERSION = %s" % version, section) + try: + all_sections.remove("EMC") + section = re.search(r"\[EMC\](.+?)\n\[", inistring, re.DOTALL) + if section: section = section.group(1) + newini.write("[EMC]") + if section != None: + if version != "0.0": + section = re.sub("VERSION (.+)", "VERSION = %s" % version, section) + else: + newini.write("# The version string for this INI file.\n") + newini.write("VERSION = %s\n" % version) + newini.write(section) else: - newini.write("# The version string for this INI file.\n") newini.write("VERSION = %s\n" % version) - newini.write(section) - else: - newini.write("VERSION = %s\n" % version) + except: + pass return inistring, newini, all_sections -if version == "$Revision$" or version < "1.0": - inistring, newini, all_sections = ini_preamble("1.0") - #These sections don't need any work. - copysection("DISPLAY") - copysection("FILTER") - - #[RS274NGC] Section, change FEATURES to separate entries - all_sections.remove("RS274NGC") - section = re.search(r"\[RS274NGC\](.+?)\n\[", inistring, re.DOTALL) - if section: section = section.group(1) - newini.write("\n[RS274NGC]\n") - if section != None: - features = ini.find('RS274NGC', 'FEATURES') - if features != None: - features = int(features) - section = re.sub("FEATURES.*?\n", "", section) - section += ("RETAIN_G43 = %s\n" % ("1" if features & 0x1 else "0")) - section += ("INI_VARS = %s\n" % ("1" if features & 0x4 else "0")) - section += ("HAL_PIN_VARS = %s\n" % ("1" if features & 0x8 else "0")) - if features & 0x2: section += ("OWORD_NARGS = 1\n" ) - if features & 0x10: section += ("NO_DOWNCASE_OWORD = 1\n" ) - if features & 0x20: section += ("OWORD_WARNONLY = 1\n" ) - section += "\n" - newini.write(section) - - all_sections.remove("EMCMOT") - section = re.search(r"\[EMCMOT\](.+?)\n\[", inistring, re.DOTALL) - if section: section = section.group(1) - newini.write("[EMCMOT]\n") - section = re.sub("# Interval between tries to emcmot.*?\n", "", section) - section = re.sub("COMM_WAIT.*?\n", "", section) - newini.write(section) - - copysection("TASK") - copysection("HAL") - copysection("HALUI") - - # We need info from TRAJ to get KINS right - - joints = ini.find("TRAJ", "JOINTS") - coordinates = ini.find("TRAJ", "COORDINATES").replace(" ","") - if coordinates != None: joints = len(coordinates) - if joints == None: joints = ini.find("TRAJ", "AXES") - if joints == None: joints = "3" - joints = int(joints) - if coordinates == None: coordinates = "XYZABCUVW" - - coordinates = list(coordinates) - - # Search the Halfiles to find the kinematics. - kins = None - kinstype = None - coords_entry = False - if coordinates != "XYZABCUVW"[:joints]: coords_entry = True - for halfile in halpaths: - hal = open(os.path.join(os.path.dirname(filename), halfile), 'r') - for line in hal.readlines(): - match = re.match(r'(?:#autoconverted|loadrt) +(\w+kins)', line) - if match: - kins = match.group(1) - match = re.search(r'coordinates *= *(\w+)', line) - if match: - coordinates = list(match.group(1)) - coords_entry = 1 - match = re.search(r'kinstype *= *(\w+)', line) - if kinstype: kinstype = match.group(1) - break - if kins: break - if not kins: kins = "trivkins" - - #gantrykins and gentrivkins are gone, so need special treatment - - if kins == "gantrykins": - kins = "trivkins" - kinstype = "BOTH" - coords_entry = True +for current_file in included_files: + print(f'===> Updating "{current_file}"...') + if version == "$Revision$" or version < "1.0": + print('version == "$Revision$" or version < "1.0"') + inistring, newini, all_sections = ini_preamble("1.0", current_file) + #These sections don't need any work. + copysection("DISPLAY") + copysection("FILTER") + + #[RS274NGC] Section, change FEATURES to separate entries + try: + all_sections.remove("RS274NGC") + section = re.search(r"\[RS274NGC\](.+?)\n\[", inistring, re.DOTALL) + if section: section = section.group(1) + newini.write("\n[RS274NGC]\n") + if section != None: + features = ini.find('RS274NGC', 'FEATURES') + if features != None: + features = int(features) + section = re.sub("FEATURES.*?\n", "", section) + section += ("RETAIN_G43 = %s\n" % ("1" if features & 0x1 else "0")) + section += ("INI_VARS = %s\n" % ("1" if features & 0x4 else "0")) + section += ("HAL_PIN_VARS = %s\n" % ("1" if features & 0x8 else "0")) + if features & 0x2: section += ("OWORD_NARGS = 1\n" ) + if features & 0x10: section += ("NO_DOWNCASE_OWORD = 1\n" ) + if features & 0x20: section += ("OWORD_WARNONLY = 1\n" ) + section += "\n" + newini.write(section) + except: + pass + + try: + all_sections.remove("EMCMOT") + section = re.search(r"\[EMCMOT\](.+?)\n\[", inistring, re.DOTALL) + if section: section = section.group(1) + newini.write("[EMCMOT]\n") + section = re.sub("# Interval between tries to emcmot.*?\n", "", section) + section = re.sub("COMM_WAIT.*?\n", "", section) + newini.write(section) + except: + pass + + copysection("TASK") + copysection("HAL") + copysection("HALUI") + + # We need info from TRAJ to get KINS right + + joints = ini.find("TRAJ", "JOINTS") + coordinates = ini.find("TRAJ", "COORDINATES").replace(" ","") + if coordinates != None: joints = len(coordinates) + if joints == None: joints = ini.find("TRAJ", "AXES") + if joints == None: joints = "3" + joints = int(joints) + if coordinates == None: coordinates = "XYZABCUVW" + + coordinates = list(coordinates) + + # Search the Halfiles to find the kinematics. + kins = None + kinstype = None + coords_entry = False + if coordinates != "XYZABCUVW"[:joints]: coords_entry = True for halfile in halpaths: hal = open(os.path.join(os.path.dirname(filename), halfile), 'r') for line in hal.readlines(): - match = re.match(r'setp +gantrykins.joint-(\d) +(\d)', line) + match = re.match(r'(?:#autoconverted|loadrt) +(\w+kins)', line) if match: - j = int(match.group(1)) - if j > joints: joints = j - a = int(match.group(2)) - coordinates[j] = 'XYZABCUVW'[a] - - if kins == "gentrivkins": - kins = "trivkins" #trivkins has the same defaults as gentrivkins - - # In JA [TRAJ] expects MAX_LINEAR_VELOCITY not MAX_VELOCITY - all_sections.remove("TRAJ") - section = re.search(r"\[TRAJ\](.+?)\n\[", inistring, re.DOTALL) - if section: section = section.group(1) - newini.write("\n[TRAJ]\n") - if section != None: - if not re.search("MAX_LINEAR_VELOCITY", section): - if re.search("MAX_VELOCITY", section): - section = re.sub("MAX_VELOCITY", "MAX_LINEAR_VELOCITY", section) - else: - mv = re.findall(r"MAX_VELOCITY[\s=]+(\d*(\.\d+)?)", inistring, re.MULTILINE) - section = ("\n# this value based on fastest single axis" + - "\nMAX_LINEAR_VELOCITY = %s" % max(mv)[0] + section) - if not re.search("DEFAULT_LINEAR_VELOCITY", section): - section = re.sub("DEFAULT_VELOCITY", "DEFAULT_LINEAR_VELOCITY", section) - if not re.search("MAX_LINEAR_ACCELERATION", section): - section = re.sub("MAX_ACCELERATION", "MAX_LINEAR_ACCELERATION", section) - if not re.search("DEFAULT_ACCELERATION", section): - section = re.sub("DEFAULT_ACCELERATION", "DEFAULT_LINEAR_ACCELERATION", section) - print("COORDINATES = %s\n" % ''.join(coordinates)) - section = re.sub("COORDINATES.*", "COORDINATES = %s" % ''.join(coordinates[: joints]), section) - section = re.sub("CYCLE_TIME.*?\n", "", section) - section = re.sub("AXES *=.*\n", "", section) - newini.write(section) - - copysection("EMCIO") - - # Insert the new-fangled [KINS] section - - newini.write("\n\n[KINS]\n") - newini.write("KINEMATICS = %s" % kins) - if coords_entry: newini.write(" coordinates=%s" % ''.join(coordinates[: joints])) - if kinstype: newini.write(" kinstype=%s" % kinstype) - newini.write("\n") - newini.write("#This is a best-guess at the number of joints, it should be checked\n") - newini.write("JOINTS = %i\n" % joints) - - j = 0 - lock_mask = 0x0 - L2J={} - while 1: - # Search preferentially in "[JOINT_N] in case the file is part-converted already - if re.search(r"^(\[JOINT_%i\])"%j, inistring, re.MULTILINE): - if re.search(r"^(\[AXIS_%s\])" % "XYZABCUVW"[j], inistring, re.MULTILINE): - copysection("AXIS_%s" % "XYZABCUVW"[j]) - # copysection("JOINT_%i" % j) - elif j < len(coordinates): - newini.write("\n[AXIS_%s]\n" % coordinates[j]) - writeifexists(newini, "JOINT_%i" % j, "HOME") - writeifexists(newini, "JOINT_%i" % j, "MIN_LIMIT") - writeifexists(newini, "JOINT_%i" % j, "MAX_LIMIT") - writeifexists(newini, "JOINT_%i" % j, "MAX_VELOCITY") - writeifexists(newini, "JOINT_%i" % j, "MAX_ACCELERATION") - copysection("[JOINT_%i]" % j) - elif j < len(coordinates): - # in this "elif" j is an index in to coordinates. - if coordinates[j] in L2J: # duplicate axis letter - L2J[coordinates[j]].append(j) # = [L2J[coordinates[j]], j] - else: - L2J.update({coordinates[j] : [j]}) - elif j >= 9: - break - else: + kins = match.group(1) + match = re.search(r'coordinates *= *(\w+)', line) + if match: + coordinates = list(match.group(1)) + coords_entry = 1 + match = re.search(r'kinstype *= *(\w+)', line) + if kinstype: kinstype = match.group(1) + break + if kins: break + if not kins: kins = "trivkins" + + #gantrykins and gentrivkins are gone, so need special treatment + + if kins == "gantrykins": + kins = "trivkins" + kinstype = "BOTH" + coords_entry = True + for halfile in halpaths: + hal = open(os.path.join(os.path.dirname(filename), halfile), 'r') + for line in hal.readlines(): + match = re.match(r'setp +gantrykins.joint-(\d) +(\d)', line) + if match: + j = int(match.group(1)) + if j > joints: joints = j + a = int(match.group(2)) + coordinates[j] = 'XYZABCUVW'[a] + + if kins == "gentrivkins": + kins = "trivkins" #trivkins has the same defaults as gentrivkins + + try: + # In JA [TRAJ] expects MAX_LINEAR_VELOCITY not MAX_VELOCITY + all_sections.remove("TRAJ") + section = re.search(r"\[TRAJ\](.+?)\n\[", inistring, re.DOTALL) + if section: section = section.group(1) + newini.write("\n[TRAJ]\n") + if section != None: + if not re.search("MAX_LINEAR_VELOCITY", section): + if re.search("MAX_VELOCITY", section): + section = re.sub("MAX_VELOCITY", "MAX_LINEAR_VELOCITY", section) + else: + mv = re.findall(r"MAX_VELOCITY[\s=]+(\d*(\.\d+)?)", inistring, re.MULTILINE) + section = ("\n# this value based on fastest single axis" + + "\nMAX_LINEAR_VELOCITY = %s" % max(mv)[0] + section) + if not re.search("DEFAULT_LINEAR_VELOCITY", section): + section = re.sub("DEFAULT_VELOCITY", "DEFAULT_LINEAR_VELOCITY", section) + if not re.search("MAX_LINEAR_ACCELERATION", section): + section = re.sub("MAX_ACCELERATION", "MAX_LINEAR_ACCELERATION", section) + if not re.search("DEFAULT_ACCELERATION", section): + section = re.sub("DEFAULT_ACCELERATION", "DEFAULT_LINEAR_ACCELERATION", section) + print("COORDINATES = %s\n" % ''.join(coordinates)) + section = re.sub("COORDINATES.*", "COORDINATES = %s" % ''.join(coordinates[: joints]), section) + section = re.sub("CYCLE_TIME.*?\n", "", section) + section = re.sub("AXES *=.*\n", "", section) + newini.write(section) + except: pass - j += 1 - - for L in list("XYZABCUVW"): - if L in L2J: - axisnum = "XYZABCUVW".index(L) - newini.write("\n[AXIS_%s]\n" % L) - writeifexists(newini, "AXIS_%i" % axisnum, "MIN_LIMIT") - writeifexists(newini, "AXIS_%i" % axisnum, "MAX_LIMIT") - writeifexists(newini, "AXIS_%i" % axisnum, "MAX_VELOCITY") - writeifexists(newini, "AXIS_%i" % axisnum, "MAX_ACCELERATION") - if ini.find("AXIS_%i" % j, "LOCKING_INDEXER"): - lock_mask |= 1 << j - newini.write("LOCKING_INDEXER_JOINT = %i\n" % j) - - hs = ini.find("AXIS_%i" % axisnum, "HOME_SEQUENCE") - if hs == "-1" or hs == None: # -1 used to exclude a joint now we use no entry - sequence = "" - elif len(L2J[L]) > 1: # tandem axis - sequence = "HOME_SEQUENCE = -%s" % hs - else: - sequence = "HOME_SEQUENCE = %s" % hs - for J in L2J[L]: - # Take the coordinates index as the JOINT_Number - newini.write("\n[JOINT_%i]" % J) - section = re.search(r"\[AXIS_%i\](.+?)(\n\[|$)" % J, inistring, re.DOTALL) - if not section: - section = re.search(r"\[AXIS_%i\](.+?)(\n\[|$)" % "XYZABCUVW".index(coordinates[J]), inistring, re.DOTALL) - if section: - section = re.sub("HOME_SEQUENCE.*", sequence, section.group(1)) - newini.write(section) - if not r'\[AXIS_%i\]' % axisnum in subs: - subs.update({r'\[AXIS_%i\]' % axisnum : '[JOINT_%i]' % J}) - subs2.update({r'joint\.%i\.' % axisnum : 'joint.%i.' % J}) + copysection("EMCIO") + + # Insert the new-fangled [KINS] section + newini.write("\n\n[KINS]\n") + newini.write("KINEMATICS = %s" % kins) + if coords_entry: newini.write(" coordinates=%s" % ''.join(coordinates[: joints])) + if kinstype: newini.write(" kinstype=%s" % kinstype) + newini.write("\n") + newini.write("#This is a best-guess at the number of joints, it should be checked\n") + newini.write("JOINTS = %i\n" % joints) + + j = 0 + lock_mask = 0x0 + # Skip this part if no [JOINT_N] at all + if re.search(r"\[JOINT_\d+\]", inistring, re.DOTALL): + L2J={} + while 1: + # Search preferentially in "[JOINT_N] in case the file is part-converted already + if re.search(r"^(\[JOINT_%i\])"%j, inistring, re.MULTILINE): + if re.search(r"^(\[AXIS_%s\])" % "XYZABCUVW"[j], inistring, re.MULTILINE): + copysection("AXIS_%s" % "XYZABCUVW"[j]) + # copysection("JOINT_%i" % j) + elif j < len(coordinates): + newini.write("\n[AXIS_%s]\n" % coordinates[j]) + writeifexists(newini, "JOINT_%i" % j, "HOME") + writeifexists(newini, "JOINT_%i" % j, "MIN_LIMIT") + writeifexists(newini, "JOINT_%i" % j, "MAX_LIMIT") + writeifexists(newini, "JOINT_%i" % j, "MAX_VELOCITY") + writeifexists(newini, "JOINT_%i" % j, "MAX_ACCELERATION") + copysection("[JOINT_%i]" % j) + elif j < len(coordinates): + # in this "elif" j is an index in to coordinates. + if coordinates[j] in L2J: # duplicate axis letter + L2J[coordinates[j]].append(j) # = [L2J[coordinates[j]], j] else: - subs.update({r'\[AXIS_%i\]' % J : '[JOINT_%i]' % J}) + L2J.update({coordinates[j] : [j]}) + elif j >= 9: + break else: - print("File parsing error, found an [AXIS_%i] section, but no content" % J) - exit() - # We no longer need the [AXIS_N] data - for j in range(0,8): - if ("AXIS_%i" % j) in all_sections: all_sections.remove("AXIS_%i" % j) - - # If there were any custom sections, tag them on the end. - while all_sections: - copysection(all_sections[0]) - - # and turn the locking mask into a string - if lock_mask: - lock_string = 'unlock_joints_mask=%i' % lock_mask - else: - lock_string = "" + pass + + j += 1 + + for L in list("XYZABCUVW"): + if L in L2J: + axisnum = "XYZABCUVW".index(L) + newini.write("\n[AXIS_%s]\n" % L) + writeifexists(newini, "AXIS_%i" % axisnum, "MIN_LIMIT") + writeifexists(newini, "AXIS_%i" % axisnum, "MAX_LIMIT") + writeifexists(newini, "AXIS_%i" % axisnum, "MAX_VELOCITY") + writeifexists(newini, "AXIS_%i" % axisnum, "MAX_ACCELERATION") + + # Search also current file because 'ini' contains all includes + if re.search(r"^(\[AXIS_%s\])" % axisnum, inistring, re.MULTILINE): + + if ini.find("AXIS_%i" % j, "LOCKING_INDEXER"): + lock_mask |= 1 << j + newini.write("LOCKING_INDEXER_JOINT = %i\n" % j) + + hs = ini.find("AXIS_%i" % axisnum, "HOME_SEQUENCE") + if hs == "-1" or hs == None: # -1 used to exclude a joint now we use no entry + sequence = "" + elif len(L2J[L]) > 1: # tandem axis + sequence = "HOME_SEQUENCE = -%s" % hs + else: + sequence = "HOME_SEQUENCE = %s" % hs + for J in L2J[L]: + # Take the coordinates index as the JOINT_Number + newini.write("\n[JOINT_%i]" % J) + section = re.search(r"\[AXIS_%i\](.+?)(\n\[|$)" % J, inistring, re.DOTALL) + if not section: + section = re.search(r"\[AXIS_%i\](.+?)(\n\[|$)" % "XYZABCUVW".index(coordinates[J]), inistring, re.DOTALL) + if section: + section = re.sub("HOME_SEQUENCE.*", sequence, section.group(1)) + newini.write(section) + if not r'\[AXIS_%i\]' % axisnum in subs: + subs.update({r'\[AXIS_%i\]' % axisnum : '[JOINT_%i]' % J}) + subs2.update({r'joint\.%i\.' % axisnum : 'joint.%i.' % J}) + else: + subs.update({r'\[AXIS_%i\]' % J : '[JOINT_%i]' % J}) + else: + print("File parsing error, found an [AXIS_%i] section, but no content" % J) + exit() + # We no longer need the [AXIS_N] data + for j in range(0,8): + if ("AXIS_%i" % j) in all_sections: all_sections.remove("AXIS_%i" % j) + + # If there were any custom sections, tag them on the end. + while all_sections: + copysection(all_sections[0]) + + # and turn the locking mask into a string + if lock_mask: + lock_string = 'unlock_joints_mask=%i' % lock_mask + else: + lock_string = "" - #That's the INI file done: - newini.close() + #That's the INI file done: + newini.close() -if version == "1.0": - #Just update the version in the INI - inistring = open(filename,'r').read() - newini = open(filename, 'w') - inistring = re.sub("VERSION *= *(.*)", "VERSION = 1.1", inistring) - newini.write(inistring) - newini.close() - -if version < "1.2": - inistring, newini, all_sections = ini_preamble("1.2") - - all_sections.remove("DISPLAY") - section = find_section("DISPLAY", inistring) - newini.write("\n[DISPLAY]") - if section != None: - if re.search("MIN_SPINDLE_OVERRIDE", section): - section = re.sub("MIN_SPINDLE_OVERRIDE", "MIN_SPINDLE_0_OVERRIDE", section) - if re.search("MAX_SPINDLE_OVERRIDE", section): - section = re.sub("MAX_SPINDLE_OVERRIDE", "MAX_SPINDLE_0_OVERRIDE", section) - if re.search("DEFAULT_SPINDLE_SPEED", section): - section = re.sub("DEFAULT_SPINDLE_SPEED", "DEFAULT_SPINDLE_0_SPEED", section) - if re.search("MIN_SPINDLE_SPEED", section): - section = re.sub("MIN_SPINDLE_SPEED", "MIN_SPINDLE_0_SPEED", section) - if re.search("MAX_SPINDLE_SPEED", section): - section = re.sub("MAX_SPINDLE_SPEED", "MAX_SPINDLE_0_SPEED", section) - if re.search("MIN_VELOCITY", section): - section = re.sub("MIN_VELOCITY", "MIN_LINEAR_VELOCITY", section) - # Copy values from TRAJ - if not re.search("DEFAULT_LINEAR_VELOCITY", section): - val = ini.find("TRAJ", "DEFAULT_LINEAR_VELOCITY") - if val: - section = insert_after("MAX_LINEAR_VELOCITY", f"DEFAULT_LINEAR_VELOCITY = {val}\n" , section) - if not re.search("MIN_LINEAR_VELOCITY", section): - val = ini.find("TRAJ", "MIN_LINEAR_VELOCITY") - if val is None: - val = ini.find("TRAJ", "MIN_VELOCITY") - if val: - section = insert_after("MAX_LINEAR_VELOCITY", f"MIN_LINEAR_VELOCITY = {val}\n" , section) - if not re.search("MAX_LINEAR_VELOCITY", section): - val = ini.find("TRAJ", "MAX_LINEAR_VELOCITY") - if val: - section = insert_after("MIN_LINEAR_VELOCITY", f"MAX_LINEAR_VELOCITY = {val}\n" , section) - newini.write(section) - - # TODO update-ini 1.1 --> 1.2: - # - # [DISPLAY] - # MIN_SPINDLE_OVERRIDE -> MIN_SPINDLE_0_OVERRIDE - # MAX_SPINDLE_OVERRIDE -> MAX_SPINDLE_0_OVERRIDE - # DEFAULT_SPINDLE_SPEED -> DEFAULT_SPINDLE_0_SPEED - # MIN_SPINDLE_SPEED -> MIN_SPINDLE_0_SPEED - # MAX_SPINDLE_SPEED -> MAX_SPINDLE_0_SPEED - # - # copy [TRAJ]DEFAULT_LINEAR_VELOCITY -> [DISPLAY]DEFAULT_LINEAR_VELOCITY - # move [TRAJ]MIN_LINEAR_VELOCITY -> [DISPLAY]MIN_LINEAR_VELOCITY - # ~rename [TRAJ, DISPLAY]MIN_VELOCITY --> MIN_LINEAR_VELOCITY~ - # copy [TRAJ]MAX_LINEAR_VELOCITY -> [DISPLAY]MAX_LINEAR_VELOCITY - - #These sections don't need any work. - copysection("FILTER") - copysection("RS274NGC") - copysection("PYTHON") - copysection("EMCMOT") - copysection("TASK") - copysection("HAL") - copysection("HALUI") - # copysection("TRAJ") - all_sections.remove("TRAJ") - section = find_section("TRAJ", inistring) - if re.search("MIN_LINEAR_VELOCITY", section): - section = re.sub("MIN_LINEAR_VELOCITY.*\n?", "# moved MIN_LINEAR_VELOCITY to [DISPLAY]\n", section) - if re.search("MIN_VELOCITY", section): - section = re.sub("MIN_VELOCITY.*\n?", "# moved MIN_VELOCITY to DISPLAY]MIN_LINEAR_VELOCITY\n", section) - newini.write("\n[TRAJ]") - newini.write(section) - - # Copy the remaining sections - while all_sections: - copysection(all_sections[0]) - - #That's the INI file done: - newini.close() + if version == "1.0": + print("version == 1.0") + #Just update the version in the INI + inistring = open(current_file,'r').read() + newini = open(current_file, 'w') + inistring = re.sub("VERSION *= *(.*)", "VERSION = 1.1", inistring) + newini.write(inistring) + newini.close() + + if version < "1.2": + print("version < 1.2") + inistring, newini, all_sections = ini_preamble("1.2", current_file) + + try: + all_sections.remove("DISPLAY") + section = find_section("DISPLAY", inistring) + newini.write("\n[DISPLAY]") + if section != None: + if re.search("MIN_SPINDLE_OVERRIDE", section): + section = re.sub("MIN_SPINDLE_OVERRIDE", "MIN_SPINDLE_0_OVERRIDE", section) + if re.search("MAX_SPINDLE_OVERRIDE", section): + section = re.sub("MAX_SPINDLE_OVERRIDE", "MAX_SPINDLE_0_OVERRIDE", section) + if re.search("DEFAULT_SPINDLE_SPEED", section): + section = re.sub("DEFAULT_SPINDLE_SPEED", "DEFAULT_SPINDLE_0_SPEED", section) + if re.search("MIN_SPINDLE_SPEED", section): + section = re.sub("MIN_SPINDLE_SPEED", "MIN_SPINDLE_0_SPEED", section) + if re.search("MAX_SPINDLE_SPEED", section): + section = re.sub("MAX_SPINDLE_SPEED", "MAX_SPINDLE_0_SPEED", section) + if re.search("MIN_VELOCITY", section): + section = re.sub("MIN_VELOCITY", "MIN_LINEAR_VELOCITY", section) + # Copy values from TRAJ + if not re.search("DEFAULT_LINEAR_VELOCITY", section): + val = ini.find("TRAJ", "DEFAULT_LINEAR_VELOCITY") + if val: + section = insert_after("MAX_LINEAR_VELOCITY", f"DEFAULT_LINEAR_VELOCITY = {val}\n" , section) + if not re.search("MIN_LINEAR_VELOCITY", section): + val = ini.find("TRAJ", "MIN_LINEAR_VELOCITY") + if val is None: + val = ini.find("TRAJ", "MIN_VELOCITY") + if val: + section = insert_after("MAX_LINEAR_VELOCITY", f"MIN_LINEAR_VELOCITY = {val}\n" , section) + if not re.search("MAX_LINEAR_VELOCITY", section): + val = ini.find("TRAJ", "MAX_LINEAR_VELOCITY") + if val: + section = insert_after("MIN_LINEAR_VELOCITY", f"MAX_LINEAR_VELOCITY = {val}\n" , section) + newini.write(section) + except: + pass + + # TODO update-ini 1.1 --> 1.2: + # + # [DISPLAY] + # MIN_SPINDLE_OVERRIDE -> MIN_SPINDLE_0_OVERRIDE + # MAX_SPINDLE_OVERRIDE -> MAX_SPINDLE_0_OVERRIDE + # DEFAULT_SPINDLE_SPEED -> DEFAULT_SPINDLE_0_SPEED + # MIN_SPINDLE_SPEED -> MIN_SPINDLE_0_SPEED + # MAX_SPINDLE_SPEED -> MAX_SPINDLE_0_SPEED + # + # copy [TRAJ]DEFAULT_LINEAR_VELOCITY -> [DISPLAY]DEFAULT_LINEAR_VELOCITY + # move [TRAJ]MIN_LINEAR_VELOCITY -> [DISPLAY]MIN_LINEAR_VELOCITY + # ~rename [TRAJ, DISPLAY]MIN_VELOCITY --> MIN_LINEAR_VELOCITY~ + # copy [TRAJ]MAX_LINEAR_VELOCITY -> [DISPLAY]MAX_LINEAR_VELOCITY + + #These sections don't need any work. + copysection("FILTER") + copysection("RS274NGC") + copysection("PYTHON") + copysection("EMCMOT") + copysection("TASK") + copysection("HAL") + copysection("HALUI") + try: + all_sections.remove("TRAJ") + section = find_section("TRAJ", inistring) + if re.search("MIN_LINEAR_VELOCITY", section): + section = re.sub("MIN_LINEAR_VELOCITY.*\n?", "# moved MIN_LINEAR_VELOCITY to [DISPLAY]\n", section) + if re.search("MIN_VELOCITY", section): + section = re.sub("MIN_VELOCITY.*\n?", "# moved MIN_VELOCITY to DISPLAY]MIN_LINEAR_VELOCITY\n", section) + newini.write("\n[TRAJ]") + newini.write(section) + except: + pass + # Copy the remaining sections + while all_sections: + copysection(all_sections[0]) + + #That's the INI file done: + newini.close() ########################################### @@ -560,6 +586,7 @@ def ini_preamble(version): # but joint-mode jog-enable is not auto-linked for safety. if version == "$Revision$" or version < "1.0": + print('version == "$Revision$" or version < "1.0"') subs.update({'axis.(.).active':'joint.\\1.active', 'axis.(.).amp-enable-out': 'joint.\\1.amp-enable-out', From 4bc0907325bc72edfb90628d75ef7213c5af3544 Mon Sep 17 00:00:00 2001 From: Hans Unzner Date: Sun, 14 Jun 2026 10:16:10 +0200 Subject: [PATCH 21/24] update_ini -includes: Copy section only if exists --- src/emc/ini/update_ini.py | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/src/emc/ini/update_ini.py b/src/emc/ini/update_ini.py index 099473e38ef..aa4835de8a7 100755 --- a/src/emc/ini/update_ini.py +++ b/src/emc/ini/update_ini.py @@ -13,15 +13,17 @@ from tkinter import messagebox def copysection(block): - #Just makes a straight copy of blocks that don't need any work - regex = r"^\s*\[%s\](\n(?:^(?!\[).*(?:\n(?=^(?!\[))|$))*)" % block - section = re.search(regex, inistring, re.M) - newini.write("\n[%s]" % block) - if section is not None: - newini.write(section.group(1)) - all_sections.remove(block) - else: - newini.write("\n#No Content\n\n") + # Copy only if section exists. Needed if splitted into several inc files. + if re.search(r"\[%s\]" % block, inistring, re.DOTALL): + #Just makes a straight copy of blocks that don't need any work + regex = r"^\s*\[%s\](\n(?:^(?!\[).*(?:\n(?=^(?!\[))|$))*)" % block + section = re.search(regex, inistring, re.M) + newini.write("\n[%s]" % block) + if section is not None: + newini.write(section.group(1)) + all_sections.remove(block) + else: + newini.write("\n#No Content\n\n") def writeifexists(file, section, src_item, dest_item = "None"): #Writes a new entry to the file, but only if it exists From 9c4cd69481f89298024c816ccfb7b716e57f53b0 Mon Sep 17 00:00:00 2001 From: Hans Unzner Date: Sun, 14 Jun 2026 15:51:52 +0200 Subject: [PATCH 22/24] update_ini - includes: [EMC] Match also until EOF if INI file is splitted --- src/emc/ini/update_ini.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/emc/ini/update_ini.py b/src/emc/ini/update_ini.py index aa4835de8a7..b5d6e5f0e51 100755 --- a/src/emc/ini/update_ini.py +++ b/src/emc/ini/update_ini.py @@ -240,16 +240,18 @@ def ini_preamble(version, file): newini.write("# The original config files may be found in the %s directory\n\n" % backupdir) # reproduce everything before the first [section] verbatim - section = re.match(r"(.*?)^\[", inistring, re.DOTALL | re.MULTILINE) + section = re.match(r"(.*?)^\[", inistring, re.DOTALL | re.MULTILINE) if section !=None: newini.write(section.group(1)) #[EMC] Section, change the version number try: all_sections.remove("EMC") - section = re.search(r"\[EMC\](.+?)\n\[", inistring, re.DOTALL) - if section: section = section.group(1) + # Match also until EOF if INI file splitted + section = re.search(r"\[EMC\](.+?)(\n\[|\Z)", inistring, re.DOTALL) newini.write("[EMC]") + if section: + section = section.group(1) if section != None: if version != "0.0": section = re.sub("VERSION (.+)", "VERSION = %s" % version, section) From 682590087a379ce5017a14db7fbdfe57ea96aeec Mon Sep 17 00:00:00 2001 From: Hans Unzner Date: Mon, 15 Jun 2026 12:09:45 +0200 Subject: [PATCH 23/24] update_ini: don't handle .ini.expanded - this is not generated any more --- src/emc/ini/update_ini.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/emc/ini/update_ini.py b/src/emc/ini/update_ini.py index b5d6e5f0e51..511f149b4c1 100755 --- a/src/emc/ini/update_ini.py +++ b/src/emc/ini/update_ini.py @@ -80,9 +80,6 @@ def find_section(section, inistring): print(t) exit() -# We want to work with the base INI file here, not the expanded version if #include is used -filename = re.sub(r'\.expanded', '', filename) - # Search for included files base_dir = os.path.dirname(filename) included_files = [] From bc723a5cf4aaaf3ee1598d3b482bc3946429faaa Mon Sep 17 00:00:00 2001 From: Hans Unzner Date: Mon, 15 Jun 2026 12:10:53 +0200 Subject: [PATCH 24/24] update_ini -includes: copy everything from a file also if there is no section at all --- src/emc/ini/update_ini.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/emc/ini/update_ini.py b/src/emc/ini/update_ini.py index 511f149b4c1..ac009627ea3 100755 --- a/src/emc/ini/update_ini.py +++ b/src/emc/ini/update_ini.py @@ -237,7 +237,7 @@ def ini_preamble(version, file): newini.write("# The original config files may be found in the %s directory\n\n" % backupdir) # reproduce everything before the first [section] verbatim - section = re.match(r"(.*?)^\[", inistring, re.DOTALL | re.MULTILINE) + section = re.match(r"(.*?)^(\[|\Z)", inistring, re.DOTALL | re.MULTILINE) if section !=None: newini.write(section.group(1))