File indexing completed on 2023-03-17 11:26:48
0001
0002
0003 from __future__ import print_function
0004 import optparse
0005 import os
0006 import re
0007 import sys
0008 import pprint
0009 import subprocess
0010 from XML2Python import xml2obj
0011 from subprocess import getoutput
0012
0013
0014 typedefsDict = \
0015 {
0016
0017 'unsigned int' : ['unsignedint', 'UInt32_t', 'uint32_t'],
0018 'unsigned long': ['unsignedlong'],
0019 'int' : ['Int32_t'],
0020 'float' : ['Float_t'],
0021 'double' : ['Double_t'],
0022 'char' : ['Char_t'],
0023 '< ' : ['<', '<'],
0024 ' >' : ['>', '>'],
0025 ', ' : [','],
0026 }
0027
0028
0029
0030
0031
0032 equivDict = \
0033 [
0034 {'SelectorUtils': ['VersionedSelector']},
0035 {'Associations': ['TTTrackTruthPair', 'edm::Wrapper.+edm::AssociationMap.+TrackingParticle']},
0036 {'TrajectoryState' : ['TrajectoryStateOnSurface']},
0037 {'TrackTriggerAssociation' : ['(TTClusterAssociationMap|TTStubAssociationMap|TTTrackAssociationMap|TrackingParticle).*Phase2TrackerDigi',
0038 '(TTStub|TTCluster|TTTrack).*Phase2TrackerDigi.*TrackingParticle']},
0039 {'L1TrackTrigger' : ['(TTStub|TTCluster|TTTrack).*Phase2TrackerDigi']},
0040 {'L1TCalorimeterPhase2' : ['l1tp2::CaloTower.*']},
0041 {'L1TCalorimeter' : ['l1t::CaloTower.*']},
0042 {'VertexFinder' : ['l1tVertexFinder::Vertex']},
0043 {'GsfTracking' : ['reco::GsfTrack(Collection|).*(MomentumConstraint|VertexConstraint)', 'Trajectory.*reco::GsfTrack']},
0044 {'PatCandidates' : ['pat::PATObject','pat::Lepton', 'reco::RecoCandidate','pat::[A-Za-z]+Ref(Vector|)', 'pat::UserHolder']},
0045 {'BTauReco' : ['reco::.*SoftLeptonTagInfo', 'reco::SoftLeptonProperties','reco::SecondaryVertexTagInfo','reco::IPTagInfo','reco::TemplatedSecondaryVertexTagInfo', 'reco::CATopJetProperties','reco::HTTTopJetProperties']},
0046 {'CastorReco' : ['reco::CastorJet']},
0047 {'JetMatching' : ['reco::JetFlavourInfo', 'reco::JetFlavour','reco::MatchedPartons']},
0048 {'RecoCandidate' : ['reco::Candidate']},
0049 {'TrackingAnalysis' : ['TrackingParticle']},
0050 {'Egamma' : ['reco::ElectronID']},
0051 {'TopObjects' : ['reco::CATopJetProperties']},
0052 {'TauReco' : ['reco::L2TauIsolationInfo','reco::RecoTauPiZero','reco::BaseTau']},
0053 {'ValidationFormats' : ['PGlobalDigi::.+','PGlobalRecHit::.+']},
0054 {'TrajectorySeed' : ['TrajectorySeed']},
0055 {'TrackCandidate' : ['TrackCandidate']},
0056 {'PatternTools' : ['MomentumConstraint','VertexConstraint','Trajectory']},
0057 {'TrackerRecHit2D' : ['SiStrip(Matched|)RecHit[12]D','SiTrackerGSRecHit[12]D','SiPixelRecHit']},
0058 {'MuonReco' : ['reco::Muon(Ref|)(Vector|)']},
0059 {'MuonSeed' : ['L3MuonTrajectorySeed']},
0060 {'HepMCCandidate' : ['reco::GenParticle.*']},
0061 {'L1Trigger' : ['l1extra::L1.+Particle', 'l1t::Vertex']},
0062 {'TrackInfo' : ['reco::TrackingRecHitInfo']},
0063 {'EgammaCandidates' : ['reco::GsfElectron.*','reco::Photon.*']},
0064 {'HcalIsolatedTrack' : ['reco::IsolatedPixelTrackCandidate', 'reco::EcalIsolatedParticleCandidate', 'reco::HcalIsolatedTrackCandidate']},
0065 {'HcalRecHit' : ['HFRecHit','HORecHit','ZDCRecHit','HBHERecHit']},
0066 {'PFRootEvent' : ['EventColin::']},
0067 {'CaloTowers' : ['CaloTower.*']},
0068 {'GsfTrackReco' : ['GsfTrack.*']},
0069 {'METReco' : ['reco::(Calo|PF|Gen|)MET','reco::PFClusterMET']},
0070 {'ParticleFlowReco' : ['reco::RecoPFClusterRefCandidateRef.*']},
0071 {'ParticleFlowCandidate' : ['reco::PFCandidateRef','reco::PFCandidateFwdRef','reco::PFCandidate']},
0072 {'PhysicsToolsObjects' : ['PhysicsTools::Calibration']},
0073 {'TrackReco' : ['reco::Track','reco::TrackRef']},
0074 {'VertexReco' : ['reco::Vertex']},
0075 {'TFWLiteSelectorTest' : ['tfwliteselectortest']},
0076 {'TauReco' : ['reco::PFJetRef']},
0077 {'JetReco' : ['reco::.*Jet','reco::.*Jet(Collection|Ref)']},
0078 {'HGCDigi' : ['HGCSample']},
0079 {'HGCRecHit' : ['constHGCRecHit','HGCRecHit']},
0080 {'SiPixelObjects' : ['SiPixelQuality.*']},
0081 ]
0082
0083 ignoreEdmDP = {
0084 'LCGReflex/__gnu_cxx::__normal_iterator<std::basic_string<char>*,std::vector<std::basic_string<char>%>%>' : 1,
0085 '' : 1
0086 }
0087
0088 def searchClassDefXml ():
0089 """ Searches through the requested directory looking at
0090 'classes_def.xml' files looking for duplicate Reflex definitions."""
0091
0092 classNameRE = re.compile (r'class\s+name\s*=\s*"([^"]*)"')
0093 spacesRE = re.compile (r'\s+')
0094 stdRE = re.compile (r'std::')
0095 srcClassNameRE = re.compile (r'(\w+)/src/classes_def.*[.]xml')
0096 ignoreSrcRE = re.compile (r'.*/FWCore/Skeletons/scripts/mkTemplates/.+')
0097 braketRE = re.compile (r'<.+>')
0098 print("Searching for 'classes_def.xml' in '%s'." % os.path.join(os.environ.get('CMSSW_BASE'),'src'))
0099 xmlFiles = []
0100 for srcDir in [os.environ.get('CMSSW_BASE'),os.environ.get('CMSSW_RELEASE_BASE')]:
0101 if not len(srcDir): continue
0102 for xml in getoutput ('cd '+os.path.join(srcDir,'src')+'; find . -name "*classes_def*.xml" -follow -print').split ('\n'):
0103 if xml and (not xml in xmlFiles):
0104 xmlFiles.append(xml)
0105 if options.showXMLs:
0106 pprint.pprint (xmlFiles)
0107
0108 xmlPackages = []
0109 packagesREs = {}
0110 equivREs = {}
0111 explicitREs = []
0112 for item in equivDict:
0113 for pack in item:
0114 for equiv in item[pack]:
0115 explicitREs.append( (re.compile(r'\b' + equiv + r'\b'),pack))
0116 if options.lostDefs:
0117 for filename in xmlFiles:
0118 if (not filename) or (ignoreSrcRE.match(filename)): continue
0119 match = srcClassNameRE.search (filename)
0120 if not match: continue
0121 packageName = match.group(1)
0122 xmlPackages.append (packageName)
0123 matchString = r'\b' + packageName + r'\b'
0124 packagesREs[packageName] = re.compile (matchString)
0125 equivList = equivREs.setdefault (packageName, [])
0126 for item in equivDict:
0127 for equiv in item.get (packageName, []):
0128 matchString = re.compile(r'\b' + equiv + r'\b')
0129 equivList.append( (matchString, equiv) )
0130 equivList.append( (packagesREs[packageName], packageName) )
0131 classDict = {}
0132 ncdict = {'class' : 'className', 'function' : 'functionName'}
0133 for filename in xmlFiles:
0134 if (not filename) or (ignoreSrcRE.match(filename)): continue
0135 dupProblems = ''
0136 exceptName = ''
0137 regexList = []
0138 localObjects = []
0139 simpleObjectREs = []
0140 if options.lostDefs:
0141 lostMatch = srcClassNameRE.search (filename)
0142 if lostMatch:
0143 exceptName = lostMatch.group (1)
0144 regexList = equivREs[exceptName]
0145 xcount = len(regexList)-1
0146 if not regexList[xcount][0].search (exceptName):
0147 print('%s not found in' % exceptName, end=' ')
0148 print(regexList[xcount][0])
0149 sys.exit()
0150 else: continue
0151 if options.verbose:
0152 print("filename", filename)
0153 try:
0154 filepath = os.path.join(os.environ.get('CMSSW_BASE'),'src',filename)
0155 if not os.path.exists(filepath):
0156 filepath = os.path.join(os.environ.get('CMSSW_RELEASE_BASE'),'src',filename)
0157 xmlObj = xml2obj (filename = filepath,
0158 filtering = True,
0159 nameChangeDict = ncdict)
0160 except Exception as detail:
0161 print("File %s is malformed XML. Please fix." % filename)
0162 print(" ", detail)
0163 continue
0164 try:
0165 classList = xmlObj.selection.className
0166 except:
0167 try:
0168 classList = xmlObj.className
0169 except:
0170
0171 print("**** SKIPPING '%s' - Doesn't seem to have proper information." % filename)
0172 continue
0173 if not classList:
0174 classList = xmlObj.functionName
0175 if not classList:
0176 print("**** SKIPPING '%s' - Dosen't seem to have proper information(not class/function)." % filename)
0177 continue
0178 for piece in classList:
0179 try:
0180 className = spacesRE.sub ('', piece.name)
0181 except:
0182
0183
0184 continue
0185 className = stdRE.sub ('', className)
0186
0187
0188 for typedef, tdList in typedefsDict.items():
0189 for alias in tdList:
0190 className = re.sub (alias, typedef, className)
0191 classDict.setdefault (className, set()).add (filename)
0192
0193 if not options.lostDefs:
0194 continue
0195 localObjects.append (className)
0196 if options.lazyLostDefs and not braketRE.search (className):
0197
0198 matchString = r'\b' + className + r'\b'
0199 simpleObjectREs.append( (re.compile (matchString), className ) )
0200 for className in localObjects:
0201
0202
0203 foundEquiv = False
0204 for equivRE in regexList:
0205
0206 if equivRE[0].search (className):
0207 foundEquiv = True
0208 break
0209 for simpleRE in simpleObjectREs:
0210 if simpleRE[0].search (className):
0211 foundEquiv = True
0212 if options.verbose and simpleRE[1] != className:
0213 print(" Using %s to ignore %s" \
0214 % (simpleRE[1], className))
0215 break
0216 if foundEquiv: continue
0217 for exRes in explicitREs:
0218 if exRes[0].search(className):
0219 dupProblems += " %s : %s\n" % (exRes[1], className)
0220 foundEquiv = True
0221 break
0222 if foundEquiv: continue
0223 for packageName in xmlPackages:
0224
0225
0226 if packagesREs[packageName].search (className):
0227 dupProblems += " %s : %s\n" % (packageName, className)
0228 break
0229
0230 if dupProblems:
0231 print('\n%s\n%s\n' % (filename, dupProblems))
0232
0233 if options.dups:
0234 for name, fileSet in sorted( classDict.items() ):
0235 if len (fileSet) < 2:
0236 continue
0237 print(name)
0238 fileList = sorted (fileSet)
0239 for filename in fileList:
0240 print(" ", filename)
0241 print()
0242
0243
0244
0245
0246
0247 def searchDuplicatePlugins ():
0248 """ Searches the edmpluginFile to find any duplicate
0249 plugins."""
0250 edmpluginFile = ''
0251 libenv = 'LD_LIBRARY_PATH'
0252 if os.environ.get('SCRAM_ARCH').startswith('osx'): libenv = 'DYLD_FALLBACK_LIBRARY_PATH'
0253 biglib = '/biglib/'+os.environ.get('SCRAM_ARCH')
0254 for libdir in os.environ.get(libenv).split(':'):
0255 if libdir.endswith(biglib): continue
0256 if os.path.exists(libdir+'/.edmplugincache'): edmpluginFile = edmpluginFile + ' ' + libdir+'/.edmplugincache'
0257 if edmpluginFile == '': edmpluginFile = os.path.join(os.environ.get('CMSSW_BASE'),'lib',os.environ.get('SCRAM_ARCH'),'.edmplugincache')
0258 cmd = "cat %s | awk '{print $2\" \"$1}' | sort | uniq | awk '{print $1}' | sort | uniq -c | grep '2 ' | awk '{print $2}'" % edmpluginFile
0259 output = getoutput (cmd).split('\n')
0260 for line in output:
0261 if line in ignoreEdmDP: continue
0262 line = line.replace("*","\*")
0263 cmd = "cat %s | grep ' %s ' | awk '{print $1}' | sort | uniq " % (edmpluginFile,line)
0264 out1 = getoutput (cmd).split('\n')
0265 print(line)
0266 for plugin in out1:
0267 if plugin:
0268 print(" **"+plugin+"**")
0269 print()
0270
0271 if __name__ == "__main__":
0272
0273 parser = optparse.OptionParser ("Usage: %prog [options]\n"\
0274 "Searches classes_def.xml for wrong/duplicate "\
0275 "definitions")
0276 xmlGroup = optparse.OptionGroup (parser, "ClassDef XML options")
0277 dumpGroup = optparse.OptionGroup (parser, "EdmPluginDump options")
0278 xmlGroup.add_option ('--dups', dest='dups', action='store_true',
0279 default=False,
0280 help="Search for duplicate definitions")
0281 xmlGroup.add_option ('--lostDefs', dest='lostDefs', action='store_true',
0282 default=False,
0283 help="Looks for definitions in the wrong libraries")
0284 xmlGroup.add_option ('--lazyLostDefs', dest='lazyLostDefs',
0285 action='store_true',
0286 default=False,
0287 help="Will try to ignore as many lost defs as reasonable")
0288 xmlGroup.add_option ('--verbose', dest='verbose',
0289 action='store_true',
0290 default=False,
0291 help="Prints out a lot of information")
0292 xmlGroup.add_option ('--showXMLs', dest='showXMLs', action='store_true',
0293 default=False,
0294 help="Shows all 'classes_def.xml' files")
0295 xmlGroup.add_option ('--dir', dest='srcdir', type='string', default='',
0296 help="Obsolete")
0297 dumpGroup.add_option ('--edmPD', dest='edmPD', action='store_true',
0298 default=False,
0299 help="Searches EDM Plugin Dump for duplicates")
0300 dumpGroup.add_option ('--edmFile', dest='edmFile', type='string',
0301 default='',
0302 help="Obsolete")
0303 parser.add_option_group (xmlGroup)
0304 parser.add_option_group (dumpGroup)
0305 (options, args) = parser.parse_args()
0306
0307
0308 if options.lazyLostDefs:
0309 options.lostDefs = True
0310 if options.showXMLs or options.lostDefs or options.dups:
0311 searchClassDefXml ()
0312 if options.edmPD:
0313 searchDuplicatePlugins ()