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