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