update_ini
1 #!/usr/bin/env python 2 3 THIS_VERSION = "1.1" 4 5 import sys 6 import os 7 import shutil 8 import linuxcnc 9 import re 10 import datetime 11 from Tkinter import * 12 import tkMessageBox 13 14 def copysection(block): 15 #Just makes a straight copy of blocks that don't need any work 16 regex = "^\s*\[%s\](.+?)(?:^\s*\[|\Z)" % block 17 section = re.search(regex, inistring, re.M | re.DOTALL) 18 newini.write("\n[%s]" % block) 19 if section != None: 20 newini.write(section.group(1)) 21 all_sections.remove(block) 22 else: 23 newini.write("\n#No Content\n") 24 25 def writeifexists(file, section, src_item, dest_item = "None"): 26 #Writes a new entry to the file, but only if it exists 27 if dest_item == 'None': dest_item = src_item 28 val = ini.find(section, src_item) 29 if val: file.write("%s = %s\n" % (dest_item, val)) 30 31 force = 0 32 dialogs = 0 33 subs = {} 34 subs2 = {} 35 36 filename = None 37 for opt in sys.argv[1:]: 38 if opt == '-d': 39 dialogs = 1 40 r = Tk() 41 r.option_add('*Dialog.msg.font', 'Times 12') 42 r.option_add('*Dialog.msg.wrapLength', '6i') 43 44 elif opt == '-f': 45 force = 1 46 elif opt[0] == '-': 47 print "Unknown command line option to update_ini, exiting" 48 exit() 49 elif os.path.isfile(opt): 50 filename = opt 51 52 if filename == None: 53 t = """Usage: update_ini [-d] [-f] filename.ini\n 54 If the -d flag is used then a dialog box will be displayed 55 describing the purpose of this script, and giving the user the option 56 to change their minds\nIf the -f flag is used then no questions will be 57 asked and the conversion will proceed blindly""" 58 if dialogs: 59 tkMessageBox.showerror('invalid options', str(t)) 60 elif not force: 61 print t 62 exit() 63 64 if dialogs: 65 ret = tkMessageBox._show("Confirm automatic update", 66 "This version of LinuxCNC separates the concepts of Axes and " 67 "Joints which necessitates changes to the INI and HAL files. " 68 "The changes required are described here:\n" 69 "http://linuxcnc.org/docs/devel/html/ in the section " 70 "'Getting Started with LinuxCNC' -> 'Updating LinuxCNC'\n" 71 "The [EMC]VERSION data in your INI file indicates that your " 72 "configuration requires update.\n" 73 "A script exists that can attempt to automatically " 74 "reconfigure your configuration files.\nPress 'Yes' to perform " 75 "the conversion, 'No' to continue with the current configuration " 76 "files or 'Cancel' to exit LinuxCNC.\n" 77 "The process can not be automatically reversed, though a " 78 "backup version of your entire existing config will be created.", 79 tkMessageBox.QUESTION, tkMessageBox.YESNOCANCEL) 80 if ret == 'cancel': exit(42) 81 elif ret == 'no': exit(0) 82 83 # We want to work with the base INI file here, not the expanded version if #include is used 84 filename = re.sub(r'\.expanded', '', filename) 85 86 try: 87 ini = linuxcnc.ini(filename) 88 except: 89 t = "%s is not a valid ini file" % filename 90 if dialogs: 91 tkMessageBox.showerror('invalid options', t) 92 elif not force: 93 print t 94 exit() 95 96 version = ini.find('EMC', 'VERSION') 97 if not version: 98 version = "0.0" 99 100 if version == "$Revision$": 101 pass 102 elif version >= THIS_VERSION: 103 t = """The supplied INI file is already at version %s and should not need 104 updating""" % version 105 if dialogs: 106 tkMessageBox.showerror('conversion not needed', t) 107 elif not force: 108 print t 109 exit() 110 111 if ini.find('KINS', 'JOINTS') and not force and not version == "1.0": 112 if dialogs: 113 if tkMessageBox.askquestion("Already Converted", 114 "The supplied INI file already has a [KINS] section. this probably " 115 "means that it was previously converted by hand. Continue conversion?" 116 "(Change [EMC]VERSION to %s to suppress these messages) " 117 % THIS_VERSION) != 'yes': 118 exit(0) 119 else: 120 if raw_input("The supplied INI file already has a [KINS] section." 121 "this probably means that it was previously converted by hand. " 122 "Continue y/N? (Change [EMC]VERSION to %s to suppress these messages) " 123 % THIS_VERSION) != "y": 124 exit(0) 125 126 # Looks like we are good to go, so first let's put the original configs 127 # somewhere safe. 128 129 basedir = os.path.dirname(os.path.abspath(filename)) 130 backupdir = os.path.join(basedir, os.path.splitext(os.path.basename(filename))[0] + ".old") 131 132 while os.path.isdir(backupdir): 133 backupdir += ".old" 134 os.mkdir(backupdir) 135 old_ini = os.path.join(backupdir, os.path.basename(filename)) 136 for f in os.listdir(basedir): 137 if os.path.isdir(os.path.join(basedir, os.path.basename(f))): 138 pass 139 else: 140 shutil.copy(os.path.join(basedir, os.path.basename(f)), 141 os.path.join(backupdir, os.path.basename(f))) 142 143 #From now on, we use the backup copy as the reference 144 ini = linuxcnc.ini(old_ini) 145 146 #And the hal files too. 147 halfiles = ini.findall('HAL', 'HALFILE') 148 halfiles += ini.findall('HAL', 'POSTGUI_HALFILE') 149 halfiles += ['touchy.hal'] 150 print "halfiles = ", halfiles 151 152 halpaths = [] 153 for halfile in halfiles: 154 if os.path.isfile(os.path.join(basedir, halfile)): 155 halpaths.append(os.path.join(basedir, halfile)) 156 elif (os.path.isfile(os.path.join(basedir, "hallib", halfile))): 157 os.system('cp ' + os.path.join(basedir, "hallib", halfile) + ' ' + 158 os.path.join(basedir, halfile)) 159 halpaths.append(os.path.join(basedir, halfile)) 160 elif halfile == "touchy.hal": 161 pass 162 else: 163 print "halfile %s not found\n" % halfile 164 165 print "halpaths = ", halpaths 166 167 if version == "1.0": 168 #Just update the version in the INI 169 inistring = open(filename,'r').read() 170 newini = open(filename, 'w') 171 inistring = re.sub("VERSION *= *(.*)", "VERSION = %s" % THIS_VERSION, inistring) 172 newini.write(inistring) 173 newini.close() 174 175 if version == "$Revision$" or version < "1.0": 176 177 inistring = open(filename,'r').read() 178 newini = open(filename, 'w') 179 # Get a list of all sections 180 all_sections = re.findall("^\s*\[(.+)\]", inistring, re.MULTILINE) 181 182 # A C-style Switch would be nice here, to allow us to fall through successive 183 # version updates. 184 # At the moment there is only one update, but any future updates should be 185 # a second "if version == 1.0" and so on. The first "if" needs to change the 186 # version string, though. 187 188 newini.write("# This config file was created %s by the update_ini script\n" % datetime.datetime.now()) 189 newini.write("# The original config files may be found in the %s directory\n\n" % backupdir) 190 191 # reproduce everything before the first [section] verbatim 192 section = re.match("(.*?)^\[", inistring, re.DOTALL | re.MULTILINE) 193 if section !=None: 194 newini.write(section.group(1)) 195 196 #[EMC] Section, change the version number 197 all_sections.remove("EMC") 198 section = re.search("\[EMC\](.+?)\n\[", inistring, re.DOTALL) 199 if section: section = section.group(1) 200 newini.write("[EMC]\n") 201 if section != None: 202 if version != "0.0": 203 section = re.sub("VERSION (.+)", "VERSION = %s" % THIS_VERSION, section) 204 else: 205 newini.write("# The version string for this INI file.\n") 206 newini.write("VERSION = %s\n" % THIS_VERSION) 207 newini.write(section) 208 else: 209 newini.write("VERSION = %s\n" % THIS_VERSION) 210 211 #These sections don't need any work. 212 copysection("DISPLAY") 213 copysection("FILTER") 214 copysection("RS274NGC") 215 216 all_sections.remove("EMCMOT") 217 section = re.search("\[EMCMOT\](.+?)\n\[", inistring, re.DOTALL) 218 if section: section = section.group(1) 219 newini.write("[EMCMOT]\n") 220 section = re.sub("# Interval between tries to emcmot.*?\n", "", section) 221 section = re.sub("COMM_WAIT.*?\n", "", section) 222 newini.write(section) 223 224 copysection("TASK") 225 copysection("HAL") 226 copysection("HALUI") 227 228 # We need info from TRAJ to get KINS right 229 230 joints = ini.find("TRAJ", "JOINTS") 231 coordinates = ini.find("TRAJ", "COORDINATES").replace(" ","") 232 if coordinates != None: joints = len(coordinates) 233 if joints == None: joints = ini.find("TRAJ", "AXES") 234 if joints == None: joints = "3" 235 joints = int(joints) 236 if coordinates == None: coordinates = "XYZABCUVW" 237 238 coordinates = list(coordinates) 239 240 # Search the Halfiles to find the kinematics. 241 kins = None 242 kinstype = None 243 coords_entry = False 244 if coordinates != "XYZABCUVW"[:joints]: coords_entry = True 245 for halfile in halpaths: 246 hal = open(os.path.join(os.path.dirname(filename), halfile), 'r') 247 for line in hal.readlines(): 248 match = re.match('(?:#autoconverted|loadrt) +(\w+kins)', line) 249 if match: 250 kins = match.group(1) 251 match = re.search('coordinates *= *(\w+)', line) 252 if match: 253 coordinates = list(match.group(1)) 254 coords_entry = 1 255 match = re.search('kinstype *= *(\w+)', line) 256 if kinstype: kinstype = match.group(1) 257 break 258 if kins: break 259 if not kins: kins = "trivkins" 260 261 #gantrykins and gentrivkins are gone, so need special treatment 262 263 if kins == "gantrykins": 264 kins = "trivkins" 265 kinstype = "BOTH" 266 coords_entry = True 267 for halfile in halpaths: 268 hal = open(os.path.join(os.path.dirname(filename), halfile), 'r') 269 for line in hal.readlines(): 270 match = re.match('setp +gantrykins.joint-(\d) +(\d)', line) 271 if match: 272 j = int(match.group(1)) 273 if j > joints: joints = j 274 a = int(match.group(2)) 275 coordinates[j] = 'XYZABCUVW'[a] 276 277 if kins == "gentrivkins": 278 kins = "trivkins" #trivkins has the same defaults as gentrivkins 279 280 # In JA [TRAJ] expects MAX_LINEAR_VELOCITY not MAX_VELOCITY 281 all_sections.remove("TRAJ") 282 section = re.search("\[TRAJ\](.+?)\n\[", inistring, re.DOTALL) 283 if section: section = section.group(1) 284 newini.write("\n[TRAJ]\n") 285 if section != None: 286 if not re.search("MAX_LINEAR_VELOCITY", section): 287 if re.search("MAX_VELOCITY", section): 288 section = re.sub("MAX_VELOCITY", "MAX_LINEAR_VELOCITY", section) 289 else: 290 mv = re.findall("MAX_VELOCITY[\s=]+(\d*(\.\d+)?)", inistring, re.MULTILINE) 291 section = ("\n# this value based on fastest single axis" + 292 "\nMAX_LINEAR_VELOCITY = %s" % max(mv)[0] + section) 293 if not re.search("DEFAULT_LINEAR_VELOCITY", section): 294 section = re.sub("DEFAULT_VELOCITY", "DEFAULT_LINEAR_VELOCITY", section) 295 if not re.search("MAX_LINEAR_ACCELERATION", section): 296 section = re.sub("MAX_ACCELERATION", "MAX_LINEAR_ACCELERATION", section) 297 if not re.search("DEFAULT_ACCELERATION", section): 298 section = re.sub("DEFAULT_ACCELERATION", "DEFAULT_LINEAR_ACCELERATION", section) 299 print "COORDINATES = %s\n" % ''.join(coordinates) 300 section = re.sub("COORDINATES.*", "COORDINATES = %s" % ''.join(coordinates[: joints]), section) 301 section = re.sub("CYCLE_TIME.*?\n", "", section) 302 section = re.sub("AXES *=.*\n", "", section) 303 newini.write(section) 304 305 copysection("EMCIO") 306 307 # Insert the new-fangled [KINS] section 308 309 newini.write("\n\n[KINS]\n") 310 newini.write("KINEMATICS = %s" % kins) 311 if coords_entry: newini.write(" coordinates=%s" % ''.join(coordinates[: joints])) 312 if kinstype: newini.write(" kinstype=%s" % kinstype) 313 newini.write("\n") 314 newini.write("#This is a best-guess at the number of joints, it should be checked\n") 315 newini.write("JOINTS = %i\n" % joints) 316 317 j = 0 318 lock_mask = 0x0 319 L2J={} 320 while 1: 321 # Search preferentially in "[JOINT_N] in case the file is part-converted already 322 if re.search("^(\[JOINT_%i\])"%j, inistring, re.MULTILINE): 323 if re.search("^(\[AXIS_%s\])" % "XYZABCUVW"[j], inistring, re.MULTILINE): 324 copysection("AXIS_%s" % "XYZABCUVW"[j]) 325 # copysection("JOINT_%i" % j) 326 elif j < len(coordinates): 327 newini.write("\n[AXIS_%s]\n" % coordinates[j]) 328 writeifexists(newini, "JOINT_%i" % j, "HOME") 329 writeifexists(newini, "JOINT_%i" % j, "MIN_LIMIT") 330 writeifexists(newini, "JOINT_%i" % j, "MAX_LIMIT") 331 writeifexists(newini, "JOINT_%i" % j, "MAX_VELOCITY") 332 writeifexists(newini, "JOINT_%i" % j, "MAX_ACCELERATION") 333 copysection("[JOINT_%i]" % j) 334 elif j < len(coordinates): 335 # in this "elif" j is an index in to coordinates. 336 if coordinates[j] in L2J: # duplicate axis letter 337 L2J[coordinates[j]].append(j) # = [L2J[coordinates[j]], j] 338 else: 339 L2J.update({coordinates[j] : [j]}) 340 elif j >= 9: 341 break 342 else: 343 pass 344 345 j += 1 346 347 for L in list("XYZABCUVW"): 348 if L in L2J: 349 axisnum = "XYZABCUVW".index(L) 350 newini.write("\n[AXIS_%s]\n" % L) 351 writeifexists(newini, "AXIS_%i" % axisnum, "MIN_LIMIT") 352 writeifexists(newini, "AXIS_%i" % axisnum, "MAX_LIMIT") 353 writeifexists(newini, "AXIS_%i" % axisnum, "MAX_VELOCITY") 354 writeifexists(newini, "AXIS_%i" % axisnum, "MAX_ACCELERATION") 355 if ini.find("AXIS_%i" % j, "LOCKING_INDEXER"): 356 lock_mask |= 1 << j 357 newini.write("LOCKING_INDEXER_JOINT = %i\n" % j) 358 359 hs = ini.find("AXIS_%i" % axisnum, "HOME_SEQUENCE") 360 if hs == "-1" or hs == None: # -1 used to exclude a joint now we use no entry 361 sequence = "" 362 elif len(L2J[L]) > 1: # tandem axis 363 sequence = "HOME_SEQUENCE = -%s" % hs 364 else: 365 sequence = "HOME_SEQUENCE = %s" % hs 366 for J in L2J[L]: 367 # Take the coordinates index as the JOINT_Number 368 newini.write("\n[JOINT_%i]" % J) 369 section = re.search("\[AXIS_%i\](.+?)(\n\[|$)" % J, inistring, re.DOTALL) 370 if not section: 371 section = re.search("\[AXIS_%i\](.+?)(\n\[|$)" % "XYZABCUVW".index(coordinates[J]), inistring, re.DOTALL) 372 if section: 373 section = re.sub("HOME_SEQUENCE.*", sequence, section.group(1)) 374 newini.write(section) 375 if not '\[AXIS_%i\]' % axisnum in subs: 376 subs.update({'\[AXIS_%i\]' % axisnum : '[JOINT_%i]' % J}) 377 subs2.update({'joint\.%i\.' % axisnum : 'joint.%i.' % J}) 378 else: 379 subs.update({'\[AXIS_%i\]' % J : '[JOINT_%i]' % J}) 380 else: 381 print "File parsing error, found an [AXIS_%i] section, but no content" % J 382 exit() 383 # We no longer need the [AXIS_N] data 384 for j in range(0,8): 385 if ("AXIS_%i" % j) in all_sections: all_sections.remove("AXIS_%i" % j) 386 387 # If there were any custom sections, tag them on the end. 388 while all_sections: 389 copysection(all_sections[0]) 390 391 # and turn the locking mask into a string 392 if lock_mask: 393 lock_string = 'unlock_joints_mask=%i' % lock_mask 394 else: 395 lock_string = "" 396 397 #That's the INI file done: 398 newini.close() 399 400 401 402 # Now change all the pin names etc in the linked HAL files. 403 # Any machine can be jogged in world mode (in theory) but joint-mode jog-enable 404 # is not auto-linked for safety. 405 406 if version == "$Revision$" or version < "1.0": 407 408 subs.update({'axis.(.).active':'joint.\\1.active', 409 'axis.(.).amp-enable-out': 'joint.\\1.amp-enable-out', 410 'axis.(.).amp-fault-in': 'joint.\\1.amp-fault-in', 411 'axis.(.).backlash-corr': 'joint.\\1.backlash-corr', 412 'axis.(.).backlash-filt': 'joint.\\1.backlash-filt', 413 'axis.(.).backlash-vel': 'joint.\\1.backlash-vel', 414 'axis.(.).coarse-pos-cmd': 'joint.\\1.coarse-pos-cmd', 415 'axis.(.).error': 'joint.\\1.error', 416 'axis.(.).f-error': 'joint.\\1.f-error', 417 'axis.(.).f-error-lim': 'joint.\\1.f-error-lim', 418 'axis.(.).f-errored': 'joint.\\1.f-errored', 419 'axis.(.).faulted': 'joint.\\1.faulted', 420 'axis.(.).free-pos-cmd': 'joint.\\1.free-pos-cmd', 421 'axis.(.).free-tp-enable': 'joint.\\1.free-tp-enable', 422 'axis.(.).free-vel-lim': 'joint.\\1.free-vel-lim', 423 'axis.(.).home-state': 'joint.\\1.home-state', 424 'axis.(.).home-sw-in': 'joint.\\1.home-sw-in', 425 'axis.(.).homed': 'joint.\\1.homed', 426 'axis.(.).homing': 'joint.\\1.homing', 427 'axis.(.).in-position': 'joint.\\1.in-position', 428 'axis.(.).index-enable': 'joint.\\1.index-enable', 429 'axis.(.).joint-pos-cmd': 'joint.\\1.pos-cmd', 430 'axis.(.).joint-pos-fb': 'joint.\\1.pos-fb', 431 'axis.(.).joint-vel-cmd': 'joint.\\1.vel-cmd', 432 'axis.(.).kb-jog-active': 'joint.\\1.kb-jog-active', 433 'axis.(.).motor-offset': 'joint.\\1.motor-offset', 434 'axis.(.).motor-pos-cmd': 'joint.\\1.motor-pos-cmd', 435 'axis.(.).motor-pos-fb': 'joint.\\1.motor-pos-fb', 436 'axis.(.).neg-hard-limit': 'joint.\\1.neg-hard-limit', 437 'axis.(.).neg-lim-sw-in': 'joint.\\1.neg-lim-sw-in', 438 'axis.(.).pos-hard-limit': 'joint.\\1.pos-hard-limit', 439 'axis.(.).pos-lim-sw-in': 'joint.\\1.pos-lim-sw-in', 440 'axis.(.).wheel-jog-active': 'joint.\\1.wheel-jog-active', 441 'axis.(.).unlock': 'joint.\\1.unlock', 442 'axis.(.).is-unlocked': 'joint.\\1.is-unlocked', 443 'axis.(.).jog-enable': '@ax\\1@.jog-enable', 444 'axis.(.).jog-counts': 'joint.\\1.jog-counts @ax\\1@.jog-counts', 445 'axis.(.).jog-scale': 'joint.\\1.jog-scale @ax\\1@.jog-scale', 446 'axis.(.).jog-vel-mode': 'joint.\\1.jog-vel-mode @ax\\1@.jog-vel-mode', 447 'halui.axis.(.).pos-commanded':'halui.@ax\\1@.pos-commanded', 448 'halui.axis.(.).pos-feedback':'halui.@ax\\1@.pos-feedback', 449 'halui.axis.(.).pos-relative':'halui.@ax\\1@.pos-relative', 450 'halui.joint.(.).is-selected':'halui.@ax\\1@.is-selected', 451 'halui.jog.(.).analog': 'halui.@ax\\1@.analog', 452 'halui.jog.(.).increment': 'halui.@ax\\1@.increment', 453 'halui.jog.(.).increment-minus':'halui.@ax\\1@.increment-minus', 454 'halui.jog.(.).increment-plus':'halui.@ax\\1@.increment-plus', 455 'halui.jog.(.).minus': 'halui.@ax\\1@.minus', 456 'halui.jog.(.).plus': 'halui.@ax\\1@.plus', 457 'halui.joint.(.).select': 'halui.@ax\\1@.select', 458 'halui.jog.selected.increment':'halui.axis.selected.increment', 459 'halui.jog.selected.increment-minus':'halui.axis.selected.increment-minus', 460 'halui.jog.selected.increment-plus':'halui.axis.selected.increment-plus', 461 'halui.jog.selected.minus': 'halui.axis.selected.minus', 462 'halui.jog.selected.plus': 'halui.axis.selected.plus', 463 'halui.jog-deadband': 'halui.axis.jog-deadband', 464 'halui.jog-speed': 'halui.axis.jog-speed', 465 'halui.joint.selected': 'halui.joint.selected', 466 'halui.joint.selected.is_homed':'halui.joint.selected.is-homed', 467 'halui.joint.selected.on-soft-limit':'halui.joint.selected.on-soft-max-limit', 468 'num_joints=\[TRAJ\]AXES': 'num_joints=[KINS]JOINTS', 469 'loadrt(.+kins)': 'loadrt [KINS]KINEMATICS\n#autoconverted \\1', 470 471 '(setp +gantrykins.+)': '# \\1', 472 '(.+servo_period_ns.+)': '\\1 %s' % lock_string 473 }) 474 475 # converts @axN@ pattern to axis.L and splits any malformed setp from mpg 476 subs2.update({ 477 '^\s*setp\s+(joint\S+)\s+(axis\S+)\s+(\S+)\s*$': 478 'setp \\1 \\3\nsetp \\2 \\3\n', 479 '@ax0@': 'axis.x', 480 '@ax1@': 'axis.y', 481 '@ax2@': 'axis.z', 482 '@ax3@': 'axis.a', 483 '@ax4@': 'axis.b', 484 '@ax5@': 'axis.c', 485 '@ax6@': 'axis.u', 486 '@ax7@': 'axis.v', 487 '@ax8@': 'axis.w', 488 }) 489 490 if version < "1.1": 491 subs.update({ 492 'motion.spindle-brake' : 'spindle.0.brake', 493 'motion.spindle-forward' : 'spindle.0.forward', 494 'motion.spindle-index-enable' : 'spindle.0.index-enable', 495 'motion.spindle-inhibit' : 'spindle.0.inhibit', 496 'motion.spindle-on' : 'spindle.0.on', 497 'motion.spindle-reverse' : 'spindle.0.reverse', 498 'motion.spindle-revs' : 'spindle.0.revs', 499 'motion.spindle-speed-in' : 'spindle.0.speed-in', 500 'motion.spindle-speed-out' : 'spindle.0.speed-out', 501 'motion.spindle-speed-out-abs' : 'spindle.0.speed-out-abs', 502 'motion.spindle-speed-out-rps' : 'spindle.0.speed-out-rps', 503 'motion.spindle-speed-out-rps-abs' : 'spindle.0.speed-out-rps-abs', 504 'motion.spindle-orient-angle' : 'spindle.0.orient-angle', 505 'motion.spindle-orient-mode' : 'spindle.0.orient-mode', 506 'motion.spindle-orient' : 'spindle.0.orient', 507 'motion.spindle-is-oriented' : 'spindle.0.is-oriented', 508 'motion.spindle-orient-fault' : 'spindle.0.orient-fault', 509 'motion.spindle-locked' : 'spindle.0.locked', 510 'motion.spindle-at-speed' : 'spindle.0.at-speed', 511 'halui.spindle.brake-is-on' : 'halui.spindle.0.brake-is-on', 512 'halui.spindle.brake-off' : 'halui.spindle.0.brake-off', 513 'halui.spindle.brake-on' : 'halui.spindle.0.brake-on', 514 'halui.spindle.decrease' : 'halui.spindle.0.decrease', 515 'halui.spindle.forward' : 'halui.spindle.0.forward', 516 'halui.spindle.increase' : 'halui.spindle.0.increase', 517 'halui.spindle.is-on' : 'halui.spindle.0.is-on', 518 'halui.spindle.reverse' : 'halui.spindle.0.reverse', 519 'halui.spindle.runs-backward' : 'halui.spindle.0.runs-backward', 520 'halui.spindle.runs-forward' : 'halui.spindle.0.runs-forward', 521 'halui.spindle.start' : 'halui.spindle.0.start', 522 'halui.spindle.stop' : 'halui.spindle.0.stop', 523 'halui.spindle.override.count-enable' : 'halui.spindle.0.override.count-enable', 524 'halui.spindle.override.counts' : 'halui.spindle.0.override.counts', 525 'halui.spindle.override.decrease' : 'halui.spindle.0.override.decrease', 526 'halui.spindle.override.direct-value' : 'halui.spindle.0.override.direct-value', 527 'halui.spindle.override.increase' : 'halui.spindle.0.override.increase', 528 'halui.spindle.override.scale' : 'halui.spindle.0.override.scale', 529 'halui.spindle.override.value' : 'halui.spindle.0.override.value' 530 }) 531 532 if subs == {}: 533 print """This file does not need converting, and furthermore execution 534 should never have reached this spot""" 535 else: 536 for halfile in halpaths: 537 halstring = open(halfile,'r').read() 538 for sub in subs: 539 halstring = re.sub(sub, subs[sub], halstring, flags=re.M) 540 for sub in subs2: 541 halstring = re.sub(sub, subs2[sub], halstring, flags=re.M) 542 newhal = open(halfile, 'w') 543 newhal.write(halstring) 544 newhal.close() 545 546 if force: 547 shutil.rmtree(backupdir)