##// END OF EJS Templates
Merge pull request #1671 from takluyver/back-to-the-future...
Thomas Kluyver -
r9163:0aacf477 merge
parent child Browse files
Show More
@@ -90,7 +90,7 b' class CachingCompiler(codeop.Compile):'
90 90 # Now, we must monkeypatch the linecache directly so that parts of the
91 91 # stdlib that call it outside our control go through our codepath
92 92 # (otherwise we'd lose our tracebacks).
93 linecache.checkcache = self.check_cache
93 linecache.checkcache = check_linecache_ipython
94 94
95 95 def ast_parse(self, source, filename='<unknown>', symbol='exec'):
96 96 """Parse code to an AST with the current compiler flags active.
@@ -134,11 +134,11 b' class CachingCompiler(codeop.Compile):'
134 134 linecache._ipython_cache[name] = entry
135 135 return name
136 136
137 def check_cache(self, *args):
138 """Call linecache.checkcache() safely protecting our cached values.
139 """
140 # First call the orignal checkcache as intended
141 linecache._checkcache_ori(*args)
142 # Then, update back the cache with our data, so that tracebacks related
143 # to our compiled codes can be produced.
144 linecache.cache.update(linecache._ipython_cache)
137 def check_linecache_ipython(*args):
138 """Call linecache.checkcache() safely protecting our cached values.
139 """
140 # First call the orignal checkcache as intended
141 linecache._checkcache_ori(*args)
142 # Then, update back the cache with our data, so that tracebacks related
143 # to our compiled codes can be produced.
144 linecache.cache.update(linecache._ipython_cache)
@@ -14,7 +14,6 b''
14 14 # Imports
15 15 #-----------------------------------------------------------------------------
16 16
17 from __future__ import with_statement
18 17 from __future__ import absolute_import
19 18 from __future__ import print_function
20 19
@@ -42,7 +41,7 b' from IPython.core import ultratb'
42 41 from IPython.core.alias import AliasManager, AliasError
43 42 from IPython.core.autocall import ExitAutocall
44 43 from IPython.core.builtin_trap import BuiltinTrap
45 from IPython.core.compilerop import CachingCompiler
44 from IPython.core.compilerop import CachingCompiler, check_linecache_ipython
46 45 from IPython.core.display_trap import DisplayTrap
47 46 from IPython.core.displayhook import DisplayHook
48 47 from IPython.core.displaypub import DisplayPublisher
@@ -1533,7 +1532,7 b' class InteractiveShell(SingletonConfigurable):'
1533 1532 self.InteractiveTB = ultratb.AutoFormattedTB(mode = 'Plain',
1534 1533 color_scheme='NoColor',
1535 1534 tb_offset = 1,
1536 check_cache=self.compile.check_cache)
1535 check_cache=check_linecache_ipython)
1537 1536
1538 1537 # The instance will store a pointer to the system-wide exception hook,
1539 1538 # so that runtime code (such as magics) can access it. This is because
@@ -2518,7 +2517,7 b' class InteractiveShell(SingletonConfigurable):'
2518 2517 # raised in user code. It would be nice if there were
2519 2518 # versions of runlines, execfile that did raise, so
2520 2519 # we could catch the errors.
2521 self.run_cell(thefile.read(), store_history=False)
2520 self.run_cell(thefile.read(), store_history=False, shell_futures=False)
2522 2521 except:
2523 2522 self.showtraceback()
2524 2523 warn('Unknown failure executing file: <%s>' % fname)
@@ -2552,7 +2551,7 b' class InteractiveShell(SingletonConfigurable):'
2552 2551 self._current_cell_magic_body = None
2553 2552 return self.run_cell_magic(magic_name, line, cell)
2554 2553
2555 def run_cell(self, raw_cell, store_history=False, silent=False):
2554 def run_cell(self, raw_cell, store_history=False, silent=False, shell_futures=True):
2556 2555 """Run a complete IPython cell.
2557 2556
2558 2557 Parameters
@@ -2566,6 +2565,11 b' class InteractiveShell(SingletonConfigurable):'
2566 2565 silent : bool
2567 2566 If True, avoid side-effects, such as implicit displayhooks and
2568 2567 and logging. silent=True forces store_history=False.
2568 shell_futures : bool
2569 If True, the code will share future statements with the interactive
2570 shell. It will both be affected by previous __future__ imports, and
2571 any __future__ imports in the code will affect the shell. If False,
2572 __future__ imports are not shared in either direction.
2569 2573 """
2570 2574 if (not raw_cell) or raw_cell.isspace():
2571 2575 return
@@ -2583,6 +2587,11 b' class InteractiveShell(SingletonConfigurable):'
2583 2587 self._current_cell_magic_body = \
2584 2588 ''.join(self.input_splitter.cell_magic_parts)
2585 2589 cell = self.input_splitter.source_reset()
2590
2591 # Our own compiler remembers the __future__ environment. If we want to
2592 # run code with a separate __future__ environment, use the default
2593 # compiler
2594 compiler = self.compile if shell_futures else CachingCompiler()
2586 2595
2587 2596 with self.builtin_trap:
2588 2597 prefilter_failed = False
@@ -2612,8 +2621,7 b' class InteractiveShell(SingletonConfigurable):'
2612 2621
2613 2622 with self.display_trap:
2614 2623 try:
2615 code_ast = self.compile.ast_parse(cell,
2616 filename=cell_name)
2624 code_ast = compiler.ast_parse(cell, filename=cell_name)
2617 2625 except IndentationError:
2618 2626 self.showindentationerror()
2619 2627 if store_history:
@@ -2630,7 +2638,7 b' class InteractiveShell(SingletonConfigurable):'
2630 2638
2631 2639 interactivity = "none" if silent else self.ast_node_interactivity
2632 2640 self.run_ast_nodes(code_ast.body, cell_name,
2633 interactivity=interactivity)
2641 interactivity=interactivity, compiler=compiler)
2634 2642
2635 2643 # Execute any registered post-execution functions.
2636 2644 # unless we are silent
@@ -2686,7 +2694,8 b' class InteractiveShell(SingletonConfigurable):'
2686 2694 return ast.fix_missing_locations(node)
2687 2695
2688 2696
2689 def run_ast_nodes(self, nodelist, cell_name, interactivity='last_expr'):
2697 def run_ast_nodes(self, nodelist, cell_name, interactivity='last_expr',
2698 compiler=compile):
2690 2699 """Run a sequence of AST nodes. The execution mode depends on the
2691 2700 interactivity parameter.
2692 2701
@@ -2703,6 +2712,9 b' class InteractiveShell(SingletonConfigurable):'
2703 2712 will run the last node interactively only if it is an expression (i.e.
2704 2713 expressions in loops or other blocks are not displayed. Other values
2705 2714 for this parameter will raise a ValueError.
2715 compiler : callable
2716 A function with the same interface as the built-in compile(), to turn
2717 the AST nodes into code objects. Default is the built-in compile().
2706 2718 """
2707 2719 if not nodelist:
2708 2720 return
@@ -2727,13 +2739,13 b' class InteractiveShell(SingletonConfigurable):'
2727 2739 try:
2728 2740 for i, node in enumerate(to_run_exec):
2729 2741 mod = ast.Module([node])
2730 code = self.compile(mod, cell_name, "exec")
2742 code = compiler(mod, cell_name, "exec")
2731 2743 if self.run_code(code):
2732 2744 return True
2733 2745
2734 2746 for i, node in enumerate(to_run_interactive):
2735 2747 mod = ast.Interactive([node])
2736 code = self.compile(mod, cell_name, "single")
2748 code = compiler(mod, cell_name, "single")
2737 2749 if self.run_code(code):
2738 2750 return True
2739 2751
@@ -67,7 +67,7 b' def test_compiler_check_cache():'
67 67 cp = compilerop.CachingCompiler()
68 68 cp.cache('x=1', 99)
69 69 # Ensure now that after clearing the cache, our entries survive
70 cp.check_cache()
70 linecache.checkcache()
71 71 for k in linecache.cache:
72 72 if k.startswith('<ipython-input-99'):
73 73 break
@@ -384,6 +384,22 b' class InteractiveShellTestCase(unittest.TestCase):'
384 384 finally:
385 385 # Reset the custom exception hook
386 386 ip.set_custom_exc((), None)
387
388 @skipif(sys.version_info[0] >= 3, "no differences with __future__ in py3")
389 def test_future_environment(self):
390 "Can we run code with & without the shell's __future__ imports?"
391 ip.run_cell("from __future__ import division")
392 ip.run_cell("a = 1/2", shell_futures=True)
393 self.assertEqual(ip.user_ns['a'], 0.5)
394 ip.run_cell("b = 1/2", shell_futures=False)
395 self.assertEqual(ip.user_ns['b'], 0)
396
397 ip.compile.reset_compiler_flags()
398 # This shouldn't leak to the shell's compiler
399 ip.run_cell("from __future__ import division \nc=1/2", shell_futures=False)
400 self.assertEqual(ip.user_ns['c'], 0.5)
401 ip.run_cell("d = 1/2", shell_futures=True)
402 self.assertEqual(ip.user_ns['d'], 0)
387 403
388 404
389 405 class TestSafeExecfileNonAsciiPath(unittest.TestCase):
@@ -827,7 +827,7 b' def test_edit_interactive():'
827 827 except code.InteractivelyDefined as e:
828 828 nt.assert_equal(e.index, n)
829 829 else:
830 nt.fail("Should have raised InteractivelyDefined")
830 raise AssertionError("Should have raised InteractivelyDefined")
831 831
832 832
833 833 def test_edit_cell():
General Comments 0
You need to be logged in to leave comments. Login now