CMS 3D CMS Logo

/data/doxygen/doxygen-1.7.3/gen/CMSSW_4_2_8/src/FWCore/ParameterSet/python/comments.py

Go to the documentation of this file.
00001 #!/bin/env python
00002 
00003 # tool to add comments to python configuration files
00004 # 
00005 # this tool makes the following assumptions
00006 #  - for each file Subproject/Package/data/config.[cff,cfg,cfi] 
00007 #    there is a file Subproject/Package/python/config_[cff,cfg,cfi].py
00008 #  - comments are either in the line just above a command or just behind in the same line
00009 
00010 
00011 # should hold the comment ID
00012 # which is Comment.value and Comment.type = "trailing" or "inline"
00013 # 
00014 
00015 from FWCore.ParameterSet import cfgName2py
00016 
00017 class Comment:
00018     pass
00019 
00020 
00021 def prepareReplaceDict(line, comment, replaceDict):
00022     """take a line and a corresponding comment and prepare the replaceDict such that it can be found again in the python version """
00023     allKeywords = ['module','int32','vint32','uint32', 'vuint32','double','vdouble','InputTag', 'VInputTag', 'PSet', 'VPSet', 'string', 'vstring', 'bool', 'vbool', 'path', 'sequence', 'schedule', 'endpath', 'es_source', 'es_module', 'block', 'FileInPath']
00024     unnamedKeywords = ['es_source', 'es_module']
00025 
00026 
00027     words = line.lstrip().split()
00028     # at least <keyword> <label> = "
00029     if len(words) > 1:
00030         firstWord = words[0]
00031         if firstWord in allKeywords and len(words) > 2 and words[2] == '=':
00032            tokenInPython = words[1] + " = "
00033            replaceDict[tokenInPython] = comment
00034         elif firstWord == 'untracked' and len(words) > 3 and words[1] in allKeywords and words[3] == '=':
00035            tokenInPython = words[2] + " = cms.untracked"
00036            replaceDict[tokenInPython] = comment
00037         elif firstWord.startswith('include'): # handling of include statements
00038            pythonModule = cfgName2py.cfgName2py(line.split('"')[1])
00039            pythonModule = pythonModule.replace("/",".").replace("python.","").replace(".py","")
00040            tokenInPython = "from "+pythonModule
00041            tokenInPython = tokenInPython.replace("/",".").replace("python.","").replace(".py","")
00042            replaceDict[tokenInPython] = comment
00043            # if a cfg
00044            tokenInPython = "process.load(\""+pythonModule
00045            replaceDict[tokenInPython] = comment
00046         elif firstWord == 'source' and len(words) > 1 and words[1] == '=':
00047            replaceDict['source = '] = comment
00048         elif firstWord in unnamedKeywords and len(words) > 2 and words[1] == '=':
00049            tokenInPython = words[2] + ' = cms.ES'
00050            replaceDict[tokenInPython] = comment
00051         elif firstWord == 'replace' and len(words) > 2 and words[2] == '=':
00052            tokenInPython= words[1] + " = "
00053            replaceDict[tokenInPython] = comment
00054         elif firstWord == 'replace' and len(words) > 2 and words[2] == '=':
00055            tokenInPython= words[1] + " = "
00056            replaceDict[tokenInPython] = comment
00057            # if it's a cfg
00058            tokenInPython = 'process.'+tokenInPython
00059            replaceDict[tokenInPython] = comment
00060         elif firstWord == 'using' and len(words) == 2:
00061            tokenInPython= words[1]
00062            replaceDict[tokenInPython] = comment
00063        # if it's a significant line, we're not in a comment any more
00064         else:
00065           replaceDict["@beginning"] +="\n"+comment.value
00066     
00067 
00068 
00069 def identifyComments(configString):
00070     
00071     replaceDict = {}
00072 
00073     replaceDict["@beginning"] = "# The following comments couldn't be translated into the new config version:\n"
00074     allKeywords = ['module','int32','vint32','uint32', 'vuint32','double','vdouble','InputTag', 'VInputTag', 'PSet', 'VPSet', 'string', 'bool', 'vbool', 'path', 'sequence', 'schedule', 'endpath', 'es_source', 'es_module', 'block', 'FileInPath']
00075     unnamedKeywords = ['es_source', 'es_module']
00076     # the ugly parsing part
00077     inComment = False # are we currently in a comment?
00078     inSlashStarComment = False
00079 
00080     # TODO - include inline comments
00081     # for now only modules work
00082     for line in configString.splitlines():
00083         if line.lstrip().startswith("/*"):
00084             comment = Comment()
00085             comment.type = "slashstar"
00086             splitStarSlash = line.lstrip().lstrip("/*").split("*/")
00087             comment.value = "# "+splitStarSlash[0]+"\n"
00088             # has it ended yet?  Might ignore legitimate commands after the end.
00089             inSlashStarComment = (line.find('*/') == -1)
00090             inComment = True
00091         elif inSlashStarComment:
00092             splitStarSlash = line.lstrip().lstrip("/*").split("*/")
00093             comment.value += "# "+splitStarSlash[0]+"\n"
00094             inSlashStarComment = (line.find('*/') == -1)
00095         elif line.lstrip().startswith("#") or line.lstrip().startswith("//"):
00096           if inComment:
00097             comment.value += "#"+line.lstrip().lstrip("//").lstrip("#") + "\n"
00098           else:
00099             comment = Comment()
00100             comment.type = "trailing"
00101             comment.value = "#"+line.lstrip().lstrip("//").lstrip("#") + "\n"
00102             inComment = True
00103         elif inComment:  # we are now in a line just below a comment
00104           words = line.lstrip().split()
00105           # at least <keyword> <label> = "
00106           if len(words) > 1:
00107              prepareReplaceDict(line,comment,replaceDict)             
00108           if len(words) > 0:
00109              inComment = False
00110         else:
00111              # now to comments in the same line
00112              if len(line.split("#")) > 1 or len(line.split("//")) > 1:
00113                comment = Comment()
00114                if len(line.split("#")) > 1:
00115                  comment.value = '#'+line.split("#")[1]
00116                else:
00117                  comment.value = '#'+line.split("//")[1]
00118                comment.type = "inline"
00119                # prepare the replaceDict
00120                prepareReplaceDict(line, comment, replaceDict)
00121       
00122 
00123     return replaceDict
00124           
00125         
00126 
00127 
00128 def modifyPythonVersion(configString, replaceDict):
00129 
00130     # first put all comments at the beginning of the file which could not be assigned to any other token
00131     if replaceDict["@beginning"] != "# The following comments couldn't be translated into the new config version:\n":
00132       configString = replaceDict["@beginning"]+"\n"+configString 
00133 
00134     replaceDict.pop("@beginning")
00135 
00136     # identify the lines to replace and prepare the replacing line
00137     actualReplacements = {}
00138     for keyword, comment in replaceDict.iteritems():
00139         for line in configString.splitlines():
00140             if line.lstrip().startswith(keyword):
00141                 indentation = line[0:line.find(keyword)]
00142                 if len([1 for l in configString.splitlines() if l.lstrip().startswith(keyword)]) !=1:
00143                     print "WARNING. Following keyword not unique:", keyword
00144                     continue 
00145                 if comment.type == "inline":
00146                   newLine = line + " #"+comment.value+"\n"
00147                 else:
00148                   newLine = line.replace(line,comment.value+line)  # lacking the trailing whitespace support
00149                   newLine = newLine.replace('#', indentation+'#')
00150                 actualReplacements[line] = newLine
00151 
00152 
00153     # now do the actual replacement
00154     for original, new in actualReplacements.iteritems():        
00155         configString = configString.replace(original, new)
00156 
00157     return configString
00158 
00159 
00160 def loopfile(cfgFileName):
00161    cfgFile = file(cfgFileName)
00162    cfgString = cfgFile.read()
00163    
00164    pyFileName = cfgName2py.cfgName2py(cfgFileName)
00165 
00166    try: 
00167      pyFile = file(pyFileName)
00168      pyString = pyFile.read()
00169    except IOError:
00170      print pyFileName, "does not exist"
00171      return
00172    comments = identifyComments(cfgString)
00173    print "Opening", pyFileName
00174    newPyString = modifyPythonVersion(pyString, comments)
00175    pyFile.close()
00176 
00177    pyOutFile = file(pyFileName,"w")
00178    pyOutFile.write(newPyString)
00179    print "Wrote", pyFileName
00180    pyOutFile.close()
00181  
00182 #out = file("foo_cfi.py","w")
00183 #out.write(configString)
00184 #print configString
00185 
00186 
00187 
00188 # 
00189 import os
00190 from sys import argv
00191 
00192 if len(argv) != 2:
00193     print "Please give either a filename, or 'local'"
00194 elif argv[1] == 'local':
00195   for subsystem in os.listdir("."):
00196     try:
00197       #print subsystem
00198        for package in os.listdir("./"+subsystem):
00199          #print "  ",subsystem+"/"+package
00200           try:
00201             for name in os.listdir(subsystem+"/"+package+"/data"):
00202               if len(name.split("."))==2 and name.split(".")[1] in ["cfg","cfi","cff"]:
00203                 print subsystem+"/"+package+"/data/"+name
00204                 loopfile(subsystem+"/"+package+"/data/"+name)
00205           except OSError:
00206             pass
00207     except OSError:
00208       pass
00209     
00210 
00211 else:
00212   loopfile(argv[1])
00213 
00214