00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 import sys, os, inspect, copy
00027 import modulefinder
00028
00029 def packageNameFromFilename(name):
00030 return ".".join(name.replace("python/","").replace(".py","").split("/")[-3:])
00031
00032
00033 class Color:
00034 """ANSI escape display sequences"""
00035 info = "\033[1;34m"
00036 hilight = "\033[31m"
00037 alternate = "\033[32m"
00038 extra = "\033[33m"
00039 backlight = "\033[43m"
00040 underline = "\033[4m"
00041 lessemphasis = "\033[30m"
00042 deemphasis = "\033[1;30m"
00043 none = "\033[0m"
00044
00045 _stack = []
00046
00047 class SearchHit:
00048 pass
00049
00050 class Package(object):
00051 def __init__(self,name,top=False):
00052 self.name = name
00053 self.dependencies = []
00054 self.searched = False
00055 self.stack = []
00056 if top:
00057 self.module = None
00058 else:
00059 self.module = __import__(name,[],[],"*")
00060 def dump(self,level):
00061 indent = " " * level
00062 print indent, "+", Color.info, self.name, Color.none
00063
00064 self.dependencies.sort(key = lambda x: x.name)
00065 for package in self.dependencies:
00066 package.dump(level+1)
00067 def search(self,pattern,result):
00068 """ recursive search for pattern in source files"""
00069
00070 if self.module:
00071 for number, line in enumerate(inspect.getsource(self.module).splitlines()):
00072 if pattern in line:
00073 filename = packageNameFromFilename(inspect.getsourcefile(self.module))
00074 if not self.searched:
00075
00076 self.hit = SearchHit()
00077 self.hit.number = number
00078 self.hit.filename = filename
00079 self.hit.line = line
00080 self.hit.stacks = list()
00081 result.append(self.hit)
00082 self.hit.stacks.append(copy.copy(_stack))
00083
00084 _stack.append(self.name)
00085 for package in self.dependencies:
00086 package.search(pattern,result)
00087 _stack.pop()
00088 self.searched = True
00089
00090
00091 class mymf(modulefinder.ModuleFinder):
00092 def __init__(self,*args,**kwargs):
00093 self._depgraph = {}
00094 self._types = {}
00095 self._last_caller = None
00096
00097 self._localarea = os.path.expandvars('$CMSSW_BASE')
00098 self._globalarea = os.path.expandvars('$CMSSW_RELEASE_BASE')
00099 modulefinder.ModuleFinder.__init__(self,*args,**kwargs)
00100 def import_hook(self, name, caller=None, fromlist=None, level=-1):
00101 old_last_caller = self._last_caller
00102 try:
00103 self._last_caller = caller
00104 return modulefinder.ModuleFinder.import_hook(self,name,caller,fromlist, level=level)
00105 finally:
00106 self._last_caller = old_last_caller
00107
00108 def import_module(self,partnam,fqname,parent):
00109
00110 if partnam in ("FWCore","os"):
00111 r = None
00112 else:
00113 r = modulefinder.ModuleFinder.import_module(self,partnam,fqname,parent)
00114
00115 if parent and not r and self._localarea != '' and self._globalarea != '':
00116 parent.__file__ = parent.__file__.replace(self._localarea,self._globalarea)
00117 parent.__path__[0] = parent.__path__[0].replace(self._localarea,self._globalarea)
00118 r = modulefinder.ModuleFinder.import_module(self,partnam,fqname,parent)
00119
00120 if r is not None:
00121 self._depgraph.setdefault(self._last_caller.__name__,{})[r.__name__] = 1
00122 return r
00123 def load_module(self, fqname, fp, pathname, (suffix, mode, type)):
00124 r = modulefinder.ModuleFinder.load_module(self, fqname, fp, pathname, (suffix, mode, type))
00125 if r is not None:
00126 self._types[r.__name__] = type
00127 return r
00128
00129
00130 def transformIntoGraph(depgraph,toplevel):
00131 packageDict = {}
00132
00133 packageDict[toplevel] = Package(toplevel, top = True)
00134
00135
00136 for key, value in depgraph.iteritems():
00137 if key.count(".") == 2 and key != toplevel:
00138 packageDict[key] = Package(key)
00139 for name in value.keys():
00140 if name.count(".") == 2: packageDict[name] = Package(name)
00141
00142 for key, value in depgraph.iteritems():
00143 if key.count(".") == 2 or key == toplevel:
00144 package = packageDict[key]
00145 package.dependencies = [packageDict[name] for name in value.keys() if name.count(".") == 2]
00146
00147
00148 return packageDict[toplevel]
00149
00150
00151 def getDependenciesFromPythonFile(filename,toplevelname,path):
00152 modulefinder = mymf(path)
00153 modulefinder.run_script(filename)
00154 globalDependencyDict = modulefinder._depgraph
00155 globalDependencyDict[toplevelname] = globalDependencyDict["__main__"]
00156 return globalDependencyDict
00157
00158
00159 def getImportTree(filename,path):
00160 toplevelname = packageNameFromFilename(filename)
00161
00162 globalDependencyDict = getDependenciesFromPythonFile(filename,toplevelname,path)
00163
00164
00165 dependencyGraph = transformIntoGraph(globalDependencyDict,toplevelname)
00166 return dependencyGraph