def test_computeDataMembers_error_2(self): class E2: def __init__(*args): self.x = 0 with self.assertRaises(Exceptions.PythonToForaConversionError): PyAstUtil.computeDataMembers(E2)
def _instantiateFunction(self, filename, lineNumber, memberDictionary): """Instantiate a function instance.""" objectOrNone = self.moduleLevelObject(filename, lineNumber) if objectOrNone is not None: return objectOrNone sourceAst = PyAstUtil.getAstFromFilePath(filename) functionAst = PyAstUtil.functionDefOrLambdaAtLineNumber(sourceAst, lineNumber) outputLocals = {} globalScope = {} globalScope.update(memberDictionary) self.importModuleMagicVariables(globalScope, filename) if isinstance(functionAst, ast.Lambda): expr = ast.Expression() expr.body = functionAst expr.lineno = functionAst.lineno expr.col_offset = functionAst.col_offset code = compile(expr, filename, 'eval') return eval(code, globalScope, outputLocals) else: code = compile(ast.Module([functionAst]), filename, 'exec') exec code in globalScope, outputLocals assert len(outputLocals) == 1 return list(outputLocals.values())[0]
def _classObjectFromFilenameAndLine(self, filename, lineNumber, members): """Construct a class object given its textual definition.""" objectOrNone = self.moduleLevelObject(filename, lineNumber) if objectOrNone is not None: return objectOrNone sourceAst = PyAstUtil.getAstFromFilePath(filename) classAst = PyAstUtil.classDefAtLineNumber(sourceAst, lineNumber) outputLocals = {} globalScope = {} globalScope.update(members) self.importModuleMagicVariables(globalScope, filename) try: code = compile(ast.Module([classAst]), filename, 'exec') exec code in globalScope, outputLocals except: logging.error("Failed to instantiate class at %s:%s\n%s", filename, lineNumber, traceback.format_exc()) raise Exceptions.PyforaError("Failed to instantiate class at %s:%s" % (filename, lineNumber)) assert len(outputLocals) == 1 return list(outputLocals.values())[0]
def test_computeDataMembers_error_3(self): class E3: def __init__(self): self.x = 0 def f(x): return x with self.assertRaises(Exceptions.PythonToForaConversionError): PyAstUtil.computeDataMembers(E3)
def test_computeDataMembers_error_4(self): class E4: def __init__(self): self.x = 0 class c(object): def __init__(self): self.z = 0 with self.assertRaises(Exceptions.PythonToForaConversionError): PyAstUtil.computeDataMembers(E4)
def augmentRaiseFunction(raiseFunction, path, line, col): enclosingFunctionVisitor = PyAstUtil.FindEnclosingFunctionVisitor(line) codeAst = PyAstUtil.getAstFromFilePath(path) enclosingFunctionName = enclosingFunctionVisitor.find(codeAst) vis = AugmentRaiseFunctionModificationVisitor(line, col, enclosingFunctionName) module = ast.parse(augmentRaiseFunctionTemplate) vis.visit(module) code = compile(module, path, 'exec') exec code in globals(), locals() return _augmentRaiseFunctionTempl(raiseFunction)
def test_computeDataMembers_3(self): class C3: def __init__(self): self.x = self.y = 0 dataMembers = PyAstUtil.computeDataMembers(C3) self.assertEqual(dataMembers, set(['x', 'y']))
def test_computeDataMembers_4(self): class C4: def __init__(self, arg): (self.x, self.y), self.z = arg dataMembers = PyAstUtil.computeDataMembers(C4) self.assertEqual(dataMembers, set(['x', 'y', 'z']))
def _cachedCompute(self): if not self._isComputed: if PyAstUtil.isScopeNode(self._root): self.generic_visit(self._root) self._isComputed = True else: raise Exceptions.InternalError( "'%s' called on unsupported node-type (%s)" % (self.__class__.__name__, type(self._root)))
def test_computeDataMembers_1(self): class C: def __init__(self, x): self.x = x self.y = x**2.0 dataMembers = PyAstUtil.computeDataMembers(C) self.assertEqual(dataMembers, set(['x', 'y']))
def _cachedCompute(self): if not self._isComputed: if PyAstUtil.isScopeNode(self._root): self.generic_visit(self._root) self._isComputed = True else: raise Exceptions.InternalError( "'%s' called on unsupported node-type (%s)" % (self.__class__.__name__, type(self._root)) )
def collectPossiblyUninitializedLocalVariables(pyAstNode): """Returns the possibly free local variables of the code rooted at `pyAstNode.""" # Context doesn't play a role below, but we reuse the code for checking `pyAstNode if not PyAstUtil.isScopeNode(pyAstNode): raise Exceptions.InternalError( "Unsupported type of root node in Analysis (%s)" % type(pyAstNode)) possiblyUninitVisitor = _PossiblyUninitializedScopedVisitor() possiblyUninitVisitor.visit(pyAstNode) return possiblyUninitVisitor.getPossiblyUninitializedLocalVariables()
def test_computeDataMembers_2(self): class C2: def __init__(self, x): if x > 0: self.x = x dataMembers = PyAstUtil.computeDataMembers(C2) # in our translation, we're _always_ producing an x member self.assertEqual(dataMembers, set(['x']))
def test_computeDataMembers_3(self): class C3: def __init__(self): self.x = self.y = 0 dataMembers = PyAstUtil.computeDataMembers(C3) self.assertEqual( dataMembers, set(['x', 'y']) )
def test_computeDataMembers_4(self): class C4: def __init__(self, arg): (self.x, self.y), self.z = arg dataMembers = PyAstUtil.computeDataMembers(C4) self.assertEqual( dataMembers, set(['x', 'y', 'z']) )
def test_computeDataMembers_1(self): class C: def __init__(self, x): self.x = x self.y = x ** 2.0 dataMembers = PyAstUtil.computeDataMembers(C) self.assertEqual( dataMembers, set(['x', 'y']) )
def _pyObjectNodeForWithBlock(self, pyObject): lineNumber = pyObject.lineNumber sourceTree = PyAstUtil.pyAstFromText(pyObject.sourceText) withBlockAst = PyAstUtil.withBlockAtLineNumber(sourceTree, lineNumber) withBlockFun = ast.FunctionDef( name="", args=ast.arguments(args=[], defaults=[], kwarg=None, vararg=None), body=withBlockAst.body, decorator_list=[] ) freeVariableMemberAccessChains = \ self._freeOrUninitializedMemberAccesChains(withBlockFun) freeVariableMemberAccessChainResolutions = \ self._resolveFreeVariableMemberAccesChains( freeVariableMemberAccessChains, pyObject.boundVariables ) processedFreeVariableMemberAccessChainResolutions = { \ '.'.join(chain): resolution for chain, resolution in \ freeVariableMemberAccessChainResolutions.iteritems() } if pyObject.sourceFileName in self._fileTextCache: fileObject = self._fileTextCache[pyObject.sourceFileName] else: with open(pyObject.sourceFileName, "r") as sourceFile: sourceFileText = sourceFile.read() fileObject = PyObjectNodes.File(pyObject.sourceFileName, sourceFileText) self._fileTextCache[pyObject.sourceFileName] = fileObject return PyObjectNodes.WithBlock( pyObject, fileObject, lineNumber, processedFreeVariableMemberAccessChainResolutions )
def _pyObjectNodeForWithBlock(self, pyObject): lineNumber = pyObject.lineNumber sourceTree = PyAstUtil.pyAstFromText(pyObject.sourceText) withBlockAst = PyAstUtil.withBlockAtLineNumber(sourceTree, lineNumber) withBlockFun = ast.FunctionDef(name="", args=ast.arguments(args=[], defaults=[], kwarg=None, vararg=None), body=withBlockAst.body, decorator_list=[]) freeVariableMemberAccessChains = \ self._freeOrUninitializedMemberAccesChains(withBlockFun) freeVariableMemberAccessChainResolutions = \ self._resolveFreeVariableMemberAccesChains( freeVariableMemberAccessChains, pyObject.boundVariables ) processedFreeVariableMemberAccessChainResolutions = { \ '.'.join(chain): resolution for chain, resolution in \ freeVariableMemberAccessChainResolutions.iteritems() } if pyObject.sourceFileName in self._fileTextCache: fileObject = self._fileTextCache[pyObject.sourceFileName] else: with open(pyObject.sourceFileName, "r") as sourceFile: sourceFileText = sourceFile.read() fileObject = PyObjectNodes.File(pyObject.sourceFileName, sourceFileText) self._fileTextCache[pyObject.sourceFileName] = fileObject return PyObjectNodes.WithBlock( pyObject, fileObject, lineNumber, processedFreeVariableMemberAccessChainResolutions)
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 test_computeDataMembers_2(self): class C2: def __init__(self, x): if x > 0: self.x = x dataMembers = PyAstUtil.computeDataMembers(C2) # in our translation, we're _always_ producing an x member self.assertEqual( dataMembers, set(['x']) )
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 _classInstanceDescriptionFromClassInstance(self, pyObject): try: classObject = pyObject.__class__ dataMemberNames = PyAstUtil.computeDataMembers(classObject) classMemberNameToMemberValue = {} for dataMemberName in dataMemberNames: memberValue = getattr(pyObject, dataMemberName) classMemberNameToMemberValue[dataMemberName] = memberValue return PyObjectNodes.ClassInstanceDescription( pyObject, classObject, classMemberNameToMemberValue) except: logging.error('Failed on %s (of type %s)', pyObject, type(pyObject)) raise
def test_freeVariablesMemberAccessChain_onFunctionDefNode(self): tree1 = ast.parse( textwrap.dedent(""" def g(arg): if arg < 0: return x + arg return x * h(arg - 1, g) """)) res = PyAstFreeVariableAnalyses.getFreeVariableMemberAccessChains( tree1) self.assertEqual(set([('h', ), ('x', )]), res) tree2 = PyAstUtil.functionDefOrLambdaAtLineNumber(tree1, 2) self.assertEqual( set([('h', ), ('x', )]), PyAstFreeVariableAnalyses.getFreeVariableMemberAccessChains( tree2, False))
def _classInstanceDescriptionFromClassInstance(self, pyObject): try: classObject = pyObject.__class__ dataMemberNames = PyAstUtil.computeDataMembers(classObject) classMemberNameToMemberValue = {} for dataMemberName in dataMemberNames: memberValue = getattr(pyObject, dataMemberName) classMemberNameToMemberValue[dataMemberName] = memberValue return PyObjectNodes.ClassInstanceDescription( pyObject, classObject, classMemberNameToMemberValue ) except: logging.error('Failed on %s (of type %s)', pyObject, type(pyObject)) raise
def test_freeVariablesMemberAccessChain_onFunctionDefNode(self): tree1 = ast.parse( textwrap.dedent( """ def g(arg): if arg < 0: return x + arg return x * h(arg - 1, g) """ ) ) res = PyAstFreeVariableAnalyses.getFreeVariableMemberAccessChains(tree1) self.assertEqual( set([('h',), ('x',)]), res ) tree2 = PyAstUtil.functionDefOrLambdaAtLineNumber(tree1, 2) self.assertEqual( set([('h',), ('x',)]), PyAstFreeVariableAnalyses.getFreeVariableMemberAccessChains(tree2, False) )
def getFreeVariableMemberAccessChains(pyAstNode, isClassContext=None): pyAstNode = PyAstUtil.getRootInContext(pyAstNode, isClassContext) freeVariableMemberAccessChainsVisitor = _FreeVariableMemberAccessChainsVisitor() freeVariableMemberAccessChainsVisitor.visit(pyAstNode) return freeVariableMemberAccessChainsVisitor.freeVariableMemberAccessChains
def getFreeVariables(pyAstNode, isClassContext=None): pyAstNode = PyAstUtil.getRootInContext(pyAstNode, isClassContext) freeVarsVisitor = _FreeVarsVisitor() freeVarsVisitor.visit(pyAstNode) return freeVarsVisitor.getFreeVars()