0001 # Copyright 2003, Grant T. Olson, see License.txt for details 0002 0003 import re, sys, os 0004 0005 class nsNode: 0006 PACKAGE = 1 0007 MODULE = 2 0008 CLASS = 3 0009 FUNCTION = 4 0010 VARIABLE = 5 0011 GLOBALREF = 6 0012 ROOT = 7 0013 RETURNS = 8 0014 PARAMS = 9 0015 DIRECTORY = 10 0016 0017 nsStringToType = { "P":PACKAGE, "M":MODULE, "C":CLASS, "F":FUNCTION,"V":VARIABLE, "G":GLOBALREF, "ROOT":ROOT, 0018 "RET":RETURNS, "PARAM":PARAMS, "DIRECTORY":DIRECTORY} 0019 nsTypeToString = { PACKAGE:"P", MODULE:"M", CLASS:"C", FUNCTION:"F", VARIABLE:"V", GLOBALREF:"G", ROOT:"ROOT", 0020 RETURNS:"RET", PARAMS:"PARAM", DIRECTORY:"DIRECTORY"} 0021 0022 splitRE = re.compile(r"\|([^:]+):([^\|\n]+)(.*)").match 0023 0024 baseHREF = "" 0025 def getPath(self): 0026 import os.path 0027 """ Returns the path in the filesystem """ 0028 if self.nsType == nsNode.PACKAGE or self.nsType == nsNode.DIRECTORY: 0029 if self.parent: 0030 return os.path.join(self.parent.getPath(), self.name) 0031 else: 0032 return self.name 0033 elif self.nsType == nsNode.MODULE: 0034 if self.parent: 0035 return os.path.join(self.parent.getPath(), self.name + ".py") 0036 else: 0037 return self.name + ".py" 0038 else: 0039 return "" 0040 0041 def splitString(self, string): 0042 """ 3-Tuple: (type, name, rest) """ 0043 return nsNode.splitRE(string).groups() 0044 0045 def getChildType(self, nsType): 0046 return [child for child in self.children if child.nsType == nsType] 0047 def getClasses(self): return self.getChildType(nsNode.CLASS) 0048 def getModules(self): return self.getChildType(nsNode.MODULE) 0049 def getVariables(self): return self.getChildType(nsNode.CLASS) 0050 def getPackages(self): return self.getChildType(nsNode.PACKAGE) 0051 def getFunctions(self): return self.getChildType(nsNode.FUNCTION) 0052 def getDirectories(self): return self.getChildType(nsNode.DIRECTORY) 0053 0054 def __init__(self, nsType = None, name = "", parentNode = None): 0055 if nsType: 0056 self.nsType = nsType 0057 else: 0058 self.nsType = nsNode.PACKAGE 0059 self.name = name 0060 self.parent = parentNode 0061 if parentNode: 0062 self.root = parentNode.root 0063 else: 0064 self.root = self 0065 self.children = [] 0066 0067 def findNode(self, nodeType, nodeName): 0068 """ 0069 Standard depth-first search 0070 Probably best for locating modules and packages 0071 """ 0072 if self.nsType == nodeType and self.name == nodeName: 0073 return self 0074 for child in self.children: 0075 tmpMatch = child.findNode(nodeType, nodeName) 0076 if tmpMatch: 0077 return tmpMatch 0078 return None 0079 0080 def hasChild(self, childNsType, childName): 0081 for child in self.children: 0082 if child.nsType == childNsType and child.name == childName: 0083 return 1 0084 return 0 0085 0086 def getChild(self, childNsType, childName): 0087 for child in self.children: 0088 if child.nsType == childNsType and child.name == childName: 0089 return child 0090 raise Exception("INVALID CHILD") 0091 0092 def getAnyChild(self, childName): 0093 for child in self.children: 0094 if child.name == childName: 0095 return child 0096 return None 0097 0098 def addChild(self, childNsType, childName): 0099 if self.hasChild(childNsType, childName): 0100 raise Exception("Can't add an existing child(%s %s) to %s" % 0101 (self.nsTypeToString[childNsType], childName, self)) 0102 0103 tmpChild = nsNode(childNsType, childName, self) 0104 self.children.append(tmpChild) 0105 return tmpChild 0106 0107 def addOrGetChild(self, childNsType, childName): 0108 """ Just like add, but it will return an existing child instead of throwing an error """ 0109 if self.hasChild(childNsType, childName): 0110 return self.getChild(childNsType, childName) 0111 else: 0112 tmpChild = nsNode(childNsType, childName, self) 0113 self.children.append(tmpChild) 0114 return tmpChild 0115 0116 def saveToStream(self, write=sys.stdout.write): 0117 write(str(self) + "\n") 0118 for child in self.children: 0119 child.saveToStream(write) 0120 0121 def addFullNode(self, rest): 0122 nsType, name, rest = self.splitString(rest) 0123 nsType = self.nsStringToType[nsType] 0124 tmpNode = self.root 0125 0126 if tmpNode.nsType != nsType or tmpNode.name != name: 0127 raise Exception ("Invalid Root Node") 0128 while rest: 0129 nsType, name, rest = self.splitString(rest) 0130 nsType = self.nsStringToType[nsType] 0131 if tmpNode.hasChild(nsType, name): 0132 tmpNode = tmpNode.getChild(nsType, name) 0133 else: 0134 tmpNode = tmpNode.addChild(nsType, name) 0135 0136 if not rest: 0137 break 0138 0139 def loadFromStream(self, readlines): 0140 for line in readlines(): 0141 self.addFullNode(line) 0142 0143 def __str__(self): 0144 if self.parent: 0145 return str(self.parent) + "|%s:%s" % (self.nsTypeToString[self.nsType], self.name) 0146 else: 0147 return "|%s:%s" % (self.nsTypeToString[self.nsType], self.name) 0148 0149 0150 nsNodeTree = None 0151 0152 0153 def loadTree(): 0154 """ This should be called to load the nodes""" 0155 global nsNodeTree 0156 if not nsNodeTree: 0157 import astProcess 0158 print "Building Index of Source(5-10 minutes)...", 0159 nsNodeTree = astProcess.makeTree() 0160 0161 def loadTreeFromFile(filename): 0162 """ 0163 Load preprocessed node file 0164 this is faster when you're debugging 0165 """ 0166 global nsNodeTree 0167 nsNodeTree = nsNode(nsNode.ROOT, "ROOT") 0168 f = file(filename) 0169 nsNodeTree.loadFromStream(f.readlines) 0170 f.close() 0171 0172 0173 0174 def moduleBreadthFirstSearch(nsName, searchList=None): 0175 if searchList == None: 0176 if not nsNodeTree: 0177 loadTree() #hopefully it's already loaded 0178 searchList = [nsNodeTree] 0179 while searchList: 0180 currentNode = searchList[0] 0181 searchList = searchList[1:] 0182 name = currentNode.name.split(os.sep)[-1] #strip path if it's there 0183 if currentNode.nsType in (nsNode.MODULE, nsNode.PACKAGE) and name == nsName: 0184 return currentNode 0185 else: 0186 if currentNode.nsType in (nsNode.ROOT, nsNode.DIRECTORY): 0187 #only these care about subpackages and directories 0188 #technically, no other types should have any subpackages or directories) 0189 searchList.extend(currentNode.getModules()) 0190 searchList.extend(currentNode.getPackages()) 0191 searchList.extend(currentNode.getDirectories()) 0192 0193 def getModuleNode(nsName, searchList = None): 0194 if not nsNodeTree: 0195 loadTree() #this should already be done, but better safe than sorry 0196 return moduleBreadthFirstSearch(nsName, searchList) 0197 #return nsNodeTree.findNode(nsType, nsName) 0198 0199 0200 def pathToNode(path): 0201 tmpNode = None 0202 if not nsNodeTree: 0203 loadTree() 0204 #locate starting dir first 0205 directories = nsNodeTree.getDirectories() 0206 dirLen = 0 0207 for directory in directories: 0208 if path.startswith(directory.name) and dirLen < len(directory.name): 0209 tmpNode = directory 0210 dirLen = len(directory.name) 0211 0212 if not tmpNode: return None 0213 0214 remainingPath = path[len(tmpNode.name):] 0215 if remainingPath.endswith(".py"): 0216 remainingPath = remainingPath[:-3] 0217 pathItems = [x for x in remainingPath.split(os.sep) if x] 0218 0219 for item in pathItems: 0220 for currentNode in tmpNode.children: 0221 name = currentNode.name.split(os.sep)[-1] #strip path if it's there 0222 if name == item: 0223 tmpNode = currentNode 0224 break 0225 tmpNode = None 0226 if not tmpNode: 0227 return None 0228 return tmpNode
Generated by PyXR 0.9.4