0001 # Copyright 2003, Grant T. Olson, see License.txt for details 0002 0003 from __future__ import generators 0004 from astCrawler import astCrawler 0005 from nsNode import nsNode 0006 import re 0007 import os 0008 import stat 0009 import os.path 0010 import sys 0011 import symbol 0012 from misc import pythonpath, skipInvalidFiles, openPythonFile, InvalidSourceError 0013 import traceback 0014 from parser import ParserError 0015 0016 class astProcess(astCrawler): 0017 """ 0018 Tries to extract classes, functions, and vars from files so we can use the info later 0019 """ 0020 def __init__(self, text, nsTree=nsNode(nsNode.ROOT, "XXX"), debugOutput=sys.stdout): 0021 astCrawler.__init__(self, text) 0022 self.nsTree = nsTree 0023 self.currentNode = nsTree 0024 self.debugOutput = debugOutput 0025 0026 debug = 0 0027 def debugPrint(self, text): 0028 if self.debug: 0029 self.debugOutput.write("%s\n" % text) 0030 0031 def registerHandlers(self): 0032 self.handlers[symbol.funcdef] = self.functionHandler 0033 self.handlers[symbol.classdef] = self.classHandler 0034 #self.handlers[symbol.expr_stmt] = self.expressionHandler 0035 0036 def expressionHandler(self, params): 0037 lhs = params[0] 0038 assignType = params[1] 0039 rhs = params [2:] 0040 varName = "" 0041 if lhs[0] == token.NAME: 0042 varName = lhs[1] 0043 else: 0044 varName = str(lhs) 0045 self.debugPrint("NAMESPACE: %s, VARIABLE ASSIGNMENT lsh: %s type: %s rhs: %s" % (self.currentNode, lhs, assignType, rhs)) 0046 if not self.currentNode.hasChild(nsNode.VARIABLE, varName): 0047 self.currentNode.addChild(nsNode.VARIABLE, varName) 0048 0049 def functionHandler(self, params): 0050 defConstant = params[0] 0051 funcName = params[1][1] 0052 parameters = params[2] 0053 colonConst = params[3] 0054 suite = params[4] 0055 0056 self.debugPrint("NAMESPACE: %s, FUNCTION => %s, PARAMS %s" % (self.currentNode, funcName, parameters)) 0057 self.currentNode = self.currentNode.addOrGetChild(nsNode.FUNCTION, funcName) 0058 self.process(suite) 0059 self.currentNode = self.currentNode.parent 0060 0061 def classHandler(self, params): 0062 classConst = params[0] 0063 className = params[1][1] 0064 rest = params[2:] 0065 y = 2 0066 while params[y][1] != ":": 0067 y += 1 0068 suite = params[y+1] 0069 self.debugPrint("NAMESPACE: %s => CLASS: %s" % (self.currentNode, className)) 0070 self.currentNode = self.currentNode.addOrGetChild(nsNode.CLASS, className) 0071 self.debugPrint("CURRENT NODE %s" % self.currentNode) 0072 self.process(suite) 0073 self.currentNode = self.currentNode.parent 0074 0075 def processFileList(filelist, node=nsNode(nsNode.ROOT, "ROOT")): 0076 for module in filelist: 0077 sys.stdout.write(".");sys.stdout.flush(); #print , adds a space 0078 moduleName = os.path.split(module)[-1] # strip path 0079 moduleName = moduleName[:-3] # strip .py 0080 0081 f = openPythonFile(module) 0082 txt = f.read() 0083 f.close() 0084 child = node.addChild(nsNode.MODULE,moduleName) 0085 0086 try: 0087 tmpProcess = astProcess(txt + "\n\n", child) 0088 except KeyboardInterrupt: 0089 raise 0090 except: 0091 if sys.exc_info()[0] not in (ParserError, SyntaxError): 0092 raise 0093 msg = "\nUnable to process file %s: Doesn't contain vaild python source: " % module 0094 if skipInvalidFiles: 0095 print >> sys.stderr, msg + "Skipping\n" 0096 else: 0097 raise InvalidSourceError(msg + "\nSet skipInvalidFiles=1 in settings.cfg to continue on error\n") 0098 else: 0099 tmpProcess.debug = 0 0100 tmpProcess.process() 0101 0102 def processDir(directoryName, node): 0103 def sourceFiles(currentPath, files): 0104 return [os.path.join(currentPath, x) for x in files if x[-3:] == ".py"] 0105 def packages(currentPath, files): 0106 for aFile in files: 0107 fileName = os.path.join(currentPath, aFile) 0108 mode = os.stat(fileName)[stat.ST_MODE] 0109 if stat.S_ISDIR(mode): 0110 if os.path.exists( os.path.join(fileName, "__init__.py")): 0111 yield fileName 0112 0113 if os.path.exists(directoryName) and os.path.isdir(directoryName): 0114 dirFiles = os.listdir(directoryName) 0115 else: 0116 print >> sys.stderr, "\nDirectory '%s' does not exist, skipping" % directoryName 0117 dirFiles = [] 0118 processFileList(sourceFiles(directoryName, dirFiles), node) 0119 for package in packages(directoryName, dirFiles): 0120 processDir(package, node.addChild(nsNode.PACKAGE, package)) 0121 0122 0123 0124 def makeTree(paths=pythonpath): 0125 rootNode = nsNode(nsNode.ROOT, "ROOT") 0126 for dir in paths: 0127 processDir(dir, rootNode.addChild(nsNode.DIRECTORY, dir)) 0128 print 0129 return rootNode 0130 0131 if __name__=='__main__': 0132 import sys 0133 if len(sys.argv) != 2: 0134 print "Usage: python astProcess.py cachefile.dat" 0135 else: 0136 x = makeTree() 0137 sys.argv 0138 f = file(sys.argv[1], "w") 0139 x.saveToStream(f.write) 0140 f.close() 0141 0142 0143
Generated by PyXR 0.9.4