def updatePyAstVariableUsages(pyAst, variablesInScope, varsToTurnIntoCalls,
                              isClassContext):
    #in the variables we've been handed, every member access chain 'x.y.z' has been
    #replaced with an actual variable lookup of the form 'x.y.z'. We need to perform
    #this same replacement in the actual python source code we're running, since
    #we may not actually have enough information to recover 'x'

    replacements = {}
    for possible_replacement in variablesInScope:
        if '.' in possible_replacement:
            replacements[tuple(
                possible_replacement.split('.'))] = possible_replacement

    #we need to deepcopy the AST since the collapser modifies the AST, and this is just a
    #slice of a cached tree.
    pyAst = ast.fix_missing_locations(copy.deepcopy(pyAst))

    if varsToTurnIntoCalls:
        pyAst = PyAstFreeVariableAnalyses.replaceUsesWithCalls(
            pyAst, set(varsToTurnIntoCalls), isClassContext)

    pyAst = PyAstFreeVariableAnalyses.collapseFreeVariableMemberAccessChains(
        pyAst, replacements, isClassContext=isClassContext)

    return ast.fix_missing_locations(pyAst)
Exemple #2
0
 def test_FreeVariableTransformer_3(self):
     tree = ast.parse(
         textwrap.dedent("""
             def g(y):
                 return x.y.z.__str__()
             """))
     # deep-copy tree because transformers modify the AST in place
     # making the test of areAstsIdentical(tree, tree') meaningless
     tree1 = copy.deepcopy(tree)
     tree2 = PyAstFreeVariableAnalyses.collapseFreeVariableMemberAccessChains(
         tree1, {('x', 'y', 'z'): 'x_y_z'}, isClassContext=False)
     self.assertIsNotNone(tree2)
     self.assertFalse(PyAstUtil.areAstsIdentical(tree, tree2))