Files

641 lines
19 KiB
Python

import os
import sys
import datetime
print "" # print a new line
print "Running KiCadPadMod.py"
def ensure_dir(file_path):
try:
os.makedirs(file_path)
except OSError:
if not os.path.isdir(file_path):
raise
numArgs = len(sys.argv)
lastArg = numArgs - 1
#if numArgs < 3:
# #Print help
# print ""
# print "Not enough arguments!"
# print "See /Documentation/KiCadPadMod.md for manual."
# exit()
#Iterate through the line and inspect all the elements.
argPointer = 1
notEnoughArgs = 0
justListArgs = 0
subArgString = "undef"
padArgString = "undef"
nopadArgString = "undef"
onlypadArgString = "undef"
addArgString = "undef"
remArgString = "undef"
modArgString = "undef"
modArgValueString = "undef"
modArgValueMMString = "undef"
sourcePath = "undef"
destPath = "undef"
searchTermString = "undef"
#Insert the following to debug parsing
#print " Result..."
#print " currentArg =",
#print sys.argv[argPointer]
#print " argPointer =",
#print argPointer
#print " lastArg =",
#print lastArg
if lastArg < 3: #At min, we need .py path path
notEnoughArgs = 1
#Look for -l
if sys.argv[argPointer] == "-l" and notEnoughArgs == 0 :
justListArgs = 1
# print "-l option in effect, not touching files"
if argPointer <= lastArg - 2:
argPointer += 1
else:
notEnoughArgs = 1
#look for sub
if sys.argv[argPointer] == "-sub" and notEnoughArgs == 0 :
# print "we have sub, need 3 additional args"
if argPointer <= lastArg - 3:
argPointer += 1
subArgString = sys.argv[argPointer]
argPointer += 1
else:
notEnoughArgs = 1
#look for pad
if sys.argv[argPointer] == "-pad" and notEnoughArgs == 0 :
# print "we have pad, need 3 additional args"
if argPointer <= lastArg - 3:
argPointer += 1
padArgString = sys.argv[argPointer]
argPointer += 1
else:
notEnoughArgs = 1
#look for nopad
if sys.argv[argPointer] == "-nopad" and notEnoughArgs == 0 :
# print "we have nopad, need 3 additional args"
if argPointer <= lastArg - 3:
argPointer += 1
nopadArgString = sys.argv[argPointer]
argPointer += 1
else:
notEnoughArgs = 1
#look for onlypad
if sys.argv[argPointer] == "-onlypad" and notEnoughArgs == 0 :
# print "we have onlypad, need 3 additional args"
if argPointer <= lastArg - 3:
argPointer += 1
onlypadArgString = sys.argv[argPointer]
argPointer += 1
else:
notEnoughArgs = 1
#look for add
if sys.argv[argPointer] == "-add" and notEnoughArgs == 0 :
# print "we have add, need 3 additional args"
if argPointer <= lastArg - 3:
argPointer += 1
addArgString = sys.argv[argPointer]
argPointer += 1
else:
notEnoughArgs = 1
#look for rem
if sys.argv[argPointer] == "-rem" and notEnoughArgs == 0 :
# print "we have rem, need 3 additional args"
if argPointer <= lastArg - 3:
argPointer += 1
remArgString = sys.argv[argPointer]
argPointer += 1
else:
notEnoughArgs = 1
#look for mod
if sys.argv[argPointer] == "-mod" and notEnoughArgs == 0 :
# print "we have mod, need 4 additional args"
if argPointer <= lastArg - 4:
argPointer += 1
modArgString = sys.argv[argPointer]
argPointer += 1
modArgValueString = sys.argv[argPointer]
modArgValueMMString = "{:6.4f}".format(float(sys.argv[argPointer]) * 25.4)
argPointer += 1
else:
notEnoughArgs = 1
#Now there should be two args remaining
sourcePath = sys.argv[argPointer]
argPointer += 1
destPath = sys.argv[argPointer]
argPointer += 1
#If there is another term, it's the search term
if argPointer <= lastArg:
searchTermString = sys.argv[argPointer]
if justListArgs == 1 or notEnoughArgs == 1:
print ""
if justListArgs == 1:
print "-l option in effect, listing results"
if notEnoughArgs == 1:
print " (Notice: parsing failed)"
else:
print "-l option not in effect, but parsing failed so listing results anyhow"
print ""
print "subArgString:",
print subArgString
print "padArgString:",
print padArgString
print "nopadArgString:",
print nopadArgString
print "onlypadArgString:",
print onlypadArgString
print "addArgString:",
print addArgString
print "remArgString:",
print remArgString
print "modArgString:",
print modArgString
print "modArgValueString:",
print modArgValueString
print "modArgValueMMString:",
print modArgValueMMString
print "sourcePath:",
print sourcePath
print "destPath:",
print destPath
print "searchTermString:",
print searchTermString
# Now check for valid options
invalidOptions = 0
optionsCount = 0
print ""
if subArgString != "undef":
if subArgString == "0" or subArgString == "1":
print "Valid sublevel"
else:
invalidOptions = 1
print "[ERROR] Invalid sublevel option"
else:
print "No sublevel specified, operation TBD"
if padArgString != "undef":
if padArgString == "SMD" or padArgString == "PTH" or padArgString == "NPTH":
print "Valid pad value"
else:
invalidOptions = 1
print "[ERROR] Invalid pad option"
else:
invalidOptions = 1
print "no pad option specified!"
if nopadArgString != "undef":
if nopadArgString == "CENTER":
print "excluding center pad"
else:
invalidOptions = 1
print "[ERROR] Invalid nopad option"
else:
print "nopad not used, including center pad."
if onlypadArgString != "undef":
if onlypadArgString == "CENTER":
print "Only operation on center pad"
else:
invalidOptions = 1
print "[ERROR] Invalid onlypad option"
else:
print "onlypad not used, including all pads."
if nopadArgString != "undef" and onlypadArgString != "undef":
invalidOptions = 1
print "[ERROR] You can't exclude the center pad but only operate on it!"
if addArgString != "undef":
if addArgString == "F.Paste" or addArgString == "B.Paste" or addArgString == "F.Mask" or addArgString == "B.Mask":
print "Valid add value"
optionsCount += 1
else:
invalidOptions = 1
print "[ERROR] Invalid add option"
else:
print "No add option specified."
if remArgString != "undef":
if remArgString == "F.Paste" or remArgString == "B.Paste" or remArgString == "F.Mask" or remArgString == "B.Mask":
print "Valid rem value"
optionsCount += 1
else:
invalidOptions = 1
print "[ERROR] Invalid rem option"
else:
print "No rem option specified."
if modArgString != "undef":
if modArgString == "PadClearance" or modArgString == "MaskClearance" or modArgString == "PasteClearance":
print "Valid mod value"
optionsCount += 1
else:
invalidOptions = 1
print "[ERROR] Invalid mod option"
else:
print "No mod option specified."
if optionsCount == 0:
invalidOptions = 1
print "[ERROR] No operations specified."
if optionsCount > 1:
invalidOptions = 1
print "[ERROR] More than one option specified."
print " (Use batch file to run script multiple times instead.)"
# Now check for valid paths
if sourcePath != "undef":
print "Source path specified",
else:
invalidOptions = 1
print "[ERROR] Source path not present"
if destPath != "undef":
print "Destination path specified",
else:
invalidOptions = 1
print "[ERROR] Destination path not present"
if searchTermString != "undef":
print "Search terms specified",
else:
print "No search terms provided, using *.kicad_mod"
if justListArgs == 1 or notEnoughArgs == 1 or invalidOptions == 1:
print ""
if notEnoughArgs == 1:
print "[ERROR] Encountered invalid syntax."
if invalidOptions == 1:
print "[ERROR] Encountered invalid options."
if justListArgs == 1 and notEnoughArgs == 0 and invalidOptions == 0:
print "Syntax and parsing passed!"
else:
exit()
else:
print ""
print "Option parsing passed!"
# Now check file paths are actually valid
pathError = 0
print ""
print "Checking file paths"
print "Destination path:",
print destPath
if not os.path.isdir(destPath):
print " Destination path does not exists. Will be created!"
else:
print " Destination path exists!"
print "Source path:",
print sourcePath
if not os.path.isdir(sourcePath):
pathError = 1
print " [ERROR] soruce path doesn't exist!"
else:
print " Source path exists!"
if pathError == 1:
print ""
print "Path error, can't continue"
exit()
directoryList = []
fileList = []
#save contents of source into fileList, excluding those without .kicad_mod
for filename in os.listdir(sourcePath):
if filename[len(filename) - 10:] == ".kicad_mod":
fullFilePath = filename
print "file:",
print fullFilePath,
if searchTermString != "undef":
if filename.find(searchTermString, 0, len(filename)) != -1:
#found match
fileList.append(fullFilePath)
print ""
else:
print "[IGNORED]"
else:
fileList.append(fullFilePath)
print ""
if subArgString == "1":
#Save contents of source into directoryList, only choosing files with .pretty
for filename in os.listdir(sourcePath):
if filename[len(filename) - 7:] == ".pretty":
fullFilePath = filename
directoryList.append(fullFilePath)
#extend fileList with subdirs
for directoryname in directoryList:
print "directory:",
print directoryname
for filename in os.listdir(sourcePath + "\\" + directoryname):
if filename[len(filename) - 10:] == ".kicad_mod":
fullFilePath = directoryname + "\\" + filename
print " file:",
print fullFilePath,
if searchTermString != "undef":
if filename.find(searchTermString, 0, len(filename)) != -1:
#found match
fileList.append(fullFilePath)
print ""
else:
print "[IGNORED]"
else:
fileList.append(fullFilePath)
print ""
#print fileList
#print directoryList
if justListArgs == 1:
print ""
print "Exiting (-l option used)"
exit()
else:
print "Running script..."
ensure_dir(destPath)
for dirname in directoryList:
ensure_dir(destPath + dirname)
for filename in fileList:
print ""
print "Opening",
fullFilePath = sourcePath + filename
print fullFilePath
# Open the export mod style file
if os.path.isfile(fullFilePath) == True:
statinfo = os.stat(fullFilePath)
workingFileHandle = open(fullFilePath, "r")
# Read the footprint to memeory
workingFileMemory = workingFileHandle.read()
# ..Now workingFileMemory is a string that is the input file
#First, seek out initial "pad" text
locVar = workingFileMemory.find("(pad ", 0, len(workingFileMemory))
if locVar > 0:
#This file has one or more
fileVar = 0
parsingFile = 1
while parsingFile == 1 and fileVar < len(workingFileMemory):
locVar = workingFileMemory.find("(pad ", fileVar, len(workingFileMemory))
if locVar > 0:
#print "Found pad!"
fileVar = locVar + 1
leftParen = locVar
leftParenCount = 1
rightParenCount = 0
countIsNonZero = 1
nextParen = leftParen
while countIsNonZero == 1:
#Find next paren
var2 = workingFileMemory.find("(", nextParen + 1, len(workingFileMemory))
var1 = workingFileMemory.find(")", nextParen + 1, len(workingFileMemory))
if var1 != -1 or var2 != 0:
if var2 < var1 and var2 > 0:
#set output = var2
nextParen = var2
else:
nextParen = var1
#Found something
#modify counts
if workingFileMemory[nextParen] == '(':
#print workingFileMemory[nextParen]
leftParenCount = leftParenCount + 1
elif workingFileMemory[nextParen] == ')':
#print workingFileMemory[nextParen]
rightParenCount = rightParenCount + 1
else:
print "No more chars"
countIsNonZero = 0
#print leftParenCount,
#print ",",
#print rightParenCount
#if counts are equal, do a thing then bail
workOnPad = 0
if leftParenCount == rightParenCount:
print "Found: ",
if workingFileMemory.find("(at 0 0)", leftParen, nextParen) > 0:
#This is a center pad
print "Center,",
if nopadArgString != "CENTER":
print "(will modify)",
#work on this pad
workOnPad = 1
else:
countIsNonZero = 0 #break
print "(ignored)"
if workingFileMemory.find("(at 0 0)", leftParen, nextParen) == -1:
print "Normal,",
#This is not a center pad
if onlypadArgString != "CENTER":
print "(will modify)",
#work on this pad
workOnPad = 1
else:
countIsNonZero = 0 #break
print "(ignored)"
# Now test for the type of pad, but only after center rules adhered to
if workOnPad == 1:
workOnPad = 0
if workingFileMemory.find(" smd ", leftParen + 4, nextParen) > 0: #adding 4 insures pad named 'smd' doesn't trigger
#This is a smd pad
print "Type: SMD",
if padArgString == "SMD":
print "(will modify)"
#work on this pad
workOnPad = 1
else:
countIsNonZero = 0 #break
print "(ignored)"
if workingFileMemory.find(" thru_hole ", leftParen + 4, nextParen) > 0: #adding 4 insures pad named 'thru_hole' doesn't trigger
#This is a thru_hole pad
print "Type: PTH",
if padArgString == "PTH":
print "(will modify)"
#work on this pad
workOnPad = 1
else:
countIsNonZero = 0 #break
print "(ignored)"
if workingFileMemory.find(" np_thru_hole ", leftParen + 4, nextParen) > 0: #adding 4 insures pad named 'np_thru_hole' doesn't trigger
#This is a np_thru_hole pad
print "Type: NPTH",
if padArgString == "NPTH":
print "(will modify)"
#work on this pad
workOnPad = 1
else:
countIsNonZero = 0 #break
print "(ignored)"
if workOnPad == 1:
countIsNonZero = 0
rightParen = nextParen + 1
# print "Syntax Correct!"
# print workingFileMemory[leftParen:rightParen]
#This is where the options on what to do take place.
#If rem is used, remove the pad layer
if remArgString != "undef":
#We will be removing a layer
#Generate string data
# find .
var3 = remArgString.find(".", 0, len(remArgString))
if var3 != -1:
searchString = " *." + remArgString[var3+1:]
replaceString = " F." + remArgString[var3+1:] + " B." + remArgString[var3+1:]
removeString = " " + remArgString
#Look for the (layers .....) param
var1 = workingFileMemory.find("(layers ", leftParen, rightParen)
var2 = workingFileMemory.find(")", var1, rightParen)
#convert *.thing to F.thing and B.thing
var3 = workingFileMemory.find(searchString, var1, var2)
if var3 != -1:
tempFileMemory = workingFileMemory[:var3] + workingFileMemory[var3 + len(searchString):]
#Move pointers
rightParen -= len(searchString)
var2 -= len(searchString)
#Now insert new text
#print tempFileMemory[leftParen:rightParen]
workingFileMemory = tempFileMemory[:var3] + replaceString + tempFileMemory[var3:]
rightParen += len(replaceString)
var2 += len(replaceString)
#print workingFileMemory[leftParen:rightParen]
#Search for string to remove
var4 = workingFileMemory.find(removeString, var1, var2)
if var4 != -1:
tempFileMemory = workingFileMemory[:var4] + workingFileMemory[var4 + len(removeString):]
workingFileMemory = tempFileMemory
rightParen -= len(removeString)
var2 -= len(removeString)
#print workingFileMemory[leftParen:rightParen]
#If add was used, add the layer if it doesn't already exist
if addArgString != "undef":
#We will be adding a layer
# find .
var3 = addArgString.find(".", 0, len(addArgString))
if var3 != -1:
#Generate string data
searchString = " *." + addArgString[var3+1:]
addString = " " + addArgString
#Look for the (layers .....) param
var1 = workingFileMemory.find("(layers ", leftParen, rightParen)
var2 = workingFileMemory.find(")", var1, rightParen)
#if *.thing is found, we are done!
var3 = workingFileMemory.find(searchString, var1, var2)
if var3 != -1:
# *. was found! the arg is covered.
var3 = var3
else:
# *. not found, but perhaps the single one is there
var3 = workingFileMemory.find(addString[1:], leftParen, rightParen)
if var3 != -1:
#found it, we are done
var3 = var3
else:
#we need to add it.
tempFileMemory = workingFileMemory[:var2] + addString + workingFileMemory[var2:]
rightParen += len(addString)
var2 += len(addString)
workingFileMemory = tempFileMemory
#print workingFileMemory[leftParen:rightParen]
#If mod was used, remove the attrib and reapply it.
if modArgString != "undef" and modArgValueMMString != "undef":
#We will be modifying a parameter
#Generate string data
searchString = "undef"
if modArgString == "PadClearance":
searchString = "(clearance"
if modArgString == "MaskClearance":
searchString = "(solder_mask_margin"
if modArgString == "PasteClearance":
searchString = "(solder_paste_margin"
if searchString != "undef":
#good to go!
addString = searchString + " " + modArgValueMMString + ")"
#Look for instance of search term
var3 = workingFileMemory.find(searchString, leftParen, rightParen)
if var3 != -1:
#found it -- index it
var1 = workingFileMemory.find(searchString, leftParen, rightParen)
var2 = workingFileMemory.find(")", var1, rightParen)
#Calculate length of this string
stringLen = var2 - var1 + 1
#remove it
tempFileMemory = workingFileMemory[:var1] + workingFileMemory[var1 + stringLen:]
workingFileMemory = tempFileMemory
rightParen -= stringLen
var2 -= stringLen
#var1 should now equal var2
#Now add the new tag
if workingFileMemory[rightParen - 2] != " ":
tempString = " " + addString
addString = tempString
tempFileMemory = workingFileMemory[:rightParen - 1] + addString + workingFileMemory[rightParen - 1:]
rightParen += len(addString)
var2 += len(addString)
workingFileMemory = tempFileMemory
#print workingFileMemory[leftParen:rightParen]
else:
print "Invalid modArgString"
else:
parsingFile = 0
# print workingFileMemory[locVar-3:locVar+3]
else:
#This file has none!
print "File has no pads!"
#print tempFileMemory
#programPause = raw_input("Press the <ENTER> key to continue...")
#Write the output file
outputFilePath = destPath + filename
# Write out the workingFileMemory
if os.path.isfile(outputFilePath) == True:
statinfo = os.stat(outputFilePath)
outputFileHandle = open(outputFilePath, "w+")
# Read the KiCad Library to memeory
else:
print "creating",
print outputFilePath
outputFileHandle = open(outputFilePath, "w+")
outputFileHandle.write(workingFileMemory) # Enable this line to write memory to OUTPUT
outputFileHandle.close()
workingFileHandle.close()
else:
print "File not opened!"
print ""
print "Script finished!"