26 import sys, os, inspect, copy, struct, dis, imp
30 return ".".
join(name.replace(
"python/",
"").
replace(
".py",
"").
split(
"/")[-3:])
34 """ANSI escape display sequences"""
37 alternate =
"\033[32m"
39 backlight =
"\033[43m"
41 lessemphasis =
"\033[30m"
42 deemphasis =
"\033[1;30m"
59 self.
module = __import__(name,[],[],
"*")
62 print indent,
"+", Color.info, self.
name, Color.none
64 self.dependencies.sort(key =
lambda x: x.name)
68 """ recursive search for pattern in source files"""
71 for number, line
in enumerate(inspect.getsource(self.
module).splitlines()):
77 self.hit.number = number
78 self.hit.filename = filename
80 self.hit.stacks =
list()
81 result.append(self.
hit)
82 self.hit.stacks.append(copy.copy(_stack))
84 _stack.append(self.
name)
86 package.search(pattern,result)
91 class mymf(modulefinder.ModuleFinder):
99 modulefinder.ModuleFinder.__init__(self,*args,**kwargs)
100 def import_hook(self, name, caller=None, fromlist=None, level=-1):
104 return modulefinder.ModuleFinder.import_hook(self,name,caller,fromlist, level=level)
110 if partnam
in (
"os",
"unittest"):
113 r = modulefinder.ModuleFinder.import_module(self,partnam,fqname,parent)
118 r = modulefinder.ModuleFinder.import_module(self,partnam,fqname,parent)
121 self._depgraph.setdefault(self._last_caller.__name__,{})[r.__name__] = 1
123 def load_module(self, fqname, fp, pathname, (suffix, mode, type)):
124 r = modulefinder.ModuleFinder.load_module(self, fqname, fp, pathname, (suffix, mode, type))
126 self.
_types[r.__name__] = type
131 This is basically just the default opcode scanner from ModuleFinder, but extended to also
132 look for "process.load(<module>)' commands. Since the Process object might not necassarily
133 be called "process", it scans for a call to a "load" method with a single parameter on
134 *any* object. If one is found it checks if the parameter is a string that refers to a valid
135 python module in the local or global area. If it does, the scanner assumes this was a call
136 to a Process object and yields the module name.
137 It's not possible to scan first for Process object declarations to get the name of the
138 objects since often (e.g. for customisation functions) the object is passed to a function
141 The ModuleFinder.scan_opcodes_25 implementation this is based was taken from
142 https://hg.python.org/cpython/file/2.7/Lib/modulefinder.py#l364
148 consts = co.co_consts
149 LOAD_CONST = modulefinder.LOAD_CONST
150 IMPORT_NAME = modulefinder.IMPORT_NAME
151 STORE_OPS = modulefinder.STORE_OPS
152 HAVE_ARGUMENT = modulefinder.HAVE_ARGUMENT
153 LOAD_ATTR = chr(dis.opname.index(
'LOAD_ATTR'))
154 LOAD_NAME = chr(dis.opname.index(
'LOAD_NAME'))
155 CALL_FUNCTION = chr(dis.opname.index(
'CALL_FUNCTION'))
156 LOAD_LOAD_AND_IMPORT = LOAD_CONST + LOAD_CONST + IMPORT_NAME
159 indexOfLoadConst = names.index(
"load")
162 loadMethodOpcodes = LOAD_ATTR+struct.pack(
'<H',indexOfLoadConst)
165 loadMethodOpcodes=
None
171 if loadMethodOpcodes!=
None and len(code)>=9 :
172 if code[:3]==loadMethodOpcodes :
177 if code[6]==CALL_FUNCTION :
181 indexInTable=
unpack(
'<H',code[4:6])[0]
182 if code[3]==LOAD_CONST :
184 loadMethodArgument=consts[indexInTable]
189 loadMethodArgument = loadMethodArgument.replace(
"/",
".")
197 for subModule
in loadMethodArgument.split(
".") :
198 moduleInfo=imp.find_module( subModule, parentFilename )
199 parentFilename=[moduleInfo[1]]
201 yield "import", (
None, loadMethodArgument)
205 for subModule
in loadMethodArgument.split(
".") :
206 moduleInfo=imp.find_module( subModule, parentFilename )
207 parentFilename=[moduleInfo[1]]
209 yield "import", (
None, loadMethodArgument)
210 except Exception
as error:
216 elif code[3]==LOAD_NAME :
220 print "Unable to determine the value of variable '"+names[indexInTable]+
"' to see if it is a proces.load(...) statement in file "+co.co_filename
226 oparg, =
unpack(
'<H', code[1:3])
227 yield "store", (names[oparg],)
230 if code[:9:3] == LOAD_LOAD_AND_IMPORT:
231 oparg_1, oparg_2, oparg_3 =
unpack(
'<xHxHxH', code[:9])
232 level = consts[oparg_1]
234 yield "import", (consts[oparg_2], names[oparg_3])
236 yield "absolute_import", (consts[oparg_2], names[oparg_3])
238 yield "relative_import", (level, consts[oparg_2], names[oparg_3])
241 if c >= HAVE_ARGUMENT:
247 if currentStack
is None : currentStack=[]
249 duplicateIndex=currentStack.index( node )
251 print "Removing recursive loop in:"
252 for index
in xrange(duplicateIndex,len(currentStack)) :
253 print " ",currentStack[index].name,
"-->"
255 currentStack[-1].dependencies.remove(node)
258 currentStack.append( node )
259 for subnode
in node.dependencies :
265 packageDict[toplevel] =
Package(toplevel, top =
True)
268 for key, value
in depgraph.iteritems():
269 if key.count(
".") == 2
and key != toplevel:
270 packageDict[key] =
Package(key)
271 for name
in value.keys():
272 if name.count(
".") == 2: packageDict[name] =
Package(name)
274 for key, value
in depgraph.iteritems():
275 if key.count(
".") == 2
or key == toplevel:
276 package = packageDict[key]
277 package.dependencies = [packageDict[name]
for name
in value.keys()
if name.count(
".") == 2]
281 return packageDict[toplevel]
285 modulefinder =
mymf(path)
286 modulefinder.run_script(filename)
287 globalDependencyDict = modulefinder._depgraph
288 globalDependencyDict[toplevelname] = globalDependencyDict[
"__main__"]
289 return globalDependencyDict
299 return dependencyGraph
def getDependenciesFromPythonFile
def packageNameFromFilename
static std::string join(char **cmd)
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