##// END OF EJS Templates
Add framework for AST transformations of input code.
Thomas Kluyver -
Show More
@@ -199,6 +199,13 b' class InteractiveShell(SingletonConfigurable):'
199 """An enhanced, interactive shell for Python."""
199 """An enhanced, interactive shell for Python."""
200
200
201 _instance = None
201 _instance = None
202
203 ast_transformers = List([], config=True, help=
204 """
205 A list of ast.NodeTransformer subclass instances, which will be applied
206 to user input before code is run.
207 """
208 )
202
209
203 autocall = Enum((0,1,2), default_value=0, config=True, help=
210 autocall = Enum((0,1,2), default_value=0, config=True, help=
204 """
211 """
@@ -2630,6 +2637,8 b' class InteractiveShell(SingletonConfigurable):'
2630 self.execution_count += 1
2637 self.execution_count += 1
2631 return None
2638 return None
2632
2639
2640 code_ast = self.transform_ast(code_ast)
2641
2633 interactivity = "none" if silent else self.ast_node_interactivity
2642 interactivity = "none" if silent else self.ast_node_interactivity
2634 self.run_ast_nodes(code_ast.body, cell_name,
2643 self.run_ast_nodes(code_ast.body, cell_name,
2635 interactivity=interactivity)
2644 interactivity=interactivity)
@@ -2662,6 +2671,31 b' class InteractiveShell(SingletonConfigurable):'
2662 self.history_manager.store_output(self.execution_count)
2671 self.history_manager.store_output(self.execution_count)
2663 # Each cell is a *single* input, regardless of how many lines it has
2672 # Each cell is a *single* input, regardless of how many lines it has
2664 self.execution_count += 1
2673 self.execution_count += 1
2674
2675 def transform_ast(self, node):
2676 """Apply the AST transformations from self.ast_transformers
2677
2678 Parameters
2679 ----------
2680 node : ast.Node
2681 The root node to be transformed. Typically called with the ast.Module
2682 produced by parsing user input.
2683
2684 Returns
2685 -------
2686 An ast.Node corresponding to the node it was called with. Note that it
2687 may also modify the passed object, so don't rely on references to the
2688 original AST.
2689 """
2690 for transformer in self.ast_transformers:
2691 try:
2692 node = transformer.visit(node)
2693 except Exception:
2694 warn("AST transformer %r threw an error. It will be unregistered.")
2695 self.ast_transformers.remove(transformer)
2696
2697 return node
2698
2665
2699
2666 def run_ast_nodes(self, nodelist, cell_name, interactivity='last_expr'):
2700 def run_ast_nodes(self, nodelist, cell_name, interactivity='last_expr'):
2667 """Run a sequence of AST nodes. The execution mode depends on the
2701 """Run a sequence of AST nodes. The execution mode depends on the
@@ -20,6 +20,7 b' Authors'
20 # Imports
20 # Imports
21 #-----------------------------------------------------------------------------
21 #-----------------------------------------------------------------------------
22 # stdlib
22 # stdlib
23 import ast
23 import os
24 import os
24 import shutil
25 import shutil
25 import sys
26 import sys
@@ -414,6 +415,28 b' class TestModules(unittest.TestCase, tt.TempFileMixin):'
414 out = "False\nFalse\nFalse\n"
415 out = "False\nFalse\nFalse\n"
415 tt.ipexec_validate(self.fname, out)
416 tt.ipexec_validate(self.fname, out)
416
417
418 class Negator(ast.NodeTransformer):
419 """Negates all number literals in an AST."""
420 def visit_Num(self, node):
421 node.n = -node.n
422 return node
423
424 class TestAstTransform(unittest.TestCase):
425 def setUp(self):
426 self.negator = Negator()
427 ip.ast_transformers.append(self.negator)
428
429 def tearDown(self):
430 ip.ast_transformers.remove(self.negator)
431
432 def test_run_cell(self):
433 with tt.AssertPrints('-34'):
434 ip.run_cell('print (12 + 22)')
435
436 # A named reference to a number shouldn't be transformed.
437 ip.user_ns['n'] = 55
438 with tt.AssertNotPrints('-55'):
439 ip.run_cell('print (n)')
417
440
418 def test__IPYTHON__():
441 def test__IPYTHON__():
419 # This shouldn't raise a NameError, that's all
442 # This shouldn't raise a NameError, that's all
General Comments 0
You need to be logged in to leave comments. Login now