diff --git a/FritzingCheckPart.py b/FritzingCheckPart.py index a43cbf4..1f6ea5a 100755 --- a/FritzingCheckPart.py +++ b/FritzingCheckPart.py @@ -4,32 +4,39 @@ # (.fzp and .svg) and both check them for correctness and converting xml # formats (such as CSS style and px on font-size) that Fritzing doesn't support # in to equivelent xml that Fritzing does support. As well it will convert old -# style white silkscreen images to the new black silkscreen standard. +# style white silkscreen images to the new black silkscreen standard. -# Set Debug to 0 for normal operation (rename the input file and write the +# Set Debug to 0 for normal operation (rename the input file and write the # pretty printed output to the input file name. -# -# Set Debug to 1 to not rename the input file and write the output to stdout -# rather than the file for debugging but with no debug messages. -# -# Set Debug to 2 to not rename the input file and write the output to stdout +# +# Set Debug to 1 to not rename the input file and write the output to stdout +# rather than the file for debugging but with no debug messages. +# +# Set Debug to 2 to not rename the input file and write the output to stdout # rather than the file for debugging with debug messages for entry and exit -# from routines. -# -# Set Debug to 3 to not rename the input file and write the output to stdout +# from routines. +# +# Set Debug to 3 to not rename the input file and write the output to stdout # rather than the file for debugging with verbous debug messages for detail # debugging. +import logging +import os +import re +import sys + +import FritzingTools as Fritzing +import PPTools as PP + Debug = 0 -Version = '0.0.2' # Version number of this file. - +Version = '0.0.3' # Version number of this file. + # Set up the requested debug level # Import os and sys to get file rename and the argv stuff, re for regex and # logging for logging support -import os, sys, re, logging if Debug == 3: @@ -46,18 +53,17 @@ logging.basicConfig(stream=sys.stderr, level=logging.WARNING) # End of if Debug == 3: - + # Import various svg routines and pretty printing routines. - -import FritzingTools as Fritzing, PPTools as PP - + + # Start of the main script # Set the Errors flag to 'n' to indicate no errors yet. ErrorsSeen = 'n' -# Create the processed dictionary to keep track of what files have been +# Create the processed dictionary to keep track of what files have been # processed in a dir dir context to prevent part. type svg files from being # processed twice (which would destroy the original file as it got backed up # for the second time). The FzpDict gets reset for each file and thus won't @@ -69,18 +75,20 @@ Errors, Warnings, Info, FzpDict, CurView, TagStack, State, InheritedAttributes = Fritzing.InitializeAll() -# PrefixDir needs to be global even between files, so reset it once here. +# PrefixDir needs to be global even between files, so reset it once here. PrefixDir = None -FileType, DirProcessing, PrefixDir, Path, File, SrcDir, DstDir = Fritzing.ProcessArgs (sys.argv, Errors) +FileType, DirProcessing, PrefixDir, Path, File, SrcDir, DstDir = Fritzing.ProcessArgs( + sys.argv, Errors) -logging.debug (' FritzingCheckPart.py FileType %s, DirProcessing %s PrefixDir %s, Path %s, File %s, SrcDir %s, DstDir %s\n', FileType, DirProcessing, PrefixDir, Path, File, SrcDir, DstDir) +logging.debug( + ' FritzingCheckPart.py FileType %s, DirProcessing %s PrefixDir %s, Path %s, File %s, SrcDir %s, DstDir %s\n', + FileType, DirProcessing, PrefixDir, Path, File, SrcDir, DstDir) # If the returned FileType is None then go print the errors then exit. -if FileType == None: - +if FileType == None: PP.PrintErrors(Errors) sys.exit(1) @@ -104,24 +112,24 @@ if DirProcessing == 'Y': # The input is two directories (src and dst), so process the files in src - # directory one at a time and write the results to the dst directory. - # There are three cases, One: a directory of svg files only, which will - # be processed and written to the dst directory (although the empty - # directories for the svg files will be there as well) Two: a fzp file - # where first the fzp file will be processed, and then its associated + # directory one at a time and write the results to the dst directory. + # There are three cases, One: a directory of svg files only, which will + # be processed and written to the dst directory (although the empty + # directories for the svg files will be there as well) Two: a fzp file + # where first the fzp file will be processed, and then its associated # svg files will be processed (with data from the fzp file to check against - # the svg data) and written in to the corresponding directories under the - # dst directory. Three: a part.filename.fzp which will be processed in to - # the dst directory, and then its associated svg files which will also be - # processed in to the dst directory (again with the empty svg directories + # the svg data) and written in to the corresponding directories under the + # dst directory. Three: a part.filename.fzp which will be processed in to + # the dst directory, and then its associated svg files which will also be + # processed in to the dst directory (again with the empty svg directories # being present as well). As the fzp file is processed (and its associated - # svgs) the svg filenames will be added to the FilesProcessed dictionary - # and tested for here so that the svg does not get processed as part of - # the fzp and then again as the individual svg (without the connector - # information from the fzp) to avoid duplication, less information - # (because of no fzp data), confusion and most importantly loss of the - # original input file. Any svg files that aren't referenced by an fzp will - # get processed as svg files though. + # svgs) the svg filenames will be added to the FilesProcessed dictionary + # and tested for here so that the svg does not get processed as part of + # the fzp and then again as the individual svg (without the connector + # information from the fzp) to avoid duplication, less information + # (because of no fzp data), confusion and most importantly loss of the + # original input file. Any svg files that aren't referenced by an fzp will + # get processed as svg files though. # Then process all the files in the src directory @@ -134,11 +142,11 @@ FQOutFile = os.path.join(DstDir, InFile) # Then get just the file name (no path) for the regexs and the svg - # already processed as part of an fzp check. + # already processed as part of an fzp check. BaseFile = os.path.basename(FQInFile) - # Determine if this is a part. type file or not. + # Determine if this is a part. type file or not. if PartRegex.search(BaseFile) or SVgPrefixRegex.search(BaseFile): @@ -148,107 +156,119 @@ FzpType = 'FZPFRITZ' - # End of if PartRegex.search(BaseFile) or SVgPrefixRegex.search(BaseFile): + # End of if PartRegex.search(BaseFile) or + # SVgPrefixRegex.search(BaseFile): + + logging.debug( + ' FritzingCheckPart.py dir loop set FzpType %s\n', FzpType) - logging.debug (' FritzingCheckPart.py dir loop set FzpType %s\n', FzpType) - # Check the dictionary to make sure we haven't already processed this - # svg as part of one of the fzp files we have already processed. + # svg as part of one of the fzp files we have already processed. - logging.debug (' FritzingCheckPart.py dir loop trying FQInFile %s\n', FQInFile) + logging.debug( + ' FritzingCheckPart.py dir loop trying FQInFile %s\n', FQInFile) if not 'processed.' + FQInFile in FilesProcessed: - logging.debug (' FritzingCheckPart.py didn\'t find \"%s\" in FilesProcessed\n', 'processed.' + FQInFile ) + logging.debug( + ' FritzingCheckPart.py didn\'t find \"%s\" in FilesProcessed\n', 'processed.' + FQInFile) - # We haven't yet processed this file so do so now. + # We haven't yet processed this file so do so now. # Initialize all the global variables before processing a new file. - + Errors, Warnings, Info, FzpDict, CurView, TagStack, State, InheritedAttributes = Fritzing.InitializeAll() - + print('\n**** Starting to process file {0:s}'.format(str(InFile))) - + if SvgExtRegex.search(BaseFile): - + # This looks to be an svg file so process it. - - # set the FzpType to None (as dir to dir processing doesn't + + # set the FzpType to None (as dir to dir processing doesn't # require filename translation). - - Doc = Fritzing.ProcessSvg(FzpType, 'SVG', FQInFile, FQOutFile, CurView, PrefixDir, Errors, Warnings, Info, FzpDict, FilesProcessed, TagStack, State, InheritedAttributes, Debug) - + + Doc = Fritzing.ProcessSvg(FzpType, 'SVG', FQInFile, FQOutFile, CurView, PrefixDir, Errors, + Warnings, Info, FzpDict, FilesProcessed, TagStack, State, InheritedAttributes, + Debug) + elif PartRegex.search(BaseFile): - + # This looks to be an part.filename.fzp file so process it. - - # set the FzpType to 'dir' (as dir to dir processing doesn't + + # set the FzpType to 'dir' (as dir to dir processing doesn't # require filename translation) and FileType to 'fzpPart'. - - - Doc = Fritzing.ProcessFzp(DirProcessing, FzpType, 'FZPPART', FQInFile, FQOutFile, CurView, PrefixDir, Errors, Warnings, Info, FzpDict, FilesProcessed, TagStack, State, InheritedAttributes, Debug) - + + Doc = Fritzing.ProcessFzp(DirProcessing, FzpType, 'FZPPART', FQInFile, FQOutFile, CurView, PrefixDir, + Errors, Warnings, Info, FzpDict, FilesProcessed, TagStack, State, + InheritedAttributes, Debug) + elif FzpExtRegex.search(BaseFile): - + # This looks to be a filename.fzp file so process it. - - # set the FzpType to 'dir' (as dir to dir processing doesn't + + # set the FzpType to 'dir' (as dir to dir processing doesn't # require filename translation) and FileType to 'fzpFritz'. - # We do however need to add the PrefixDir to the output + # We do however need to add the PrefixDir to the output # filename. FQOutFile = os.path.join(DstDir, PrefixDir) - + FQOutFile = os.path.join(FQOutFile, InFile) - - Doc = Fritzing.ProcessFzp(DirProcessing, FzpType, 'FZPFRITZ', FQInFile, FQOutFile, CurView, PrefixDir, Errors, Warnings, Info, FzpDict, FilesProcessed, TagStack, State, InheritedAttributes, Debug) - + + Doc = Fritzing.ProcessFzp(DirProcessing, FzpType, 'FZPFRITZ', FQInFile, FQOutFile, CurView, PrefixDir, + Errors, Warnings, Info, FzpDict, FilesProcessed, TagStack, State, + InheritedAttributes, Debug) + else: - - # Not a fritzing file type so warn about it but otherwise + + # Not a fritzing file type so warn about it but otherwise # ignore it. - - Warnings.append('Warning 1: File\n\n\'{0:s}\'\n\nIsn\'t a Fritzing file and has been ignored in processing the directory\n'.format(str(InFile))) - + + Warnings.append( + 'Warning 1: File\n\n\'{0:s}\'\n\nIsn\'t a Fritzing file and has been ignored in processing the directory\n'.format( + str(InFile))) + # End of if SvgExtRegex.search(InFile): - + if len(Errors) != 0: - - # If we have seen errors in this file, note that to set the - # eventual return code when all processing is done. - + # If we have seen errors in this file, note that to set the + # eventual return code when all processing is done. + ErrorsSeen = 'Y' - + # End of if len(Errors) != 0: - + # Output the Info, Warnings and Errors associated with the document - # before they get cleared for the next file. - + # before they get cleared for the next file. + PP.PrintInfo(Info) - + PP.PrintWarnings(Warnings) - + PP.PrintErrors(Errors) else: - logging.debug (' FritzingCheckPart.py skipped file %s as already proessed\n', FQInFile) + logging.debug( + ' FritzingCheckPart.py skipped file %s as already proessed\n', FQInFile) # End of if not 'processed.' + FQInFile in FilesProcessed: - + # End of for InFile in os.listdir(SrcDir): elif FileType == 'SVG': # This looks to be an svg file so process it Create the input file name # from Path, PrefixDir and File then set the output file to None - # to cause the input file to be moved to .bak and be replaced by the output. + # to cause the input file to be moved to .bak and be replaced by the + # output. InFile = os.path.join(Path, PrefixDir) InFile = os.path.join(InFile, File) - # set the FzpType + # set the FzpType if SVgPrefixRegex.match(File): @@ -264,7 +284,8 @@ # End of if SVgPrefixRegex.match(File): - Doc = Fritzing.ProcessSvg(FzpType, FileType, InFile, None, CurView, PrefixDir, Errors, Warnings, Info, FzpDict, FilesProcessed, TagStack, State, InheritedAttributes, Debug) + Doc = Fritzing.ProcessSvg(FzpType, FileType, InFile, None, CurView, PrefixDir, Errors, + Warnings, Info, FzpDict, FilesProcessed, TagStack, State, InheritedAttributes, Debug) # Output the Info, Warnings and Errors associated with the document @@ -278,7 +299,8 @@ # This looks to be an fzpPart file so process it Create the input file name # from Path, PrefixDir and File then set the output file to None - # to cause the input file to be moved to .bak and be replaced by the output. + # to cause the input file to be moved to .bak and be replaced by the + # output. InFile = os.path.join(Path, PrefixDir) @@ -286,7 +308,9 @@ # set the FzpType to 'fzpPart' by reusing FileType in this call - Doc = Fritzing.ProcessFzp(DirProcessing, FileType, FileType, InFile, None, CurView, PrefixDir, Errors, Warnings, Info, FzpDict, FilesProcessed, TagStack, State, InheritedAttributes, Debug) + Doc = Fritzing.ProcessFzp(DirProcessing, FileType, FileType, InFile, None, CurView, PrefixDir, + Errors, Warnings, Info, FzpDict, FilesProcessed, TagStack, State, InheritedAttributes, + Debug) # Output the Info, Warnings and Errors associated with the document @@ -296,11 +320,12 @@ PP.PrintErrors(Errors) -elif FileType == 'FZPFRITZ': +elif FileType == 'FZPFRITZ': # This looks to be an fzp file so process it Create the input file name # from Path, PrefixDir and File then set the output file to None - # to cause the input file to be moved to .bak and be replaced by the output. + # to cause the input file to be moved to .bak and be replaced by the + # output. InFile = os.path.join(Path, PrefixDir) @@ -312,7 +337,9 @@ # Use FileType as the FzpType in this call - Doc = Fritzing.ProcessFzp(DirProcessing, FileType, FileType, InFile, None, CurView, PrefixDir, Errors, Warnings, Info, FzpDict, FilesProcessed, TagStack, State, InheritedAttributes, Debug) + Doc = Fritzing.ProcessFzp(DirProcessing, FileType, FileType, InFile, None, CurView, PrefixDir, + Errors, Warnings, Info, FzpDict, FilesProcessed, TagStack, State, InheritedAttributes, + Debug) # Output the errors and warnings associated with the document @@ -324,12 +351,12 @@ else: - Errors.append('Error 8: Unknown FileType {0:s} (should not occur, software error)\n'.format(str(FileType))) + Errors.append( + 'Error 8: Unknown FileType {0:s} (should not occur, software error)\n'.format(str(FileType))) # End of if FileType == 'dir': if len(Errors) != 0: - # if there were errors set the flag so we exit non 0 ErrorsSeen = 'y' diff --git a/FritzingTools.py b/FritzingTools.py index 2c48d0d..79d3dee 100755 --- a/FritzingTools.py +++ b/FritzingTools.py @@ -1,35 +1,39 @@ #!/usr/bin/env python3 -# Various support routines for processing Fritzing's fzp and svg files. +# Various support routines for processing Fritzing's fzp and svg files. # Change this from 'no' to 'yes' to cause 0 length/width terminal definitions # to be warned about but not modified, to being changed (which will cause them -# to move in the svg and need repositioning) to a length/width of 10 (which +# to move in the svg and need repositioning) to a length/width of 10 (which # depending on scaling may or may not be .01in). The default is warn but not # change, but I use modify as it is much easier converting 0 width parts with # Inkscape like that. -ModifyTerminal = 'n' -# Set to 'n' (or anything not 'y') to supress Warning 28: (dup id in +import PPTools as PP +import logging +import re +import sys +import os + +ModifyTerminal = 'y' + +# Set to 'n' (or anything not 'y') to supress Warning 28: (dup id in # description field) which is all of common, annoying and harmless. # However by default the warning is issued ... IssueNameDupWarning = 'n' -Version = '0.0.2' # Version number of this file. +Version = '0.0.3' # Version number of this file. # Import copyfile - from shutil import copyfile # Import os and sys to get file rename and the argv stuff, re for regex, # logging to get logging support and PPTools for the parse routine -import os, sys, re, logging, PPTools as PP # and the lxml library for the xml - from lxml import etree def InitializeAll(): @@ -58,35 +62,39 @@ def InitializeAll(): TagStack = [['empty', 0]] - State={'lasttag': 'none', 'nexttag': 'none', 'lastvalue': 'none', 'image': 'none', 'noradius': [], 'KeyErrors': []} + State = {'lasttag': 'none', 'nexttag': 'none', 'lastvalue': 'none', + 'image': 'none', 'noradius': [], 'KeyErrors': []} - InheritedAttributes=None + InheritedAttributes = None return Errors, Warnings, Info, FzpDict, CurView, TagStack, State, InheritedAttributes # End of def InitializeAll(): + def InitializeState(): - # Initialize only the state related global variables (not the PrefixDir, - # Errors, Warnings or dictionary) to start processing a different file - # such as an svg linked from a fzp. + # Initialize only the state related global variables (not the PrefixDir, + # Errors, Warnings or dictionary) to start processing a different file + # such as an svg linked from a fzp. TagStack = [['empty', 0]] - State={'lasttag': 'none', 'nexttag': 'none', 'lastvalue': 'none', 'image': 'none', 'noradius': [], 'KeyErrors': []} + State = {'lasttag': 'none', 'nexttag': 'none', 'lastvalue': 'none', + 'image': 'none', 'noradius': [], 'KeyErrors': []} - InheritedAttributes=None + InheritedAttributes = None return TagStack, State, InheritedAttributes # End of def InitializeState(): + def ProcessArgs(Argv, Errors): - # Process the input arguments on the command line. + # Process the input arguments on the command line. - logging.info (' Entering ProcessArgs\n') + logging.info(' Entering ProcessArgs\n') # Regex to match '.svg' to find svg files @@ -100,13 +108,15 @@ def ProcessArgs(Argv, Errors): PartRegex = re.compile(r'^part\.', re.IGNORECASE) - # Regex to match 'part.filename' for substitution for both unix and windows. + # Regex to match 'part.filename' for substitution for both unix and + # windows. - PartReplaceRegex = re.compile(r'^part\..*$|\/part\..*$|\\part\..*$', re.IGNORECASE) + PartReplaceRegex = re.compile( + r'^part\..*$|\/part\..*$|\\part\..*$', re.IGNORECASE) # Set the return values to the error return (really only FileType needs # to be done, but do them all for consistancy. Set PrefixDir and Path - # to striing constants (not None) for the dir routines. + # to striing constants (not None) for the dir routines. FileType = None @@ -124,32 +134,35 @@ def ProcessArgs(Argv, Errors): if len(sys.argv) == 3: - # If we have two directories, one empty, process all the fzp files in - # the first directory in to the empty second directory, creating - # subdirectories as needed (but no backup files!) + # If we have two directories, one empty, process all the fzp files in + # the first directory in to the empty second directory, creating + # subdirectories as needed (but no backup files!) - DirProcessing, PrefixDir, Path, File, SrcDir, DstDir = ProcessDirArgs(Argv, Errors) + DirProcessing, PrefixDir, Path, File, SrcDir, DstDir = ProcessDirArgs( + Argv, Errors) if DirProcessing == 'Y': # Success, so set FileType to 'dir' from None to indicate no - # error is present and to continue processing. - + # error is present and to continue processing. + FileType = 'dir' # End of if (DirProcessing == 'Y': - logging.info (' Exiting ProcessArgs\n') + logging.info(' Exiting ProcessArgs\n') return FileType, DirProcessing, PrefixDir, Path, File, SrcDir, DstDir elif len(sys.argv) != 2: - # No input file or too many arguments so print a usage message and exit. + # No input file or too many arguments so print a usage message and + # exit. - Errors.append('Usage: {0:s} filename.fzp or filename.svg or srcdir dstdir\n'.format(str(sys.argv[0]))) + Errors.append('Usage: {0:s} filename.fzp or filename.svg or srcdir dstdir\n'.format( + str(sys.argv[0]))) - logging.info (' Exiting ProcessArgs\n') + logging.info(' Exiting ProcessArgs\n') return FileType, DirProcessing, PrefixDir, Path, File, SrcDir, DstDir @@ -159,27 +172,29 @@ def ProcessArgs(Argv, Errors): InFile = sys.argv[1] - logging.debug (' ProcessArgs: input filename %s\n', InFile) + logging.debug(' ProcessArgs: input filename %s\n', InFile) - logging.debug (' ProcessArgs: isfile %s\n', os.path.isfile(InFile)) + logging.debug(' ProcessArgs: isfile %s\n', os.path.isfile(InFile)) - logging.debug (' ProcessArgs: svg %s\n', SvgExtRegex.search(InFile)) + logging.debug(' ProcessArgs: svg %s\n', SvgExtRegex.search(InFile)) - logging.debug (' ProcessArgs: fzp %s\n', FzpExtRegex.search(InFile)) + logging.debug(' ProcessArgs: fzp %s\n', FzpExtRegex.search(InFile)) - if (not os.path.isfile(InFile) or + if (not os.path.isfile(InFile) or (SvgExtRegex.search(InFile) == None and - FzpExtRegex.search(InFile) == None)): + FzpExtRegex.search(InFile) == None)): # Input file isn't valid, return a usage message. - Errors.append('Usage: {0:s} filename.fzp or filename.svg or srcdir dstdir\n\n\'{1:s}\'\n\neither isn\'t a file or doesn\'t end in .fzp or .svg\n'.format(str(sys.argv[0]), str(InFile))) + Errors.append('Usage: {0:s} filename.fzp or filename.svg or srcdir dstdir\n\n\'{1:s}\'\n\neither isn\'t a file or doesn\'t end in .fzp or .svg\n'.format( + str(sys.argv[0]), str(InFile))) - logging.info (' Exiting ProcessArgs\n') + logging.info(' Exiting ProcessArgs\n') return FileType, DirProcessing, PrefixDir, Path, File, SrcDir, DstDir - # End of if not os.path.isfile(InFile) and not SvgExtRegex.search(InFile) and not FzpExtRegex.search(InFile): + # End of if not os.path.isfile(InFile) and not + # SvgExtRegex.search(InFile) and not FzpExtRegex.search(InFile): Path = '' @@ -195,7 +210,7 @@ def ProcessArgs(Argv, Errors): # End of if not Path: - # and then get the filename + # and then get the filename File = os.path.basename(InFile) @@ -205,56 +220,60 @@ def ProcessArgs(Argv, Errors): FileType = 'SVG' - logging.debug (' ProcessArgs: Found svg input file %s set FileType %s\n', InFile, FileType) + logging.debug( + ' ProcessArgs: Found svg input file %s set FileType %s\n', InFile, FileType) else: - # this is an fzp file of some kind so figure out which kind and + # this is an fzp file of some kind so figure out which kind and # set the appropriate path. pat = PartRegex.search(File) - logging.debug (' ProcessArgs: Found svg input file %s Match %s\n', InFile, pat) - + logging.debug( + ' ProcessArgs: Found svg input file %s Match %s\n', InFile, pat) + if PartRegex.search(File): - + # It is a part. type fzp, thus the svgs are in this same - # directory named svg.image_type.filename so set FileType + # directory named svg.image_type.filename so set FileType # to fzpPart to indicate that. - + FileType = 'FZPPART' - logging.debug (' ProcessArgs: Set filetype FZPPART\n') - + logging.debug(' ProcessArgs: Set filetype FZPPART\n') + else: - + # This is a Fritzing internal type fzp and thus the svgs are in - # svg/PrefixDir/image_type/filename.svg. So make sure we have a - # prefix directory on the input file. + # svg/PrefixDir/image_type/filename.svg. So make sure we have a + # prefix directory on the input file. - # get the path from the input file. + # get the path from the input file. Path = os.path.dirname(InFile) # and the file name - File = os.path.basename(InFile) - + File = os.path.basename(InFile) + SplitDir = os.path.split(Path) - + if SplitDir[1] == '' or SplitDir[1] == '.' or SplitDir[1] == '..': - - Errors.append('Error 10: There must be a directory that is not \'.\' or \'..\' in the input name for\na fzp file in order to find the svg files.\n') - - logging.info (' Exiting ProcessArgs no prefix dir error\n') - + + Errors.append( + 'Error 10: There must be a directory that is not \'.\' or \'..\' in the input name for\na fzp file in order to find the svg files.\n') + + logging.info(' Exiting ProcessArgs no prefix dir error\n') + return FileType, DirProcessing, PrefixDir, Path, File, SrcDir, DstDir - - # End of if SplitDir[1] == '' or SplitDir[1] == '.' or SplitDir[1] == '..': - + + # End of if SplitDir[1] == '' or SplitDir[1] == '.' or + # SplitDir[1] == '..': + Path = SplitDir[0] - - PrefixDir = SplitDir[1] + + PrefixDir = SplitDir[1] if PrefixDir == None: @@ -264,32 +283,35 @@ def ProcessArgs(Argv, Errors): PrefixDir = "" # End of if PrefixDir == None: - - # then so set FileType to fzpFritz to indicate that. - + + # then so set FileType to fzpFritz to indicate that. + FileType = 'FZPFRITZ' - - logging.debug (' Found Fritzing type input file %s path %s\n', InFile, Path) + + logging.debug( + ' Found Fritzing type input file %s path %s\n', InFile, Path) # End of if PartRegex.search(File): - + # End of if SvgExtRegex.search(File): # End of if len(sys.argv) == 3: - logging.debug (' ProcessArgs: End of ProcessArgs return FileType %s PrefixDir %s Path %s File %s\n', FileType, PrefixDir, Path, File) + logging.debug(' ProcessArgs: End of ProcessArgs return FileType %s PrefixDir %s Path %s File %s\n', + FileType, PrefixDir, Path, File) - logging.info (' Exiting ProcessArgs\n') + logging.info(' Exiting ProcessArgs\n') return FileType, DirProcessing, PrefixDir, Path, File, SrcDir, DstDir # End of def ProcessArgs(Argv, Errors): + def ProcessDirArgs(argv, Errors): - logging.info (' Entering ProcessDirArgs\n') + logging.info(' Entering ProcessDirArgs\n') - # Clear the return variables in case of error. + # Clear the return variables in case of error. DirProcessing = 'N' @@ -309,9 +331,10 @@ def ProcessDirArgs(argv, Errors): if not os.path.isdir(SrcDir): - Errors.append('Usage: {0:s} src_dir dst_dir\n\nsrc_dir {1:s} isn\'t a directory\n'.format(sys.argv[0], SrcDir)) + Errors.append('Usage: {0:s} src_dir dst_dir\n\nsrc_dir {1:s} isn\'t a directory\n'.format( + sys.argv[0], SrcDir)) - logging.info (' Exiting ProcessDirArgs src dir error\n') + logging.info(' Exiting ProcessDirArgs src dir error\n') return DirProcessing, PrefixDir, Path, File, SrcDir, DstDir @@ -321,9 +344,10 @@ def ProcessDirArgs(argv, Errors): if not os.path.isdir(DstDir): - Errors.append('Usage: {0:s} src_dir dst_dir\n\ndst_dir {1:s} Isn\'t a directory\n'.format(sys.argv[0], DstDir)) + Errors.append('Usage: {0:s} src_dir dst_dir\n\ndst_dir {1:s} Isn\'t a directory\n'.format( + sys.argv[0], DstDir)) - logging.info (' Exiting ProcessDirArgs dst dir error\n') + logging.info(' Exiting ProcessDirArgs dst dir error\n') return DirProcessing, PrefixDir, Path, File, SrcDir, DstDir @@ -333,9 +357,10 @@ def ProcessDirArgs(argv, Errors): if os.listdir(DstDir) != []: - Errors.append('Error 13: dst dir\n\n{0:s}\n\nmust be empty and it is not\n'.format(str(DstDir))) + Errors.append( + 'Error 13: dst dir\n\n{0:s}\n\nmust be empty and it is not\n'.format(str(DstDir))) - logging.info (' Exiting ProcessDirArgs dst dir not empty error\n') + logging.info(' Exiting ProcessDirArgs dst dir not empty error\n') return DirProcessing, PrefixDir, Path, File, SrcDir, DstDir @@ -346,162 +371,177 @@ def ProcessDirArgs(argv, Errors): SplitDir = os.path.split(SrcDir) - logging.debug (' ProcessDirArgs: SplitDir %s\n', SplitDir) + logging.debug(' ProcessDirArgs: SplitDir %s\n', SplitDir) if SplitDir[1] == '' or SplitDir[1] == '.' or SplitDir[1] == '..': - Errors.append('Error 10: There must be a directory that is not \'.\' or \'..\' in the input name for\na fzp file in order to find the svg files.\n') + Errors.append( + 'Error 10: There must be a directory that is not \'.\' or \'..\' in the input name for\na fzp file in order to find the svg files.\n') - logging.info (' Exiting ProcessDirArgs no prefix dir error\n') + logging.info(' Exiting ProcessDirArgs no prefix dir error\n') return DirProcessing, PrefixDir, Path, File, SrcDir, DstDir else: - + Path = SplitDir[0] - - PrefixDir = SplitDir[1] + + PrefixDir = SplitDir[1] if PrefixDir == None: - # Insure PrefixDir has a string value for the directory routines. + # Insure PrefixDir has a string value for the directory routines. PrefixDir = "" # End of if PrefixDir == None: - DstFzpDir = os.path.join(DstDir,PrefixDir) + DstFzpDir = os.path.join(DstDir, PrefixDir) - try: + try: os.makedirs(DstFzpDir) except os.error as e: - Errors.append('Error 14: Creating dir\n\n{0:s} {1:s} \({2:s}\)\n'.format(DstFzpDir), e.strerror, str(e.errno)) + Errors.append('Error 14: Creating dir\n\n{0:s} {1:s} \({2:s}\)\n'.format( + DstFzpDir), e.strerror, str(e.errno)) - logging.info (' Exiting ProcessDirArgs dir on error %s\n',e.strerror) + logging.info( + ' Exiting ProcessDirArgs dir on error %s\n', e.strerror) return DirProcessing, PrefixDir, Path, File, SrcDir, DstDir # End of try: - - logging.debug (' ProcessDirArgs: mkdir %s\n',DstFzpDir) - + + logging.debug(' ProcessDirArgs: mkdir %s\n', DstFzpDir) + # The fzp directory was created so create the base svg directory - + DstSvgDir = os.path.join(DstDir, 'svg') - - try: - + + try: + os.makedirs(DstSvgDir) except os.error as e: - Errors.append('Error 14: Creating dir\n\n{0:s} {1:s} \({2:s}\)\n'.format(DstFzpDir), e.strerror, str(e.errno)) + Errors.append('Error 14: Creating dir\n\n{0:s} {1:s} \({2:s}\)\n'.format( + DstFzpDir), e.strerror, str(e.errno)) - logging.info (' Exiting ProcessDirArgs dir on error %s\n',e.strerror) + logging.info( + ' Exiting ProcessDirArgs dir on error %s\n', e.strerror) return DirProcessing, PrefixDir, Path, File, SrcDir, DstDir # End of try: - - logging.debug (' ProcessDirArgs: mkdir %s\n',DstSvgDir) - + + logging.debug(' ProcessDirArgs: mkdir %s\n', DstSvgDir) + DstSvgDir = os.path.join(DstSvgDir, PrefixDir) - - try: - + + try: + os.makedirs(DstSvgDir) except os.error as e: - Errors.append('Error 14: Creating dir\n\n{0:s} {1:s} \({2:s}\)\n'.format(DstFzpDir), e.strerror, str(e.errno)) + Errors.append('Error 14: Creating dir\n\n{0:s} {1:s} \({2:s}\)\n'.format( + DstFzpDir), e.strerror, str(e.errno)) - logging.info (' Exiting ProcessDirArgs dir on error %s\n',e.strerror) + logging.info( + ' Exiting ProcessDirArgs dir on error %s\n', e.strerror) return DirProcessing, PrefixDir, Path, File, SrcDir, DstDir # End of try: - - logging.debug (' ProcessDirArgs: mkdir %s\n', DstSvgDir) - + + logging.debug(' ProcessDirArgs: mkdir %s\n', DstSvgDir) + # then the four svg direcotries - + SvgDir = os.path.join(DstSvgDir, 'breadboard') - - try: - + + try: + os.makedirs(SvgDir) except os.error as e: - Errors.append('Error 14: Creating dir\n\n{0:s} {1:s} \({2:s}\)\n'.format(DstFzpDir), e.strerror, str(e.errno)) + Errors.append('Error 14: Creating dir\n\n{0:s} {1:s} \({2:s}\)\n'.format( + DstFzpDir), e.strerror, str(e.errno)) - logging.info (' Exiting ProcessDirArgs dir on error %s\n',e.strerror) + logging.info( + ' Exiting ProcessDirArgs dir on error %s\n', e.strerror) return DirProcessing, PrefixDir, Path, File, SrcDir, DstDir # End of try: - + logging.debug(' ProcessDirArgs: mkdir %s\n', SvgDir) - + SvgDir = os.path.join(DstSvgDir, 'icon') - - try: - + + try: + os.makedirs(SvgDir) except os.error as e: - Errors.append('Error 14: Creating dir\n\n{0:s} {1:s} \({2:s}\)\n'.format(DstFzpDir), e.strerror, str(e.errno)) + Errors.append('Error 14: Creating dir\n\n{0:s} {1:s} \({2:s}\)\n'.format( + DstFzpDir), e.strerror, str(e.errno)) - logging.info (' Exiting ProcessDirArgs dir on error %s\n',e.strerror) + logging.info( + ' Exiting ProcessDirArgs dir on error %s\n', e.strerror) return DirProcessing, PrefixDir, Path, File, SrcDir, DstDir # End of try: - + logging.debug(' ProcessDirArgs: mkdir %s\n', SvgDir) - + SvgDir = os.path.join(DstSvgDir, 'pcb') - - try: - + + try: + os.makedirs(SvgDir) except os.error as e: - Errors.append('Error 14: Creating dir\n\n{0:s} {1:s} \({2:s}\)\n'.format(DstFzpDir), e.strerror, str(e.errno)) + Errors.append('Error 14: Creating dir\n\n{0:s} {1:s} \({2:s}\)\n'.format( + DstFzpDir), e.strerror, str(e.errno)) - logging.info (' Exiting ProcessDirArgs dir on error %s\n',e.strerror) + logging.info( + ' Exiting ProcessDirArgs dir on error %s\n', e.strerror) return DirProcessing, PrefixDir, Path, File, SrcDir, DstDir # End of try: - + logging.debug(' ProcessDirArgs: mkdir %s\n', SvgDir) - + SvgDir = os.path.join(DstSvgDir, 'schematic') - - try: - + + try: + os.makedirs(SvgDir) except os.error as e: - Errors.append('Error, Creating dir {0:s} {1:s} ({2:s})\n'.format(DstFzpDir), e.strerror, str(e.errno)) + Errors.append('Error, Creating dir {0:s} {1:s} ({2:s})\n'.format( + DstFzpDir), e.strerror, str(e.errno)) - logging.info (' Exiting ProcessDirArgs dir on error %s\n',e.strerror) + logging.info( + ' Exiting ProcessDirArgs dir on error %s\n', e.strerror) return DirProcessing, PrefixDir, Path, File, SrcDir, DstDir # End of try: - + logging.debug(' ProcessDirArgs: mkdir %s\n', SvgDir) # End of if SplitDir[1] == '' or SplitDir[1] == '.' or SplitDir[1] == '..': - + # If we get here we have a src and dst directory plus all the required new # dst directories so return all that to the calling routine. Set # DirProcessing to 'Y' to indicate success. @@ -509,37 +549,40 @@ def ProcessDirArgs(argv, Errors): DirProcessing, = 'Y' # Then set FileType to 'dir' from None to not cause a silent error exit - # on return. + # on return. FileType = 'dir' - logging.debug (' ProcessDirArgs returning DirProcessing %s PrefixDir %s Path %s File %s SrcDir %s DstDir %s\n', DirProcessing, PrefixDir, Path, File, SrcDir, DstDir) + logging.debug(' ProcessDirArgs returning DirProcessing %s PrefixDir %s Path %s File %s SrcDir %s DstDir %s\n', + DirProcessing, PrefixDir, Path, File, SrcDir, DstDir) - logging.info (' Exiting ProcessDirArgs\n') + logging.info(' Exiting ProcessDirArgs\n') return DirProcessing, PrefixDir, Path, File, SrcDir, DstDir # End of def ProcessDirArgs(Argv, Errors): + def PopTag(TagStack, Level): # Determine from the current level if the value on the tag stack is still # in scope. If it is not, then remove the value from the stack. - logging.info (' Entering PopTag Level %s\n', Level) + logging.info(' Entering PopTag Level %s\n', Level) logging.debug(' PopTag: entry TagStack %s Level %s\n', TagStack, Level) Tag, StackLevel = TagStack[len(TagStack) - 1] # Because we may have exited several recusion levels before calling this - # delete all the tags below the current level. + # delete all the tags below the current level. while Level != 0 and StackLevel >= Level: # Pop the last item from the stack. - logging.debug(' PopTag: popped Tag %s, StackLevel %s\n', Tag, StackLevel ) + logging.debug(' PopTag: popped Tag %s, StackLevel %s\n', + Tag, StackLevel) TagStack.pop(len(TagStack) - 1) @@ -549,13 +592,14 @@ def PopTag(TagStack, Level): logging.debug(' PopTag: exit TagStack %s Level %s\n', TagStack, Level) - logging.info (' Exiting PopTag Level %s\n', Level) + logging.info(' Exiting PopTag Level %s\n', Level) # End of def PopTag(Elem, TagStack, Level): + def BackupFilename(InFile, Errors): - logging.info (' Entering BackupFilename\n') + logging.info(' Entering BackupFilename\n') # First set the appropriate output file name None for an error condition. @@ -565,17 +609,18 @@ def BackupFilename(InFile, Errors): # Then try and rename the input file to InFile.bak - os.rename (InFile, InFile + '.bak') + os.rename(InFile, InFile + '.bak') except os.error as e: - Errors.append('Error 15: Can not rename\n\n\'{0:s}\'\n\nto\n\n\'{1:s}\'\n\n\'{2:s}\'\n\n{3:s} ({4:s})\n'.format(str(InFile), str(InFile + '.bak'), str( e.filename), e.strerror, str(e.errno))) + Errors.append('Error 15: Can not rename\n\n\'{0:s}\'\n\nto\n\n\'{1:s}\'\n\n\'{2:s}\'\n\n{3:s} ({4:s})\n'.format( + str(InFile), str(InFile + '.bak'), str(e.filename), e.strerror, str(e.errno))) return InFile, OutFile # End of try: - # If we get here, then the file was successfully renamed so change the + # If we get here, then the file was successfully renamed so change the # filenames and return. OutFile = InFile @@ -584,70 +629,82 @@ def BackupFilename(InFile, Errors): return InFile, OutFile - logging.info (' Exiting BackupFilename\n') + logging.info(' Exiting BackupFilename\n') # End of def BackupFilename(InFile, Errors): + def DupNameError(InFile, Id, Elem, Errors): - logging.info (' Entering DupNameError:\n') + logging.info(' Entering DupNameError:\n') + + logging.debug( + ' DupNameError: Entry InFile %s Id %s Elem %s Errors %s\n', InFile, Id, Elem, Errors) - logging.debug (' DupNameError: Entry InFile %s Id %s Elem %s Errors %s\n', InFile, Id, Elem, Errors) + # Log duplicate name error - # Log duplicate name error + Errors.append('Error 16: File\n\'{0:s}\'\nAt line {1:s}\n\nId {2:s} present more than once (and should be unique)\n'.format( + str(InFile), str(Elem.sourceline), str(Id))) - Errors.append('Error 16: File\n\'{0:s}\'\nAt line {1:s}\n\nId {2:s} present more than once (and should be unique)\n'.format(str(InFile), str(Elem.sourceline), str(Id))) + logging.info(' Exiting DupNameError\n') - logging.info (' Exiting DupNameError\n') +# End of def DupNameError(InFile, Id, Elem, Errors): -#End of def DupNameError(InFile, Id, Elem, Errors): def DupNameWarning(InFile, Id, Elem, Warnings): - logging.info (' Entering DupNameWarning:\n') + logging.info(' Entering DupNameWarning:\n') - logging.debug (' DupNameWarning: Entry InFile %s Id %s Elem %s Errors %s\n', InFile, Id, Elem, Warnings) + logging.debug(' DupNameWarning: Entry InFile %s Id %s Elem %s Errors %s\n', + InFile, Id, Elem, Warnings) # Log duplicate name warning - Warnings.append('Warning 28: File\n\'{0:s}\'\nAt line {1:s}\n\nname {2:s} present more than once (and should be unique)\n'.format(str(InFile), str(Elem.sourceline), str(Id))) + Warnings.append('Warning 28: File\n\'{0:s}\'\nAt line {1:s}\n\nname {2:s} present more than once (and should be unique)\n'.format( + str(InFile), str(Elem.sourceline), str(Id))) + + logging.info(' Exiting DupNameWarning\n') - logging.info (' Exiting DupNameWarning\n') +# End of def DupNameWarning(InFile, Id, Elem, Warnings): -#End of def DupNameWarning(InFile, Id, Elem, Warnings): def ProcessTree(FzpType, FileType, InFile, OutFile, CurView, PrefixDir, Elem, Errors, Warnings, Info, FzpDict, TagStack, State, InheritedAttributes, Debug, Level=0): - # Potentially recursively process the element nodes of an lxml tree to + # Potentially recursively process the element nodes of an lxml tree to # aquire the information we need to check file integrity. This routine gets # called recursively to process child nodes (other routines get called for - # leaf node processing). + # leaf node processing). - logging.info (' Entering ProcessTree FileType %s InFile %s Level %s\n', FileType, InFile, Level) - - logging.debug (' **** ProcessTree: Source line %s Elem len %s Level %s\nTag %s\nattributes\n%s\ntext %s\nFzpType %s FileType %s InFile %s OutFile %s CurView %s PrefixDir %s Errors %s Warnings %s Info %s TagStack %s State %s InheritedAttributes %s\n', Elem.sourceline, len(Elem), Level, Elem.tag, Elem.attrib, Elem.text, FzpType, FileType, InFile, OutFile, CurView, PrefixDir, Errors, Warnings, Info, TagStack, State, InheritedAttributes) + logging.info( + ' Entering ProcessTree FileType %s InFile %s Level %s\n', FileType, InFile, Level) + logging.debug(' **** ProcessTree: Source line %s Elem len %s Level %s\nTag %s\nattributes\n%s\ntext %s\nFzpType %s FileType %s InFile %s OutFile %s CurView %s PrefixDir %s Errors %s Warnings %s Info %s TagStack %s State %s InheritedAttributes %s\n', + Elem.sourceline, len(Elem), Level, Elem.tag, Elem.attrib, Elem.text, FzpType, FileType, InFile, OutFile, CurView, PrefixDir, Errors, Warnings, Info, TagStack, State, InheritedAttributes) # Start by checking for non whitespace charactes in tail (which is likely - # an error) and flag the line if present. + # an error) and flag the line if present. Tail = Elem.tail - logging.debug (' ProcessTree: Tail = \'%s\'\n', Tail) + logging.debug(' ProcessTree: Tail = \'%s\'\n', Tail) + + if Tail != None and not Tail.isspace(): - if Tail != None and not Tail.isspace(): + Warnings.append('Warning 2: File\n\'{0:s}\'\nAt line {1:s}\n\nText \'{2:s}\' isn\'t white space and may cause a problem\n'.format( + str(InFile), str(Elem.sourceline), str(Tail))) - Warnings.append('Warning 2: File\n\'{0:s}\'\nAt line {1:s}\n\nText \'{2:s}\' isn\'t white space and may cause a problem\n'.format(str(InFile), str(Elem.sourceline), str(Tail))) - - # End of if not Elem.tail.isspace(): + # End of if not Elem.tail.isspace(): if len(Elem): - logging.debug (' ProcessTree: Procees parent node attributes Source line %s len %s Level %s tag %s\n', Elem.sourceline, len(Elem), Level, Elem.tag) + logging.debug(' ProcessTree: Procees parent node attributes Source line %s len %s Level %s tag %s\n', + Elem.sourceline, len(Elem), Level, Elem.tag) - ProcessLeafNode(FzpType, FileType, InFile, OutFile, CurView, PrefixDir, Elem, Errors, Warnings, Info, FzpDict, TagStack, State, InheritedAttributes, Debug, Level) + ProcessLeafNode(FzpType, FileType, InFile, OutFile, CurView, PrefixDir, Elem, Errors, + Warnings, Info, FzpDict, TagStack, State, InheritedAttributes, Debug, Level) - logging.debug (' ProcessTree: Child nodes Source line %s len %s Level %s tag %s\n', Elem.sourceline, len(Elem), Level, Elem.tag) + logging.debug(' ProcessTree: Child nodes Source line %s len %s Level %s tag %s\n', + Elem.sourceline, len(Elem), Level, Elem.tag) # This node has children so recurse down the tree to deal with them. @@ -655,77 +712,89 @@ def ProcessTree(FzpType, FileType, InFile, OutFile, CurView, PrefixDir, Elem, Er if len(Elem): - # this node has children so process them (the attributes of - # this node will be processed by the recursion call and the - # level will be increased by one.) + # this node has children so process them (the attributes of + # this node will be processed by the recursion call and the + # level will be increased by one.) - ProcessTree(FzpType, FileType, InFile, OutFile, CurView, PrefixDir, Elem, Errors, Warnings, Info, FzpDict, TagStack, State, InheritedAttributes, Debug, Level+1) + ProcessTree(FzpType, FileType, InFile, OutFile, CurView, PrefixDir, Elem, Errors, + Warnings, Info, FzpDict, TagStack, State, InheritedAttributes, Debug, Level + 1) - else: # This particular element in the for loop is a leaf node. + else: # This particular element in the for loop is a leaf node. - # As this is a leaf node proecess it again increasing the - # level by 1 before doing the call. + # As this is a leaf node proecess it again increasing the + # level by 1 before doing the call. - ProcessLeafNode(FzpType, FileType, InFile, OutFile, CurView, PrefixDir, Elem, Errors, Warnings, Info, FzpDict, TagStack, State, InheritedAttributes, Debug, Level+1) + ProcessLeafNode(FzpType, FileType, InFile, OutFile, CurView, PrefixDir, Elem, Errors, + Warnings, Info, FzpDict, TagStack, State, InheritedAttributes, Debug, Level + 1) # End of if len(Elem): # End of for Elem in Elem: else: - + # This is a leaf node and thus the level needs to be increased by 1 - # before we process it. + # before we process it. - ProcessLeafNode(FzpType, FileType, InFile, OutFile, CurView, PrefixDir, Elem, Errors, Warnings, Info, FzpDict, TagStack, State, InheritedAttributes, Debug, Level+1) + ProcessLeafNode(FzpType, FileType, InFile, OutFile, CurView, PrefixDir, Elem, Errors, + Warnings, Info, FzpDict, TagStack, State, InheritedAttributes, Debug, Level + 1) # end of if len(Elem): - logging.info (' Exiting ProcessTree Level %s\n', Level) + logging.info(' Exiting ProcessTree Level %s\n', Level) + +# End of def ProcessTree(FzpType, FileType, InFile, OutFile, CurView, +# PrefixDir, Elem, Errors, Warnings, Info, FzpDict, TagStack, State, +# InheritedAttributes, Debug, Level=0): -# End of def ProcessTree(FzpType, FileType, InFile, OutFile, CurView, PrefixDir, Elem, Errors, Warnings, Info, FzpDict, TagStack, State, InheritedAttributes, Debug, Level=0): def ProcessLeafNode(FzpType, FileType, InFile, OutFile, CurView, PrefixDir, Elem, Errors, Warnings, Info, FzpDict, TagStack, State, InheritedAttributes, Debug, Level): - logging.info (' Entering ProcessLeafNode FileType %s Level %s\n', FileType, Level) + logging.info( + ' Entering ProcessLeafNode FileType %s Level %s\n', FileType, Level) - logging.debug (' ProcessLeafNode: FzpType %s FileType %s InFile %s CurView %s Errors %s\n', FzpType, FileType, InFile,CurView, Errors) + logging.debug(' ProcessLeafNode: FzpType %s FileType %s InFile %s CurView %s Errors %s\n', + FzpType, FileType, InFile, CurView, Errors) # Start by checking for non whitespace charactes in tail (which is likely - # an error) and flag the line if present. + # an error) and flag the line if present. Tail = Elem.tail - logging.debug (' ProcessLeafNode: Tail = \'%s\'\n', Tail) + logging.debug(' ProcessLeafNode: Tail = \'%s\'\n', Tail) + + if Tail != None and not Tail.isspace(): - if Tail != None and not Tail.isspace(): + Warnings.append('Warning 2: File\n\'{0:s}\'\nAt line {1:s}\n\nText \'{2:s}\' isn\'t white space and may cause a problem\n'.format( + str(InFile), str(Elem.sourceline), str(Tail))) - Warnings.append('Warning 2: File\n\'{0:s}\'\nAt line {1:s}\n\nText \'{2:s}\' isn\'t white space and may cause a problem\n'.format(str(InFile), str(Elem.sourceline), str(Tail))) - - # End of if not Elem.tail.isspace(): + # End of if not Elem.tail.isspace(): # Select the appropriate leaf node processing routing based on the FileType - # variable. + # variable. + + if FileType == 'FZPFRITZ' or FileType == 'FZPPART': - if FileType == 'FZPFRITZ' or FileType == 'FZPPART': + # If this is a fzp file do the leaf node processing for that. - # If this is a fzp file do the leaf node processing for that. + ProcessFzpLeafNode(FzpType, FileType, InFile, CurView, PrefixDir, + Elem, Errors, Warnings, Info, FzpDict, TagStack, State, Level) - ProcessFzpLeafNode(FzpType, FileType, InFile, CurView, PrefixDir, Elem, Errors, Warnings, Info, FzpDict, TagStack, State, Level) - elif FileType == 'SVG': - ProcessSvgLeafNode(FzpType, FileType, InFile, CurView, PrefixDir, Elem, Errors, Warnings, Info, FzpDict, TagStack, State, InheritedAttributes, Level) + ProcessSvgLeafNode(FzpType, FileType, InFile, CurView, PrefixDir, Elem, Errors, + Warnings, Info, FzpDict, TagStack, State, InheritedAttributes, Level) else: if not 'SoftwareError' in State: # Report the software error once, then set 'SoftwareError' in State - # to supress more messages and just return. It won't work right - # but the problem will at least be reported. + # to supress more messages and just return. It won't work right + # but the problem will at least be reported. - Errors.append('Error 19: File\n\'{0:s}\'\n\nFile type {1:s} is an unknown format (software error)\n'.format(str(InFile), str(FileType))) + Errors.append('Error 19: File\n\'{0:s}\'\n\nFile type {1:s} is an unknown format (software error)\n'.format( + str(InFile), str(FileType))) State['SoftwareError'] = 'y' @@ -733,59 +802,66 @@ def ProcessLeafNode(FzpType, FileType, InFile, OutFile, CurView, PrefixDir, Elem # End of if FileType == 'FZPFRITZ' or FileType == 'FZPPART': - logging.info (' Exiting ProcessLeafNode Level %s\n', Level) + logging.info(' Exiting ProcessLeafNode Level %s\n', Level) + +# End of def ProcessLeafNode(FzpType, InFile, OutFile, CurView, PrefixDir, +# Elem, Errors, Warnings, Info, FzpDict, TagStack, State, +# InheritedAttributes, Debug, Level): -# End of def ProcessLeafNode(FzpType, InFile, OutFile, CurView, PrefixDir, Elem, Errors, Warnings, Info, FzpDict, TagStack, State, InheritedAttributes, Debug, Level): def ProcessFzp(DirProcessing, FzpType, FileType, InFile, OutFile, CurView, PrefixDir, Errors, Warnings, Info, FzpDict, FilesProcessed, TagStack, State, InheritedAttributes, Debug): - logging.info (' Entering ProcessFzp FzpType %s FileType %s InFile %s\n', FzpType, FileType, InFile) + logging.info(' Entering ProcessFzp FzpType %s FileType %s InFile %s\n', + FzpType, FileType, InFile) - logging.debug (' ProcessFzp: FzpType %s FileType %s InFile %s OutFile %s CurView %s PrefixDir %s Errors %s Warnings %s Info %s FzpDict %s TagStack %s State %s InheritedAttributes %s Debug %s\n', FzpType, FileType, InFile, OutFile, CurView, PrefixDir, Errors, Warnings, Info, FzpDict, TagStack, State, InheritedAttributes, Debug) + logging.debug(' ProcessFzp: FzpType %s FileType %s InFile %s OutFile %s CurView %s PrefixDir %s Errors %s Warnings %s Info %s FzpDict %s TagStack %s State %s InheritedAttributes %s Debug %s\n', + FzpType, FileType, InFile, OutFile, CurView, PrefixDir, Errors, Warnings, Info, FzpDict, TagStack, State, InheritedAttributes, Debug) # Parse the input document. - Doc, Root = PP.ParseFile (InFile, Errors) + Doc, Root = PP.ParseFile(InFile, Errors) - logging.debug (' ProcessFzp: return from parse Doc %s\n', Doc) + logging.debug(' ProcessFzp: return from parse Doc %s\n', Doc) if Doc != None: # We have successfully parsed the input document so process it. Since # We don't yet have a CurView, set it to None. - logging.debug (' ProcessFzp: Calling ProceesTree Doc %s\n', Doc) + logging.debug(' ProcessFzp: Calling ProceesTree Doc %s\n', Doc) - # Set the local output file to a value in case we don't use it but - # do test it. + # Set the local output file to a value in case we don't use it but + # do test it. FQOutFile = None if OutFile == None: if Debug == 0: - + # No output file indicates we are processing a single fzp file # so rename the src file to .bak and use the original src file # as the output file (assuming the rename is successfull). # Use FQOutFile as the new file name to preserve the value - # of OutFile for svg processing later. - + # of OutFile for svg processing later. + InFile, FQOutFile = BackupFilename(InFile, Errors) - - logging.debug (' ProcessFzp: After BackupFilename(InFile, Errors) InFile %s FQOutFile %s\n', InFile, FQOutFile) - + + logging.debug( + ' ProcessFzp: After BackupFilename(InFile, Errors) InFile %s FQOutFile %s\n', InFile, FQOutFile) + if FQOutFile == None: - + # An error occurred, so just return to indicate that without # writing the file (as there is no where to write it to). - - logging.info (' ProcessFzp: Exiting ProcessFzp after rename error\n') - + + logging.info( + ' ProcessFzp: Exiting ProcessFzp after rename error\n') + return - + # End of if FQOutFile == None: - + # End of if Debug == 0: else: @@ -799,68 +875,80 @@ def ProcessFzp(DirProcessing, FzpType, FileType, InFile, OutFile, CurView, Prefi # Now that we have an appropriate input file name, process the tree. # (we won't get here if there is a file rename error above!) - logging.debug (' ProcessFzp: before ProcessTree FileType %s FQOutFile %s\n', FileType, FQOutFile) + logging.debug( + ' ProcessFzp: before ProcessTree FileType %s FQOutFile %s\n', FileType, FQOutFile) - ProcessTree(FzpType, FileType, InFile, FQOutFile, None, PrefixDir, Root, Errors, Warnings, Info, FzpDict, TagStack, State, InheritedAttributes, Debug) + ProcessTree(FzpType, FileType, InFile, FQOutFile, None, PrefixDir, Root, Errors, + Warnings, Info, FzpDict, TagStack, State, InheritedAttributes, Debug) - logging.debug (' ProcessFzp: After ProcessTree FileType %s FQOutFile %s\n', FileType, FQOutFile) + logging.debug( + ' ProcessFzp: After ProcessTree FileType %s FQOutFile %s\n', FileType, FQOutFile) # We are at the end of processing the fzp file so check that the # connector numbers are contiguous. - FzpCheckConnectors(InFile, Root, FzpDict, Errors, Warnings, Info, State) - # We have an output file name so write the fzp file to it (or the + FzpCheckConnectors(InFile, Root, FzpDict, + Errors, Warnings, Info, State) + # We have an output file name so write the fzp file to it (or the # console if Debug is > 0.) - logging.debug (' ProcessFzp: Prettyprint FQOutFile %s FileType %s\n', FQOutFile, FileType) + logging.debug( + ' ProcessFzp: Prettyprint FQOutFile %s FileType %s\n', FQOutFile, FileType) - PP.OutputTree(Doc, Root, FileType, InFile, FQOutFile, Errors, Warnings, Info, Debug) + PP.OutputTree(Doc, Root, FileType, InFile, FQOutFile, + Errors, Warnings, Info, Debug) # Then process the associatted svg files from the fzp. - logging.debug (' ProcessFzp: Calling ProcessSvgsFromFzp DirProcessing %s FzpType %s FileType %s InFile %s OutFile %s PrefixDir %s Errors %s Warnings %s Info %s FzpDict %s Debug %s\n', DirProcessing, FzpType, FileType, InFile, OutFile, PrefixDir, Errors, Warnings, Info, FzpDict, Debug) - + logging.debug(' ProcessFzp: Calling ProcessSvgsFromFzp DirProcessing %s FzpType %s FileType %s InFile %s OutFile %s PrefixDir %s Errors %s Warnings %s Info %s FzpDict %s Debug %s\n', + DirProcessing, FzpType, FileType, InFile, OutFile, PrefixDir, Errors, Warnings, Info, FzpDict, Debug) - # Use the original value of OutFile to process the svgs. + # Use the original value of OutFile to process the svgs. - ProcessSvgsFromFzp(DirProcessing, FzpType, FileType, InFile, OutFile, PrefixDir, Errors, Warnings, Info, FzpDict, FilesProcessed, Debug) + ProcessSvgsFromFzp(DirProcessing, FzpType, FileType, InFile, OutFile, + PrefixDir, Errors, Warnings, Info, FzpDict, FilesProcessed, Debug) # End of if Doc != None: - - logging.info (' Exiting ProcessFzp\n') -# End of def ProcessFzp(DirProcessing, FzpType, FileType, InFile, OutFile, CurView, PrefixDir, Errors, Warnings, Info, FzpDict, FilesProcessed, TagStack, State, InheritedAttributes, Debug): + logging.info(' Exiting ProcessFzp\n') + +# End of def ProcessFzp(DirProcessing, FzpType, FileType, InFile, OutFile, +# CurView, PrefixDir, Errors, Warnings, Info, FzpDict, FilesProcessed, +# TagStack, State, InheritedAttributes, Debug): + def ProcessSvgsFromFzp(DirProcessing, FzpType, FileType, InFile, OutFile, PrefixDir, Errors, Warnings, Info, FzpDict, FilesProcessed, Debug): # Process the svg files referenced in the FzpDict created from a Fritzing # .fzp file. - logging.info (' Entering ProcessSvgsFromFzp DirProcessing %s FzpType %s FileType %s InFile %s\n', DirProcessing, FzpType, FileType, InFile) + logging.info(' Entering ProcessSvgsFromFzp DirProcessing %s FzpType %s FileType %s InFile %s\n', + DirProcessing, FzpType, FileType, InFile) - logging.debug (' ProcessSvgsFromFzp: OutFile %s PrefixDir %s FzpDict %s\n', OutFile, PrefixDir, FzpDict) + logging.debug(' ProcessSvgsFromFzp: OutFile %s PrefixDir %s FzpDict %s\n', + OutFile, PrefixDir, FzpDict) - # First we need to determine the directory structure / filename for the - # svg files as there are several to choose from: uncompressed parts which - # are all in the same directory but with odd prefixes of - # svg.layer.filename or in a Fritzing directory which will be + # First we need to determine the directory structure / filename for the + # svg files as there are several to choose from: uncompressed parts which + # are all in the same directory but with odd prefixes of + # svg.layer.filename or in a Fritzing directory which will be # ../svg/PrefixDir/layername/filename in 4 different directories. In # addition we may be processing a single fzp file (in which case the input # file needs a '.bak' appended to it), or directory of fzp files in which - # case the '.bak' isn't needed. We will form appropriate file names from - # the InFile, OutFile and PrefixDir arguments to feed to the svg - # processing routine. + # case the '.bak' isn't needed. We will form appropriate file names from + # the InFile, OutFile and PrefixDir arguments to feed to the svg + # processing routine. # Insure FQOutFile has a value FQOutFile = None - # Get the path from the input and output files (which will be the fzp file - # at this point.) + # Get the path from the input and output files (which will be the fzp file + # at this point.) InPath = os.path.dirname(InFile) - # Record in FilesProcessed that we have processed this file name in case + # Record in FilesProcessed that we have processed this file name in case # this is a directory operation. Get just the file name. BaseFile = os.path.basename(InFile) @@ -869,81 +957,89 @@ def ProcessSvgsFromFzp(DirProcessing, FzpType, FileType, InFile, OutFile, Prefix # If we have already processed it, flag an error (should not occur). - logging.debug (' ProcessSvgsFromFzp: InFile %s Error 87 issued\n', InFile) + logging.debug( + ' ProcessSvgsFromFzp: InFile %s Error 87 issued\n', InFile) - Errors.append('Error 87: File\n\'{0:s}\'\n\nFile has already been processed (software error)\n'.format(str(InFile))) + Errors.append( + 'Error 87: File\n\'{0:s}\'\n\nFile has already been processed (software error)\n'.format(str(InFile))) - logging.info (' Exiting ProcessSvgsFromFzp on already processed error\n') + logging.info( + ' Exiting ProcessSvgsFromFzp on already processed error\n') return - + else: - # Mark that we have processed this file. + # Mark that we have processed this file. FilesProcessed['processed.' + InFile] = 'y' - logging.debug (' ProcessSvgsFromFzp: InFile %s marked as processed\n', InFile) + logging.debug( + ' ProcessSvgsFromFzp: InFile %s marked as processed\n', InFile) # End of if 'processed.' + InFile in FilesProcessed: - logging.debug (' ProcessSvgsFromFzp: InPath %s InFile %s', InPath, InFile) + logging.debug(' ProcessSvgsFromFzp: InPath %s InFile %s', InPath, InFile) if OutFile == None: OutPath = '' - logging.debug (' ProcessSvgsFromFzp: OutPath %s OutFile %s', OutPath, OutFile) + logging.debug( + ' ProcessSvgsFromFzp: OutPath %s OutFile %s', OutPath, OutFile) else: OutPath = os.path.dirname(OutFile) - logging.debug (' ProcessSvgsFromFzp: OutPath %s OutFile %s', OutPath, OutFile) + logging.debug( + ' ProcessSvgsFromFzp: OutPath %s OutFile %s', OutPath, OutFile) # End of if OutFile == None: for CurView in FzpDict['views']: - logging.debug (' ProcessSvgsFromFzp: Process View %s FileType %s FzpDict[views] %s\n', CurView, FileType, FzpDict['views']) + logging.debug( + ' ProcessSvgsFromFzp: Process View %s FileType %s FzpDict[views] %s\n', CurView, FileType, FzpDict['views']) # Extract just the image name as a string from the list entry. Image = ''.join(FzpDict[CurView + '.image']) - logging.debug (' ProcessSvgsFromFzp 1: CurView %s Image %s FzpType %s FileType %s OutFile %s\n', CurView, Image, FzpType, FileType, OutFile) + logging.debug(' ProcessSvgsFromFzp 1: CurView %s Image %s FzpType %s FileType %s OutFile %s\n', + CurView, Image, FzpType, FileType, OutFile) - # indicate we haven't seen an output file rename error. + # indicate we haven't seen an output file rename error. OutFileError = 'n' if FzpType == 'FZPPART': - # The svg is of the form svg.layer.filename in the directory - # pointed to by Path. So append a svg. to the file name and - # convert the '/' to a '.' to form the file name for processing. + # The svg is of the form svg.layer.filename in the directory + # pointed to by Path. So append a svg. to the file name and + # convert the '/' to a '.' to form the file name for processing. Image = Image.replace(r"/", ".") if OutFile == None: - # Single file processing so set the output filename and use - # FQOutFile.bak as the input. Again preserve the original - # value of OutFile for processing later svg files. + # Single file processing so set the output filename and use + # FQOutFile.bak as the input. Again preserve the original + # value of OutFile for processing later svg files. Image = Image.replace(r"/", ".") FQOutFile = os.path.join(InPath, 'svg.' + Image) # Set the input file from the output file in case debug is non - # zero and we don't set a backup file. + # zero and we don't set a backup file. FQInFile = FQOutFile if Debug == 0: # If Debug isn't set then rename the input file and - # change the input file name. Otherwise leave it alone + # change the input file name. Otherwise leave it alone # (in this case OutFile is unused and output goes to the # console for debugging.) @@ -952,15 +1048,16 @@ def ProcessSvgsFromFzp(DirProcessing, FzpType, FileType, InFile, OutFile, Prefix if FQOutFile == None: # an error occurred renaming the input file so set an - # an OutFileError so we don't try and process this - # file as we have no valid output file to write it to. + # an OutFileError so we don't try and process this + # file as we have no valid output file to write it to. OutFileError = 'n' # End of if FQOutFile == None: - logging.debug (' ProcessSvgsFromFzp 2: FQInFile %s FQOutFile %s OutFileError %s\n', FQInFile, FQOutFile, OutFileError) - + logging.debug( + ' ProcessSvgsFromFzp 2: FQInFile %s FQOutFile %s OutFileError %s\n', FQInFile, FQOutFile, OutFileError) + # End of if Debug == 0: else: @@ -976,25 +1073,28 @@ def ProcessSvgsFromFzp(DirProcessing, FzpType, FileType, InFile, OutFile, Prefix elif FzpType == 'FZPFRITZ': - # The svg is of the form path../svg/PrefixDir/layername/filename, - # so prepend the appropriate path and use that as the file name. + # The svg is of the form path../svg/PrefixDir/layername/filename, + # so prepend the appropriate path and use that as the file name. - # First create the new end path as NewFile + # First create the new end path as NewFile # (i.e. '../svg/PrefixDir/Image') once, ready to append as needed. NewFile = '..' NewFile = os.path.join(NewFile, 'svg') - logging.debug (' ProcessSvgsFromFzp: after add svg NewFile %s PrefixDir %s\n', NewFile, PrefixDir) + logging.debug( + ' ProcessSvgsFromFzp: after add svg NewFile %s PrefixDir %s\n', NewFile, PrefixDir) NewFile = os.path.join(NewFile, PrefixDir) - logging.debug (' ProcessSvgsFromFzp: after add PrefixDir NewFile %s\n', NewFile) + logging.debug( + ' ProcessSvgsFromFzp: after add PrefixDir NewFile %s\n', NewFile) NewFile = os.path.join(NewFile, Image) - logging.debug (' ProcessSvgsFromFzp: after add Image NewFile %s\n', NewFile) + logging.debug( + ' ProcessSvgsFromFzp: after add Image NewFile %s\n', NewFile) # add the new end path to the end of the source path @@ -1005,19 +1105,20 @@ def ProcessSvgsFromFzp(DirProcessing, FzpType, FileType, InFile, OutFile, Prefix if Debug == 0: # If Debug isn't set then rename the input file and - # change the input file name. Otherwise leave it alone + # change the input file name. Otherwise leave it alone # (in this case OutFile is unused and output goes to the # console for debugging.) FQInFile, FQOutFile = BackupFilename(FQInFile, Errors) - logging.debug (' ProcessSvgsFromFzp: after rename FQInfile %s FQOutFile %s\n', FQInFile, FQOutFile) + logging.debug( + ' ProcessSvgsFromFzp: after rename FQInfile %s FQOutFile %s\n', FQInFile, FQOutFile) if FQOutFile == None: # an error occurred renaming the input file so set an - # an OutFileError so we don't try and process this - # file as we have no valid output file to write it to. + # an OutFileError so we don't try and process this + # file as we have no valid output file to write it to. OutFileError = 'y' @@ -1033,20 +1134,20 @@ def ProcessSvgsFromFzp(DirProcessing, FzpType, FileType, InFile, OutFile, Prefix else: - # dir to dir processing + # dir to dir processing FQInFile = os.path.join(InPath, NewFile) FQOutFile = os.path.join(OutPath, NewFile) - # End of if OutFile == None: else: # Software error! Shouldn't ever get here. - Errors.append('Error 19: File\n\'{0:s}\'\n\nFile type {1:s} is an unknown format (software error)\n'.format(str(InFile), str(FzpType))) + Errors.append('Error 19: File\n\'{0:s}\'\n\nFile type {1:s} is an unknown format (software error)\n'.format( + str(InFile), str(FzpType))) # Don't try and process further as will likely crash due to unset # variables. @@ -1055,13 +1156,15 @@ def ProcessSvgsFromFzp(DirProcessing, FzpType, FileType, InFile, OutFile, Prefix # End of if FzpType == 'FZPPART': - logging.debug (' ProcessSvgsFromFzp: FileType %s Process %s to %s\n', FileType, FQInFile, FQOutFile) + logging.debug(' ProcessSvgsFromFzp: FileType %s Process %s to %s\n', + FileType, FQInFile, FQOutFile) if not os.path.isfile(FQInFile): # The file doesn't exist so flag an error, - Errors.append('Error 20: File\n\'{0:s}\'\n\nDuring processing svgs from fzp, svg file doesn\'t exist\n'.format(str(FQInFile))) + Errors.append( + 'Error 20: File\n\'{0:s}\'\n\nDuring processing svgs from fzp, svg file doesn\'t exist\n'.format(str(FQInFile))) else: @@ -1074,7 +1177,8 @@ def ProcessSvgsFromFzp(DirProcessing, FzpType, FileType, InFile, OutFile, Prefix # get the path from the input file - logging.debug(' ProcessSvgsFromFzp: TmpPath %s TmpFile %s\n', TmpPath, TmpFile) + logging.debug( + ' ProcessSvgsFromFzp: TmpPath %s TmpFile %s\n', TmpPath, TmpFile) if TmpPath == '': @@ -1086,24 +1190,28 @@ def ProcessSvgsFromFzp(DirProcessing, FzpType, FileType, InFile, OutFile, Prefix if not TmpFile in os.listdir(TmpPath): - logging.debug(' ProcessSvgsFromFzp: dir names %s\n', os.listdir(TmpPath)) + logging.debug( + ' ProcessSvgsFromFzp: dir names %s\n', os.listdir(TmpPath)) - # File system case mismatch error. + # File system case mismatch error. - logging.debug(' ProcessSvgsFromFzp: InFile %s OutFile %s FzpType %s \n', InFile, OutFile, FzpType) + logging.debug( + ' ProcessSvgsFromFzp: InFile %s OutFile %s FzpType %s \n', InFile, OutFile, FzpType) if OutFile == None or DirProcessing == 'Y': # Then InFile is the fzp file. - Errors.append('Error 21: Svg file\n\n\'{0:s}\'\n\nHas a different case in the file system than in the fzp file\n\n\'{1:s}\'\n'.format(str(FQInFile), str(InFile))) + Errors.append('Error 21: Svg file\n\n\'{0:s}\'\n\nHas a different case in the file system than in the fzp file\n\n\'{1:s}\'\n'.format( + str(FQInFile), str(InFile))) else: - # Then OutFile is the fzp file (InFile will have .bak + # Then OutFile is the fzp file (InFile will have .bak # appended which we don't want.) - Errors.append('Error 21: Svg file\n\n\'{0:s}\'\n\nHas a different case in the file system than in the fzp file\n\n\'{1:s}\'\n'.format(str(FQInFile), str(OutFile))) + Errors.append('Error 21: Svg file\n\n\'{0:s}\'\n\nHas a different case in the file system than in the fzp file\n\n\'{1:s}\'\n'.format( + str(FQInFile), str(OutFile))) # End of if OutFile == None or DirProcessing == 'Y': @@ -1113,9 +1221,9 @@ def ProcessSvgsFromFzp(DirProcessing, FzpType, FileType, InFile, OutFile, Prefix if CurView == 'iconView': - # If this is iconview, don't do processing as we aren't - # going to check anything and sometimes the breadboard - # svg is reused which will cause a warning and replace + # If this is iconview, don't do processing as we aren't + # going to check anything and sometimes the breadboard + # svg is reused which will cause a warning and replace # the .bak file (which is undesirable). We do however # want to have the output file even though we didn't # do anything to it, so do copy the infile to the outfile @@ -1124,118 +1232,139 @@ def ProcessSvgsFromFzp(DirProcessing, FzpType, FileType, InFile, OutFile, Prefix if FQOutFile != None and Debug == 0: - # If Debug isn't 0, the file names are the same and - # will cause an exception during the copy. + # If Debug isn't 0, the file names are the same and + # will cause an exception during the copy. copyfile(FQInFile, FQOutFile) # End of if FQOutFile != None: - logging.debug (' ProcessSvgsFromFzp: Process View %s skipping iconview\n', CurView) + logging.debug( + ' ProcessSvgsFromFzp: Process View %s skipping iconview\n', CurView) continue # End of if CurView == 'iconview': - # Mark that we have processed this file in case this is - # directory processing of part.files to avoid double + # Mark that we have processed this file in case this is + # directory processing of part.files to avoid double # processing the svg files. if 'processed.' + FQInFile in FilesProcessed: - # Already seen, may occur if svgs are shared, so warn as - # the .bak file will be overwritten and the user needs to - # know that + # Already seen, may occur if svgs are shared, so warn as + # the .bak file will be overwritten and the user needs to + # know that - logging.debug(' ProcessSvgsFromFzp: FQInFile %s Warning 29 issued. FilesProcessed %s\n', FQInFile, FilesProcessed) + logging.debug( + ' ProcessSvgsFromFzp: FQInFile %s Warning 29 issued. FilesProcessed %s\n', FQInFile, FilesProcessed) - Warnings.append('Warning 29: File\n\'{0:s}\'\n\nProcessing view {1:s}, File {2:s}\nhas already been processed\nbut will be processed again as part of this fzp file in case of new warnings.\n'.format(str(InFile), str(CurView), str(FQInFile))) + Warnings.append('Warning 29: File\n\'{0:s}\'\n\nProcessing view {1:s}, File {2:s}\nhas already been processed\nbut will be processed again as part of this fzp file in case of new warnings.\n'.format( + str(InFile), str(CurView), str(FQInFile))) else: - logging.debug(' ProcessSvgsFromFzp: FQInFile %s marked as processed.\n', FQInFile) + logging.debug( + ' ProcessSvgsFromFzp: FQInFile %s marked as processed.\n', FQInFile) FilesProcessed['processed.' + FQInFile] = 'y' # End of if 'processed.' + FQInFile in FilesProcessed: # If the file exists and there was not a file rename error then - # go and try and process the svg (set the FileType explicitly - # to svg), but first reset the state variables for the new + # go and try and process the svg (set the FileType explicitly + # to svg), but first reset the state variables for the new # file (but not Errors, Warnings, FzpDict or CurView). TagStack, State, InheritedAttributes = InitializeState() - ProcessSvg(FzpType, 'SVG', FQInFile, FQOutFile, CurView, PrefixDir, Errors, Warnings, Info, FzpDict, FilesProcessed, TagStack, State, InheritedAttributes, Debug) + ProcessSvg(FzpType, 'SVG', FQInFile, FQOutFile, CurView, PrefixDir, Errors, Warnings, + Info, FzpDict, FilesProcessed, TagStack, State, InheritedAttributes, Debug) - # We are finished processing this file from an fzp, and it + # We are finished processing this file from an fzp, and it # isn't the icon file (which doesn't have connectors) because - # that was caught above, so check the connectors on this svg + # that was caught above, so check the connectors on this svg # file to make sure they are all present. - logging.debug (' ProcessSvgsFromFzp: Checking connectors for %s\n', InFile) + logging.debug( + ' ProcessSvgsFromFzp: Checking connectors for %s\n', InFile) for Connector in FzpDict['connectors.fzp.' + CurView]: - # Check that the connector is in the svg and error if not. + # Check that the connector is in the svg and error if not. - logging.debug (' ProcessSvgsFromFzp: Checking connector %s\n', Connector) + logging.debug( + ' ProcessSvgsFromFzp: Checking connector %s\n', Connector) if not 'connectors.svg.' + CurView in FzpDict: - Errors.append('Error 17: File\n\'{0:s}\'\n\nNo connectors found for view {1:s}.\n'.format(str(InFile), str(CurView))) + Errors.append('Error 17: File\n\'{0:s}\'\n\nNo connectors found for view {1:s}.\n'.format( + str(InFile), str(CurView))) elif not Connector in FzpDict['connectors.svg.' + CurView]: - logging.debug (' ProcessSvgsFromFzp: Connector %s missing\n', Connector) + logging.debug( + ' ProcessSvgsFromFzp: Connector %s missing\n', Connector) - Errors.append('Error 18: File\n\'{0:s}\'\n\nConnector {1:s} is in the fzp file but not the svg file. (typo?)\n\nsvg {2:s}\n'.format(str(InFile), str(Connector), str(FQInFile))) + Errors.append('Error 18: File\n\'{0:s}\'\n\nConnector {1:s} is in the fzp file but not the svg file. (typo?)\n\nsvg {2:s}\n'.format( + str(InFile), str(Connector), str(FQInFile))) # End of if not 'connectors.svg.' + CurView in FzpDict: - - # End of `for Connector in FzpDict['connectors.fzp.' + CurView]: + + # End of `for Connector in FzpDict['connectors.fzp.' + + # CurView]: if CurView == 'schematicView' and 'subparts' in FzpDict: # We have subparts, so now having processed the entire svg - # make sure we have found all the connectors we should have. + # make sure we have found all the connectors we should + # have. - logging.debug(' ProcessSvgsFromFzp: Subpart start FzpDict[\'subparts\'] %s\n',FzpDict['subparts']) + logging.debug( + ' ProcessSvgsFromFzp: Subpart start FzpDict[\'subparts\'] %s\n', FzpDict['subparts']) for SubPart in FzpDict['subparts']: # Get the list of subparts from the fzp. - logging.debug(' ProcessSvgsFromFzp: Subpart before loop SubPart=%s\nFzpDict[SubPart + \'.subpart.cons\']=%s\nFzpDict[SubPart + \'.svg.subparts\']=%s\n',SubPart, FzpDict[SubPart + '.subpart.cons'], FzpDict[SubPart + '.svg.subparts']) + logging.debug(' ProcessSvgsFromFzp: Subpart before loop SubPart=%s\nFzpDict[SubPart + \'.subpart.cons\']=%s\nFzpDict[SubPart + \'.svg.subparts\']=%s\n', SubPart, FzpDict[ + SubPart + '.subpart.cons'], FzpDict[SubPart + '.svg.subparts']) for SubpartConnector in FzpDict[SubPart + '.subpart.cons']: - logging.debug(' ProcessSvgsFromFzp: SubpartConnector %s\n',SubpartConnector) + logging.debug( + ' ProcessSvgsFromFzp: SubpartConnector %s\n', SubpartConnector) if not SubPart + '.svg.subparts' in FzpDict: - # No connectors in svg error. + # No connectors in svg error. - logging.debug(' ProcessSvgsFromFzp: no connectors in svg, SubpartConnector %s\n',SubPartConnector, SubPart) + logging.debug( + ' ProcessSvgsFromFzp: no connectors in svg, SubpartConnector %s\n', SubPartConnector, SubPart) - Errors.append('Error 78: Svg file\n\n\'{0:s}\'\n\nWhile looking for {1:s}, Subpart {2:s} has no connectors in the svg\n'.format(str(FQInFile), str(OutFile), str(SubpartConnector), str(SubPart))) + Errors.append('Error 78: Svg file\n\n\'{0:s}\'\n\nWhile looking for {1:s}, Subpart {2:s} has no connectors in the svg\n'.format( + str(FQInFile), str(OutFile), str(SubpartConnector), str(SubPart))) elif not SubpartConnector in FzpDict[SubPart + '.svg.subparts']: - # Throw an error if one of the connectors we - # should have isn't in the svg. + # Throw an error if one of the connectors we + # should have isn't in the svg. - Errors.append('Error 79: Svg file\n\n\'{0:s}\'\n\nSubpart {1:s} is missing connector {2:s} in the svg\n'.format(str(FQInFile), str(SubPart), str(SubpartConnector))) + Errors.append('Error 79: Svg file\n\n\'{0:s}\'\n\nSubpart {1:s} is missing connector {2:s} in the svg\n'.format( + str(FQInFile), str(SubPart), str(SubpartConnector))) - logging.debug(' ProcessSvgsFromFzp: Error 79: no connector %s in svg, SubpartConnector %s\n',SubpartConnector, SubPart) + logging.debug( + ' ProcessSvgsFromFzp: Error 79: no connector %s in svg, SubpartConnector %s\n', SubpartConnector, SubPart) # if not SubPart + '.svg.subparts' in FzpDict: - # End of for SubpartConnector in FzpDict[SubPart + '.subpart.cons']: + # End of for SubpartConnector in FzpDict[SubPart + + # '.subpart.cons']: # End of for SubPart in FzpDict['subparts']: - # End of if CurView == 'schematicView' and 'subparts' in FzpDict: + # End of if CurView == 'schematicView' and 'subparts' in + # FzpDict: # End of if OutFileError == 'n': @@ -1243,26 +1372,29 @@ def ProcessSvgsFromFzp(DirProcessing, FzpType, FileType, InFile, OutFile, Prefix # End of for CurView in FzpDict['views']: - logging.info (' Exiting ProcessSvgsFromFzp\n') + logging.info(' Exiting ProcessSvgsFromFzp\n') + +# End of def ProcessSvgsFromFzp(FzpType, FileType, InFile, OutFile, +# PrefixDir, Errors, Warnings, Info, FzpDict, FilesProcessed, Debug): -#End of def ProcessSvgsFromFzp(FzpType, FileType, InFile, OutFile, PrefixDir, Errors, Warnings, Info, FzpDict, FilesProcessed, Debug): def ProcessFzpLeafNode(FzpType, FileType, InFile, CurView, PrefixDir, Elem, Errors, Warnings, Info, FzpDict, TagStack, State, Level): - # We are processing an fzp file so do the appropiate things for that. + # We are processing an fzp file so do the appropiate things for that. - logging.info (' Entering ProcessFzpLeafNode FileType %s Infile %s Level %s\n', FzpType, InFile, Level) + logging.info( + ' Entering ProcessFzpLeafNode FileType %s Infile %s Level %s\n', FzpType, InFile, Level) # Regex to detect comment lines (ignoring case) - CommentRegex = re.compile(r'^ 2: - - logging.debug (' ProcessFzpLeafNode moduleid BaseTag %s len %s', BaseTag, len(TagStack)) + + logging.debug(' ProcessFzpLeafNode moduleid BaseTag %s len %s', + BaseTag, len(TagStack)) if len(TagStack) > 2 and BaseTag == 'views': - logging.debug (' ProcessFzpLeafNode: start processing views\n') + logging.debug(' ProcessFzpLeafNode: start processing views\n') # As long as we haven't cycled to 'connectors' as the primary tag, # keep processing views tags. - + if not 'views' in FzpDict: - # If we don't have a views yet create an empty one. + # If we don't have a views yet create an empty one. - logging.debug (' ProcessFzpLeafNode: create \'views\' in dictionary\n') + logging.debug( + ' ProcessFzpLeafNode: create \'views\' in dictionary\n') FzpDict['views'] = [] @@ -1347,7 +1485,7 @@ def ProcessFzpLeafNode(FzpType, FileType, InFile, CurView, PrefixDir, Elem, Erro if State['lasttag'] == 'module': - # Note that we have seen the 'views' tag now. + # Note that we have seen the 'views' tag now. State['lasttag'] = 'views' @@ -1357,15 +1495,16 @@ def ProcessFzpLeafNode(FzpType, FileType, InFile, CurView, PrefixDir, Elem, Erro # End of if State['lasttag'] == 'module': - # We are currently looking for file and layer names so do that. + # We are currently looking for file and layer names so do that. if len(TagStack) > 3: - # We have already dealt with the TagStack 3 ('views') case above - # so only call FzpProcessViewsTs3 for 4 or higher - # (viewname, layers and layer). + # We have already dealt with the TagStack 3 ('views') case above + # so only call FzpProcessViewsTs3 for 4 or higher + # (viewname, layers and layer). - FzpProcessViewsTs3(InFile, Elem, Errors, Warnings, Info, FzpDict, TagStack, State, Level) + FzpProcessViewsTs3(InFile, Elem, Errors, Warnings, + Info, FzpDict, TagStack, State, Level) # End of len(TagStack) > 3: @@ -1377,21 +1516,23 @@ def ProcessFzpLeafNode(FzpType, FileType, InFile, CurView, PrefixDir, Elem, Erro # process the connectors - logging.debug (' ProcessFzpLeafNode: Start of processing connectors\n') + logging.debug(' ProcessFzpLeafNode: Start of processing connectors\n') # By the time we get here we should have all the views present so check # and make sure we have at least one view and warn about any that are - # missing or have unexpected names (no views is an error!). + # missing or have unexpected names (no views is an error!). if not 'FzpCheckViews' in State: - logging.debug (' ProcessFzpLeafNode: Set State[\'FzpCheckViews\'] = [] and call FzpCheckViews State %s line %s\n', State, Elem.sourceline) + logging.debug( + ' ProcessFzpLeafNode: Set State[\'FzpCheckViews\'] = [] and call FzpCheckViews State %s line %s\n', State, Elem.sourceline) # Indicate we have executed the check so it is only done once. State['FzpCheckViews'] = [] - FzpCheckViews(InFile, Elem, Errors, Warnings, Info, FzpDict, TagStack, State, Level) + FzpCheckViews(InFile, Elem, Errors, Warnings, Info, + FzpDict, TagStack, State, Level) # End of if not FzpCheckViews in State: @@ -1405,24 +1546,25 @@ def ProcessFzpLeafNode(FzpType, FileType, InFile, CurView, PrefixDir, Elem, Erro # Again BaseTag is TagStack[2] (the current tag may be different.) - if len(TagStack) > 3 and BaseTag == 'connectors': + if len(TagStack) > 3 and BaseTag == 'connectors': - logging.debug (' ProcessFzpLeafNode: continue processing connectors\n') + logging.debug(' ProcessFzpLeafNode: continue processing connectors\n') - # We have dealt with TagStack = 3 'connectors' above so only do + # We have dealt with TagStack = 3 'connectors' above so only do # 4 and higher by calling FzpProcessConnectorsTs3. - FzpProcessConnectorsTs3(InFile, Elem, Errors, Warnings, Info, FzpDict, TagStack, State, Level) + FzpProcessConnectorsTs3( + InFile, Elem, Errors, Warnings, Info, FzpDict, TagStack, State, Level) # End of if len(TagStack) > 3 and BaseTag == 'connectors': - # If TagStack is 3 and is 'module', 'buses' + # If TagStack is 3 and is 'module', 'buses' # Again BaseTag is TagStack[2] (the current tag may be different.) if len(TagStack) == 3 and BaseTag == 'buses': - logging.debug (' ProcessFzpLeafNode: start processing buses\n') + logging.debug(' ProcessFzpLeafNode: start processing buses\n') # Since some parts have an empty bus tag at the end of the fzp # don't check the previous state (but do set the new state in case @@ -1434,67 +1576,74 @@ def ProcessFzpLeafNode(FzpType, FileType, InFile, CurView, PrefixDir, Elem, Erro if not 'buses' in FzpDict: - # If we don't have a buses yet create an empty one. + # If we don't have a buses yet create an empty one. - logging.debug (' ProcessFzpLeafNode: create \'buses\' in dictionary\n') + logging.debug( + ' ProcessFzpLeafNode: create \'buses\' in dictionary\n') FzpDict['buses'] = [] # End of if not 'buses' in FzpDict: - logging.debug (' ProcessFzpLeafNode: TagStack len %s\n', len(TagStack)) + logging.debug(' ProcessFzpLeafNode: TagStack len %s\n', len(TagStack)) # End of if len(TagStack) == 3 and BaseTag == 'buses': # Again BaseTag is TagStack[2] (the current tag may be different.) - if len(TagStack) > 3 and BaseTag == 'buses': + if len(TagStack) > 3 and BaseTag == 'buses': - logging.debug (' ProcessFzpLeafNode: continue processing buses\n') + logging.debug(' ProcessFzpLeafNode: continue processing buses\n') # Go and process the bus tags - FzpProcessBusTs3(InFile, Elem, Errors, Warnings, Info, FzpDict, TagStack, State, Level) + FzpProcessBusTs3(InFile, Elem, Errors, Warnings, Info, + FzpDict, TagStack, State, Level) # End of if len(TagStack) > 3 and BaseTag == 'buses': - logging.debug (' ProcessFzpLeafNode: before subparts processing TagStack len %s TagStack %s\n', len(TagStack), TagStack) + logging.debug(' ProcessFzpLeafNode: before subparts processing TagStack len %s TagStack %s\n', len( + TagStack), TagStack) # Again BaseTag is TagStack[2] (the current tag may be different.) if len(TagStack) == 3 and BaseTag == 'schematic-subparts': - logging.debug (' ProcessFzpLeafNode: start sub parts processing\n') + logging.debug(' ProcessFzpLeafNode: start sub parts processing\n') if 'buses' in FzpDict: # A bus has already been defined and won't allow schematic parts. - logging.debug (' ProcessFzpLeafNode: subparts but bus defined\n') + logging.debug(' ProcessFzpLeafNode: subparts but bus defined\n') if 'bus_defined' in FzpDict: if 'bus_defined' == 'n': - Errors.append('Error 23: File\n\'{0:s}\'\nAt line {1:s}\n\nA bus is already defined, schematic parts won\'t work with busses\n'.format(str(InFile), str(Elem.sourceline))) + Errors.append('Error 23: File\n\'{0:s}\'\nAt line {1:s}\n\nA bus is already defined, schematic parts won\'t work with busses\n'.format( + str(InFile), str(Elem.sourceline))) - # Mark that we have flagged the error so we don't repeat it. + # Mark that we have flagged the error so we don't repeat + # it. FzpDict['bus_defined'] = 'y' # End of if 'bus_defined' == 'n': # End of if 'bus_defined' in FzpDict: - + else: - + if not 'schematic-subparts' in FzpDict: - - # If we don't have a schematic-subparts yet create an empty one. - logging.debug (' ProcessFzpLeafNode: create \'schematic-subparts\' in dictionary\n') - + + # If we don't have a schematic-subparts yet create an empty + # one. + logging.debug( + ' ProcessFzpLeafNode: create \'schematic-subparts\' in dictionary\n') + FzpDict['schematic-subparts'] = [] - + # End of if not 'schematic-subparts' in FzpDict: # End of if 'buses' in FzpDict: @@ -1509,72 +1658,85 @@ def ProcessFzpLeafNode(FzpType, FileType, InFile, CurView, PrefixDir, Elem, Erro # Again BaseTag is TagStack[2] (the current tag may be different.) - if len(TagStack) > 3 and BaseTag == 'schematic-subparts': + if len(TagStack) > 3 and BaseTag == 'schematic-subparts': - logging.debug (' ProcessFzpLeafNode: continue sub parts Tag > 2 TagStack %s\n',TagStack) + logging.debug( + ' ProcessFzpLeafNode: continue sub parts Tag > 2 TagStack %s\n', TagStack) # Process the schematic-subparts section of the fzp. if not 'bus_defined' in FzpDict: # But only if there isn't a bus already defined. - - FzpProcessSchematicPartsTs3(InFile, Elem, Errors, Warnings, Info, FzpDict, TagStack, State, Level) + + FzpProcessSchematicPartsTs3( + InFile, Elem, Errors, Warnings, Info, FzpDict, TagStack, State, Level) # End of if not 'bus_defined' in FzpDict: # End of if len(TagStack) > 3 and BaseTag == 'schematic-subparts': - - logging.debug (' Exiting ProcessFzpLeafNode Level %s State %s line %s\n', Level, State, Elem.sourceline) - logging.info (' Exiting ProcessFzpLeafNode Level %s\n', Level) + logging.debug(' Exiting ProcessFzpLeafNode Level %s State %s line %s\n', + Level, State, Elem.sourceline) -# End of def ProcessFzpLeafNode(FzpType, FileType, InFile, CurView, PrefixDir, Elem, Errors, Warnings, Info, FzpDict, TagStack, State, Level): + logging.info(' Exiting ProcessFzpLeafNode Level %s\n', Level) +def stripPartName(name): + return name.translate({ord(i): None for i in '-_ .'}) + +# End of def ProcessFzpLeafNode(FzpType, FileType, InFile, CurView, +# PrefixDir, Elem, Errors, Warnings, Info, FzpDict, TagStack, State, +# Level): def FzpTags(InFile, Elem, Errors, Warnings, Info, FzpDict, TagStack, Level): # Looks for and log any of the Fritzing tags. We will check the dictionary # to make sure the appropriate tag has been seen when processing layer and - # pin information later. + # pin information later. - logging.info (' Entering FzpTags Level %s\n', Level) + logging.info(' Entering FzpTags Level %s\n', Level) Tag = Elem.tag if Tag != None: - # If we have a tag go and adjust the tag stack if needed. + # If we have a tag go and adjust the tag stack if needed. PopTag(TagStack, Level) # End of if Tag != None: - logging.debug (' FzpTags: Tag: %s attributes:%s TagStack %s\n',Elem.tag, Elem.attrib, TagStack) + logging.debug(' FzpTags: Tag: %s attributes:%s TagStack %s\n', + Elem.tag, Elem.attrib, TagStack) # Check the single per file tags (more than one is an error) if Tag in ['module', 'version', 'author', 'title', 'label', 'date', 'tags', 'properties', 'taxonomy', 'url', 'schematic-subparts', 'buses']: - logging.debug (' FzpTags: Source line %s Level %s tag %s\n', Elem.sourceline, Level, Tag) + logging.debug(' FzpTags: Source line %s Level %s tag %s\n', + Elem.sourceline, Level, Tag) # Record the tag in the dictionary (and check for more than one!) if Tag in FzpDict: - logging.debug (' FzpTags: Dup Source line %s Level %s tag %s\n', Elem.sourceline, Level, Tag) + logging.debug( + ' FzpTags: Dup Source line %s Level %s tag %s\n', Elem.sourceline, Level, Tag) # If its already been seen flag an errror. - Errors.append('Error 24: File\n\'{0:s}\'\nAt line {1:s}\n\nMore than one copy of Tag {2:s}\n'.format(str(InFile), str(Elem.sourceline), str( Tag))) - + Errors.append('Error 24: File\n\'{0:s}\'\nAt line {1:s}\n\nMore than one copy of Tag {2:s}\n'.format( + str(InFile), str(Elem.sourceline), str(Tag))) + # End of if Tag in FzpDict: - + FzpDict[Tag] = [Tag] - # End of if Tag in ['module', 'version', 'author', 'title', 'label', 'date', 'tags', 'properties', 'taxonomy', 'url', 'schematic-subparts', 'buses']: + # End of if Tag in ['module', 'version', 'author', 'title', 'label', + # 'date', 'tags', 'properties', 'taxonomy', 'url', 'schematic-subparts', + # 'buses']: # For the repeating tags: views, iconView, layers, breadboardView, - # schematicView, pcbView, connector, subpart, bus and the non repeating + # schematicView, pcbView, connector, subpart, bus and the non repeating # tags connectors, schematic-subparts, buses stick them in a stack # so we know where we are when we come across an attribute. @@ -1584,56 +1746,66 @@ def FzpTags(InFile, Elem, Errors, Warnings, Info, FzpDict, TagStack, Level): TagStack.append([Tag, Level]) - logging.debug (' FzpTags: End, found tag, source line %s Tag %s Level %s TagStack %s TagStack len %s\n', Elem.sourceline, Tag, Level, TagStack, len(TagStack)) + logging.debug(' FzpTags: End, found tag, source line %s Tag %s Level %s TagStack %s TagStack len %s\n', + Elem.sourceline, Tag, Level, TagStack, len(TagStack)) else: - - logging.debug (' FzpTags: End didn\'t find tag, source line %s Tag %s Level %s TagStack %s TagStack len %s\n', Elem.sourceline, Tag, Level, TagStack, len(TagStack)) - # End of if Tag in ['module', 'version', 'author', 'title', 'label', 'date', 'tags', 'tag', 'properties', 'property', 'spice', 'taxonomy', 'description', 'url', 'line', 'model', 'views', 'iconView', 'layers', 'layer', 'breadboardView', 'schematicView', 'pcbView', 'connectors', 'connector', 'p', 'buses', 'bus', 'nodeMember', 'schematic-subparts', 'subpart']: + logging.debug(' FzpTags: End didn\'t find tag, source line %s Tag %s Level %s TagStack %s TagStack len %s\n', + Elem.sourceline, Tag, Level, TagStack, len(TagStack)) - logging.info (' Exiting FzpTags Level %s\n', Level) + # End of if Tag in ['module', 'version', 'author', 'title', 'label', + # 'date', 'tags', 'tag', 'properties', 'property', 'spice', 'taxonomy', + # 'description', 'url', 'line', 'model', 'views', 'iconView', 'layers', + # 'layer', 'breadboardView', 'schematicView', 'pcbView', 'connectors', + # 'connector', 'p', 'buses', 'bus', 'nodeMember', 'schematic-subparts', + # 'subpart']: + + logging.info(' Exiting FzpTags Level %s\n', Level) + +# End of def FzpTags(InFile, Elem, Errors, Warnings, Info, FzpDict, +# TagStack, Level): -# End of def FzpTags(InFile, Elem, Errors, Warnings, Info, FzpDict, TagStack, Level): def FzpmoduleId(FzpType, InFile, Elem, Errors, Warnings, Info, FzpDict, State, Level): - logging.info (' Entering FzpmoduleId Level %s\n', Level) + logging.info(' Entering FzpmoduleId Level %s\n', Level) LeadingPartRegex = re.compile(r'^part\.', re.IGNORECASE) TrailingFzpRegex = re.compile(r'\.fzp$', re.IGNORECASE) - # Check to see if we have a moduleId and flag an error if not, because - # one is required. - - ModuleId = Elem.get('moduleId') + # Check to see if we have a moduleId and flag an error if not, because + # one is required. - logging.debug(' FzpmoduleId: ModuleId %s\n',ModuleId) + ModuleId = Elem.get('moduleId') + + logging.debug(' FzpmoduleId: ModuleId %s\n', ModuleId) # Make a local copy of the base file name (without its path if any) - # as we may make changes to it that we don't want to propigate. + # as we may make changes to it that we don't want to propigate. File = os.path.basename(InFile) # Remove the trailing .bak if it is present. - File = re.sub(r'\.bak$','', File) + File = re.sub(r'\.bak$', '', File) if ModuleId == None: if not 'moduleId' in FzpDict: - Errors.append('Error 22: File\n\'{0:s}\'\n\nAt line {1:s}\n\nNo ModuleId found in fzp file\n'.format(str(InFile), str(Elem.sourceline))) + Errors.append('Error 22: File\n\'{0:s}\'\n\nAt line {1:s}\n\nNo ModuleId found in fzp file\n'.format( + str(InFile), str(Elem.sourceline))) # End of if not 'moduleId' in FzpDict: logging.debug(' FzpmoduleId: no moduleId\n') else: - - # We have found a moduleId so process it. Check that it matches the - # input filename without the fzp, and there is only one of them. Look + + # We have found a moduleId so process it. Check that it matches the + # input filename without the fzp, and there is only one of them. Look # for (and warn if absent) a referenceFile and fritzingVersion as well. # Check if this is a breadboard file and mark that in State if so. @@ -1644,7 +1816,8 @@ def FzpmoduleId(FzpType, InFile, Elem, Errors, Warnings, Info, FzpDict, State, L # End of if File in ['breadboard.fzp', 'breadboard2.fzp']: - logging.debug(' FzpmoduleId: FzpType %s InFile %s File %s\n', FzpType, InFile, File) + logging.debug(' FzpmoduleId: FzpType %s InFile %s File %s\n', + FzpType, InFile, File) if FzpType == 'FZPPART': @@ -1663,15 +1836,25 @@ def FzpmoduleId(FzpType, InFile, Elem, Errors, Warnings, Info, FzpDict, State, L logging.debug(' FzpmoduleId: removed .fzp to leave %s\n', File) - if File != ModuleId: - Warnings.append('Warning 3: File\n\'{0:s}\'\nAt line {1:s}\n\nModuleId \'{2:s}\'\n\nDoesn\'t match filename\n\n\'{3:s}\'\n'.format(str(InFile), str(Elem.sourceline), str(ModuleId), str(File))) - - # End of if File != ModuleId: - + if not stripPartName(ModuleId).startswith( + stripPartName(File)): + + Warnings.append( + "Warning 3: File\n" + "'{0:s}'\n" + "At line {1:s}\n\n" + "ModuleId '{2:s}'\n\n" + "is not similar to filename\n\n" + "'{3:s}'\n".format( + str(InFile), str(Elem.sourceline), str(ModuleId), str(File))) + + + if 'moduleId' in FzpDict: - - Errors.append('Error 25: File\n\'{0:s}\'\nAt line {1:s}\n\nMultiple ModuleIds found in fzp file\n'.format(str(InFile), str(Elem.sourceline))) + + Errors.append('Error 25: File\n\'{0:s}\'\nAt line {1:s}\n\nMultiple ModuleIds found in fzp file\n'.format( + str(InFile), str(Elem.sourceline))) FzpDict['moduleId'].append(ModuleId) @@ -1682,7 +1865,8 @@ def FzpmoduleId(FzpType, InFile, Elem, Errors, Warnings, Info, FzpDict, State, L FzpDict['moduleId'] = [ModuleId] - logging.debug(' FzpmoduleId: Added ModuleId %s to FzpDict\n', ModuleId) + logging.debug( + ' FzpmoduleId: Added ModuleId %s to FzpDict\n', ModuleId) # End of if 'ModuleId' in FzpDict: @@ -1690,19 +1874,21 @@ def FzpmoduleId(FzpType, InFile, Elem, Errors, Warnings, Info, FzpDict, State, L # Now look for a reference file. - RefFile = Elem.get('referenceFile') + RefFile = Elem.get('referenceFile') logging.debug(' FzpmoduleId: ReFile %s File %s\n', RefFile, File) - + if RefFile == None: - Warnings.append('Warning 4: File\n\'{0:s}\'\nAt line {1:s}\n\nNo referenceFile found in fzp file\n'.format(str(InFile), str(Elem.sourceline))) + Warnings.append('Warning 4: File\n\'{0:s}\'\nAt line {1:s}\n\nNo referenceFile found in fzp file\n'.format( + str(InFile), str(Elem.sourceline))) else: if 'referenceFile' in FzpDict: - Warnings.append('Warning 5: File\n\'{0:s}\'\nAt line {1:s}\n\nMultiple referenceFile found in fzp file\n'.format(str(InFile), str(Elem.sourceline))) + Warnings.append('Warning 5: File\n\'{0:s}\'\nAt line {1:s}\n\nMultiple referenceFile found in fzp file\n'.format( + str(InFile), str(Elem.sourceline))) FzpDict['referenceFile'].append(RefFile) @@ -1717,10 +1903,11 @@ def FzpmoduleId(FzpType, InFile, Elem, Errors, Warnings, Info, FzpDict, State, L if RefFile != File + '.fzp': - # The reference file doesn't match the input file name which it + # The reference file doesn't match the input file name which it # should. - Warnings.append('Warning 6: File\n\'{0:s}\'\nAt line {1:s}\n\nReferenceFile name \n\n\'{2:s}\'\n\nDoesn\'t match fzp filename\n\n\'{3:s}\'\n'.format(str(InFile), str(Elem.sourceline), str(RefFile), str(File + '.fzp'))) + Warnings.append('Warning 6: File\n\'{0:s}\'\nAt line {1:s}\n\nReferenceFile name \n\n\'{2:s}\'\n\nDoesn\'t match fzp filename\n\n\'{3:s}\'\n'.format( + str(InFile), str(Elem.sourceline), str(RefFile), str(File + '.fzp'))) # End of if RefFile != File + '.fzp': @@ -1728,19 +1915,21 @@ def FzpmoduleId(FzpType, InFile, Elem, Errors, Warnings, Info, FzpDict, State, L # Then check for a Fritzing version - Version = Elem.get('fritzingVersion') + Version = Elem.get('fritzingVersion') if Version == None: - Warnings.append('Warning 7: File\n\'{0:s}\'\nAt line {1:s}\n\nNo Fritzing version in fzp file\n'.format(str(InFile), str(Elem.sourceline))) + Warnings.append('Warning 7: File\n\'{0:s}\'\nAt line {1:s}\n\nNo Fritzing version in fzp file\n'.format( + str(InFile), str(Elem.sourceline))) else: # There is a Fritzing version so record it. - + if 'fritzingVersion' in FzpDict: - - Warnings.append('Warning 8: File\n\'{0:s}\'\nAt line {1:s}\n\nMultiple fritzingVersion found in fzp file\n'.format(str(InFile), str(Elem.sourceline))) + + Warnings.append('Warning 8: File\n\'{0:s}\'\nAt line {1:s}\n\nMultiple fritzingVersion found in fzp file\n'.format( + str(InFile), str(Elem.sourceline))) FzpDict['fritzingVersion'].append(Version) @@ -1755,38 +1944,44 @@ def FzpmoduleId(FzpType, InFile, Elem, Errors, Warnings, Info, FzpDict, State, L # End of if Version == None: - logging.info (' Exiting moduleId found moduleId\n') + logging.info(' Exiting moduleId found moduleId\n') + +# End of def FzpmoduleId(FzpType, InFile, Elem, Errors, Warnings, Info, +# FzpDict, State, Level): -# End of def FzpmoduleId(FzpType, InFile, Elem, Errors, Warnings, Info, FzpDict, State, Level): def FzpProcessViewsTs3(InFile, Elem, Errors, Warnings, Info, FzpDict, TagStack, State, Level): # We are in the views grouping so find and record our groupnames, layerIds - # and filenames in the input stream. + # and filenames in the input stream. - logging.info (' Entering FzpProcessViewsTs3 Level %s source line %s\n', Level, Elem.sourceline) + logging.info( + ' Entering FzpProcessViewsTs3 Level %s source line %s\n', Level, Elem.sourceline) StackTag, StackLevel = TagStack[len(TagStack) - 1] - logging.debug (' FzpProcessViewsTs3: StackTag %s State %s TagStack %s attributes %s\n', StackTag, State, TagStack, Elem.attrib) + logging.debug(' FzpProcessViewsTs3: StackTag %s State %s TagStack %s attributes %s\n', + StackTag, State, TagStack, Elem.attrib) - # TagStack length of 3 ('empty', 'module', 'views') is what tripped the - # call to this routine so we start processing at TagStack length 4 in - # this large case statement which trips when it finds the correct state + # TagStack length of 3 ('empty', 'module', 'views') is what tripped the + # call to this routine so we start processing at TagStack length 4 in + # this large case statement which trips when it finds the correct state # (or complains if it finds an incorrect state due to errrorS.) if len(TagStack) == 4: # TagStack should be 'module', 'views', view name so check and process # the view name. Check that State['nexttag'] is 'viewname' or 'layer' - # (the end of a previous entry) to indicate that is what we are - # expecting at this time. + # (the end of a previous entry) to indicate that is what we are + # expecting at this time. if State['nexttag'] != 'viewname' and State['nexttag'] != 'layer': - Errors.append('Error 26: File\n\'{0:s}\'\nAt line {1:s}\n\nState error, expected tag {2:s} not a view name\n'.format(str(InFile), str(Elem.sourceline), str(State['nexttag']))) - - # End of if State['nexttag'] != 'viewname' and State['nexttag'] != 'layer': + Errors.append('Error 26: File\n\'{0:s}\'\nAt line {1:s}\n\nState error, expected tag {2:s} not a view name\n'.format( + str(InFile), str(Elem.sourceline), str(State['nexttag']))) + + # End of if State['nexttag'] != 'viewname' and State['nexttag'] != + # 'layer': # Get the latest tag value from StackTag in to View @@ -1794,22 +1989,24 @@ def FzpProcessViewsTs3(InFile, Elem, Errors, Warnings, Info, FzpDict, TagStack, if View == 'layers': - # If it is 'layers' (indicating we don't have a valid view), - # set View to none so it has a value (even though its wrong) and - # the state is unrecoverable. So as we have noted the error just - # proceed although it will likely cause an error cascade. + # If it is 'layers' (indicating we don't have a valid view), + # set View to none so it has a value (even though its wrong) and + # the state is unrecoverable. So as we have noted the error just + # proceed although it will likely cause an error cascade. View = 'none' - logging.debug (' FzpProcessViewsTs3: missing view, View set to none\n', View) + logging.debug( + ' FzpProcessViewsTs3: missing view, View set to none\n', View) - Errors.append('Error 27: File\n\'{0:s}\'\nAt line {1:s}\n\nView name missing\n'.format(str(InFile), str(Elem.sourceline))) + Errors.append('Error 27: File\n\'{0:s}\'\nAt line {1:s}\n\nView name missing\n'.format( + str(InFile), str(Elem.sourceline))) # End of if View == 'layers': - + if View in ['iconView', 'breadboardView', 'schematicView', 'pcbView']: - # View value is legal so process it. + # View value is legal so process it. if not 'views' in FzpDict: @@ -1817,7 +2014,8 @@ def FzpProcessViewsTs3(InFile, Elem, Errors, Warnings, Info, FzpDict, TagStack, FzpDict['views'] = [View] - logging.debug (' FzpProcessViewsTs3: Created dict entry views and added %s\n', View) + logging.debug( + ' FzpProcessViewsTs3: Created dict entry views and added %s\n', View) else: @@ -1825,17 +2023,20 @@ def FzpProcessViewsTs3(InFile, Elem, Errors, Warnings, Info, FzpDict, TagStack, # Error, already seen. - Errors.append('Error 28: File\n\'{0:s}\'\nAt line {1:s}\n\nMultiple view tags {2:s} present, ignored\n'.format(str(InFile), str(Elem.sourceline), str(View))) + Errors.append('Error 28: File\n\'{0:s}\'\nAt line {1:s}\n\nMultiple view tags {2:s} present, ignored\n'.format( + str(InFile), str(Elem.sourceline), str(View))) + + logging.debug( + ' FzpProcessViewsTs3: error view %s already present\n', View) - logging.debug (' FzpProcessViewsTs3: error view %s already present\n', View) + else: - else: + # Add this view to the list. - # Add this view to the list. - FzpDict['views'].append(View) - logging.debug (' FzpProcessViewsTs3: appended View %s to dict entry views\n', View) + logging.debug( + ' FzpProcessViewsTs3: appended View %s to dict entry views\n', View) # End of if View in FzpDict['views']: @@ -1843,21 +2044,26 @@ def FzpProcessViewsTs3(InFile, Elem, Errors, Warnings, Info, FzpDict, TagStack, else: - Errors.append('Error 29: File\n\'{0:s}\'\nAt line {1:s}\n\nView tag {2:s} not recognized (typo?)\n'.format(str(InFile), str(Elem.sourceline), str(View))) + Errors.append('Error 29: File\n\'{0:s}\'\nAt line {1:s}\n\nView tag {2:s} not recognized (typo?)\n'.format( + str(InFile), str(Elem.sourceline), str(View))) - logging.debug (' FzpProcessViewsTs3: error View %s not recognized\n', View) + logging.debug( + ' FzpProcessViewsTs3: error View %s not recognized\n', View) - # End of if View in ['iconView', 'breadboardView', 'schematicView', 'pcbView']: + # End of if View in ['iconView', 'breadboardView', 'schematicView', + # 'pcbView']: - # Now set State['lastvalue'] to View to keep state for the next entry + # Now set State['lastvalue'] to View to keep state for the next entry State['lastvalue'] = View - # Set State['nexttag'] to the next tag we expect to see for the next entry + # Set State['nexttag'] to the next tag we expect to see for the next + # entry State['nexttag'] = 'layers' - logging.debug (' FzpProcessViewsTs3: Set State[\'views\'] to %s and State[\'tag\'] to %s\n', State['lastvalue'], State['nexttag']) + logging.debug(' FzpProcessViewsTs3: Set State[\'views\'] to %s and State[\'tag\'] to %s\n', State[ + 'lastvalue'], State['nexttag']) elif len(TagStack) == 5 and StackTag == 'layers': @@ -1865,42 +2071,46 @@ def FzpProcessViewsTs3(InFile, Elem, Errors, Warnings, Info, FzpDict, TagStack, # note an internal state error. - Errors.append('Error 26: File\n\'{0:s}\'\nAt line {1:s}\n\nNState error, nexttag {2:s} not \'layers\'\n'.format(str(InFile), str(Elem.sourceline), str(State['nexttag']))) - - # End of if State['nexttag'] != 'layers': - - # Get the current tag value from the state variable set on a previous - # call to this routine. + Errors.append('Error 26: File\n\'{0:s}\'\nAt line {1:s}\n\nNState error, nexttag {2:s} not \'layers\'\n'.format( + str(InFile), str(Elem.sourceline), str(State['nexttag']))) + + # End of if State['nexttag'] != 'layers': + + # Get the current tag value from the state variable set on a previous + # call to this routine. - View = State['lastvalue'] + View = State['lastvalue'] + + # We should have an image file here so try and get it. - # We should have an image file here so try and get it. - Image = Elem.get('image') if Image == None: # We didn't find an image, so set it to 'none' so it has a value - # even if it is bogus. + # even if it is bogus. Image = 'none' - Errors.append('Error 30: File\n\'{0:s}\'\nAt line {1:s}\n\nNo image name present\n'.format(str(InFile), str(Elem.sourceline))) + Errors.append('Error 30: File\n\'{0:s}\'\nAt line {1:s}\n\nNo image name present\n'.format( + str(InFile), str(Elem.sourceline))) # End of if Image == None: - - # We have found an image attribute so put it in the dictonary + + # We have found an image attribute so put it in the dictonary # indexed by viewname aquired above. if (View + '.image') in FzpDict: # too many input files! - Errors.append('Error 31: File\n\'{0:s}\'\nAt line {1:s}\n\nMultiple {2:s} image files present\n'.format(str(InFile), str(Elem.sourceline), str(View))) + Errors.append('Error 31: File\n\'{0:s}\'\nAt line {1:s}\n\nMultiple {2:s} image files present\n'.format( + str(InFile), str(Elem.sourceline), str(View))) FzpDict[View + '.image'].append(Image) - - logging.debug (' FzpProcessViewsTs3: error multiple image files added %s\n', Image) + + logging.debug( + ' FzpProcessViewsTs3: error multiple image files added %s\n', Image) else: @@ -1908,11 +2118,11 @@ def FzpProcessViewsTs3(InFile, Elem, Errors, Warnings, Info, FzpDict, TagStack, FzpDict[View + '.image'] = [Image] - logging.debug (' FzpProcessViewsTs3: added image file %s\n', Image) + logging.debug(' FzpProcessViewsTs3: added image file %s\n', Image) # End if (View + 'image') in FzpDict: - # Then set State['lastvalue'] to the image to capture the layerids that + # Then set State['lastvalue'] to the image to capture the layerids that # should follow this image file. State['image'] = Image @@ -1927,13 +2137,14 @@ def FzpProcessViewsTs3(InFile, Elem, Errors, Warnings, Info, FzpDict, TagStack, # note an internal state error. - Errors.append('Error 26: File\n\'{0:s}\'\nAt line {1:s}\n\nState error, nexttag {2:s} not \'layer\'\n'.format(str(InFile), str(Elem.sourceline), str(State['nexttag']))) - - # End of if State['nexttag'] != 'layers': - - # set the current view from State['lastvalue'] and the current image - # path/filename value from State['image'] for dict keys. The values - # are those saved the last time we were in this routine). + Errors.append('Error 26: File\n\'{0:s}\'\nAt line {1:s}\n\nState error, nexttag {2:s} not \'layer\'\n'.format( + str(InFile), str(Elem.sourceline), str(State['nexttag']))) + + # End of if State['nexttag'] != 'layers': + + # set the current view from State['lastvalue'] and the current image + # path/filename value from State['image'] for dict keys. The values + # are those saved the last time we were in this routine). View = State['lastvalue'] @@ -1947,11 +2158,12 @@ def FzpProcessViewsTs3(InFile, Elem, Errors, Warnings, Info, FzpDict, TagStack, if LayerId == None: # There isn't a layer id so set it to none so it has a value even - # if it is bogus. + # if it is bogus. LayerId = 'none' - Errors.append('Error 32: File\n\'{0:s}\'\nAt line {1:s}\n\nNo layerId value present\n'.format(str(InFile), str(Elem.sourceline))) + Errors.append('Error 32: File\n\'{0:s}\'\nAt line {1:s}\n\nNo layerId value present\n'.format( + str(InFile), str(Elem.sourceline))) # End of if LayerId == None: @@ -1965,7 +2177,8 @@ def FzpProcessViewsTs3(InFile, Elem, Errors, Warnings, Info, FzpDict, TagStack, if Index in FzpDict: - Errors.append('Error 33: File\n\'{0:s}\'\nAt line {1:s}\n\nView {2:s} already has layerId {3:s}, {4:s} ignored\n'.format(str(InFile), str(Elem.sourceline),str(View), str(FzpDict[Index]), str(LayerId))) + Errors.append('Error 33: File\n\'{0:s}\'\nAt line {1:s}\n\nView {2:s} already has layerId {3:s}, {4:s} ignored\n'.format( + str(InFile), str(Elem.sourceline), str(View), str(FzpDict[Index]), str(LayerId))) else: @@ -1980,17 +2193,19 @@ def FzpProcessViewsTs3(InFile, Elem, Errors, Warnings, Info, FzpDict, TagStack, if not Index in FzpDict: - # this is the first and possibly only layerId so create it. + # this is the first and possibly only layerId so create it. FzpDict[Index] = [LayerId] - logging.debug (' FzpProcessViewsTs3: created LayerId %s\n', LayerId) + logging.debug( + ' FzpProcessViewsTs3: created LayerId %s\n', LayerId) elif LayerId in FzpDict[Index]: # must be unique and isn't. - Errors.append('Error 33: File\n{0:s}\nAt line {1:s}\n\nView {2:s} already has layerId {3:s}, ignored\n'.format(str(InFile), str(Elem.sourceline),str(View), str(FzpDict[Index]), str(LayerId))) + Errors.append('Error 33: File\n{0:s}\nAt line {1:s}\n\nView {2:s} already has layerId {3:s}, ignored\n'.format( + str(InFile), str(Elem.sourceline), str(View), str(FzpDict[Index]), str(LayerId))) else: @@ -1998,18 +2213,20 @@ def FzpProcessViewsTs3(InFile, Elem, Errors, Warnings, Info, FzpDict, TagStack, FzpDict[Index].append(LayerId) - logging.debug (' FzpProcessViewsTs3: appended LayerId %s\n', LayerId) + logging.debug( + ' FzpProcessViewsTs3: appended LayerId %s\n', LayerId) # End of if not Index in FzpDict: # End of if View != 'pcbView': - # if the view is pcbview and the layer is copper0 or copper1 note + # if the view is pcbview and the layer is copper0 or copper1 note # the layers presense to decide if this is a through hole or smd part # later (if there is only copper1 layer it is smd if both are present # it is through hole only copper0 is an error. - logging.debug (' FzpProcessViewsTs3: View %s LayerId %s\n', View, LayerId) + logging.debug( + ' FzpProcessViewsTs3: View %s LayerId %s\n', View, LayerId) if View == 'pcbView' and LayerId in ['copper0', 'copper1']: @@ -2023,33 +2240,37 @@ def FzpProcessViewsTs3(InFile, Elem, Errors, Warnings, Info, FzpDict, TagStack, # End of if View == 'pcbview' and LayerId in ['copper0', 'copper1']: - # State is fine as is, no need for updates here. + # State is fine as is, no need for updates here. else: # Input state incorrect so set an error. - Errors.append('Error 26: File\n\'{0:s}\'\nAt line {1:s}\n\nState error, expected tag {2:s} got tag {3:s}\n'.format(str(InFile), str(Elem.sourceline), str(State['nexttag']), str(StackTag))) - + Errors.append('Error 26: File\n\'{0:s}\'\nAt line {1:s}\n\nState error, expected tag {2:s} got tag {3:s}\n'.format( + str(InFile), str(Elem.sourceline), str(State['nexttag']), str(StackTag))) + # then set the next expected tag to be 'layer' for the layerId. State['nexttag'] = 'layer' - logging.debug (' FzpProcessViewsTs3: unknown state combination expected %s got %s\n', State['nexttag'], StackTag) + logging.debug(' FzpProcessViewsTs3: unknown state combination expected %s got %s\n', State[ + 'nexttag'], StackTag) # End of if len(TagStack) == 4: - logging.debug (' FzpProcessViewsTs3: FzpDict: %s\n', FzpDict) + logging.debug(' FzpProcessViewsTs3: FzpDict: %s\n', FzpDict) + + logging.info(' Exiting FzpProcessViewsTs3 Level %s\n', Level) - logging.info (' Exiting FzpProcessViewsTs3 Level %s\n', Level) +# End of def FzpProcessViewsTs3(InFile, Elem, Errors, Warnings, Info, +# FzpDict, TagStack, State, Level): -# End of def FzpProcessViewsTs3(InFile, Elem, Errors, Warnings, Info, FzpDict, TagStack, State, Level): def FzpCheckViews(InFile, Elem, Errors, Warnings, Info, FzpDict, TagStack, State, Level): - logging.info (' Entering FzpCheckViews Level %s\n', Level) + logging.info(' Entering FzpCheckViews Level %s\n', Level) - logging.debug (' FzpCheckViews: State: %s\n', State) + logging.debug(' FzpCheckViews: State: %s\n', State) # note no valid views seen yet @@ -2057,18 +2278,19 @@ def FzpCheckViews(InFile, Elem, Errors, Warnings, Info, FzpDict, TagStack, State if not 'views' in FzpDict: - Errors.append('Error 34: File\n\'{0:s}\'\n\nNo views found.\n'.format(str(InFile))) - + Errors.append( + 'Error 34: File\n\'{0:s}\'\n\nNo views found.\n'.format(str(InFile))) + else: # Check for unexpected View names - for View in FzpDict['views']: if View not in ['iconView', 'breadboardView', 'schematicView', 'pcbView']: - Errors.append('Error 35: File\n\'{0:s}\'\n\nUnknown view {1:s} found. (Typo?)\n'.format(str(InFile), str(View))) + Errors.append('Error 35: File\n\'{0:s}\'\n\nUnknown view {1:s} found. (Typo?)\n'.format( + str(InFile), str(View))) else: @@ -2076,7 +2298,8 @@ def FzpCheckViews(InFile, Elem, Errors, Warnings, Info, FzpDict, TagStack, State ViewsSeen += 1 - # End of if View not in ['iconView', 'breadboardView', 'schematicView', 'pcbView'] + # End of if View not in ['iconView', 'breadboardView', + # 'schematicView', 'pcbView'] # End of for View in FzpDict['views']: @@ -2086,17 +2309,19 @@ def FzpCheckViews(InFile, Elem, Errors, Warnings, Info, FzpDict, TagStack, State if ViewsSeen == 0: - Errors.append('Error 36: File\n\'{0:s}\'\n\nNo valid views found.\n'.format(str(InFile))) + Errors.append( + 'Error 36: File\n\'{0:s}\'\n\nNo valid views found.\n'.format(str(InFile))) elif ViewsSeen < 4: - Warnings.append('Warning 9: File\n\'{0:s}\'\n\nOne or more expected views missing (may be intended)\n'.format(str(InFile))) - + Warnings.append( + 'Warning 9: File\n\'{0:s}\'\n\nOne or more expected views missing (may be intended)\n'.format(str(InFile))) + # End of if ViewsSeen == 0: - # Now check for copper0 and copper1 layers. Only copper1 indicates + # Now check for copper0 and copper1 layers. Only copper1 indicates # an smd part, both copper0 and copper1 indicates a through hole part - # and only copper0 is an error. No copper or State['hybridsetforpcbView'] + # and only copper0 is an error. No copper or State['hybridsetforpcbView'] # indicates no pcb view. if 'hybridsetforpcbView' in State: @@ -2107,97 +2332,111 @@ def FzpCheckViews(InFile, Elem, Errors, Warnings, Info, FzpDict, TagStack, State elif 'copper0.layerid' in FzpDict and 'copper1.layerid' in FzpDict: - Info.append('File\n\'{0:s}\'\n\nThis is a through hole part as both copper0 and copper1 views are present.\nIf you wanted a smd part remove the copper0 definition from line {1:s}\n'.format(str(InFile), str(FzpDict['copper0.lineno']))) + Info.append('File\n\'{0:s}\'\n\nThis is a through hole part as both copper0 and copper1 views are present.\nIf you wanted a smd part remove the copper0 definition from line {1:s}\n'.format( + str(InFile), str(FzpDict['copper0.lineno']))) elif not 'copper0.layerid' in FzpDict and 'copper1.layerid' in FzpDict: - Info.append('File\n\'{0:s}\'\n\nThis is a smd part as only the copper1 view is present.\nIf you wanted a through hole part add the copper0 definition before line {1:s}\n'.format(str(InFile), str(FzpDict['copper1.lineno']))) + Info.append('File\n\'{0:s}\'\n\nThis is a smd part as only the copper1 view is present.\nIf you wanted a through hole part add the copper0 definition before line {1:s}\n'.format( + str(InFile), str(FzpDict['copper1.lineno']))) elif 'copper0.layerid' in FzpDict and not 'copper1.layerid' in FzpDict: - Errors.append('Error 37: File\n\'{0:s}\'\n\nThis is a smd part as only the copper0 view is present but it is on the bottom layer, not the top.\nIf you wanted a smd part change copper0 to copper 1 at line {1:s}\nIf you wanted a through hole part add the copper1 definition after line {1:s}\n'.format(str(InFile), str(FzpDict['copper0.lineno']))) + Errors.append('Error 37: File\n\'{0:s}\'\n\nThis is a smd part as only the copper0 view is present but it is on the bottom layer, not the top.\nIf you wanted a smd part change copper0 to copper 1 at line {1:s}\nIf you wanted a through hole part add the copper1 definition after line {1:s}\n'.format( + str(InFile), str(FzpDict['copper0.lineno']))) # End of if 'hybridsetforpcbView' in State: - logging.info (' Exiting FzpCheckViews Level %s\n', Level) + logging.info(' Exiting FzpCheckViews Level %s\n', Level) + +# End of FzpCheckViews(InFile, Elem, Errors, Warnings, Info, FzpDict, +# TagStack, State, Level): -# End of FzpCheckViews(InFile, Elem, Errors, Warnings, Info, FzpDict, TagStack, State, Level): def FzpProcessConnectorsTs3(InFile, Elem, Errors, Warnings, Info, FzpDict, TagStack, State, Level): # We are in the connectors grouping so find and record connectors and their - # attributes in the input stream. + # attributes in the input stream. - logging.info (' Entering FzpProcessConnectorsTs3 Level %s source line %s\n', Level, Elem.sourceline) + logging.info( + ' Entering FzpProcessConnectorsTs3 Level %s source line %s\n', Level, Elem.sourceline) - logging.debug (' FzpProcessConnectorsTs3: Entry TagStack %s State %s Errors %s\n', TagStack, State, Errors) + logging.debug( + ' FzpProcessConnectorsTs3: Entry TagStack %s State %s Errors %s\n', TagStack, State, Errors) - # TagStack length of 3 ('empty', 'module', 'connectors') is what tripped - # the call to this routine so we start processing at TagStack length 4 in - # this large case statement which trips when it finds the correct state + # TagStack length of 3 ('empty', 'module', 'connectors') is what tripped + # the call to this routine so we start processing at TagStack length 4 in + # this large case statement which trips when it finds the correct state # (or complains if it finds an incorrect state due to errrorS.) if len(TagStack) == 4: # Go and process the TagStack level 4 stuff (connector name type id) - FzpProcessConnectorsTs4(InFile, Elem, Errors, Warnings, Info, FzpDict, TagStack, State, Level) + FzpProcessConnectorsTs4( + InFile, Elem, Errors, Warnings, Info, FzpDict, TagStack, State, Level) elif len(TagStack) == 5: # Go and process the TagStack level 5 stuff (description or views) - FzpProcessConnectorsTs5(InFile, Elem, Errors, Warnings, Info, FzpDict, TagStack, State, Level) - + FzpProcessConnectorsTs5( + InFile, Elem, Errors, Warnings, Info, FzpDict, TagStack, State, Level) elif len(TagStack) == 6: # Go and process the TagStack level 6 stuff (viewname) - FzpProcessConnectorsTs6(InFile, Elem, Errors, Warnings, Info, FzpDict, TagStack, State, Level) + FzpProcessConnectorsTs6( + InFile, Elem, Errors, Warnings, Info, FzpDict, TagStack, State, Level) elif len(TagStack) == 7: # Go and process the TagStack level 7 stuff (p svgId layer terminalId # legId copper0 copper1 etc.) - FzpProcessConnectorsTs7(InFile, Elem, Errors, Warnings, Info, FzpDict, TagStack, State, Level) + FzpProcessConnectorsTs7( + InFile, Elem, Errors, Warnings, Info, FzpDict, TagStack, State, Level) else: - # Too many levels down in the tag stack. There is an error somewhere. + # Too many levels down in the tag stack. There is an error somewhere. - Errors.append('Error 38: File\n\'{0:s}\'\nAt line {1:s}\n\nState error, tag stack is at level {2:s} and should only go to level 7\n'.format(str(InFile), str(Elem.sourceline), str(len(TagStack)))) + Errors.append('Error 38: File\n\'{0:s}\'\nAt line {1:s}\n\nState error, tag stack is at level {2:s} and should only go to level 7\n'.format( + str(InFile), str(Elem.sourceline), str(len(TagStack)))) # End of if len(TagStack) == 4: - logging.info (' Exiting FzpProcessConnectorsTs3 Level %s\n', Level) + logging.info(' Exiting FzpProcessConnectorsTs3 Level %s\n', Level) -# End of def FzpProcessConnectorsTs4(InFile, Elem, Errors, Warnings, Info, FzpDict, TagStack, State, Level): +# End of def FzpProcessConnectorsTs4(InFile, Elem, Errors, Warnings, Info, +# FzpDict, TagStack, State, Level): -def FzpProcessConnectorsTs4(InFile, Elem, Errors, Warnings, Info, FzpDict, TagStack, State, Level): - logging.info (' Entering FzpProcessConnectorsTs4 Level %s source line %s\n', Level, Elem.sourceline) +def FzpProcessConnectorsTs4(InFile, Elem, Errors, Warnings, Info, FzpDict, TagStack, State, Level): - logging.debug (' FzpProcessConnectorsTs4: Entry TagStack %s State %s\n', TagStack, State) + logging.info( + ' Entering FzpProcessConnectorsTs4 Level %s source line %s\n', Level, Elem.sourceline) + logging.debug( + ' FzpProcessConnectorsTs4: Entry TagStack %s State %s\n', TagStack, State) LeadingConnectorRegex = re.compile(r'connector', re.IGNORECASE) # TagStack should be 'module', 'connectors', 'connector' with attributes - # name, type and id so check and process them. Check that - # State['nexttag'] is 'connector' or 'p' (from the end of a previous - # connector) to indicate that is what we are expecting at this time. - - # Because we may also have spice data here (that we want to ignore) that - # isn't on the tag stack, check if the current tag may be spice (or at - # typo, we can't tell the difference) by checking the current tag value. + # name, type and id so check and process them. Check that + # State['nexttag'] is 'connector' or 'p' (from the end of a previous + # connector) to indicate that is what we are expecting at this time. + + # Because we may also have spice data here (that we want to ignore) that + # isn't on the tag stack, check if the current tag may be spice (or at + # typo, we can't tell the difference) by checking the current tag value. # Set the value of Tag from Elem (because spice tags won't be on the stack) Tag = Elem.tag - logging.debug (' ProcessConnectorsTs4: initial Tag %s\n', Tag) + logging.debug(' ProcessConnectorsTs4: initial Tag %s\n', Tag) # Since we can have spice data inserted here, check the tag to see if it # is one we are willing to deal with. If not read on discarding and warning @@ -2210,73 +2449,81 @@ def FzpProcessConnectorsTs4(InFile, Elem, Errors, Warnings, Info, FzpDict, TagSt if not Tag in ['erc', 'voltage', 'current']: - logging.debug (' FzpProcessConnectorsTs4: assuming Tag %s is spice data\n', Tag) + logging.debug( + ' FzpProcessConnectorsTs4: assuming Tag %s is spice data\n', Tag) - Warnings.append('Warning 10: File\n\'{0:s}\'\nAt line {1:s}\n\nTag {2:s}\nis not recognized and assumed to be spice data which is ignored\n(but it might be a typo, thus this warning)\n'.format(str(InFile), str(Elem.sourceline), str(Tag))) + Warnings.append('Warning 10: File\n\'{0:s}\'\nAt line {1:s}\n\nTag {2:s}\nis not recognized and assumed to be spice data which is ignored\n(but it might be a typo, thus this warning)\n'.format( + str(InFile), str(Elem.sourceline), str(Tag))) # End of if not Tag in ['erc', 'voltage', 'current']: - + # leave the state variables as is until we find something we recognize. else: - + StackTag, StackLevel = TagStack[len(TagStack) - 1] Tag = StackTag - + if State['nexttag'] != 'connector' and State['nexttag'] != 'p': - - logging.debug (' FzpProcessConnectorsTs4: TagStack 3: %s should be p or connector\n', State['nexttag']) - - Errors.append('Error 26: File\n\'{0:s}\'\nAt line {1:s}\n\nState error, expected tag \'connector\' or \'p\' not {2:s}\n'.format(str(InFile), str(Elem.sourceline), str(State['nexttag']))) - - # End of if State['nexttag'] != 'connector' and State['nexttag'] != 'p': - + + logging.debug( + ' FzpProcessConnectorsTs4: TagStack 3: %s should be p or connector\n', State['nexttag']) + + Errors.append('Error 26: File\n\'{0:s}\'\nAt line {1:s}\n\nState error, expected tag \'connector\' or \'p\' not {2:s}\n'.format( + str(InFile), str(Elem.sourceline), str(State['nexttag']))) + + # End of if State['nexttag'] != 'connector' and State['nexttag'] != + # 'p': + # Make sure the tag we saw is connector (independent of what we # expected to see above) - + if Tag != 'connector': - - logging.debug (' FzpProcessConnectorsTs4: TagStack 3: Tag %s should be connector\n', Tag) - - Errors.append('Error 26: File\n\'{0:s}\'\nAt line {1:s}\n\nSate error, expected tag \'connector\' not {2:s}\n'.format(str(InFile), str(Elem.sourceline), str(Tag))) - + + logging.debug( + ' FzpProcessConnectorsTs4: TagStack 3: Tag %s should be connector\n', Tag) + + Errors.append('Error 26: File\n\'{0:s}\'\nAt line {1:s}\n\nSate error, expected tag \'connector\' not {2:s}\n'.format( + str(InFile), str(Elem.sourceline), str(Tag))) + # End of if Tag != 'connector': - + # Set the current tag to 'connector' - + State['lasttag'] = 'connector' - + # and that we expect a description to be next. - + State['nexttag'] = 'description' - + # Get the attribute values we should have - + Id = Elem.get('id') - + Type = Elem.get('type') - + Name = Elem.get('name') - + if Id == None: - - Errors.append('Error 39: File\n\'{0:s}\'\nAt line {1:s}\n\nConnector has no id\n'.format(str(InFile), str(Elem.sourceline))) - + + Errors.append('Error 39: File\n\'{0:s}\'\nAt line {1:s}\n\nConnector has no id\n'.format( + str(InFile), str(Elem.sourceline))) + # give it a bogus value so it has one. - + Id = 'none' - + elif Id in FzpDict: - + # If it is a dup, error! - + DupNameError(InFile, Id, Elem, Errors) - + else: - + # else mark it as seen - + FzpDict[Id] = Id # and note that we have seen this pin number. To get the number @@ -2286,8 +2533,8 @@ def FzpProcessConnectorsTs4(InFile, Elem, Errors, Warnings, Info, FzpDict, TagSt if 'pinnos' in FzpDict: - # The entry already exists so append this pin number to the - # list. + # The entry already exists so append this pin number to the + # list. FzpDict['pinnos'].append(PinNo) @@ -2298,105 +2545,116 @@ def FzpProcessConnectorsTs4(InFile, Elem, Errors, Warnings, Info, FzpDict, TagSt FzpDict['pinnos'] = [PinNo] # End of if 'pinnos' in FzpDict: - + # End of if Id == None: - - # Create an entry with unique prefix 'connectorx.id.bus so bus - # checking won't match svg terminal or leg ids, only id entries. - # Set it to itself so we know this isn't yet part of any bus during - # bus processing later. - + + # Create an entry with unique prefix 'connectorx.id.bus so bus + # checking won't match svg terminal or leg ids, only id entries. + # Set it to itself so we know this isn't yet part of any bus during + # bus processing later. + FzpDict[Id + '.id.bus'] = Id + '.id.bus' # Do the same for subparts so we are ready if buses and subparts can # ever coexist (they can't right now ...) FzpDict[Id + '.id.subpart'] = Id + '.id.subpart' - - # Set the id value in to State for later processing. - + + # Set the id value in to State for later processing. + State['lastvalue'] = Id - + if Name == None: - - Errors.append('Error 40: File\'n{0:s}\'\nAt line {1:s}\n\nConnector has no name\n'.format(str(InFile), str(elem.sourceline))) - + + Errors.append('Error 40: File\'n{0:s}\'\nAt line {1:s}\n\nConnector has no name\n'.format( + str(InFile), str(elem.sourceline))) + # give it a bogus value so it has one. - + Name = 'none' - + elif Name in FzpDict: # If it is a dup, warning if such warnings are enabled! - - logging.debug (' FzpProcessConnectorsTs4 source line %s Name %s IssueNameDupWarning \'%s\'\n', Elem.sourceline, Name, IssueNameDupWarning) - if IssueNameDupWarning == 'y': + logging.debug(' FzpProcessConnectorsTs4 source line %s Name %s IssueNameDupWarning \'%s\'\n', + Elem.sourceline, Name, IssueNameDupWarning) + + if IssueNameDupWarning == 'y': DupNameWarning(InFile, Name, Elem, Warnings) - # End of if IssueNameDupWarning == 'y': - + # End of if IssueNameDupWarning == 'y': + else: - + # else mark it as seen - + FzpDict[Name] = Name - + # End of if Name == None: - + # record the name in the dictionary - + FzpDict[Id + '.name'] = Name - - logging.debug (' FzpProcessConnectorsTs4 source line %s Tag %s Id %s Type %s Name %s\n', Elem.sourceline, Tag, Id, Type, Name) - + + logging.debug(' FzpProcessConnectorsTs4 source line %s Tag %s Id %s Type %s Name %s\n', + Elem.sourceline, Tag, Id, Type, Name) + if Type != 'male' and not 'notmalewarning' in State and not'breadboardfzp' in State: - # If this isn't a breadboard file (which has hundreds of female - # connectors) give a warning. - - Warnings.append('Warning 11: File\n\'{0:s}\'\nAt line {1:s}\n\nType {2:s} is not male (it usually should be)\n'.format(str(InFile), str(Elem.sourceline), str(Type))) + # If this isn't a breadboard file (which has hundreds of female + # connectors) give a warning. + + Warnings.append('Warning 11: File\n\'{0:s}\'\nAt line {1:s}\n\nType {2:s} is not male (it usually should be)\n'.format( + str(InFile), str(Elem.sourceline), str(Type))) # Note we have output this warning so we don't repeat it. State['notmalewarning'] = 'y' - - # End of if Type != 'male' and not 'notmalewarning' in State and not'breadboardfzp' in State: - + + # End of if Type != 'male' and not 'notmalewarning' in State and + # not'breadboardfzp' in State: + if Type == None: - + # If not flag an error as it must have one. - - Errors.append('Error 41: File\n\'{0:s}\'\nAt line {1:s}\n\nConnector {2:s} has no type\n'.format(str(InFile), str(Elem.sourceline), str(Id))) - - # then assign it a bogus value so it has one. - + + Errors.append('Error 41: File\n\'{0:s}\'\nAt line {1:s}\n\nConnector {2:s} has no type\n'.format( + str(InFile), str(Elem.sourceline), str(Id))) + + # then assign it a bogus value so it has one. + Type = 'none' - + # End of if Type == None: - + # Record the connector type indexed by connector name - + FzpDict[Id + '.type'] = Type - - logging.info (' Exiting FzpProcessConnectorsTs4\n') - # end of if Tag == None or not Tag in ['connector', 'description', 'views', 'breadboardView', 'p', 'schematicView', 'pcbView']: - -# End of FzpProcessConnectorsTs4(InFile, Elem, Errors, Warnings, Info, FzpDict, TagStack, State, Level): + logging.info(' Exiting FzpProcessConnectorsTs4\n') + + # end of if Tag == None or not Tag in ['connector', 'description', + # 'views', 'breadboardView', 'p', 'schematicView', 'pcbView']: + +# End of FzpProcessConnectorsTs4(InFile, Elem, Errors, Warnings, Info, +# FzpDict, TagStack, State, Level): + def FzpProcessConnectorsTs5(InFile, Elem, Errors, Warnings, Info, FzpDict, TagStack, State, Level): - logging.info (' Entering FzpProcessConnectorsTs5 Level %s source line %s\n', Level, Elem.sourceline) + logging.info( + ' Entering FzpProcessConnectorsTs5 Level %s source line %s\n', Level, Elem.sourceline) - logging.debug (' FzpProcessConnectorsTs5: Entry TagStack %s State %s\n', TagStack, State) + logging.debug( + ' FzpProcessConnectorsTs5: Entry TagStack %s State %s\n', TagStack, State) # Set the value of Tag from Elem (because spice tags won't be on the stack) Tag = Elem.tag - logging.debug (' FzpProcessConnectorsTs5: initial Tag %s\n', Tag) + logging.debug(' FzpProcessConnectorsTs5: initial Tag %s\n', Tag) # Since we can have spice data inserted here, check the tag to see if it # is one we are willing to deal with. If not read on discarding and warning @@ -2406,66 +2664,77 @@ def FzpProcessConnectorsTs5(InFile, Elem, Errors, Warnings, Info, FzpDict, TagSt # Assume this is spice data, but warn about it in case it is a typo - logging.debug (' FzpProcessConnectorsTs5: assuming Tag %s is spice data\n', Tag) + logging.debug( + ' FzpProcessConnectorsTs5: assuming Tag %s is spice data\n', Tag) + + Warnings.append('Warning: File\n\'{0:s}\'\nAt line {1:s}\n\nTag {2:s}\nis not recognized and assumed to be spice data which is ignored\n(but it might also be a typo, thus this warning)\n'.format( + str(InFile), str(Elem.sourceline), str(Tag))) - Warnings.append('Warning: File\n\'{0:s}\'\nAt line {1:s}\n\nTag {2:s}\nis not recognized and assumed to be spice data which is ignored\n(but it might also be a typo, thus this warning)\n'.format(str(InFile), str(Elem.sourceline), str(Tag))) - # leave the state variables as is until we find something we recognize. else: - + # Set Id from State['lastvalue'] - + Id = State['lastvalue'] - - # We should now have either description or views so check what we - # expect and then what we actually have. - + + # We should now have either description or views so check what we + # expect and then what we actually have. + if State['nexttag'] != 'description' and State['nexttag'] != 'views': - - Errors.append('Error 26: File\n\'{0:s}\'\nAt line {1:s}\n\nState error, expected tag \'description\' or \'views\' not {2:s}\n'.format(str(InFile), str(Elem.sourceline), str(State['nexttag']))) - - # End of if State['nexttag'] != 'description' and State['nexttag'] != 'views': - if Tag == 'description': - - # All we need to do is set up the last and next tags. - + + Errors.append('Error 26: File\n\'{0:s}\'\nAt line {1:s}\n\nState error, expected tag \'description\' or \'views\' not {2:s}\n'.format( + str(InFile), str(Elem.sourceline), str(State['nexttag']))) + + # End of if State['nexttag'] != 'description' and State['nexttag'] != + # 'views': + if Tag == 'description': + + # All we need to do is set up the last and next tags. + State['lasttag'] = 'description' - + State['nexttag'] = 'views' - + elif Tag == 'views': - + # All we need to do is check the last tag was 'description' then # set up the last and next tags. - + if State['lasttag'] != 'description': - - Errors.append('Error 42: File\n\'{0:s}\'\nAt line {1:s}\n\nConnector {2:s} has no description\n'.format(str(InFile), str(Elem.sourceline), str(Id))) - + + Errors.append('Error 42: File\n\'{0:s}\'\nAt line {1:s}\n\nConnector {2:s} has no description\n'.format( + str(InFile), str(Elem.sourceline), str(Id))) + # End of if State['lasttag'] != 'description': - + State['lastag'] = 'views' - + State['nexttag'] = 'viewname' - + else: - - Errors.append('Error 26: File\n\'{0:s}\'\nAt line {1:s}\n\nState error, connector {2:s}, expected tag \'description\' or \'views\' got {3:s}\n'.format(str(InFile), str(Elem.sourceline), str(Id), str(Tag))) - + + Errors.append('Error 26: File\n\'{0:s}\'\nAt line {1:s}\n\nState error, connector {2:s}, expected tag \'description\' or \'views\' got {3:s}\n'.format( + str(InFile), str(Elem.sourceline), str(Id), str(Tag))) + # End of if Tag == 'description': - - # End of if not Tag in ['connector', 'description', 'views', 'breadboardView', 'p', 'schematicView', 'pcbView']: - logging.info (' Exiting FzpProcessConnectorsTs5\n') + # End of if not Tag in ['connector', 'description', 'views', + # 'breadboardView', 'p', 'schematicView', 'pcbView']: + + logging.info(' Exiting FzpProcessConnectorsTs5\n') + +# End of FzpProcessConnectorsTs5(InFile, Elem, Errors, Warnings, Info, +# FzpDict, TagStack, State, Level): -#End of FzpProcessConnectorsTs5(InFile, Elem, Errors, Warnings, Info, FzpDict, TagStack, State, Level): def FzpProcessConnectorsTs6(InFile, Elem, Errors, Warnings, Info, FzpDict, TagStack, State, Level): - logging.info (' Entering FzpProcessConnectorsTs6 Level %s source line %s\n', Level, Elem.sourceline) + logging.info( + ' Entering FzpProcessConnectorsTs6 Level %s source line %s\n', Level, Elem.sourceline) - logging.debug (' FzpProcessConnectorsTs6: Entry TagStack %s State %s\n', TagStack, State) + logging.debug( + ' FzpProcessConnectorsTs6: Entry TagStack %s State %s\n', TagStack, State) # Set the value of Tag from the TagStack @@ -2479,28 +2748,32 @@ def FzpProcessConnectorsTs6(InFile, Elem, Errors, Warnings, Info, FzpDict, TagSt if Tag == 'p': - Errors.append('Error 43: File\n\'{0:s}\'\nAt line {1:s}\n\nConnector {2:s} missing viewname\n'.format(str(InFile), str(Elem.sourceline), str(Id))) - + Errors.append('Error 43: File\n\'{0:s}\'\nAt line {1:s}\n\nConnector {2:s} missing viewname\n'.format( + str(InFile), str(Elem.sourceline), str(Id))) + State['lasttag'] = 'viewname' - State['nexttag'] = 'p' + State['nexttag'] = 'p' elif State['nexttag'] != 'p' and State['nexttag'] != 'viewname': - Errors.append('Error 26: File\n\'{0:s}\'\nAt line {1:s}\n\nState error, connector {2:s}, expected \'p\' or \'viewname\' got {3:s}\n'.format(str(InFile), str(Elem.sourceline), str(Id), str(State['nexttag']))) + Errors.append('Error 26: File\n\'{0:s}\'\nAt line {1:s}\n\nState error, connector {2:s}, expected \'p\' or \'viewname\' got {3:s}\n'.format( + str(InFile), str(Elem.sourceline), str(Id), str(State['nexttag']))) # It is unclear what State should be so leave it as is which will # likely cause an error cascade, but we have flagged the first one. else: - # We look to have a view name so process it. + # We look to have a view name so process it. if Tag not in ['breadboardView', 'schematicView', 'pcbView']: - logging.debug (' ProcessConnectorsTs6 source line %s Append invalid tag error Tag %s TagStack %s State %s\n', Elem.sourceline, Tag, TagStack, State) + logging.debug(' ProcessConnectorsTs6 source line %s Append invalid tag error Tag %s TagStack %s State %s\n', + Elem.sourceline, Tag, TagStack, State) - Errors.append('Error 44: File\n\'{0:s}\'\nAt line {1:s}\n\nViewname {2:s} invalid (typo?)\n'.format(str(InFile), str(Elem.sourceline), str(Tag))) + Errors.append('Error 44: File\n\'{0:s}\'\nAt line {1:s}\n\nViewname {2:s} invalid (typo?)\n'.format( + str(InFile), str(Elem.sourceline), str(Tag))) else: @@ -2516,18 +2789,22 @@ def FzpProcessConnectorsTs6(InFile, Elem, Errors, Warnings, Info, FzpDict, TagSt # End of if Tag == 'p': - logging.debug (' FzpProcessConnectorsTs6: Exit TagStack %s State %s\n', TagStack, State) + logging.debug( + ' FzpProcessConnectorsTs6: Exit TagStack %s State %s\n', TagStack, State) - logging.info (' Exiting FzpProcessConnectorsTs6\n') + logging.info(' Exiting FzpProcessConnectorsTs6\n') -# End of def FzpProcessConnectorsTs6(InFile, Elem, Errors, Warnings, Info, FzpDict, TagStack, State, Level): +# End of def FzpProcessConnectorsTs6(InFile, Elem, Errors, Warnings, Info, +# FzpDict, TagStack, State, Level): def FzpProcessConnectorsTs7(InFile, Elem, Errors, Warnings, Info, FzpDict, TagStack, State, Level): - logging.info (' Entering FzpProcessConnectorsTs7 Level %s source line %s\n', Level, Elem.sourceline) + logging.info( + ' Entering FzpProcessConnectorsTs7 Level %s source line %s\n', Level, Elem.sourceline) - logging.debug (' FzpProcessConnectorsTs7: Entry TagStack %s State %s\n', TagStack, State) + logging.debug( + ' FzpProcessConnectorsTs7: Entry TagStack %s State %s\n', TagStack, State) # Set the value of Tag from the TagStack @@ -2541,23 +2818,25 @@ def FzpProcessConnectorsTs7(InFile, Elem, Errors, Warnings, Info, FzpDict, TagSt if not State['nexttag'] == 'p': - # expected state doesn't match. + # expected state doesn't match. - logging.debug (' FzpProcessConnectorsTs7 source line %s State[\'nexttag\'] %s isn\'t \'p\'\n', Elem.sourceline, State['nexttag']) + logging.debug( + ' FzpProcessConnectorsTs7 source line %s State[\'nexttag\'] %s isn\'t \'p\'\n', Elem.sourceline, State['nexttag']) - Errors.append('Error 26: File\n\'{0:s}\'\nAt line {1:s}\n\nState error, expected tag \'p\' got {2:s}\n'.format(str(InFile), str(Elem.sourceline), str(State['nexttag']))) + Errors.append('Error 26: File\n\'{0:s}\'\nAt line {1:s}\n\nState error, expected tag \'p\' got {2:s}\n'.format( + str(InFile), str(Elem.sourceline), str(State['nexttag']))) # unclear what State should be so leave as is which may cause an - # error cascade. + # error cascade. else: if Tag == 'p': - # We have found a 'p' line which means we have the associated - # view id on the tag stack and need to add the connector names - # to the dictionary for use checking the pins in the svgs - # later. + # We have found a 'p' line which means we have the associated + # view id on the tag stack and need to add the connector names + # to the dictionary for use checking the pins in the svgs + # later. # Get the viewname from the TagStack. @@ -2565,7 +2844,7 @@ def FzpProcessConnectorsTs7(InFile, Elem, Errors, Warnings, Info, FzpDict, TagSt View = StackTag - logging.debug (' FzpProcessConnectorsTs7 View set to %s\n', View) + logging.debug(' FzpProcessConnectorsTs7 View set to %s\n', View) # We need a layer value (even if it is None) for the index. @@ -2575,49 +2854,55 @@ def FzpProcessConnectorsTs7(InFile, Elem, Errors, Warnings, Info, FzpDict, TagSt Layer = 'none' - logging.debug (' FzpProcessConnectorsTs7 source line %s missing layer\n', Elem.sourceline) + logging.debug( + ' FzpProcessConnectorsTs7 source line %s missing layer\n', Elem.sourceline) - Errors.append('Error 45: File\n\'{0:s}\'\nAt line {1:s}\n\nLayer missing\n'.format(str(InFile), str(Elem.sourceline))) + Errors.append('Error 45: File\n\'{0:s}\'\nAt line {1:s}\n\nLayer missing\n'.format( + str(InFile), str(Elem.sourceline))) # End of if Layer == None: - # Verify the layerId is correct. + # Verify the layerId is correct. - if not View + '.' + 'LayerId' in FzpDict: + if not View + '.' + 'LayerId' in FzpDict: # Don't have a layerId for this view! - Errors.append('Error 46: File\n\'{0:s}\'\nAt line {1:s}\n\nNo layerId for View {2:s}\n'.format(str(InFile), str(Elem.sourceline), str(View))) + Errors.append('Error 46: File\n\'{0:s}\'\nAt line {1:s}\n\nNo layerId for View {2:s}\n'.format( + str(InFile), str(Elem.sourceline), str(View))) - elif View != 'pcbView' and Layer != FzpDict[View + '.' + 'LayerId']: + elif View != 'pcbView' and Layer != FzpDict[View + '.' + 'LayerId']: # For all except pcbView, the layerIds don't match. - Errors.append('Error 47: File\n\'{0:s}\'\nAt line {1:s}\n\nLayerId {2:s} doesn\'t match View {3:s} layerId {4:s}\n'.format(str(InFile), str(Elem.sourceline), str(Layer), str(View), str(FzpDict[View + '.' + 'LayerId']))) + Errors.append('Error 47: File\n\'{0:s}\'\nAt line {1:s}\n\nLayerId {2:s} doesn\'t match View {3:s} layerId {4:s}\n'.format( + str(InFile), str(Elem.sourceline), str(Layer), str(View), str(FzpDict[View + '.' + 'LayerId']))) elif View == 'pcbView': - if not Layer in FzpDict[View + '.' + 'LayerId']: + if not Layer in FzpDict[View + '.' + 'LayerId']: # Layer isn't a valid layer for pcbView. - Errors.append('Error 47: File\n\'{0:s}\'\nAt line {1:s}\n\nLayerId {2:s} doesn\'t match any in View {3:s} layerIds {4:s}\n'.format(str(InFile), str(Elem.sourceline), str(Layer), str(View), str(FzpDict[View + '.' + 'LayerId']))) + Errors.append('Error 47: File\n\'{0:s}\'\nAt line {1:s}\n\nLayerId {2:s} doesn\'t match any in View {3:s} layerIds {4:s}\n'.format( + str(InFile), str(Elem.sourceline), str(Layer), str(View), str(FzpDict[View + '.' + 'LayerId']))) elif Layer == 'copper0': - # While multiple layers are allowed, only copper0 and + # While multiple layers are allowed, only copper0 and # copper1 (if they exist) are allowed in connectors and - # they must be unique. + # they must be unique. if Id + '.' + Layer in FzpDict: - # Not unique so error. + # Not unique so error. - Errors.append('Error 48: File\n\'{0:s}\'\nAt line {1:s}\n\nConnector {2:s} layer {3:s} already defined, must be unique\n'.format(str(InFile), str(Elem.sourceline), str(Id), str(Layer))) + Errors.append('Error 48: File\n\'{0:s}\'\nAt line {1:s}\n\nConnector {2:s} layer {3:s} already defined, must be unique\n'.format( + str(InFile), str(Elem.sourceline), str(Id), str(Layer))) else: - - # It is unique so note that we have seen it now. + + # It is unique so note that we have seen it now. FzpDict[Id + '.' + Layer] = 'y' @@ -2625,19 +2910,20 @@ def FzpProcessConnectorsTs7(InFile, Elem, Errors, Warnings, Info, FzpDict, TagSt elif Layer == 'copper1': - # While multiple layers are allowed, only copper0 and + # While multiple layers are allowed, only copper0 and # copper1 (if they exist) are allowed in connectors and - # they must be unique. + # they must be unique. if Id + '.' + Layer in FzpDict: - # Not unique so error. + # Not unique so error. - Errors.append('Error 48: File\n\'{0:s}\'\nAt line {1:s}\n\nConnector {2:s} layer {3:s} already defined, must be unique\n'.format(str(InFile), str(Elem.sourceline), str(Id), str(Layer))) + Errors.append('Error 48: File\n\'{0:s}\'\nAt line {1:s}\n\nConnector {2:s} layer {3:s} already defined, must be unique\n'.format( + str(InFile), str(Elem.sourceline), str(Id), str(Layer))) else: - - # It is unique so note that we have seen it now. + + # It is unique so note that we have seen it now. FzpDict[Id + '.' + Layer] = 'y' @@ -2647,7 +2933,7 @@ def FzpProcessConnectorsTs7(InFile, Elem, Errors, Warnings, Info, FzpDict, TagSt # End of if not View + '.' + 'LayerId' in FzpDict: - # Get the hybrid attribute if present (as it affects checking + # Get the hybrid attribute if present (as it affects checking # below) Hybrid = Elem.get('hybrid') @@ -2659,7 +2945,8 @@ def FzpProcessConnectorsTs7(InFile, Elem, Errors, Warnings, Info, FzpDict, TagSt if Hybrid != 'yes': - Errors.append('Error 49: File\n\'{0:s}\'\nAt line {1:s}\n\nhybrid is present but isn\'t \'yes\' but {2:s} (typo?)\n'.format(str(InFile), str(Elem.eline),str(Hybrid))) + Errors.append('Error 49: File\n\'{0:s}\'\nAt line {1:s}\n\nhybrid is present but isn\'t \'yes\' but {2:s} (typo?)\n'.format( + str(InFile), str(Elem.eline), str(Hybrid))) else: @@ -2675,14 +2962,14 @@ def FzpProcessConnectorsTs7(InFile, Elem, Errors, Warnings, Info, FzpDict, TagSt # End of if Hybrid != None: - logging.debug (' FzpProcessConnectorsTs7 Layer set to %s\n', Layer) + logging.debug(' FzpProcessConnectorsTs7 Layer set to %s\n', Layer) - # then get all the attributes and check their values as + # then get all the attributes and check their values as # appropriate. Mark we haven't yet seen a svgid, terminalId or - # legId. A svgId is required and will cause an error, terminalId - # will be warned about (becuase it is usually an error) in - # schematicview and both a TerminalId and a LegId is an error, it - # must be one or the other not both. + # legId. A svgId is required and will cause an error, terminalId + # will be warned about (becuase it is usually an error) in + # schematicview and both a TerminalId and a LegId is an error, it + # must be one or the other not both. SvgIdSeen = 'n' @@ -2692,15 +2979,18 @@ def FzpProcessConnectorsTs7(InFile, Elem, Errors, Warnings, Info, FzpDict, TagSt for Key in Elem.keys(): - logging.debug (' FzpProcessConnectorsTs7: source line %s Tag %s Id %s Key %s\n', Elem.sourceline, Tag, Id, Key) + logging.debug( + ' FzpProcessConnectorsTs7: source line %s Tag %s Id %s Key %s\n', Elem.sourceline, Tag, Id, Key) if Key not in ['terminalId', 'svgId', 'layer', 'legId', 'hybrid']: # Warn about a non standard key ... - logging.debug (' FzpProcessConnectorsTs7 unknown key %s\n', Key) + logging.debug( + ' FzpProcessConnectorsTs7 unknown key %s\n', Key) - Warnings.append('Warning 12: File\n\'{0:s}\'\nAt line {1:s}\n\nKey {2:s} is not recognized\n'.format(str(InFile), str(Elem.sourceline), str(Key))) + Warnings.append('Warning 12: File\n\'{0:s}\'\nAt line {1:s}\n\nKey {2:s} is not recognized\n'.format( + str(InFile), str(Elem.sourceline), str(Key))) # End of if Key not in ['terminalId', 'svgId', 'layer', 'legId']: # Now get the value of the key. @@ -2709,7 +2999,8 @@ def FzpProcessConnectorsTs7(InFile, Elem, Errors, Warnings, Info, FzpDict, TagSt if Key == None: - Errors.append('Error 50: File\n\'{0:s}\'\nAt line {1:s}\n\nTag {2:s} is present but has no value\n'.format(str(InFile), str(Elem.sourceline),str(Key))) + Errors.append('Error 50: File\n\'{0:s}\'\nAt line {1:s}\n\nTag {2:s} is present but has no value\n'.format( + str(InFile), str(Elem.sourceline), str(Key))) # End of if Key == None" @@ -2717,8 +3008,8 @@ def FzpProcessConnectorsTs7(InFile, Elem, Errors, Warnings, Info, FzpDict, TagSt if Key == 'svgId': - # Note that we have seen an svgId tag (if the value is - # None, the error will have been noted above.) + # Note that we have seen an svgId tag (if the value is + # None, the error will have been noted above.) SvgIdSeen = 'y' @@ -2726,22 +3017,21 @@ def FzpProcessConnectorsTs7(InFile, Elem, Errors, Warnings, Info, FzpDict, TagSt if Key == 'terminalId': - # Note that we have seen an terminalId tag (if the value - # is None, the error will have been noted above.) + # Note that we have seen an terminalId tag (if the value + # is None, the error will have been noted above.) TerminalIdSeen = 'y' - + # End of if Key == 'terminalId': if Key == 'legId': - # Note that we have seen an legId tag (if the value is - # None, the error will have been noted above.) + # Note that we have seen an legId tag (if the value is + # None, the error will have been noted above.) LegIdSeen = 'y' # End of if Key == 'legId': - if Key == 'layer': @@ -2752,12 +3042,13 @@ def FzpProcessConnectorsTs7(InFile, Elem, Errors, Warnings, Info, FzpDict, TagSt if View + '.layer' in FzpDict: - # Already exists so append this one if it isn't + # Already exists so append this one if it isn't # already present. if not Layer in FzpDict[View + '.layer']: - logging.debug (' FzpProcessConnectorsTs7: source line %s View %s layer %s added\n', Elem.sourceline, View, Layer) + logging.debug( + ' FzpProcessConnectorsTs7: source line %s View %s layer %s added\n', Elem.sourceline, View, Layer) FzpDict[View + '.layer'].append(Layer) @@ -2767,7 +3058,8 @@ def FzpProcessConnectorsTs7(InFile, Elem, Errors, Warnings, Info, FzpDict, TagSt # Doesn't exist yet, so create it and add the layer. - logging.debug (' FzpProcessConnectorsTs7: source line %s View %s, create and add layer %s added\n', Elem.sourceline, View, Layer) + logging.debug( + ' FzpProcessConnectorsTs7: source line %s View %s, create and add layer %s added\n', Elem.sourceline, View, Layer) FzpDict[View + '.layer'] = [Layer] # End of if View + '.layer' in FzpDict: @@ -2777,44 +3069,46 @@ def FzpProcessConnectorsTs7(InFile, Elem, Errors, Warnings, Info, FzpDict, TagSt # Key isn't layer so if it is a connector and Hybrid isn't # set to 'yes' (in which case the connector will be ignored # as this view is unused) - + if Key in ['terminalId', 'svgId', 'legId'] and Hybrid != 'yes': # Check if it matches with the connector defined - + if not re.match(Id, Value): # No, flag it as a warning, as it is unusual (but # not illegal) and thus possibly an error. - - logging.debug (' FzpProcessConnectorsTs7: Id %s doesn\'t match Value %s\n',Id, Value) - Warnings.append('Warning 13: File\n\'{0:s}\'\nAt line {1:s}\n\nValue {2:s} doesn\'t match Id {3:s}. (Typo?)\n'.format(str(InFile), str(Elem.sourceline), str(Value), str(Id))) + logging.debug( + ' FzpProcessConnectorsTs7: Id %s doesn\'t match Value %s\n', Id, Value) + Warnings.append('Warning 13: File\n\'{0:s}\'\nAt line {1:s}\n\nValue {2:s} doesn\'t match Id {3:s}. (Typo?)\n'.format( + str(InFile), str(Elem.sourceline), str(Value), str(Id))) # End of if not re.match(Id, Value): # Now make sure this connector is unique in this view - # and if it is add it to the list of connectors to + # and if it is add it to the list of connectors to # verify is in the associated svg. if not View + '.' + Value + '.' + Layer in FzpDict: # This is one of the pin names and we haven't seen - # it before, so add it to the connectors list for + # it before, so add it to the connectors list for # matching in the svg. Indicate we have seen this # connector (in case we see another) FzpDict[View + '.' + Value + '.' + Layer] = 'y' - # If the entry for this view doesn't exist yet, + # If the entry for this view doesn't exist yet, # create it and add this connector to the list # otherwise append the connector to the existing - # list (weeding out duplicate . + # list (weeding out duplicate . if not 'connectors.fzp.' + View in FzpDict: - - logging.debug (' FzpProcessConnectorsTs7: create %s add %s\n','connectors.fzp.' + View, Value) + + logging.debug( + ' FzpProcessConnectorsTs7: create %s add %s\n', 'connectors.fzp.' + View, Value) # First connector so create the list. @@ -2822,29 +3116,34 @@ def FzpProcessConnectorsTs7(InFile, Elem, Errors, Warnings, Info, FzpDict, TagSt else: - - logging.debug (' FzpProcessConnectorsTs7: View %s conents %s\n','connectors.fzp.' + View, FzpDict['connectors.fzp.' + View]) + logging.debug(' FzpProcessConnectorsTs7: View %s conents %s\n', + 'connectors.fzp.' + View, FzpDict['connectors.fzp.' + View]) if not Value in FzpDict['connectors.fzp.' + View]: # For pcb view pins will appear twice, once # for copper0 and once for copper1, we only - # need one value so if it is already here + # need one value so if it is already here # don't add a new one. - logging.debug (' FzpProcessConnectorsTs7: add %s add %s\n','connectors.fzp.' + View, Value) + logging.debug( + ' FzpProcessConnectorsTs7: add %s add %s\n', 'connectors.fzp.' + View, Value) - FzpDict['connectors.fzp.' + View].append(Value) + FzpDict['connectors.fzp.' + + View].append(Value) - # End of if not Value in FzpDict['connectors.fzp.' + View]: + # End of if not Value in + # FzpDict['connectors.fzp.' + View]: - # End of if not 'connectors.fzp.' + View in FzpDict: + # End of if not 'connectors.fzp.' + View in + # FzpDict: - # End of if not View + '.' + Value + '.' + Layer in FzpDict: + # End of if not View + '.' + Value + '.' + Layer in + # FzpDict: if View == 'schematicView': - # This is schematic view, so in case this is a + # This is schematic view, so in case this is a # subpart, associate the pins with the connectorId if not 'schematic.' + Id in FzpDict: @@ -2859,7 +3158,8 @@ def FzpProcessConnectorsTs7(InFile, Elem, Errors, Warnings, Info, FzpDict, TagSt # End of if View == 'schematicView': - # End of if Key in ['terminalId', 'svgId', 'legId'] and Hybrid != 'yes': + # End of if Key in ['terminalId', 'svgId', 'legId'] and + # Hybrid != 'yes': # End of if Key == 'layer': @@ -2869,43 +3169,50 @@ def FzpProcessConnectorsTs7(InFile, Elem, Errors, Warnings, Info, FzpDict, TagSt # complained about a missing layer above so only do svgId and if # view is schematicview, terminalId as a warning, here.TerminalId # and legId are optional although no terminalId is usually an error - # in schematic, only svgId is required, but if hybrid is 'yes' + # in schematic, only svgId is required, but if hybrid is 'yes' # even that is optional. However both a terminalId and a legID are - # an error so note that. + # an error so note that. if TerminalIdSeen == 'y' and LegIdSeen == 'y': - Errors.append('Error 80: File\n\'{0:s}\'\nAt line {1:s}\n\nBoth terminalId and legId present, only one or the other is allowed.\n'.format(str(InFile), str(Elem.sourceline))) + Errors.append('Error 80: File\n\'{0:s}\'\nAt line {1:s}\n\nBoth terminalId and legId present, only one or the other is allowed.\n'.format( + str(InFile), str(Elem.sourceline))) # End of if TerminalIdSeen == 'y' and LegIdSeen == 'y': if SvgIdSeen != 'y' and Hybrid != 'yes': - Errors.append('Error 51: File\n\'{0:s}\'\nAt line {1:s}\n\nsvgId missing\n'.format(str(InFile), str(Elem.sourceline))) - + Errors.append('Error 51: File\n\'{0:s}\'\nAt line {1:s}\n\nsvgId missing\n'.format( + str(InFile), str(Elem.sourceline))) + # End of if SvgIdSeen != 'y' and Hybrid != 'yes': if TerminalIdSeen != 'y' and View == 'schematicView' and Hybrid != 'yes': - Warnings.append('Warning 14: File\n\'{0:s}\'\nAt line {1:s}\n\nterminalId missing in schematicView (likely an error)\n'.format(str(InFile), str(Elem.sourceline))) + Warnings.append('Warning 14: File\n\'{0:s}\'\nAt line {1:s}\n\nterminalId missing in schematicView (likely an error)\n'.format( + str(InFile), str(Elem.sourceline))) - # End of if TerminalIdSeen != 'y' and View == 'schematicview' and Hybrid != 'yes': + # End of if TerminalIdSeen != 'y' and View == 'schematicview' and + # Hybrid != 'yes': # End of if Tag == 'p': # End of if not State['nexttag'] == 'p': - logging.debug (' Exiting FzpProcessConnectorsTs7: source line %s tag %s attrib %s TagStack %s State %s\n', Elem.sourceline, Elem.tag, Elem.attrib, TagStack, State) + logging.debug(' Exiting FzpProcessConnectorsTs7: source line %s tag %s attrib %s TagStack %s State %s\n', + Elem.sourceline, Elem.tag, Elem.attrib, TagStack, State) - logging.info (' Exiting FzpProcessConnectorsTs7\n') + logging.info(' Exiting FzpProcessConnectorsTs7\n') + +# End of FzpProcessConnectorsTs7(InFile, Elem, Errors, Warnings, Info, +# FzpDict, TagStack, State, Level): -# End of FzpProcessConnectorsTs7(InFile, Elem, Errors, Warnings, Info, FzpDict, TagStack, State, Level): def FzpProcessBusTs3(InFile, Elem, Errors, Warnings, Info, FzpDict, TagStack, State, Level): - logging.info (' Entering FzpProcessBusTs3 Level %s\n', Level) + logging.info(' Entering FzpProcessBusTs3 Level %s\n', Level) - # TagStack length of 3 ('empty', 'module', 'buses') is what tripped the - # call to this routine so we start processing at TagStack length 3 in this + # TagStack length of 3 ('empty', 'module', 'buses') is what tripped the + # call to this routine so we start processing at TagStack length 3 in this # case statement which trips when it finds the correct state (or complains # if it finds an incorrect state due to errors.) @@ -2913,40 +3220,49 @@ def FzpProcessBusTs3(InFile, Elem, Errors, Warnings, Info, FzpDict, TagStack, St # Go and process the TagStack level 4 stuff (bus for the bus id) - FzpProcessBusTs4(InFile, Elem, Errors, Warnings, Info, FzpDict, TagStack, State, Level) + FzpProcessBusTs4(InFile, Elem, Errors, Warnings, Info, + FzpDict, TagStack, State, Level) elif len(TagStack) == 5: # Go and process the TagStack level 5 stuff (nodeMembers) - FzpProcessBusTs5(InFile, Elem, Errors, Warnings, Info, FzpDict, TagStack, State, Level) + FzpProcessBusTs5(InFile, Elem, Errors, Warnings, Info, + FzpDict, TagStack, State, Level) elif len(TagStack) > 5: - # There shouldn't be anything past 5th level so something is wrong. + # There shouldn't be anything past 5th level so something is wrong. - Errors.append('Error 38: File\n\'{0:s}\'\nAt line {1:s}\n\nState error, tag stack is at level {2:s} and should only go to level 5\n\nTag {3:s} will be ignored\n'.format(str(InFile), str(Elem.sourceline), str(len(TagStack)), str(Tag))) + Errors.append('Error 38: File\n\'{0:s}\'\nAt line {1:s}\n\nState error, tag stack is at level {2:s} and should only go to level 5\n\nTag {3:s} will be ignored\n'.format( + str(InFile), str(Elem.sourceline), str(len(TagStack)), str(Tag))) # End of if len(TagStack) == 4: - - logging.info (' Exiting FzpProcessBusTs3 Level %s\n', Level) -# End of def FzpProcessBusTs3(InFile, Elem, Errors, Warnings, Info, FzpDict, TagStack, State, Level): + logging.info(' Exiting FzpProcessBusTs3 Level %s\n', Level) + +# End of def FzpProcessBusTs3(InFile, Elem, Errors, Warnings, Info, +# FzpDict, TagStack, State, Level): + def FzpProcessBusTs4(InFile, Elem, Errors, Warnings, Info, FzpDict, TagStack, State, Level): - logging.info (' Entering FzpProcessBusTs4 level %s source line %s\n', Level, Elem.sourceline) + logging.info( + ' Entering FzpProcessBusTs4 level %s source line %s\n', Level, Elem.sourceline) - logging.debug (' FzpProcessBusTs4: Entry TagStack %s State %s\n', TagStack, State) + logging.debug( + ' FzpProcessBusTs4: Entry TagStack %s State %s\n', TagStack, State) if not State['lasttag'] in ['buses', 'bus', 'nodeMember']: - logging.debug (' FzpProcessBusTs4: Unexpected state %s expected buses or nodeMember\n',State['lasttag']) + logging.debug( + ' FzpProcessBusTs4: Unexpected state %s expected buses or nodeMember\n', State['lasttag']) - # Not the expected state possibly a missing line. + # Not the expected state possibly a missing line. + + Errors.append('Error 26: File\n\'{0:s}\'\nAt line {1:s}\n\nState error, expected lasttag \'buses\' or \'nodeMember\' not {2:s}\n(Missing line?)\n'.format( + str(InFile), str(Elem.sourceline), str(State['lasttag']))) - Errors.append('Error 26: File\n\'{0:s}\'\nAt line {1:s}\n\nState error, expected lasttag \'buses\' or \'nodeMember\' not {2:s}\n(Missing line?)\n'.format(str(InFile), str(Elem.sourceline), str(State['lasttag']))) - # End of if not State['lasttag'] in ['buses', 'nodeMember']: StackTag, StackLevel = TagStack[len(TagStack) - 1] @@ -2955,16 +3271,18 @@ def FzpProcessBusTs4(InFile, Elem, Errors, Warnings, Info, FzpDict, TagStack, St if Tag != 'bus': - logging.debug (' FzpProcessBusTs4: Unexpected Tag %s expected bus\n', Tag) + logging.debug( + ' FzpProcessBusTs4: Unexpected Tag %s expected bus\n', Tag) + + Errors.append('Error 26: File\n\'{0:s}\'\nAt line {1:s}\n\nState error, expected tag \'bus\' not {2:s}. (Missing line?)\n'.format( + str(InFile), str(Elem.sourceline), str(Tag))) - Errors.append('Error 26: File\n\'{0:s}\'\nAt line {1:s}\n\nState error, expected tag \'bus\' not {2:s}. (Missing line?)\n'.format(str(InFile), str(Elem.sourceline), str(Tag))) - # it is unclear what state should be so leave it as is which may cause # an error cascade ... else: - # We look to have a bus line so get the bus id. + # We look to have a bus line so get the bus id. Id = Elem.get('id') @@ -2977,52 +3295,55 @@ def FzpProcessBusTs4(InFile, Elem, Errors, Warnings, Info, FzpDict, TagStack, St FzpDict['empty_bus_defined'] = 'y' - Warnings.append('Warning 15: File:\n\'{0:s}\'\nAt line {1:s}\n\nEmpty bus definition, no id (remove?)\n'.format(str(InFile), str(Elem.sourceline))) + Warnings.append('Warning 15: File:\n\'{0:s}\'\nAt line {1:s}\n\nEmpty bus definition, no id (remove?)\n'.format( + str(InFile), str(Elem.sourceline))) - else: + else: - # and note we have seen a bus (not just the buses tag) for subparts - # but we haven't put out an error message for it yet if there is a - # sub parts definition later, we will. + # and note we have seen a bus (not just the buses tag) for subparts + # but we haven't put out an error message for it yet if there is a + # sub parts definition later, we will. FzpDict['bus_defined'] = 'n' - logging.debug (' FzpProcessBusTs4: source line %s Tag %s Id %s State %s\n', Elem.sourceline, Tag, Id, State) + logging.debug(' FzpProcessBusTs4: source line %s Tag %s Id %s State %s\n', + Elem.sourceline, Tag, Id, State) if Id + '.bus_seen' in FzpDict: - + # Not unique error - + DupNameError(InFile, Id, Elem, Errors) - + else: - - logging.debug (' FzpProcessBusTs4: Marked Id %s seen\n', Id) - - # else mark it as seen - + + logging.debug(' FzpProcessBusTs4: Marked Id %s seen\n', Id) + + # else mark it as seen + FzpDict[Id + '.bus_seen'] = Id - + # End of if Id + '.bus_seen' in FzpDict: - + # End of Id == None: # Set the bus id even if it is None, so we don't impact the last bus - # with the current information. + # with the current information. State['lastvalue'] = Id if (Id + '.bus') in FzpDict: - logging.debug (' FzpProcessBusTs4: Id %s already exists\n', Id) + logging.debug(' FzpProcessBusTs4: Id %s already exists\n', Id) # If we already have this bus id flag an error. - Errors.append('Error 52: File\n\'{0:s}\'\nAt line {1:s}\n\nBus {2:s} already defined\n'.format(str(InFile), str(Elem.sourceline), str(Id))) + Errors.append('Error 52: File\n\'{0:s}\'\nAt line {1:s}\n\nBus {2:s} already defined\n'.format( + str(InFile), str(Elem.sourceline), str(Id))) else: - logging.debug (' FzpProcessBusTs4: created counter for Id %s\n', Id) + logging.debug(' FzpProcessBusTs4: created counter for Id %s\n', Id) # mark this as a bus currently with no nodes. @@ -3036,22 +3357,28 @@ def FzpProcessBusTs4(InFile, Elem, Errors, Warnings, Info, FzpDict, TagStack, St State['nexttag'] = 'nodeMember' - logging.debug (' FzpProcessBusTs4: source line %s end of bus Id %s State %s\n', Elem.sourceline, Id, State) + logging.debug( + ' FzpProcessBusTs4: source line %s end of bus Id %s State %s\n', Elem.sourceline, Id, State) # End of if Tag != 'bus': - logging.info (' Exiting FzpProcessBusTs4 level %s source line %s\n', Level, Elem.sourceline) + logging.info( + ' Exiting FzpProcessBusTs4 level %s source line %s\n', Level, Elem.sourceline) + +# End of def FzpProcessBusTs4(InFile, Elem, Errors, Warnings, Info, +# FzpDict, TagStack, State, Level): -# End of def FzpProcessBusTs4(InFile, Elem, Errors, Warnings, Info, FzpDict, TagStack, State, Level): def FzpProcessBusTs5(InFile, Elem, Errors, Warnings, Info, FzpDict, TagStack, State, Level): - logging.info (' Entering FzpProcessBusTs5 level %s source line %s\n', Level, Elem.sourceline) + logging.info( + ' Entering FzpProcessBusTs5 level %s source line %s\n', Level, Elem.sourceline) - logging.debug (' FzpProcessBusTs5: Entry TagStack %s State %s\n', TagStack, State) + logging.debug( + ' FzpProcessBusTs5: Entry TagStack %s State %s\n', TagStack, State) - # At this point we set the last Id we saw from State and Tag from the - # TagStack. + # At this point we set the last Id we saw from State and Tag from the + # TagStack. Id = State['lastvalue'] @@ -3061,77 +3388,89 @@ def FzpProcessBusTs5(InFile, Elem, Errors, Warnings, Info, FzpDict, TagStack, St if not State['nexttag'] in ['bus', 'nodeMember']: - logging.debug (' FzpProcessBusTs5: Unexpected state %s expected bus or nodeMember\n',State['nexttag']) + logging.debug( + ' FzpProcessBusTs5: Unexpected state %s expected bus or nodeMember\n', State['nexttag']) # State isn't what we expected, error - Errors.append('Error 26: File\n\'{0:s}\'\nAt line {1:s}\n\nState error, expected lasttag \'bus\' or \'nodeMember\' not {2:s}\n(Missing line?)\n'.format(str(InFile), str(Elem.sourceline), str(State['lasttag']))) + Errors.append('Error 26: File\n\'{0:s}\'\nAt line {1:s}\n\nState error, expected lasttag \'bus\' or \'nodeMember\' not {2:s}\n(Missing line?)\n'.format( + str(InFile), str(Elem.sourceline), str(State['lasttag']))) + + else: - else: - if Tag == 'nodeMember': - - # Since Connector shouldn't be unique we don't need to check if + + # Since Connector shouldn't be unique we don't need to check if # it is. - + Connector = Elem.get('connectorId') - + if Connector != None: - + # Check if the connector exists - + if not Connector + '.id.bus' in FzpDict: - logging.debug (' FzpProcessBusTs5: Connector %s doesn\'t exist\n',Connector) - + logging.debug( + ' FzpProcessBusTs5: Connector %s doesn\'t exist\n', Connector) + # No, flag an error. - - Errors.append('Error 53: File\n\'{0:s}\'\nAt line {1:s}\n\nBus nodeMember {2:s} does\'t exist\n'.format(str(InFile), str(Elem.sourceline), str(Connector))) - + + Errors.append('Error 53: File\n\'{0:s}\'\nAt line {1:s}\n\nBus nodeMember {2:s} does\'t exist\n'.format( + str(InFile), str(Elem.sourceline), str(Connector))) + else: - - # Since we set the value as the key as a place holder - # intially, check if that is still true (i.e. this isn't - # part of another bus already). - + + # Since we set the value as the key as a place holder + # intially, check if that is still true (i.e. this isn't + # part of another bus already). + if FzpDict[Connector + '.id.bus'] == FzpDict[Connector + '.id.bus']: - logging.debug (' FzpProcessBusTs5: Connector %s added to bus %s\n',Connector, Id) - - # connector not part of another bus so mark it as ours. + logging.debug( + ' FzpProcessBusTs5: Connector %s added to bus %s\n', Connector, Id) + + # connector not part of another bus so mark it as ours. # by writing our bus Id in to it. - + FzpDict[Connector + '.id.bus'] = Id - + else: - - # connector is already part of another bus, flag an error. - - logging.debug (' FzpProcessBusTs5: connector %s already in another bus\n',Connector) - - Errors.append('Error 54: File\n\'{0:s}\'\nAt line {1:s}\n\nBus nodeMember {2:s} already in bus {3:s}\n'.format(str(InFile), str(Elem.sourceline), str(Connector), str(FzpDict[Connector + '.id.bus']))) - - # End of if FzpDict[connector + '.id.bus'] == FzpDict[connector + '.id.bus']: - + + # connector is already part of another bus, flag an + # error. + + logging.debug( + ' FzpProcessBusTs5: connector %s already in another bus\n', Connector) + + Errors.append('Error 54: File\n\'{0:s}\'\nAt line {1:s}\n\nBus nodeMember {2:s} already in bus {3:s}\n'.format( + str(InFile), str(Elem.sourceline), str(Connector), str(FzpDict[Connector + '.id.bus']))) + + # End of if FzpDict[connector + '.id.bus'] == + # FzpDict[connector + '.id.bus']: + # End of if not Connector + '.id.bus' in FzpDict: - + # Now increase the count of nodes in the bus by 1. - + FzpDict[Id + '.bus'] += 1 - + # End of if Connector != None: - + # End of if Tag == 'nodeMember': - + # End of if not State['nexttag'] in ['bus', 'nodeMember']: - logging.info (' Exiting FzpProcessBusTs5 level %s source line %s\n', Level, Elem.sourceline) + logging.info( + ' Exiting FzpProcessBusTs5 level %s source line %s\n', Level, Elem.sourceline) + +# End of def FzpProcessBusTs5(InFile, Elem, Errors, Warnings, Info, +# FzpDict, TagStack, State, Level): -# End of def FzpProcessBusTs5(InFile, Elem, Errors, Warnings, Info, FzpDict, TagStack, State, Level): def FzpProcessSchematicPartsTs3(InFile, Elem, Errors, Warnings, Info, FzpDict, TagStack, State, Level): - logging.info (' Entering FzpProcessSchematicPartsTs3 Level %s\n', Level) + logging.info(' Entering FzpProcessSchematicPartsTs3 Level %s\n', Level) StackTag, StackLevel = TagStack[len(TagStack) - 1] @@ -3143,11 +3482,13 @@ def FzpProcessSchematicPartsTs3(InFile, Elem, Errors, Warnings, Info, FzpDict, T # Unexpected state error - Errors.append('Error: File\n\'{0:s}\'\nAt line {1:s}\n\nDuplicate tag in schematic-subparts\n'.format(str(InFile), str(Elem.sourceline))) + Errors.append('Error: File\n\'{0:s}\'\nAt line {1:s}\n\nDuplicate tag in schematic-subparts\n'.format( + str(InFile), str(Elem.sourceline))) # End of if Tag == 'schematic-subparts': - logging.debug (' FzpProcessSchematicPartsTs3: TagStack len %s Tag %s\n', len(TagStack), Tag) + logging.debug( + ' FzpProcessSchematicPartsTs3: TagStack len %s Tag %s\n', len(TagStack), Tag) # Process the data according to tag stack level. @@ -3155,36 +3496,41 @@ def FzpProcessSchematicPartsTs3(InFile, Elem, Errors, Warnings, Info, FzpDict, T # Go and process the TagStack level 4 stuff (subpart id and label) - FzpProcessSchematicPartsTs4(InFile, Elem, Errors, Warnings, Info, FzpDict, TagStack, State, Level) + FzpProcessSchematicPartsTs4( + InFile, Elem, Errors, Warnings, Info, FzpDict, TagStack, State, Level) elif len(TagStack) == 5: # Go and process the TagStack level 4 stuff (connectors) - FzpProcessSchematicPartsTs5(InFile, Elem, Errors, Warnings, Info, FzpDict, TagStack, State, Level) + FzpProcessSchematicPartsTs5( + InFile, Elem, Errors, Warnings, Info, FzpDict, TagStack, State, Level) elif len(TagStack) == 6: # Go and process the TagStack level 5 stuff (connector) - FzpProcessSchematicPartsTs6(InFile, Elem, Errors, Warnings, Info, FzpDict, TagStack, State, Level) - + FzpProcessSchematicPartsTs6( + InFile, Elem, Errors, Warnings, Info, FzpDict, TagStack, State, Level) elif len(TagStack) > 6: - # There shouldn't be anything past 5th level so something is wrong. + # There shouldn't be anything past 5th level so something is wrong. - Errors.append('Error 38: File\n\'{0:s}\'\nAt line {1:s}\n\nState error, tag stack is at level {2:s} and should only go to level 6\n\nTag {3:s} will be ignored\n'.format(str(InFile), str(Elem.sourceline), str(len(TagStack)), str(Tag))) + Errors.append('Error 38: File\n\'{0:s}\'\nAt line {1:s}\n\nState error, tag stack is at level {2:s} and should only go to level 6\n\nTag {3:s} will be ignored\n'.format( + str(InFile), str(Elem.sourceline), str(len(TagStack)), str(Tag))) # End of if len(TagStack) == 3: - logging.info (' Exiting FzpProcessSchematicPartsTs3 Level %s\n', Level) + logging.info(' Exiting FzpProcessSchematicPartsTs3 Level %s\n', Level) + +# End of def FzpProcessSchematicPartsTs3(InFile, Elem, Errors, Warnings, +# Info, FzpDict, TagStack, State, Level): -# End of def FzpProcessSchematicPartsTs3(InFile, Elem, Errors, Warnings, Info, FzpDict, TagStack, State, Level): def FzpProcessSchematicPartsTs4(InFile, Elem, Errors, Warnings, Info, FzpDict, TagStack, State, Level): - logging.info (' Entering FzpProcessSchematicPartsTs4 Level %s\n', Level) + logging.info(' Entering FzpProcessSchematicPartsTs4 Level %s\n', Level) StackTag, StackLevel = TagStack[len(TagStack) - 1] @@ -3192,107 +3538,121 @@ def FzpProcessSchematicPartsTs4(InFile, Elem, Errors, Warnings, Info, FzpDict, T if Tag != 'subpart': - logging.debug (' FzpProcessSchematicPartsTs4: Unexpected Tag %s expected subpart\n', Tag) + logging.debug( + ' FzpProcessSchematicPartsTs4: Unexpected Tag %s expected subpart\n', Tag) # State isn't what we expected, error - Errors.append('Error 26: File\n\n{0:s}\'\nAt line {1:s}\n\nState error, expected tag \'subpart\' not {2:s}. (Missing line?)\n'.format(str(InFile), str(Elem.sourceline), str(Tag))) + Errors.append('Error 26: File\n\n{0:s}\'\nAt line {1:s}\n\nState error, expected tag \'subpart\' not {2:s}. (Missing line?)\n'.format( + str(InFile), str(Elem.sourceline), str(Tag))) else: if State['lasttag'] == 'schematic-subparts' or State['lasttag'] == 'connector': - + Id = Elem.get('id') - + if Id == None: - - logging.debug (' FzpProcessSchematicPartsTs4: Id none error\n') - Errors.append('Error 55: File\n\'{0:s}\'\nAt line {1:s}\n\nSubpart has no id\n'.format(str(InFile), str(Elem.sourceline))) - + logging.debug(' FzpProcessSchematicPartsTs4: Id none error\n') + + Errors.append('Error 55: File\n\'{0:s}\'\nAt line {1:s}\n\nSubpart has no id\n'.format( + str(InFile), str(Elem.sourceline))) + elif Id in FzpDict: - - logging.debug (' FzpProcessSchematicPartsTs4: subpart Id not unique error\n') + + logging.debug( + ' FzpProcessSchematicPartsTs4: subpart Id not unique error\n') # error, connector must be unique - - Errors.append('Error 56: File\n\'{0:s}\'\nAt line {1:s}\n\nSubpart id {2:s} already exists (must be unique)\n'.format(str(InFile), str(Elem.sourceline), str(Id))) - + + Errors.append('Error 56: File\n\'{0:s}\'\nAt line {1:s}\n\nSubpart id {2:s} already exists (must be unique)\n'.format( + str(InFile), str(Elem.sourceline), str(Id))) + # End of if Id == None: - + Label = Elem.get('label') - + if Label == None: - - logging.debug (' FzpProcessSchematicPartsTs4: Label None error\n') - - Errors.append('Error 57: File\n\'{0:s}\'\nAt line {1:s}\n\nSubpart has no label\n'.format(str(InFile), str(Elem.sourceline))) - + + logging.debug( + ' FzpProcessSchematicPartsTs4: Label None error\n') + + Errors.append('Error 57: File\n\'{0:s}\'\nAt line {1:s}\n\nSubpart has no label\n'.format( + str(InFile), str(Elem.sourceline))) + elif Label in FzpDict: - + # not unique error - - logging.debug (' FzpProcessSchematicPartsTs4: Label Not unique error\n') - + + logging.debug( + ' FzpProcessSchematicPartsTs4: Label Not unique error\n') + DupNameError(InFile, Label, Elem, Errors) - + else: - + # mark it as seen - - logging.debug (' FzpProcessSchematicPartsTs4: Mark Label %s seen\n',Label) - - FzpDict[Label] = Label - + + logging.debug( + ' FzpProcessSchematicPartsTs4: Mark Label %s seen\n', Label) + + FzpDict[Label] = Label + # End of if Label in FzpDict: - + # Set the subpart id even if it is None so we don't impact the last # subpart. - + State['lastvalue'] = Id - + if (Id + '.subpart') in FzpDict: - + # If we already have this subpart id flag an error (note in the # case of None, it may be due to other errors.) - - logging.debug (' FzpProcessSchematicPartsTs4: Id %s seeni already\n',Id) - - Errors.append('Error 58: File\n\'{0:s}\'\nAt line {1:s}\n\nSubpart {2:s} already defined (duplicate?)\n'.format(str(InFile), str(Elem.sourceline), str(Id))) - + + logging.debug( + ' FzpProcessSchematicPartsTs4: Id %s seeni already\n', Id) + + Errors.append('Error 58: File\n\'{0:s}\'\nAt line {1:s}\n\nSubpart {2:s} already defined (duplicate?)\n'.format( + str(InFile), str(Elem.sourceline), str(Id))) + else: - + # mark this as a subpart currently with no connections. - - logging.debug (' FzpProcessSchematicPartsTs4: Id %s set empty\n',Id) - + + logging.debug( + ' FzpProcessSchematicPartsTs4: Id %s set empty\n', Id) + FzpDict[Id + '.subpart'] = 0 if not 'subparts' in FzpDict: - # Note that we have subparts in the dictionary for svg - # processing. + # Note that we have subparts in the dictionary for svg + # processing. FzpDict['subparts'] = [] # End of if not Subparts in FzpDict: # Then add this subpart to the list of subpart ids and indicate - # we haven't yet seen it in the svg. + # we haven't yet seen it in the svg. + + FzpDict['subparts'].append(Id) - FzpDict['subparts'].append(Id) - # End of if (Id + '.subpart') in FzpDict: - + else: # State isn't what we expected, error - - logging.debug (' FzpProcessSchematicPartsTs4: State error\n',State) - Errors.append('Error 26: File\n\'{0:s}\'\nAt line {1:s}\n\nState error, expected tag \'schematic-subparts\' or \'connector\' not {2:s}.\n'.format(str(InFile), str(Elem.sourceline), str(State['lasttag']))) + logging.debug(' FzpProcessSchematicPartsTs4: State error\n', State) + + Errors.append('Error 26: File\n\'{0:s}\'\nAt line {1:s}\n\nState error, expected tag \'schematic-subparts\' or \'connector\' not {2:s}.\n'.format( + str(InFile), str(Elem.sourceline), str(State['lasttag']))) - # End of if State['lasttag'] == 'schematic-subparts' or State['lasttag'] == 'connector': + # End of if State['lasttag'] == 'schematic-subparts' or + # State['lasttag'] == 'connector': State['lasttag'] = Tag @@ -3300,13 +3660,15 @@ def FzpProcessSchematicPartsTs4(InFile, Elem, Errors, Warnings, Info, FzpDict, T # End of if Tag != 'subpart': - logging.info (' Exiting FzpProcessSchematicPartsTs4 Level %s\n', Level) + logging.info(' Exiting FzpProcessSchematicPartsTs4 Level %s\n', Level) + +# End of def FzpProcessSchematicPartsTs4(InFile, Elem, Errors, Warnings, +# Info, FzpDict, TagStack, State, Level): -# End of def FzpProcessSchematicPartsTs4(InFile, Elem, Errors, Warnings, Info, FzpDict, TagStack, State, Level): def FzpProcessSchematicPartsTs5(InFile, Elem, Errors, Warnings, Info, FzpDict, TagStack, State, Level): - logging.info (' Entering FzpProcessSchematicPartsTs5 Level %s\n', Level) + logging.info(' Entering FzpProcessSchematicPartsTs5 Level %s\n', Level) StackTag, StackLevel = TagStack[len(TagStack) - 1] @@ -3314,17 +3676,20 @@ def FzpProcessSchematicPartsTs5(InFile, Elem, Errors, Warnings, Info, FzpDict, T if Tag != 'connectors': - logging.debug (' FzpProcessSchematicPartsTs5: Unexpected Tag %s expected connectors\n', Tag) + logging.debug( + ' FzpProcessSchematicPartsTs5: Unexpected Tag %s expected connectors\n', Tag) # State isn't what we expected, error - Errors.append('Error 26: File\n\'{0:s}\'\nAt line {1:s}\n\nState error expected tag \'connectors\' not {2:s}. Missing line?\n'.format(str(InFile), str(Elem.sourceline), str(Tag))) + Errors.append('Error 26: File\n\'{0:s}\'\nAt line {1:s}\n\nState error expected tag \'connectors\' not {2:s}. Missing line?\n'.format( + str(InFile), str(Elem.sourceline), str(Tag))) # End of if Tag != 'connectors': if State['lasttag'] == 'subpart': - logging.debug (' FzpProcessSchematicPartsTs5: set nexttag to connector\n') + logging.debug( + ' FzpProcessSchematicPartsTs5: set nexttag to connector\n') State['lasttag'] = Tag @@ -3334,19 +3699,23 @@ def FzpProcessSchematicPartsTs5(InFile, Elem, Errors, Warnings, Info, FzpDict, T # State isn't what we expected, error - logging.debug (' FzpProcessSchematicPartsTs5: unexpected state %s expected connector\n', Tag) + logging.debug( + ' FzpProcessSchematicPartsTs5: unexpected state %s expected connector\n', Tag) - Errors.append('Error 26: File\n\'{0:s}\'\nAt line {1:s}\n\nState error, expected last tag \'subpart\' not {2:s}. (Missing line?)\n'.format(str(InFile), str(Elem.sourceline), str(State['lasttag']))) + Errors.append('Error 26: File\n\'{0:s}\'\nAt line {1:s}\n\nState error, expected last tag \'subpart\' not {2:s}. (Missing line?)\n'.format( + str(InFile), str(Elem.sourceline), str(State['lasttag']))) # End of if State['lasttag'] == 'subpart': - logging.info (' Exiting FzpProcessSchematicPartsTs5 Level %s\n', Level) + logging.info(' Exiting FzpProcessSchematicPartsTs5 Level %s\n', Level) + +# End of def FzpProcessSchematicPartsTs5(InFile, Elem, Errors, Warnings, +# Info, FzpDict, TagStack, State, Level): -# End of def FzpProcessSchematicPartsTs5(InFile, Elem, Errors, Warnings, Info, FzpDict, TagStack, State, Level): def FzpProcessSchematicPartsTs6(InFile, Elem, Errors, Warnings, Info, FzpDict, TagStack, State, Level): - logging.info (' Entering FzpProcessSchematicPartsTs6 Level %s\n', Level) + logging.info(' Entering FzpProcessSchematicPartsTs6 Level %s\n', Level) StackTag, StackLevel = TagStack[len(TagStack) - 1] @@ -3354,11 +3723,13 @@ def FzpProcessSchematicPartsTs6(InFile, Elem, Errors, Warnings, Info, FzpDict, T if Tag != 'connector': - logging.debug (' FzpProcessSchematicPartsTs6: Unexpected Tag %s expected connector\n', Tag) + logging.debug( + ' FzpProcessSchematicPartsTs6: Unexpected Tag %s expected connector\n', Tag) # State isn't what we expected, error - Errors.append('Error 26: File\n\'{0:s}\'\nAt line {1:s}\n\nState error, expected tag \'connector\' not {2:s}. (Missing line?)\n'.format(str(InFile), str(Elem.sourceline), str(Tag))) + Errors.append('Error 26: File\n\'{0:s}\'\nAt line {1:s}\n\nState error, expected tag \'connector\' not {2:s}. (Missing line?)\n'.format( + str(InFile), str(Elem.sourceline), str(Tag))) # End of if Tag != 'connector': @@ -3369,34 +3740,37 @@ def FzpProcessSchematicPartsTs6(InFile, Elem, Errors, Warnings, Info, FzpDict, T if State['lasttag'] == 'connectors' or State['lasttag'] == 'connector': # Get the ConnectorId - + ConnectorId = Elem.get('id') if ConnectorId == None: - Errors.append('Error 59: File\n\'{0:s}\'\nAt line {1:s}\n\nConnector id missing, ignored\n'.format(str(InFile), str(Elem.sourceline))) + Errors.append('Error 59: File\n\'{0:s}\'\nAt line {1:s}\n\nConnector id missing, ignored\n'.format( + str(InFile), str(Elem.sourceline))) elif not ConnectorId in FzpDict: - Errors.append('Error 60: File\n\'{0:s}\'\nAt line {1:s}\n\nConnector {2:s} doesn\'t exist (and it must)\n'.format(str(InFile), str(Elem.sourceline), str(ConnectorId))) + Errors.append('Error 60: File\n\'{0:s}\'\nAt line {1:s}\n\nConnector {2:s} doesn\'t exist (and it must)\n'.format( + str(InFile), str(Elem.sourceline), str(ConnectorId))) else: - - # Since we set the value as the key as a place holder - # intially, check if that is still true (i.e. this isn't - # part of another subpart already). - + + # Since we set the value as the key as a place holder + # intially, check if that is still true (i.e. this isn't + # part of another subpart already). + if FzpDict[ConnectorId + '.id.subpart'] == FzpDict[ConnectorId + '.id.subpart']: - logging.debug (' FzpProcessSchematicPartsTs6: Connector %s added to bus %s\n',ConnectorId, Id) - - # connector not part of another subpart so mark it as ours. + logging.debug( + ' FzpProcessSchematicPartsTs6: Connector %s added to bus %s\n', ConnectorId, Id) + + # connector not part of another subpart so mark it as ours. # by writing our subpart Id in to it. - + FzpDict[ConnectorId + '.id.subpart'] = Id # success, so increase the connector count for this subpart - # by 1. + # by 1. FzpDict[Id + '.subpart'] += 1 @@ -3408,35 +3782,39 @@ def FzpProcessSchematicPartsTs6(InFile, Elem, Errors, Warnings, Info, FzpDict, T # End of if not Id + '.subpart.cons' in FzpDict: - # Then add this connector to it. + # Then add this connector to it. if not 'schematic.' + ConnectorId in FzpDict: - - Errors.append('Error 81: File\n\'{0:s}\'\nAt line {1:s}\n\nSubpart connector {2:s} has no pins defined\n'.format(str(InFile), str(Elem.sourceline), str(ConnectorId), str(FzpDict[ConnectorId + '.id.subpart']))) + + Errors.append('Error 81: File\n\'{0:s}\'\nAt line {1:s}\n\nSubpart connector {2:s} has no pins defined\n'.format( + str(InFile), str(Elem.sourceline), str(ConnectorId), str(FzpDict[ConnectorId + '.id.subpart']))) else: - for Con in FzpDict['schematic.' + ConnectorId]: + for Con in FzpDict['schematic.' + ConnectorId]: - # Append the pins associated with this connector to - # the subpart ID list to check when the schematic - # svg is processed later. + # Append the pins associated with this connector to + # the subpart ID list to check when the schematic + # svg is processed later. FzpDict[Id + '.subpart.cons'].append(Con) - # End of for Con in FzpDict['schematic.' + ConnectorId]: + # End of for Con in FzpDict['schematic.' + ConnectorId]: # End of if not 'schematic.' + ConnectorId in FzpDict: - + else: - + # connector is already part of another subpart, flag an error. - logging.debug (' FzpProcessSchematicPartsTs6: connector %s already in another subpart\n',ConnectorId) - - Errors.append('Error 61: File\n\'{0:s}\'\nAt line {1:s}\n\nSubpart connector {2:s} already in subpart {3:s}\n'.format(str(InFile), str(Elem.sourceline), str(ConnectorId), str(FzpDict[ConnectorId + '.id.subpart']))) - - # End of if FzpDict[connectorId + '.id.subpart'] == FzpDict[connectorId + '.id.subpart']: + logging.debug( + ' FzpProcessSchematicPartsTs6: connector %s already in another subpart\n', ConnectorId) + + Errors.append('Error 61: File\n\'{0:s}\'\nAt line {1:s}\n\nSubpart connector {2:s} already in subpart {3:s}\n'.format( + str(InFile), str(Elem.sourceline), str(ConnectorId), str(FzpDict[ConnectorId + '.id.subpart']))) + + # End of if FzpDict[connectorId + '.id.subpart'] == + # FzpDict[connectorId + '.id.subpart']: # End of if ConnectorId == None: @@ -3444,42 +3822,47 @@ def FzpProcessSchematicPartsTs6(InFile, Elem, Errors, Warnings, Info, FzpDict, T # State isn't what we expected, error - Errors.append('Error 26: File\n\'{0:s}\'\nAt line {1:s}\n\nState error, expected last tag \'connectors\' or \'connector\' not {2:s}.\n'.format(str(InFile), str(Elem.sourceline), str(State['lasttag']))) + Errors.append('Error 26: File\n\'{0:s}\'\nAt line {1:s}\n\nState error, expected last tag \'connectors\' or \'connector\' not {2:s}.\n'.format( + str(InFile), str(Elem.sourceline), str(State['lasttag']))) - # end of if State['lasttag'] == 'connectors' or State['lasttag'] == 'connector': + # end of if State['lasttag'] == 'connectors' or State['lasttag'] == + # 'connector': State['lasttag'] = Tag State['nexttag'] = 'connector' - logging.info (' Exiting FzpProcessSchematicPartsTs6 Level %s\n', Level) + logging.info(' Exiting FzpProcessSchematicPartsTs6 Level %s\n', Level) + +# End of def FzpProcessSchematicPartsTs6(InFile, Elem, Errors, Warnings, +# Info, FzpDict, TagStack, State, Level): -# End of def FzpProcessSchematicPartsTs6(InFile, Elem, Errors, Warnings, Info, FzpDict, TagStack, State, Level): def FzpCheckConnectors(InFile, Elem, FzpDict, Errors, Warnings, Info, State): - logging.info (' Entering FzpCheckConnectors\n') + logging.info(' Entering FzpCheckConnectors\n') if not 'pinnos' in FzpDict or len(FzpDict['pinnos']) == 0: # no connectors found! - logging.debug (' FzpCheckConnectors: no pinnos found\n') + logging.debug(' FzpCheckConnectors: no pinnos found\n') - Errors.append('Error 62: File\n\'{0:s}\'\n\nNo connectors found to check\n'.format(str(InFile))) + Errors.append( + 'Error 62: File\n\'{0:s}\'\n\nNo connectors found to check\n'.format(str(InFile))) else: - # Check that pin numbers start at 0 and are contiguous. + # Check that pin numbers start at 0 and are contiguous. - logging.debug (' FzpCheckConnectors: pinnos %s\n',FzpDict['pinnos']) + logging.debug(' FzpCheckConnectors: pinnos %s\n', FzpDict['pinnos']) for Pin in range(len(FzpDict['pinnos'])): - - # Mark an error if any number in sequence doesn't exist as the - # connector numbers must be contiguous. - logging.debug (' FzpCheckConnectors: Pin %s\n', Pin) + # Mark an error if any number in sequence doesn't exist as the + # connector numbers must be contiguous. + + logging.debug(' FzpCheckConnectors: Pin %s\n', Pin) if not 'pinnosmsg' in State: @@ -3487,68 +3870,79 @@ def FzpCheckConnectors(InFile, Elem, FzpDict, Errors, Warnings, Info, State): if not str(Pin) in FzpDict['pinnos']: - logging.debug (' FzpCheckConnectors: pin %s pinnos %s\n',Pin, FzpDict['pinnos']) + logging.debug( + ' FzpCheckConnectors: pin %s pinnos %s\n', Pin, FzpDict['pinnos']) - Errors.append('Error 64: File\n\'{0:s}\'\n\nConnector{1:s} doesn\'t exist when it must to stay in sequence\n'.format(str(InFile), str(Pin))) + Errors.append('Error 64: File\n\'{0:s}\'\n\nConnector{1:s} doesn\'t exist when it must to stay in sequence\n'.format( + str(InFile), str(Pin))) State['pinnosmsg'] = 'y' # End of if not Pin in FzpDict['pinnos']: # End of if not 'pinnosmsg' in State: - + # End of for pin in range(len(FzpDict['pinnos'])): # End of if not pinnos in FzpDict or len(FzpDict['pinnos']) == 0: - logging.info (' Exiting FzpCheckConnectors\n') + logging.info(' Exiting FzpCheckConnectors\n') + +# End of def FzpCheckConnectors(InFile, Elem, FzpDict, Errors, Warnings, +# Info, State): -# End of def FzpCheckConnectors(InFile, Elem, FzpDict, Errors, Warnings, Info, State): def ProcessSvg(FzpType, FileType, InFile, OutFile, CurView, PrefixDir, Errors, Warnings, Info, FzpDict, FilesProcessed, TagStack, State, InheritedAttributes, Debug): - logging.info (' Entering ProcessSvg\n') + logging.info(' Entering ProcessSvg\n') - logging.debug (' ProcessSvg: FileType %s InFile %s OutFile %s CurView %s\n', FileType, InFile, OutFile, CurView) + logging.debug(' ProcessSvg: FileType %s InFile %s OutFile %s CurView %s\n', + FileType, InFile, OutFile, CurView) # Parse the input document. - Doc, Root = PP.ParseFile (InFile, Errors) + Doc, Root = PP.ParseFile(InFile, Errors) - logging.debug (' ProcessSvg: return from parse Doc %s\n', Doc) + logging.debug(' ProcessSvg: return from parse Doc %s\n', Doc) if Doc != None: - logging.debug (' ProcessSvg: Calling ProcessTree Doc %s\n', Doc) + logging.debug(' ProcessSvg: Calling ProcessTree Doc %s\n', Doc) # We have successfully parsed the input document so process it. If - # this is only an svg file without an associated fzp, the FzpDict - # will be empty as there is no fzp data to check the svg against. + # this is only an svg file without an associated fzp, the FzpDict + # will be empty as there is no fzp data to check the svg against. - ProcessTree(FzpType, FileType, InFile, OutFile, CurView, PrefixDir, Root, Errors, Warnings, Info, FzpDict, TagStack, State, InheritedAttributes, Debug) + ProcessTree(FzpType, FileType, InFile, OutFile, CurView, PrefixDir, Root, + Errors, Warnings, Info, FzpDict, TagStack, State, InheritedAttributes, Debug) if not 'fzp' in FzpDict and 'pcbsvg' in State: - + # We don't have a fzp file so check the pcb layers which it would - # normally do if this is a pcb svg. + # normally do if this is a pcb svg. - SvgCheckPcbLayers(InFile, Errors, Warnings, Info, FzpDict, TagStack, State) + SvgCheckPcbLayers(InFile, Errors, Warnings, + Info, FzpDict, TagStack, State) # End of if not 'fzp' in FzpDict: - PP.OutputTree(Doc, Root, FileType, InFile, OutFile, Errors, Warnings, Info, Debug) + PP.OutputTree(Doc, Root, FileType, InFile, OutFile, + Errors, Warnings, Info, Debug) # End of if Doc != None: - logging.info (' Exiting ProcessSvg\n') + logging.info(' Exiting ProcessSvg\n') + +# End of def ProcessSvg(FzpType, FileType, InFile, OutFile, CurView, +# PrefixDir, Errors, Warnings, Info, FzpDict, FilesProcessed, TagStack, +# State, InheritedAttributes, Debug): -# End of def ProcessSvg(FzpType, FileType, InFile, OutFile, CurView, PrefixDir, Errors, Warnings, Info, FzpDict, FilesProcessed, TagStack, State, InheritedAttributes, Debug): def RemovePx(InFile, Elem, Info, Level): # Remove the trailing px from a font-size command if present. - logging.info (' Entering RemovePx Level %s\n', Level) + logging.info(' Entering RemovePx Level %s\n', Level) pxRegex = re.compile(r'px', re.IGNORECASE) @@ -3558,7 +3952,7 @@ def RemovePx(InFile, Elem, Info, Level): if pxRegex.search(FontSize) != None: - logging.debug (' RemovePx: Removed a px from font-size\n') + logging.debug(' RemovePx: Removed a px from font-size\n') # we have a font size, so see if it has a px and remove it if so. @@ -3566,22 +3960,24 @@ def RemovePx(InFile, Elem, Info, Level): Elem.set('font-size', FontSize) - Info.append('Modified 1: File\n\'{0:s}\'\nAt line {1:s}\n\nRemoved px from font-size leaving {2:s}\n'.format(str(InFile), str(Elem.sourceline), str(FontSize))) + Info.append('Modified 1: File\n\'{0:s}\'\nAt line {1:s}\n\nRemoved px from font-size leaving {2:s}\n'.format( + str(InFile), str(Elem.sourceline), str(FontSize))) # End of if pxRegex.search(FontSize) != None: # End of if not FontSize == None: - logging.info (' Exiting RemovePx Level %s\n', Level) + logging.info(' Exiting RemovePx Level %s\n', Level) # End of def RemovePx(InFile, Elem, Info): def ProcessSvgLeafNode(FzpType, FileType, InFile, CurView, PrefixDir, Elem, Errors, Warnings, Info, FzpDict, TagStack, State, InheritedAttributes, Level): - logging.info (' Entering ProcessSvgLeafNode Level %s\n', Level) + logging.info(' Entering ProcessSvgLeafNode Level %s\n', Level) - logging.debug (' ProcessSvgLeafNode: Entry File %s Source line %s FileType %s CurView %s State %s\n',InFile, Elem.sourceline, FileType, CurView, State) + logging.debug(' ProcessSvgLeafNode: Entry File %s Source line %s FileType %s CurView %s State %s\n', + InFile, Elem.sourceline, FileType, CurView, State) NameSpaceRegex = re.compile(r'{.+}') @@ -3589,30 +3985,30 @@ def ProcessSvgLeafNode(FzpType, FileType, InFile, CurView, PrefixDir, Elem, Erro ConnectorTermRegex = re.compile(r'connector.+terminal', re.IGNORECASE) - # Get the id and tag values and remove the namespace if present. + # Get the id and tag values and remove the namespace if present. Id = Elem.get('id') - logging.debug (' ProcessSvgLeafNode: Id %s\n', Id) + logging.debug(' ProcessSvgLeafNode: Id %s\n', Id) Tag = NameSpaceRegex.sub('', str(Id)) - logging.debug (' ProcessSvgLeafNode: removed namespace from Id %s\n', Id) + logging.debug(' ProcessSvgLeafNode: removed namespace from Id %s\n', Id) - # If there is an id for this node, remove the name space element - # from the tag to make later processing easier. + # If there is an id for this node, remove the name space element + # from the tag to make later processing easier. Tag = Elem.tag - logging.debug (' ProcessSvgLeafNode: Tag %s\n', Tag) + logging.debug(' ProcessSvgLeafNode: Tag %s\n', Tag) Tag = NameSpaceRegex.sub('', str(Tag)) - logging.debug (' ProcessSvgLeafNode: removed namespace from Tag %s\n', Tag) + logging.debug(' ProcessSvgLeafNode: removed namespace from Tag %s\n', Tag) if not 'SvgStart' in State: - # Haven't yet seen the svg start line so check this one. + # Haven't yet seen the svg start line so check this one. SvgStartElem(InFile, Elem, Errors, Warnings, Info, State, Level) @@ -3622,25 +4018,28 @@ def ProcessSvgLeafNode(FzpType, FileType, InFile, CurView, PrefixDir, Elem, Erro SvgRefFile(FzpType, InFile, Elem, Errors, Warnings, Info, State, Level) - # First find and set any of Fritzing's layer ids in this element. + # First find and set any of Fritzing's layer ids in this element. - SvgGroup(InFile, CurView, Elem, Errors, Warnings, Info, FzpDict, TagStack, State, Level) + SvgGroup(InFile, CurView, Elem, Errors, Warnings, + Info, FzpDict, TagStack, State, Level) # Check we have a layerId before any drawing element. - SvgCheckForLayerId(Tag, InFile, CurView, Elem, Errors, Warnings, Info, FzpDict, TagStack, State, Level) + SvgCheckForLayerId(Tag, InFile, CurView, Elem, Errors, + Warnings, Info, FzpDict, TagStack, State, Level) - # Then convert any style commands to inline xml (as Fritzing sometimes - # doesn't process style commands and the 2 forms are identical). + # Then convert any style commands to inline xml (as Fritzing sometimes + # doesn't process style commands and the 2 forms are identical). SvgInlineStyle(InFile, Elem, Warnings, State) # Remove any inheritable attributes (external scripts for pcb generation - # can't inherit parameters so make them local). + # can't inherit parameters so make them local). - SvgRemoveInheritableAttribs(InFile, Elem, Errors, Warnings, Info, State, InheritedAttributes, Level) + SvgRemoveInheritableAttribs( + InFile, Elem, Errors, Warnings, Info, State, InheritedAttributes, Level) - # Remove any px from the font-size commands. + # Remove any px from the font-size commands. RemovePx(InFile, Elem, Info, Level) @@ -3653,44 +4052,48 @@ def ProcessSvgLeafNode(FzpType, FileType, InFile, CurView, PrefixDir, Elem, Erro if not 'font.warning' in FzpDict: # Issue the warning then mark it as done so it only happens once - # per file. + # per file. - Warnings.append('Warning 24: File\n\'{0:s}\'\nAt line {1:s}\n\nFont family {2:s} is not Droid Sans or OCRA\nThis won\'t render in Fritzing\n'.format(str(InFile), str(Elem.sourceline), str(FontFamily))) + Warnings.append('Warning 24: File\n\'{0:s}\'\nAt line {1:s}\n\nFont family {2:s} is not Droid Sans or OCRA\nThis won\'t render in Fritzing\n'.format( + str(InFile), str(Elem.sourceline), str(FontFamily))) FzpDict['font.warning'] = 'y' # End of if not 'font.warning' in FzpDict: - # End of if not FontFamily == None and not FontFamily in ['DroidSans', "'Droid Sans'", "'OCRA'", 'OCRA']: + # End of if not FontFamily == None and not FontFamily in ['DroidSans', + # "'Droid Sans'", "'OCRA'", 'OCRA']: # Check if this is a connector terminal definition - # The str below takes care of comments which aren't a byte string and - # thus cause an exception. + # The str below takes care of comments which aren't a byte string and + # thus cause an exception. Term = ConnectorTermRegex.search(str(Id)) - logging.debug (' ProcessSvgLeafNode: Term %s Tag %s\n', Term, Tag) - + logging.debug(' ProcessSvgLeafNode: Term %s Tag %s\n', Term, Tag) + if Term != None: # This looks to be a terminal definition so check it is a valid type. - if Tag in ['path' , 'g']: + if Tag in ['path', 'g']: # Note one of the illegal terminalId types is present. - Errors.append('Error 77: File\n\'{0:s}\'\nAt line {1:s}\n\nterminalId {2:s} can\'t be a {3:s} as it won\'t work.\n'.format(str(InFile), str(Elem.sourceline), str(Id), str(Tag))) + Errors.append('Error 77: File\n\'{0:s}\'\nAt line {1:s}\n\nterminalId {2:s} can\'t be a {3:s} as it won\'t work.\n'.format( + str(InFile), str(Elem.sourceline), str(Id), str(Tag))) - # End of if Tag in ['path']: + # End of if Tag in ['path']: # Since this is a terminal, check for height or width of 0 and complain - # if so. - + # if so. + Height = Elem.get('height') - + Width = Elem.get('width') - logging.debug (' ProcessSvgLeafNode: terminal %s height / width check height %s width %s\n', Id, Height, Width) + logging.debug( + ' ProcessSvgLeafNode: terminal %s height / width check height %s width %s\n', Id, Height, Width) if Height == '0': @@ -3700,18 +4103,21 @@ def ProcessSvgLeafNode(FzpType, FileType, InFile, CurView, PrefixDir, Elem, Erro Elem.set('height', '10') - # and log an error to warn the user we made a change that will - # affect the svg terminal position so they check it. + # and log an error to warn the user we made a change that will + # affect the svg terminal position so they check it. - Error.append('Modified 2: File\n\'{0:s}\'\nAt line {1:s}\n\nConnector {2:s} had a zero height, set to 10\nCheck the alignment of this pin in the svg!\n'.format(str(InFile), str(Elem.sourceline), str(Id))) + Errors.append('Modified 2: File\n\'{0:s}\'\nAt line {1:s}\n\nConnector {2:s} had a zero height, set to 10\nCheck the alignment of this pin in the svg!\n'.format( + str(InFile), str(Elem.sourceline), str(Id))) - else : + else: - Warnings.append('Warning 16: File\n\'{0:s}\'\nAt line {1:s}\n\nConnector {2:s} has a zero height\nand thus is not selectable in Inkscape\n'.format(str(InFile), str(Elem.sourceline), str(Id))) + Warnings.append('Warning 16: File\n\'{0:s}\'\nAt line {1:s}\n\nConnector {2:s} has a zero height\nand thus is not selectable in Inkscape\n'.format( + str(InFile), str(Elem.sourceline), str(Id))) # End of if ModifyTerminal == 'y': - logging.debug (' ProcessSvgLeafNode: terminal %s 0 height warned or changed\n', Id) + logging.debug( + ' ProcessSvgLeafNode: terminal %s 0 height warned or changed\n', Id) # End of if Height == '0': @@ -3720,61 +4126,66 @@ def ProcessSvgLeafNode(FzpType, FileType, InFile, CurView, PrefixDir, Elem, Erro if ModifyTerminal == 'y': # Set the element to 10 and issue an error so the user knows - # to check the alignment of the terminal (which will have - # changed). + # to check the alignment of the terminal (which will have + # changed). Elem.set('width', '10') - Errors.append('Modified 2: File\n\'{0:s}\'\nAt line {1:s}\n\nConnector {2:s} had a zero width, set to 10\nCheck the alignment of this pin in the svg!\n'.format(str(InFile), str(Elem.sourceline), str(Id))) + Errors.append('Modified 2: File\n\'{0:s}\'\nAt line {1:s}\n\nConnector {2:s} had a zero width, set to 10\nCheck the alignment of this pin in the svg!\n'.format( + str(InFile), str(Elem.sourceline), str(Id))) else: - Warnings.append('Warning 16: File\n\'{0:s}\'\nAt line {1:s}\n\nConnector {2:s} has a zero width\nand thus is not selectable in Inkscape\n'.format(str(InFile), str(Elem.sourceline), str(Id))) + Warnings.append('Warning 16: File\n\'{0:s}\'\nAt line {1:s}\n\nConnector {2:s} has a zero width\nand thus is not selectable in Inkscape\n'.format( + str(InFile), str(Elem.sourceline), str(Id))) # End of if ModifyTerminal == 'y': - logging.debug (' ProcessSvgLeafNode: terminal %s issued\n', Id) + logging.debug(' ProcessSvgLeafNode: terminal %s issued\n', Id) # End of if Width == '0': - + # End of if Term != None: # End of if not 'connectors.svg.' + CurView in FzpDict: if Id != None and 'fzp' in FzpDict: - # We are processing an svg from a fzp file so we can do more tests as + # We are processing an svg from a fzp file so we can do more tests as # we have connector and subpart data in the dict. - # iconView doesn't have connectors so ignore it. + # iconView doesn't have connectors so ignore it. if CurView != None and CurView != 'iconView' and Id in FzpDict['connectors.fzp.' + CurView]: if not 'connectors.svg.' + CurView in FzpDict: - + # Doesn't exist yet so create it and add this connector. - + FzpDict['connectors.svg.' + CurView] = [Id] - - logging.debug (' ProcessSvgLeafNode: Created connectors.svg.%s and added %s to get %s\n', CurView, Id, FzpDict['connectors.svg.' + CurView]) - + + logging.debug(' ProcessSvgLeafNode: Created connectors.svg.%s and added %s to get %s\n', + CurView, Id, FzpDict['connectors.svg.' + CurView]) + else: - - # Check for a dup connector. While Inkscape won't let you + + # Check for a dup connector. While Inkscape won't let you # create one, a text editor or script generated part would ... - + if Id in FzpDict['connectors.svg.' + CurView]: - - Errors.append('Error 66: File\n{0:s}\nAt line {1:s}\n\nConnector {2:s} is a duplicate (and should be unique)\n'.format(str(InFile), str(Elem.sourceline), str(Id))) - + + Errors.append('Error 66: File\n{0:s}\nAt line {1:s}\n\nConnector {2:s} is a duplicate (and should be unique)\n'.format( + str(InFile), str(Elem.sourceline), str(Id))) + else: - - # not a dup, so append it to the list. - + + # not a dup, so append it to the list. + FzpDict['connectors.svg.' + CurView].append(Id) - - logging.debug (' ProcessSvgLeafNode: Appended %s to connectors.svg.%s to get %s\n', Id, CurView, FzpDict['connectors.svg.' + CurView]) - + + logging.debug(' ProcessSvgLeafNode: Appended %s to connectors.svg.%s to get %s\n', Id, CurView, FzpDict[ + 'connectors.svg.' + CurView]) + # End of if Id in FzpDict['connectors.svg.' + CurView]: # End of if not 'connectors.svg.' + CurView in FzpDict: @@ -3784,7 +4195,7 @@ def ProcessSvgLeafNode(FzpType, FileType, InFile, CurView, PrefixDir, Elem, Erro # Get what should be the subpart tag from the tag stack if len(TagStack) > 2: - + SubPartTag, StackLevel = TagStack[2] else: @@ -3793,33 +4204,41 @@ def ProcessSvgLeafNode(FzpType, FileType, InFile, CurView, PrefixDir, Elem, Erro # End of if len(TagStack) > 2: - logging.debug (' ProcessSvgLeafNode: SubPartTag %s\n', SubPartTag) + logging.debug( + ' ProcessSvgLeafNode: SubPartTag %s\n', SubPartTag) if not 'subpartid' in State: # no subpartID present at this time error. - Errors.append('Error 82: File\n\'{0:s}\'\nAt line {1:s}\n\nconnector {2:s} isn\'t in a subpart\n'.format(str(InFile), str(Elem.sourceline), str(Id))) + Errors.append('Error 82: File\n\'{0:s}\'\nAt line {1:s}\n\nconnector {2:s} isn\'t in a subpart\n'.format( + str(InFile), str(Elem.sourceline), str(Id))) - logging.debug (' ProcessSvgLeafNode: subparts connector %s not in subpart\n', Id) + logging.debug( + ' ProcessSvgLeafNode: subparts connector %s not in subpart\n', Id) else: - logging.debug (' ProcessSvgLeafNode: State[\'subpartid\'] %s SubPartTag %s\n', State['subpartid'], SubPartTag) - + logging.debug(' ProcessSvgLeafNode: State[\'subpartid\'] %s SubPartTag %s\n', State[ + 'subpartid'], SubPartTag) + if not State['subpartid'] == SubPartTag: if SubPartTag == 'none': - Errors.append('Error 82: File\n\'{0:s}\'\nAt line {1:s}\n\nconnector {2:s} isn\'t in a subpart\n'.format(str(InFile), str(Elem.sourceline), str(Id))) + Errors.append('Error 82: File\n\'{0:s}\'\nAt line {1:s}\n\nconnector {2:s} isn\'t in a subpart\n'.format( + str(InFile), str(Elem.sourceline), str(Id))) - logging.debug (' ProcessSvgLeafNode: subparts connector %s not in subpart\n', Id) + logging.debug( + ' ProcessSvgLeafNode: subparts connector %s not in subpart\n', Id) else: - Errors.append('Error 83: File\n\'{0:s}\'\nAt line {1:s}\n\nConnector {2:s} shouldn\'t be in subpart {3:s} as it is\n'.format(str(InFile), str(Elem.sourceline), str(Id), str(SubPartTag))) + Errors.append('Error 83: File\n\'{0:s}\'\nAt line {1:s}\n\nConnector {2:s} shouldn\'t be in subpart {3:s} as it is\n'.format( + str(InFile), str(Elem.sourceline), str(Id), str(SubPartTag))) - logging.debug (' ProcessSvgLeafNode: subparts connector %s not in correct subpart\n', Id) + logging.debug( + ' ProcessSvgLeafNode: subparts connector %s not in correct subpart\n', Id) # End of if SubPartTag == 'none': @@ -3829,17 +4248,21 @@ def ProcessSvgLeafNode(FzpType, FileType, InFile, CurView, PrefixDir, Elem, Erro FzpDict[SubPartTag + '.svg.subparts'].append(Id) - logging.debug (' ProcessSvgLeafNode: connector %s added to FzpDict[%s]\n', Id, SubPartTag + '.svg.subparts') + logging.debug( + ' ProcessSvgLeafNode: connector %s added to FzpDict[%s]\n', Id, SubPartTag + '.svg.subparts') else: - Errors.append('Error 84: File\n\'{0:s}\'\nAt line {1:s}\n\nConnector {2:s} in incorrect subpart {3:s}\n'.format(str(InFile), str(Elem.sourceline), str(Id), str(SubPartTag))) + Errors.append('Error 84: File\n\'{0:s}\'\nAt line {1:s}\n\nConnector {2:s} in incorrect subpart {3:s}\n'.format( + str(InFile), str(Elem.sourceline), str(Id), str(SubPartTag))) - logging.debug (' ProcessSvgLeafNode: subparts connector %s in wrong subpart %s\n', Id, SubPartTag) + logging.debug( + ' ProcessSvgLeafNode: subparts connector %s in wrong subpart %s\n', Id, SubPartTag) # End of if Id in FzpDict[SubPartTag + ',subpart.cons']: - # End of if not 'subpartid' in State and not State['subpartid'] == SubPartTag: + # End of if not 'subpartid' in State and not State['subpartid'] + # == SubPartTag: # End of if CurView == 'schematicView' and 'subparts' in FzpDict: @@ -3851,7 +4274,7 @@ def ProcessSvgLeafNode(FzpType, FileType, InFile, CurView, PrefixDir, Elem, Erro # As this is only true for through hole parts and we don't yet # know if this part is through hole, put this in State for now # to be added to Errors only if this turns out to be a through - # hole part later. + # hole part later. RadiusX = Elem.get('rx') @@ -3861,13 +4284,17 @@ def ProcessSvgLeafNode(FzpType, FileType, InFile, CurView, PrefixDir, Elem, Erro # pcb exists and has copper0 and copper1 - Errors.append('Error 65: File\n\'{0:s}\'\nAt line {1:s}\n\nConnector {2:s} is an ellipse not a circle, (gerber generation will break.)\n'.format(str(InFile), str(Elem.sourceline), str(Id))) + Errors.append('Error 65: File\n\'{0:s}\'\nAt line {1:s}\n\nConnector {2:s} is an ellipse not a circle, (gerber generation will break.)\n'.format( + str(InFile), str(Elem.sourceline), str(Id))) else: - State['noradius'].append('Error 65: File\n\'{0:s}\'\nAt line {1:s}\n\nConnector {2:s} is an ellipse not a circle, (gerber generation will break.)\n'.format(str(InFile), str(Elem.sourceline), str(Id))) + State['noradius'].append('Error 65: File\n\'{0:s}\'\nAt line {1:s}\n\nConnector {2:s} is an ellipse not a circle, (gerber generation will break.)\n'.format( + str(InFile), str(Elem.sourceline), str(Id))) - # End of if not 'hybridsetforpcbView' in State and copper0.layerid' in FzpDict and 'copper1.layerid' in FzpDict: + # End of if not 'hybridsetforpcbView' in State and + # copper0.layerid' in FzpDict and 'copper1.layerid' in + # FzpDict: # End of if RadiusX != None: @@ -3876,7 +4303,7 @@ def ProcessSvgLeafNode(FzpType, FileType, InFile, CurView, PrefixDir, Elem, Erro # As this is only true for through hole parts and we don't yet # know if this part is through hole, put this in State for now # to be added to Errors only if this turns out to be a through - # hole part later. + # hole part later. if Radius == None: @@ -3884,17 +4311,21 @@ def ProcessSvgLeafNode(FzpType, FileType, InFile, CurView, PrefixDir, Elem, Erro # pcb exists and has copper0 and copper1 - Errors.append('Error 74: File\n\'{0:s}\'\nAt line {1:s}\n\nConnector {2:s} has no radius no hole will be generated\n'.format(str(InFile), str(Elem.sourceline), str(Id))) + Errors.append('Error 74: File\n\'{0:s}\'\nAt line {1:s}\n\nConnector {2:s} has no radius no hole will be generated\n'.format( + str(InFile), str(Elem.sourceline), str(Id))) else: - + # this is only an svg so we don't yet know if this is # a through hole part yet so save the error message # in State until we do. - - State['noradius'].append('Error 74: File\n\'{0:s}\'\nAt line {1:s}\n\nConnector {2:s} has no radius no hole will be generated\n'.format(str(InFile), str(Elem.sourceline), str(Id))) - # End of if not 'hybridsetforpcbView' in State and copper0.layerid' in FzpDict and 'copper1.layerid' in FzpDict: + State['noradius'].append('Error 74: File\n\'{0:s}\'\nAt line {1:s}\n\nConnector {2:s} has no radius no hole will be generated\n'.format( + str(InFile), str(Elem.sourceline), str(Id))) + + # End of if not 'hybridsetforpcbView' in State and + # copper0.layerid' in FzpDict and 'copper1.layerid' in + # FzpDict: # End of if Radius != None: @@ -3904,38 +4335,42 @@ def ProcessSvgLeafNode(FzpType, FileType, InFile, CurView, PrefixDir, Elem, Erro if CurView == 'schematicView' and 'subparts' in FzpDict: - # We are in schematic and it has subparts so check they are + # We are in schematic and it has subparts so check they are # correct. if Id in FzpDict['subparts']: - logging.debug (' ProcessSvgLeafNode: Start of subpart Id %s\n', Id) + logging.debug( + ' ProcessSvgLeafNode: Start of subpart Id %s\n', Id) - # Mark that we have seen a subpart label with (so far) no + # Mark that we have seen a subpart label with (so far) no # connectors if Id + '.svg.subparts' in FzpDict: - # Complain about a dup (although this shouldn't be able - # to occur except via manual editing). + # Complain about a dup (although this shouldn't be able + # to occur except via manual editing). - logging.debug (' ProcessSvgLeafNode: subparts Id %s duplicate\n', Id) - Errors.append('Error 85: File\n\'{0:s}\'\nAt line {1:s}\n\nsubpart label {2:s} is already defined\n'.format(str(InFile), str(Elem.sourceline), str(Id))) + logging.debug( + ' ProcessSvgLeafNode: subparts Id %s duplicate\n', Id) + Errors.append('Error 85: File\n\'{0:s}\'\nAt line {1:s}\n\nsubpart label {2:s} is already defined\n'.format( + str(InFile), str(Elem.sourceline), str(Id))) else: - # Create an empty list to contain the connectorids + # Create an empty list to contain the connectorids # for this label for later checking (to make sure they are - # all present). + # all present). FzpDict[Id + '.svg.subparts'] = [] # Then record this subpartid in State for later connector - # ids. + # ids. State['subpartid'] = Id - logging.debug (' ProcessSvgLeafNode: Create FzpDict[%s] and set state[\'subpartid\'] to %s\n', Id + '.svg.subparts', Id) + logging.debug( + ' ProcessSvgLeafNode: Create FzpDict[%s] and set state[\'subpartid\'] to %s\n', Id + '.svg.subparts', Id) # End of if Id + '.subparts' in FzpDict: @@ -3949,28 +4384,31 @@ def ProcessSvgLeafNode(FzpType, FileType, InFile, CurView, PrefixDir, Elem, Erro # If there are inherited attributes step through them adding any # attributes that don't already exist. If the attribute is present - # discard the inherited value. + # discard the inherited value. SvgSetInheritedAttributes(InFile, Elem, InheritedAttributes) # End of if not InheritedAttributes == None: # Finally after all the attributes are set, search for font-size commands - # and remove the trailing px (which Fritzing doesn't like) if it is present. + # and remove the trailing px (which Fritzing doesn't like) if it is + # present. RemovePx(InFile, Elem, Info, Level) # Then if this is group silkscreen, convert old style white silkscreen - # (in all its forms) to new style black silkscreen. Warn about and + # (in all its forms) to new style black silkscreen. Warn about and # modify items that are neither black nor white. if State['lastvalue'] == 'silkscreen': # Create the two color dictionaries - ColorIsWhite = { 'white': 'y', 'WHITE': 'y', '#ffffff': 'y', '#FFFFFF': 'y', 'rgb(255, 255, 255)': 'y'} + ColorIsWhite = {'white': 'y', 'WHITE': 'y', '#ffffff': 'y', + '#FFFFFF': 'y', 'rgb(255, 255, 255)': 'y'} - ColorIsBlack = { 'black': 'y', 'BLACK': 'y', '#000000': 'y', 'rgb(0, 0, 0)': 'y'} + ColorIsBlack = {'black': 'y', 'BLACK': 'y', + '#000000': 'y', 'rgb(0, 0, 0)': 'y'} Stroke = Elem.get('stroke') @@ -3978,13 +4416,15 @@ def ProcessSvgLeafNode(FzpType, FileType, InFile, CurView, PrefixDir, Elem, Erro Elem.set('stroke', '#000000') - # Change any non black color to black. + # Change any non black color to black. - Info.append('Modified 3: File\n\'{0:s}\'\nAt line {1:s}\n\nSilkscreen, converted stoke from white to black\n'.format(str(InFile), str(Elem.sourceline))) + Info.append('Modified 3: File\n\'{0:s}\'\nAt line {1:s}\n\nSilkscreen, converted stoke from white to black\n'.format( + str(InFile), str(Elem.sourceline))) elif not (Stroke == None or Stroke == 'none' or Stroke in ColorIsBlack): - Info.append('Modified 3: File\n\'{0:s}\'\nAt line {1:s}\n\nSilkscreen stroke color {2:s} isn\'t white or black. Set to black.\n'.format(str(InFile), str(Elem.sourceline), str(Stroke))) + Info.append('Modified 3: File\n\'{0:s}\'\nAt line {1:s}\n\nSilkscreen stroke color {2:s} isn\'t white or black. Set to black.\n'.format( + str(InFile), str(Elem.sourceline), str(Stroke))) Elem.set('stroke', '#000000') @@ -3996,7 +4436,8 @@ def ProcessSvgLeafNode(FzpType, FileType, InFile, CurView, PrefixDir, Elem, Erro # If the color is currently white or not black set it to black. - Info.append('Modified 3: File\n\'{0:s}\'\nAt line {1:s}\n\nSilkscreen, converted fill from white to black\n'.format(str(InFile), str(Elem.sourceline))) + Info.append('Modified 3: File\n\'{0:s}\'\nAt line {1:s}\n\nSilkscreen, converted fill from white to black\n'.format( + str(InFile), str(Elem.sourceline))) Elem.set('fill', '#000000') @@ -4005,7 +4446,8 @@ def ProcessSvgLeafNode(FzpType, FileType, InFile, CurView, PrefixDir, Elem, Erro # If the current color is neither white nor black (but not none), # tell the user so but otherwise ignore it. - Info.append('Modified 3: File\n\'{0:s}\'\nAt line {1:s}\n\nSilkscreen fill color {2:s} isn\'t white or black. Set to black.\n'.format(str(InFile), str(Elem.sourceline), str(Fill))) + Info.append('Modified 3: File\n\'{0:s}\'\nAt line {1:s}\n\nSilkscreen fill color {2:s} isn\'t white or black. Set to black.\n'.format( + str(InFile), str(Elem.sourceline), str(Fill))) Elem.set('fill', '#000000') @@ -4013,29 +4455,33 @@ def ProcessSvgLeafNode(FzpType, FileType, InFile, CurView, PrefixDir, Elem, Erro # End of if State['lastvalue'] == 'silkscreen': - logging.debug (' ProcessSvgLeafNode: State %s\n', State) + logging.debug(' ProcessSvgLeafNode: State %s\n', State) + + logging.info(' Exiting ProcessSvgLeafNode Level %s\n', Level) - logging.info (' Exiting ProcessSvgLeafNode Level %s\n', Level) +# End of def ProcessSvgLeafNode(FzpType, FileType, InFile, CurView, +# PrefixDir, Elem, Errors, Warnings, Info, FzpDict, TagStack, State, +# InheritedAttributes, Level): -# End of def ProcessSvgLeafNode(FzpType, FileType, InFile, CurView, PrefixDir, Elem, Errors, Warnings, Info, FzpDict, TagStack, State, InheritedAttributes, Level): def SvgStartElem(InFile, Elem, Errors, Warnings, Info, State, Level): - logging.info (' Entering SvgStartElem Level %s\n', Level) + logging.info(' Entering SvgStartElem Level %s\n', Level) NumPxRegex = re.compile(r'\d$|px$', re.IGNORECASE) Tag = Elem.tag if Tag == '{http://www.w3.org/2000/svg}svg' or Tag == 'svg': - + if 'SvgStart' in State: - Warnings.append('Warning 17: File\n\'{0:s}\'\nAt line {1:s}\n\nMore than one svg tag found\n'.format(str(InFile), str(Elem.sourceline))) - + Warnings.append('Warning 17: File\n\'{0:s}\'\nAt line {1:s}\n\nMore than one svg tag found\n'.format( + str(InFile), str(Elem.sourceline))) + # End of if 'SvgStart' in State: - # Mark that we have seen the start tag for later. + # Mark that we have seen the start tag for later. State['SvgStart'] = 'y' @@ -4045,21 +4491,23 @@ def SvgStartElem(InFile, Elem, Errors, Warnings, Info, State, Level): # Check for either a bare number or numberpx as the height or width. - logging.debug (' SvgStartElem: Height %s Width %s\n',Height, Width) + logging.debug(' SvgStartElem: Height %s Width %s\n', Height, Width) if Height == None: - Warnings.append('Warning 18: File\n\'{0:s}\'\nAt line {1:s}\n\nHeight attribute missing\n'.format(str(InFile), str(Elem.sourceline))) + Warnings.append('Warning 18: File\n\'{0:s}\'\nAt line {1:s}\n\nHeight attribute missing\n'.format( + str(InFile), str(Elem.sourceline))) else: Units = NumPxRegex.search(str(Height)) - logging.debug (' SvgStartElem: Height units %s\n', Units) + logging.debug(' SvgStartElem: Height units %s\n', Units) if Units != None: - Warnings.append('Warning 19: File\n\'{0:s}\'\nAt line {1:s}\n\nHeight {2:s} is defined in px\nin or mm is a better option (px can cause scaling problems!)\n'.format(str(InFile), str(Elem.sourceline), str(Height))) + Warnings.append('Warning 19: File\n\'{0:s}\'\nAt line {1:s}\n\nHeight {2:s} is defined in px\nin or mm is a better option (px can cause scaling problems!)\n'.format( + str(InFile), str(Elem.sourceline), str(Height))) # End of if Height != None: @@ -4067,59 +4515,64 @@ def SvgStartElem(InFile, Elem, Errors, Warnings, Info, State, Level): if Width == None: - Warnings.append('Warning 18: File\n\'{0:s}\'\nAt line {1:s}\n\nWidth attribute missing\n'.format(str(InFile), str(Elem.sourceline))) + Warnings.append('Warning 18: File\n\'{0:s}\'\nAt line {1:s}\n\nWidth attribute missing\n'.format( + str(InFile), str(Elem.sourceline))) else: Units = NumPxRegex.search(str(Width)) - logging.debug (' SvgStartElem: Width units %s\n', Units) + logging.debug(' SvgStartElem: Width units %s\n', Units) if Units != None: - Warnings.append('Warning 19: File\n\'{0:s}\'\nAt line {1:s}\n\nWidth {2:s} is defined in px\nin or mm is a better option (px can cause scaling problems!)\n'.format(str(InFile), str(Elem.sourceline), str(Width))) + Warnings.append('Warning 19: File\n\'{0:s}\'\nAt line {1:s}\n\nWidth {2:s} is defined in px\nin or mm is a better option (px can cause scaling problems!)\n'.format( + str(InFile), str(Elem.sourceline), str(Width))) # End of if Units != "": # End of if Width = None: else: - + if not 'SvgStart' in State: - Errors.append('Error 67: File\n\'{0:s}\'\nAt line {1:s}\n\nFirst Tag {2:s} isn\'t an svg definition\n\n'.format(str(InFile), str(Elem.sourceline), str(Tag))) + Errors.append('Error 67: File\n\'{0:s}\'\nAt line {1:s}\n\nFirst Tag {2:s} isn\'t an svg definition\n\n'.format( + str(InFile), str(Elem.sourceline), str(Tag))) # then set 'SvgStart' so we don't repeat this warning. State['SvgStart'] = 'y' - + # End of if not 'SvgStart' in State: # End of if Tag == '{http://www.w3.org/2000/svg}svg': - logging.info (' Exiting SvgStartElem Level %s\n', Level) + logging.info(' Exiting SvgStartElem Level %s\n', Level) # End of def SvgStartElem(InFile, Elem, Errors, Warnings, Info, State, Level): + def SvgRefFile(FzpType, InFile, Elem, Errors, Warnings, Info, State, Level): - logging.info (' Entering SvgRefFile Line %s Level %s\n', Elem.sourceline, Level) + logging.info(' Entering SvgRefFile Line %s Level %s\n', + Elem.sourceline, Level) + + logging.debug(' SvgRefFile: FzpType %s InFile %s\n', FzpType, InFile) - logging.debug (' SvgRefFile: FzpType %s InFile %s\n', FzpType, InFile) - SvgRegex = re.compile(r'^svg\.\w+\.', re.IGNORECASE) - + # Check if this is a referenceFile definition. Tag = Elem.tag - logging.debug (' SvgRefFile: Tag %s\n',Tag) + logging.debug(' SvgRefFile: Tag %s\n', Tag) if Tag != '{http://www.w3.org/2000/svg}referenceFile': # No, so return. - logging.debug (' SvgRefFile: not reference file, returning\n') + logging.debug(' SvgRefFile: not reference file, returning\n') return @@ -4131,9 +4584,9 @@ def SvgRefFile(FzpType, InFile, Elem, Errors, Warnings, Info, State, Level): # Remove the trailing .bak if it is present. - File = re.sub(r'\.bak$','', File) + File = re.sub(r'\.bak$', '', File) - logging.debug (' SvgRefFile: File %s\n', File) + logging.debug(' SvgRefFile: File %s\n', File) if FzpType == 'FZPPART': @@ -4142,7 +4595,7 @@ def SvgRefFile(FzpType, InFile, Elem, Errors, Warnings, Info, State, Level): File = SvgRegex.sub('', File) - logging.debug (' SvgRefFile: Corrected file %s\n', File) + logging.debug(' SvgRefFile: Corrected file %s\n', File) # End of if FzpType == 'FZPPART': @@ -4150,25 +4603,29 @@ def SvgRefFile(FzpType, InFile, Elem, Errors, Warnings, Info, State, Level): # They don't match, so correct it (and log it). - Info.append('Modified 4: File\n\'{0:s}\'\nAt line {1:s}\n\nReferenceFile\n\n\'{2:s}\'\n\ndoesn\'t match input file\n\n\'{3:s}\'\n\nCorrected\n'.format(str(InFile), str(Elem.sourceline), str(Elem.text), str(File))) + Info.append('Modified 4: File\n\'{0:s}\'\nAt line {1:s}\n\nReferenceFile\n\n\'{2:s}\'\n\ndoesn\'t match input file\n\n\'{3:s}\'\n\nCorrected\n'.format( + str(InFile), str(Elem.sourceline), str(Elem.text), str(File))) Elem.text = File - logging.debug (' SvgRefFile: set reference file to %s\n',Elem.text) + logging.debug(' SvgRefFile: set reference file to %s\n', Elem.text) # End of if ReferenceFile != File: -# End of def SvgRefFile(FzpType, InFile, Elem, Errors, Warnings, Info, State, Level): +# End of def SvgRefFile(FzpType, InFile, Elem, Errors, Warnings, Info, +# State, Level): + def SvgCheckForLayerId(Tag, InFile, CurView, Elem, Errors, Warnings, Info, FzpDict, TagStack, State, Level): - logging.info (' Entering SvgCheckForLayerId Level %s\n', Level) + logging.info(' Entering SvgCheckForLayerId Level %s\n', Level) - logging.debug(' SvgCheckForLayerId: On entry Tag %s TagStack %s State %s\n', Tag, TagStack, State) + logging.debug( + ' SvgCheckForLayerId: On entry Tag %s TagStack %s State %s\n', Tag, TagStack, State) - # Check we have seen a svg definition and a layerId before the first + # Check we have seen a svg definition and a layerId before the first # drawing element. Ignore iconview because it doesn't matter as it isn't - # processed by Fritzing. + # processed by Fritzing. if CurView != 'iconView' and not 'SvgFirstGroup' in State and Tag in ['rect', 'line', 'text', 'polyline', 'polygon', 'path', 'circle', 'ellipse', 'tspan']: @@ -4176,7 +4633,8 @@ def SvgCheckForLayerId(Tag, InFile, CurView, Elem, Errors, Warnings, Info, FzpDi # If we haven't seen the svg definition flag an error. - Errors.append('Error 68: File\n\'{0:s}\'\nAt line {1:s}\n\nFound first group but without a svg definition\n'.format(str(InFile), str(Elem.sourceline))) + Errors.append('Error 68: File\n\'{0:s}\'\nAt line {1:s}\n\nFound first group but without a svg definition\n'.format( + str(InFile), str(Elem.sourceline))) # End of if not 'SvgStart' in State: @@ -4184,27 +4642,33 @@ def SvgCheckForLayerId(Tag, InFile, CurView, Elem, Errors, Warnings, Info, FzpDi State['SvgFirstGroup'] = 'y' - logging.debug(' SvgCheckForLayerId: line %s Tag %s found starting tag\n', Elem.sourceline, Tag) - + logging.debug( + ' SvgCheckForLayerId: line %s Tag %s found starting tag\n', Elem.sourceline, Tag) + if CurView != 'iconView' and 'SvgFirstGroup' in State and not 'LayerId' in State: - logging.debug(' SvgCheckForLayerId: drawing element before layerid State %s\n', State) + logging.debug( + ' SvgCheckForLayerId: drawing element before layerid State %s\n', State) # Complain about a drawing element before a layerId - Errors.append('Error 69: File\n\'{0:s}\'\nAt line {1:s}\n\nFound a drawing element before a layerId (or no layerId)\n'.format(str(InFile), str(Elem.sourceline))) + Errors.append('Error 69: File\n\'{0:s}\'\nAt line {1:s}\n\nFound a drawing element before a layerId (or no layerId)\n'.format( + str(InFile), str(Elem.sourceline))) # End of if 'SvgFirstGroup' in State and not 'LayerId' in State: - - # End of if not 'SvgFirstGroup' in State and Tag in ['rect', 'line', 'text', 'polyline', 'polygon', 'path', 'circle', 'ellipse', 'tspan']: - logging.info (' Exiting SvgCheckForLayerId Level %s\n', Level) + # End of if not 'SvgFirstGroup' in State and Tag in ['rect', 'line', + # 'text', 'polyline', 'polygon', 'path', 'circle', 'ellipse', 'tspan']: + + logging.info(' Exiting SvgCheckForLayerId Level %s\n', Level) + +# End of def SvgCheckForLayerId(Tag, InFile, CurView, Elem, Errors, +# Warnings, Info, FzpDict, TagStack, State, Level): -# End of def SvgCheckForLayerId(Tag, InFile, CurView, Elem, Errors, Warnings, Info, FzpDict, TagStack, State, Level): def SvgCheckCopperTransform(Id, Transform, State, Level): - logging.info (' Entering SvgCheckCopperTransform Level %s\n', Level) + logging.info(' Entering SvgCheckCopperTransform Level %s\n', Level) if Transform != None: @@ -4216,17 +4680,19 @@ def SvgCheckCopperTransform(Id, Transform, State, Level): # End of if Transform != None: - logging.debug(' SvgCheckCopperTransform: returned %s \'%s\'\n', Id + '_trans', State[Id + '_trans']) + logging.debug(' SvgCheckCopperTransform: returned %s \'%s\'\n', + Id + '_trans', State[Id + '_trans']) - logging.info (' Exiting SvgCheckCopperTransform Level %s\n', Level) + logging.info(' Exiting SvgCheckCopperTransform Level %s\n', Level) # End of def SvgCheckCopperTransform(Id, Transform, State, Level): + def SvgPcbLayers(Id, InFile, CurView, Elem, Errors, Warnings, Info, FzpDict, TagStack, State, Level): - logging.info (' Entering SvgPcbLayers Level %s\n', Level) + logging.info(' Entering SvgPcbLayers Level %s\n', Level) - logging.debug (' Entering SvgPcbLayers State %s\n', State) + logging.debug(' Entering SvgPcbLayers State %s\n', State) StackTag, StackLevel = TagStack[len(TagStack) - 1] @@ -4246,11 +4712,13 @@ def SvgPcbLayers(Id, InFile, CurView, Elem, Errors, Warnings, Info, FzpDict, Tag if 'seensilkscreen' in State: - # Already seen is an error. + # Already seen is an error. - Errors.append('Error 70: File\n\'{0:s}\'\nAt line {1:s}\n\nMore than one silkscreen layer\n'.format(str(InFile), str(Elem.sourceline))) + Errors.append('Error 70: File\n\'{0:s}\'\nAt line {1:s}\n\nMore than one silkscreen layer\n'.format( + str(InFile), str(Elem.sourceline))) - logging.debug (' SvgPcbLayers: Already seen silkscreen State %s\n', State) + logging.debug( + ' SvgPcbLayers: Already seen silkscreen State %s\n', State) else: @@ -4258,25 +4726,28 @@ def SvgPcbLayers(Id, InFile, CurView, Elem, Errors, Warnings, Info, FzpDict, Tag State['seensilkscreen'] = 'y' - logging.debug (' SvgPcbLayers: Mark seen silkscreen State %s\n', State) + logging.debug( + ' SvgPcbLayers: Mark seen silkscreen State %s\n', State) - # If we have already seen a copper layer issue a warning as that - # makes selection in pcb more difficult. + # If we have already seen a copper layer issue a warning as that + # makes selection in pcb more difficult. if 'seencopper0' in State or 'seencopper1' in State: - Warnings.append('Warning 25: File\n\'{0:s}\'\nAt line {1:s}\n\nSilkscreen layer should be above the copper layers for easier selection\nin pcb view\n'.format(str(InFile), str(Elem.sourceline))) + Warnings.append('Warning 25: File\n\'{0:s}\'\nAt line {1:s}\n\nSilkscreen layer should be above the copper layers for easier selection\nin pcb view\n'.format( + str(InFile), str(Elem.sourceline))) # End of if 'seencopper0' in State or 'seencopper1' in State: # End of if 'seensilkscreen' in State: - + if len(TagStack) != 2: - # Not at the top layer is an error. + # Not at the top layer is an error. + + Errors.append('Error 71: File\n\'{0:s}\'\nAt line {1:s}\n\nSilkscreen layer should be at the top, not under group {2:s}\n'.format( + str(InFile), str(Elem.sourceline), str(BaseTag))) - Errors.append('Error 71: File\n\'{0:s}\'\nAt line {1:s}\n\nSilkscreen layer should be at the top, not under group {2:s}\n'.format(str(InFile), str(Elem.sourceline), str(BaseTag))) - # End of if len(TagStack) != 2: # End of if Id == 'silkscreen': @@ -4285,9 +4756,11 @@ def SvgPcbLayers(Id, InFile, CurView, Elem, Errors, Warnings, Info, FzpDict, Tag if 'seencopper1' in State: - Errors.append('Error 70: File\n\'{0:s}\'\nAt line {1:s}\n\nMore than one copper1 layer\n'.format(str(InFile), str(Elem.sourceline))) + Errors.append('Error 70: File\n\'{0:s}\'\nAt line {1:s}\n\nMore than one copper1 layer\n'.format( + str(InFile), str(Elem.sourceline))) - logging.debug (' SvgPcbLayers: Already seen copper1 State %s\n', State) + logging.debug( + ' SvgPcbLayers: Already seen copper1 State %s\n', State) else: @@ -4295,15 +4768,16 @@ def SvgPcbLayers(Id, InFile, CurView, Elem, Errors, Warnings, Info, FzpDict, Tag State['seencopper1'] = 'y' - logging.debug (' SvgPcbLayers: Mark seen copper1 State %s\n', State) + logging.debug(' SvgPcbLayers: Mark seen copper1 State %s\n', State) # End of if 'seencopper1' in State: if len(TagStack) != 2: - # Not at the top layer is an error but not fatal. + # Not at the top layer is an error but not fatal. - Warnings.append('Warning 20: File\n\'{0:s}\'\nAt line {1:s}\n\ncopper1 layer should be at the top, not under group {2:s}\n'.format(str(InFile), str(Elem.sourceline), str(BaseTag))) + Warnings.append('Warning 20: File\n\'{0:s}\'\nAt line {1:s}\n\ncopper1 layer should be at the top, not under group {2:s}\n'.format( + str(InFile), str(Elem.sourceline), str(BaseTag))) # End of if len(TagStack) != 2: @@ -4313,9 +4787,11 @@ def SvgPcbLayers(Id, InFile, CurView, Elem, Errors, Warnings, Info, FzpDict, Tag if 'seencopper0' in State: - Errors.append('Error 70: File\n\'{0:s}\'\nAt line {1:s}\n\nMore than one copper0 layer\n'.format(str(InFile), str(Elem.sourceline))) + Errors.append('Error 70: File\n\'{0:s}\'\nAt line {1:s}\n\nMore than one copper0 layer\n'.format( + str(InFile), str(Elem.sourceline))) - logging.debug (' SvgPcbLayers: Already seen copper0 State %s\n', State) + logging.debug( + ' SvgPcbLayers: Already seen copper0 State %s\n', State) else: @@ -4323,52 +4799,56 @@ def SvgPcbLayers(Id, InFile, CurView, Elem, Errors, Warnings, Info, FzpDict, Tag State['seencopper0'] = 'y' - logging.debug (' SvgPcbLayers: Mark seen copper0 State %s\n', State) + logging.debug(' SvgPcbLayers: Mark seen copper0 State %s\n', State) # End of if 'seencopper0' in State: if len(TagStack) == 2 and 'seencopper1' in State: - # Not under copper1 is an error (this is the same level as copper1) + # Not under copper1 is an error (this is the same level as copper1) - Errors.append('Error 72: File\n\'{0:s}\'\nAt line {1:s}\n\ncopper0 should be under copper1 not the same level\n'.format(str(InFile), str(Elem.sourceline))) + Errors.append('Error 72: File\n\'{0:s}\'\nAt line {1:s}\n\ncopper0 should be under copper1 not the same level\n'.format( + str(InFile), str(Elem.sourceline))) elif len(TagStack) > 3: # too many layers is an error. - Errors.append('Error 73: File\n\'{0:s}\'\nAt line {1:s}\n\nToo many layers, there should only be copper1 then copper0\n'.format(str(InFile), str(Elem.sourceline))) + Errors.append('Error 73: File\n\'{0:s}\'\nAt line {1:s}\n\nToo many layers, there should only be copper1 then copper0\n'.format( + str(InFile), str(Elem.sourceline))) # End of if len(TagStack) == 3 and 'seencopper1' in State: # End of if Id == 'copper0': - logging.info (' Exiting SvgPcbLayers Level %s\n', Level) + logging.info(' Exiting SvgPcbLayers Level %s\n', Level) + +# End of def SvgPcbLayers(Id, InFile, CurView, Elem, Errors, Warnings, +# Info, FzpDict, TagStack, State, Level): -# End of def SvgPcbLayers(Id, InFile, CurView, Elem, Errors, Warnings, Info, FzpDict, TagStack, State, Level): def SvgCheckPcbLayers(InFile, Errors, Warnings, Info, FzpDict, TagStack, State): - logging.info (' Entering SvgCheckPcbLayers\n') + logging.info(' Entering SvgCheckPcbLayers\n') # This is only an svg file (we haven't seen the associated fzp) # so determine if this is likely SMD and if not output the no # hole messages in State and set SMD or Through hole in Info. - logging.debug (' SvgCheckPcbLayers: No fzp file State %s\n', State) + logging.debug(' SvgCheckPcbLayers: No fzp file State %s\n', State) if 'seencopper0' in State and 'seencopper1' in State: - # This is a through hole part so note that in Info and - # copy any no radius error messages to Errors. - - Info.append('File\n\'{0:s}\'\n\nThis is a through hole part as both copper0 and copper1 views are present.\n'.format(str(InFile))) + # This is a through hole part so note that in Info and + # copy any no radius error messages to Errors. + Info.append( + 'File\n\'{0:s}\'\n\nThis is a through hole part as both copper0 and copper1 views are present.\n'.format(str(InFile))) if State['noradius'] != '': - # We have seen holes without a radius (which is normal for - # smd parts but an error in through hole) so report them + # We have seen holes without a radius (which is normal for + # smd parts but an error in through hole) so report them # by moving them from State in to Errors. for Message in State['noradius']: @@ -4383,36 +4863,43 @@ def SvgCheckPcbLayers(InFile, Errors, Warnings, Info, FzpDict, TagStack, State): # This appears to be a normal SMD part so note that in Info. - Info.append('File\n\'{0:s}\'\n\nThis is a smd part as only the copper1 view is present.\n'.format(str(InFile))) + Info.append( + 'File\n\'{0:s}\'\n\nThis is a smd part as only the copper1 view is present.\n'.format(str(InFile))) elif 'seencopper0' in State: # This appears to be a SMD part but on the bottom of the board # so note that in Errors. - Errors.append('Error 75: File\n\'{0:s}\'\n\nThis is a smd part as only the copper0 view is present\nbut it is on the bottom layer, not the top.\n\n'.format(str(InFile))) + Errors.append( + 'Error 75: File\n\'{0:s}\'\n\nThis is a smd part as only the copper0 view is present\nbut it is on the bottom layer, not the top.\n\n'.format(str(InFile))) elif 'seensilkscreen' in State: # This appears to be only a silkscreen so note that in Info. - Info.append('File\n\'{0:s}\'\n\nThis is an only silkscreen part as has no copper layers present.\n'.format(str(InFile))) + Info.append( + 'File\n\'{0:s}\'\n\nThis is an only silkscreen part as has no copper layers present.\n'.format(str(InFile))) else: - Warnings.append('Warning 21: File\n\'{0:s}\'\n\nThis appears to be a pcb svg but has no copper or silkscreen layers!\n'.format(str(InFile))) + Warnings.append( + 'Warning 21: File\n\'{0:s}\'\n\nThis appears to be a pcb svg but has no copper or silkscreen layers!\n'.format(str(InFile))) # End of if 'seencopper0' in State and 'seencopper1' in State: - logging.info (' Exiting SvgCheckPcbLayers\n') + logging.info(' Exiting SvgCheckPcbLayers\n') + +# End of def SvgCheckPcbLayers(InFile, Errors, Warnings, Info, FzpDict, +# TagStack, State): -# End of def SvgCheckPcbLayers(InFile, Errors, Warnings, Info, FzpDict, TagStack, State): def SvgGroup(InFile, CurView, Elem, Errors, Warnings, Info, FzpDict, TagStack, State, Level): - logging.info (' Entering SvgGroup Level %s\n', Level) + logging.info(' Entering SvgGroup Level %s\n', Level) - logging.debug(' SvgGroup: On entry Errors: %s CurView %s TagStack %s State %s\n', Errors, CurView, TagStack, State) + logging.debug(' SvgGroup: On entry Errors: %s CurView %s TagStack %s State %s\n', + Errors, CurView, TagStack, State) TspanRegex = re.compile(r'^tspan', re.IGNORECASE) @@ -4420,7 +4907,7 @@ def SvgGroup(InFile, CurView, Elem, Errors, Warnings, Info, FzpDict, TagStack, S # First get the tag to see if we are past the boiler plate and have seen # the initial group that starts the actual svg (so we can search for the - # layerid before any constructs). + # layerid before any constructs). Tag = Elem.tag @@ -4428,9 +4915,9 @@ def SvgGroup(InFile, CurView, Elem, Errors, Warnings, Info, FzpDict, TagStack, S Tag = NameSpaceRegex.sub('', str(Tag)) - Id = Elem.get('id') - - logging.debug(' SvgGroup: Entry Id %s TagStack %s\n', Id, TagStack ) + Id = Elem.get('id') + + logging.debug(' SvgGroup: Entry Id %s TagStack %s\n', Id, TagStack) if Id != None: @@ -4444,15 +4931,15 @@ def SvgGroup(InFile, CurView, Elem, Errors, Warnings, Info, FzpDict, TagStack, S if CurView == None: - # This isn't from an fzp file so we don't have a layerid list to - # compare against. So see if this is likely a layerId (this will + # This isn't from an fzp file so we don't have a layerid list to + # compare against. So see if this is likely a layerId (this will # sometimes false error when a layerId is nonstandard). In addition # keep track of tspan ids to check for nested tspans which fritzing # doesn't support. Hopefully they will not occur in areas where the # tag stack values are checked (they shouldn't, but you never know) if Id in ['breadboard', 'icon', 'schematic', 'silkscreen', 'copper0', 'copper1'] or TspanRegex.match(str(Id)): - + # Push the Id and Level on to the tag stack. TagStack.append([Id, Level]) @@ -4464,29 +4951,32 @@ def SvgGroup(InFile, CurView, Elem, Errors, Warnings, Info, FzpDict, TagStack, S if TspanRegex.match(str(State['lastvalue'])): # Nested tspan which fritzing doesn't support so issue a - # warning. + # warning. - Warnings.append('Warning 26: File\n\'{0:s}\'\nAt line {1:s}\n\nApparant nested tspan which fritzing doesn\'t support\nIf your text doesn\'t appear in Fritzing this is probably why\n'.format(str(InFile), str(Elem.sourceline))) + Warnings.append('Warning 26: File\n\'{0:s}\'\nAt line {1:s}\n\nApparant nested tspan which fritzing doesn\'t support\nIf your text doesn\'t appear in Fritzing this is probably why\n'.format( + str(InFile), str(Elem.sourceline))) # End of if TspanRegex.match(str(State['lastvalue'])): else: - # This isn't a tspan element so check it the tag is a group - # and issue a warning if it is not. + # This isn't a tspan element so check it the tag is a group + # and issue a warning if it is not. if not Tag == 'g': - Warnings.append('Warning 27: File\n\'{0:s}\'\nAt line {1:s}\n\nFritzing layerId {2:s} isn\'t a group which it usually should be\n'.format(str(InFile), str(Elem.sourceline), str(Id))) + Warnings.append('Warning 27: File\n\'{0:s}\'\nAt line {1:s}\n\nFritzing layerId {2:s} isn\'t a group which it usually should be\n'.format( + str(InFile), str(Elem.sourceline), str(Id))) # End of if not Tag == 'g': - # End of if re.match(r'^tspan', str(Id)) and re.match(r'^tspan', str(State['lastvalue'])): - + # End of if re.match(r'^tspan', str(Id)) and re.match(r'^tspan', + # str(State['lastvalue'])): + # Set the current layer in to State['lastvalue'] - + State['lastvalue'] = Id - + if Id in ['silkscreen', 'copper0', 'copper1']: # Mark that this appears to be a pcb svg in State. @@ -4495,32 +4985,35 @@ def SvgGroup(InFile, CurView, Elem, Errors, Warnings, Info, FzpDict, TagStack, S # Then check that the layers are in the correct order. - SvgPcbLayers(Id, InFile, CurView, Elem, Errors, Warnings, Info, FzpDict, TagStack, State, Level) + SvgPcbLayers(Id, InFile, CurView, Elem, Errors, + Warnings, Info, FzpDict, TagStack, State, Level) else: logging.debug(' SvgGroup: before test State %s\n', State) - # If this Id is tspan, it isn't a layerid so don't trip the - # too many layerids warning. + # If this Id is tspan, it isn't a layerid so don't trip the + # too many layerids warning. if not TspanRegex.match(str(Id)) and 'LayerId' in State: - # Single layerId case, but more than one layerId. + # Single layerId case, but more than one layerId. + + Warnings.append('Warning 22: File\n\'{0:s}\'\nAt line {1:s}\n\nAlready have a layerId\n'.format( + str(InFile), str(Elem.sourceline))) - Warnings.append('Warning 22: File\n\'{0:s}\'\nAt line {1:s}\n\nAlready have a layerId\n'.format(str(InFile), str(Elem.sourceline))) - logging.debug(' SvgGroup: Warning dup layer issued\n') # End of if 'LayerId' in State: # End of if Id in ['silkscreen', 'copper0', 'copper1']: - + # and note we have seen a LayerId in State for later. - + State['LayerId'] = 'y' - # End of if Id in ['breadboard', 'icon', 'schematic', 'silkscreen', 'copper0', copper1']: + # End of if Id in ['breadboard', 'icon', 'schematic', 'silkscreen', + # 'copper0', copper1']: else: @@ -4532,31 +5025,35 @@ def SvgGroup(InFile, CurView, Elem, Errors, Warnings, Info, FzpDict, TagStack, S if CurView == 'schematicView' and 'subparts' in FzpDict: # We are in a schematic svg that has subparts so check if this - # is a subpart id and add it to the tag stack if so. + # is a subpart id and add it to the tag stack if so. - logging.debug(' SvgGroup: CurView %s subparts %s\n', CurView, FzpDict['subparts']) + logging.debug(' SvgGroup: CurView %s subparts %s\n', + CurView, FzpDict['subparts']) if Id in FzpDict['subparts']: - # Check that schematic is the only thing above this on + # Check that schematic is the only thing above this on # the tag stack and issue a warning if that isn't true. if len(TagStack) != 2: - logging.debug(' SvgGroup: TagStack len %s not top level warning issued\n', len(TagStack)) + logging.debug( + ' SvgGroup: TagStack len %s not top level warning issued\n', len(TagStack)) - Errors.append('Error 86: File\n\'{0:s}\'\nAt line {1:s}\n\nSubpart {2:s} isn\'t at the top level when it must be\nFollowing subpart errors may be invalid until this is fixed\n'.format(str(InFile), str(Elem.sourceline), str(Id))) + Errors.append('Error 86: File\n\'{0:s}\'\nAt line {1:s}\n\nSubpart {2:s} isn\'t at the top level when it must be\nFollowing subpart errors may be invalid until this is fixed\n'.format( + str(InFile), str(Elem.sourceline), str(Id))) # End of if len(TagStack) != 2: - logging.debug(' SvgGroup: subpart %s found and added\n', Id) - + logging.debug( + ' SvgGroup: subpart %s found and added\n', Id) + # Push the Id and Level on to the tag stack. TagStack.append([Id, Level]) - + # Set the current layer in to State['lastvalue'] - + State['lastvalue'] = Id # End of if Id in FzpDict['subparts']: @@ -4565,7 +5062,8 @@ def SvgGroup(InFile, CurView, Elem, Errors, Warnings, Info, FzpDict, TagStack, S # Only one layerid so check for it. - logging.debug(' SvgGroup: CurView %s LayerId %s\n', CurView, FzpDict[CurView + '.LayerId']) + logging.debug(' SvgGroup: CurView %s LayerId %s\n', + CurView, FzpDict[CurView + '.LayerId']) if Id == FzpDict[CurView + '.LayerId']: @@ -4575,29 +5073,31 @@ def SvgGroup(InFile, CurView, Elem, Errors, Warnings, Info, FzpDict, TagStack, S if 'LayerId' in State: - # More than one layerid warning. + # More than one layerid warning. - Warnings.append('Warning 25: File\n\'{0:s}\'\nAt line {1:s}\n\nAlready have a layerId\n'.format(str(InFile), str(Elem.sourceline))) + Warnings.append('Warning 25: File\n\'{0:s}\'\nAt line {1:s}\n\nAlready have a layerId\n'.format( + str(InFile), str(Elem.sourceline))) else: - + # and note we have seen a LayerId in State for later. - + State['LayerId'] = 'y' - + # Set the current layer in to State['lastvalue'] - + State['lastvalue'] = Id - + logging.debug(' SvgGroup: set State[\'view\'] to %s\n', Id) # End of if 'LayerId' in State: - # Issue a warning if the layerId isn't a group. + # Issue a warning if the layerId isn't a group. if not Tag == 'g': - Warnings.append('Warning 27: File\n\'{0:s}\'\nAt line {1:s}\n\nFritzing layerId {2:s} isn\'t a group which it usually should be\n'.format(str(InFile), str(Elem.sourceline), str(Id))) + Warnings.append('Warning 27: File\n\'{0:s}\'\nAt line {1:s}\n\nFritzing layerId {2:s} isn\'t a group which it usually should be\n'.format( + str(InFile), str(Elem.sourceline), str(Id))) # End of if not Tag == 'g': @@ -4605,53 +5105,56 @@ def SvgGroup(InFile, CurView, Elem, Errors, Warnings, Info, FzpDict, TagStack, S else: - # This is pcbView so the LayerIds are a list, and life is more + # This is pcbView so the LayerIds are a list, and life is more # complex. For layerids other than copper0 and copper1, they must - # be at the top of the tagstack (not under another layerid). If - # both copper0 and copper1 are present the order should be copper1 + # be at the top of the tagstack (not under another layerid). If + # both copper0 and copper1 are present the order should be copper1 # copper0 so smd parts are by default on the top layer. So warn # about copper1 under copper0 and error for copper0 and copper1 on - # the same level. + # the same level. + + logging.debug(' SvgGroup: %s Curview %s LayerIds %s\n', + Id, CurView, FzpDict[CurView + '.LayerId']) - logging.debug(' SvgGroup: %s Curview %s LayerIds %s\n', Id, CurView, FzpDict[CurView + '.LayerId']) - if Id in FzpDict[CurView + '.LayerId']: - + # Push the Id and Level on to the tag stack. TagStack.append([Id, Level]) - + logging.debug(' SvgGroup: pushed %s on to tag stack\n', Id) - + # and note we have seen the LayerId in State for later. - + State['LayerId'] = 'y' - + State[CurView + 'LayerId'] = 'y' - + # Set the current layer in to State['lastvalue'] - + State['lastvalue'] = Id - SvgPcbLayers(Id, InFile, CurView, Elem, Errors, Warnings, Info, FzpDict, TagStack, State, Level) - + SvgPcbLayers(Id, InFile, CurView, Elem, Errors, + Warnings, Info, FzpDict, TagStack, State, Level) + logging.debug(' SvgGroup: set State[\'view\'] to %s\n', Id) - # Issue a warning if the layerId isn't a group. + # Issue a warning if the layerId isn't a group. if not Tag == 'g': - Warnings.append('Warning 27: File\n\'{0:s}\'\nAt line {1:s}\n\nFritzing layerId {2:s} isn\'t a group which it usually should be\n'.format(str(InFile), str(Elem.sourceline), str(Id))) + Warnings.append('Warning 27: File\n\'{0:s}\'\nAt line {1:s}\n\nFritzing layerId {2:s} isn\'t a group which it usually should be\n'.format( + str(InFile), str(Elem.sourceline), str(Id))) # End of if not Tag == 'g': - + # End of if Id in FzpDict[CurView + '.LayerId']: # End of if CurView == None: if Id in ['copper0', 'copper1']: - # If this is copper0 or copper1, check for a transform as a + # If this is copper0 or copper1, check for a transform as a # transform in one but not the other is an error. Transform = Elem.get('transform') @@ -4662,58 +5165,66 @@ def SvgGroup(InFile, CurView, Elem, Errors, Warnings, Info, FzpDict, TagStack, S if 'copper0' in TagStack and 'copper1' in TagStack and State['copper0_trans'] != State['copper1_trans']: - # We have seen both coppers and they doesn't have - # identical transforms so set an error. + # We have seen both coppers and they doesn't have + # identical transforms so set an error. - Errors.append('Error 76: File\n\'{0:s}\'\nAt line {1:s}\n\nCopper0 and copper1 have non identical transforms (no transforms is best)\n'.format(str(InFile), str(Elem.sourceline))) + Errors.append('Error 76: File\n\'{0:s}\'\nAt line {1:s}\n\nCopper0 and copper1 have non identical transforms (no transforms is best)\n'.format( + str(InFile), str(Elem.sourceline))) logging.debug(' SvgGroup: set copper transform error\n') - # End of if 'copper0' in TagStack and 'copper1' in TagStack and State['copper0_trans'] != State['copper1_trans']: + # End of if 'copper0' in TagStack and 'copper1' in TagStack and + # State['copper0_trans'] != State['copper1_trans']: # End of if CurView == None: - logging.debug(' SvgGroup: On exit Errors %s CurView %s TagStack %s len tagstack %s State %s\n', Errors, CurView, TagStack, len(TagStack), State) + logging.debug(' SvgGroup: On exit Errors %s CurView %s TagStack %s len tagstack %s State %s\n', + Errors, CurView, TagStack, len(TagStack), State) + + logging.info(' Exiting SvgGroup Level %s\n', Level) - logging.info (' Exiting SvgGroup Level %s\n', Level) +# End of def SvgGroup(InFile, CurView, Elem, Errors, Warnings, Info, +# FzpDict, TagStack, State, Level): -# End of def SvgGroup(InFile, CurView, Elem, Errors, Warnings, Info, FzpDict, TagStack, State, Level): def SvgInlineStyle(InFile, Elem, Warnings, State): # If there is a style command in the attributes, convert it to inline - # xml (overwriting current values if present). - - logging.info (' Entering SvgInlineStyle\n') + # xml (overwriting current values if present). + + logging.info(' Entering SvgInlineStyle\n') # Get the current style values if any ElemAttributes = Elem.get('style') - if not ElemAttributes == None: + if not ElemAttributes == None: # Delete the current style attribute - logging.debug (' SvgInlineStyle: delete style: %s\n', ElemAttributes) + logging.debug(' SvgInlineStyle: delete style: %s\n', ElemAttributes) Elem.attrib.pop("style", None) - # Then add the elements back in inline (replacing current values if - # present, as style should overide inline values usually). + # Then add the elements back in inline (replacing current values if + # present, as style should overide inline values usually). Attributes = ElemAttributes.split(';') - logging.debug (' SvgInlineStyle: attributes %s line %s\n', Attributes, Elem.sourceline) + logging.debug(' SvgInlineStyle: attributes %s line %s\n', + Attributes, Elem.sourceline) for Attribute in Attributes: - KeyValue = Attribute.split (':') + KeyValue = Attribute.split(':') - logging.debug (' SvgInlineStyle: Attribute %s KeyValue %s\n', Attribute, KeyValue) + logging.debug( + ' SvgInlineStyle: Attribute %s KeyValue %s\n', Attribute, KeyValue) # Then set the pair as attribute=value - logging.debug (' SvgInlineStyle: attribute %s key len %s key[0] %s\n', Attribute, str(len(KeyValue)), KeyValue[0]) + logging.debug(' SvgInlineStyle: attribute %s key len %s key[0] %s\n', Attribute, str( + len(KeyValue)), KeyValue[0]) if len(KeyValue) == 2: @@ -4722,19 +5233,21 @@ def SvgInlineStyle(InFile, Elem, Warnings, State): # if this test isn't made. Probably invalid xml but harmless. # Whitespace (I think only leading whitespace) in the i # attributes also causes this exception so remove any leading - # white space (because there is at least one file that not + # white space (because there is at least one file that not # doing so breaks!). - logging.debug (' SvgInlineStyle: before regex KeyValue\[0\] \'%s\' KeyValue\[1\] \'%s\'\n', KeyValue[0], KeyValue[1]) + logging.debug(' SvgInlineStyle: before regex KeyValue\[0\] \'%s\' KeyValue\[1\] \'%s\'\n', KeyValue[ + 0], KeyValue[1]) - KeyValue[0] = re.sub(r'^\s+','', KeyValue[0]) + KeyValue[0] = re.sub(r'^\s+', '', KeyValue[0]) - KeyValue[1] = re.sub(r'^\s+','', KeyValue[1]) + KeyValue[1] = re.sub(r'^\s+', '', KeyValue[1]) - logging.debug (' SvgInlineStyle: after regex KeyValue\[0\] \'%s\' KeyValue\[1\] \'%s\'\n', KeyValue[0], KeyValue[1]) + logging.debug(' SvgInlineStyle: after regex KeyValue\[0\] \'%s\' KeyValue\[1\] \'%s\'\n', KeyValue[ + 0], KeyValue[1]) try: - + Elem.set(KeyValue[0], KeyValue[1]) except ValueError: @@ -4747,17 +5260,20 @@ def SvgInlineStyle(InFile, Elem, Warnings, State): if not KeyValue[0] in State['KeyErrors']: - logging.debug (' SvgInlineStyle: KeyValue\[0\] %s State %s\n', KeyValue[0], State) + logging.debug( + ' SvgInlineStyle: KeyValue\[0\] %s State %s\n', KeyValue[0], State) # Haven't seen this one yet so log it. - Warnings.append('Warning 23: File\n\'{0:s}\'\nAt line {1:s}\n\nKey {2:s}\nvalue {3:s} is invalid and has been deleted\n'.format(str(InFile), str(Elem.sourceline), str(KeyValue[0]), str(KeyValue[1]))) + Warnings.append('Warning 23: File\n\'{0:s}\'\nAt line {1:s}\n\nKey {2:s}\nvalue {3:s} is invalid and has been deleted\n'.format( + str(InFile), str(Elem.sourceline), str(KeyValue[0]), str(KeyValue[1]))) # Then add it to State to ignore more of them State['KeyErrors'].append(KeyValue[0]) - logging.debug (' SvgInlineStyle: attribute %s %s is invalid, deleted\n', KeyValue[0], KeyValue[1]) + logging.debug(' SvgInlineStyle: attribute %s %s is invalid, deleted\n', KeyValue[ + 0], KeyValue[1]) # End of if not KeyValue[0] in State['KeyErrors']: @@ -4767,12 +5283,13 @@ def SvgInlineStyle(InFile, Elem, Warnings, State): # End of for Attribute in Attributes: - # end of if not ElemAttributes == None: + # end of if not ElemAttributes == None: - logging.info (' Exiting SvgInlineStyle\n') + logging.info(' Exiting SvgInlineStyle\n') # End of def SvgInlineStyle(InFile, Elem, Warnings, State): + def SvgRemoveInheritableAttribs(InFile, Elem, Errors, Warnings, Info, State, InheritedAttributes, Level): # Some part of Fritzing (probably the script to produce the gerber output) @@ -4785,17 +5302,20 @@ def SvgRemoveInheritableAttribs(InFile, Elem, Errors, Warnings, Info, State, Inh # the leaf nodes of all elements of copper0 or copper1 which should fix # the problem and allow us to use optimised svg in Inkscape. - logging.info (' Entering SvgRemoveInheritableAttribs Level %s State[\'lastvalue\'] %s\n', Level, State['lastvalue']) + logging.info( + ' Entering SvgRemoveInheritableAttribs Level %s State[\'lastvalue\'] %s\n', Level, State['lastvalue']) if not (State['lastvalue'] == 'copper0' or State['lastvalue'] == 'copper1'): - # Not in a pcb copper layer so don't do anything. + # Not in a pcb copper layer so don't do anything. - logging.debug(' Exiting SvgRemoveInheritableAttribs unchanged not pcb group\n') + logging.debug( + ' Exiting SvgRemoveInheritableAttribs unchanged not pcb group\n') return - # End of if not (State['lastvalue'] == 'copper0' or State['lastvalue'] == 'copper1'): + # End of if not (State['lastvalue'] == 'copper0' or State['lastvalue'] == + # 'copper1'): # First Convert any style command to inline xml @@ -4807,35 +5327,40 @@ def SvgRemoveInheritableAttribs(InFile, Elem, Errors, Warnings, Info, State, Inh if StrokeWidth != None: - # Overwrite any previous value with the current value. + # Overwrite any previous value with the current value. InheritedAttributes = 'stroke-width:' + StrokeWidth # End of if StrokeWidth != None: - logging.debug(' Exiting SvgRemoveInheritableAttribs set InheritedAttributes to %s\n', StrokeWidth) + logging.debug( + ' Exiting SvgRemoveInheritableAttribs set InheritedAttributes to %s\n', StrokeWidth) + + logging.info(' Exiting SvgRemoveInheritableAttribs Level %s\n', Level) - logging.info (' Exiting SvgRemoveInheritableAttribs Level %s\n', Level) +# End of def SvgRemoveInheritableAttribs(InFile, Elem, Errors, Warnings, +# Info, State, InheritedAttributes, Level): -# End of def SvgRemoveInheritableAttribs(InFile, Elem, Errors, Warnings, Info, State, InheritedAttributes, Level): def SvgSvgSetInheritedAttributes(InFile, Elem, InheritedAttributes): # Some part of Fritzing (probably the script to produce the gerber output) # can't deal with inheritance. The case that drove this change (and the # only translation currently being done) is to save the svg in Inkscape - # as optimized svg (rather than plain) at which point the stroke-width + # as optimized svg (rather than plain) at which point the stroke-width # attribute is optimized in to copper0 or copper1 top level and inherited. # The output geber missing the stroke-width parameter outputs an oversize - # nonplated through hole. To fix that we copy the stroke length in to + # nonplated through hole. To fix that we copy the stroke length in to # the leaf nodes of all elements of copper0 or copper1 which should fix # the problem and allow us to use optimised svg in Inkscape. - logging.info (' Entering SvgSetInheritedAttributes\n') + logging.info(' Entering SvgSetInheritedAttributes\n') - Info.append('Modified 5: File\n\'{0:s}\'\nAt line {1:s}\n\nConverted style to inline xml\n'.format(str(InFile), str(Elem.sourceline))) + Info.append('Modified 5: File\n\'{0:s}\'\nAt line {1:s}\n\nConverted style to inline xml\n'.format( + str(InFile), str(Elem.sourceline))) - logging.debug ('SvgSetInheritedAttributes: Elem attributes on entry %s InheritedAttributes %s\n', Elem.attrib, InheritedAttributes) + logging.debug('SvgSetInheritedAttributes: Elem attributes on entry %s InheritedAttributes %s\n', + Elem.attrib, InheritedAttributes) attributes = InheritedAttributes.split(';') @@ -4845,16 +5370,17 @@ def SvgSvgSetInheritedAttributes(InFile, Elem, InheritedAttributes): if not Elem.get(KeyValue[0]): - # if the key doesn't currently exist then add it and its - # associated value. + # if the key doesn't currently exist then add it and its + # associated value. - logging.debug (' SvgSetInheritedAttributes: Set new element key %s to inherited attribute value: %s\n', KeyValue[0], KeyValue[1]) + logging.debug(' SvgSetInheritedAttributes: Set new element key %s to inherited attribute value: %s\n', KeyValue[ + 0], KeyValue[1]) Elem.set(KeyValue[0], KeyValue[1]) - logging.debug (' SvgSetInheritedAttributes: At end Elem attributes %s\n', Elem.attrib) + logging.debug( + ' SvgSetInheritedAttributes: At end Elem attributes %s\n', Elem.attrib) - logging.info (' Exiting SvgSetInheritedAttributes\n') + logging.info(' Exiting SvgSetInheritedAttributes\n') # End of def SvgSetInheritedAttributes(InFile, Elem, InheritedAttributes): - diff --git a/PP.py b/PP.py index a5c3020..fc5912c 100755 --- a/PP.py +++ b/PP.py @@ -1,28 +1,32 @@ #!/usr/bin/env python3 -# A python xml pretty_print script written to pretty print svg files from -# Inkscape, but should work on pretty much any xml. +# A python xml pretty_print script written to pretty print svg files from +# Inkscape, but should work on pretty much any xml. -# Set Debug to 0 for normal operation (rename the input file and write the +# Set Debug to 0 for normal operation (rename the input file and write the # pretty printed output to the input file name. -# -# Set Debug to 1 to not rename the input file and send the output to the +# +# Set Debug to 1 to not rename the input file and send the output to the # console rather than write it to the file, but no other debug messages. # Set Debug to 2 for debug messages on entry and exit from subroutines and -# to not rename the input file iand write the output to the console rather -# than the file for debugging. +# to not rename the input file iand write the output to the console rather +# than the file for debugging. -# Set Debug to 3 for very verbose debug messages. +# Set Debug to 3 for very verbose debug messages. +import logging +import re +import sys +import os +import PPTools as PP Debug = 0 Version = '0.0.2' # Version number of this file. - -# Import os and sys to get file rename and the argv stuff, re for regex and + +# Import os and sys to get file rename and the argv stuff, re for regex and # logging to get logging support and the various svg routines from LxmlTools. - -import os, sys, re, logging + # Set up the requested debug level @@ -43,8 +47,7 @@ # End of if Debug == 3: # The logging level needs to be set before we import this library. - -import PPTools as PP + # Start of the main script @@ -56,41 +59,42 @@ Info = [] -InFile = PP.ProcessArgs (sys.argv, Errors) +InFile = PP.ProcessArgs(sys.argv, Errors) if len(InFile) > 0: - + for File in InFile: - print ('Process {0:s}\n'.format(str(File))) + print('Process {0:s}\n'.format(str(File))) - Doc, Root = PP.ParseFile (File, Errors) + Doc, Root = PP.ParseFile(File, Errors) if Root != None: - # If we managed to parse the file, then set up to pretty print it - # as if it was a svg (to pretty print to the element level). - # As we don't have a path broken out of the file name, set it to - # nothing (Fritzing processing needs the path when using these + # If we managed to parse the file, then set up to pretty print it + # as if it was a svg (to pretty print to the element level). + # As we don't have a path broken out of the file name, set it to + # nothing (Fritzing processing needs the path when using these # routines). FileType = 'SVG' Path = '' - PP.OutputTree(Doc, Root, FileType, Path, File, Errors, Warnings, Info, Debug) + PP.OutputTree(Doc, Root, FileType, Path, File, + Errors, Warnings, Info, Debug) # End of if Root != None: # End of for Files in InFile: - # Print any error messages found. + # Print any error messages found. PP.PrintErrors(Errors) - + # End of if len(InFile) > 0: -# Set the return code depending on whether there were errors or not. +# Set the return code depending on whether there were errors or not. if len(Errors) > 0: diff --git a/PPTools.py b/PPTools.py index 8244a0c..654ee23 100755 --- a/PPTools.py +++ b/PPTools.py @@ -4,28 +4,31 @@ # other xml as well.) # Enable detail pretty printing of svg files. If you suspect the detail pretty -# printing is causeing problems, set this to 'n' to disable detail pretty +# printing is causeing problems, set this to 'n' to disable detail pretty # printing (and if that fixes it, please report the bug). +import logging +import re +import sys +import os +from lxml import etree +from io import BytesIO DetailPP = 'Y' Version = '0.0.2' # Version number of this file. -# Import os and sys to get file rename and the argv stuff, re for regex and -# logging to get logging support. +# Import os and sys to get file rename and the argv stuff, re for regex and +# logging to get logging support. -import os, sys, re, logging # This library lets me write the lxml output to a string (which apparantly # can't be done from lxml) to pretty print it further than lxml does. -from io import BytesIO # and the lxml library for the xml parsing. -from lxml import etree -# Try and supress debug messages from PP which is debugged already. +# Try and supress debug messages from PP which is debugged already. logging.basicConfig(stream=sys.stderr, level=logging.WARNING) @@ -35,9 +38,10 @@ # http://effbot.org/zone/element-lib.htm#prettyprint + def Indent(Elem, Debug, Level=0): - logging.info (' Entering indent level %s\n', Level) + logging.info(' Entering indent level %s\n', Level) I = "\n" + Level*" " if len(Elem): @@ -53,28 +57,29 @@ def Indent(Elem, Debug, Level=0): if Level and (not Elem.tail or not Elem.tail.strip()): Elem.tail = I - logging.info (' Exiting Indent level %s\n', Level) + logging.info(' Exiting Indent level %s\n', Level) # End of def Indent(Elem, Debug, Level=0): -# A splitting subroutine that will split only on blanks not in a quoted +# A splitting subroutine that will split only on blanks not in a quoted # string (the only one in the thread that will do so without either eating # the quotes or putting them in a separate item neither of which will do here) # from: # # http://stackoverflow.com/questions/79968/split-a-string-by-spaces-preserving-quoted-substrings-in-python # -# modified to also ignore spaces in text by matching '>.+?.+?.+?.+?<\/text>' by ' >.+?<\/text>' so the the - # text will be split on to a new line (even if there wasn't a space - # there before, which in ours is usually the case, it is on a line with - # a grom. + # Replace the text string '>.+?<\/text>' by ' >.+?<\/text>' so the the + # text will be split on to a new line (even if there wasn't a space + # there before, which in ours is usually the case, it is on a line with + # a grom. T = re.sub(r'(>.+?<\/text>)', ' \g<1>', S) @@ -93,37 +98,38 @@ def Replacer(M): T = re.sub(r'(>.+?<\/tspan>)', ' \g<1>', S) - # Do this with a trailing blank for comments to so the following element # is correctly indented on a new line. T = re.sub(r'()', '\g<1> ', S) - # Now replace the blanks in quoted strings, text, comments and - # referenceFile (all of which contain blanks we need to keep) with \x00 - # then split the string on blanks. + # Now replace the blanks in quoted strings, text, comments and + # referenceFile (all of which contain blanks we need to keep) with \x00 + # then split the string on blanks. - Parts = re.sub(r'".+?"|>.+?<\/text>|>.+?<\/tspan>||referenceFile\s*>.+?.+?<\/text>|>.+?<\/tspan>||referenceFile\s*>.+? 2: - logging.debug (' PrettyPrintElements: Pass xml def through\n') + logging.debug(' PrettyPrintElements: Pass xml def through\n') # End of if Debug > 2: XmlPP = XmlPP + Line + '\n' - else : + else: - # First get the leading whitespace (if any) and save it + # First get the leading whitespace (if any) and save it # for later use - WhiteSpace = LeadingWhiteSpaceRegex.search(Line) + WhiteSpace = LeadingWhiteSpaceRegex.search(Line) LeadingWhiteSpace = WhiteSpace.group(1) # Then remove the initial white space from the line to leave - # only the elements. + # only the elements. Line = LeadingWhiteSpaceRegex.sub('', Line) - # Use splitter (again from stackoverflow) to split only + # Use splitter (again from stackoverflow) to split only # on blanks not inside a quoted string. Items = Splitter(Line, Debug) if Debug > 2: - logging.debug (' PrettyPrintElements: Split line\n%s\n', Items) + logging.debug(' PrettyPrintElements: Split line\n%s\n', Items) # End of if Debug > 2: - # The first element of the list is the tag name for this - # element so (if the list exists) pop the first element of - # the list in to variable Tag to keep to match the end tag - # if we need to and write the tag value to XmlPP with only - # the leading whitespace and no indentation. + # The first element of the list is the tag name for this + # element so (if the list exists) pop the first element of + # the list in to variable Tag to keep to match the end tag + # if we need to and write the tag value to XmlPP with only + # the leading whitespace and no indentation. if len(Items) == 0: # Null element, shouldn't occur but it will be warned about # earlier so do nothing here (except if debug is enabled) - # which also keeps python happy about the indentation. + # which also keeps python happy about the indentation. if Debug > 2: - logging.debug (' PrettyPrintElements: Error, blank field in line\n') + logging.debug( + ' PrettyPrintElements: Error, blank field in line\n') # End of if Debug > 2: elif len(Items) == 1: - # There is only one element so just copy it to the output - # with out any additional indentation. + # There is only one element so just copy it to the output + # with out any additional indentation. XmlPP = XmlPP + LeadingWhiteSpace + Items[0] + '\n' else: # This is the first element of a multi element list and - # thus is the opening tag, so copy it to the output - # without further indentation. + # thus is the opening tag, so copy it to the output + # without further indentation. XmlPP = XmlPP + LeadingWhiteSpace + Items[0] + '\n' - # Then remove it from the input. + # Then remove it from the input. Items.pop(0) # Now move to the end of the list to remove the closing - # tag if present. Note this ignores end tags of the form + # tag if present. Note this ignores end tags of the form # and the like, both because I was unsuccessful # matching them and because removing breaks the - # text formating. They seem to be rare enough to ignore + # text formating. They seem to be rare enough to ignore # for now. RegexMatch = EndTagRegex.search(Items[len(Items) - 1]) @@ -238,34 +245,37 @@ def PrettyPrintElements(XmlIn, Errors, Debug): if Debug > 2: - logging.debug (' Last element Endtag\n%s\n', EndTag) + logging.debug(' Last element Endtag\n%s\n', EndTag) # End of if Debug > 2: - # Then remove the end tag from the list element. + # Then remove the end tag from the list element. - Items[len(Items) - 1] = EndTagRegex.sub('', Items[len(Items) - 1]) + Items[len(Items) - 1] = EndTagRegex.sub('', + Items[len(Items) - 1]) else: if Debug > 2: - logging.debug (' PrettyPrintElements: regex no match\n%s\n', Items[len(Items) - 1]) + logging.debug( + ' PrettyPrintElements: regex no match\n%s\n', Items[len(Items) - 1]) # End of if Debug > 2: - + # End of RegexMatch != None: if Debug > 2: - logging.debug (' PrettyPrintElements: Modified last element\n%s\n', Items[len(Items) - 1]) + logging.debug( + ' PrettyPrintElements: Modified last element\n%s\n', Items[len(Items) - 1]) # End of if Debug > 2: for Item in Items: # Then print the elements (with a 2 space indent), - # one to a line. + # one to a line. XmlPP = XmlPP + LeadingWhiteSpace + ' ' + Item + '\n' @@ -291,50 +301,52 @@ def PrettyPrintElements(XmlIn, Errors, Debug): # End of for Line in XmlIn.split('\n'): - logging.info (' Exiting PrettyPrintElements\n') + logging.info(' Exiting PrettyPrintElements\n') return (XmlPP) # End of def PrettyPrintElements(XmlIn, Errors, Debug): + def OutputTree(Doc, Root, FileType, InFile, OutFile, Errors, Warnings, Info, Debug): # Prettyprint the xml and write it to a file or the console (depending on # the debug setting). If OutFile is None rename the InFile to InFile.bak - # and write the new data to InFile. + # and write the new data to InFile. - logging.info (' Entering OutputTree Debug %s\n', Debug) + logging.info(' Entering OutputTree Debug %s\n', Debug) # Do a rough (to the element level) pretty print of the document. - # (this is all we will do for an fpz file). + # (this is all we will do for an fpz file). Root = Indent(Root, Debug) - - # now use an answer from stackoverflow to get the properly formatted - # xml definition xml to a string using BytesIO (as lxml doesn't seem + + # now use an answer from stackoverflow to get the properly formatted + # xml definition xml to a string using BytesIO (as lxml doesn't seem # to be able to write this to a string directly) - + Xml = BytesIO() - - Doc.write(Xml, xml_declaration=True, encoding=Doc.docinfo.encoding, standalone=Doc.docinfo.standalone) - - # again use a couple of stackoverflow answers to get that to a splitable + + Doc.write(Xml, xml_declaration=True, encoding=Doc.docinfo.encoding, + standalone=Doc.docinfo.standalone) + + # again use a couple of stackoverflow answers to get that to a splitable # string - - ByteStr = Xml.getvalue() - + + ByteStr = Xml.getvalue() + # Then convert the bytes stream to a string for processing. - + XmlIn = ByteStr.decode(Doc.docinfo.encoding) - + if FileType == 'SVG' and DetailPP == 'Y': - # If this is an svg file (as opposed to an fpz file) then do a + # If this is an svg file (as opposed to an fpz file) then do a # a finer grained pretty print inside the elements as well. logging.debug(' OutputTree doing element level pretty print\n') - XmlPP = PrettyPrintElements(XmlIn, Errors, Debug) + XmlPP = PrettyPrintElements(XmlIn, Errors, Debug) else: @@ -344,38 +356,38 @@ def OutputTree(Doc, Root, FileType, InFile, OutFile, Errors, Warnings, Info, Deb # End of if FileType == 'SVG': - logging.debug(' OutputTree Start OutFile %s Debug %s\n', OutFile, Debug) if Debug != 0: # We are debugging so print the output to sysout rather than a file - # and do not rename (or change) the input file but do print the - # filename we would have used if sending it to a file. + # and do not rename (or change) the input file but do print the + # filename we would have used if sending it to a file. if OutFile == None: # OutFile None will go to the input filename - print ('Output would go to file:\n\n{0:s}\n\n'.format(InFile)) + print('Output would go to file:\n\n{0:s}\n\n'.format(InFile)) else: - + # otherwise it will go to the OutFile as expected. - print ('Output would go to file:\n\n{0:s}\n\n'.format(OutFile)) + print('Output would go to file:\n\n{0:s}\n\n'.format(OutFile)) # End of if OutFile == None: - print (XmlPP) + print(XmlPP) else: - # Normal operation, if OutFile is None rename the input file to - # filename.bak and write the xml to a new file with the original - # filename. + # Normal operation, if OutFile is None rename the input file to + # filename.bak and write the xml to a new file with the original + # filename. - logging.debug(' OutputTree Normal operation OutFile %s Debug %s\n', OutFile, Debug) + logging.debug( + ' OutputTree Normal operation OutFile %s Debug %s\n', OutFile, Debug) if OutFile == None: @@ -384,11 +396,12 @@ def OutputTree(Doc, Root, FileType, InFile, OutFile, Errors, Warnings, Info, Deb try: - os.rename (InFile, InFile + '.bak') + os.rename(InFile, InFile + '.bak') except os.error as e: - Errors.append('Error 1: Can not rename {0:s} {1:s} ({2:s})\n'.format(str( e.filename), e.strerror, str(e.errno))) + Errors.append('Error 1: Can not rename {0:s} {1:s} ({2:s})\n'.format( + str(e.filename), e.strerror, str(e.errno))) # Couldn't rename the file, can't proceed so set the error # and return. @@ -406,8 +419,8 @@ def OutputTree(Doc, Root, FileType, InFile, OutFile, Errors, Warnings, Info, Deb # End of try: # End of if OutFile == None: - - # now open the output file + + # now open the output file logging.debug(' OutputTree opening OutFile %s\n', OutFile) @@ -419,7 +432,8 @@ def OutputTree(Doc, Root, FileType, InFile, OutFile, Errors, Warnings, Info, Deb logging.debug(' OutputTree open error %s\n', e.strerror) - Errors.append('Error 2: Can not open {0:s} {1:s} ({2:s})\n'.format(str( e.filename), e.strerror, str(e.errno))) + Errors.append('Error 2: Can not open {0:s} {1:s} ({2:s})\n'.format( + str(e.filename), e.strerror, str(e.errno))) else: @@ -435,7 +449,8 @@ def OutputTree(Doc, Root, FileType, InFile, OutFile, Errors, Warnings, Info, Deb logging.debug(' OutputTree write error %s\n', e.strerror) - Errors.append('Error 3: Can not write {0:s} {1:s} ({2:s})\n'.format(str( e.filename), e.strerror, str(e.errno))) + Errors.append('Error 3: Can not write {0:s} {1:s} ({2:s})\n'.format( + str(e.filename), e.strerror, str(e.errno))) else: @@ -449,7 +464,8 @@ def OutputTree(Doc, Root, FileType, InFile, OutFile, Errors, Warnings, Info, Deb logging.debug(' OutputTree close error %s\n', e.strerror) - Errors.append('Error 4: Can not close {0:s} {1:s} ({2:s})\n'.format(str( e.filename), e.strerror, str(e.errno))) + Errors.append('Error 4: Can not close {0:s} {1:s} ({2:s})\n'.format( + str(e.filename), e.strerror, str(e.errno))) # End of try f.close() @@ -459,16 +475,17 @@ def OutputTree(Doc, Root, FileType, InFile, OutFile, Errors, Warnings, Info, Deb # End of if Debug != 0: - logging.info (' Exiting OutputTree\n') + logging.info(' Exiting OutputTree\n') # End of def OutputTree(Doc, Root, FileType, InFile, OutFile, Errors, Warnings, Info, Debug): -def ParseFile (File, Errors): -# Parse the xml document and return either the root of the document or None -# and the error message(s) in Errors. +def ParseFile(File, Errors): + + # Parse the xml document and return either the root of the document or None + # and the error message(s) in Errors. - logging.info (' Entering ParseFile\n') + logging.info(' Entering ParseFile\n') # Set Doc and Root to none in case of error. @@ -476,31 +493,32 @@ def ParseFile (File, Errors): Root = None + parser = etree.XMLParser(remove_blank_text=True) try: - parser = etree.XMLParser(remove_blank_text=True) - Doc = etree.parse(File, parser) except IOError: - Errors.append('Error 5: ParseFile can\'t read file {0:s}\n'.format(str(File))) + Errors.append( + 'Error 5: ParseFile can\'t read file {0:s}\n'.format(str(File))) - logging.info (' Exiting ParseFile on no file error\n') + logging.info(' Exiting ParseFile on no file error\n') return None, Root except etree.XMLSyntaxError: - Errors.append('Error 6: ParseFile error parsing the input xml file {0:s}\n'.format(str(File))) + Errors.append( + 'Error 6: ParseFile error parsing the input xml file {0:s}\n'.format(str(File))) - logging.debug (' Parse error, parser.error_log %s\n', parser.error_log) + logging.debug(' Parse error, parser.error_log %s\n', parser.error_log) if len(parser.error_log): for error in parser.error_log: - # Extract and log the errors the parser is reporting. + # Extract and log the errors the parser is reporting. Errors.append('{0:s}\n'.format(str(error))) @@ -508,7 +526,7 @@ def ParseFile (File, Errors): # End of if len(parser.error_log): - logging.info (' Exiting ParseFile on parser error\n') + logging.info(' Exiting ParseFile on parser error\n') # Then return Doc as None to indicate an error occurred. @@ -517,19 +535,20 @@ def ParseFile (File, Errors): # End of try: # If we got here we have successfully parsed the document so get it's - # root. + # root. Root = Doc.getroot() - logging.info (' Exiting ParseFile with doc parsed\n') + logging.info(' Exiting ParseFile with doc parsed\n') return Doc, Root # End of def ParseFile (File, Errors): + def PrintInfo(Info): - logging.info (' Entering PrintInfo\n') + logging.info(' Entering PrintInfo\n') if len(Info) != 0: @@ -537,19 +556,20 @@ def PrintInfo(Info): # There is Info so print them to the console. - print (Infodata) + print(Infodata) # End of for Infodata in Info: # End of if len(Info) != 0: - logging.info (' Exiting PrintInfo\n') + logging.info(' Exiting PrintInfo\n') # end of def PrintInfo(Info): + def PrintWarnings(Warnings): - logging.info (' Entering PrintWarnings\n') + logging.info(' Entering PrintWarnings\n') if len(Warnings) != 0: @@ -557,19 +577,20 @@ def PrintWarnings(Warnings): # There are warnings so print them to the console. - print (Warning) + print(Warning) # End of for Warning in Warnings: # End of if len(Warnings != 0): - logging.info (' Exiting PrintWarnings\n') + logging.info(' Exiting PrintWarnings\n') # End of def PrintWarnings(Warnings): + def PrintErrors(Errors): - logging.info (' Entering PrintErrors\n') + logging.info(' Entering PrintErrors\n') if len(Errors) != 0: @@ -581,21 +602,22 @@ def PrintErrors(Errors): # There are errors so print them to the console. - print (Error) + print(Error) # End of for Error in Errors: # End of if len(Errors != 0): - logging.info (' Exiting PrintErrors\n') + logging.info(' Exiting PrintErrors\n') # End of def PrintErrors(Errors): -def ProcessArgs (Argv, Errors): - # Process the input arguments on the command line. +def ProcessArgs(Argv, Errors): + + # Process the input arguments on the command line. - logging.info (' Entering ProcessArgs\n') + logging.info(' Entering ProcessArgs\n') # Create an empty InFile list (in case of more than one input file) @@ -605,7 +627,8 @@ def ProcessArgs (Argv, Errors): # No input file so print a usage message and exit. - Errors.append('Usage 7: {0:s} filename (filename ...)\n'.format(str(sys.argv[0]))) + Errors.append( + 'Usage 7: {0:s} filename (filename ...)\n'.format(str(sys.argv[0]))) return(InFile) @@ -619,9 +642,10 @@ def ProcessArgs (Argv, Errors): if not os.path.isfile(File): - # Input file isn't valid, note that, ignore it and proceed. + # Input file isn't valid, note that, ignore it and proceed. - Errors.append('Error 8: {0:s} isn\'t a file: ignored\n'.format(str(File))) + Errors.append( + 'Error 8: {0:s} isn\'t a file: ignored\n'.format(str(File))) else: @@ -633,10 +657,10 @@ def ProcessArgs (Argv, Errors): # End of for File in sys.argv: - logging.debug (' End of ProcessArgs return InFile %s\n', InFile) + logging.debug(' End of ProcessArgs return InFile %s\n', InFile) - logging.info (' Exiting ProcessArgs\n') + logging.info(' Exiting ProcessArgs\n') - return InFile + return InFile # End of def ProcessArgs (Argv, Errors): diff --git a/README b/README deleted file mode 100644 index 2c9e367..0000000 --- a/README +++ /dev/null @@ -1,1683 +0,0 @@ - -Description: - - FritzingCheckPart.py is a python script which checks parts files for -use by the Fritzing EDA program (fritzing.org). It started out to correct -some of the issues that Fritzing has with the output from the Inkscape -(inkscape.org) open source svg editor program. It then grew in to checking the -format of the various file (fzp and svg) that make up a fritzing part. - As a part of that it also prettyprints xml (with varying success), it -does best with postprocessed fritzing svg files, because it understands their -format and has modified the xml (mostly moving CSS style commands in to inline -xml which as a side effect makes prettyprinting easier), to better suit -fritzing. A standalone script PP.py, is included which will prettyprint a -xml document without doing any of the fritzing related conversions. - -Installation: - - The script uses python3 and the lxml library extensions to python. -Since Fritzing runs on Windows, linux and MacOS X the script should run on -those platforms too, and it may. I don't have MacOS X so I don't know that -it will run there (although there is no reason that it shouldn't, I just -haven't done it.) - -On Windows: - - I run the script from cygwin on Windows. It will likely run on one of -the native python implementations (you may need to use pip to install the lxml -extension) but I haven't done so. For cygwin you need to install cygwin -(cygwin.org) using the setup program as detailed on cygwin.org. The basic -install with the following additions does fine: - -python3: Py3K language interpreter -python3-lxml: Python XML2/XSLT bindings - -(and all their associated dependencies) - -with that in place from a cygwin terminal copy the python scripts - -FritzingCheckPart.py -FritzingTools.py -PP.py -PPTools.py - -to /usr/local/bin - -chmod ugo+x /usr/local/bin/*.py - -On Linux (Ubuntu 16.04 LTS): - -copy the py scripts to /usr/local/bin via sudo: - -sudo cp FritzingCheckPart.py /usr/local/bin -sudo cp FritzingTools.py /usr/local/bin -sudo cp PP.py /usr/local/bin -sudo cp PPTools.py /usr/local/bin - -chmod ugo+x /usr/local/bin/*.py - -The Ubuntu install appears to have lxml and python 3 already installed - -Note the script has problems with unicode under python 2.7 and probably won't -run there without modification (which I don't know how to make). - -Testing: - -Assuming you have Fritzing installed the following will check (and complain -about!) the parts in core: - -mkdir tst - -FritzingCheckPart.py fritzing-0.9.3b.linux.AMD64/fritzing-parts/core tst - -(replace the fritzing-0.9.3b.linux.AMD64/fritzing-parts/core with the path - to your fritzing-parts core directory!) - -which should produce output like this (in large volume) on the console: - - -**** Starting to process file 10x2-Epaper-Breakout-Board-v11.fzp - - -Error: File -'/cygdrive/c/fritzing/fritzing.0.9.3b.64.pc/fritzing.0.9.3b.64.pc/fritzing-parts/core/10x2-Epaper-Breakout-Board-v11.fzp' - -Connector0 doesn't exist (connectors should start at 0) - -... - - -Normal use: - -PrettyPrinting: - -PP.py xml_file [another_xml_file ...] - -will pretty print the xml file to xml_file leaving the original file in -xml_file.bak internally it sets the file type to svg so that it will split -blanks in lines such as attribute="value" attribute="value" in to - -attribute="value" -attribute="value" - -with appropriate indenting. Since this is meant for post processed Fritzing -svg file it may or may not do what you want. So try it and see. It won't -split on blanks in text or quoted strings but may screw up on general xml -sometimes, so use it if it is useful. - -FritzingCheckPart.py - -There are several modes (selected internally by the number and type of -the arguments to the script.): - -1) - -dir to dir: - -FritzingCheckPart.py src_dir dst_dir - -This processes all the fritzing files it finds in src_dir and writes their -output in to dst_dir. Dst_dir needs to be empty to avoid damaging existing -files. Subdirectories to match the fritzing file set up will be created in -the dst_dir. If you are processing part.fzp type files the output will go -in to dst_dir at the top level and the svg and subdirectories will remain -empty. In the case of core in the example above the identical directory -format will be recreated under dst_dir. To run this a second time you need -to empty the dst_dir via command like - -rm -R dst_dir/* - -This is mostly used for testing (against core as a source of diverse files, -many with errors) and to allow a mass correction of core if desired. Note -you only want to run this mode against core as the other modes will change -files in core that are under git control and tend to break Fritzing. - -2) - -FritzingCheckPart.py part.filename.fzp - -part.filename.fzp format (from an unzipped .fzpz file which will have files -of the form - -part.filename.fzp -svg.breadboard.filename.svg -svg.icon.filename.svg -svg.schematic.filename.svg -svg.pcb.filename.svg - -The input files will be renamed to filename.bak with the script output, the -fixed up (we hope) xml, written to the original file name ready to be rezipped -and loaded to fritzing. If something goes wrong, the original data is in the -.bak files (so long as you haven't run the script twice). First the fzp file -will be processed to get the connector information and the expected svg files, -then each svg file in turn will be processed. So you need to pay attention to -the file name in the error messages, as it may not be referring to the input -file, but an svg file linked from the input file. - -3) - -FritzingCheckPart.py parts/user/filename.fzp - -the input file is in directory user/filename.fzp (and the user in the path -is required to be present, the script will error out if it is not). The svg -files are in - -user/svg/user/breadboard/filename.svg -user/svg/user/icon/filename.svg -user/svg/user/pcb/filename.svg -user/svg/user/schematic/filename.svg - -which is the standard place where imported parts are stored by fritzing (in -the core exampe at the start of this, the "core" directory is the same as -"user" here). Again the fzp file will be processed followed by the associated -svgs. So again you need to pay attention to the file name in the error -messages, as it may not be referring to the input file, but an svg file -linked from the input file. - -4) - -FritzingCheckPart.py filename.svg - -this form does what checks it can on the svg file (which aren't that many as -it lacks the data from the fzp file to know what connectors it should be -checking for). What it does do is the original purpose of this script which -is to change the style(attribute:value;attirbute:value) commands to the -equivelent inline xml attirbute="value" attribute="value" as parts -of fritzing, (specifically bendable legs) don't support style type attributes -and won't work if they are present. It changes font-size=3.5px to -font-size=3.5 as the trailing px, required by CSS, causes font size errors -in fritzing. It converts silkscreen (in pcb) items from the old standard -white (which Inkscape with a white background won't display succcessfully) to -the new standard of black. It will discover and complain about (but not so -far, do anything about, due to positioning/scaling issues) terminals that -have a zero height or width. These are not selectable by Inkscape making -them difficult to move in the svg. Unfortunatly you need to manually change -the size (which changes the position) and then move the teriminal to the -correct position. It would be nice to automate this, but it isn't done now. -Last but not least, if this is a pcb svg file it moves stroke-width -commands which would be inherited by a lower level group in to that group. -The scripts that produce gerber files are not able to access inherited values -(as they aren't reading the xml) and thus if a stroke-width would be -inherited from a higher level and thus is not present at the level the pad -is generated at gerber production fails. I expect this will be the main use -for this script. After modifiying a svg file with Inkscape you need to run -this script to correct the modifications that Inkscape has made for CSS -compliance before feeding it to Fritzing (which isn't CSS compliant in at -least some cases). - -Configuration: - -There are four internal configuration settings (you need to edit the listed -.py file and change these with a text editor): - -1) in file PPTools.py - -DetailPP = 'y' - -Enabled by default. If detail prettyprinting of an svg appears to have screwed -up, set this value to 'n' to disable detail prettyprinting and try again. If it -works without the detailed prettyprinting please file a bug. - -2) in file FritzingTools.py - -ModifyTerminal = 'n' - -Disabled by default because it will make a change that will change the spacing -of the terminal position in the svg, which you will manually need to correct -using an svg editor, if the width or height is 0. I enable this (by setting the -value to 'y') and then pay attention to the modifed messages to tell when it -has changed a terminal from 0. If the terminal is 0 width or height at least -Inkscape (which I use) will not select the element to move it. You have to -manually select the element and change its position with the tool bar which -I find annoying. With the value set to 'n (the default) you will get a warning -message like this one from a current core part: - -Warning 16: File -'/cygdrive/c/fritzing/fritzing.0.9.3b.64.pc/fritzing-parts/core/../svg/core/schematic/4071_4_x_2_input_OR_gate_multipart_schematic.svg' -At line 66 - -Connector connector6terminal has a zero height -and thus is not selectable in Inkscape - -This warning is all that it will do. It is up to you to edit the svg and set -the height/width to something other than 0 and correct the x/y positioning. - - With the value set to 'y' on the same file (in this case changed to an -exported part so as to not change core which will break parts update, but the -same file as above) there is a different message in a different place: - -Modified 2: File -'svg.schematic.prefix0000_fa1ebd566edf2f3d943a0046711f2d3c_1_schematic.svg' -At line 23 - -Connector connector6terminal had a zero height, set to 10 -Check the alignment of this pin in the svg! - -This message tells you the script has made a change that is going to have moved -the x/y position of the connector (and depending on what the scaling in the svg -is set to, perhaps made the height/width incorrect, as 10 isn't an appropiate -value for all scale factors). The warning message is no longer present as there -is now this change notification instead. As a result you need to edit the svg -and check that the terminal is 10 thou (or your preferred size, 10 thou is -mine) and in the correct x/y position as expected by the part. The upside is -that Inkscape will now select the terminal and move it if you move the entire -terminal which it wouldn't before. - -3) in file FritzingCheckPart.py - -IssueNameDupWarning = 'y' - -This value (enabled by default) if set to 'n' will supress the Warning 28: -message which indictes the name field is not unique. While it should be -unique according to the parts file format document, Fritzing doesn't appear -to care and it seems to be only used for display in pin labels when hovered -over. It is fairly common to not be unique and thus clutters up the error -message display. I usually set this to 'n'. - -4) in file FritzingCheckPart.py - -Debug = 0 - -This value enables debug messages (set to 1 for file output to the console -but no further debug messages, set to 2 for enter/exit routine debug messages, -and to 3 for detailied but very verbose debug messages). It is used for -debugging the script itself so you will normally leave it at 0 for normal -operation. - - - -Likely bugs: - -The most likely bug relates to prettyprinting. To prettyprint svg files the -lines are split on blanks (' ') and each element is indented and printed on -a new line. Obviously (and for text, comments and referenceFile names so far, -detected and corrected for) lines with spaces that are supposed to be there -in the final document will get screwed up by the above and will need their -tags added to the exemption regex in the code. - The original file(s) are saved in a .bak file (i.e. filename.svg will -be moved to filename.svg.bak with the script output in filename.svg). However -if you run the script a second time without copying the .bak file somewhere -safe the original file will be overwritten without further warning, so be -careful. In case of script error you will likely want the original file ... - There also may be any number of other bugs I haven't found yet. If you -come across one please report it and I'll see if I can fix it. - -Known bugs: - -1) Makeing a square pad in pcb via a path with a hole in it usually (but - apparantly not always) works in Fritzing. This script however will toss - -Error 74: File -'/cygdrive/c/fritzing/fritzing.0.9.3b.64.pc/fritzing-parts/core/../svg/core/pcb/DRV8825_breakout_pcb.svg' -At line 17 - -Connector connector136 has no radius no hole will be generated - - Which isn't correct (but also isn't easy to fix). You can either ignore this - error as invalid (as long as the gerber export works which it does in this - case) or replace the pad with a standard circle with a radius and stroke - width (which would be my choice in the matter!) which will remove this error. - - -Potential error messages and what to do about them: - -First the dreaded trace back: - -$ ./FritzingCheckPart.py Bean_revE.fzp -Traceback (most recent call last): - File "./FritzingCheckPart.py", line 51, in - rc, FileType, Path, File = tools.ProcessArgs (sys.argv, Errors) -TypeError: 'int' object is not iterable - -if you get a message like this, then I have screwed up and offended the python -gods and they have taken exception (this is basically a software error). The -best bet is to provide the call above and if possible a copy of the file that -caused it so I can try and fix it. - - - -now on to expected error messages: - -Most (but not all, as the first few below show) error messages are of the -form: - -Error: File -'/cygdrive/c/fritzing/fritzing.0.9.3b.64.pc/fritzing.0.9.3b.64.pc/fritzing-parts/core/blend_micro1.0.fzp' -At line 444 - -which gives you the file name followed by the line number (if known, sometimes -it isn't) of where the error was detectd. - - Of note is the filename will be blend_micro1.0.fzp.bak if you are -processing an individual part (which will normally be the case). The reason -for this is the output file - -blend_micro1.0.fzp - -has been prettyprinted, and the line numbers won't match the input file -(blend_micro1.0.fzp.bak) so you need to look for the error in the filename -listed in the error message and then match it to the same text (which will -have a different line number and possibly format very likely) in the output -file if you need to. The input file will give you the place in the file that -the error occurred and you should fix it there and then remove the .bak -extension and re run the script in the corrected input file. - -Usage messages (which are a type of error as they are fatal, but don't have -numbers any more) - - -Usage: PP.py filename (filename ...) - - Indicates you didn't give a filename to the PP.py script. It wants - one or more xml files such as - - PP.py test.svg - - or - - PP.py test1.svg test2.xml test3.fzp - - -Usage: FritzingTools.py filename.fzp or filename.svg or srcdir dstdir - - Either no or too many arguments to the script. It wants either a - single file name or 2 directories. - - -Usage: FritzingTools.py src_dir dst_dir - -src_dir filename isn\'t a directory - - In this mode both arguments need to be directories and src isn't. - - -Usage: FritzingTools.py src_dir dst_dir - -dst_dir filename isn\'t a directory - - In this mode both arguments need to be directories and dst isn't. - - - -Error messages in the order they occur in the code so essentially random -but numbered so you can index by the number to get the error description -and an explaination of the errror (with the move of the Usage messages -above, some numbers are now missing though.) - - -Error 1: Can not rename filename os_error_message (os_error_number) - - The os routines returned an exception when the input file was - renamed. Hopefully the cause is obvious from the os messages. - - -Error 2: Can not open filename os_error_message (os_error_number) - - The os routines returned an exception when the input file was - opened. Hopefully the cause is obvious from the os messages. - - -Error 3: Can not write filename os_error_message (os_error_number) - - The os routines returned an exception when the input file was - written. Hopefully the cause is obvious from the os messages. - - -Error 4: Can not close filename os_error_message (os_error_number) - - The os routines returned an exception when the input file was - closed. Hopefully the cause is obvious from the os messages. - - -Error 5: ParseFile can't read file filename - - The xml parser got an I/O error trying to parse the named file. - - -Error 6: ParseFile error parsing the input xml file filename - - The xml parser found illegal xml at the line and column listed after - this. Note the lxml parser is more strict than either Inkscape or - Fritzing and will report errors that both Inkscape and Fritzing - will accept as valid xml. If you look however, there really is an - error there and you should correct it. Below is an example from the - Bean_revE.fzp file currently in core: - - /cygdrive/c/fritzing/fritzing.0.9.3b.64.pc/fritzing.0.9.3b.64.pc/fritzing-parts/core/Bean_revE.fzp:161:90:FATAL:PARSER:ERR_SPACE_REQUIRED: attributes construct error - - line 161 from Bean_revE.fzp - -

- - there are two errors in this line. There is a missing space between - connector81terminal' and hybrid='yes' and the second hybrid='yes is - wrong. The line should be corrected to this: - -

- - which is correct xml and the complaints from parser will stop. You - will get a lot more errors, but again they are really there, even - though the part with these errors loads and runs happily in Fritzing. - - -Error 8: filename isn't a file: ignored - - The file name provided either isn't a file or isn't readable and has - been ignored. - - -Error 10: There must be a directory that is not '.' or '..' in the input name -for a fzp file in order to find the svg files. - - Indicates that it needs a directory (for example core/file.fzp) in - order to figure out where the svg files are (../svg/core/... in this - case). Supply the directory and it will be happy. - - -Error 13: dst dir - -dst_dir - -must be empty and it is not - - The dst_dir isn't empty (perhaps from a previous run). If you are sure - the directory is expendable rm -R dst_dir/* will fix this. - - -Error 14: Creating dir - -dir_name os_error_message (os_error_number) - - A problem creating one of the dst directories. Hopefully the os error - messages will make the cause clear. - - -Error 15: Can not rename - -'src_file' - -to - -'src_file.bak' - -'file_name_from_os' - -os_error_message (os_error_number) - - A problem occurred trying to rename the src_file to src_file.bak. - Hopefully the os error messages indicate why. - - -Error 16: File -'filename' -At line 20 - -Id xxx present more than once (and should be unique) - - The listed id is present more than once and should be unique (often - Fritzing ignores this but it is incorrect) - - -Error 17: File -'filename' - -No connectors found for view viewname. - - This is one of those messages without a line number as after all the - connectors have been processed, no connectors were found. - - -Error 18: File -'filename' - -Connector connector2terminal is in the fzp file but not the svg file. (typo?) - - This connector is specified in the fzp file, but isn't in the - associated svg file. Depending on what type of connector it is - this may or may not be fatal (a svgId is fatal a terminalId is not). - In either case it is incorrect. - - -Error 19: File -'filename' - -File type xxx is an unknown format (software error) - - - Another case of software error where the type isn't svg, fzppart or - fzpfritz. Shouldn't happen. - - -Error 20: File -'filename.svg' - -During processing svgs from fzp, svg file doesn't exist - - The filename referenced for this view in the fzp file doesn't exist. - Fritzing will try and find something to substitute, but this is still - an error. - - -Error 21: Svg file - -'Filename.svg' - -Has a different case in the file system than in the fpz file - -'filename.svg' - - This doesn't matter on Windows as the file system is case insensitive - however it does matter on Linux and probably MacOS where the file - system is case sensitive and the wrong case file will not be found. - Change either the fzp or the file in the file system to the same - case and all will be well on all systems. While I could correct this - in the fzp file it seems better to do it manually because it isn't - clear whether the fzp file is incorrect or this particular file system - is incorrect, and thus is better left to a human decision rather than - a program. - - -Error 22: File -'filename.fzp' -At line 1 - -No ModuleId found in fzp file - - There isn't a moduleId in the fzp file. This is likely fatal as I don't - think the part can load without a moduleId. Add a moduleId to the file - (preferably export a new part to get a Fritzing approved moduleId). - - -Error 23: File -'filename.fzp' -At line 20 - -A bus is already defined, schematic parts won't work with busses - - A non empty Bus definition has already been seen. Fritzing won't - currently support both busess and schematic parts. - - -Error 24: File -'filename' -At line 20 - -More than one copy of Tag sometag - - Tag sometag should only occur once in the fzp file and we have seen - another copy of it here. - - -Error 25: File -'filename.fzp' -At line 2 - -Multiple ModuleIds found in fzp file - - There is more than one moduleId set in the fzp file (there should only - be one) - - -Error 26: File -'filename.fzp' -At line 20 - -State error, expected tag tag not a view name - - There is something wrong in the fzp file (or this code). The tag we - have doesn't match the expected state of a correct fzp file. Best bet - is to check the format of the fzp file against a known good version, - as there is probably an extra or missing line in this file. - - -Error 27: File -'filename.fzp' -At line 20 - -View name missing - - We have no viewname (iconView breadboardView schematicView pcbView) - which should be present. - - -Error 28: File -'filename.fzp' -At line 20 - -Multiple view tags schematicView present, ignored - - There is more than one view of this name defined in the file when there - should only be one of each. - - -Error 29: File -'filename.fzp' -At line 20 - -View tag scchematicView not recognized (typo?) - - View tag isn't one of (iconView breadboardView schematicView pcbView) - which it should be. - - -Error 30: File -'filename.fzp' -At line 20 - -No image name present - - The file name for the svg file is missing in the fzp file. - - -Error 31: File -'filename.fzp' -At line 20 - -Multiple viewname image files present - - There is more than one image file name present, there should only be - one. - - -Error 32: File -'filename.fzp' -At line 20 - -No layerId value present - - There is a layerId attribute present, but it has no value (and it needs - one). - - -Error 33: File -'filename.fzp' -At line 20 - -View viewname already has layerId layername, layername1 ignored - - The layerId isn't unique and it must be. - - -Error 34: File -'filename.fzp' - -No views found. - - There are no views found in the fzp file. There isn't a line number - because this occurs after we have seen all the lines that may contain - a view. - - -Error 35: File -'filename.fzp' - -Unknown view viewname found. (Typo?) - - Found a view name that isn't one of iconView breadboardView - schematicView or pcbView (probably a typo) - - -Error 36: File -'filename.fzp' - -No valid views found. - - Didn't find any of iconView breadboardView schematicView or pcbView - in the list of view names. - - -Error 37: File -'filename.fzp' - -This is a smd part as only the copper0 view is present but it is on the -bottom layer, not the top. If you wanted a smd part change copper0 to -copper 1 at line 20 If you wanted a through hole part add the copper1 -definition after line 19 - - This is a smd part but it is on the wrong layer (and thus likely an - error). If you really want the part to be on the bottom for something - this error can be ignored. - - -Error 38: File -'filename.fzp' -At line 20 - -State error, tag stack is at level 8 and should only go to level 7 - - This error indicates that there are too many lines in the fzp file - as the tags have gotten deeper than is possible for a valid file. - - -Error 39: File -'filename.fzp' -At line 20 - -Connector has no id - - A connector has no id associated with it and it must have one. - - -Error 40: File -'filename.fzp' -At line 20 - -Connector has no Name - - A connector has no Name associated with it and it must have one. - - -Error 41: File -'filename.fzp' -At line 20 - -Connector connector3 has no Type - - A connector has to have type male or female and has neither. - - -Error 42: File -'filename.fzp' -At line 20 - -Connector connector3 has no description - - A connector doesn't have a description. When you hover on a pad in - breadboard or schematic you won't get a description. - - -Error 43: File -'filename.fzp' -At line 20 - -Connector connector3 missing view name - - The connector doesn't have a view name. - - -Error 44: File -'filename.fzp' -At line 20 - -Viewname bbreadboardView invalid (typo?) - - The viewname isn't one of breadboardView schematicView pcbView and - it should be. - - -Error 45: File -'filename.fzp' -At line 20 - -Layer missing - - The layer attribute is missing in the fzp file. - - -Error 46: File -'filename.fzp' -At line 20 - -No layerId for View SchematicView - - A layerId wasn't specified for this view earlier in the fzp file. - - -Error 47: File -'filename.fzp' -At line 20 - -LayerId here doesn't match View schematicView layerId schematic - - A layerId here doesn't match the layerId specified earlier for this - view (or views in the case of pcb view which can have multiple - layerids.) - - -Error 48: File -'filename.fzp' -At line 20 - -Connector connector4 layer copper0 already defined, must be unique - - This connectorid layer combination is already defined and must be - unique. - - -Error 49: File -'filename.fzp' -At line 20 - -hybrid is present but isn't 'yes' but yyes (typo?) - - The hybrid flag is present but with an invalid value (it must be yes). - - -Error 50: File -'filename.fzp' -At line 20 - -Tag svgId is present but has no value - - The listed tag is present but has no value set. - - -Error 51: File -'filename.fzp' -At line 20 - -svgId missing - - There is no svgId present for this connector and one is required. - - -Error 52: File -'filename.fzp' -At line 20 - -Bus bus2 already defined - - There is aready a bus with this id and ids must be unique. - - -Error 53: File -'filename.fzp' -At line 20 - -Bus nodeMember connector2 does't exist - - The nodeMember specified doesn't exist and it must. - - -Error 54: File -'filename.fzp' -At line 20 - -Bus nodeMember connector2 already in bus bus3 - - The nodeMember specified is already in the specified bus and can't - be in two at once. - - -Error 55: File -'filename.fzp' -At line 20 - -Subpart has no id - - The subpart is missing the id field (required) - - -Error 56: File -'filename.fzp' -At line 20 - -Subpart id subpartid already exists (must be unique) - - The subpart is already in use for another subpart and must be unique. - - -Error 57: File -'filename.fzp' -At line 20 - -Subpart has no label - - The subpart has not label and it needs one. - - -Error 58: File -'filename.fzp' -At line 20 - -Subpart subpartid already defined (duplicate?) - - The subpart has already been defined and must be unique. - - -Error 59: File -'filename.fzp' -At line 20 - -Connector id missing, ignored - - The subpart definition is missing the id field. - - -Error 60: File -'filename.fzp' -At line 20 - -Connector connector2 doesn't exist (and it must) - - The connector id isn't already defined in the fzp file and it must be. - - -Error 61: File -'filename.fzp' -At line 20 - -Subpart connector connector0 already in subpart sub1 - - The connector id is already part of another subpart and can only be - in one subpart. - - -Error 62: File -'filename.fzp' - -No connectors found to check - - There are no connectors defined when we tried to check that the - connectors are in the correct sequence. - - -Error 63: File -'filename.fzp' - -Connector0 doesn't exist (connectors should start at 0) - - There isn't a connector0 and there should be. - - -Error 64: File -'filename.fzp' - -Connector connector5 doesn't exist when it must to stay in sequence - - Connectors 0 to 4 exist, then it skips to something above 5. This - causes label problems (as fritzing assumes the labels are in sequence - and will misnumber the missing and following connections). - - -Error 65: File -'filename.fzp' -At line 20 - -Connector connector1pad is an ellipse not a circle, (gerber generation will -break.) - - This indicates a connector in a pcb svg is an ellipse (i.e. has rx and - ry rather than r as a radius in the xml). This is usually because of - a removed translate that has changed horizontal or vertical scale. The - easiest fix is to copy one radius value to the other in xml editor - (making sure the new radius value still keeps the intended hole size). - - -Error 66: File -'filename.fzp' -At line 20 - -Connector connector2pin is a duplicate (and should be unique) - - The listed connector has already been seen in the svg file and should - be unique. As long as the two are defined identically fritzing seems - to ignore this, but it should be corrected. - - -Error 67: File -'filename.fzp' -At line 2 - -First Tag tag isn\'t an svg definition - - The first tag in an svg file should be svg. If it isn't there will - probably be a problem. Compare your file against a known correct one - is probably the best bet here. - - -Error 68: File -'filename.fzp' -At line 20 - -Found first group but without a svg definition - - Similar to the error above, we have found a group but haven't seen a - svg id yet. - - -Error 69: File -'filename.fzp' -At line 20 - -Found a drawing element before a layerId (or no layerId) - - A drawing element (perhaps a connector) has been found before the - layerId. If it is a visible part of the drawing, it likely won't be - present if the drawing is exported as a svg, so it is better to have - the layerId first. This also may mean that the layerId is missing - entirely in which case one should be added befoe any drawing elements. - - -Error 70: File -'filename.fzp' -At line 20 - -More than one silkscreen/copper0/copper1 layer - - We have already seen a layer of this name in this svg, a second one is - an error. - - -Error 71: File -'filename.fzp' -At line 20 - -Silkscreen layer should be at the top, not under group copper1 - - As it says the silkscreen layer should be at the top not under any - other group. - - -Error 72: File -'filename.fzp' -At line 20 - -copper0 should be under copper1 not the same level - - As it says copper0 should be under copper1 not at the same level. - - -Error 73: File -'filename.fzp' -At line 20 - -Too many layers, there should only be copper1 then copper0 - - There is a layer under copper1/copper0 which there shouldn't be. - - -Error 74: File -'filename.fzp' -At line 20 - -Connector connector1pad has no radius no hole will be generated - - This has been determined to be a through hole part (as no hole is - normal for a smd part) but there is no radius for the pad and thus - no hole will be generated which is usually an error. - - -Error 75: File -'filename.fzp' - -This is a smd part as only the copper0 view is present -but it is on the bottom layer, not the top. - - Smd parts should normally be on the top side of the board so this is - most likely an error. - - -Error 76: File -'filename.fzp' -At line 20 - -Copper0 and copper1 have non identical transforms (no transforms is best) - - - There is a transform in one or the other of the copper layers but not - the other. What this breaks is moving a component from the top of the - pcb to the bottom in inspector. The order of the transforms changes as - does the scaling making the part wrong on the pcb. Ungrouping and then - regrouping copper1/copper0 will usually fix this (the ungroup removes - the transform). - - -Error 77: File -'filename.fzp' -At line 20 - -terminalId can't be a path as it won't work. - - The terminalId can't be of the specified type (currently path, but - there may be others that will get added). Unless it has a center such - as a rectangle, line, or polygon fritzing won't take it as a terminalId - and will default to the center of the svgId which likely isn't what you - want. I prefer to use a rectangle of .01in by .01in for terminalID. - -Error 78: Svg File -'filename.svg' - -While looking for connector1pin, Subpart subpart2 has no connectors in the svg - - This subpart doesn't have any connectors defined in it and it should. - -Error 79: Svg File -'filename.svg' - -Subpart subpart2 is missing connector connector1pin in the svg - - The listed pin is missing in the svg file (it may be defined in another - subpart, in which case it will have a warning message there). - -Error 80: File -'filename.fzp' -At line 20 - -Both terminalId and legId present, only one or the other is allowed. - - As the message says, there are two terminal definitions and it must - be only one or the other. - -Error 81: File -'filename.fzp' -At line 20 - -Subpart connector subpart1 has no pins defined - - This subpart has no pins defined and it usually needs at least one - (there may be cases where this can be ignored though ...) - -Error 82: File -'filename.svg' -At line 20 - -connector connector1pin isn't in a subpart - - This connector isn't part of a subpart groupname and it should be. - -Error 83: File -'filename.svg' -At line 20 - -Connector connector1pin shouldn't be in subpart subpart2 as it is - - The fzp file says this connector should be in another subpart, not - this one (at the time this error is issued we don't know what the - other subpart is which is why it isn't listed). - -Error 84: File -'filename.svg' -At line 20 - -Connector connector1pin in incorrect subpart subpart2 - - This will usually accompany Error 83 above indicating that the - connector is in a subpart where it isn't defined in the fzp file. - Again, because at this point we don't know where the connector should - be, we can't list the subpart it should be in. - -Error 85: File -'filename.svg' -At line 20 - -subpart label subpart2 is already defined - - There is already a subpart with this label in the svg. I'm not sure - this error can actually occur. Inkscape won't allow you to set it (but - a text edit would), but it may not get through the xml parser as valid - xml if you did (but I haven't tested that so far). - -Error 86: File -'filename.svg' -At line 20 - -Subpart subpart1 isn\'t at the top level when it must be -Following subpart errors may be invalid until this is fixed - - While this may be legal in Fritzing, due to the complexity of checking - subparts this script only supports subparts of the form: - - pair). This may or may not interfere with creating - schematic-subparts, and isn't really needed unless you want to add - a bus. As a result it could be removed to reduce clutter and size. - - -Warning 16: File -'filename.fzp' -At line 20 - -Connector connector1pin has a zero height or width -and thus is not selectable in Inkscape - - While connectors with 0 height or width work just fine, at least in - Inkscape they are not selectable by dragging a box around them and - clicking on them. Thus you can't easily move them (you need to change - their coordinates in the tool bar after selecting them in xml editor). - I prefer to use .01in by .01in rectangles for terminals because they - will select and move when selected with a dragged square in the gui. - Unfortunatly changing the height and width also changes the x/y - position, so automatically correcting this will be more complex than - just adding a value, so it is left for you to do at the moment. - -Warning 17: File -'filename.fzp' -At line 20 - -More than one svg tag found - - This may be perfectly valid (such as multiple name spaces for some - reason), but it is unusual enough to note in case it isn't intended. - - -Warning 18: File -'filename.fzp' -At line 20 - -Height attribute missing - - This should probably be an error as I don't think it will work, but - there is no height attribute in the viewbox definition. - - -Warning 19: File -'filename.fzp' -At line 20 - -Height 200px is defined in px -in or mm is a better option (px can cause scaling problems!) - - While this is perfectly legal, it is unwise (but common!). If defined - in px (and either no units or an explicit px is in px) fritzing will - make a guess (and sometimes get it wrong) about how many px per inch - the drawing used. Older Inkscapes (0.91 and older) used 90px per inch - as of 0.92 they use the CSS standard of 96px per inch. Older copies - of Illustrator used 72px per inch. If you change this to being inches - or millimeters there is no guess required and it will scale correctly. - To do so in Inkscape do a edit select all and set the tool bar to in - or mm. Take the height and width (inches or mm) from the tool bar read - out and use xml editor to set those numbers in to the height and width - in the viewbox setting (with the in at the end to indicate this is in - inches). When you set them Inkscape will change the drawing to match - the new scale (note it is possible some part of the drawing may not - change correctly so visually check it). This is usually the cause of - a drawing that looks correct in Inkscape but is the wrong scale (i.e. - doesn't match the grid) in fritzing. To correct that, in Inkscape - you can recalculate the scaling like this: - - heightpx * 72/90/96 = size in inches. - - You will need to try the likely values 72, 90 or 96 til the scaling - in Fritzing is correct and then set the correct value in inches (or - mm if you prefer) as the height and width in the first entry in xml - editor. -Warning 20: File -'filename.fzp' -At line 20 - -copper1 layer should be at the top, not under group copper0 - - If the second group is copper0 this is normal (or at least harmless) - as the order doesn't really matter. However for smd parts the single - copper layer needs to be copper1 so it is preferable to be copper1 - followed by copper0. - - -Warning 21: File -'filename.fzp' -At line 20 - -This appears to be a pcb svg but has no copper or silkscreen layers! - - As the message says there is no image data here at all which is likely - an error (as the layer is defined in the fzp file). - - -Warning 22: File -'filename.fzp' -At line 20 - -Already have a layerId - - There is a second (or more) layerId in a view that only allows one - layer id. Likely an error. - - -Warning 23: File -'filename.fzp' -At line 20 - -Key key_value -value '-inkscape-font-specification 'Droid Sans, Normal' is invalid and has -been deleted - - This is the typical value that I have seen. The lxml parser appears to - object to the leading - in the value. This warning is here in case at - some point something less ignorable than this gets found here. - -Warning 24: File -'filename.fzp' -At line 20 - -Font family 'ArialMT' is not Droid Sans or OCRA -This likely won't render in Fritzing - - Fritzing only supports fonts Droid Sans or OCRA so this likely won't - be rendered in Fritzging. If you really need this particular font you - need to convert it to a path in your svg editor (but that is a pain to - anyone trying to modify your part and thus undesirable). - -Warning 25: File -'filename.fzp' -At line 20 - -Silkscreen layer should be above the copper layers for easier selection in -pcb view - - If silkscreen is below the copper layers then part selection will - favor the silkscreen layer making part selection more difficult. - Moving the silkscreen layer before the copper layers will fix this. - -Warning 26: File -'filename.fzp' -At line 20 - -Apparant nested tspan which fritzing doesn't support -If your text doesn't appear in Fritzing this is probably why - - As noted nested tspan don't work in Fritzing at least sometimes, in - fact tspan is not supposed to work but usually does. - -Warning 27: File -'filename.fzp' -At line 20 - -Fritzing layerId silkscreen isn't a group which it usually should be - - This is a warning because (at least for silkscreen, don't know about - the others) Fritzing will accept a path as the silkscreen (although - it can only have one element and a group would be a better bet). - -Warning 28: File -'filename.fzp' -At line 20 - -name gnd present more than once (and should be unique) - - This id is duplicated in another name or description field. It is a - warning in this case because dups here (unlike connectors) are not - typically fatal. The part file format document does say they should - be unique though. - -Modified: - - These messages document the changes made by the script to the input - files. Note the line numbers refer to the input file (which will be - usually in the filename.svg.bak file) as the output file has been - prettyprinted which changes the line numbers. As a result you need - to look at the input file at the line of the change and then search for - that text in the output file to find the area of the change. - -Warning 29: File -'filename.fzp' -At line 20 - -File test.svg -has already been processed -but will be processed again as part of this fzp file in case of new warnings. - - This svg file is likely shared by several parts. One downside of this - is that the original of this file won't be in the .bak file as that - will be replaced by the version from the last processing output. It - is processed again in case there are errors relative to this fzp file - that are different than the first processing instance. Because - sometimes iconView is copied from breadboard (which would trip this - warning) and because we don't actually check anything in icon view - icon view processing from the fzp is skipped. - -Modified 1: File -'filename.fzp' -At line 20 - -Removed px from font-size leaving 3.5 - - Removed the px from font-size="3.5x" because Fritzing objects to the px - on the font-size and sets the font-size to 0 when the part is edited. - -Modified 2: File -'filename.fzp' -At line 20 - -Connector connector0terminal had a zero width (or height), set to 10 -Check the alignment of this pin in the svg - - As it says, a 0 length height or width was set to 10 which may causee - the location of the terminal to change. You need to verify (and move - if necessary) the location of this terminal in the svg. You may also - need to adjust the size of the terminal to be 10 thou as the size of - 10 may not be correct depending on scaling and translates. - -Modified 3: File -'filename.fzp' -At line 20 - -Silkscreen, converted stoke/fill from white or not black to black - - Notification that we have changed the color of the silkscreen layer - in the svg from white (or not black) to black for both stroke and fill. - -Modified 4: File -'filename.fzp' -At line 20 - -ReferenceFile - -'filename.svg' - -doesn\'t match input file - -'filename1.svg' - -Corrected - - Notification that the reference file was updated to be the same as the - file name of this svg file. Nothing much appears to care whether this - field is correct or not. - -Modified 5: File -'filename.fzp' -At line 20 - -Converted style to inline xml - - A style command such as - - style="fill:none;stroke:#787878;stroke-width:9.72220039 - - has been converted to the equivelent xml: - - fill="none" stroke="#787878" stroke-width="9.72220039" - - (which prettyprinting will then break down to one element per properly - indented line changing the output line numbers substantially) because - fritzing (specifically bendable legs) does not support the style - command syntax even though it is legal xml and Inkscape will convert - the inline xml to a style command to be CSS complient. diff --git a/README.md b/README.md new file mode 100644 index 0000000..77becca --- /dev/null +++ b/README.md @@ -0,0 +1,1689 @@ + +## Description + +FritzingCheckPart.py is a python script that checks parts files for use by +the Fritzing EDA program (fritzing.org). It started to correct some of the +issues that Fritzing has with the output from the Inkscape (inkscape.org) +open-source SVG editor program. It then grew into checking the format of +the various file (FZP and SVG) that make up a fritzing part. As a part of +that, it also prettyprints XML (with varying success). It does best with +post-processed fritzing SVG files because it understands their format and +has modified the XML (mostly moving CSS style commands into inline XML, +which as a side effect makes prettyprinting easier) to better suit +fritzing. A standalone script, PP.py, is included, which will pretty-print +an XML document without any fritzing-related conversions. + +## Installation + +The script uses python3 and the lxml library extensions to python. Since +Fritzing runs on Windows, Linux, and macOS, the script should run on those +platforms too, and it may. I don't have macOS, so I don't know that it +will run there (although there is no reason it shouldn't, I just haven't +done it.) + +### Windows with cygwin + +I run the script from cygwin on Windows. It will likely run on one of +the native python implementations (you may need to use pip to install the lxml +extension) but I haven't done so. For cygwin you need to install [cygwin](cygwin.org) . +Use the setup program as detailed on cygwin.org. The basic install with the following +additions does fine: + +python3: Py3K language interpreter +python3-lxml: Python XML2/XSLT bindings + +(and all their associated dependencies) + +with that in place from a cygwin terminal copy the python scripts + +``` +FritzingCheckPart.py +FritzingTools.py +PP.py +PPTools.py +``` + +to `/usr/local/bin` + +`chmod ugo+x /usr/local/bin/*.py` + +### Linux + +Tested on Ubuntu 18.04 LTS +Python3 is required + +``` +git clone git@github.com:vanepp/FritzingCheckPart.git +#alternative +# git clone git@github.com:KjellMorgenstern/FritzingCheckPart.git +pip install --user lxml +``` + + +## Testing + +Assuming you have Fritzing installed the following will check (and complain +about!) the parts in core: + +``` +mkdir tst +FritzingCheckPart.py fritzing-0.9.3b.linux.AMD64/fritzing-parts/core tst +``` + +(replace the fritzing-0.9.3b.linux.AMD64/fritzing-parts/core with the path + to your fritzing-parts core directory!) + +which should produce output like this (in large volume) on the console: + +``` +**** Starting to process file 10x2-Epaper-Breakout-Board-v11.fzp + + +Error: File +'/cygdrive/c/fritzing/fritzing.0.9.3b.64.pc/fritzing.0.9.3b.64.pc/fritzing-parts/core/10x2-Epaper-Breakout-Board-v11.fzp' + +Connector0 doesn't exist (connectors should start at 0) + +... +``` + +## Normal use + +### PrettyPrinting + +`PP.py xml_file [another_xml_file ...]` + +will pretty-print the XML file to xml_file leaving the original file in +xml_file.bak internally it sets the file type to SVG so that it will split +blanks into lines such as attribute="value" attribute="value" into +``` +attribute="value" +attribute="value" +``` +with appropriate indenting. Since this is meant for post-processed Fritzing +SVG files, it may or may not do what you want. So try it and see. It won't +split on blanks in text or quoted strings but may screw up on general XML +sometimes, so use it if it is useful. + +### FritzingCheckPart.py + +There are several modes (selected internally by the number and type of +the arguments to the script.): + +#### Mode 1 + +dir to dir: + +`FritzingCheckPart.py src_dir dst_dir` + +This processes all the fritzing files it finds in src_dir and writes their +output in to dst_dir. Dst_dir needs to be empty to avoid damaging existing +files. Subdirectories to match the fritzing file set up will be created in +the dst_dir. If you are processing part.fzp type files the output will go +in to dst_dir at the top level and the svg and subdirectories will remain +empty. In the case of core in the example above the identical directory +format will be recreated under dst_dir. To run this a second time you need +to empty the dst_dir via command like + +`rm -R dst_dir/*` + +This is mostly used for testing (against core as a source of diverse files, +many with errors) and to allow a mass correction of core if desired. Note +you only want to run this mode against core as the other modes will change +files in core that are under git control and tend to break Fritzing. + +#### Mode 2 + +`FritzingCheckPart.py part.filename.fzp` + +part.filename.fzp format (from an unzipped .fzpz file which will have files +of the form + +``` +part.filename.fzp +svg.breadboard.filename.svg +svg.icon.filename.svg +svg.schematic.filename.svg +svg.pcb.filename.svg +``` + +The input files will be renamed to filename.bak with the script output, the +fixed up (we hope) xml, written to the original file name ready to be rezipped +and loaded to fritzing. If something goes wrong, the original data is in the +.bak files (so long as you haven't run the script twice). First the fzp file +will be processed to get the connector information and the expected svg files, +then each svg file in turn will be processed. So you need to pay attention to +the file name in the error messages, as it may not be referring to the input +file, but an svg file linked from the input file. + +#### Mode 3 + +`FritzingCheckPart.py parts/user/filename.fzp` + +the input file is in directory user/filename.fzp (and the user in the path +is required to be present, the script will error out if it is not). The svg +files are in + +``` +user/svg/user/breadboard/filename.svg +user/svg/user/icon/filename.svg +user/svg/user/pcb/filename.svg +user/svg/user/schematic/filename.svg +``` + +which is the standard place where imported parts are stored by fritzing (in +the core exampe at the start of this, the "core" directory is the same as +"user" here). Again the fzp file will be processed followed by the associated +svgs. So again you need to pay attention to the file name in the error +messages, as it may not be referring to the input file, but an svg file +linked from the input file. + +#### Mode 4 + +`FritzingCheckPart.py filename.svg` + + +this form does what checks it can on the SVG file (which aren't that many as +it lacks the data from the fzp file to know what connectors it should be +checking for). What it does do is the original purpose of this script which +is to change the style(attribute:value;attribute:value) commands to the +equivalent inline xml attribute="value" attribute="value" as parts +of fritzing, (specifically bendable legs) don't support style type attributes +and won't work if they are present. It changes font-size=3.5px to +font-size=3.5 as the trailing px, required by CSS, causes font size errors +in fritzing. It converts silkscreen (in PCB) items from the old standard +white (which Inkscape with a white background won't display successfully) to +the new standard of black. It will discover and complain about (but not so +far, do anything about, due to positioning/scaling issues) terminals with +zero height or width. These are not selectable by Inkscape making them +difficult to move in the SVG. Unfortunately, you need to manually change +the size (which changes the position) and then move the terminal to the +correct position. It would be nice to automate this, but it isn't done now. +Last but not least, if this is a PCB SVG file, it moves stroke-width +commands which would be inherited by a lower level group in to that group. +The scripts that produce gerber files are not able to access inherited values +(as they aren't reading the XML) and thus if a stroke-width would be +inherited from a higher level and thus is not present at the level the pad +is generated at gerber production fails. I expect this will be the main use +for this script. After modifying an SVG file with Inkscape, you need to run +this script to correct the modifications that Inkscape has made for CSS +compliance before feeding it to Fritzing (which isn't CSS compliant in at +least some cases). + +### Configuration + +There are four internal configuration settings (you need to edit the listed +.py file and change these with a text editor): + +#### Setting 1 +in file PPTools.py + +DetailPP = 'y' + +Enabled by default. If detail prettyprinting of an svg appears to have screwed +up, set this value to 'n' to disable detail prettyprinting and try again. If it +works without the detailed prettyprinting please file a bug. + +#### Settting 2 +in file FritzingTools.py + +ModifyTerminal = 'n' + +Disabled by default because it will make a change that will change the spacing +of the terminal position in the SVG, which you will manually need to correct +using an SVG editor if the width or height is 0. I enable this (by setting the +value to 'y') and then pay attention to the modified messages to tell when it +has changed a terminal from 0. If the terminal is 0 width or height, at least +Inkscape (which I use) will not select the element to move it. You have to +manually select the element and change its position with the toolbar which +I find it annoying. With the value set to 'n (the default), you will get a warning +message like this one from a current core part: + +Warning 16: File +'/cygdrive/c/fritzing/fritzing.0.9.3b.64.pc/fritzing-parts/core/../svg/core/schematic/4071_4_x_2_input_OR_gate_multipart_schematic.svg' +At line 66 + +Connector connector6terminal has a zero height +and thus is not selectable in Inkscape + +This warning is all that it will do. It is up to you to edit the svg and set +the height/width to something other than 0 and correct the x/y positioning. + + With the value set to 'y' on the same file (in this case changed to an +exported part so as to not change core which will break parts update, but the +same file as above) there is a different message in a different place: + +### Modified 2: File +'svg.schematic.prefix0000_fa1ebd566edf2f3d943a0046711f2d3c_1_schematic.svg' +At line 23 + +Connector connector6terminal had a zero height, set to 10 +Check the alignment of this pin in the svg! + +This message tells you the script has moved the x/y position of the connector. +Depending on the scale, height or width could become incorrect, as ten isn't +appropriate for all scale factors. The warning message is no longer present as +there is now this change notification instead. As a result, you need to edit +the SVG and check that the terminal is 10 thou (or your preferred size, 10 thou +is mine) and in the correct x/y position as expected by the part. The upside +is that Inkscape will now select the terminal and move it if you move the +entire terminal, which it wouldn't before. + +#### Setting 3 +in file FritzingCheckPart.py + +IssueNameDupWarning = 'y' + +This value (enabled by default) if set to 'n' will suppress the Warning 28: +a message which indicates the name field is not unique. While it should be +unique according to the parts file format document, Fritzing doesn't appear +to care, and it seems to be only used for display in pin labels when hovered +over. It is fairly common to not be unique and thus clutters up the error +message display. I usually set this to 'n'. + +#### Setting 4 +in file FritzingCheckPart.py + +Debug = 0 + +This value enables debugging messages (set to 1 for file output to the console +but no further debug messages, set to 2 for enter/exit routine debug messages, +and to 3 for detailed but very verbose debug messages). It is used for +debugging the script itself so you will leave it at 0 for normal +operation. + +## Development + +### Likely bugs: + +The most likely bug relates to prettyprinting. To prettyprint svg files the +lines are split on blanks (' ') and each element is indented and printed on +a new line. Obviously (and for text, comments and referenceFile names so far, +detected and corrected for) lines with spaces that are supposed to be there +in the final document will get screwed up by the above and will need their +tags added to the exemption regex in the code. + The original file(s) are saved in a .bak file (i.e. filename.svg will +be moved to filename.svg.bak with the script output in filename.svg). However +if you run the script a second time without copying the .bak file somewhere +safe the original file will be overwritten without further warning, so be +careful. In case of script error you will likely want the original file ... + There also may be any number of other bugs I haven't found yet. If you +come across one please report it and I'll see if I can fix it. + +### Known bugs: + +#### Bug 1 +Making a square pad in pcb via a path with a hole in it usually (but + apparently not always) works in Fritzing. This script however will toss + +### Error 74: File +'/cygdrive/c/fritzing/fritzing.0.9.3b.64.pc/fritzing-parts/core/../svg/core/pcb/DRV8825_breakout_pcb.svg' +At line 17 + +Connector connector136 has no radius no hole will be generated + + Which isn't correct (but also isn't easy to fix). You can either ignore this + error as invalid (as long as the gerber export works which it does in this + case) or replace the pad with a standard circle with a radius and stroke + width (which would be my choice in the matter!) which will remove this error. + + +Potential error messages and what to do about them: + +First the dreaded trace back: + +$ ./FritzingCheckPart.py Bean_revE.fzp +Traceback (most recent call last): + File "./FritzingCheckPart.py", line 51, in + rc, FileType, Path, File = tools.ProcessArgs (sys.argv, Errors) +TypeError: 'int' object is not iterable + +if you get a message like this, then I have screwed up and offended the python +gods and they have taken exception (this is basically a software error). The +best bet is to provide the call above and if possible a copy of the file that +caused it so I can try and fix it. + + + +now on to expected error messages: + +Most (but not all, as the first few below show) error messages are of the +form: + +Error: File +'/cygdrive/c/fritzing/fritzing.0.9.3b.64.pc/fritzing.0.9.3b.64.pc/fritzing-parts/core/blend_micro1.0.fzp' +At line 444 + +which gives you the file name followed by the line number (if known, sometimes +it isn't) of where the error was detected. + + Of note is the filename will be blend_micro1.0.fzp.bak if you are +processing an individual part (which will normally be the case). The reason +for this is the output file + +blend_micro1.0.fzp + +has been prettyprinted, and the line numbers won't match the input file +(blend_micro1.0.fzp.bak) so you need to look for the error in the filename +listed in the error message and then match it to the same text (which will +have a different line number and possibly format very likely) in the output +file if you need to. The input file will give you the place in the file that +the error occurred. You should fix it there and then remove the .bak +extension and rerun the script in the corrected input file. + +## Usage messages + +Usage messages (which are a type of error as they are fatal, but don't have +numbers any more) + + +Usage: PP.py filename (filename ...) + + Indicates you didn't give a filename to the PP.py script. It wants + one or more xml files such as + + PP.py test.svg + + or + + PP.py test1.svg test2.xml test3.fzp + + +Usage: FritzingTools.py filename.fzp or filename.svg or srcdir dstdir + + Either no or too many arguments to the script. It wants either a + single file name or 2 directories. + + +Usage: FritzingTools.py src_dir dst_dir + +src_dir filename isn\'t a directory + + In this mode both arguments need to be directories and src isn't. + + +Usage: FritzingTools.py src_dir dst_dir + +dst_dir filename isn\'t a directory + + In this mode both arguments need to be directories and dst isn't. + + +## Error messages + +Error messages in the order they occur in the code so essentially random +but numbered so you can index by the number to get the error description +and an explanation of the error (with the move of the Usage messages +above, some numbers are now missing though.) + +### Error 1: Can not rename filename os_error_message (os_error_number) + +The os routines returned an exception when the input file was +renamed. Hopefully the cause is obvious from the os messages. + + +### Error 2: Can not open filename os_error_message (os_error_number) + +The os routines returned an exception when the input file was +opened. Hopefully the cause is obvious from the os messages. + + +### Error 3: Can not write filename os_error_message (os_error_number) + +The os routines returned an exception when the input file was +written. Hopefully the cause is obvious from the os messages. + + +### Error 4: Can not close filename os_error_message (os_error_number) + +The os routines returned an exception when the input file was +closed. Hopefully the cause is obvious from the os messages. + + +### Error 5: ParseFile can't read file filename + +The xml parser got an I/O error trying to parse the named file. + + +### Error 6: ParseFile error parsing the input xml file filename + +The xml parser found illegal xml at the line and column listed after +this. Note the lxml parser is stricter than either Inkscape or +Fritzing and will report errors that both Inkscape and Fritzing +will accept as valid xml. If you look however, there really is an +error there and you should correct it. Below is an example from the +Bean_revE.fzp file currently in core: + +/cygdrive/c/fritzing/fritzing.0.9.3b.64.pc/fritzing.0.9.3b.64.pc/fritzing-parts/core/Bean_revE.fzp:161:90:FATAL:PARSER:ERR_SPACE_REQUIRED: attributes construct error + +line 161 from Bean_revE.fzp + +

+ +there are two errors in this line. There is a missing space between +connector81terminal' and hybrid='yes' and the second hybrid='yes is +wrong. The line should be corrected to this: + +

+ +which is correct XML and the complaints from parser will stop. You +will get a lot more errors, but again they are really there, even +though the part with these errors loads and runs happily in Fritzing. + + +### Error 8: filename isn't a file: ignored + +The file name provided either isn't a file or isn't readable and has +been ignored. + + +### Error 10: There must be a directory that is not '.' or '..' in the input name +for a fzp file in order to find the svg files. + +Indicates that it needs a directory (for example core/file.fzp) in +order to figure out where the svg files are (../svg/core/... in this +case). Supply the directory and it will be happy. + + +### Error 13: dst dir + +dst_dir + +must be empty and it is not + +The dst_dir isn't empty (perhaps from a previous run). If you are sure +the directory is expendable rm -R dst_dir/* will fix this. + + +### Error 14: Creating dir + +dir_name os_error_message (os_error_number) + +A problem creating one of the dst directories. Hopefully the os error +messages will make the cause clear. + + +### Error 15: Can not rename + +'src_file' +to +'src_file.bak' + +'file_name_from_os' + +os_error_message (os_error_number) + +A problem occurred trying to rename the src_file to src_file.bak. +Hopefully the os error messages indicate why. + + +### Error 16: File 'filename' At line 20 + +Id xxx present more than once (and should be unique) + +The listed id is present more than once and should be unique (often +Fritzing ignores this but it is incorrect) + + +### Error 17: File 'filename' No connectors found for view viewname. + +This is one of those messages without a line number as after all the +connectors have been processed, no connectors were found. + + +### Error 18: File +'filename' + +Connector connector2terminal is in the fzp file but not the svg file. (typo?) + +This connector is specified in the fzp file, but isn't in the +associated svg file. Depending on what type of connector it is +this may or may not be fatal (a svgId is fatal a terminalId is not). +In either case it is incorrect. + + +### Error 19: File +'filename' + +File type xxx is an unknown format (software error) + + +Another case of software error where the type isn't svg, fzppart or +fzpfritz. Shouldn't happen. + + +### Error 20: File +'filename.svg' + +During processing svgs from fzp, svg file doesn't exist + +The filename referenced for this view in the fzp file doesn't exist. +Fritzing will try and find something to substitute, but this is still +an error. + + +### Error 21: Svg file + +'Filename.svg' + +Has a different case in the file system than in the fpz file + +'filename.svg' + +This doesn't matter on Windows as the file system is case insensitive +however it does matter on Linux and probably MacOS where the file +system is case sensitive and the wrong case file will not be found. +Change either the FZP or the file in the file system to the same +case and all will be well on all systems. While I could correct this +in the fzp file it seems better to do it manually because it isn't +clear whether the fzp file is incorrect or this particular file system +is incorrect, and thus is better left to a human decision rather than +a program. + + +### Error 22: File +'filename.fzp' +At line 1 + +No ModuleId found in fzp file + +There isn't a moduleId in the fzp file. This is likely fatal as I don't +think the part can load without a moduleId. Add a moduleId to the file +(preferably export a new part to get a Fritzing approved moduleId). + + +### Error 23: File +'filename.fzp' +At line 20 + +A bus is already defined, schematic parts won't work with busses + +A non empty Bus definition has already been seen. Fritzing won't +currently support both busses and schematic parts. + + +### Error 24: File +'filename' +At line 20 + +More than one copy of Tag sometag + +Tag sometag should only occur once in the fzp file and we have seen +another copy of it here. + + +### Error 25: File +'filename.fzp' +At line 2 + +Multiple ModuleIds found in fzp file + +There is more than one moduleId set in the fzp file (there should only +be one) + + +### Error 26: File +'filename.fzp' +At line 20 + +State error, expected tag tag not a view name + +There is something wrong in the fzp file (or this code). The tag we +have doesn't match the expected state of a correct fzp file. Best bet +is to check the format of the fzp file against a known good version, +as there is probably an extra or missing line in this file. + + +### Error 27: File +'filename.fzp' +At line 20 + +View name missing + +We have no viewname (iconView breadboardView schematicView pcbView) +which should be present. + + +### Error 28: File +'filename.fzp' +At line 20 + +Multiple view tags schematicView present, ignored + +There is more than one view of this name defined in the file when there +should only be one of each. + + +### Error29: File +'filename.fzp' +At line 20 + +View tag schematicView not recognized (typo?) + +View tag isn't one of (iconView breadboardView schematicView pcbView) +which it should be. + + +### Error30: File +'filename.fzp' +At line 20 + +No image name present + +The file name for the svg file is missing in the fzp file. + + +### Error31: File +'filename.fzp' +At line 20 + +Multiple viewname image files present + +There is more than one image file name present, there should only be +one. + + +### Error32: File +'filename.fzp' +At line 20 + +No layerId value present + +There is a layerId attribute present, but it has no value (and it needs +one). + + +### Error33: File +'filename.fzp' +At line 20 + +View viewname already has layerId layername, layername1 ignored + +The layerId isn't unique and it must be. + + +### Error34: File +'filename.fzp' + +No views found. + +There are no views found in the fzp file. There isn't a line number +because this occurs after we have seen all the lines that may contain +a view. + + +### Error35: File +'filename.fzp' + +Unknown view viewname found. (Typo?) + +Found a view name that isn't one of iconView breadboardView +schematicView or pcbView (probably a typo) + + +### Error36: File +'filename.fzp' + +No valid views found. + +Didn't find any of iconView breadboardView schematicView or pcbView +in the list of view names. + + +### Error37: File +'filename.fzp' + +This is a smd part as only the copper0 view is present, but it is on the +bottom layer, not the top. If you wanted a smd part change copper0 to +copper 1 at line 20 If you wanted a through-hole part add the copper1 +definition after line 19 + +This is a smd part, but it is on the wrong layer (and thus likely an +error). If you really want the part to be on the bottom for something +this error can be ignored. + + +### Error38: File +'filename.fzp' +At line 20 + +State error, tag stack is at level 8 and should only go to level 7 + +This error indicates that there are too many lines in the fzp file +as the tags have gotten deeper than is possible for a valid file. + + +### Error39: File +'filename.fzp' +At line 20 + +Connector has no id + +A connector has no id associated with it and it must have one. + + +### Error40: File +'filename.fzp' +At line 20 + +Connector has no Name + +A connector has no Name associated with it and it must have one. + + +### Error41: File +'filename.fzp' +At line 20 + +Connector connector3 has no Type + +A connector has to have type male or female and has neither. + + +### Error42: File +'filename.fzp' +At line 20 + +Connector connector3 has no description + +A connector doesn't have a description. When you hover on a pad in +breadboard or schematic you won't get a description. + + +### Error43: File +'filename.fzp' +At line 20 + +Connector connector3 missing view name + +The connector doesn't have a view name. + + +### Error44: File +'filename.fzp' +At line 20 + +Viewname bbreadboardView invalid (typo?) + +The viewname isn't one of breadboardView schematicView pcbView and +it should be. + + +### Error45: File +'filename.fzp' +At line 20 + +Layer missing + +The layer attribute is missing in the fzp file. + + +### Error46: File +'filename.fzp' +At line 20 + +No layerId for View SchematicView + +A layerId wasn't specified for this view earlier in the fzp file. + + +### Error47: File +'filename.fzp' +At line 20 + +LayerId here doesn't match View schematicView layerId schematic + +A layerId here doesn't match the layerId specified earlier for this +view (or views in the case of pcb view which can have multiple +layerids.) + + +### Error48: File +'filename.fzp' +At line 20 + +Connector connector4 layer copper0 already defined, must be unique + +This connectorid layer combination is already defined and must be +unique. + + +### Error49: File +'filename.fzp' +At line 20 + +hybrid is present but isn't 'yes' but yyes (typo?) + +The hybrid flag is present but with an invalid value (it must be yes). + + +### Error50: File +'filename.fzp' +At line 20 + +Tag svgId is present but has no value + +The listed tag is present but has no value set. + + +### Error51: File +'filename.fzp' +At line 20 + +svgId missing + +There is no svgId present for this connector and one is required. + + +### Error52: File +'filename.fzp' +At line 20 + +Bus bus2 already defined + +There is aready a bus with this id and ids must be unique. + + +### Error53: File +'filename.fzp' +At line 20 + +Bus nodeMember connector2 does't exist + +The nodeMember specified doesn't exist and it must. + + +### Error54: File +'filename.fzp' +At line 20 + +Bus nodeMember connector2 already in bus bus3 + +The nodeMember specified is already in the specified bus and can't +be in two at once. + + +### Error55: File +'filename.fzp' +At line 20 + +Subpart has no id + +The subpart is missing the id field (required) + + +### Error56: File +'filename.fzp' +At line 20 + +Subpart id subpartid already exists (must be unique) + +The subpart is already in use for another subpart and must be unique. + + +### Error57: File +'filename.fzp' +At line 20 + +Subpart has no label + +The subpart has not label and it needs one. + + +### Error58: File +'filename.fzp' +At line 20 + +Subpart subpartid already defined (duplicate?) + +The subpart has already been defined and must be unique. + + +### Error59: File +'filename.fzp' +At line 20 + +Connector id missing, ignored + +The subpart definition is missing the id field. + + +### Error60: File +'filename.fzp' +At line 20 + +Connector connector2 doesn't exist (and it must) + +The connector id isn't already defined in the fzp file and it must be. + + +### Error61: File +'filename.fzp' +At line 20 + +Subpart connector connector0 already in subpart sub1 + +The connector id is already part of another subpart and can only be +in one subpart. + + +### Error62: File +'filename.fzp' + +No connectors found to check + +There are no connectors defined when we tried to check that the +connectors are in the correct sequence. + + +### Error63: File +'filename.fzp' + +Connector0 doesn't exist (connectors should start at 0) + +There isn't a connector0 and there should be. + + +### Error64: File +'filename.fzp' + +Connector connector5 doesn't exist when it must to stay in sequence + +Connectors 0 to 4 exist, then it skips to something above 5. This +causes label problems (as fritzing assumes the labels are in sequence +and will misnumber the missing and following connections). + + +### Error65: File +'filename.fzp' +At line 20 + +Connector connector1pad is an ellipse not a circle, (gerber generation will +break.) + +This indicates a connector in a pcb svg is an ellipse (i.e. has rx and +ry rather than r as a radius in the xml). This is usually because of +a removed translate that has changed horizontal or vertical scale. The +easiest fix is to copy one radius value to the other in xml editor +(making sure the new radius value still keeps the intended hole size). + + +### Error66: File +'filename.fzp' +At line 20 + +Connector connector2pin is a duplicate (and should be unique) + +The listed connector has already been seen in the svg file and should +be unique. As long as the two are defined identically fritzing seems +to ignore this, but it should be corrected. + + +### Error67: File +'filename.fzp' +At line 2 + +First Tag tag isn\'t an svg definition + +The first tag in an svg file should be svg. If it isn't there will +probably be a problem. Compare your file against a known correct one +is probably the best bet here. + + +### Error68: File +'filename.fzp' +At line 20 + +Found first group but without a svg definition + +Similar to the error above, we have found a group but haven't seen a +svg id yet. + + +### Error69: File +'filename.fzp' +At line 20 + +Found a drawing element before a layerId (or no layerId) + +A drawing element (perhaps a connector) has been found before the +layerId. If it is a visible part of the drawing, it likely won't be +present if the drawing is exported as a svg, so it is better to have +the layerId first. This also may mean that the layerId is missing +entirely in which case one should be added befoe any drawing elements. + + +### Error70: File +'filename.fzp' +At line 20 + +More than one silkscreen/copper0/copper1 layer + +We have already seen a layer of this name in this svg, a second one is +an error. + + +### Error71: File +'filename.fzp' +At line 20 + +Silkscreen layer should be at the top, not under group copper1 + +As it says the silkscreen layer should be at the top not under any +other group. + + +### Error72: File +'filename.fzp' +At line 20 + +copper0 should be under copper1 not the same level + +As it says copper0 should be under copper1 not at the same level. + + +### Error73: File +'filename.fzp' +At line 20 + +Too many layers, there should only be copper1 then copper0 + +There is a layer under copper1/copper0 which there shouldn't be. + + +### Error74: File +'filename.fzp' +At line 20 + +Connector connector1pad has no radius no hole will be generated + +This has been determined to be a through hole part (as no hole is +normal for a smd part) but there is no radius for the pad and thus +no hole will be generated which is usually an error. + + +### Error75: File +'filename.fzp' + +This is a smd part as only the copper0 view is present +but it is on the bottom layer, not the top. + +Smd parts should normally be on the top side of the board so this is +most likely an error. + + +### Error76: File +'filename.fzp' +At line 20 + +Copper0 and copper1 have non identical transforms (no transforms is best) + + +There is a transform in one or the other of the copper layers but not +the other. What this breaks is moving a component from the top of the +pcb to the bottom in inspector. The order of the transforms changes as +does the scaling making the part wrong on the pcb. Ungrouping and then +regrouping copper1/copper0 will usually fix this (the ungroup removes +the transform). + + +### Error77: File +'filename.fzp' +At line 20 + +terminalId can't be a path as it won't work. + +The terminalId can't be of the specified type (currently path, but +there may be others that will get added). Unless it has a center such +as a rectangle, line, or polygon fritzing won't take it as a terminalId +and will default to the center of the svgId which likely isn't what you +want. I prefer to use a rectangle of .01in by .01in for terminalID. + +### Error78: Svg File +'filename.svg' + +While looking for connector1pin, Subpart subpart2 has no connectors in the svg + +This subpart doesn't have any connectors defined in it and it should. + +### Error79: Svg File +'filename.svg' + +Subpart subpart2 is missing connector connector1pin in the svg + +The listed pin is missing in the svg file (it may be defined in another +subpart, in which case it will have a warning message there). + +### Error 80: File +'filename.fzp' +At line 20 + +Both terminalId and legId present, only one or the other is allowed. + +As the message says, there are two terminal definitions and it must +be only one or the other. + +### Error 81: File +'filename.fzp' +At line 20 + +Subpart connector subpart1 has no pins defined + +This subpart has no pins defined and it usually needs at least one +(there may be cases where this can be ignored though ...) + +### Error 82: File +'filename.svg' +At line 20 + +connector connector1pin isn't in a subpart + +This connector isn't part of a subpart groupname and it should be. + +### Error 83: File +'filename.svg' +At line 20 + +Connector connector1pin shouldn't be in subpart subpart2 as it is + +The fzp file says this connector should be in another subpart, not +this one (at the time this error is issued we don't know what the +other subpart is which is why it isn't listed). + +### Error 84: File +'filename.svg' +At line 20 + +Connector connector1pin in incorrect subpart subpart2 + +This will usually accompany Error 83 above indicating that the +connector is in a subpart where it isn't defined in the fzp file. +Again, because at this point we don't know where the connector should +be, we can't list the subpart it should be in. + +### Error 85: File +'filename.svg' +At line 20 + +subpart label subpart2 is already defined + +There is already a subpart with this label in the svg. I'm not sure +this error can actually occur. Inkscape won't allow you to set it (but +a text edit would), but it may not get through the xml parser as valid +xml if you did (but I haven't tested that so far). + +### Error 86: File +'filename.svg' +At line 20 + +Subpart subpart1 isn\'t at the top level when it must be +Following subpart errors may be invalid until this is fixed + +While this may be legal in Fritzing, due to the complexity of checking +subparts this script only supports subparts of the form: + + pair). This may or may not interfere with creating +schematic-subparts, and isn't really needed unless you want to add +a bus. As a result it could be removed to reduce clutter and size. + + +### Warning 16: File +'filename.fzp' +At line 20 + +Connector connector1pin has a zero height or width +and thus is not selectable in Inkscape + +While connectors with 0 height or width work just fine, at least in +Inkscape they are not selectable by dragging a box around them and +clicking on them. Thus you can't easily move them (you need to change +their coordinates in the tool bar after selecting them in xml editor). +I prefer to use .01in by .01in rectangles for terminals because they +will select and move when selected with a dragged square in the gui. +Unfortunatly changing the height and width also changes the x/y +position, so automatically correcting this will be more complex than +just adding a value, so it is left for you to do at the moment. + +### Warning 17: File +'filename.fzp' +At line 20 + +More than one svg tag found + +This may be perfectly valid (such as multiple name spaces for some +reason), but it is unusual enough to note in case it isn't intended. + + +### Warning 18: File +'filename.fzp' +At line 20 + +Height attribute missing + +This should probably be an error as I don't think it will work, but +there is no height attribute in the viewbox definition. + + +### Warning 19: File +'filename.fzp' +At line 20 + +Height 200px is defined in px +in or mm is a better option (px can cause scaling problems!) + +While this is perfectly legal, it is unwise (but common!). If defined +in px (and either no units or an explicit px is in px) fritzing will +make a guess (and sometimes get it wrong) about how many px per inch +the drawing used. Older Inkscapes (0.91 and older) used 90px per inch +as of 0.92 they use the CSS standard of 96px per inch. Older copies +of Illustrator used 72px per inch. If you change this to being inches +or millimeters, there is no guess required, and it will scale correctly. +To do so in Inkscape do an edit, select all, and set the toolbar to inches +or mm. Take the height and width (inches or mm) from the toolbar readout +and use XML editor to set those numbers into the height and width in the +viewbox setting (with 'in' at the end to indicate this is in inches). +When you set them, Inkscape will change the drawing to match the new scale. +Note it is possible some part of the drawing may not change correctly, +so visually check it. This is usually the cause of a drawing that looks +correct in Inkscape but is on the wrong scale (i.e. doesn't match the +grid) in fritzing. To correct that, in Inkscape you can recalculate the +scaling like this: + +heightpx * 72/90/96 = size in inches. + +You will need to try the likely values 72, 90 or 96 til the scaling +in Fritzing is correct and then set the correct value in inches (or +mm if you prefer) as the height and width in the first entry in xml +editor. +### Warning 20: File +'filename.fzp' +At line 20 + +copper1 layer should be at the top, not under group copper0 + +If the second group is copper0 this is normal (or at least harmless) +as the order doesn't really matter. However for smd parts the single +copper layer needs to be copper1 so it is preferable to be copper1 +followed by copper0. + + +### Warning 21: File +'filename.fzp' +At line 20 + +This appears to be a pcb svg but has no copper or silkscreen layers! + +As the message says there is no image data here at all which is likely +an error (as the layer is defined in the fzp file). + + +### Warning 22: File +'filename.fzp' +At line 20 + +Already have a layerId + +There is a second (or more) layerId in a view that only allows one +layer id. Likely an error. + + +### Warning 23: File +'filename.fzp' +At line 20 + +Key key_value +value '-inkscape-font-specification 'Droid Sans, Normal' is invalid and has +been deleted + +This is the typical value that I have seen. The lxml parser appears to +object to the leading - in the value. This warning is here in case at +some point something less ignorable than this gets found here. + +### Warning 24: File +'filename.fzp' +At line 20 + +Font family 'ArialMT' is not Droid Sans or OCRA +This likely won't render in Fritzing + +Fritzing only supports fonts Droid Sans or OCRA so this likely won't +be rendered in Fritzging. If you really need this particular font you +need to convert it to a path in your svg editor (but that is a pain to +anyone trying to modify your part and thus undesirable). + +### Warning 25: File +'filename.fzp' +At line 20 + +Silkscreen layer should be above the copper layers for easier selection in +pcb view + +If silkscreen is below the copper layers then part selection will +favor the silkscreen layer making part selection more difficult. +Moving the silkscreen layer before the copper layers will fix this. + +### Warning 26: File +'filename.fzp' +At line 20 + +Apparant nested tspan which fritzing doesn't support +If your text doesn't appear in Fritzing this is probably why + +As noted nested tspan don't work in Fritzing at least sometimes, in +fact tspan is not supposed to work but usually does. + +### Warning 27: File +'filename.fzp' +At line 20 + +Fritzing layerId silkscreen isn't a group which it usually should be + +This is a warning because (at least for silkscreen, don't know about +the others) Fritzing will accept a path as the silkscreen (although +it can only have one element and a group would be a better bet). + +### Warning 28: File +'filename.fzp' +At line 20 + +name gnd present more than once (and should be unique) + +This id is duplicated in another name or description field. It is a +warning in this case because dups here (unlike connectors) are not +typically fatal. The part file format document does say they should +be unique though. + +Modified: + +These messages document the changes made by the script to the input +files. Note the line numbers refer to the input file (which will be +usually in the filename.svg.bak file) as the output file has been +prettyprinted which changes the line numbers. As a result you need +to look at the input file at the line of the change and then search for +that text in the output file to find the area of the change. + +### Warning 29: File +'filename.fzp' +At line 20 + +File test.svg +has already been processed +but will be processed again as part of this fzp file in case of new warnings. + +This svg file is likely shared by several parts. One downside of this +is that the original of this file won't be in the .bak file as that +will be replaced by the version from the last processing output. It +is processed again in case there are errors relative to this fzp file +that are different than the first processing instance. Because +sometimes iconView is copied from breadboard (which would trip this +warning) and because we don't actually check anything in icon view +icon view processing from the fzp is skipped. + +## Modification messages + +### Modified 1: File +'filename.fzp' +At line 20 + +Removed px from font-size leaving 3.5 + +Removed the px from font-size="3.5x" because Fritzing objects to the px +on the font-size and sets the font-size to 0 when the part is edited. + +### Modified 2: File +'filename.fzp' +At line 20 + +Connector connector0terminal had a zero width (or height), set to 10 +Check the alignment of this pin in the SVG + +As it says, a 0 length height or width was set to 10 which may causee +the location of the terminal to change. You need to verify (and move +if necessary) the location of this terminal in the svg. You may also +need to adjust the size of the terminal to be 10 thou as the size of +10 may not be correct depending on scaling and translates. + +### Modified 3: File +'filename.fzp' +At line 20 + +Silkscreen, converted stoke/fill from white or not black to black + +Notification that we have changed the color of the silkscreen layer +in the svg from white (or not black) to black for both stroke and fill. + +### Modified 4: File +'filename.fzp' +At line 20 + +ReferenceFile + +'filename.svg' + +doesn\'t match input file + +'filename1.svg' + +Corrected + +Notification that the reference file was updated to be the same as the +file name of this svg file. Nothing much appears to care whether this +field is correct or not. + +### Modified 5: File +'filename.fzp' +At line 20 + +Converted style to inline xml + +A style command such as + +style="fill:none;stroke:#787878;stroke-width:9.72220039 + +has been converted to the equivelent xml: + +fill="none" stroke="#787878" stroke-width="9.72220039" + +(which prettyprinting will then break down to one element per properly +indented line changing the output line numbers substantially) because +fritzing (specifically bendable legs) does not support the style +command syntax even though it is legal xml and Inkscape will convert +the inline xml to a style command to be CSS compliant.