ListCallTransformer   A
last analyzed

Complexity

Total Complexity 6

Size/Duplication

Total Lines 25
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 25
rs 10
wmc 6

3 Methods

Rating   Name   Duplication   Size   Complexity  
A is_list_addition() 0 7 1
A visit_Call() 0 8 4
A is_list_assignment() 0 3 1
1
import ast
2
from scope import ScopeMixin
3
4
5
def add_list_calls(node):
6
    """Provide context to Module and Function Def"""
7
    return ListCallTransformer().visit(node)
8
9
10
def add_variable_context(node):
11
    """Provide context to Module and Function Def"""
12
    return VariableTransformer().visit(node)
13
14
15
class ListCallTransformer(ast.NodeTransformer):
16
    """
17
    Adds all calls to list to scope block.
18
    You need to apply VariableTransformer before you use it.
19
    """
20
    def visit_Call(self, node):
21
        if self.is_list_addition(node):
22
            var = node.scopes.find(node.func.value.id)
23
            if self.is_list_assignment(var.assigned_from):
24
                if not hasattr(var, "calls"):
25
                    var.calls = []
26
                var.calls.append(node)
27
        return node
28
29
    def is_list_assignment(self, node):
30
        return (isinstance(node.value, ast.List) and
31
                isinstance(node.targets[0].ctx, ast.Store))
32
33
    def is_list_addition(self, node):
34
        """Check if operation is adding something to a list"""
35
        list_operations = ["append", "extend", "insert"]
36
        return (isinstance(node.func.ctx, ast.Load) and
37
                hasattr(node.func, "value") and
38
                isinstance(node.func.value, ast.Name) and
39
                node.func.attr in list_operations)
40
41
42
class VariableTransformer(ast.NodeTransformer, ScopeMixin):
43
    """Adds all defined variables to scope block"""
44
    def visit_FunctionDef(self, node):
45
        node.vars = []
46
        for arg in node.args.args:
47
            arg.assigned_from = node
48
            node.vars.append(arg)
49
        self.generic_visit(node)
50
        return node
51
52
    def visit_Import(self, node):
53
        for name in node.names:
54
            name.imported_from = node
55
56
    def visit_If(self, node):
57
        node.vars = []
58
        map(self.visit, node.body)
59
        node.body_vars = node.vars
60
61
        node.vars = []
62
        map(self.visit, node.orelse)
63
        node.orelse_vars = node.vars
64
65
        node.vars = []
66
        return node
67
68
    def visit_For(self, node):
69
        node.target.assigned_from = node
70
        node.vars = [node.target]
71
        self.generic_visit(node)
72
        return node
73
74
    def visit_Module(self, node):
75
        node.vars = []
76
        self.generic_visit(node)
77
        return node
78
79
    def visit(self, node):
80
        with self.enter_scope(node):
81
            return super(VariableTransformer, self).visit(node)
82
83
    def visit_Assign(self, node):
84
        for target in node.targets:
85
            if isinstance(target, ast.Name):
86
                target.assigned_from = node
87
                self.scope.vars.append(target)
88
        return node
89