CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
TreeCrawler.py
Go to the documentation of this file.
1 # This CMS code is based on previous work done by Toby Dickenson, as indiciated below
2 #
3 # for questions: Benedikt.Hegner@cern.ch
4 
5 # Copyright 2004 Toby Dickenson
6 #
7 # Permission is hereby granted, free of charge, to any person obtaining
8 # a copy of this software and associated documentation files (the
9 # "Software"), to deal in the Software without restriction, including
10 # without limitation the rights to use, copy, modify, merge, publish,
11 # distribute, sublicense, and/or sell copies of the Software, and to
12 # permit persons to whom the Software is furnished to do so, subject
13 # to the following conditions:
14 #
15 # The above copyright notice and this permission notice shall be included
16 # in all copies or substantial portions of the Software.
17 #
18 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19 # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
21 # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
22 # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 
26 import sys, os, inspect, copy
27 import modulefinder
28 
30  return ".".join(name.replace("python/","").replace(".py","").split("/")[-3:])
31 
32 
33 class Color:
34  """ANSI escape display sequences"""
35  info = "\033[1;34m"
36  hilight = "\033[31m"
37  alternate = "\033[32m"
38  extra = "\033[33m"
39  backlight = "\033[43m"
40  underline = "\033[4m"
41  lessemphasis = "\033[30m"
42  deemphasis = "\033[1;30m"
43  none = "\033[0m"
44 
45 _stack = []
46 
47 class SearchHit:
48  pass
49 
50 class Package(object):
51  def __init__(self,name,top=False):
52  self.name = name
53  self.dependencies = []
54  self.searched = False
55  self.stack = []
56  if top:
57  self.module = None
58  else:
59  self.module = __import__(name,[],[],"*")
60  def dump(self,level):
61  indent = " " * level
62  print indent, "+", Color.info, self.name, Color.none
63  # sort dependencies alphabetically
64  self.dependencies.sort(key = lambda x: x.name)
65  for package in self.dependencies:
66  package.dump(level+1)
67  def search(self,pattern,result):
68  """ recursive search for pattern in source files"""
69  # first start searching in the package itself / do this only once
70  if self.module:
71  for number, line in enumerate(inspect.getsource(self.module).splitlines()):
72  if pattern in line:
73  filename = packageNameFromFilename(inspect.getsourcefile(self.module))
74  if not self.searched:
75  # save the hit, so we can add later stacks to it
76  self.hit = SearchHit()
77  self.hit.number = number
78  self.hit.filename = filename
79  self.hit.line = line
80  self.hit.stacks = list()
81  result.append(self.hit)
82  self.hit.stacks.append(copy.copy(_stack))
83  # then go on with dependencies
84  _stack.append(self.name)
85  for package in self.dependencies:
86  package.search(pattern,result)
87  _stack.pop()
88  self.searched = True
89 
90 
91 class mymf(modulefinder.ModuleFinder):
92  def __init__(self,*args,**kwargs):
93  self._depgraph = {}
94  self._types = {}
95  self._last_caller = None
96  #TODO - replace by environment variables CMSSW_BASE and CMSSW_RELEASE_BASE (*and* do it only if the global one is not empty like for IB areas)
97  self._localarea = os.path.expandvars('$CMSSW_BASE')
98  self._globalarea = os.path.expandvars('$CMSSW_RELEASE_BASE')
99  modulefinder.ModuleFinder.__init__(self,*args,**kwargs)
100  def import_hook(self, name, caller=None, fromlist=None, level=-1):
101  old_last_caller = self._last_caller
102  try:
103  self._last_caller = caller
104  return modulefinder.ModuleFinder.import_hook(self,name,caller,fromlist, level=level)
105  finally:
106  self._last_caller = old_last_caller
107 
108  def import_module(self,partnam,fqname,parent):
109 
110  if partnam in ("FWCore","os"):
111  r = None
112  else:
113  r = modulefinder.ModuleFinder.import_module(self,partnam,fqname,parent)
114  # since the modulefinder is not able to look into the global area when coming from the local area, we force a second try
115  if parent and not r and self._localarea != '' and self._globalarea != '':
116  parent.__file__ = parent.__file__.replace(self._localarea,self._globalarea)
117  parent.__path__[0] = parent.__path__[0].replace(self._localarea,self._globalarea)
118  r = modulefinder.ModuleFinder.import_module(self,partnam,fqname,parent)
119 
120  if r is not None:
121  self._depgraph.setdefault(self._last_caller.__name__,{})[r.__name__] = 1
122  return r
123  def load_module(self, fqname, fp, pathname, (suffix, mode, type)):
124  r = modulefinder.ModuleFinder.load_module(self, fqname, fp, pathname, (suffix, mode, type))
125  if r is not None:
126  self._types[r.__name__] = type
127  return r
128 
129 
130 def transformIntoGraph(depgraph,toplevel):
131  packageDict = {}
132  # create the top level config
133  packageDict[toplevel] = Package(toplevel, top = True)
134 
135  # create package objects
136  for key, value in depgraph.iteritems():
137  if key.count(".") == 2 and key != toplevel:
138  packageDict[key] = Package(key)
139  for name in value.keys():
140  if name.count(".") == 2: packageDict[name] = Package(name)
141  # now create dependencies
142  for key, value in depgraph.iteritems():
143  if key.count(".") == 2 or key == toplevel:
144  package = packageDict[key]
145  package.dependencies = [packageDict[name] for name in value.keys() if name.count(".") == 2]
146 
147  # find and return the top level config
148  return packageDict[toplevel]
149 
150 
151 def getDependenciesFromPythonFile(filename,toplevelname,path):
152  modulefinder = mymf(path)
153  modulefinder.run_script(filename)
154  globalDependencyDict = modulefinder._depgraph
155  globalDependencyDict[toplevelname] = globalDependencyDict["__main__"]
156  return globalDependencyDict
157 
158 
159 def getImportTree(filename,path):
160  toplevelname = packageNameFromFilename(filename)
161  # get dependencies from given file
162  globalDependencyDict = getDependenciesFromPythonFile(filename,toplevelname,path)
163 
164  # transform this flat structure in a dependency tree
165  dependencyGraph = transformIntoGraph(globalDependencyDict,toplevelname)
166  return dependencyGraph
def transformIntoGraph
Definition: TreeCrawler.py:130
def getDependenciesFromPythonFile
Definition: TreeCrawler.py:151
def packageNameFromFilename
Definition: TreeCrawler.py:29
static std::string join(char **cmd)
Definition: RemoteFile.cc:18
list object
Definition: dbtoconf.py:77
def getImportTree
Definition: TreeCrawler.py:159
double split
Definition: MVATrainer.cc:139
How EventSelector::AcceptEvent() decides whether to accept an event for output otherwise it is excluding the probing of A single or multiple positive and the trigger will pass if any such matching triggers are PASS or EXCEPTION[A criterion thatmatches no triggers at all is detected and causes a throw.] A single negative with an expectation of appropriate bit checking in the decision and the trigger will pass if any such matching triggers are FAIL or EXCEPTION A wildcarded negative criterion that matches more than one trigger in the trigger list("!*","!HLTx*"if it matches 2 triggers or more) will accept the event if all the matching triggers are FAIL.It will reject the event if any of the triggers are PASS or EXCEPTION(this matches the behavior of"!*"before the partial wildcard feature was incorporated).Triggers which are in the READY state are completely ignored.(READY should never be returned since the trigger paths have been run