CMS 3D CMS Logo

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