3 from __future__
import print_function
10 from XML2Python
import xml2obj
12 from subprocess
import getoutput
14 from commands
import getoutput
20 'unsigned int' : [
'unsignedint',
'UInt32_t',
'uint32_t'],
21 'unsigned long': [
'unsignedlong'],
23 'float' : [
'Float_t'],
24 'double' : [
'Double_t'],
37 {
'Associations': [
'TTTrackTruthPair',
'edm::Wrapper.+edm::AssociationMap.+TrackingParticle']},
38 {
'TrajectoryState' : [
'TrajectoryStateOnSurface']},
39 {
'TrackTriggerAssociation' : [
'(TTClusterAssociationMap|TTStubAssociationMap|TTTrackAssociationMap|TrackingParticle).*Phase2TrackerDigi',
40 '(TTStub|TTCluster|TTTrack).*Phase2TrackerDigi.*TrackingParticle']},
41 {
'L1TrackTrigger' : [
'(TTStub|TTCluster|TTTrack).*Phase2TrackerDigi']},
42 {
'L1TCalorimeterPhase2' : [
'l1tp2::CaloTower.*']},
43 {
'L1TCalorimeter' : [
'l1t::CaloTower.*']},
44 {
'VertexFinder' : [
'l1tVertexFinder::Vertex']},
45 {
'GsfTracking' : [
'reco::GsfTrack(Collection|).*(MomentumConstraint|VertexConstraint)',
'Trajectory.*reco::GsfTrack']},
46 {
'PatCandidates' : [
'pat::PATObject',
'pat::Lepton',
'reco::RecoCandidate',
'pat::[A-Za-z]+Ref(Vector|)',
'pat::UserHolder']},
47 {
'BTauReco' : [
'reco::.*SoftLeptonTagInfo',
'reco::SoftLeptonProperties',
'reco::SecondaryVertexTagInfo',
'reco::IPTagInfo',
'reco::TemplatedSecondaryVertexTagInfo',
'reco::CATopJetProperties',
'reco::HTTTopJetProperties']},
48 {
'CastorReco' : [
'reco::CastorJet']},
49 {
'JetMatching' : [
'reco::JetFlavourInfo',
'reco::JetFlavour',
'reco::MatchedPartons']},
50 {
'RecoCandidate' : [
'reco::Candidate']},
51 {
'TrackingAnalysis' : [
'TrackingParticle']},
52 {
'Egamma' : [
'reco::ElectronID']},
53 {
'TopObjects' : [
'reco::CATopJetProperties']},
54 {
'TauReco' : [
'reco::L2TauIsolationInfo',
'reco::RecoTauPiZero',
'reco::BaseTau']},
55 {
'ValidationFormats' : [
'PGlobalDigi::.+',
'PGlobalRecHit::.+']},
56 {
'TrajectorySeed' : [
'TrajectorySeed']},
57 {
'TrackCandidate' : [
'TrackCandidate']},
58 {
'PatternTools' : [
'MomentumConstraint',
'VertexConstraint',
'Trajectory']},
59 {
'TrackerRecHit2D' : [
'SiStrip(Matched|)RecHit[12]D',
'SiTrackerGSRecHit[12]D',
'SiPixelRecHit']},
60 {
'MuonReco' : [
'reco::Muon(Ref|)(Vector|)']},
61 {
'MuonSeed' : [
'L3MuonTrajectorySeed']},
62 {
'HepMCCandidate' : [
'reco::GenParticle.*']},
63 {
'L1Trigger' : [
'l1extra::L1.+Particle',
'l1t::Vertex']},
64 {
'TrackInfo' : [
'reco::TrackingRecHitInfo']},
65 {
'EgammaCandidates' : [
'reco::GsfElectron.*',
'reco::Photon.*']},
66 {
'HcalIsolatedTrack' : [
'reco::IsolatedPixelTrackCandidate',
'reco::EcalIsolatedParticleCandidate',
'reco::HcalIsolatedTrackCandidate']},
67 {
'HcalRecHit' : [
'HFRecHit',
'HORecHit',
'ZDCRecHit',
'HBHERecHit']},
68 {
'PFRootEvent' : [
'EventColin::']},
69 {
'CaloTowers' : [
'CaloTower.*']},
70 {
'GsfTrackReco' : [
'GsfTrack.*']},
71 {
'METReco' : [
'reco::(Calo|PF|Gen|)MET',
'reco::PFClusterMET']},
72 {
'ParticleFlowReco' : [
'reco::RecoPFClusterRefCandidateRef.*']},
73 {
'ParticleFlowCandidate' : [
'reco::PFCandidateRef',
'reco::PFCandidateFwdRef',
'reco::PFCandidate']},
74 {
'PhysicsToolsObjects' : [
'PhysicsTools::Calibration']},
75 {
'TrackReco' : [
'reco::Track',
'reco::TrackRef']},
76 {
'VertexReco' : [
'reco::Vertex']},
77 {
'TFWLiteSelectorTest' : [
'tfwliteselectortest']},
78 {
'TauReco' : [
'reco::PFJetRef']},
79 {
'JetReco' : [
'reco::.*Jet',
'reco::.*Jet(Collection|Ref)']},
80 {
'HGCDigi' : [
'HGCSample']},
81 {
'HGCRecHit' : [
'constHGCRecHit',
'HGCRecHit']},
82 {
'SiPixelObjects' : [
'SiPixelQuality.*']},
86 'LCGReflex/__gnu_cxx::__normal_iterator<std::basic_string<char>*,std::vector<std::basic_string<char>%>%>' : 1,
91 """ Searches through the requested directory looking at
92 'classes_def.xml' files looking for duplicate Reflex definitions."""
94 classNameRE = re.compile (
r'class\s+name\s*=\s*"([^"]*)"')
95 spacesRE = re.compile (
r'\s+')
96 stdRE = re.compile (
r'std::')
97 srcClassNameRE = re.compile (
r'(\w+)/src/classes_def.*[.]xml')
98 ignoreSrcRE = re.compile (
r'.*/FWCore/Skeletons/scripts/mkTemplates/.+')
99 braketRE = re.compile (
r'<.+>')
100 print(
"Searching for 'classes_def.xml' in '%s'." % os.path.join(os.environ.get(
'CMSSW_BASE'),
'src'))
102 for srcDir
in [os.environ.get(
'CMSSW_BASE'),os.environ.get(
'CMSSW_RELEASE_BASE')]:
103 if not len(srcDir):
continue
104 for xml
in getoutput (
'cd '+os.path.join(srcDir,
'src')+
'; find . -name "*classes_def*.xml" -follow -print').split (
'\n'):
105 if xml
and (
not xml
in xmlFiles):
108 pprint.pprint (xmlFiles)
114 for item
in equivDict:
116 for equiv
in item[pack]:
117 explicitREs.append( (re.compile(
r'\b' + equiv +
r'\b'),pack))
119 for filename
in xmlFiles:
120 if (
not filename)
or (ignoreSrcRE.match(filename)):
continue
121 match = srcClassNameRE.search (filename)
122 if not match:
continue
123 packageName = match.group(1)
124 xmlPackages.append (packageName)
125 matchString =
r'\b' + packageName +
r'\b'
126 packagesREs[packageName] = re.compile (matchString)
127 equivList = equivREs.setdefault (packageName, [])
128 for item
in equivDict:
129 for equiv
in item.get (packageName, []):
130 matchString = re.compile(
r'\b' + equiv +
r'\b')
131 equivList.append( (matchString, equiv) )
132 equivList.append( (packagesREs[packageName], packageName) )
134 ncdict = {
'class' :
'className',
'function' :
'functionName'}
135 for filename
in xmlFiles:
136 if (
not filename)
or (ignoreSrcRE.match(filename)):
continue
143 lostMatch = srcClassNameRE.search (filename)
145 exceptName = lostMatch.group (1)
146 regexList = equivREs[exceptName]
147 xcount = len(regexList)-1
148 if not regexList[xcount][0].search (exceptName):
149 print(
'%s not found in' % exceptName, end=
' ')
150 print(regexList[xcount][0])
154 print(
"filename", filename)
156 filepath = os.path.join(os.environ.get(
'CMSSW_BASE'),
'src',filename)
157 if not os.path.exists(filepath):
158 filepath = os.path.join(os.environ.get(
'CMSSW_RELEASE_BASE'),
'src',filename)
159 xmlObj = xml2obj (filename = filepath,
161 nameChangeDict = ncdict)
162 except Exception
as detail:
163 print(
"File %s is malformed XML. Please fix." % filename)
167 classList = xmlObj.selection.className
170 classList = xmlObj.className
173 print(
"**** SKIPPING '%s' - Doesn't seem to have proper information." % filename)
176 classList = xmlObj.functionName
178 print(
"**** SKIPPING '%s' - Dosen't seem to have proper information(not class/function)." % filename)
180 for piece
in classList:
182 className = spacesRE.sub (
'', piece.name)
187 className = stdRE.sub (
'', className)
190 for typedef, tdList
in typedefsDict.items():
192 className = re.sub (alias, typedef, className)
193 classDict.setdefault (className, set()).add (filename)
195 if not options.lostDefs:
197 localObjects.append (className)
198 if options.lazyLostDefs
and not braketRE.search (className):
200 matchString =
r'\b' + className +
r'\b'
201 simpleObjectREs.append( (re.compile (matchString), className ) )
202 for className
in localObjects:
206 for equivRE
in regexList:
208 if equivRE[0].search (className):
211 for simpleRE
in simpleObjectREs:
212 if simpleRE[0].search (className):
214 if options.verbose
and simpleRE[1] != className:
215 print(
" Using %s to ignore %s" \
216 % (simpleRE[1], className))
218 if foundEquiv:
continue
219 for exRes
in explicitREs:
220 if exRes[0].
search(className):
221 dupProblems +=
" %s : %s\n" % (exRes[1], className)
224 if foundEquiv:
continue
225 for packageName
in xmlPackages:
228 if packagesREs[packageName].search (className):
229 dupProblems +=
" %s : %s\n" % (packageName, className)
233 print(
'\n%s\n%s\n' % (filename, dupProblems))
236 for name, fileSet
in sorted( classDict.items() ):
237 if len (fileSet) < 2:
240 fileList = sorted (fileSet)
241 for filename
in fileList:
250 """ Searches the edmpluginFile to find any duplicate
253 libenv =
'LD_LIBRARY_PATH'
254 if os.environ.get(
'SCRAM_ARCH').startswith(
'osx'): libenv =
'DYLD_FALLBACK_LIBRARY_PATH'
255 biglib =
'/biglib/'+os.environ.get(
'SCRAM_ARCH')
256 for libdir
in os.environ.get(libenv).
split(
':'):
257 if libdir.endswith(biglib):
continue
258 if os.path.exists(libdir+
'/.edmplugincache'): edmpluginFile = edmpluginFile +
' ' + libdir+
'/.edmplugincache'
259 if edmpluginFile ==
'': edmpluginFile = os.path.join(os.environ.get(
'CMSSW_BASE'),
'lib',os.environ.get(
'SCRAM_ARCH'),
'.edmplugincache')
260 cmd =
"cat %s | awk '{print $2\" \"$1}' | sort | uniq | awk '{print $1}' | sort | uniq -c | grep '2 ' | awk '{print $2}'" % edmpluginFile
261 output = getoutput (cmd).
split(
'\n')
263 if line
in ignoreEdmDP:
continue
264 line = line.replace(
"*",
"\*")
265 cmd =
"cat %s | grep ' %s ' | awk '{print $1}' | sort | uniq " % (edmpluginFile,line)
266 out1 = getoutput (cmd).
split(
'\n')
270 print(
" **"+plugin+
"**")
273 if __name__ ==
"__main__":
275 parser = optparse.OptionParser (
"Usage: %prog [options]\n"\
276 "Searches classes_def.xml for wrong/duplicate "\
278 xmlGroup = optparse.OptionGroup (parser,
"ClassDef XML options")
279 dumpGroup = optparse.OptionGroup (parser,
"EdmPluginDump options")
280 xmlGroup.add_option (
'--dups', dest=
'dups', action=
'store_true',
282 help=
"Search for duplicate definitions")
283 xmlGroup.add_option (
'--lostDefs', dest=
'lostDefs', action=
'store_true',
285 help=
"Looks for definitions in the wrong libraries")
286 xmlGroup.add_option (
'--lazyLostDefs', dest=
'lazyLostDefs',
289 help=
"Will try to ignore as many lost defs as reasonable")
290 xmlGroup.add_option (
'--verbose', dest=
'verbose',
293 help=
"Prints out a lot of information")
294 xmlGroup.add_option (
'--showXMLs', dest=
'showXMLs', action=
'store_true',
296 help=
"Shows all 'classes_def.xml' files")
297 xmlGroup.add_option (
'--dir', dest=
'srcdir', type=
'string', default=
'',
299 dumpGroup.add_option (
'--edmPD', dest=
'edmPD', action=
'store_true',
301 help=
"Searches EDM Plugin Dump for duplicates")
302 dumpGroup.add_option (
'--edmFile', dest=
'edmFile', type=
'string',
305 parser.add_option_group (xmlGroup)
306 parser.add_option_group (dumpGroup)
307 (options, args) = parser.parse_args()
310 if options.lazyLostDefs:
311 options.lostDefs =
True
312 if options.showXMLs
or options.lostDefs
or options.dups:
315 searchDuplicatePlugins ()