def test_TransvisitorsDontModifyTree(self): tree = ast.parse(self.some_python_code) # deep-copy tree because transformers modify the AST in place # making the test of areAstsIdentical(tree, tree') meaningless tree1 = copy.deepcopy(tree) noopTransformer = NodeVisitorBases.SemanticOrderNodeTransvisitor() tree2 = noopTransformer.visit(tree1) self.assertIsNotNone(tree2) self.assertTrue(PyAstUtil.areAstsIdentical(tree, tree2)) scopeMgr = NodeVisitorBases.InScopeSaveRestoreValue( lambda: True, lambda x: None) noopTransformer = NodeVisitorBases.GenericScopedTransvisitor(scopeMgr) tree3 = noopTransformer.visit(tree1) self.assertIsNotNone(tree3) self.assertTrue(PyAstUtil.areAstsIdentical(tree, tree3)) freeVarsVisitor = PyAstFreeVariableAnalyses._FreeVariableMemberAccessChainsTransvisitor( ) tree4 = freeVarsVisitor.visit(tree1) self.assertIsNotNone(tree4) self.assertTrue(PyAstUtil.areAstsIdentical(tree, tree4))
def __init__(self): scopeMgr = NodeVisitorBases.ScopedSaveRestoreComputedValue( self.getBoundValues, self._setBoundValues, GenericBoundValuesScopedVisitor._computeScopeBoundValues) super(GenericBoundValuesScopedVisitor, self).__init__(scopeMgr) self._boundValues = set() self._boundInScopeSoFar = set()
def visit_arguments(self, node): self.visit(node.defaults) with self._isInDefinitionMgr(True): self.visit(node.args) if node.vararg is not None: self._boundVarsWithPos.add( VarWithPosition(var=node.vararg, pos=NodeVisitorBases.PositionInFile( lineno=node.lineno, col_offset=node.col_offset))) if node.kwarg is not None: self._boundVarsWithPos.add( VarWithPosition(var=node.kwarg, pos=NodeVisitorBases.PositionInFile( lineno=node.lineno, col_offset=node.col_offset)))
def visit_Name(self, node): if self._isInDefinition: self._boundVarsWithPos.add( VarWithPosition(var=node.id, pos=NodeVisitorBases.PositionInFile( lineno=node.lineno, col_offset=node.col_offset)))
def visit_ClassDef(self, node): self._boundNamesWithPos.add( VarWithPosition(var=node.name, pos=NodeVisitorBases.PositionInFile( lineno=node.lineno, col_offset=node.col_offset))) return node
def visit_FunctionDef(self, node): # exclude synthetic wrapper FunctionDef nodes if node.name != '': self._boundNamesWithPos.add( VarWithPosition(var=node.name, pos=NodeVisitorBases.PositionInFile( lineno=node.lineno, col_offset=node.col_offset)))
def visit_Name(self, node): identifier = node.id if isinstance(node.ctx, ast.Store): self._boundInScopeSoFar.add(identifier) elif not self.isBoundSoFar(identifier) and \ isinstance(node.ctx, ast.Load): self._freeVariableMemberAccessChainsWithPos.add( VarWithPosition(var=(identifier, ), pos=NodeVisitorBases.PositionInFile( lineno=node.lineno, col_offset=node.col_offset)))
def getRootInContext(pyAstNode, isClassContext): if not NodeVisitorBases.isScopeNode(pyAstNode): raise Exceptions.InternalError( "Unsupported type of root node in Analysis (%s)." % type(pyAstNode)) if isinstance(pyAstNode, ast.FunctionDef): if isClassContext is None: raise Exceptions.InternalError( "Value for `isClassContext is required when `type(pyAstNode) is `ast.FunctionDef.") elif isClassContext is False: pyAstNode = ast.Module([pyAstNode]) # else nothing return pyAstNode
def getRootInContext(pyAstNode, isClassContext): if not NodeVisitorBases.isScopeNode(pyAstNode): raise Exceptions.InternalError( "Unsupported type of root node in Analysis (%s)." % type(pyAstNode)) if isinstance(pyAstNode, ast.FunctionDef): if isClassContext is None: raise Exceptions.InternalError( "Value for `isClassContext is required when `type(pyAstNode) is `ast.FunctionDef." ) elif isClassContext is False: pyAstNode = ast.Module([pyAstNode]) # else nothing return pyAstNode
def visit_Attribute(self, node): chainOrNone = _memberAccessChainOrNone(node) if chainOrNone is not None: if chainOrNone[0] not in self._boundValues: self._freeVariableMemberAccessChainsWithPos.add( VarWithPosition(var=chainOrNone, pos=NodeVisitorBases.PositionInFile( lineno=node.lineno, col_offset=node.col_offset))) else: #required to recurse deeper into the AST, but only do it if #_freeVariableMemberAccessChain was None, indicating that it #doesn't want to consume the whole expression self.generic_visit(node.value)
def __init__(self, exclude_predicate=None): scopeMgr = NodeVisitorBases.ScopedSaveRestoreComputedValue( self.getBoundValues, self._setBoundValues, _FreeVariableMemberAccessChainsTransvisitor. _computeScopeBoundValues) super(_FreeVariableMemberAccessChainsTransvisitor, self).__init__(scopeMgr) self._boundValues = set() self._boundInScopeSoFar = set() self._freeVariableMemberAccessChainsWithPos = collections.defaultdict( set) self._freeVariablesWithPos = collections.defaultdict(set) self._exclude_predicate = exclude_predicate
def addFreeVariableMemberAccessChain(self, chain, lineno, col_offset): pos = NodeVisitorBases.PositionInFile(lineno=lineno, col_offset=col_offset) self._freeVariableMemberAccessChainsWithPos[chain].add(pos) self._freeVariablesWithPos[chain[0]].add(pos)