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