def _subchainAndResolutionOrNone(self, pyObject, chain): if PyforaInspect.isfunction(pyObject): return self._lookupChainInFunction(pyObject, chain) if PyforaInspect.isclass(pyObject): return self._lookupChainInClass(pyObject, chain) return None
def _subchainAndResolutionOrNone(self, pyObject, pyAst, chainWithPosition): if PyforaInspect.isfunction(pyObject): return self._lookupChainInFunction(pyObject, chainWithPosition) if PyforaInspect.isclass(pyObject): return self._lookupChainInClass(pyObject, pyAst, chainWithPosition) return None
def _lookupChainInFunctionOrClass(self, pyObject, pyAst, chainWithPosition): if PyforaInspect.isfunction(pyObject): return self._lookupChainInFunction(pyObject, chainWithPosition) if PyforaInspect.isclass(pyObject): return self._lookupChainInClass(pyObject, pyAst, chainWithPosition) assert False, "should only have functions or classes here"
def getSourceFilenameAndText(pyObject): try: sourceFile = PyforaInspect.getsourcefile(pyObject) except TypeError as e: raise Exceptions.CantGetSourceTextError(e.message) if sourceFile not in sourceFileCache_: sourceFileCache_[sourceFile] = "".join(PyforaInspect.getlines(sourceFile)) return sourceFileCache_[sourceFile], sourceFile
def _subchainAndResolutionOrNone(self, pyObject, chainWithPosition): if PyforaInspect.isfunction(pyObject): return self._lookupChainInFunction(pyObject, chainWithPosition) if PyforaInspect.isclass(pyObject): return self._lookupChainInClass(pyObject, chainWithPosition) raise Exceptions.PythonToForaConversionError( "don't know how to resolve %s in %s (line:%s)" % (chainWithPosition.var, pyObject, chainWithPosition.pos.lineno))
def _subchainAndResolutionOrNone(self, pyObject, chainWithPosition): if PyforaInspect.isfunction(pyObject): return self._lookupChainInFunction(pyObject, chainWithPosition) if PyforaInspect.isclass(pyObject): return self._lookupChainInClass(pyObject, chainWithPosition) raise Exceptions.PythonToForaConversionError( "don't know how to resolve %s in %s (line:%s)" % (chainWithPosition.var, pyObject, chainWithPosition.pos.lineno) )
def getSourceFilenameAndText(pyObject): try: sourceFile = PyforaInspect.getsourcefile(pyObject) except TypeError as e: raise Exceptions.CantGetSourceTextError(e.message) if sourceFile not in sourceFileCache_: sourceFileCache_[sourceFile] = "".join( PyforaInspect.getlines(sourceFile)) return sourceFileCache_[sourceFile], sourceFile
def _objectToWalkInsteadOrNone(self, pyObject): """Takes a python object and returns another python object or None. If the given python object belongs to the PyObjectNode hierarchy, return None, otherwise build or fetch from a cache the appropriate PyObjectNode to walk, and return it. """ tr = None if isinstance(pyObject, PyObjectNodes.PyObjectNode): return tr # If this is the common path, we may want to pull it to the call-site(s) if isinstance(pyObject, RemotePythonObject.RemotePythonObject): tr = PyObjectNodes.RemotePythonObject(pyObject) elif isinstance( pyObject, Exception ) and pyObject.__class__ in NamedSingletons.pythonSingletonToName: tr = PyObjectNodes.BuiltinExceptionInstance( pyObject, NamedSingletons.pythonSingletonToName[pyObject.__class__], pyObject.args) elif isinstance( pyObject, (type, type(isinstance) )) and pyObject in NamedSingletons.pythonSingletonToName: tr = PyObjectNodes.NamedSingleton( pyObject, NamedSingletons.pythonSingletonToName[pyObject]) elif isinstance(pyObject, PyforaWithBlock.PyforaWithBlock): tr = self._pyObjectNodeForWithBlock(pyObject) elif id(pyObject) in self._convertedObjectCache: tr = self._convertedObjectCache[id(pyObject)][1] elif self.purePythonClassMapping.canMap(pyObject): pureInstance = self.purePythonClassMapping.mappableInstanceToPure( pyObject) self._convertedObjectCache[id(pyObject)] = (pyObject, pureInstance) tr = pureInstance elif isinstance(pyObject, tuple): tr = PyObjectNodes.Tuple(pyObject) elif isinstance(pyObject, list): tr = PyObjectNodes.List(pyObject) elif isinstance(pyObject, dict): tr = PyObjectNodes.Dict(pyObject) elif _isPrimitive(pyObject): tr = PyObjectNodes.Primitive(pyObject) elif PyforaInspect.isfunction(pyObject): tr = self._pyObjectNodeForFunction(pyObject) elif PyforaInspect.isclass(pyObject): tr = self._pyObjectNodeForClass(pyObject) elif isClassInstance(pyObject): tr = self._classInstanceDescriptionFromClassInstance(pyObject) return tr
def test_pyforaInspect_twoClassesOneName(self): class C2: def fC1(self): return 0 def f2(): class C2: def fC2(self): return 1 return C2 with self.assertRaises(PyforaInspect.PyforaInspectError) : PyforaInspect.getsourcelines(f2()().__class__)
def test_pyforaInspect_twoClassesOneName(self): class C2: def fC1(self): return 0 def f2(): class C2: def fC2(self): return 1 return C2 with self.assertRaises(PyforaInspect.PyforaInspectError): PyforaInspect.getsourcelines(f2()().__class__)
def __enter__(self): self.frame = PyforaInspect.currentframe(1) sourceFileName, lineNumber, _, _, _ = PyforaInspect.getframeinfo(self.frame) self.sourceFileName = sourceFileName self.lineNumber = lineNumber self.sourceText = "".join(PyforaInspect.getlines(self.sourceFileName)) # Seems to "turn on" tracing, otherwise setting # frame.f_trace seems to have no effect # doesn't seem to have any effects outside of this with context. sys.settrace(lambda *args, **keys: None) self.frame.f_trace = self.trace
def populateModuleMembers(self, path): res = {} module = self.moduleForFile(path) for leafItemName in module.__dict__: leafItemValue = module.__dict__[leafItemName] if PyforaInspect.isclass(leafItemValue) or PyforaInspect.isfunction(leafItemValue): try: _, lineNumber = PyforaInspect.findsource(leafItemValue) res[lineNumber+1] = leafItemValue except: pass self.moduleClassesAndFunctionsByPath[path] = res
def test_pyforaInspect_twoNestedClasses(self): def f1(): class C1: def fC1(self): return 0 return C1 def f2(): class C1: def fC2(self): return 1 return C1 with self.assertRaises(PyforaInspect.PyforaInspectError) : PyforaInspect.getsourcelines(f1()().__class__)
def renderTraceback(trace): res = [] for tb in trace: if isinstance(tb["path"],tuple): path = tb["path"] if path[0] == "ModuleImporter": path = os.path.join(_pyforaRoot, *path[1:]) + ".fora" else: path = path[0] else: path = os.path.abspath(tb["path"]) if 'range' in tb: lineNumber = tb['range']['start']['line'] else: lineNumber = tb["line"] from pyfora.pyAst.PyAstUtil import findEnclosingFunctionName, getAstFromFilePath inFunction = findEnclosingFunctionName( getAstFromFilePath(path), lineNumber ) if path.endswith(".py") else None if inFunction is not None: res.append(' File "%s", line %s, in %s' % (path, lineNumber, inFunction)) else: res.append(' File "%s", line %s' % (path, lineNumber)) lines = PyforaInspect.getlines(os.path.abspath(path)) if lines is not None and lineNumber >= 1 and lineNumber <= len(lines): res.append(" " + lines[lineNumber-1][:-1].lstrip()) return "\n".join(res)
def getSourceFilenameAndText(pyObject): try: sourceFile = PyforaInspect.getsourcefile(pyObject) except TypeError as e: raise Exceptions.CantGetSourceTextError(e.message) linesOrNone = PyforaInspect.getlines(sourceFile) if linesOrNone is None: raise Exceptions.CantGetSourceTextError( "can't get source lines for file %s" % sourceFile) if sourceFile not in sourceFileCache_: sourceFileCache_[sourceFile] = "".join(linesOrNone) return sourceFileCache_[sourceFile], sourceFile
def computeSubchainAndTerminalValueAlongModules(self, rootValue, chainWithPosition): """ Return a ResultionResult or raise a PythonToForaConversionError """ ix = 1 chain = chainWithPosition.var position = chainWithPosition.pos subchain, terminalValue = chain[:ix], rootValue while PyforaInspect.ismodule( terminalValue) and self.terminal_value_filter(terminalValue): if ix >= len(chain): #we're terminating at a module terminalValue = Unconvertible(terminalValue) break if not hasattr(terminalValue, chain[ix]): raise Exceptions.PythonToForaConversionError( "Module %s has no member %s" % (str(terminalValue), chain[ix])) terminalValue = getattr(terminalValue, chain[ix]) ix += 1 subchain = chain[:ix] return ResolutionResult.resolution(subchain=subchain, resolution=terminalValue, position=position)
def renderTraceback(trace): res = [] for tb in trace: if isinstance(tb["path"], tuple): path = tb["path"] if path[0] == "ModuleImporter": path = os.path.join(_pyforaRoot, *path[1:]) + ".fora" else: path = path[0] else: path = os.path.abspath(tb["path"]) if 'range' in tb: lineNumber = tb['range']['start']['line'] else: lineNumber = tb["line"] from pyfora.pyAst.PyAstUtil import findEnclosingFunctionName, getAstFromFilePath inFunction = findEnclosingFunctionName( getAstFromFilePath(path), lineNumber) if path.endswith(".py") else None if inFunction is not None: res.append(' File "%s", line %s, in %s' % (path, lineNumber, inFunction)) else: res.append(' File "%s", line %s' % (path, lineNumber)) lines = PyforaInspect.getlines(path) if lines is not None and lineNumber >= 1 and lineNumber <= len(lines): res.append(" " + lines[lineNumber - 1][:-1].lstrip()) return "\n".join(res)
def getSourceLines(pyObject): try: tr = PyforaInspect.getsourcelines(pyObject) except (TypeError, IOError) as e: raise Exceptions.CantGetSourceTextError( e.message), None, sys.exc_info()[2] return tr
def populateModuleMembers(self, path): if path in self.moduleClassesAndFunctionsByPath: return res = self.moduleClassesAndFunctionsByPath[path] = {} module = self.moduleForFile(path) if module is not None and self.canPopulateForPath(path): for leafItemName in module.__dict__: leafItemValue = module.__dict__[leafItemName] if PyforaInspect.isclass( leafItemValue) or PyforaInspect.isfunction( leafItemValue): try: sourcePath = PyforaInspect.getsourcefile(leafItemValue) if sourcePath is not None: if os.path.samefile(path, sourcePath): _, lineNumber = PyforaInspect.findsource( leafItemValue) lineNumberToUse = lineNumber + 1 if lineNumberToUse in res and res[ lineNumberToUse] is not leafItemValue: raise Exceptions.ForaToPythonConversionError( ("PythonObjectRehydratorHelpers got a line number collision at lineNumber %s" ", between %s and %s"), lineNumberToUse, leafItemValue, res[lineNumber + 1]) res[lineNumberToUse] = leafItemValue else: self.populateModuleMembers(sourcePath) except Exceptions.ForaToPythonConversionError: raise except PyforaInspect.PyforaInspectError: pass except IOError: #this gets raised when PyforaInspect can't find a file it needs pass except Exception as e: logging.critical( "PyforaInspect threw an exception: %s. tb = %s", e, traceback.format_exc())
def test_class_line_number_collision(self): from ufora.FORA.python.PurePython.testModules.same_line_number.A import A from ufora.FORA.python.PurePython.testModules.same_line_number.A import B line_number_of_class_A_definition = PyforaInspect.getsourcelines(A)[1] line_number_of_class_B_definition = PyforaInspect.getsourcelines(B)[1] self.assertEqual(line_number_of_class_A_definition, line_number_of_class_B_definition) with self.create_executor() as executor: x = 99999 with executor.remotely.downloadAll(): a = A(99999) self.assertIsInstance(a, A) self.assertEqual(a.__dict__, A(x).__dict__)
def test_pyforaInspect_twoClassestwoNames(self): def f1(): class C3a: def fC1(self): return 0 return C3a def f2(): class C3b: def fC2(self): return 1 return C3b self.assertNotEqual( PyforaInspect.getsourcelines(f1()().__class__), PyforaInspect.getsourcelines(f2()().__class__) )
def test_pyforaInspect_twoClassestwoNames(self): def f1(): class C3a: def fC1(self): return 0 return C3a def f2(): class C3b: def fC2(self): return 1 return C3b self.assertNotEqual(PyforaInspect.getsourcelines(f1()().__class__), PyforaInspect.getsourcelines(f2()().__class__))
def _objectToWalkInsteadOrNone(self, pyObject): """Takes a python object and returns another python object or None. If the given python object belongs to the PyObjectNode hierarchy, return None, otherwise build or fetch from a cache the appropriate PyObjectNode to walk, and return it. """ tr = None if isinstance(pyObject, PyObjectNodes.PyObjectNode): return tr # If this is the common path, we may want to pull it to the call-site(s) if isinstance(pyObject, RemotePythonObject.RemotePythonObject): tr = PyObjectNodes.RemotePythonObject(pyObject) elif isinstance(pyObject, Exception) and pyObject.__class__ in NamedSingletons.pythonSingletonToName: tr = PyObjectNodes.BuiltinExceptionInstance( pyObject, NamedSingletons.pythonSingletonToName[pyObject.__class__], pyObject.args ) elif isinstance(pyObject, (type, type(isinstance))) and pyObject in NamedSingletons.pythonSingletonToName: tr = PyObjectNodes.NamedSingleton(pyObject, NamedSingletons.pythonSingletonToName[pyObject]) elif isinstance(pyObject, PyforaWithBlock.PyforaWithBlock): tr = self._pyObjectNodeForWithBlock(pyObject) elif id(pyObject) in self._convertedObjectCache: tr = self._convertedObjectCache[id(pyObject)][1] elif self.purePythonClassMapping.canMap(pyObject): pureInstance = self.purePythonClassMapping.mappableInstanceToPure(pyObject) self._convertedObjectCache[id(pyObject)] = (pyObject, pureInstance) tr = pureInstance elif isinstance(pyObject, tuple): tr = PyObjectNodes.Tuple(pyObject) elif isinstance(pyObject, list): tr = PyObjectNodes.List(pyObject) elif isinstance(pyObject, dict): tr = PyObjectNodes.Dict(pyObject) elif _isPrimitive(pyObject): tr = PyObjectNodes.Primitive(pyObject) elif PyforaInspect.isfunction(pyObject): tr = self._pyObjectNodeForFunction(pyObject) elif PyforaInspect.isclass(pyObject): tr = self._pyObjectNodeForClass(pyObject) elif isClassInstance(pyObject): tr = self._classInstanceDescriptionFromClassInstance(pyObject) return tr
def getSourceFilenameAndText(pyObject): try: sourceFile = PyforaInspect.getsourcefile(pyObject) except TypeError as e: raise Exceptions.CantGetSourceTextError(e.message) linesOrNone = PyforaInspect.getlines(sourceFile) if linesOrNone is None: raise Exceptions.CantGetSourceTextError( "can't get source lines for file %s" % sourceFile ) if sourceFile not in sourceFileCache_: sourceFileCache_[sourceFile] = "".join(linesOrNone) return sourceFileCache_[sourceFile], sourceFile
def test_pyforaInspect_twoNestedClasses(self): def f1(): class C1: def fC1(self): return 0 return C1 def f2(): class C1: def fC2(self): return 1 return C1 with self.assertRaises(PyforaInspect.PyforaInspectError): PyforaInspect.getsourcelines(f1()().__class__)
def computeDataMembers(pyClassObject): assert PyforaInspect.isclass(pyClassObject) initAstOrNone = _computeInitMethodAstOrNone(pyClassObject) if initAstOrNone is None: return [] return _computeDataMembersFromInitAst(initAstOrNone)
def collectDataMembersSetInInit(pyClassObject): # Return a list of data members set in the '__init__' method. assert PyforaInspect.isclass(pyClassObject) initAstOrNone = _computeInitMethodAstOrNone(pyClassObject) if initAstOrNone is None: return [] return _collectDataMembersSetInInitAst(initAstOrNone)
def cachedFromArgs(cls, fileName, fileText=None): if fileName in cls._fileTextCache: return cls._fileTextCache[fileName] if fileText is None: fileText = "".join(PyforaInspect.getlines(fileName)) tr = cls(fileName, fileText) cls._fileTextCache[fileName] = tr return tr
def getSourceText(pyObject): try: source, lineno = PyforaInspect.getsourcelines(pyObject) except TypeError as e: raise Exceptions.CantGetSourceTextError(e.message) # Create a prefix of (lineno-1) blank lines to keep track of line numbers for error reporting blankLines = os.linesep * (lineno - 1) # We don't know how to avoid the use of `textwrap.dedent to get the code # though `ast.parse, which means that the computed column_numbers may be # off and we shouldn't report them. return textwrap.dedent(blankLines + "".join(source))
def _walkPyObject(self, pyObject, objectId): if isinstance(pyObject, RemotePythonObject.RemotePythonObject): self._registerRemotePythonObject(objectId, pyObject) elif isinstance(pyObject, Future.Future): #it would be better to register the future and do a second pass of walking self._walkPyObject(pyObject.result(), objectId) elif isinstance(pyObject, _FileDescription): self._registerFileDescription(objectId, pyObject) elif isinstance(pyObject, Exception) and pyObject.__class__ in \ NamedSingletons.pythonSingletonToName: self._registerBuiltinExceptionInstance(objectId, pyObject) elif isinstance(pyObject, (type, type(isinstance))) and \ pyObject in NamedSingletons.pythonSingletonToName: self._registerNamedSingleton( objectId, NamedSingletons.pythonSingletonToName[pyObject] ) elif isinstance(pyObject, PyforaWithBlock.PyforaWithBlock): self._registerWithBlock(objectId, pyObject) elif isinstance(pyObject, _Unconvertible): self._registerUnconvertible(objectId) elif isinstance(pyObject, tuple): self._registerTuple(objectId, pyObject) elif isinstance(pyObject, list): self._registerList(objectId, pyObject) elif isinstance(pyObject, dict): self._registerDict(objectId, pyObject) elif isPrimitive(pyObject): self._registerPrimitive(objectId, pyObject) elif PyforaInspect.isfunction(pyObject): self._registerFunction(objectId, pyObject) elif PyforaInspect.isclass(pyObject): self._registerClass(objectId, pyObject) elif isinstance(pyObject, instancemethod): self._registerInstanceMethod(objectId, pyObject) elif isClassInstance(pyObject): self._registerClassInstance(objectId, pyObject) else: assert False, "don't know what to do with %s" % pyObject
def populateModuleMembers(self, path): res = {} module = self.moduleForFile(path) if module is not None: for leafItemName in module.__dict__: leafItemValue = module.__dict__[leafItemName] if PyforaInspect.isclass(leafItemValue) or PyforaInspect.isfunction(leafItemValue): try: sourcePath = PyforaInspect.getsourcefile(leafItemValue) if os.path.samefile(path, sourcePath): _, lineNumber = PyforaInspect.findsource(leafItemValue) lineNumberToUse = lineNumber + 1 if lineNumberToUse in res: raise Exceptions.ForaToPythonConversionError( ("PythonObjectRehydrator got a line number collision at lineNumber %s" ", between %s and %s"), lineNumberToUse, leafItemValue, res[lineNumber + 1] ) res[lineNumberToUse] = leafItemValue else: self.populateModuleMembers(sourcePath) except Exceptions.ForaToPythonConversionError: raise except Exception as e: logging.critical("PyforaInspect threw an exception: %s. tb = %s", e, traceback.format_exc()) self.moduleClassesAndFunctionsByPath[path] = res
def getSourceFilenameAndText(pyObject): try: sourceFile = PyforaInspect.getsourcefile(pyObject) except TypeError as e: raise Exceptions.CantGetSourceTextError(e.message) if sourceFile in sourceFileCache_: return sourceFileCache_[sourceFile], sourceFile with open(sourceFile, "r") as f: tr = f.read() sourceFileCache_[sourceFile] = tr return tr, sourceFile
def __enter__(self): sourceFileName, lineNumber, _, _ = traceback.extract_stack(limit=2)[0] self.sourceFileName = sourceFileName self.lineNumber = lineNumber with open(sourceFileName, "r") as sourceFile: self.sourceText = sourceFile.read() # Seems to "turn on" tracing, otherwise setting # frame.f_trace seems to have no effect # doesn't seem to have any effects outside of this with context. sys.settrace(lambda *args, **keys: None) self.frame = PyforaInspect.currentframe(1) self.frame.f_trace = self.trace
def _walkPyObject(self, pyObject, objectId): if isinstance(pyObject, RemotePythonObject.RemotePythonObject): self._registerRemotePythonObject(objectId, pyObject) elif isinstance(pyObject, Future.Future): #it would be better to register the future and do a second pass of walking self._walkPyObject(pyObject.result(), objectId) elif isinstance(pyObject, _FileDescription): self._registerFileDescription(objectId, pyObject) elif isinstance(pyObject, Exception) and pyObject.__class__ in \ NamedSingletons.pythonSingletonToName: self._registerBuiltinExceptionInstance(objectId, pyObject) elif isinstance(pyObject, (type, type(isinstance))) and \ pyObject in NamedSingletons.pythonSingletonToName: self._registerNamedSingleton( objectId, NamedSingletons.pythonSingletonToName[pyObject]) elif isinstance(pyObject, PyforaWithBlock.PyforaWithBlock): self._registerWithBlock(objectId, pyObject) elif isinstance(pyObject, _Unconvertible): self._registerUnconvertible(objectId) elif isinstance(pyObject, tuple): self._registerTuple(objectId, pyObject) elif isinstance(pyObject, list): self._registerList(objectId, pyObject) elif isinstance(pyObject, dict): self._registerDict(objectId, pyObject) elif isPrimitive(pyObject): self._registerPrimitive(objectId, pyObject) elif PyforaInspect.isfunction(pyObject): self._registerFunction(objectId, pyObject) elif PyforaInspect.isclass(pyObject): self._registerClass(objectId, pyObject) elif isinstance(pyObject, instancemethod): self._registerInstanceMethod(objectId, pyObject) elif isClassInstance(pyObject): self._registerClassInstance(objectId, pyObject) else: assert False, "don't know what to do with %s" % pyObject
def _computeSubchainAndTerminalValueAlongModules(self, rootValue, chain): ix = 1 subchain, terminalValue = chain[:ix], rootValue while PyforaInspect.ismodule(terminalValue): if ix >= len(chain): #we're terminating at a module raise Exceptions.PythonToForaConversionError( "Can't convert the module %s" % str(terminalValue)) if not hasattr(terminalValue, chain[ix]): raise Exceptions.PythonToForaConversionError( "Module %s has no member %s" % (str(terminalValue), chain[ix])) terminalValue = getattr(terminalValue, chain[ix]) ix += 1 subchain = chain[:ix] return subchain, terminalValue
def _computeSubchainAndTerminalValueAlongModules(self, rootValue, chain): ix = 1 subchain, terminalValue = chain[:ix], rootValue while PyforaInspect.ismodule(terminalValue): if ix >= len(chain): #we're terminating at a module raise Exceptions.PythonToForaConversionError( "Can't convert the module %s" % str(terminalValue) ) if not hasattr(terminalValue, chain[ix]): raise Exceptions.PythonToForaConversionError( "Module %s has no member %s" % (str(terminalValue), chain[ix]) ) terminalValue = getattr(terminalValue, chain[ix]) ix += 1 subchain = chain[:ix] return subchain, terminalValue
def _pyObjectNodeForClassOrFunction(self, pyObject, classOrFunction): try: sourceFileText, sourceFileName = PyAstUtil.getSourceFilenameAndText(pyObject) except Exceptions.CantGetSourceTextError as e: raise Exceptions.PythonToForaConversionError(e.message) _, sourceLine = PyforaInspect.getsourcelines(pyObject) sourceAst = PyAstUtil.getSourceFileAst(pyObject) if classOrFunction is PyObjectNodes.FunctionDefinition: pyAst = PyAstUtil.functionDefOrLambdaAtLineNumber(sourceAst, sourceLine) else: assert classOrFunction is PyObjectNodes.ClassDefinition pyAst = PyAstUtil.classDefAtLineNumber(sourceAst, sourceLine) freeVariableMemberAccessChainResolutions = \ self._resolveFreeVariableMemberAccessChains( pyObject, pyAst ) processedFreeVariableMemberAccessChainResolutions = { \ '.'.join(chain): resolution for chain, resolution in \ freeVariableMemberAccessChainResolutions.iteritems() } if sourceFileName in self._fileTextCache: fileObject = self._fileTextCache[sourceFileName] else: fileObject = PyObjectNodes.File(sourceFileName, sourceFileText) self._fileTextCache[sourceFileName] = fileObject return classOrFunction( pyObject, fileObject, sourceLine, processedFreeVariableMemberAccessChainResolutions )
def _computeSubchainAndTerminalValueAlongModules(rootValue, chainWithPosition): ix = 1 chain = chainWithPosition.var position = chainWithPosition.pos subchain, terminalValue = chain[:ix], rootValue while PyforaInspect.ismodule(terminalValue): if ix >= len(chain): #we're terminating at a module terminalValue = _Unconvertible() break if not hasattr(terminalValue, chain[ix]): raise Exceptions.PythonToForaConversionError( "Module %s has no member %s" % (str(terminalValue), chain[ix]) ) terminalValue = getattr(terminalValue, chain[ix]) ix += 1 subchain = chain[:ix] return subchain, terminalValue, position
def _pyObjectNodeForClassOrFunction(self, pyObject, classOrFunction): try: sourceFileText, sourceFileName = PyAstUtil.getSourceFilenameAndText( pyObject) except Exceptions.CantGetSourceTextError as e: raise Exceptions.PythonToForaConversionError(e.message) _, sourceLine = PyforaInspect.getsourcelines(pyObject) sourceAst = PyAstUtil.getSourceFileAst(pyObject) if classOrFunction is PyObjectNodes.FunctionDefinition: pyAst = PyAstUtil.functionDefOrLambdaAtLineNumber( sourceAst, sourceLine) else: assert classOrFunction is PyObjectNodes.ClassDefinition pyAst = PyAstUtil.classDefAtLineNumber(sourceAst, sourceLine) freeVariableMemberAccessChainResolutions = \ self._resolveFreeVariableMemberAccessChains( pyObject, pyAst ) processedFreeVariableMemberAccessChainResolutions = { \ '.'.join(chain): resolution for chain, resolution in \ freeVariableMemberAccessChainResolutions.iteritems() } if sourceFileName in self._fileTextCache: fileObject = self._fileTextCache[sourceFileName] else: fileObject = PyObjectNodes.File(sourceFileName, sourceFileText) self._fileTextCache[sourceFileName] = fileObject return classOrFunction( pyObject, fileObject, sourceLine, processedFreeVariableMemberAccessChainResolutions)
def _computeSubchainAndTerminalValueAlongModules(rootValue, chainWithPosition): ix = 1 chain = chainWithPosition.var position = chainWithPosition.pos subchain, terminalValue = chain[:ix], rootValue while PyforaInspect.ismodule(terminalValue): if ix >= len(chain): #we're terminating at a module terminalValue = _Unconvertible() break if not hasattr(terminalValue, chain[ix]): raise Exceptions.PythonToForaConversionError( "Module %s has no member %s" % (str(terminalValue), chain[ix])) terminalValue = getattr(terminalValue, chain[ix]) ix += 1 subchain = chain[:ix] return subchain, terminalValue, position
def _classOrFunctionDefinition(self, pyObject, classOrFunction): """ `_classOrFunctionDefinition: create a `_FunctionDefinition` or `_ClassDefinition` out of a python class or function, recursively visiting the resolvable free variable member access chains in `pyObject` as well as the source file object. Args: `pyObject`: a python class or function. `classOrFunction`: should either be `_FunctionDefinition` or `_ClassDefinition`. Returns: a `_FunctionDefinition` or `_ClassDefinition`. """ if pyObject.__name__ == '__inline_fora': raise Exceptions.PythonToForaConversionError( "in pyfora, '__inline_fora' is a reserved word") try: sourceFileText, sourceFileName = PyAstUtil.getSourceFilenameAndText( pyObject) except Exceptions.CantGetSourceTextError: self._raiseConversionErrorForSourceTextError(pyObject) except: logging.error('Failed on %s (of type %s)', pyObject, type(pyObject)) raise _, sourceLine = PyforaInspect.getsourcelines(pyObject) sourceAst = PyAstUtil.pyAstFromText(sourceFileText) if classOrFunction is _FunctionDefinition: pyAst = PyAstUtil.functionDefOrLambdaAtLineNumber( sourceAst, sourceLine) else: assert classOrFunction is _ClassDefinition pyAst = PyAstUtil.classDefAtLineNumber(sourceAst, sourceLine) try: freeVariableMemberAccessChainResolutions = \ self._computeAndResolveFreeVariableMemberAccessChainsInAst( pyObject, pyAst ) except UnresolvedFreeVariableException as e: _convertUnresolvedFreeVariableExceptionAndRaise(e, sourceFileName) try: processedFreeVariableMemberAccessChainResolutions = {} for chain, (resolution, location) in \ freeVariableMemberAccessChainResolutions.iteritems(): processedFreeVariableMemberAccessChainResolutions['.'.join(chain)] = \ self.walkPyObject(resolution) except UnresolvedFreeVariableExceptionWithTrace as e: e.addToTrace( Exceptions.makeTraceElement(path=sourceFileName, lineNumber=location[0])) raise sourceFileId = self.walkPyObject( _FileDescription.cachedFromArgs(fileName=sourceFileName, fileText=sourceFileText)) return classOrFunction( sourceFileId=sourceFileId, lineNumber=sourceLine, freeVariableMemberAccessChainsToId=\ processedFreeVariableMemberAccessChainResolutions )
def getAstFromFilePath(filename): linesOrNone = PyforaInspect.getlines(filename) if linesOrNone is not None: return pyAstFromText("".join(linesOrNone)) return None
def getSourceFileAst(pyObject): filename = PyforaInspect.getsourcefile(pyObject) return getAstFromFilePath(filename)
def _classOrFunctionDefinition(self, pyObject, classOrFunction): """ `_classOrFunctionDefinition: create a `_FunctionDefinition` or `_ClassDefinition` out of a python class or function, recursively visiting the resolvable free variable member access chains in `pyObject` as well as the source file object. Args: `pyObject`: a python class or function. `classOrFunction`: should either be `_FunctionDefinition` or `_ClassDefinition`. Returns: a `_FunctionDefinition` or `_ClassDefinition`. """ if pyObject.__name__ == '__inline_fora': raise Exceptions.PythonToForaConversionError( "in pyfora, '__inline_fora' is a reserved word" ) try: sourceFileText, sourceFileName = PyAstUtil.getSourceFilenameAndText(pyObject) except Exceptions.CantGetSourceTextError: self._raiseConversionErrorForSourceTextError(pyObject) except: logging.error('Failed on %s (of type %s)', pyObject, type(pyObject)) raise _, sourceLine = PyforaInspect.getsourcelines(pyObject) sourceAst = PyAstUtil.pyAstFromText(sourceFileText) if classOrFunction is _FunctionDefinition: pyAst = PyAstUtil.functionDefOrLambdaAtLineNumber(sourceAst, sourceLine) else: assert classOrFunction is _ClassDefinition pyAst = PyAstUtil.classDefAtLineNumber(sourceAst, sourceLine) try: freeVariableMemberAccessChainResolutions = \ self._computeAndResolveFreeVariableMemberAccessChainsInAst( pyObject, pyAst ) except UnresolvedFreeVariableException as e: _convertUnresolvedFreeVariableExceptionAndRaise(e, sourceFileName) try: processedFreeVariableMemberAccessChainResolutions = {} for chain, (resolution, location) in \ freeVariableMemberAccessChainResolutions.iteritems(): processedFreeVariableMemberAccessChainResolutions['.'.join(chain)] = \ self.walkPyObject(resolution) except UnresolvedFreeVariableExceptionWithTrace as e: e.addToTrace( Exceptions.makeTraceElement( path=sourceFileName, lineNumber=location[0] ) ) raise sourceFileId = self.walkPyObject( _FileDescription.cachedFromArgs( fileName=sourceFileName, fileText=sourceFileText ) ) return classOrFunction( sourceFileId=sourceFileId, lineNumber=sourceLine, freeVariableMemberAccessChainsToId=\ processedFreeVariableMemberAccessChainResolutions )
def getSourceLines(pyObject): try: tr = PyforaInspect.getsourcelines(pyObject) except (TypeError, IOError) as e: raise Exceptions.CantGetSourceTextError(e.message), None, sys.exc_info()[2] return tr
def _classMemberFunctions(self, pyObject): return PyforaInspect.getmembers( pyObject, lambda elt: PyforaInspect.ismethod(elt) or PyforaInspect. isfunction(elt))
def walkPyObject(self, pyObject): """ `walkPyObject`: recursively traverse a live python object, registering its "pieces" with an `ObjectRegistry` (`self.objectRegistry`). Note that we use python `id`s for caching in this class, which means it cannot be used in cases where `id`s might get reused (recall they are just memory addresses). `objectId`s are assigned to all pieces of the python object. Returns: An `int`, the `objectId` of the root python object. """ if id(pyObject) in self._pyObjectIdToObjectId: return self._pyObjectIdToObjectId[id(pyObject)] if id(pyObject) in self._convertedObjectCache: pyObject = self._convertedObjectCache[id(pyObject)] elif self._purePythonClassMapping.canMap(pyObject): pureInstance = self._purePythonClassMapping.mappableInstanceToPure( pyObject ) self._convertedObjectCache[id(pyObject)] = pureInstance pyObject = pureInstance objectId = self._allocateId(pyObject) if isinstance(pyObject, RemotePythonObject.RemotePythonObject): self._registerRemotePythonObject(objectId, pyObject) elif isinstance(pyObject, _FileDescription): self._registerFileDescription(objectId, pyObject) elif isinstance(pyObject, Exception) and pyObject.__class__ in \ NamedSingletons.pythonSingletonToName: self._registerBuiltinExceptionInstance(objectId, pyObject) elif isinstance(pyObject, (type, type(isinstance))) and \ pyObject in NamedSingletons.pythonSingletonToName: self._registerNamedSingleton( objectId, NamedSingletons.pythonSingletonToName[pyObject] ) elif isinstance(pyObject, PyforaWithBlock.PyforaWithBlock): self._registerWithBlock(objectId, pyObject) elif isinstance(pyObject, tuple): self._registerTuple(objectId, pyObject) elif isinstance(pyObject, list): self._registerList(objectId, pyObject) elif isinstance(pyObject, dict): self._registerDict(objectId, pyObject) elif isPrimitive(pyObject): self._registerPrimitive(objectId, pyObject) elif PyforaInspect.isfunction(pyObject): self._registerFunction(objectId, pyObject) elif PyforaInspect.isclass(pyObject): self._registerClass(objectId, pyObject) elif isinstance(pyObject, instancemethod): self._registerInstanceMethod(objectId, pyObject) elif isClassInstance(pyObject): self._registerClassInstance(objectId, pyObject) else: assert False, "don't know what to do with %s" % pyObject return objectId
def _classMemberFunctions(self, pyObject): return PyforaInspect.getmembers( pyObject, lambda elt: PyforaInspect.ismethod(elt) or PyforaInspect.isfunction(elt) )