diff -r c1f9435bb645 -r 32a30f609530 scripts/check_includes.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/check_includes.py Thu Nov 27 23:41:08 2008 +0000 @@ -0,0 +1,194 @@ +#!/usr/bin/env python + +import sys + +import cPickle +import os +import graph + + +ROOTDIR = "soc" + + +def parseFile(file_name): + if os.path.exists("imports.dat"): + log = open("imports.dat", "r") + all_imports = cPickle.load(log) + log.close() + else: + all_imports = {} + + if file_name in all_imports: + print "Overwriting previous data on '%s'." % file_name + + imports = [] + + file = open(file_name) + + for line in file: + if line.lstrip().startswith('import soc'): + splitline = line[:-1].split(' ') + mod = splitline[1] + imports.append(mod) + + if line.lstrip().startswith('from soc'): + splitline = line[:-1].split(' ') + mod = splitline[1] + '.' + splitline[3] + imports.append(mod) + + for idx, imp in enumerate(imports): + if imp in set(imports[idx+1:]): + sys.stderr.write("Warning: file '%s' has a redundant import: '%s'.\n" % (file_name, imp)) + + if file_name.endswith("__init__.py"): + normalized = file_name[:-12].replace('/', '.') + else: + normalized = file_name[:-3].replace('/', '.') + + print "Writing imports for file %s (%s)." % (file_name, normalized) + all_imports[normalized] = imports + + log = open("imports.dat", "w") + cPickle.dump(all_imports, log) + log.close() + + return 0 + + +def buildGraph(): + if not os.path.exists("imports.dat"): + sys.stderr.write("Missing imports.dat file, run 'build' first\n") + return + + log = open("imports.dat", "r") + all_imports = cPickle.load(log) + + gr = graph.digraph() + + gr.add_nodes(all_imports.keys()) + + for file_name, imports in all_imports.iteritems(): + for imp in imports: + gr.add_edge(file_name, imp) + + return gr + + +def showGraph(gr): + for node in gr: + print "%s: " % node + for edge in gr[node]: + print "\t%s" % edge + + return 0 + + +def getParents(gst, target): + parents = [] + current = target + + while True: + for node in gst: + if current in gst[node]: + parents.append(node) + current = node + break + else: + break + + return parents + + +def pathFrom(parents, first, target): + idx = parents.index(first) + path = parents[idx::-1] + return [target] + path + [target] + + +def findCycle(gr, gst, target): + parents = getParents(gst, target) + cycles = [] + + for node in gr[target]: + if node in parents: + cycles.append(pathFrom(parents, node, target)) + + return cycles + + +def findCycles(gr): + st, pre, post = gr.depth_first_search() + gst = graph.digraph() + gst.add_spanning_tree(st) + + cycles = [] + + for node in gr: + cycles += findCycle(gr, gst, node) + + return cycles + + +def drawGraph(gr): + st, pre, post = gr.depth_first_search() + gst = graph.digraph() + gst.add_spanning_tree(st) + + sys.path.append('/usr/lib/graphviz/python/') + import gv + dot = gst.write(fmt='dot') + gvv = gv.readstring(dot) + gv.layout(gvv,'dot') + gv.render(gvv,'png','imports.png') + + +def accumulate(arg, dirname, fnames): + for fname in fnames: + if not fname.endswith(".py"): + continue + + arg.append(os.path.join(dirname, fname)) + + +def main(args): + if len(args) != 1: + print "Supported options: 'print', 'build', 'find', and 'draw'." + return -1 + + action = args[0] + + if action == "build": + fnames = [] + os.path.walk(ROOTDIR, accumulate, fnames) + + for fname in fnames: + parseFile(fname) + + print "Done parsing." + return 0 + + gr = buildGraph() + if not gr: + return 1 + + if action == "show": + return showGraph(gr) + + if action == "draw": + return drawGraph(gr) + + if action == "find": + cycles = findCycles(gr) + for cycle in cycles: + print cycle + return 0 + + print "Unknown option." + return -1 + + +if __name__ == '__main__': + import sys + os.chdir("../app") + res = main(sys.argv[1:]) + sys.exit(0)