##// END OF EJS Templates
Update %timeit magic to use AST transformations
Thomas Kluyver -
Show More
@@ -14,6 +14,7 b''
14
14
15 # Stdlib
15 # Stdlib
16 import __builtin__ as builtin_mod
16 import __builtin__ as builtin_mod
17 import ast
17 import bdb
18 import bdb
18 import os
19 import os
19 import sys
20 import sys
@@ -760,26 +761,54 b' python-profiler package from non-free.""")'
760 # but is there a better way to achieve that the code stmt has access
761 # but is there a better way to achieve that the code stmt has access
761 # to the shell namespace?
762 # to the shell namespace?
762 transform = self.shell.input_splitter.transform_cell
763 transform = self.shell.input_splitter.transform_cell
764
763 if cell is None:
765 if cell is None:
764 # called as line magic
766 # called as line magic
765 setup = 'pass'
767 ast_setup = ast.parse("pass")
766 stmt = timeit.reindent(transform(stmt), 8)
768 ast_stmt = ast.parse(transform(stmt))
767 else:
768 setup = timeit.reindent(transform(stmt), 4)
769 stmt = timeit.reindent(transform(cell), 8)
770
771 # From Python 3.3, this template uses new-style string formatting.
772 if sys.version_info >= (3, 3):
773 src = timeit.template.format(stmt=stmt, setup=setup)
774 else:
769 else:
775 src = timeit.template % dict(stmt=stmt, setup=setup)
770 ast_setup = ast.parse(transform(stmt))
771 ast_stmt = ast.parse(transform(cell))
772
773 ast_setup = self.shell.transform_ast(ast_setup)
774 ast_stmt = self.shell.transform_ast(ast_stmt)
775
776 # This codestring is taken from timeit.template - we fill it in as an
777 # AST, so that we can apply our AST transformations to the user code
778 # without affecting the timing code.
779 timeit_ast_template = ast.parse('def inner(_it, _timer):\n'
780 ' setup\n'
781 ' _t0 = _timer()\n'
782 ' for _i in _it:\n'
783 ' stmt\n'
784 ' _t1 = _timer()\n'
785 ' return _t1 - _t0\n')
786
787 class TimeitTemplateFiller(ast.NodeTransformer):
788 "This is quite tightly tied to the template definition above."
789 def visit_FunctionDef(self, node):
790 "Fill in the setup statement"
791 self.generic_visit(node)
792 if node.name == "inner":
793 node.body[:1] = ast_setup.body
794
795 return node
796
797 def visit_For(self, node):
798 "Fill in the statement to be timed"
799 if getattr(getattr(node.body[0], 'value', None), 'id', None) == 'stmt':
800 node.body = ast_stmt.body
801 return node
802
803 timeit_ast = TimeitTemplateFiller().visit(timeit_ast_template)
804 timeit_ast = ast.fix_missing_locations(timeit_ast)
776
805
777 # Track compilation time so it can be reported if too long
806 # Track compilation time so it can be reported if too long
778 # Minimum time above which compilation time will be reported
807 # Minimum time above which compilation time will be reported
779 tc_min = 0.1
808 tc_min = 0.1
780
809
781 t0 = clock()
810 t0 = clock()
782 code = compile(src, "<magic-timeit>", "exec")
811 code = compile(timeit_ast, "<magic-timeit>", "exec")
783 tc = clock()-t0
812 tc = clock()-t0
784
813
785 ns = {}
814 ns = {}
General Comments 0
You need to be logged in to leave comments. Login now