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"
50 class Package(object):
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
124 (suffix, mode, type) = aux_info
125 r = modulefinder.ModuleFinder.load_module(self, fqname, fp, pathname, (suffix, mode, type))
127 self.
_types[r.__name__] = type
132 This is basically just the default opcode scanner from ModuleFinder, but extended to also
133 look for "process.load(<module>)' commands. Since the Process object might not necassarily
134 be called "process", it scans for a call to a "load" method with a single parameter on
135 *any* object. If one is found it checks if the parameter is a string that refers to a valid
136 python module in the local or global area. If it does, the scanner assumes this was a call
137 to a Process object and yields the module name.
138 It's not possible to scan first for Process object declarations to get the name of the
139 objects since often (e.g. for customisation functions) the object is passed to a function
142 The ModuleFinder.scan_opcodes_25 implementation this is based was taken from
143 https://hg.python.org/cpython/file/2.7/Lib/modulefinder.py#l364
149 consts = co.co_consts
150 LOAD_CONST = modulefinder.LOAD_CONST
151 IMPORT_NAME = modulefinder.IMPORT_NAME
152 STORE_OPS = modulefinder.STORE_OPS
153 HAVE_ARGUMENT = modulefinder.HAVE_ARGUMENT
154 LOAD_ATTR = chr(dis.opname.index(
'LOAD_ATTR'))
155 LOAD_NAME = chr(dis.opname.index(
'LOAD_NAME'))
156 CALL_FUNCTION = chr(dis.opname.index(
'CALL_FUNCTION'))
157 LOAD_LOAD_AND_IMPORT = LOAD_CONST + LOAD_CONST + IMPORT_NAME
160 indexOfLoadConst = names.index(
"load")
163 loadMethodOpcodes = LOAD_ATTR+struct.pack(
'<H',indexOfLoadConst)
166 loadMethodOpcodes=
None
172 if loadMethodOpcodes!=
None and len(code)>=9 :
173 if code[:3]==loadMethodOpcodes :
178 if code[6]==CALL_FUNCTION :
182 indexInTable=
unpack(
'<H',code[4:6])[0]
183 if code[3]==LOAD_CONST :
185 loadMethodArgument=consts[indexInTable]
190 loadMethodArgument = loadMethodArgument.replace(
"/",
".")
198 for subModule
in loadMethodArgument.split(
".") :
199 moduleInfo=imp.find_module( subModule, parentFilename )
200 parentFilename=[moduleInfo[1]]
202 yield "import", (
None, loadMethodArgument)
206 for subModule
in loadMethodArgument.split(
".") :
207 moduleInfo=imp.find_module( subModule, parentFilename )
208 parentFilename=[moduleInfo[1]]
210 yield "import", (
None, loadMethodArgument)
211 except Exception
as error:
217 elif code[3]==LOAD_NAME :
221 print "Unable to determine the value of variable '"+names[indexInTable]+
"' to see if it is a proces.load(...) statement in file "+co.co_filename
227 oparg, =
unpack(
'<H', code[1:3])
228 yield "store", (names[oparg],)
231 if code[:9:3] == LOAD_LOAD_AND_IMPORT:
232 oparg_1, oparg_2, oparg_3 =
unpack(
'<xHxHxH', code[:9])
233 level = consts[oparg_1]
235 yield "import", (consts[oparg_2], names[oparg_3])
237 yield "absolute_import", (consts[oparg_2], names[oparg_3])
239 yield "relative_import", (level, consts[oparg_2], names[oparg_3])
242 if c >= HAVE_ARGUMENT:
248 if currentStack
is None : currentStack=[]
250 duplicateIndex=currentStack.index( node )
252 print "Removing recursive loop in:"
253 for index
in xrange(duplicateIndex,len(currentStack)) :
254 print " ",currentStack[index].name,
"-->"
256 currentStack[-1].dependencies.remove(node)
259 currentStack.append( node )
260 for subnode
in node.dependencies :
266 packageDict[toplevel] =
Package(toplevel, top =
True)
269 for key, value
in depgraph.iteritems():
270 if key.count(
".") == 2
and key != toplevel:
271 packageDict[key] =
Package(key)
272 for name
in value.keys():
273 if name.count(
".") == 2: packageDict[name] =
Package(name)
275 for key, value
in depgraph.iteritems():
276 if key.count(
".") == 2
or key == toplevel:
277 package = packageDict[key]
278 package.dependencies = [packageDict[name]
for name
in value.keys()
if name.count(
".") == 2]
282 return packageDict[toplevel]
286 modulefinder =
mymf(path)
287 modulefinder.run_script(filename)
288 globalDependencyDict = modulefinder._depgraph
289 globalDependencyDict[toplevelname] = globalDependencyDict[
"__main__"]
290 return globalDependencyDict
300 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