File: vbench_to_asv.py

package info (click to toggle)
pandas 0.23.3%2Bdfsg-3
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 167,704 kB
  • sloc: python: 230,826; ansic: 11,317; sh: 682; makefile: 133
file content (163 lines) | stat: -rw-r--r-- 4,844 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
import ast
import vbench
import os
import sys
import astor
import glob


def vbench_to_asv_source(bench, kinds=None):
    tab = ' ' * 4
    if kinds is None:
        kinds = ['time']

    output = 'class {}(object):\n'.format(bench.name)
    output += tab + 'goal_time = 0.2\n\n'

    if bench.setup:
        indented_setup = [tab * 2 + '{}\n'.format(x) for x in bench.setup.splitlines()]
        output += tab + 'def setup(self):\n' + ''.join(indented_setup) + '\n'

    for kind in kinds:
        output += tab + 'def {}_{}(self):\n'.format(kind, bench.name)
        for line in bench.code.splitlines():
            output += tab * 2 + line + '\n'
        output += '\n\n'

    if bench.cleanup:
        output += tab + 'def teardown(self):\n' + tab * 2 + bench.cleanup

    output += '\n\n'
    return output


class AssignToSelf(ast.NodeTransformer):
    def __init__(self):
        super(AssignToSelf, self).__init__()
        self.transforms = {}
        self.imports = []

        self.in_class_define = False
        self.in_setup = False

    def visit_ClassDef(self, node):
        self.transforms = {}
        self.in_class_define = True

        functions_to_promote = []
        setup_func = None

        for class_func in ast.iter_child_nodes(node):
            if isinstance(class_func, ast.FunctionDef):
                if class_func.name == 'setup':
                    setup_func = class_func
                    for anon_func in ast.iter_child_nodes(class_func):
                        if isinstance(anon_func, ast.FunctionDef):
                            functions_to_promote.append(anon_func)

        if setup_func:
            for func in functions_to_promote:
                setup_func.body.remove(func)
                func.args.args.insert(0, ast.Name(id='self', ctx=ast.Load()))
                node.body.append(func)
                self.transforms[func.name] = 'self.' + func.name

            ast.fix_missing_locations(node)

        self.generic_visit(node)

        return node

    def visit_TryExcept(self, node):
        if any(isinstance(x, (ast.Import, ast.ImportFrom)) for x in node.body):
            self.imports.append(node)
        else:
            self.generic_visit(node)
            return node

    def visit_Assign(self, node):
        for target in node.targets:
            if isinstance(target, ast.Name) and not isinstance(target.ctx, ast.Param) and not self.in_class_define:
                self.transforms[target.id] = 'self.' + target.id
        self.generic_visit(node)

        return node

    def visit_Name(self, node):
        new_node = node
        if node.id in self.transforms:
            if not isinstance(node.ctx, ast.Param):
                new_node = ast.Attribute(value=ast.Name(id='self', ctx=node.ctx), attr=node.id, ctx=node.ctx)

        self.generic_visit(node)

        return ast.copy_location(new_node, node)

    def visit_Import(self, node):
        self.imports.append(node)

    def visit_ImportFrom(self, node):
        self.imports.append(node)

    def visit_FunctionDef(self, node):
        """Delete functions that are empty due to imports being moved"""
        self.in_class_define = False

        self.generic_visit(node)

        if node.body:
            return node


def translate_module(target_module):
    g_vars = {}
    l_vars = {}
    exec('import ' + target_module) in g_vars

    print(target_module)
    module = eval(target_module, g_vars)

    benchmarks = []
    for obj_str in dir(module):
        obj = getattr(module, obj_str)
        if isinstance(obj, vbench.benchmark.Benchmark):
            benchmarks.append(obj)

    if not benchmarks:
        return

    rewritten_output = ''
    for bench in benchmarks:
        rewritten_output += vbench_to_asv_source(bench)

    with open('rewrite.py', 'w') as f:
        f.write(rewritten_output)

    ast_module = ast.parse(rewritten_output)

    transformer = AssignToSelf()
    transformed_module = transformer.visit(ast_module)

    unique_imports = {astor.to_source(node): node for node in transformer.imports}

    transformed_module.body = unique_imports.values() + transformed_module.body

    transformed_source = astor.to_source(transformed_module)

    with open('benchmarks/{}.py'.format(target_module), 'w') as f:
        f.write(transformed_source)


if __name__ == '__main__':
    cwd = os.getcwd()
    new_dir = os.path.join(os.path.dirname(__file__), '../vb_suite')
    sys.path.insert(0, new_dir)

    for module in glob.glob(os.path.join(new_dir, '*.py')):
        mod = os.path.basename(module)
        if mod in ['make.py', 'measure_memory_consumption.py', 'perf_HEAD.py', 'run_suite.py', 'test_perf.py', 'generate_rst_files.py', 'test.py', 'suite.py']:
            continue
        print('')
        print(mod)

        translate_module(mod.replace('.py', ''))