##// END OF EJS Templates
Merge pull request #10598 from Carreau/ast-interactivity...
Matthias Bussonnier -
r23743:beb08ba5 merge
parent child Browse files
Show More
@@ -0,0 +1,22 b''
1 IPython can now trigger the display hook on last assignment of cells.
2 Up until 6.0 the following code wouldn't show the value of the assigned
3 variable::
4
5 In[1]: xyz = "something"
6 # nothing shown
7
8 You would have to actually make it the last statement::
9
10 In [2]: xyz = "something else"
11 ... : xyz
12 Out[2]: "something else"
13
14 With the option ``InteractiveShell.ast_node_interactivity='last_expr_or_assign'``
15 you can now do::
16
17 In [2]: xyz = "something else"
18 Out[2]: "something else"
19
20 This option can be toggled at runtime with the ``%config`` magic, and will
21 trigger on assignment ``a = 1``, augmented assignment ``+=``, ``-=``, ``|=`` ...
22 as well as type annotated assignments: ``a:int = 2``.
@@ -79,6 +79,9 b' from warnings import warn'
79 from logging import error
79 from logging import error
80 import IPython.core.hooks
80 import IPython.core.hooks
81
81
82 from typing import List as ListType
83 from ast import AST
84
82 # NoOpContext is deprecated, but ipykernel imports it from here.
85 # NoOpContext is deprecated, but ipykernel imports it from here.
83 # See https://github.com/ipython/ipykernel/issues/157
86 # See https://github.com/ipython/ipykernel/issues/157
84 from IPython.utils.contexts import NoOpContext
87 from IPython.utils.contexts import NoOpContext
@@ -102,6 +105,13 b' class ProvisionalWarning(DeprecationWarning):'
102 """
105 """
103 pass
106 pass
104
107
108 if sys.version_info > (3,6):
109 _assign_nodes = (ast.AugAssign, ast.AnnAssign, ast.Assign)
110 _single_targets_nodes = (ast.AugAssign, ast.AnnAssign)
111 else:
112 _assign_nodes = (ast.AugAssign, ast.Assign )
113 _single_targets_nodes = (ast.AugAssign, )
114
105 #-----------------------------------------------------------------------------
115 #-----------------------------------------------------------------------------
106 # Globals
116 # Globals
107 #-----------------------------------------------------------------------------
117 #-----------------------------------------------------------------------------
@@ -376,11 +386,12 b' class InteractiveShell(SingletonConfigurable):'
376 """
386 """
377 ).tag(config=True)
387 ).tag(config=True)
378
388
379 ast_node_interactivity = Enum(['all', 'last', 'last_expr', 'none'],
389 ast_node_interactivity = Enum(['all', 'last', 'last_expr', 'none', 'last_expr_or_assign'],
380 default_value='last_expr',
390 default_value='last_expr',
381 help="""
391 help="""
382 'all', 'last', 'last_expr' or 'none', specifying which nodes should be
392 'all', 'last', 'last_expr' or 'none', 'last_expr_or_assign' specifying
383 run interactively (displaying output from expressions)."""
393 which nodes should be run interactively (displaying output from expressions).
394 """
384 ).tag(config=True)
395 ).tag(config=True)
385
396
386 # TODO: this part of prompt management should be moved to the frontends.
397 # TODO: this part of prompt management should be moved to the frontends.
@@ -2748,7 +2759,7 b' class InteractiveShell(SingletonConfigurable):'
2748 return node
2759 return node
2749
2760
2750
2761
2751 def run_ast_nodes(self, nodelist, cell_name, interactivity='last_expr',
2762 def run_ast_nodes(self, nodelist:ListType[AST], cell_name:str, interactivity='last_expr',
2752 compiler=compile, result=None):
2763 compiler=compile, result=None):
2753 """Run a sequence of AST nodes. The execution mode depends on the
2764 """Run a sequence of AST nodes. The execution mode depends on the
2754 interactivity parameter.
2765 interactivity parameter.
@@ -2761,11 +2772,13 b' class InteractiveShell(SingletonConfigurable):'
2761 Will be passed to the compiler as the filename of the cell. Typically
2772 Will be passed to the compiler as the filename of the cell. Typically
2762 the value returned by ip.compile.cache(cell).
2773 the value returned by ip.compile.cache(cell).
2763 interactivity : str
2774 interactivity : str
2764 'all', 'last', 'last_expr' or 'none', specifying which nodes should be
2775 'all', 'last', 'last_expr' , 'last_expr_or_assign' or 'none',
2765 run interactively (displaying output from expressions). 'last_expr'
2776 specifying which nodes should be run interactively (displaying output
2766 will run the last node interactively only if it is an expression (i.e.
2777 from expressions). 'last_expr' will run the last node interactively
2767 expressions in loops or other blocks are not displayed. Other values
2778 only if it is an expression (i.e. expressions in loops or other blocks
2768 for this parameter will raise a ValueError.
2779 are not displayed) 'last_expr_or_assign' will run the last expression
2780 or the last assignment. Other values for this parameter will raise a
2781 ValueError.
2769 compiler : callable
2782 compiler : callable
2770 A function with the same interface as the built-in compile(), to turn
2783 A function with the same interface as the built-in compile(), to turn
2771 the AST nodes into code objects. Default is the built-in compile().
2784 the AST nodes into code objects. Default is the built-in compile().
@@ -2780,6 +2793,21 b' class InteractiveShell(SingletonConfigurable):'
2780 if not nodelist:
2793 if not nodelist:
2781 return
2794 return
2782
2795
2796 if interactivity == 'last_expr_or_assign':
2797 if isinstance(nodelist[-1], _assign_nodes):
2798 asg = nodelist[-1]
2799 if isinstance(asg, ast.Assign) and len(asg.targets) == 1:
2800 target = asg.targets[0]
2801 elif isinstance(asg, _single_targets_nodes):
2802 target = asg.target
2803 else:
2804 target = None
2805 if isinstance(target, ast.Name):
2806 nnode = ast.Expr(ast.Name(target.id, ast.Load()))
2807 ast.fix_missing_locations(nnode)
2808 nodelist.append(nnode)
2809 interactivity = 'last_expr'
2810
2783 if interactivity == 'last_expr':
2811 if interactivity == 'last_expr':
2784 if isinstance(nodelist[-1], ast.Expr):
2812 if isinstance(nodelist[-1], ast.Expr):
2785 interactivity = "last"
2813 interactivity = "last"
@@ -2923,7 +2951,7 b' class InteractiveShell(SingletonConfigurable):'
2923 self.pylab_gui_select = gui
2951 self.pylab_gui_select = gui
2924 # Otherwise if they are different
2952 # Otherwise if they are different
2925 elif gui != self.pylab_gui_select:
2953 elif gui != self.pylab_gui_select:
2926 print ('Warning: Cannot change to a different GUI toolkit: %s.'
2954 print('Warning: Cannot change to a different GUI toolkit: %s.'
2927 ' Using %s instead.' % (gui, self.pylab_gui_select))
2955 ' Using %s instead.' % (gui, self.pylab_gui_select))
2928 gui, backend = pt.find_gui_and_backend(self.pylab_gui_select)
2956 gui, backend = pt.find_gui_and_backend(self.pylab_gui_select)
2929
2957
@@ -53,3 +53,51 b' def test_underscore_no_overrite_builtins():'
53 ip.run_cell('print(_)', store_history=True)
53 ip.run_cell('print(_)', store_history=True)
54 ip.run_cell('import builtins; del builtins._')
54 ip.run_cell('import builtins; del builtins._')
55
55
56
57 def test_interactivehooks_ast_modes():
58 """
59 Test that ast nodes can be triggerd with different modes
60 """
61 saved_mode = ip.ast_node_interactivity
62 ip.ast_node_interactivity = 'last_expr_or_assign'
63
64 try:
65 with AssertPrints('2'):
66 ip.run_cell('a = 1+1', store_history=True)
67
68 with AssertPrints('9'):
69 ip.run_cell('b = 1+8 # comment with a semicolon;', store_history=False)
70
71 with AssertPrints('7'):
72 ip.run_cell('c = 1+6\n#commented_out_function();', store_history=True)
73
74 ip.run_cell('d = 11', store_history=True)
75 with AssertPrints('12'):
76 ip.run_cell('d += 1', store_history=True)
77
78 with AssertNotPrints('42'):
79 ip.run_cell('(u,v) = (41+1, 43-1)')
80
81 finally:
82 ip.ast_node_interactivity = saved_mode
83
84 def test_interactivehooks_ast_modes_semi_supress():
85 """
86 Test that ast nodes can be triggerd with different modes and supressed
87 by semicolon
88 """
89 saved_mode = ip.ast_node_interactivity
90 ip.ast_node_interactivity = 'last_expr_or_assign'
91
92 try:
93 with AssertNotPrints('2'):
94 ip.run_cell('x = 1+1;', store_history=True)
95
96 with AssertNotPrints('7'):
97 ip.run_cell('y = 1+6; # comment with a semicolon', store_history=True)
98
99 with AssertNotPrints('9'):
100 ip.run_cell('z = 1+8;\n#commented_out_function()', store_history=True)
101
102 finally:
103 ip.ast_node_interactivity = saved_mode
General Comments 0
You need to be logged in to leave comments. Login now