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 = |
|
|
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 |
|
|
|
138 |
|
|
|
139 |
|
|
|
140 |
|
|
|
141 |
|
|
|
142 |
|
|
|
143 |
|
|
|
144 |
|
|
|
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= |
|
|
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 = |
|
|
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 = |
|
|
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 = |
|
|
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 |
|
|
|
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 |
|
|
|
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