Repository: ipython/ipython

Issue:
Time magics shadow __future__.division
I regularly include `from __future__ import division` in the first cell of my notebooks, alongside `%pylab inline`.  I also frequently wish to identify bottlenecks in my code using the `%time` and `%%time` magics.  However, this occasionally causes subtle bugs, because a line using the `%time` magic or a cell using the `%%time` magic does not actually use `__future__.division`.

```
1/2
```

yields 0.5, but

```
%time 1/2
```

and

```
%%time
1/2
```

both yield 0.



Discussion:
Yes, these should be parsed and compiled in a way that preserves the shell futures flags. I've assigned this to myself - I think it should be an easy fix.


Resolving patch:
diff --git a/IPython/core/magics/execution.py b/IPython/core/magics/execution.py
--- a/IPython/core/magics/execution.py
+++ b/IPython/core/magics/execution.py
@@ -971,11 +971,11 @@ def timeit(self, line='', cell=None):
 
         if cell is None:
             # called as line magic
-            ast_setup = ast.parse("pass")
-            ast_stmt = ast.parse(transform(stmt))
+            ast_setup = self.shell.compile.ast_parse("pass")
+            ast_stmt = self.shell.compile.ast_parse(transform(stmt))
         else:
-            ast_setup = ast.parse(transform(stmt))
-            ast_stmt = ast.parse(transform(cell))
+            ast_setup = self.shell.compile.ast_parse(transform(stmt))
+            ast_stmt = self.shell.compile.ast_parse(transform(cell))
 
         ast_setup = self.shell.transform_ast(ast_setup)
         ast_stmt = self.shell.transform_ast(ast_stmt)
@@ -999,7 +999,7 @@ def timeit(self, line='', cell=None):
         tc_min = 0.1
 
         t0 = clock()
-        code = compile(timeit_ast, "<magic-timeit>", "exec")
+        code = self.shell.compile(timeit_ast, "<magic-timeit>", "exec")
         tc = clock()-t0
 
         ns = {}
@@ -1095,7 +1095,7 @@ def time(self,line='', cell=None, local_ns=None):
         tp_min = 0.1
 
         t0 = clock()
-        expr_ast = ast.parse(expr)
+        expr_ast = self.shell.compile.ast_parse(expr)
         tp = clock()-t0
 
         # Apply AST transformations
@@ -1112,7 +1112,7 @@ def time(self,line='', cell=None, local_ns=None):
             mode = 'exec'
             source = '<timed exec>'
         t0 = clock()
-        code = compile(expr_ast, source, mode)
+        code = self.shell.compile(expr_ast, source, mode)
         tc = clock()-t0
 
         # skew measurement as little as possible


Test patch:
diff --git a/IPython/core/tests/test_magic.py b/IPython/core/tests/test_magic.py
--- a/IPython/core/tests/test_magic.py
+++ b/IPython/core/tests/test_magic.py
@@ -381,6 +381,18 @@ def test_time3():
                     "run = 0\n"
                     "run += 1")
 
+@dec.skipif(sys.version_info[0] >= 3, "no differences with __future__ in py3")
+def test_time_futures():
+    "Test %time with __future__ environments"
+    ip = get_ipython()
+    ip.autocall = 0
+    ip.run_cell("from __future__ import division")
+    with tt.AssertPrints('0.25'):
+        ip.run_line_magic('time', 'print(1/4)')
+    ip.compile.reset_compiler_flags()
+    with tt.AssertNotPrints('0.25'):
+        ip.run_line_magic('time', 'print(1/4)')
+
 def test_doctest_mode():
     "Toggle doctest_mode twice, it should be a no-op and run without error"
     _ip.magic('doctest_mode')
@@ -560,6 +572,17 @@ def test_timeit_quiet():
     with tt.AssertNotPrints("loops"):
         _ip.run_cell("%timeit -n1 -r1 -q 1")
 
+@dec.skipif(sys.version_info[0] >= 3, "no differences with __future__ in py3")
+def test_timeit_futures():
+    "Test %timeit with __future__ environments"
+    ip = get_ipython()
+    ip.run_cell("from __future__ import division")
+    with tt.AssertPrints('0.25'):
+        ip.run_line_magic('timeit', '-n1 -r1 print(1/4)')
+    ip.compile.reset_compiler_flags()
+    with tt.AssertNotPrints('0.25'):
+        ip.run_line_magic('timeit', '-n1 -r1 print(1/4)')
+
 @dec.skipif(execution.profile is None)
 def test_prun_special_syntax():
     "Test %%prun with IPython special syntax"