CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
duplicateReflexLibrarySearch.py
Go to the documentation of this file.
1 #! /usr/bin/env python
2 
3 import optparse
4 import os
5 import commands
6 import re
7 import sys
8 import pprint
9 import commands
10 import subprocess
11 from XML2Python import xml2obj
12 
13 # These aren't all typedefs, but can sometimes make the output more
14 # readable
15 typedefsDict = \
16  {
17  # What we want <= What we have
18  'unsigned int' : ['unsignedint', 'UInt32_t', 'uint32_t'],
19  'unsigned long': ['unsignedlong'],
20  'int' : ['Int32_t'],
21  'float' : ['Float_t'],
22  'double' : ['Double_t'],
23  'char' : ['Char_t'],
24  '< ' : ['<', '&lt;'],
25  ' >' : ['>', '&gt;'],
26  ', ' : [','],
27  }
28 
29 
30 # Equivalent names for packages - lets script know that, for example,
31 # 'TrackReco' package should have objects 'reco::Track'.
32 #Ordered List to search for matched packages
33 equivDict = \
34  [
35  {'GsfTracking' : ['reco::GsfTrack(Collection|).*(MomentumConstraint|VertexConstraint)', 'Trajectory.*reco::GsfTrack']},
36  {'ParallelAnalysis' : ['examples::TrackAnalysisAlgorithm']},
37  {'PatCandidates' : ['pat::PATObject','pat::Lepton']},
38  {'BTauReco' : ['reco::SoftLeptonProperties','reco::SecondaryVertexTagInfo']},
39  {'CastorReco' : ['reco::CastorJet']},
40  {'JetMatching' : ['reco::JetFlavour','reco::MatchedPartons']},
41  {'TrackingAnalysis' : ['TrackingParticle']},
42  {'Egamma' : ['reco::ElectronID']},
43  {'TopObjects' : ['reco::CATopJetProperties']},
44  {'TauReco' : ['reco::L2TauIsolationInfo','reco::RecoTauPiZero','reco::BaseTau']},
45  {'ValidationFormats' : ['PGlobalDigi::.+','PGlobalRecHit::.+']},
46  {'TrajectorySeed' : ['TrajectorySeed']},
47  {'TrackCandidate' : ['TrackCandidate']},
48  {'PatternTools' : ['MomentumConstraint','VertexConstraint','Trajectory']},
49  {'TrackerRecHit2D' : ['SiStrip(Matched|)RecHit[12]D','SiTrackerGSRecHit[12]D','SiPixelRecHit']},
50  {'MuonReco' : ['reco::Muon(Ref|)(Vector|)']},
51  {'MuonSeed' : ['L3MuonTrajectorySeed']},
52  {'HepMCCandidate' : ['reco::GenParticle.*']},
53  {'L1Trigger' : ['l1extra::L1.+Particle']},
54  {'TrackInfo' : ['reco::TrackingRecHitInfo']},
55  {'EgammaCandidates' : ['reco::GsfElectron.*','reco::Photon.*']},
56  {'HcalIsolatedTrack' : ['reco::IsolatedPixelTrackCandidate', 'reco::EcalIsolatedParticleCandidate']},
57  {'HcalRecHit' : ['HFRecHit','HORecHit','ZDCRecHit','HBHERecHit']},
58  {'PFRootEvent' : ['EventColin::']},
59  {'CaloTowers' : ['CaloTower.*']},
60  {'GsfTrackReco' : ['GsfTrack.*']},
61  {'METReco' : ['reco::(Calo|PF|Gen|)MET','reco::PFClusterMET']},
62  {'ParticleFlowReco' : ['reco::RecoPFClusterRefCandidateRef.*']},
63  {'ParticleFlowCandidate' : ['reco::PFCandidateRef','reco::PFCandidateFwdRef','reco::PFCandidate']},
64  {'PhysicsToolsObjects' : ['PhysicsTools::Calibration']},
65  {'RecoCandidate' : ['reco::Candidate']},
66  {'TrackReco' : ['reco::Track','reco::TrackRef']},
67  {'VertexReco' : ['reco::Vertex']},
68  {'TFWLiteSelectorTest' : ['tfwliteselectortest']},
69  {'PatCandidates' : ['reco::RecoCandidate','pat::[A-Za-z]+Ref(Vector|)']},
70  {'JetReco' : ['reco::.*Jet','reco::.*Jet(Collection|Ref)']},
71  ]
72 
73 ignoreEdmDP = {
74  'LCGReflex/__gnu_cxx::__normal_iterator<std::basic_string<char>*,std::vector<std::basic_string<char>%>%>' : 1,
75  '' : 1
76 }
77 
79  """ Searches through the requested directory looking at
80  'classes_def.xml' files looking for duplicate Reflex definitions."""
81  # compile necessary RE statements
82  classNameRE = re.compile (r'class\s+name\s*=\s*"([^"]*)"')
83  spacesRE = re.compile (r'\s+')
84  stdRE = re.compile (r'std::')
85  srcClassNameRE = re.compile (r'(\w+)/src/classes_def.xml')
86  ignoreSrcRE = re.compile (r'.*/FWCore/Skeletons/scripts/mkTemplates/.+')
87  braketRE = re.compile (r'<.+>')
88  print "Searching for 'classes_def.xml' in '%s'." % os.path.join(os.environ.get('CMSSW_BASE'),'src')
89  xmlFiles = []
90  for srcDir in [os.environ.get('CMSSW_BASE'),os.environ.get('CMSSW_RELEASE_BASE')]:
91  if not len(srcDir): continue
92  for xml in commands.getoutput ('cd '+os.path.join(srcDir,'src')+'; find . -name "*classes_def.xml" -print').split ('\n'):
93  if xml and (not xml in xmlFiles):
94  xmlFiles.append(xml)
95  if options.showXMLs:
96  pprint.pprint (xmlFiles)
97  # try and figure out the names of the packages
98  xmlPackages = []
99  packagesREs = {}
100  equivREs = {}
101  explicitREs = []
102  for item in equivDict:
103  for pack in item:
104  for equiv in item[pack]:
105  explicitREs.append( (re.compile(r'\b' + equiv + r'\b'),pack))
106  if options.lostDefs:
107  for filename in xmlFiles:
108  if (not filename) or (ignoreSrcRE.match(filename)): continue
109  match = srcClassNameRE.search (filename)
110  if not match: continue
111  packageName = match.group(1)
112  xmlPackages.append (packageName)
113  matchString = r'\b' + packageName + r'\b'
114  packagesREs[packageName] = re.compile (matchString)
115  equivList = equivREs.setdefault (packageName, [])
116  for item in equivDict:
117  for equiv in item.get (packageName, []):
118  matchString = re.compile(r'\b' + equiv + r'\b')
119  equivList.append( (matchString, equiv) )
120  equivList.append( (packagesREs[packageName], packageName) )
121  classDict = {}
122  ncdict = {'class' : 'className'}
123  for filename in xmlFiles:
124  if (not filename) or (ignoreSrcRE.match(filename)): continue
125  dupProblems = ''
126  exceptName = ''
127  regexList = []
128  localObjects = []
129  simpleObjectREs = []
130  if options.lostDefs:
131  lostMatch = srcClassNameRE.search (filename)
132  if lostMatch:
133  exceptName = lostMatch.group (1)
134  regexList = equivREs[exceptName]
135  xcount = len(regexList)-1
136  if not regexList[xcount][0].search (exceptName):
137  print '%s not found in' % exceptName,
138  print regexList[xcount][0]
139  sys.exit()
140  else: continue
141  if options.verbose:
142  print "filename", filename
143  try:
144  filepath = os.path.join(os.environ.get('CMSSW_BASE'),'src',filename)
145  if not os.path.exists(filepath):
146  filepath = os.path.join(os.environ.get('CMSSW_RELEASE_BASE'),'src',filename)
147  xmlObj = xml2obj (filename = filepath,
148  filtering = True,
149  nameChangeDict = ncdict)
150  except Exception as detail:
151  print "File %s is malformed XML. Please fix." % filename
152  print " ", detail
153  continue
154  try:
155  classList = xmlObj.selection.className
156  except:
157  try:
158  classList = xmlObj.className
159  except:
160  # this isn't a real classes_def.xml file. Skip it
161  print "**** SKIPPING '%s' - Doesn't seem to have proper information." % filename
162  continue
163  for piece in classList:
164  try:
165  className = spacesRE.sub ('', piece.name)
166  except:
167  # must be one of these class pattern things. Skip it
168  #print " skipping %s" % filename, piece.__repr__()
169  continue
170  className = stdRE.sub ('', className)
171  # print " ", className
172  # Now get rid of any typedefs
173  for typedef, tdList in typedefsDict.iteritems():
174  for alias in tdList:
175  className = re.sub (alias, typedef, className)
176  classDict.setdefault (className, set()).add (filename)
177  # should we check for lost definitions?
178  if not options.lostDefs:
179  continue
180  localObjects.append (className)
181  if options.lazyLostDefs and not braketRE.search (className):
182  #print " ", className
183  matchString = r'\b' + className + r'\b'
184  simpleObjectREs.append( (re.compile (matchString), className ) )
185  for className in localObjects:
186  # if we see our name (or equivalent) here, then let's
187  # skip complaining about this
188  foundEquiv = False
189  for equivRE in regexList:
190  #print "searching %s for %s" % (equivRE[1], className)
191  if equivRE[0].search (className):
192  foundEquiv = True
193  break
194  for simpleRE in simpleObjectREs:
195  if simpleRE[0].search (className):
196  foundEquiv = True
197  if options.verbose and simpleRE[1] != className:
198  print " Using %s to ignore %s" \
199  % (simpleRE[1], className)
200  break
201  if foundEquiv: continue
202  for exRes in explicitREs:
203  if exRes[0].search(className):
204  dupProblems += " %s : %s\n" % (exRes[1], className)
205  foundEquiv = True
206  break
207  if foundEquiv: continue
208  for packageName in xmlPackages:
209  # don't bother looking for the name of this
210  # package in this package
211  if packagesREs[packageName].search (className):
212  dupProblems += " %s : %s\n" % (packageName, className)
213  break
214  # for piece
215  if dupProblems:
216  print '\n%s\n%s\n' % (filename, dupProblems)
217  # for filename
218  if options.dups:
219  for name, fileSet in sorted( classDict.iteritems() ):
220  if len (fileSet) < 2:
221  continue
222  print name
223  fileList = list (fileSet)
224  fileList.sort()
225  for filename in fileList:
226  print " ", filename
227  print
228  # for name, fileSet
229  # if not noDups
230  #pprint.pprint (classDict)
231 
232 
234  """ Searches the edmpluginFile to find any duplicate
235  plugins."""
236  edmpluginFile = os.path.join(os.environ.get('CMSSW_BASE'),'lib',os.environ.get('SCRAM_ARCH'),'.edmplugincache')
237  if len (os.environ.get('CMSSW_RELEASE_BASE')):
238  edmpluginFile = edmpluginFile+ ' ' + os.path.join(os.environ.get('CMSSW_RELEASE_BASE'),'lib',os.environ.get('SCRAM_ARCH'),'.edmplugincache')
239  cmd = "cat %s | awk '{print $2\" \"$1}' | sort | uniq | awk '{print $1}' | sort | uniq -c | grep '2 ' | awk '{print $2}'" % edmpluginFile
240  output = commands.getoutput (cmd).split('\n')
241  for line in output:
242  if ignoreEdmDP.has_key(line): continue
243  line = line.replace("*","\*")
244  cmd = "cat %s | grep ' %s ' | awk '{print $1}' | sort | uniq " % (edmpluginFile,line)
245  out1 = commands.getoutput (cmd).split('\n')
246  print line
247  for plugin in out1:
248  if plugin:
249  print " **"+plugin+"**"
250  print
251 
252 if __name__ == "__main__":
253  # setup options parser
254  parser = optparse.OptionParser ("Usage: %prog [options]\n"\
255  "Searches classes_def.xml for wrong/duplicate "\
256  "definitions")
257  xmlGroup = optparse.OptionGroup (parser, "ClassDef XML options")
258  dumpGroup = optparse.OptionGroup (parser, "EdmPluginDump options")
259  xmlGroup.add_option ('--dups', dest='dups', action='store_true',
260  default=False,
261  help="Search for duplicate definitions")
262  xmlGroup.add_option ('--lostDefs', dest='lostDefs', action='store_true',
263  default=False,
264  help="Looks for definitions in the wrong libraries")
265  xmlGroup.add_option ('--lazyLostDefs', dest='lazyLostDefs',
266  action='store_true',
267  default=False,
268  help="Will try to ignore as many lost defs as reasonable")
269  xmlGroup.add_option ('--verbose', dest='verbose',
270  action='store_true',
271  default=False,
272  help="Prints out a lot of information")
273  xmlGroup.add_option ('--showXMLs', dest='showXMLs', action='store_true',
274  default=False,
275  help="Shows all 'classes_def.xml' files")
276  xmlGroup.add_option ('--dir', dest='srcdir', type='string', default='',
277  help="Obsolete")
278  dumpGroup.add_option ('--edmPD', dest='edmPD', action='store_true',
279  default=False,
280  help="Searches EDM Plugin Dump for duplicates")
281  dumpGroup.add_option ('--edmFile', dest='edmFile', type='string',
282  default='',
283  help="Obsolete")
284  parser.add_option_group (xmlGroup)
285  parser.add_option_group (dumpGroup)
286  (options, args) = parser.parse_args()
287 
288  # Let's go:
289  if options.lazyLostDefs:
290  options.lostDefs = True
291  if options.showXMLs or options.lostDefs or options.dups:
292  searchClassDefXml ()
293  if options.edmPD:
294  searchDuplicatePlugins ()
double split
Definition: MVATrainer.cc:139