##// END OF EJS Templates
Completed first pass of inputsplitter with IPython syntax....
Fernando Perez -
Show More
@@ -6,6 +6,11 b" into standalone blocks that can be executed by Python as 'single' statements"
6 6 (thus triggering sys.displayhook).
7 7
8 8 For more details, see the class docstring below.
9
10 Authors
11
12 * Fernando Perez
13 * Brian Granger
9 14 """
10 15 #-----------------------------------------------------------------------------
11 16 # Copyright (C) 2010 The IPython Development Team
@@ -26,10 +31,32 b' import sys'
26 31 from IPython.utils.text import make_quoted_expr
27 32
28 33 #-----------------------------------------------------------------------------
34 # Globals
35 #-----------------------------------------------------------------------------
36
37 # The escape sequences that define the syntax transformations IPython will
38 # apply to user input. These can NOT be just changed here: many regular
39 # expressions and other parts of the code may use their hardcoded values, and
40 # for all intents and purposes they constitute the 'IPython syntax', so they
41 # should be considered fixed.
42
43 ESC_SHELL = '!'
44 ESC_SH_CAP = '!!'
45 ESC_HELP = '?'
46 ESC_HELP2 = '??'
47 ESC_MAGIC = '%'
48 ESC_QUOTE = ','
49 ESC_QUOTE2 = ';'
50 ESC_PAREN = '/'
51
52 #-----------------------------------------------------------------------------
29 53 # Utilities
30 54 #-----------------------------------------------------------------------------
31 55
32 # FIXME: move these utilities to the general ward...
56 # FIXME: These are general-purpose utilities that later can be moved to the
57 # general ward. Kept here for now because we're being very strict about test
58 # coverage with this code, and this lets us ensure that we keep 100% coverage
59 # while developing.
33 60
34 61 # compiled regexps for autoindent management
35 62 dedent_re = re.compile(r'^\s+raise|^\s+return|^\s+pass')
@@ -88,7 +115,7 b' def get_input_encoding():'
88 115 return encoding
89 116
90 117 #-----------------------------------------------------------------------------
91 # Classes and functions
118 # Classes and functions for normal Python syntax handling
92 119 #-----------------------------------------------------------------------------
93 120
94 121 class InputSplitter(object):
@@ -425,14 +452,140 b' class InputSplitter(object):'
425 452
426 453
427 454 #-----------------------------------------------------------------------------
428 # IPython-specific syntactic support
455 # Functions and classes for IPython-specific syntactic support
429 456 #-----------------------------------------------------------------------------
430 457
431 # We implement things, as much as possible, as standalone functions that can be
432 # tested and validated in isolation.
458 # RegExp for splitting line contents into pre-char//first word-method//rest.
459 # For clarity, each group in on one line.
460
461 line_split = re.compile("""
462 ^(\s*) # any leading space
463 ([,;/%]|!!?|\?\??) # escape character or characters
464 \s*([\w\.]*) # function/method part (mix of \w and '.')
465 (\s+.*$|$) # rest of line
466 """, re.VERBOSE)
467
468
469 def split_user_input(line):
470 """Split user input into early whitespace, esc-char, function part and rest.
471
472 This is currently handles lines with '=' in them in a very inconsistent
473 manner.
474
475 Examples
476 ========
477 >>> split_user_input('x=1')
478 ('', '', 'x=1', '')
479 >>> split_user_input('?')
480 ('', '?', '', '')
481 >>> split_user_input('??')
482 ('', '??', '', '')
483 >>> split_user_input(' ?')
484 (' ', '?', '', '')
485 >>> split_user_input(' ??')
486 (' ', '??', '', '')
487 >>> split_user_input('??x')
488 ('', '??', 'x', '')
489 >>> split_user_input('?x=1')
490 ('', '', '?x=1', '')
491 >>> split_user_input('!ls')
492 ('', '!', 'ls', '')
493 >>> split_user_input(' !ls')
494 (' ', '!', 'ls', '')
495 >>> split_user_input('!!ls')
496 ('', '!!', 'ls', '')
497 >>> split_user_input(' !!ls')
498 (' ', '!!', 'ls', '')
499 >>> split_user_input(',ls')
500 ('', ',', 'ls', '')
501 >>> split_user_input(';ls')
502 ('', ';', 'ls', '')
503 >>> split_user_input(' ;ls')
504 (' ', ';', 'ls', '')
505 >>> split_user_input('f.g(x)')
506 ('', '', 'f.g(x)', '')
507 >>> split_user_input('f.g (x)')
508 ('', '', 'f.g', '(x)')
509 """
510 match = line_split.match(line)
511 if match:
512 lspace, esc, fpart, rest = match.groups()
513 else:
514 # print "match failed for line '%s'" % line
515 try:
516 fpart, rest = line.split(None,1)
517 except ValueError:
518 # print "split failed for line '%s'" % line
519 fpart, rest = line,''
520 lspace = re.match('^(\s*)(.*)',line).groups()[0]
521 esc = ''
522
523 # fpart has to be a valid python identifier, so it better be only pure
524 # ascii, no unicode:
525 try:
526 fpart = fpart.encode('ascii')
527 except UnicodeEncodeError:
528 lspace = unicode(lspace)
529 rest = fpart + u' ' + rest
530 fpart = u''
531
532 #print 'line:<%s>' % line # dbg
533 #print 'esc <%s> fpart <%s> rest <%s>' % (esc,fpart.strip(),rest) # dbg
534 return lspace, esc, fpart.strip(), rest.lstrip()
535
536
537 # The escaped translators ALL receive a line where their own escape has been
538 # stripped. Only '?' is valid at the end of the line, all others can only be
539 # placed at the start.
540
541 class LineInfo(object):
542 """A single line of input and associated info.
543
544 This is a utility class that mostly wraps the output of
545 :func:`split_user_input` into a convenient object to be passed around
546 during input transformations.
547
548 Includes the following as properties:
549
550 line
551 The original, raw line
552
553 lspace
554 Any early whitespace before actual text starts.
555
556 esc
557 The initial esc character (or characters, for double-char escapes like
558 '??' or '!!').
559
560 pre_char
561 The escape character(s) in esc or the empty string if there isn't one.
562
563 fpart
564 The 'function part', which is basically the maximal initial sequence
565 of valid python identifiers and the '.' character. This is what is
566 checked for alias and magic transformations, used for auto-calling,
567 etc.
568
569 rest
570 Everything else on the line.
571 """
572 def __init__(self, line):
573 self.line = line
574 self.lspace, self.esc, self.fpart, self.rest = \
575 split_user_input(line)
576
577 def __str__(self):
578 return "LineInfo [%s|%s|%s|%s]" % (self.lspace, self.esc,
579 self.fpart, self.rest)
580
581
582 # Transformations of the special syntaxes that don't rely on an explicit escape
583 # character but instead on patterns on the input line
584
585 # The core transformations are implemented as standalone functions that can be
586 # tested and validated in isolation. Each of these uses a regexp, we
587 # pre-compile these and keep them close to each function definition for clarity
433 588
434 # Each of these uses a regexp, we pre-compile these and keep them close to each
435 # function definition for clarity
436 589 _assign_system_re = re.compile(r'(?P<lhs>(\s*)([\w\.]+)((\s*,\s*[\w\.]+)*))'
437 590 r'\s*=\s*!\s*(?P<cmd>.*)')
438 591
@@ -467,16 +620,13 b' def transform_assign_magic(line):'
467 620 return line
468 621
469 622
470 _classic_prompt_re = re.compile(r'(^[ \t]*>>> |^[ \t]*\.\.\. )')
623 _classic_prompt_re = re.compile(r'^([ \t]*>>> |^[ \t]*\.\.\. )')
471 624
472 625 def transform_classic_prompt(line):
473 626 """Handle inputs that start with '>>> ' syntax."""
474 627
475 if not line or line.isspace() or line.strip() == '...':
476 # This allows us to recognize multiple input prompts separated by
477 # blank lines and pasted in a single chunk, very common when
478 # pasting doctests or long tutorial passages.
479 return ''
628 if not line or line.isspace():
629 return line
480 630 m = _classic_prompt_re.match(line)
481 631 if m:
482 632 return line[len(m.group(0)):]
@@ -484,16 +634,13 b' def transform_classic_prompt(line):'
484 634 return line
485 635
486 636
487 _ipy_prompt_re = re.compile(r'(^[ \t]*In \[\d+\]: |^[ \t]*\ \ \ \.\.\.+: )')
637 _ipy_prompt_re = re.compile(r'^([ \t]*In \[\d+\]: |^[ \t]*\ \ \ \.\.\.+: )')
488 638
489 639 def transform_ipy_prompt(line):
490 640 """Handle inputs that start classic IPython prompt syntax."""
491 641
492 if not line or line.isspace() or line.strip() == '...':
493 # This allows us to recognize multiple input prompts separated by
494 # blank lines and pasted in a single chunk, very common when
495 # pasting doctests or long tutorial passages.
496 return ''
642 if not line or line.isspace():
643 return line
497 644 m = _ipy_prompt_re.match(line)
498 645 if m:
499 646 return line[len(m.group(0)):]
@@ -501,21 +648,151 b' def transform_ipy_prompt(line):'
501 648 return line
502 649
503 650
504 # Warning, these cannot be changed unless various regular expressions
505 # are updated in a number of places. Not great, but at least we told you.
506 ESC_SHELL = '!'
507 ESC_SH_CAP = '!!'
508 ESC_HELP = '?'
509 ESC_MAGIC = '%'
510 ESC_QUOTE = ','
511 ESC_QUOTE2 = ';'
512 ESC_PAREN = '/'
651 def transform_unescaped(line):
652 """Transform lines that are explicitly escaped out.
653
654 This calls to the above transform_* functions for the actual line
655 translations.
656
657 Parameters
658 ----------
659 line : str
660 A single line of input to be transformed.
661
662 Returns
663 -------
664 new_line : str
665 Transformed line, which may be identical to the original."""
666
667 if not line or line.isspace():
668 return line
669
670 new_line = line
671 for f in [transform_assign_system, transform_assign_magic,
672 transform_classic_prompt, transform_ipy_prompt ] :
673 new_line = f(new_line)
674 return new_line
675
676 # Support for syntax transformations that use explicit escapes typed by the
677 # user at the beginning of a line
678
679 def tr_system(line_info):
680 "Translate lines escaped with: !"
681 cmd = line_info.line.lstrip().lstrip(ESC_SHELL)
682 return '%sget_ipython().system(%s)' % (line_info.lspace,
683 make_quoted_expr(cmd))
684
685
686 def tr_system2(line_info):
687 "Translate lines escaped with: !!"
688 cmd = line_info.line.lstrip()[2:]
689 return '%sget_ipython().getoutput(%s)' % (line_info.lspace,
690 make_quoted_expr(cmd))
691
692
693 def tr_help(line_info):
694 "Translate lines escaped with: ?/??"
695 # A naked help line should just fire the intro help screen
696 if not line_info.line[1:]:
697 return 'get_ipython().show_usage()'
698
699 # There may be one or two '?' at the end, move them to the front so that
700 # the rest of the logic can assume escapes are at the start
701 line = line_info.line
702 if line.endswith('?'):
703 line = line[-1] + line[:-1]
704 if line.endswith('?'):
705 line = line[-1] + line[:-1]
706 line_info = LineInfo(line)
707
708 # From here on, simply choose which level of detail to get.
709 if line_info.esc == '?':
710 pinfo = 'pinfo'
711 elif line_info.esc == '??':
712 pinfo = 'pinfo2'
713
714 tpl = '%sget_ipython().magic("%s %s")'
715 return tpl % (line_info.lspace, pinfo,
716 ' '.join([line_info.fpart, line_info.rest]).strip())
717
718
719 def tr_magic(line_info):
720 "Translate lines escaped with: %"
721 tpl = '%sget_ipython().magic(%s)'
722 cmd = make_quoted_expr(' '.join([line_info.fpart,
723 line_info.rest])).strip()
724 return tpl % (line_info.lspace, cmd)
725
726
727 def tr_quote(line_info):
728 "Translate lines escaped with: ,"
729 return '%s%s("%s")' % (line_info.lspace, line_info.fpart,
730 '", "'.join(line_info.rest.split()) )
731
732
733 def tr_quote2(line_info):
734 "Translate lines escaped with: ;"
735 return '%s%s("%s")' % (line_info.lspace, line_info.fpart,
736 line_info.rest)
737
738
739 def tr_paren(line_info):
740 "Translate lines escaped with: /"
741 return '%s%s(%s)' % (line_info.lspace, line_info.fpart,
742 ", ".join(line_info.rest.split()))
743
744
745 def transform_escaped(line):
746 """Transform lines that are explicitly escaped out.
747
748 This calls to the above tr_* functions for the actual line translations."""
749
750 tr = { ESC_SHELL : tr_system,
751 ESC_SH_CAP : tr_system2,
752 ESC_HELP : tr_help,
753 ESC_HELP2 : tr_help,
754 ESC_MAGIC : tr_magic,
755 ESC_QUOTE : tr_quote,
756 ESC_QUOTE2 : tr_quote2,
757 ESC_PAREN : tr_paren }
758
759 # Empty lines just get returned unmodified
760 if not line or line.isspace():
761 return line
762
763 # Get line endpoints, where the escapes can be
764 line_info = LineInfo(line)
765
766 # If the escape is not at the start, only '?' needs to be special-cased.
767 # All other escapes are only valid at the start
768 if not line_info.esc in tr:
769 if line.endswith(ESC_HELP):
770 return tr_help(line_info)
771 else:
772 # If we don't recognize the escape, don't modify the line
773 return line
774
775 return tr[line_info.esc](line_info)
776
513 777
514 778 class IPythonInputSplitter(InputSplitter):
515 779 """An input splitter that recognizes all of IPython's special syntax."""
516 780
517
518 781 def push(self, lines):
519 782 """Push one or more lines of IPython input.
520 783 """
521 return super(IPythonInputSplitter, self).push(lines)
784 # We only apply the line transformers to the input if we have either no
785 # input yet, or complete input. This prevents the accidental
786 # transformation of escapes inside multiline expressions like
787 # triple-quoted strings or parenthesized expressions.
788 lines_list = lines.splitlines()
789 if self._is_complete or not self._buffer:
790
791 new_list = map(transform_escaped, lines_list)
792 else:
793 new_list = lines_list
794
795 # Now apply the unescaped transformations to each input line
796 new_list = map(transform_unescaped, new_list)
797 newlines = '\n'.join(new_list)
798 return super(IPythonInputSplitter, self).push(newlines)
@@ -1,3 +1,4 b''
1 # -*- coding: utf-8 -*-
1 2 """Tests for the inputsplitter module.
2 3 """
3 4 #-----------------------------------------------------------------------------
@@ -23,6 +24,10 b' from IPython.core import inputsplitter as isp'
23 24 #-----------------------------------------------------------------------------
24 25 # Semi-complete examples (also used as tests)
25 26 #-----------------------------------------------------------------------------
27
28 # Note: at the bottom, there's a slightly more complete version of this that
29 # can be useful during development of code here.
30
26 31 def mini_interactive_loop(raw_input):
27 32 """Minimal example of the logic of an interactive interpreter loop.
28 33
@@ -44,7 +49,7 b' def mini_interactive_loop(raw_input):'
44 49 # Here we just return input so we can use it in a test suite, but a real
45 50 # interpreter would instead send it for execution somewhere.
46 51 src = isp.source_reset()
47 print 'Input source was:\n', src
52 #print 'Input source was:\n', src # dbg
48 53 return src
49 54
50 55 #-----------------------------------------------------------------------------
@@ -363,9 +368,18 b' class InteractiveLoopTestCase(unittest.TestCase):'
363 368 self.check_ns(['x =(1+','1+','2)'], dict(x=4))
364 369
365 370
366 class IPythonInputTestCase(InputSplitterTestCase):
367 def setUp(self):
368 self.isp = isp.IPythonInputSplitter()
371 def test_LineInfo():
372 """Simple test for LineInfo construction and str()"""
373 linfo = isp.LineInfo(' %cd /home')
374 nt.assert_equals(str(linfo), 'LineInfo [ |%|cd|/home]')
375
376
377 def test_split_user_input():
378 """Unicode test - split_user_input already has good doctests"""
379 line = u"Pérez Fernando"
380 parts = isp.split_user_input(line)
381 parts_expected = (u'', u'', u'', line)
382 nt.assert_equal(parts, parts_expected)
369 383
370 384
371 385 # Transformer tests
@@ -374,38 +388,236 b' def transform_checker(tests, func):'
374 388 for inp, tr in tests:
375 389 nt.assert_equals(func(inp), tr)
376 390
391 # Data for all the syntax tests in the form of lists of pairs of
392 # raw/transformed input. We store it here as a global dict so that we can use
393 # it both within single-function tests and also to validate the behavior of the
394 # larger objects
377 395
378 def test_assign_system():
379 tests = [('a =! ls', 'a = get_ipython().magic("sc -l = ls")'),
396 syntax = \
397 dict(assign_system =
398 [('a =! ls', 'a = get_ipython().magic("sc -l = ls")'),
380 399 ('b = !ls', 'b = get_ipython().magic("sc -l = ls")'),
381 ('x=1','x=1')]
382 transform_checker(tests, isp.transform_assign_system)
383
400 ('x=1', 'x=1'), # normal input is unmodified
401 (' ',' '), # blank lines are kept intact
402 ],
384 403
385 def test_assign_magic():
386 tests = [('a =% who', 'a = get_ipython().magic("who")'),
404 assign_magic =
405 [('a =% who', 'a = get_ipython().magic("who")'),
387 406 ('b = %who', 'b = get_ipython().magic("who")'),
388 ('x=1','x=1')]
389 transform_checker(tests, isp.transform_assign_magic)
407 ('x=1', 'x=1'), # normal input is unmodified
408 (' ',' '), # blank lines are kept intact
409 ],
390 410
411 classic_prompt =
412 [('>>> x=1', 'x=1'),
413 ('x=1', 'x=1'), # normal input is unmodified
414 (' ',' '), # blank lines are kept intact
415 ],
391 416
392 def test_classic_prompt():
393 tests = [('>>> x=1', 'x=1'),
394 ('>>> for i in range(10):','for i in range(10):'),
417 ipy_prompt =
418 [('In [1]: x=1', 'x=1'),
419 ('x=1', 'x=1'), # normal input is unmodified
420 (' ',' '), # blank lines are kept intact
421 ],
422
423 # Tests for the escape transformer to leave normal code alone
424 escaped_noesc =
425 [ (' ', ' '),
426 ('x=1', 'x=1'),
427 ],
428
429 # System calls
430 escaped_shell =
431 [ ('!ls', 'get_ipython().system("ls")'),
432 # Double-escape shell, this means to capture the output of the
433 # subprocess and return it
434 ('!!ls', 'get_ipython().getoutput("ls")'),
435 ],
436
437 # Help/object info
438 escaped_help =
439 [ ('?', 'get_ipython().show_usage()'),
440 ('?x1', 'get_ipython().magic("pinfo x1")'),
441 ('??x2', 'get_ipython().magic("pinfo2 x2")'),
442 ('x3?', 'get_ipython().magic("pinfo x3")'),
443 ('x4??', 'get_ipython().magic("pinfo2 x4")'),
444 ],
445
446 # Explicit magic calls
447 escaped_magic =
448 [ ('%cd', 'get_ipython().magic("cd")'),
449 ('%cd /home', 'get_ipython().magic("cd /home")'),
450 (' %magic', ' get_ipython().magic("magic")'),
451 ],
452
453 # Quoting with separate arguments
454 escaped_quote =
455 [ (',f', 'f("")'),
456 (',f x', 'f("x")'),
457 (' ,f y', ' f("y")'),
458 (',f a b', 'f("a", "b")'),
459 ],
460
461 # Quoting with single argument
462 escaped_quote2 =
463 [ (';f', 'f("")'),
464 (';f x', 'f("x")'),
465 (' ;f y', ' f("y")'),
466 (';f a b', 'f("a b")'),
467 ],
468
469 # Simply apply parens
470 escaped_paren =
471 [ ('/f', 'f()'),
472 ('/f x', 'f(x)'),
473 (' /f y', ' f(y)'),
474 ('/f a b', 'f(a, b)'),
475 ],
476
477 # More complex multiline tests
478 ## escaped_multiline =
479 ## [()],
480 )
481
482 # multiline syntax examples. Each of these should be a list of lists, with
483 # each entry itself having pairs of raw/transformed input. The union (with
484 # '\n'.join() of the transformed inputs is what the splitter should produce
485 # when fed the raw lines one at a time via push.
486 syntax_ml = \
487 dict(classic_prompt =
488 [ [('>>> for i in range(10):','for i in range(10):'),
395 489 ('... print i',' print i'),
396 490 ('...', ''),
397 ('x=1','x=1')
398 ]
399 transform_checker(tests, isp.transform_classic_prompt)
400
491 ],
492 ],
401 493
402 def test_ipy_prompt():
403 tests = [('In [1]: x=1', 'x=1'),
404 ('In [24]: for i in range(10):','for i in range(10):'),
494 ipy_prompt =
495 [ [('In [24]: for i in range(10):','for i in range(10):'),
405 496 (' ....: print i',' print i'),
406 497 (' ....: ', ''),
407 ('x=1', 'x=1'), # normal input is unmodified
408 (' ','') # blank lines are just collapsed
409 ]
410 transform_checker(tests, isp.transform_ipy_prompt)
498 ],
499 ],
500 )
501
502
503 def test_assign_system():
504 transform_checker(syntax['assign_system'], isp.transform_assign_system)
505
506
507 def test_assign_magic():
508 transform_checker(syntax['assign_magic'], isp.transform_assign_magic)
509
510
511 def test_classic_prompt():
512 transform_checker(syntax['classic_prompt'], isp.transform_classic_prompt)
513 for example in syntax_ml['classic_prompt']:
514 transform_checker(example, isp.transform_classic_prompt)
515
516
517 def test_ipy_prompt():
518 transform_checker(syntax['ipy_prompt'], isp.transform_ipy_prompt)
519 for example in syntax_ml['ipy_prompt']:
520 transform_checker(example, isp.transform_ipy_prompt)
521
522
523 def test_escaped_noesc():
524 transform_checker(syntax['escaped_noesc'], isp.transform_escaped)
525
526
527 def test_escaped_shell():
528 transform_checker(syntax['escaped_shell'], isp.transform_escaped)
529
530
531 def test_escaped_help():
532 transform_checker(syntax['escaped_help'], isp.transform_escaped)
411 533
534
535 def test_escaped_magic():
536 transform_checker(syntax['escaped_magic'], isp.transform_escaped)
537
538
539 def test_escaped_quote():
540 transform_checker(syntax['escaped_quote'], isp.transform_escaped)
541
542
543 def test_escaped_quote2():
544 transform_checker(syntax['escaped_quote2'], isp.transform_escaped)
545
546
547 def test_escaped_paren():
548 transform_checker(syntax['escaped_paren'], isp.transform_escaped)
549
550
551 class IPythonInputTestCase(InputSplitterTestCase):
552 """By just creating a new class whose .isp is a different instance, we
553 re-run the same test battery on the new input splitter.
554
555 In addition, this runs the tests over the syntax and syntax_ml dicts that
556 were tested by individual functions, as part of the OO interface.
557 """
558 def setUp(self):
559 self.isp = isp.IPythonInputSplitter()
560
561 def test_syntax(self):
562 """Call all single-line syntax tests from the main object"""
563 isp = self.isp
564 for example in syntax.itervalues():
565 for raw, out_t in example:
566 if raw.startswith(' '):
567 continue
568
569 isp.push(raw)
570 out = isp.source_reset().rstrip()
571 self.assertEqual(out, out_t)
572
573 def test_syntax_multiline(self):
574 isp = self.isp
575 for example in syntax_ml.itervalues():
576 out_t_parts = []
577 for line_pairs in example:
578 for raw, out_t_part in line_pairs:
579 isp.push(raw)
580 out_t_parts.append(out_t_part)
581
582 out = isp.source_reset().rstrip()
583 out_t = '\n'.join(out_t_parts).rstrip()
584 self.assertEqual(out, out_t)
585
586
587 #-----------------------------------------------------------------------------
588 # Main - use as a script
589 #-----------------------------------------------------------------------------
590
591 if __name__ == '__main__':
592 # A simple demo for interactive experimentation. This code will not get
593 # picked up by any test suite. Useful mostly for illustration and during
594 # development.
595 from IPython.core.inputsplitter import InputSplitter, IPythonInputSplitter
596
597 #isp, start_prompt = InputSplitter(), '>>> '
598 isp, start_prompt = IPythonInputSplitter(), 'In> '
599
600 autoindent = True
601 #autoindent = False
602
603 # In practice, this input loop would be wrapped in an outside loop to read
604 # input indefinitely, until some exit/quit command was issued. Here we
605 # only illustrate the basic inner loop.
606 try:
607 while True:
608 prompt = start_prompt
609 while isp.push_accepts_more():
610 indent = ' '*isp.indent_spaces
611 if autoindent:
612 line = indent + raw_input(prompt+indent)
613 else:
614 line = raw_input(prompt)
615 isp.push(line)
616 prompt = '... '
617
618 # Here we just return input so we can use it in a test suite, but a
619 # real interpreter would instead send it for execution somewhere.
620 src = isp.source_reset()
621 print 'Input source was:\n', src # dbg
622 except EOFError:
623 print 'Bye'
@@ -295,8 +295,9 b' def make_quoted_expr(s):'
295 295 quote = "'''"
296 296 else:
297 297 # give up, backslash-escaped string will do
298 return '"%s"' % esc_quotes(s)
299 res = raw + quote + s + tailpadding + quote + tail
298 return '"%s"' % esc_quotes(s).strip()
299 txt = (s + tailpadding).strip()
300 res = raw + quote + txt + quote + tail
300 301 return res
301 302
302 303
General Comments 0
You need to be logged in to leave comments. Login now