##// END OF EJS Templates
document
Matthias Bussonnier -
Show More
@@ -0,0 +1,2 b''
1 input_transformers can now have an attribute ``has_side_effects`` set to `True`, which will prevent the
2 transformers from being ran when IPython is trying to guess whether the user input is complete.
@@ -1,82 +1,90 b''
1
1
2 ===========================
2 ===========================
3 Custom input transformation
3 Custom input transformation
4 ===========================
4 ===========================
5
5
6 IPython extends Python syntax to allow things like magic commands, and help with
6 IPython extends Python syntax to allow things like magic commands, and help with
7 the ``?`` syntax. There are several ways to customise how the user's input is
7 the ``?`` syntax. There are several ways to customise how the user's input is
8 processed into Python code to be executed.
8 processed into Python code to be executed.
9
9
10 These hooks are mainly for other projects using IPython as the core of their
10 These hooks are mainly for other projects using IPython as the core of their
11 interactive interface. Using them carelessly can easily break IPython!
11 interactive interface. Using them carelessly can easily break IPython!
12
12
13 String based transformations
13 String based transformations
14 ============================
14 ============================
15
15
16 .. currentmodule:: IPython.core.inputtransforms
16 .. currentmodule:: IPython.core.inputtransforms
17
17
18 When the user enters code, it is first processed as a string. By the
18 When the user enters code, it is first processed as a string. By the
19 end of this stage, it must be valid Python syntax.
19 end of this stage, it must be valid Python syntax.
20
20
21 .. versionchanged:: 7.0
21 .. versionchanged:: 7.0
22
22
23 The API for string and token-based transformations has been completely
23 The API for string and token-based transformations has been completely
24 redesigned. Any third party code extending input transformation will need to
24 redesigned. Any third party code extending input transformation will need to
25 be rewritten. The new API is, hopefully, simpler.
25 be rewritten. The new API is, hopefully, simpler.
26
26
27 String based transformations are functions which accept a list of strings:
27 String based transformations are functions which accept a list of strings:
28 each string is a single line of the input cell, including its line ending.
28 each string is a single line of the input cell, including its line ending.
29 The transformation function should return output in the same structure.
29 The transformation function should return output in the same structure.
30
30
31 These transformations are in two groups, accessible as attributes of
31 These transformations are in two groups, accessible as attributes of
32 the :class:`~IPython.core.interactiveshell.InteractiveShell` instance.
32 the :class:`~IPython.core.interactiveshell.InteractiveShell` instance.
33 Each group is a list of transformation functions.
33 Each group is a list of transformation functions.
34
34
35 * ``input_transformers_cleanup`` run first on input, to do things like stripping
35 * ``input_transformers_cleanup`` run first on input, to do things like stripping
36 prompts and leading indents from copied code. It may not be possible at this
36 prompts and leading indents from copied code. It may not be possible at this
37 stage to parse the input as valid Python code.
37 stage to parse the input as valid Python code.
38 * Then IPython runs its own transformations to handle its special syntax, like
38 * Then IPython runs its own transformations to handle its special syntax, like
39 ``%magics`` and ``!system`` commands. This part does not expose extension
39 ``%magics`` and ``!system`` commands. This part does not expose extension
40 points.
40 points.
41 * ``input_transformers_post`` run as the last step, to do things like converting
41 * ``input_transformers_post`` run as the last step, to do things like converting
42 float literals into decimal objects. These may attempt to parse the input as
42 float literals into decimal objects. These may attempt to parse the input as
43 Python code.
43 Python code.
44
44
45 These transformers may raise :exc:`SyntaxError` if the input code is invalid, but
45 These transformers may raise :exc:`SyntaxError` if the input code is invalid, but
46 in most cases it is clearer to pass unrecognised code through unmodified and let
46 in most cases it is clearer to pass unrecognised code through unmodified and let
47 Python's own parser decide whether it is valid.
47 Python's own parser decide whether it is valid.
48
48
49 For example, imagine we want to obfuscate our code by reversing each line, so
49 For example, imagine we want to obfuscate our code by reversing each line, so
50 we'd write ``)5(f =+ a`` instead of ``a += f(5)``. Here's how we could swap it
50 we'd write ``)5(f =+ a`` instead of ``a += f(5)``. Here's how we could swap it
51 back the right way before IPython tries to run it::
51 back the right way before IPython tries to run it::
52
52
53 def reverse_line_chars(lines):
53 def reverse_line_chars(lines):
54 new_lines = []
54 new_lines = []
55 for line in lines:
55 for line in lines:
56 chars = line[:-1] # the newline needs to stay at the end
56 chars = line[:-1] # the newline needs to stay at the end
57 new_lines.append(chars[::-1] + '\n')
57 new_lines.append(chars[::-1] + '\n')
58 return new_lines
58 return new_lines
59
59
60 To start using this::
60 To start using this::
61
61
62 ip = get_ipython()
62 ip = get_ipython()
63 ip.input_transformers_cleanup.append(reverse_line_chars)
63 ip.input_transformers_cleanup.append(reverse_line_chars)
64
64
65 .. versionadded:: 7.17
66
67 input_transformers can now have an attribute ``has_side_effects`` set to
68 `True`, which will prevent the transformers from being ran when IPython is
69 trying to guess whether the user input is complete.
70
71
72
65 AST transformations
73 AST transformations
66 ===================
74 ===================
67
75
68 After the code has been parsed as Python syntax, you can use Python's powerful
76 After the code has been parsed as Python syntax, you can use Python's powerful
69 *Abstract Syntax Tree* tools to modify it. Subclass :class:`ast.NodeTransformer`,
77 *Abstract Syntax Tree* tools to modify it. Subclass :class:`ast.NodeTransformer`,
70 and add an instance to ``shell.ast_transformers``.
78 and add an instance to ``shell.ast_transformers``.
71
79
72 This example wraps integer literals in an ``Integer`` class, which is useful for
80 This example wraps integer literals in an ``Integer`` class, which is useful for
73 mathematical frameworks that want to handle e.g. ``1/3`` as a precise fraction::
81 mathematical frameworks that want to handle e.g. ``1/3`` as a precise fraction::
74
82
75
83
76 class IntegerWrapper(ast.NodeTransformer):
84 class IntegerWrapper(ast.NodeTransformer):
77 """Wraps all integers in a call to Integer()"""
85 """Wraps all integers in a call to Integer()"""
78 def visit_Num(self, node):
86 def visit_Num(self, node):
79 if isinstance(node.n, int):
87 if isinstance(node.n, int):
80 return ast.Call(func=ast.Name(id='Integer', ctx=ast.Load()),
88 return ast.Call(func=ast.Name(id='Integer', ctx=ast.Load()),
81 args=[node], keywords=[])
89 args=[node], keywords=[])
82 return node
90 return node
General Comments 0
You need to be logged in to leave comments. Login now