CMS 3D CMS Logo

callgraph.py
Go to the documentation of this file.
1 #! /usr/bin/env python3
2 from __future__ import print_function
3 import networkx as nx
4 import re
5 import json
6 from yaml import load, dump, FullLoader
7 try:
8  from yaml import CLoader as Loader, CDumper as Dumper
9 except ImportError:
10  from yaml import Loader, Dumper
11 
12 topfunc = r"::(dqmBeginRun|dqmEndRun|bookHistograms|accumulate|acquire|startingNewLoop|duringLoop|endOfLoop|beginOfJob|endOfJob|produce|analyze|filter|beginLuminosityBlock|beginRun|beginStream|streamBeginRun|streamBeginLuminosityBlock|streamEndRun|streamEndLuminosityBlock|globalBeginRun|globalEndRun|globalBeginLuminosityBlock|globalEndLuminosityBlock|endRun|endRunProduce|endLuminosityBlock)\("
13 topfuncre = re.compile(topfunc)
14 
15 baseclass = r"\b(edm::)?(one::|stream::|global::)?((DQM)?(Global|One)?ED(Producer|Filter|Analyzer|(IterateNTimes|NavigateEvents)?Looper)(Base)?|impl::(ExternalWork|Accumulator|RunWatcher|RunCacheHolder)|FromFiles|ProducerSourceBase|OutputModuleBase|InputSource|ProducerSourceFromFiles|ProducerBase|PuttableSourceBase|OutputModule|RawOutput|RawInputSource|impl::RunWatcher<edm::one::EDProducerBase>|impl::EndRunProducer<edm::one::EDProducerBase>|DQMEDHarvester|AlignmentProducerBase|BMixingModule|TrackProducerBase|cms::CkfTrackCandidateMakerBase|CallEndRunProduceImpl|CallGlobalImpl|impl::makeGlobal|impl::makeStreamModule|impl::EndRunProducer)\b"
16 baseclassre = re.compile(baseclass)
17 assert(baseclassre.match('edm::one::impl::EndRunProducer'))
18 assert(baseclassre.match('DQMOneEDAnalyzer'))
19 assert(baseclassre.match('edm::EDAnalyzer'))
20 assert(baseclassre.match('edm::stream::EDProducerBase'))
21 assert(baseclassre.match('DQMEDHarvester'))
22 assert(baseclassre.match('edm::one::impl::RunWatcher<edm::one::EDProducerBase>'))
23 assert(baseclassre.match('edm::global::EDFilter::filter() virtual'))
24 assert(baseclassre.search('edm::stream::EDProducerBase::produce'))
25 assert(topfuncre.search('edm::global::EDFilterBase::filter(&) const virtual'))
26 assert(not baseclassre.match('edm::BaseFlatGunProducer'))
27 assert(not baseclassre.match('edm::FlatRandomEGunProducer'))
28 assert(baseclassre.match('edm::ProducerSourceBase'))
29 assert(baseclassre.match('edm::one::OutputModuleBase'))
30 farg = re.compile(r"\(.*?\)")
31 tmpl = re.compile(r'<(.*)>')
32 toplevelfuncs = set()
33 
34 getfuncre = re.compile(r"edm::eventsetup::EventSetupRecord::get<")
35 epfuncre = re.compile(r"edm::eventsetup::EventSetupRecord::deprecated_get<")
36 f = 'edm::eventsetup::EventSetupRecord::get<class edm::ESHandle<class CaloTopology>>(const std::string &, class edm::ESHandle<class CaloTopology> &) const'
37 g = 'edm::eventsetup::EventSetupRecord::deprecated_get<class edm::ESHandle<class HcalDDDSimConstants>>(const char *, class edm::ESHandle<class HcalDDDSimConstants> &) const'
38 g2 = 'edm::eventsetup::EventSetupRecord::deprecated_get<class edm::ESHandle<class HcalDDDSimConstants>>(class edm::ESHandle<class HcalDDDSimConstants> &) const'
39 h = 'edm::eventsetup::EventSetupRecord::get<class edm::ESHandle<class CaloTPGTranscoder>>(class edm::ESHandle<class CaloTPGTranscoder> &) const'
40 assert(getfuncre.search(f))
41 assert(epfuncre.search(g))
42 assert(getfuncre.search(h))
43 assert(epfuncre.search(g2))
44 epf='edm::eventsetup::EventSetupRecord::get<class edm::ESHandle<class CaloTPGTranscoder>>(edm::ESHandle<CaloTPGTranscoder> &) const'
45 assert(getfuncre.search(epf))
46 
47 skipfunc = re.compile(r"TGraph::IsA\(.*\)")
48 epfuncs = set()
49 
50 function='(anonymous namespace in /src/RecoTracker/TkHitPairs/plugins/HitPairEDProducer.cc)::Impl<(anonymous namespace)::ImplSeedingHitSets, (anonymous namespace)::DoNothing, (anonymous namespace)::RegionsLayersSeparate>::produce(const _Bool, edm::Event &, const edm::EventSetup &);'
51 function2='HitPairEDProducer::produce(edm::Event &, const edm::EventSetup &);'
52 value='HitPairEDProducer'
53 valuere=r'\b%s\b' % value
54 vre=re.compile(valuere)
55 m=vre.search(function)
56 assert(m)
57 m2=vre.search(function2)
58 assert(m2)
59 
60 
61 module2package = dict()
62 with open('module_to_package.yaml') as m:
63  module2package=load(m, Loader=FullLoader)
64 
65 with open('packages.json', 'r') as j:
66  p = json.load(j)
67 
68 for k,v in p.items():
69  module=k.split('|')[0]
70  dirs=v.split('|')
71  package=dirs[0]+'/'+dirs[1]
72  module2package.setdefault(package, []).append(module)
73 
74 for k in module2package.keys():
75  module2package[k]=sorted(set(module2package[k]))
76 
77 G = nx.DiGraph()
78 with open('function-calls-db.txt') as f:
79  for line in f:
80  fields = line.split("'")
81  if len(fields) < 3:
82  continue
83  if fields[2] == ' calls function ':
84  G.add_edge(fields[1], fields[3], kind=fields[2])
85  if epfuncre.search(fields[3]) or getfuncre.search(fields[3]):
86  epfuncs.add(fields[3])
87  if fields[2] == ' overrides function ':
88  if baseclassre.match(fields[3]):
89  G.add_edge(fields[1], fields[3], kind=' overrides function ')
90  if topfuncre.search(fields[1]) :
91  toplevelfuncs.add(fields[1])
92  else:
93  G.add_edge(fields[3], fields[1], kind=' overriden function calls function ')
94  if epfuncre.search(fields[3]) or getfuncre.search(fields[3]):
95  epfuncs.add(fields[3])
96 
97 callstacks = set()
98 for tfunc in toplevelfuncs:
99  for epfunc in epfuncs:
100  if G.has_node(tfunc) and G.has_node(epfunc) and nx.has_path(G, tfunc, epfunc):
101  for path in nx.all_shortest_paths(G, tfunc, epfunc):
102  cs = str("")
103  previous = str("")
104  for p in path:
105  if getfuncre.search(p) or epfuncre.search(p):
106  break
107  #stripped=re.sub(farg, "()", p)
108  stripped=p
109  if previous != stripped:
110  cs += stripped + '; '
111  previous = stripped
112  if cs not in callstacks:
113  callstacks.add(cs)
114 
115 report = dict()
116 csset = set(callstacks)
117 for callstack in sorted(list(callstacks)):
118  for key in module2package.keys():
119  for value in module2package.get(key):
120  regex_str = r'\b%s\b'%value
121  vre=re.compile(regex_str)
122  if vre.search(callstack):
123  report.setdefault(str(key), {}).setdefault(str(value), []).append(str(callstack))
124  csset.discard(callstack)
125 
126 report['no-package']=dict()
127 for cs in sorted(list(csset)):
128  key=tmpl.split(topfuncre.split(cs)[0])[0]
129  report['no-package'].setdefault(key,[]).append(str(cs))
130 
131 r = open('eventsetuprecord-get.yaml', 'w')
132 dump(report, r, width=float("inf"))
assert(be >=bs)
def load(fileName)
Definition: svgfig.py:547
#define str(s)