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