##// END OF EJS Templates
Add new interactivity mode for ast....
Matthias Bussonnier -
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.
@@ -2749,7 +2760,7 b' class InteractiveShell(SingletonConfigurable):'
2749 return node
2760 return node
2750
2761
2751
2762
2752 def run_ast_nodes(self, nodelist, cell_name, interactivity='last_expr',
2763 def run_ast_nodes(self, nodelist:ListType[AST], cell_name:str, interactivity='last_expr',
2753 compiler=compile, result=None):
2764 compiler=compile, result=None):
2754 """Run a sequence of AST nodes. The execution mode depends on the
2765 """Run a sequence of AST nodes. The execution mode depends on the
2755 interactivity parameter.
2766 interactivity parameter.
@@ -2762,11 +2773,13 b' class InteractiveShell(SingletonConfigurable):'
2762 Will be passed to the compiler as the filename of the cell. Typically
2773 Will be passed to the compiler as the filename of the cell. Typically
2763 the value returned by ip.compile.cache(cell).
2774 the value returned by ip.compile.cache(cell).
2764 interactivity : str
2775 interactivity : str
2765 'all', 'last', 'last_expr' or 'none', specifying which nodes should be
2776 'all', 'last', 'last_expr' , 'last_expr_or_assign' or 'none',
2766 run interactively (displaying output from expressions). 'last_expr'
2777 specifying which nodes should be run interactively (displaying output
2767 will run the last node interactively only if it is an expression (i.e.
2778 from expressions). 'last_expr' will run the last node interactively
2768 expressions in loops or other blocks are not displayed. Other values
2779 only if it is an expression (i.e. expressions in loops or other blocks
2769 for this parameter will raise a ValueError.
2780 are not displayed) 'last_expr_or_assign' will run the last expression
2781 or the last assignment. Other values for this parameter will raise a
2782 ValueError.
2770 compiler : callable
2783 compiler : callable
2771 A function with the same interface as the built-in compile(), to turn
2784 A function with the same interface as the built-in compile(), to turn
2772 the AST nodes into code objects. Default is the built-in compile().
2785 the AST nodes into code objects. Default is the built-in compile().
@@ -2781,6 +2794,21 b' class InteractiveShell(SingletonConfigurable):'
2781 if not nodelist:
2794 if not nodelist:
2782 return
2795 return
2783
2796
2797 if interactivity == 'last_expr_or_assign':
2798 if isinstance(nodelist[-1], _assign_nodes):
2799 asg = nodelist[-1]
2800 if isinstance(asg, ast.Assign) and len(asg.targets) == 1:
2801 target = asg.targets[0]
2802 elif isinstance(asg, _single_targets_nodes):
2803 target = asg.target
2804 else:
2805 target = None
2806 if isinstance(target, ast.Name):
2807 nnode = ast.Expr(ast.Name(target.id, ast.Load()))
2808 ast.fix_missing_locations(nnode)
2809 nodelist.append(nnode)
2810 interactivity = 'last_expr'
2811
2784 if interactivity == 'last_expr':
2812 if interactivity == 'last_expr':
2785 if isinstance(nodelist[-1], ast.Expr):
2813 if isinstance(nodelist[-1], ast.Expr):
2786 interactivity = "last"
2814 interactivity = "last"
@@ -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