##// END OF EJS Templates
Fix RST misformatting.
Jason Grout -
Show More
@@ -1,914 +1,914 b''
1 """Analysis of text input into executable blocks.
1 """Analysis of text input into executable blocks.
2
2
3 The main class in this module, :class:`InputSplitter`, is designed to break
3 The main class in this module, :class:`InputSplitter`, is designed to break
4 input from either interactive, line-by-line environments or block-based ones,
4 input from either interactive, line-by-line environments or block-based ones,
5 into standalone blocks that can be executed by Python as 'single' statements
5 into standalone blocks that can be executed by Python as 'single' statements
6 (thus triggering sys.displayhook).
6 (thus triggering sys.displayhook).
7
7
8 A companion, :class:`IPythonInputSplitter`, provides the same functionality but
8 A companion, :class:`IPythonInputSplitter`, provides the same functionality but
9 with full support for the extended IPython syntax (magics, system calls, etc).
9 with full support for the extended IPython syntax (magics, system calls, etc).
10
10
11 For more details, see the class docstring below.
11 For more details, see the class docstring below.
12
12
13 Syntax Transformations
13 Syntax Transformations
14 ----------------------
14 ----------------------
15
15
16 One of the main jobs of the code in this file is to apply all syntax
16 One of the main jobs of the code in this file is to apply all syntax
17 transformations that make up 'the IPython language', i.e. magics, shell
17 transformations that make up 'the IPython language', i.e. magics, shell
18 escapes, etc. All transformations should be implemented as *fully stateless*
18 escapes, etc. All transformations should be implemented as *fully stateless*
19 entities, that simply take one line as their input and return a line.
19 entities, that simply take one line as their input and return a line.
20 Internally for implementation purposes they may be a normal function or a
20 Internally for implementation purposes they may be a normal function or a
21 callable object, but the only input they receive will be a single line and they
21 callable object, but the only input they receive will be a single line and they
22 should only return a line, without holding any data-dependent state between
22 should only return a line, without holding any data-dependent state between
23 calls.
23 calls.
24
24
25 As an example, the EscapedTransformer is a class so we can more clearly group
25 As an example, the EscapedTransformer is a class so we can more clearly group
26 together the functionality of dispatching to individual functions based on the
26 together the functionality of dispatching to individual functions based on the
27 starting escape character, but the only method for public use is its call
27 starting escape character, but the only method for public use is its call
28 method.
28 method.
29
29
30
30
31 ToDo
31 ToDo
32 ----
32 ----
33
33
34 - Should we make push() actually raise an exception once push_accepts_more()
34 - Should we make push() actually raise an exception once push_accepts_more()
35 returns False?
35 returns False?
36
36
37 - Naming cleanups. The tr_* names aren't the most elegant, though now they are
37 - Naming cleanups. The tr_* names aren't the most elegant, though now they are
38 at least just attributes of a class so not really very exposed.
38 at least just attributes of a class so not really very exposed.
39
39
40 - Think about the best way to support dynamic things: automagic, autocall,
40 - Think about the best way to support dynamic things: automagic, autocall,
41 macros, etc.
41 macros, etc.
42
42
43 - Think of a better heuristic for the application of the transforms in
43 - Think of a better heuristic for the application of the transforms in
44 IPythonInputSplitter.push() than looking at the buffer ending in ':'. Idea:
44 IPythonInputSplitter.push() than looking at the buffer ending in ':'. Idea:
45 track indentation change events (indent, dedent, nothing) and apply them only
45 track indentation change events (indent, dedent, nothing) and apply them only
46 if the indentation went up, but not otherwise.
46 if the indentation went up, but not otherwise.
47
47
48 - Think of the cleanest way for supporting user-specified transformations (the
48 - Think of the cleanest way for supporting user-specified transformations (the
49 user prefilters we had before).
49 user prefilters we had before).
50
50
51 Authors
51 Authors
52 -------
52 -------
53
53
54 * Fernando Perez
54 * Fernando Perez
55 * Brian Granger
55 * Brian Granger
56 """
56 """
57 #-----------------------------------------------------------------------------
57 #-----------------------------------------------------------------------------
58 # Copyright (C) 2010 The IPython Development Team
58 # Copyright (C) 2010 The IPython Development Team
59 #
59 #
60 # Distributed under the terms of the BSD License. The full license is in
60 # Distributed under the terms of the BSD License. The full license is in
61 # the file COPYING, distributed as part of this software.
61 # the file COPYING, distributed as part of this software.
62 #-----------------------------------------------------------------------------
62 #-----------------------------------------------------------------------------
63
63
64 #-----------------------------------------------------------------------------
64 #-----------------------------------------------------------------------------
65 # Imports
65 # Imports
66 #-----------------------------------------------------------------------------
66 #-----------------------------------------------------------------------------
67 # stdlib
67 # stdlib
68 import ast
68 import ast
69 import codeop
69 import codeop
70 import re
70 import re
71 import sys
71 import sys
72 import tokenize
72 import tokenize
73 from StringIO import StringIO
73 from StringIO import StringIO
74
74
75 # IPython modules
75 # IPython modules
76 from IPython.core.splitinput import split_user_input, LineInfo
76 from IPython.core.splitinput import split_user_input, LineInfo
77 from IPython.utils.py3compat import cast_unicode
77 from IPython.utils.py3compat import cast_unicode
78
78
79 #-----------------------------------------------------------------------------
79 #-----------------------------------------------------------------------------
80 # Globals
80 # Globals
81 #-----------------------------------------------------------------------------
81 #-----------------------------------------------------------------------------
82
82
83 # The escape sequences that define the syntax transformations IPython will
83 # The escape sequences that define the syntax transformations IPython will
84 # apply to user input. These can NOT be just changed here: many regular
84 # apply to user input. These can NOT be just changed here: many regular
85 # expressions and other parts of the code may use their hardcoded values, and
85 # expressions and other parts of the code may use their hardcoded values, and
86 # for all intents and purposes they constitute the 'IPython syntax', so they
86 # for all intents and purposes they constitute the 'IPython syntax', so they
87 # should be considered fixed.
87 # should be considered fixed.
88
88
89 ESC_SHELL = '!' # Send line to underlying system shell
89 ESC_SHELL = '!' # Send line to underlying system shell
90 ESC_SH_CAP = '!!' # Send line to system shell and capture output
90 ESC_SH_CAP = '!!' # Send line to system shell and capture output
91 ESC_HELP = '?' # Find information about object
91 ESC_HELP = '?' # Find information about object
92 ESC_HELP2 = '??' # Find extra-detailed information about object
92 ESC_HELP2 = '??' # Find extra-detailed information about object
93 ESC_MAGIC = '%' # Call magic function
93 ESC_MAGIC = '%' # Call magic function
94 ESC_MAGIC2 = '%%' # Call cell-magic function
94 ESC_MAGIC2 = '%%' # Call cell-magic function
95 ESC_QUOTE = ',' # Split args on whitespace, quote each as string and call
95 ESC_QUOTE = ',' # Split args on whitespace, quote each as string and call
96 ESC_QUOTE2 = ';' # Quote all args as a single string, call
96 ESC_QUOTE2 = ';' # Quote all args as a single string, call
97 ESC_PAREN = '/' # Call first argument with rest of line as arguments
97 ESC_PAREN = '/' # Call first argument with rest of line as arguments
98
98
99 ESC_SEQUENCES = [ESC_SHELL, ESC_SH_CAP, ESC_HELP ,\
99 ESC_SEQUENCES = [ESC_SHELL, ESC_SH_CAP, ESC_HELP ,\
100 ESC_HELP2, ESC_MAGIC, ESC_MAGIC2,\
100 ESC_HELP2, ESC_MAGIC, ESC_MAGIC2,\
101 ESC_QUOTE, ESC_QUOTE2, ESC_PAREN ]
101 ESC_QUOTE, ESC_QUOTE2, ESC_PAREN ]
102
102
103 #-----------------------------------------------------------------------------
103 #-----------------------------------------------------------------------------
104 # Utilities
104 # Utilities
105 #-----------------------------------------------------------------------------
105 #-----------------------------------------------------------------------------
106
106
107 # FIXME: These are general-purpose utilities that later can be moved to the
107 # FIXME: These are general-purpose utilities that later can be moved to the
108 # general ward. Kept here for now because we're being very strict about test
108 # general ward. Kept here for now because we're being very strict about test
109 # coverage with this code, and this lets us ensure that we keep 100% coverage
109 # coverage with this code, and this lets us ensure that we keep 100% coverage
110 # while developing.
110 # while developing.
111
111
112 # compiled regexps for autoindent management
112 # compiled regexps for autoindent management
113 dedent_re = re.compile('|'.join([
113 dedent_re = re.compile('|'.join([
114 r'^\s+raise(\s.*)?$', # raise statement (+ space + other stuff, maybe)
114 r'^\s+raise(\s.*)?$', # raise statement (+ space + other stuff, maybe)
115 r'^\s+raise\([^\)]*\).*$', # wacky raise with immediate open paren
115 r'^\s+raise\([^\)]*\).*$', # wacky raise with immediate open paren
116 r'^\s+return(\s.*)?$', # normal return (+ space + other stuff, maybe)
116 r'^\s+return(\s.*)?$', # normal return (+ space + other stuff, maybe)
117 r'^\s+return\([^\)]*\).*$', # wacky return with immediate open paren
117 r'^\s+return\([^\)]*\).*$', # wacky return with immediate open paren
118 r'^\s+pass\s*$' # pass (optionally followed by trailing spaces)
118 r'^\s+pass\s*$' # pass (optionally followed by trailing spaces)
119 ]))
119 ]))
120 ini_spaces_re = re.compile(r'^([ \t\r\f\v]+)')
120 ini_spaces_re = re.compile(r'^([ \t\r\f\v]+)')
121
121
122 # regexp to match pure comment lines so we don't accidentally insert 'if 1:'
122 # regexp to match pure comment lines so we don't accidentally insert 'if 1:'
123 # before pure comments
123 # before pure comments
124 comment_line_re = re.compile('^\s*\#')
124 comment_line_re = re.compile('^\s*\#')
125
125
126
126
127 def num_ini_spaces(s):
127 def num_ini_spaces(s):
128 """Return the number of initial spaces in a string.
128 """Return the number of initial spaces in a string.
129
129
130 Note that tabs are counted as a single space. For now, we do *not* support
130 Note that tabs are counted as a single space. For now, we do *not* support
131 mixing of tabs and spaces in the user's input.
131 mixing of tabs and spaces in the user's input.
132
132
133 Parameters
133 Parameters
134 ----------
134 ----------
135 s : string
135 s : string
136
136
137 Returns
137 Returns
138 -------
138 -------
139 n : int
139 n : int
140 """
140 """
141
141
142 ini_spaces = ini_spaces_re.match(s)
142 ini_spaces = ini_spaces_re.match(s)
143 if ini_spaces:
143 if ini_spaces:
144 return ini_spaces.end()
144 return ini_spaces.end()
145 else:
145 else:
146 return 0
146 return 0
147
147
148 def last_blank(src):
148 def last_blank(src):
149 """Determine if the input source ends in a blank.
149 """Determine if the input source ends in a blank.
150
150
151 A blank is either a newline or a line consisting of whitespace.
151 A blank is either a newline or a line consisting of whitespace.
152
152
153 Parameters
153 Parameters
154 ----------
154 ----------
155 src : string
155 src : string
156 A single or multiline string.
156 A single or multiline string.
157 """
157 """
158 if not src: return False
158 if not src: return False
159 ll = src.splitlines()[-1]
159 ll = src.splitlines()[-1]
160 return (ll == '') or ll.isspace()
160 return (ll == '') or ll.isspace()
161
161
162
162
163 last_two_blanks_re = re.compile(r'\n\s*\n\s*$', re.MULTILINE)
163 last_two_blanks_re = re.compile(r'\n\s*\n\s*$', re.MULTILINE)
164 last_two_blanks_re2 = re.compile(r'.+\n\s*\n\s+$', re.MULTILINE)
164 last_two_blanks_re2 = re.compile(r'.+\n\s*\n\s+$', re.MULTILINE)
165
165
166 def last_two_blanks(src):
166 def last_two_blanks(src):
167 """Determine if the input source ends in two blanks.
167 """Determine if the input source ends in two blanks.
168
168
169 A blank is either a newline or a line consisting of whitespace.
169 A blank is either a newline or a line consisting of whitespace.
170
170
171 Parameters
171 Parameters
172 ----------
172 ----------
173 src : string
173 src : string
174 A single or multiline string.
174 A single or multiline string.
175 """
175 """
176 if not src: return False
176 if not src: return False
177 # The logic here is tricky: I couldn't get a regexp to work and pass all
177 # The logic here is tricky: I couldn't get a regexp to work and pass all
178 # the tests, so I took a different approach: split the source by lines,
178 # the tests, so I took a different approach: split the source by lines,
179 # grab the last two and prepend '###\n' as a stand-in for whatever was in
179 # grab the last two and prepend '###\n' as a stand-in for whatever was in
180 # the body before the last two lines. Then, with that structure, it's
180 # the body before the last two lines. Then, with that structure, it's
181 # possible to analyze with two regexps. Not the most elegant solution, but
181 # possible to analyze with two regexps. Not the most elegant solution, but
182 # it works. If anyone tries to change this logic, make sure to validate
182 # it works. If anyone tries to change this logic, make sure to validate
183 # the whole test suite first!
183 # the whole test suite first!
184 new_src = '\n'.join(['###\n'] + src.splitlines()[-2:])
184 new_src = '\n'.join(['###\n'] + src.splitlines()[-2:])
185 return (bool(last_two_blanks_re.match(new_src)) or
185 return (bool(last_two_blanks_re.match(new_src)) or
186 bool(last_two_blanks_re2.match(new_src)) )
186 bool(last_two_blanks_re2.match(new_src)) )
187
187
188
188
189 def remove_comments(src):
189 def remove_comments(src):
190 """Remove all comments from input source.
190 """Remove all comments from input source.
191
191
192 Note: comments are NOT recognized inside of strings!
192 Note: comments are NOT recognized inside of strings!
193
193
194 Parameters
194 Parameters
195 ----------
195 ----------
196 src : string
196 src : string
197 A single or multiline input string.
197 A single or multiline input string.
198
198
199 Returns
199 Returns
200 -------
200 -------
201 String with all Python comments removed.
201 String with all Python comments removed.
202 """
202 """
203
203
204 return re.sub('#.*', '', src)
204 return re.sub('#.*', '', src)
205
205
206 def has_comment(src):
206 def has_comment(src):
207 """Indicate whether an input line has (i.e. ends in, or is) a comment.
207 """Indicate whether an input line has (i.e. ends in, or is) a comment.
208
208
209 This uses tokenize, so it can distinguish comments from # inside strings.
209 This uses tokenize, so it can distinguish comments from # inside strings.
210
210
211 Parameters
211 Parameters
212 ----------
212 ----------
213 src : string
213 src : string
214 A single line input string.
214 A single line input string.
215
215
216 Returns
216 Returns
217 -------
217 -------
218 Boolean: True if source has a comment.
218 Boolean: True if source has a comment.
219 """
219 """
220 readline = StringIO(src).readline
220 readline = StringIO(src).readline
221 toktypes = set()
221 toktypes = set()
222 try:
222 try:
223 for t in tokenize.generate_tokens(readline):
223 for t in tokenize.generate_tokens(readline):
224 toktypes.add(t[0])
224 toktypes.add(t[0])
225 except tokenize.TokenError:
225 except tokenize.TokenError:
226 pass
226 pass
227 return(tokenize.COMMENT in toktypes)
227 return(tokenize.COMMENT in toktypes)
228
228
229
229
230 def get_input_encoding():
230 def get_input_encoding():
231 """Return the default standard input encoding.
231 """Return the default standard input encoding.
232
232
233 If sys.stdin has no encoding, 'ascii' is returned."""
233 If sys.stdin has no encoding, 'ascii' is returned."""
234 # There are strange environments for which sys.stdin.encoding is None. We
234 # There are strange environments for which sys.stdin.encoding is None. We
235 # ensure that a valid encoding is returned.
235 # ensure that a valid encoding is returned.
236 encoding = getattr(sys.stdin, 'encoding', None)
236 encoding = getattr(sys.stdin, 'encoding', None)
237 if encoding is None:
237 if encoding is None:
238 encoding = 'ascii'
238 encoding = 'ascii'
239 return encoding
239 return encoding
240
240
241 #-----------------------------------------------------------------------------
241 #-----------------------------------------------------------------------------
242 # Classes and functions for normal Python syntax handling
242 # Classes and functions for normal Python syntax handling
243 #-----------------------------------------------------------------------------
243 #-----------------------------------------------------------------------------
244
244
245 class InputSplitter(object):
245 class InputSplitter(object):
246 """An object that can accumulate lines of Python source before execution.
246 """An object that can accumulate lines of Python source before execution.
247
247
248 This object is designed to be fed python source line-by-line, using
248 This object is designed to be fed python source line-by-line, using
249 :meth:`push`. It will return on each push whether the currently pushed
249 :meth:`push`. It will return on each push whether the currently pushed
250 code could be executed already. In addition, it provides a method called
250 code could be executed already. In addition, it provides a method called
251 :meth:`push_accepts_more` that can be used to query whether more input
251 :meth:`push_accepts_more` that can be used to query whether more input
252 can be pushed into a single interactive block.
252 can be pushed into a single interactive block.
253
253
254 This is a simple example of how an interactive terminal-based client can use
254 This is a simple example of how an interactive terminal-based client can use
255 this tool::
255 this tool::
256
256
257 isp = InputSplitter()
257 isp = InputSplitter()
258 while isp.push_accepts_more():
258 while isp.push_accepts_more():
259 indent = ' '*isp.indent_spaces
259 indent = ' '*isp.indent_spaces
260 prompt = '>>> ' + indent
260 prompt = '>>> ' + indent
261 line = indent + raw_input(prompt)
261 line = indent + raw_input(prompt)
262 isp.push(line)
262 isp.push(line)
263 print 'Input source was:\n', isp.source_reset(),
263 print 'Input source was:\n', isp.source_reset(),
264 """
264 """
265 # Number of spaces of indentation computed from input that has been pushed
265 # Number of spaces of indentation computed from input that has been pushed
266 # so far. This is the attributes callers should query to get the current
266 # so far. This is the attributes callers should query to get the current
267 # indentation level, in order to provide auto-indent facilities.
267 # indentation level, in order to provide auto-indent facilities.
268 indent_spaces = 0
268 indent_spaces = 0
269 # String, indicating the default input encoding. It is computed by default
269 # String, indicating the default input encoding. It is computed by default
270 # at initialization time via get_input_encoding(), but it can be reset by a
270 # at initialization time via get_input_encoding(), but it can be reset by a
271 # client with specific knowledge of the encoding.
271 # client with specific knowledge of the encoding.
272 encoding = ''
272 encoding = ''
273 # String where the current full source input is stored, properly encoded.
273 # String where the current full source input is stored, properly encoded.
274 # Reading this attribute is the normal way of querying the currently pushed
274 # Reading this attribute is the normal way of querying the currently pushed
275 # source code, that has been properly encoded.
275 # source code, that has been properly encoded.
276 source = ''
276 source = ''
277 # Code object corresponding to the current source. It is automatically
277 # Code object corresponding to the current source. It is automatically
278 # synced to the source, so it can be queried at any time to obtain the code
278 # synced to the source, so it can be queried at any time to obtain the code
279 # object; it will be None if the source doesn't compile to valid Python.
279 # object; it will be None if the source doesn't compile to valid Python.
280 code = None
280 code = None
281 # Input mode
281 # Input mode
282 input_mode = 'line'
282 input_mode = 'line'
283
283
284 # Private attributes
284 # Private attributes
285
285
286 # List with lines of input accumulated so far
286 # List with lines of input accumulated so far
287 _buffer = None
287 _buffer = None
288 # Command compiler
288 # Command compiler
289 _compile = None
289 _compile = None
290 # Mark when input has changed indentation all the way back to flush-left
290 # Mark when input has changed indentation all the way back to flush-left
291 _full_dedent = False
291 _full_dedent = False
292 # Boolean indicating whether the current block is complete
292 # Boolean indicating whether the current block is complete
293 _is_complete = None
293 _is_complete = None
294
294
295 def __init__(self, input_mode=None):
295 def __init__(self, input_mode=None):
296 """Create a new InputSplitter instance.
296 """Create a new InputSplitter instance.
297
297
298 Parameters
298 Parameters
299 ----------
299 ----------
300 input_mode : str
300 input_mode : str
301
301
302 One of ['line', 'cell']; default is 'line'.
302 One of ['line', 'cell']; default is 'line'.
303
303
304 The input_mode parameter controls how new inputs are used when fed via
304 The input_mode parameter controls how new inputs are used when fed via
305 the :meth:`push` method:
305 the :meth:`push` method:
306
306
307 - 'line': meant for line-oriented clients, inputs are appended one at a
307 - 'line': meant for line-oriented clients, inputs are appended one at a
308 time to the internal buffer and the whole buffer is compiled.
308 time to the internal buffer and the whole buffer is compiled.
309
309
310 - 'cell': meant for clients that can edit multi-line 'cells' of text at
310 - 'cell': meant for clients that can edit multi-line 'cells' of text at
311 a time. A cell can contain one or more blocks that can be compile in
311 a time. A cell can contain one or more blocks that can be compile in
312 'single' mode by Python. In this mode, each new input new input
312 'single' mode by Python. In this mode, each new input new input
313 completely replaces all prior inputs. Cell mode is thus equivalent
313 completely replaces all prior inputs. Cell mode is thus equivalent
314 to prepending a full reset() to every push() call.
314 to prepending a full reset() to every push() call.
315 """
315 """
316 self._buffer = []
316 self._buffer = []
317 self._compile = codeop.CommandCompiler()
317 self._compile = codeop.CommandCompiler()
318 self.encoding = get_input_encoding()
318 self.encoding = get_input_encoding()
319 self.input_mode = InputSplitter.input_mode if input_mode is None \
319 self.input_mode = InputSplitter.input_mode if input_mode is None \
320 else input_mode
320 else input_mode
321
321
322 def reset(self):
322 def reset(self):
323 """Reset the input buffer and associated state."""
323 """Reset the input buffer and associated state."""
324 self.indent_spaces = 0
324 self.indent_spaces = 0
325 self._buffer[:] = []
325 self._buffer[:] = []
326 self.source = ''
326 self.source = ''
327 self.code = None
327 self.code = None
328 self._is_complete = False
328 self._is_complete = False
329 self._full_dedent = False
329 self._full_dedent = False
330
330
331 def source_reset(self):
331 def source_reset(self):
332 """Return the input source and perform a full reset.
332 """Return the input source and perform a full reset.
333 """
333 """
334 out = self.source
334 out = self.source
335 self.reset()
335 self.reset()
336 return out
336 return out
337
337
338 def push(self, lines):
338 def push(self, lines):
339 """Push one or more lines of input.
339 """Push one or more lines of input.
340
340
341 This stores the given lines and returns a status code indicating
341 This stores the given lines and returns a status code indicating
342 whether the code forms a complete Python block or not.
342 whether the code forms a complete Python block or not.
343
343
344 Any exceptions generated in compilation are swallowed, but if an
344 Any exceptions generated in compilation are swallowed, but if an
345 exception was produced, the method returns True.
345 exception was produced, the method returns True.
346
346
347 Parameters
347 Parameters
348 ----------
348 ----------
349 lines : string
349 lines : string
350 One or more lines of Python input.
350 One or more lines of Python input.
351
351
352 Returns
352 Returns
353 -------
353 -------
354 is_complete : boolean
354 is_complete : boolean
355 True if the current input source (the result of the current input
355 True if the current input source (the result of the current input
356 plus prior inputs) forms a complete Python execution block. Note that
356 plus prior inputs) forms a complete Python execution block. Note that
357 this value is also stored as a private attribute (_is_complete), so it
357 this value is also stored as a private attribute (``_is_complete``), so it
358 can be queried at any time.
358 can be queried at any time.
359 """
359 """
360 if self.input_mode == 'cell':
360 if self.input_mode == 'cell':
361 self.reset()
361 self.reset()
362
362
363 self._store(lines)
363 self._store(lines)
364 source = self.source
364 source = self.source
365
365
366 # Before calling _compile(), reset the code object to None so that if an
366 # Before calling _compile(), reset the code object to None so that if an
367 # exception is raised in compilation, we don't mislead by having
367 # exception is raised in compilation, we don't mislead by having
368 # inconsistent code/source attributes.
368 # inconsistent code/source attributes.
369 self.code, self._is_complete = None, None
369 self.code, self._is_complete = None, None
370
370
371 # Honor termination lines properly
371 # Honor termination lines properly
372 if source.rstrip().endswith('\\'):
372 if source.rstrip().endswith('\\'):
373 return False
373 return False
374
374
375 self._update_indent(lines)
375 self._update_indent(lines)
376 try:
376 try:
377 self.code = self._compile(source, symbol="exec")
377 self.code = self._compile(source, symbol="exec")
378 # Invalid syntax can produce any of a number of different errors from
378 # Invalid syntax can produce any of a number of different errors from
379 # inside the compiler, so we have to catch them all. Syntax errors
379 # inside the compiler, so we have to catch them all. Syntax errors
380 # immediately produce a 'ready' block, so the invalid Python can be
380 # immediately produce a 'ready' block, so the invalid Python can be
381 # sent to the kernel for evaluation with possible ipython
381 # sent to the kernel for evaluation with possible ipython
382 # special-syntax conversion.
382 # special-syntax conversion.
383 except (SyntaxError, OverflowError, ValueError, TypeError,
383 except (SyntaxError, OverflowError, ValueError, TypeError,
384 MemoryError):
384 MemoryError):
385 self._is_complete = True
385 self._is_complete = True
386 else:
386 else:
387 # Compilation didn't produce any exceptions (though it may not have
387 # Compilation didn't produce any exceptions (though it may not have
388 # given a complete code object)
388 # given a complete code object)
389 self._is_complete = self.code is not None
389 self._is_complete = self.code is not None
390
390
391 return self._is_complete
391 return self._is_complete
392
392
393 def push_accepts_more(self):
393 def push_accepts_more(self):
394 """Return whether a block of interactive input can accept more input.
394 """Return whether a block of interactive input can accept more input.
395
395
396 This method is meant to be used by line-oriented frontends, who need to
396 This method is meant to be used by line-oriented frontends, who need to
397 guess whether a block is complete or not based solely on prior and
397 guess whether a block is complete or not based solely on prior and
398 current input lines. The InputSplitter considers it has a complete
398 current input lines. The InputSplitter considers it has a complete
399 interactive block and will not accept more input only when either a
399 interactive block and will not accept more input only when either a
400 SyntaxError is raised, or *all* of the following are true:
400 SyntaxError is raised, or *all* of the following are true:
401
401
402 1. The input compiles to a complete statement.
402 1. The input compiles to a complete statement.
403
403
404 2. The indentation level is flush-left (because if we are indented,
404 2. The indentation level is flush-left (because if we are indented,
405 like inside a function definition or for loop, we need to keep
405 like inside a function definition or for loop, we need to keep
406 reading new input).
406 reading new input).
407
407
408 3. There is one extra line consisting only of whitespace.
408 3. There is one extra line consisting only of whitespace.
409
409
410 Because of condition #3, this method should be used only by
410 Because of condition #3, this method should be used only by
411 *line-oriented* frontends, since it means that intermediate blank lines
411 *line-oriented* frontends, since it means that intermediate blank lines
412 are not allowed in function definitions (or any other indented block).
412 are not allowed in function definitions (or any other indented block).
413
413
414 If the current input produces a syntax error, this method immediately
414 If the current input produces a syntax error, this method immediately
415 returns False but does *not* raise the syntax error exception, as
415 returns False but does *not* raise the syntax error exception, as
416 typically clients will want to send invalid syntax to an execution
416 typically clients will want to send invalid syntax to an execution
417 backend which might convert the invalid syntax into valid Python via
417 backend which might convert the invalid syntax into valid Python via
418 one of the dynamic IPython mechanisms.
418 one of the dynamic IPython mechanisms.
419 """
419 """
420
420
421 # With incomplete input, unconditionally accept more
421 # With incomplete input, unconditionally accept more
422 if not self._is_complete:
422 if not self._is_complete:
423 return True
423 return True
424
424
425 # If we already have complete input and we're flush left, the answer
425 # If we already have complete input and we're flush left, the answer
426 # depends. In line mode, if there hasn't been any indentation,
426 # depends. In line mode, if there hasn't been any indentation,
427 # that's it. If we've come back from some indentation, we need
427 # that's it. If we've come back from some indentation, we need
428 # the blank final line to finish.
428 # the blank final line to finish.
429 # In cell mode, we need to check how many blocks the input so far
429 # In cell mode, we need to check how many blocks the input so far
430 # compiles into, because if there's already more than one full
430 # compiles into, because if there's already more than one full
431 # independent block of input, then the client has entered full
431 # independent block of input, then the client has entered full
432 # 'cell' mode and is feeding lines that each is complete. In this
432 # 'cell' mode and is feeding lines that each is complete. In this
433 # case we should then keep accepting. The Qt terminal-like console
433 # case we should then keep accepting. The Qt terminal-like console
434 # does precisely this, to provide the convenience of terminal-like
434 # does precisely this, to provide the convenience of terminal-like
435 # input of single expressions, but allowing the user (with a
435 # input of single expressions, but allowing the user (with a
436 # separate keystroke) to switch to 'cell' mode and type multiple
436 # separate keystroke) to switch to 'cell' mode and type multiple
437 # expressions in one shot.
437 # expressions in one shot.
438 if self.indent_spaces==0:
438 if self.indent_spaces==0:
439 if self.input_mode=='line':
439 if self.input_mode=='line':
440 if not self._full_dedent:
440 if not self._full_dedent:
441 return False
441 return False
442 else:
442 else:
443 try:
443 try:
444 code_ast = ast.parse(u''.join(self._buffer))
444 code_ast = ast.parse(u''.join(self._buffer))
445 except Exception:
445 except Exception:
446 return False
446 return False
447 else:
447 else:
448 if len(code_ast.body) == 1:
448 if len(code_ast.body) == 1:
449 return False
449 return False
450
450
451 # When input is complete, then termination is marked by an extra blank
451 # When input is complete, then termination is marked by an extra blank
452 # line at the end.
452 # line at the end.
453 last_line = self.source.splitlines()[-1]
453 last_line = self.source.splitlines()[-1]
454 return bool(last_line and not last_line.isspace())
454 return bool(last_line and not last_line.isspace())
455
455
456 #------------------------------------------------------------------------
456 #------------------------------------------------------------------------
457 # Private interface
457 # Private interface
458 #------------------------------------------------------------------------
458 #------------------------------------------------------------------------
459
459
460 def _find_indent(self, line):
460 def _find_indent(self, line):
461 """Compute the new indentation level for a single line.
461 """Compute the new indentation level for a single line.
462
462
463 Parameters
463 Parameters
464 ----------
464 ----------
465 line : str
465 line : str
466 A single new line of non-whitespace, non-comment Python input.
466 A single new line of non-whitespace, non-comment Python input.
467
467
468 Returns
468 Returns
469 -------
469 -------
470 indent_spaces : int
470 indent_spaces : int
471 New value for the indent level (it may be equal to self.indent_spaces
471 New value for the indent level (it may be equal to self.indent_spaces
472 if indentation doesn't change.
472 if indentation doesn't change.
473
473
474 full_dedent : boolean
474 full_dedent : boolean
475 Whether the new line causes a full flush-left dedent.
475 Whether the new line causes a full flush-left dedent.
476 """
476 """
477 indent_spaces = self.indent_spaces
477 indent_spaces = self.indent_spaces
478 full_dedent = self._full_dedent
478 full_dedent = self._full_dedent
479
479
480 inisp = num_ini_spaces(line)
480 inisp = num_ini_spaces(line)
481 if inisp < indent_spaces:
481 if inisp < indent_spaces:
482 indent_spaces = inisp
482 indent_spaces = inisp
483 if indent_spaces <= 0:
483 if indent_spaces <= 0:
484 #print 'Full dedent in text',self.source # dbg
484 #print 'Full dedent in text',self.source # dbg
485 full_dedent = True
485 full_dedent = True
486
486
487 if line.rstrip()[-1] == ':':
487 if line.rstrip()[-1] == ':':
488 indent_spaces += 4
488 indent_spaces += 4
489 elif dedent_re.match(line):
489 elif dedent_re.match(line):
490 indent_spaces -= 4
490 indent_spaces -= 4
491 if indent_spaces <= 0:
491 if indent_spaces <= 0:
492 full_dedent = True
492 full_dedent = True
493
493
494 # Safety
494 # Safety
495 if indent_spaces < 0:
495 if indent_spaces < 0:
496 indent_spaces = 0
496 indent_spaces = 0
497 #print 'safety' # dbg
497 #print 'safety' # dbg
498
498
499 return indent_spaces, full_dedent
499 return indent_spaces, full_dedent
500
500
501 def _update_indent(self, lines):
501 def _update_indent(self, lines):
502 for line in remove_comments(lines).splitlines():
502 for line in remove_comments(lines).splitlines():
503 if line and not line.isspace():
503 if line and not line.isspace():
504 self.indent_spaces, self._full_dedent = self._find_indent(line)
504 self.indent_spaces, self._full_dedent = self._find_indent(line)
505
505
506 def _store(self, lines, buffer=None, store='source'):
506 def _store(self, lines, buffer=None, store='source'):
507 """Store one or more lines of input.
507 """Store one or more lines of input.
508
508
509 If input lines are not newline-terminated, a newline is automatically
509 If input lines are not newline-terminated, a newline is automatically
510 appended."""
510 appended."""
511
511
512 if buffer is None:
512 if buffer is None:
513 buffer = self._buffer
513 buffer = self._buffer
514
514
515 if lines.endswith('\n'):
515 if lines.endswith('\n'):
516 buffer.append(lines)
516 buffer.append(lines)
517 else:
517 else:
518 buffer.append(lines+'\n')
518 buffer.append(lines+'\n')
519 setattr(self, store, self._set_source(buffer))
519 setattr(self, store, self._set_source(buffer))
520
520
521 def _set_source(self, buffer):
521 def _set_source(self, buffer):
522 return u''.join(buffer)
522 return u''.join(buffer)
523
523
524
524
525 #-----------------------------------------------------------------------------
525 #-----------------------------------------------------------------------------
526 # Functions and classes for IPython-specific syntactic support
526 # Functions and classes for IPython-specific syntactic support
527 #-----------------------------------------------------------------------------
527 #-----------------------------------------------------------------------------
528
528
529 # The escaped translators ALL receive a line where their own escape has been
529 # The escaped translators ALL receive a line where their own escape has been
530 # stripped. Only '?' is valid at the end of the line, all others can only be
530 # stripped. Only '?' is valid at the end of the line, all others can only be
531 # placed at the start.
531 # placed at the start.
532
532
533 # Transformations of the special syntaxes that don't rely on an explicit escape
533 # Transformations of the special syntaxes that don't rely on an explicit escape
534 # character but instead on patterns on the input line
534 # character but instead on patterns on the input line
535
535
536 # The core transformations are implemented as standalone functions that can be
536 # The core transformations are implemented as standalone functions that can be
537 # tested and validated in isolation. Each of these uses a regexp, we
537 # tested and validated in isolation. Each of these uses a regexp, we
538 # pre-compile these and keep them close to each function definition for clarity
538 # pre-compile these and keep them close to each function definition for clarity
539
539
540 _assign_system_re = re.compile(r'(?P<lhs>(\s*)([\w\.]+)((\s*,\s*[\w\.]+)*))'
540 _assign_system_re = re.compile(r'(?P<lhs>(\s*)([\w\.]+)((\s*,\s*[\w\.]+)*))'
541 r'\s*=\s*!\s*(?P<cmd>.*)')
541 r'\s*=\s*!\s*(?P<cmd>.*)')
542
542
543 def transform_assign_system(line):
543 def transform_assign_system(line):
544 """Handle the `files = !ls` syntax."""
544 """Handle the `files = !ls` syntax."""
545 m = _assign_system_re.match(line)
545 m = _assign_system_re.match(line)
546 if m is not None:
546 if m is not None:
547 cmd = m.group('cmd')
547 cmd = m.group('cmd')
548 lhs = m.group('lhs')
548 lhs = m.group('lhs')
549 new_line = '%s = get_ipython().getoutput(%r)' % (lhs, cmd)
549 new_line = '%s = get_ipython().getoutput(%r)' % (lhs, cmd)
550 return new_line
550 return new_line
551 return line
551 return line
552
552
553
553
554 _assign_magic_re = re.compile(r'(?P<lhs>(\s*)([\w\.]+)((\s*,\s*[\w\.]+)*))'
554 _assign_magic_re = re.compile(r'(?P<lhs>(\s*)([\w\.]+)((\s*,\s*[\w\.]+)*))'
555 r'\s*=\s*%\s*(?P<cmd>.*)')
555 r'\s*=\s*%\s*(?P<cmd>.*)')
556
556
557 def transform_assign_magic(line):
557 def transform_assign_magic(line):
558 """Handle the `a = %who` syntax."""
558 """Handle the `a = %who` syntax."""
559 m = _assign_magic_re.match(line)
559 m = _assign_magic_re.match(line)
560 if m is not None:
560 if m is not None:
561 cmd = m.group('cmd')
561 cmd = m.group('cmd')
562 lhs = m.group('lhs')
562 lhs = m.group('lhs')
563 new_line = '%s = get_ipython().magic(%r)' % (lhs, cmd)
563 new_line = '%s = get_ipython().magic(%r)' % (lhs, cmd)
564 return new_line
564 return new_line
565 return line
565 return line
566
566
567
567
568 _classic_prompt_re = re.compile(r'^([ \t]*>>> |^[ \t]*\.\.\. )')
568 _classic_prompt_re = re.compile(r'^([ \t]*>>> |^[ \t]*\.\.\. )')
569
569
570 def transform_classic_prompt(line):
570 def transform_classic_prompt(line):
571 """Handle inputs that start with '>>> ' syntax."""
571 """Handle inputs that start with '>>> ' syntax."""
572
572
573 if not line or line.isspace():
573 if not line or line.isspace():
574 return line
574 return line
575 m = _classic_prompt_re.match(line)
575 m = _classic_prompt_re.match(line)
576 if m:
576 if m:
577 return line[len(m.group(0)):]
577 return line[len(m.group(0)):]
578 else:
578 else:
579 return line
579 return line
580
580
581
581
582 _ipy_prompt_re = re.compile(r'^([ \t]*In \[\d+\]: |^[ \t]*\ \ \ \.\.\.+: )')
582 _ipy_prompt_re = re.compile(r'^([ \t]*In \[\d+\]: |^[ \t]*\ \ \ \.\.\.+: )')
583
583
584 def transform_ipy_prompt(line):
584 def transform_ipy_prompt(line):
585 """Handle inputs that start classic IPython prompt syntax."""
585 """Handle inputs that start classic IPython prompt syntax."""
586
586
587 if not line or line.isspace():
587 if not line or line.isspace():
588 return line
588 return line
589 #print 'LINE: %r' % line # dbg
589 #print 'LINE: %r' % line # dbg
590 m = _ipy_prompt_re.match(line)
590 m = _ipy_prompt_re.match(line)
591 if m:
591 if m:
592 #print 'MATCH! %r -> %r' % (line, line[len(m.group(0)):]) # dbg
592 #print 'MATCH! %r -> %r' % (line, line[len(m.group(0)):]) # dbg
593 return line[len(m.group(0)):]
593 return line[len(m.group(0)):]
594 else:
594 else:
595 return line
595 return line
596
596
597
597
598 def _make_help_call(target, esc, lspace, next_input=None):
598 def _make_help_call(target, esc, lspace, next_input=None):
599 """Prepares a pinfo(2)/psearch call from a target name and the escape
599 """Prepares a pinfo(2)/psearch call from a target name and the escape
600 (i.e. ? or ??)"""
600 (i.e. ? or ??)"""
601 method = 'pinfo2' if esc == '??' \
601 method = 'pinfo2' if esc == '??' \
602 else 'psearch' if '*' in target \
602 else 'psearch' if '*' in target \
603 else 'pinfo'
603 else 'pinfo'
604 arg = " ".join([method, target])
604 arg = " ".join([method, target])
605 if next_input is None:
605 if next_input is None:
606 return '%sget_ipython().magic(%r)' % (lspace, arg)
606 return '%sget_ipython().magic(%r)' % (lspace, arg)
607 else:
607 else:
608 return '%sget_ipython().set_next_input(%r);get_ipython().magic(%r)' % \
608 return '%sget_ipython().set_next_input(%r);get_ipython().magic(%r)' % \
609 (lspace, next_input, arg)
609 (lspace, next_input, arg)
610
610
611
611
612 _initial_space_re = re.compile(r'\s*')
612 _initial_space_re = re.compile(r'\s*')
613
613
614 _help_end_re = re.compile(r"""(%{0,2}
614 _help_end_re = re.compile(r"""(%{0,2}
615 [a-zA-Z_*][\w*]* # Variable name
615 [a-zA-Z_*][\w*]* # Variable name
616 (\.[a-zA-Z_*][\w*]*)* # .etc.etc
616 (\.[a-zA-Z_*][\w*]*)* # .etc.etc
617 )
617 )
618 (\?\??)$ # ? or ??""",
618 (\?\??)$ # ? or ??""",
619 re.VERBOSE)
619 re.VERBOSE)
620
620
621
621
622 def transform_help_end(line):
622 def transform_help_end(line):
623 """Translate lines with ?/?? at the end"""
623 """Translate lines with ?/?? at the end"""
624 m = _help_end_re.search(line)
624 m = _help_end_re.search(line)
625 if m is None or has_comment(line):
625 if m is None or has_comment(line):
626 return line
626 return line
627 target = m.group(1)
627 target = m.group(1)
628 esc = m.group(3)
628 esc = m.group(3)
629 lspace = _initial_space_re.match(line).group(0)
629 lspace = _initial_space_re.match(line).group(0)
630
630
631 # If we're mid-command, put it back on the next prompt for the user.
631 # If we're mid-command, put it back on the next prompt for the user.
632 next_input = line.rstrip('?') if line.strip() != m.group(0) else None
632 next_input = line.rstrip('?') if line.strip() != m.group(0) else None
633
633
634 return _make_help_call(target, esc, lspace, next_input)
634 return _make_help_call(target, esc, lspace, next_input)
635
635
636
636
637 class EscapedTransformer(object):
637 class EscapedTransformer(object):
638 """Class to transform lines that are explicitly escaped out."""
638 """Class to transform lines that are explicitly escaped out."""
639
639
640 def __init__(self):
640 def __init__(self):
641 tr = { ESC_SHELL : self._tr_system,
641 tr = { ESC_SHELL : self._tr_system,
642 ESC_SH_CAP : self._tr_system2,
642 ESC_SH_CAP : self._tr_system2,
643 ESC_HELP : self._tr_help,
643 ESC_HELP : self._tr_help,
644 ESC_HELP2 : self._tr_help,
644 ESC_HELP2 : self._tr_help,
645 ESC_MAGIC : self._tr_magic,
645 ESC_MAGIC : self._tr_magic,
646 ESC_QUOTE : self._tr_quote,
646 ESC_QUOTE : self._tr_quote,
647 ESC_QUOTE2 : self._tr_quote2,
647 ESC_QUOTE2 : self._tr_quote2,
648 ESC_PAREN : self._tr_paren }
648 ESC_PAREN : self._tr_paren }
649 self.tr = tr
649 self.tr = tr
650
650
651 # Support for syntax transformations that use explicit escapes typed by the
651 # Support for syntax transformations that use explicit escapes typed by the
652 # user at the beginning of a line
652 # user at the beginning of a line
653 @staticmethod
653 @staticmethod
654 def _tr_system(line_info):
654 def _tr_system(line_info):
655 "Translate lines escaped with: !"
655 "Translate lines escaped with: !"
656 cmd = line_info.line.lstrip().lstrip(ESC_SHELL)
656 cmd = line_info.line.lstrip().lstrip(ESC_SHELL)
657 return '%sget_ipython().system(%r)' % (line_info.pre, cmd)
657 return '%sget_ipython().system(%r)' % (line_info.pre, cmd)
658
658
659 @staticmethod
659 @staticmethod
660 def _tr_system2(line_info):
660 def _tr_system2(line_info):
661 "Translate lines escaped with: !!"
661 "Translate lines escaped with: !!"
662 cmd = line_info.line.lstrip()[2:]
662 cmd = line_info.line.lstrip()[2:]
663 return '%sget_ipython().getoutput(%r)' % (line_info.pre, cmd)
663 return '%sget_ipython().getoutput(%r)' % (line_info.pre, cmd)
664
664
665 @staticmethod
665 @staticmethod
666 def _tr_help(line_info):
666 def _tr_help(line_info):
667 "Translate lines escaped with: ?/??"
667 "Translate lines escaped with: ?/??"
668 # A naked help line should just fire the intro help screen
668 # A naked help line should just fire the intro help screen
669 if not line_info.line[1:]:
669 if not line_info.line[1:]:
670 return 'get_ipython().show_usage()'
670 return 'get_ipython().show_usage()'
671
671
672 return _make_help_call(line_info.ifun, line_info.esc, line_info.pre)
672 return _make_help_call(line_info.ifun, line_info.esc, line_info.pre)
673
673
674 @staticmethod
674 @staticmethod
675 def _tr_magic(line_info):
675 def _tr_magic(line_info):
676 "Translate lines escaped with: %"
676 "Translate lines escaped with: %"
677 tpl = '%sget_ipython().magic(%r)'
677 tpl = '%sget_ipython().magic(%r)'
678 cmd = ' '.join([line_info.ifun, line_info.the_rest]).strip()
678 cmd = ' '.join([line_info.ifun, line_info.the_rest]).strip()
679 return tpl % (line_info.pre, cmd)
679 return tpl % (line_info.pre, cmd)
680
680
681 @staticmethod
681 @staticmethod
682 def _tr_quote(line_info):
682 def _tr_quote(line_info):
683 "Translate lines escaped with: ,"
683 "Translate lines escaped with: ,"
684 return '%s%s("%s")' % (line_info.pre, line_info.ifun,
684 return '%s%s("%s")' % (line_info.pre, line_info.ifun,
685 '", "'.join(line_info.the_rest.split()) )
685 '", "'.join(line_info.the_rest.split()) )
686
686
687 @staticmethod
687 @staticmethod
688 def _tr_quote2(line_info):
688 def _tr_quote2(line_info):
689 "Translate lines escaped with: ;"
689 "Translate lines escaped with: ;"
690 return '%s%s("%s")' % (line_info.pre, line_info.ifun,
690 return '%s%s("%s")' % (line_info.pre, line_info.ifun,
691 line_info.the_rest)
691 line_info.the_rest)
692
692
693 @staticmethod
693 @staticmethod
694 def _tr_paren(line_info):
694 def _tr_paren(line_info):
695 "Translate lines escaped with: /"
695 "Translate lines escaped with: /"
696 return '%s%s(%s)' % (line_info.pre, line_info.ifun,
696 return '%s%s(%s)' % (line_info.pre, line_info.ifun,
697 ", ".join(line_info.the_rest.split()))
697 ", ".join(line_info.the_rest.split()))
698
698
699 def __call__(self, line):
699 def __call__(self, line):
700 """Class to transform lines that are explicitly escaped out.
700 """Class to transform lines that are explicitly escaped out.
701
701
702 This calls the above _tr_* static methods for the actual line
702 This calls the above _tr_* static methods for the actual line
703 translations."""
703 translations."""
704
704
705 # Empty lines just get returned unmodified
705 # Empty lines just get returned unmodified
706 if not line or line.isspace():
706 if not line or line.isspace():
707 return line
707 return line
708
708
709 # Get line endpoints, where the escapes can be
709 # Get line endpoints, where the escapes can be
710 line_info = LineInfo(line)
710 line_info = LineInfo(line)
711
711
712 if not line_info.esc in self.tr:
712 if not line_info.esc in self.tr:
713 # If we don't recognize the escape, don't modify the line
713 # If we don't recognize the escape, don't modify the line
714 return line
714 return line
715
715
716 return self.tr[line_info.esc](line_info)
716 return self.tr[line_info.esc](line_info)
717
717
718
718
719 # A function-looking object to be used by the rest of the code. The purpose of
719 # A function-looking object to be used by the rest of the code. The purpose of
720 # the class in this case is to organize related functionality, more than to
720 # the class in this case is to organize related functionality, more than to
721 # manage state.
721 # manage state.
722 transform_escaped = EscapedTransformer()
722 transform_escaped = EscapedTransformer()
723
723
724
724
725 class IPythonInputSplitter(InputSplitter):
725 class IPythonInputSplitter(InputSplitter):
726 """An input splitter that recognizes all of IPython's special syntax."""
726 """An input splitter that recognizes all of IPython's special syntax."""
727
727
728 # String with raw, untransformed input.
728 # String with raw, untransformed input.
729 source_raw = ''
729 source_raw = ''
730
730
731 # Flag to track when we're in the middle of processing a cell magic, since
731 # Flag to track when we're in the middle of processing a cell magic, since
732 # the logic has to change. In that case, we apply no transformations at
732 # the logic has to change. In that case, we apply no transformations at
733 # all.
733 # all.
734 processing_cell_magic = False
734 processing_cell_magic = False
735
735
736 # Storage for all blocks of input that make up a cell magic
736 # Storage for all blocks of input that make up a cell magic
737 cell_magic_parts = []
737 cell_magic_parts = []
738
738
739 # Private attributes
739 # Private attributes
740
740
741 # List with lines of raw input accumulated so far.
741 # List with lines of raw input accumulated so far.
742 _buffer_raw = None
742 _buffer_raw = None
743
743
744 def __init__(self, input_mode=None):
744 def __init__(self, input_mode=None):
745 super(IPythonInputSplitter, self).__init__(input_mode)
745 super(IPythonInputSplitter, self).__init__(input_mode)
746 self._buffer_raw = []
746 self._buffer_raw = []
747 self._validate = True
747 self._validate = True
748
748
749 def reset(self):
749 def reset(self):
750 """Reset the input buffer and associated state."""
750 """Reset the input buffer and associated state."""
751 super(IPythonInputSplitter, self).reset()
751 super(IPythonInputSplitter, self).reset()
752 self._buffer_raw[:] = []
752 self._buffer_raw[:] = []
753 self.source_raw = ''
753 self.source_raw = ''
754 self.cell_magic_parts = []
754 self.cell_magic_parts = []
755 self.processing_cell_magic = False
755 self.processing_cell_magic = False
756
756
757 def source_raw_reset(self):
757 def source_raw_reset(self):
758 """Return input and raw source and perform a full reset.
758 """Return input and raw source and perform a full reset.
759 """
759 """
760 out = self.source
760 out = self.source
761 out_r = self.source_raw
761 out_r = self.source_raw
762 self.reset()
762 self.reset()
763 return out, out_r
763 return out, out_r
764
764
765 def push_accepts_more(self):
765 def push_accepts_more(self):
766 if self.processing_cell_magic:
766 if self.processing_cell_magic:
767 return not self._is_complete
767 return not self._is_complete
768 else:
768 else:
769 return super(IPythonInputSplitter, self).push_accepts_more()
769 return super(IPythonInputSplitter, self).push_accepts_more()
770
770
771 def _handle_cell_magic(self, lines):
771 def _handle_cell_magic(self, lines):
772 """Process lines when they start with %%, which marks cell magics.
772 """Process lines when they start with %%, which marks cell magics.
773 """
773 """
774 self.processing_cell_magic = True
774 self.processing_cell_magic = True
775 first, _, body = lines.partition('\n')
775 first, _, body = lines.partition('\n')
776 magic_name, _, line = first.partition(' ')
776 magic_name, _, line = first.partition(' ')
777 magic_name = magic_name.lstrip(ESC_MAGIC)
777 magic_name = magic_name.lstrip(ESC_MAGIC)
778 # We store the body of the cell and create a call to a method that
778 # We store the body of the cell and create a call to a method that
779 # will use this stored value. This is ugly, but it's a first cut to
779 # will use this stored value. This is ugly, but it's a first cut to
780 # get it all working, as right now changing the return API of our
780 # get it all working, as right now changing the return API of our
781 # methods would require major refactoring.
781 # methods would require major refactoring.
782 self.cell_magic_parts = [body]
782 self.cell_magic_parts = [body]
783 tpl = 'get_ipython()._run_cached_cell_magic(%r, %r)'
783 tpl = 'get_ipython()._run_cached_cell_magic(%r, %r)'
784 tlines = tpl % (magic_name, line)
784 tlines = tpl % (magic_name, line)
785 self._store(tlines)
785 self._store(tlines)
786 self._store(lines, self._buffer_raw, 'source_raw')
786 self._store(lines, self._buffer_raw, 'source_raw')
787 # We can actually choose whether to allow for single blank lines here
787 # We can actually choose whether to allow for single blank lines here
788 # during input for clients that use cell mode to decide when to stop
788 # during input for clients that use cell mode to decide when to stop
789 # pushing input (currently only the Qt console).
789 # pushing input (currently only the Qt console).
790 # My first implementation did that, and then I realized it wasn't
790 # My first implementation did that, and then I realized it wasn't
791 # consistent with the terminal behavior, so I've reverted it to one
791 # consistent with the terminal behavior, so I've reverted it to one
792 # line. But I'm leaving it here so we can easily test both behaviors,
792 # line. But I'm leaving it here so we can easily test both behaviors,
793 # I kind of liked having full blank lines allowed in the cell magics...
793 # I kind of liked having full blank lines allowed in the cell magics...
794 #self._is_complete = last_two_blanks(lines)
794 #self._is_complete = last_two_blanks(lines)
795 self._is_complete = last_blank(lines)
795 self._is_complete = last_blank(lines)
796 return self._is_complete
796 return self._is_complete
797
797
798 def _line_mode_cell_append(self, lines):
798 def _line_mode_cell_append(self, lines):
799 """Append new content for a cell magic in line mode.
799 """Append new content for a cell magic in line mode.
800 """
800 """
801 # Only store the raw input. Lines beyond the first one are only only
801 # Only store the raw input. Lines beyond the first one are only only
802 # stored for history purposes; for execution the caller will grab the
802 # stored for history purposes; for execution the caller will grab the
803 # magic pieces from cell_magic_parts and will assemble the cell body
803 # magic pieces from cell_magic_parts and will assemble the cell body
804 self._store(lines, self._buffer_raw, 'source_raw')
804 self._store(lines, self._buffer_raw, 'source_raw')
805 self.cell_magic_parts.append(lines)
805 self.cell_magic_parts.append(lines)
806 # Find out if the last stored block has a whitespace line as its
806 # Find out if the last stored block has a whitespace line as its
807 # last line and also this line is whitespace, case in which we're
807 # last line and also this line is whitespace, case in which we're
808 # done (two contiguous blank lines signal termination). Note that
808 # done (two contiguous blank lines signal termination). Note that
809 # the storage logic *enforces* that every stored block is
809 # the storage logic *enforces* that every stored block is
810 # newline-terminated, so we grab everything but the last character
810 # newline-terminated, so we grab everything but the last character
811 # so we can have the body of the block alone.
811 # so we can have the body of the block alone.
812 last_block = self.cell_magic_parts[-1]
812 last_block = self.cell_magic_parts[-1]
813 self._is_complete = last_blank(last_block) and lines.isspace()
813 self._is_complete = last_blank(last_block) and lines.isspace()
814 return self._is_complete
814 return self._is_complete
815
815
816 def transform_cell(self, cell):
816 def transform_cell(self, cell):
817 """Process and translate a cell of input.
817 """Process and translate a cell of input.
818 """
818 """
819 self.reset()
819 self.reset()
820 self.push(cell)
820 self.push(cell)
821 return self.source_reset()
821 return self.source_reset()
822
822
823 def push(self, lines):
823 def push(self, lines):
824 """Push one or more lines of IPython input.
824 """Push one or more lines of IPython input.
825
825
826 This stores the given lines and returns a status code indicating
826 This stores the given lines and returns a status code indicating
827 whether the code forms a complete Python block or not, after processing
827 whether the code forms a complete Python block or not, after processing
828 all input lines for special IPython syntax.
828 all input lines for special IPython syntax.
829
829
830 Any exceptions generated in compilation are swallowed, but if an
830 Any exceptions generated in compilation are swallowed, but if an
831 exception was produced, the method returns True.
831 exception was produced, the method returns True.
832
832
833 Parameters
833 Parameters
834 ----------
834 ----------
835 lines : string
835 lines : string
836 One or more lines of Python input.
836 One or more lines of Python input.
837
837
838 Returns
838 Returns
839 -------
839 -------
840 is_complete : boolean
840 is_complete : boolean
841 True if the current input source (the result of the current input
841 True if the current input source (the result of the current input
842 plus prior inputs) forms a complete Python execution block. Note that
842 plus prior inputs) forms a complete Python execution block. Note that
843 this value is also stored as a private attribute (_is_complete), so it
843 this value is also stored as a private attribute (_is_complete), so it
844 can be queried at any time.
844 can be queried at any time.
845 """
845 """
846 if not lines:
846 if not lines:
847 return super(IPythonInputSplitter, self).push(lines)
847 return super(IPythonInputSplitter, self).push(lines)
848
848
849 # We must ensure all input is pure unicode
849 # We must ensure all input is pure unicode
850 lines = cast_unicode(lines, self.encoding)
850 lines = cast_unicode(lines, self.encoding)
851
851
852 # If the entire input block is a cell magic, return after handling it
852 # If the entire input block is a cell magic, return after handling it
853 # as the rest of the transformation logic should be skipped.
853 # as the rest of the transformation logic should be skipped.
854 if lines.startswith('%%') and not \
854 if lines.startswith('%%') and not \
855 (len(lines.splitlines()) == 1 and lines.strip().endswith('?')):
855 (len(lines.splitlines()) == 1 and lines.strip().endswith('?')):
856 return self._handle_cell_magic(lines)
856 return self._handle_cell_magic(lines)
857
857
858 # In line mode, a cell magic can arrive in separate pieces
858 # In line mode, a cell magic can arrive in separate pieces
859 if self.input_mode == 'line' and self.processing_cell_magic:
859 if self.input_mode == 'line' and self.processing_cell_magic:
860 return self._line_mode_cell_append(lines)
860 return self._line_mode_cell_append(lines)
861
861
862 # The rest of the processing is for 'normal' content, i.e. IPython
862 # The rest of the processing is for 'normal' content, i.e. IPython
863 # source that we process through our transformations pipeline.
863 # source that we process through our transformations pipeline.
864 lines_list = lines.splitlines()
864 lines_list = lines.splitlines()
865
865
866 transforms = [transform_ipy_prompt, transform_classic_prompt,
866 transforms = [transform_ipy_prompt, transform_classic_prompt,
867 transform_help_end, transform_escaped,
867 transform_help_end, transform_escaped,
868 transform_assign_system, transform_assign_magic]
868 transform_assign_system, transform_assign_magic]
869
869
870 # Transform logic
870 # Transform logic
871 #
871 #
872 # We only apply the line transformers to the input if we have either no
872 # We only apply the line transformers to the input if we have either no
873 # input yet, or complete input, or if the last line of the buffer ends
873 # input yet, or complete input, or if the last line of the buffer ends
874 # with ':' (opening an indented block). This prevents the accidental
874 # with ':' (opening an indented block). This prevents the accidental
875 # transformation of escapes inside multiline expressions like
875 # transformation of escapes inside multiline expressions like
876 # triple-quoted strings or parenthesized expressions.
876 # triple-quoted strings or parenthesized expressions.
877 #
877 #
878 # The last heuristic, while ugly, ensures that the first line of an
878 # The last heuristic, while ugly, ensures that the first line of an
879 # indented block is correctly transformed.
879 # indented block is correctly transformed.
880 #
880 #
881 # FIXME: try to find a cleaner approach for this last bit.
881 # FIXME: try to find a cleaner approach for this last bit.
882
882
883 # If we were in 'block' mode, since we're going to pump the parent
883 # If we were in 'block' mode, since we're going to pump the parent
884 # class by hand line by line, we need to temporarily switch out to
884 # class by hand line by line, we need to temporarily switch out to
885 # 'line' mode, do a single manual reset and then feed the lines one
885 # 'line' mode, do a single manual reset and then feed the lines one
886 # by one. Note that this only matters if the input has more than one
886 # by one. Note that this only matters if the input has more than one
887 # line.
887 # line.
888 changed_input_mode = False
888 changed_input_mode = False
889
889
890 if self.input_mode == 'cell':
890 if self.input_mode == 'cell':
891 self.reset()
891 self.reset()
892 changed_input_mode = True
892 changed_input_mode = True
893 saved_input_mode = 'cell'
893 saved_input_mode = 'cell'
894 self.input_mode = 'line'
894 self.input_mode = 'line'
895
895
896 # Store raw source before applying any transformations to it. Note
896 # Store raw source before applying any transformations to it. Note
897 # that this must be done *after* the reset() call that would otherwise
897 # that this must be done *after* the reset() call that would otherwise
898 # flush the buffer.
898 # flush the buffer.
899 self._store(lines, self._buffer_raw, 'source_raw')
899 self._store(lines, self._buffer_raw, 'source_raw')
900
900
901 try:
901 try:
902 push = super(IPythonInputSplitter, self).push
902 push = super(IPythonInputSplitter, self).push
903 buf = self._buffer
903 buf = self._buffer
904 for line in lines_list:
904 for line in lines_list:
905 if self._is_complete or not buf or \
905 if self._is_complete or not buf or \
906 (buf and buf[-1].rstrip().endswith((':', ','))):
906 (buf and buf[-1].rstrip().endswith((':', ','))):
907 for f in transforms:
907 for f in transforms:
908 line = f(line)
908 line = f(line)
909
909
910 out = push(line)
910 out = push(line)
911 finally:
911 finally:
912 if changed_input_mode:
912 if changed_input_mode:
913 self.input_mode = saved_input_mode
913 self.input_mode = saved_input_mode
914 return out
914 return out
General Comments 0
You need to be logged in to leave comments. Login now