Show More
@@ -253,7 +253,7 b' class SystemAssign(TokenTransformBase):' | |||||
253 | lhs = lines[start_line][:start_col] |
|
253 | lhs = lines[start_line][:start_col] | |
254 | end_line = find_end_of_continued_line(lines, start_line) |
|
254 | end_line = find_end_of_continued_line(lines, start_line) | |
255 | rhs = assemble_continued_line(lines, (start_line, start_col), end_line) |
|
255 | rhs = assemble_continued_line(lines, (start_line, start_col), end_line) | |
256 | assert rhs.startswith('!'), rhs |
|
256 | # assert rhs.startswith('!'), rhs | |
257 | cmd = rhs[1:] |
|
257 | cmd = rhs[1:] | |
258 |
|
258 | |||
259 | lines_before = lines[:start_line] |
|
259 | lines_before = lines[:start_line] | |
@@ -369,11 +369,15 b' class EscapedCommand(TokenTransformBase):' | |||||
369 | end_line = find_end_of_continued_line(lines, start_line) |
|
369 | end_line = find_end_of_continued_line(lines, start_line) | |
370 | line = assemble_continued_line(lines, (start_line, start_col), end_line) |
|
370 | line = assemble_continued_line(lines, (start_line, start_col), end_line) | |
371 |
|
371 | |||
372 | if line[:2] in ESCAPE_DOUBLES: |
|
372 | if len(line) > 1 and line[:2] in ESCAPE_DOUBLES: | |
373 | escape, content = line[:2], line[2:] |
|
373 | escape, content = line[:2], line[2:] | |
374 | else: |
|
374 | else: | |
375 | escape, content = line[:1], line[1:] |
|
375 | escape, content = line[:1], line[1:] | |
376 | call = tr[escape](content) |
|
376 | ||
|
377 | if escape in tr: | |||
|
378 | call = tr[escape](content) | |||
|
379 | else: | |||
|
380 | call = '' | |||
377 |
|
381 | |||
378 | lines_before = lines[:start_line] |
|
382 | lines_before = lines[:start_line] | |
379 | new_line = indent + call + '\n' |
|
383 | new_line = indent + call + '\n' | |
@@ -575,9 +579,11 b' class TransformerManager:' | |||||
575 | The number of spaces by which to indent the next line of code. If |
|
579 | The number of spaces by which to indent the next line of code. If | |
576 | status is not 'incomplete', this is None. |
|
580 | status is not 'incomplete', this is None. | |
577 | """ |
|
581 | """ | |
578 | cell += '\n' # Ensure the cell has a trailing newline |
|
|||
579 | lines = cell.splitlines(keepends=True) |
|
582 | lines = cell.splitlines(keepends=True) | |
580 | if lines[-1][:-1].endswith('\\'): |
|
583 | if not lines: | |
|
584 | return 'complete', None | |||
|
585 | ||||
|
586 | if lines[-1].endswith('\\'): | |||
581 | # Explicit backslash continuation |
|
587 | # Explicit backslash continuation | |
582 | return 'incomplete', find_last_indent(lines) |
|
588 | return 'incomplete', find_last_indent(lines) | |
583 |
|
589 | |||
@@ -604,44 +610,53 b' class TransformerManager:' | |||||
604 | tokens_by_line = make_tokens_by_line(lines) |
|
610 | tokens_by_line = make_tokens_by_line(lines) | |
605 | if not tokens_by_line: |
|
611 | if not tokens_by_line: | |
606 | return 'incomplete', find_last_indent(lines) |
|
612 | return 'incomplete', find_last_indent(lines) | |
|
613 | ||||
607 | if tokens_by_line[-1][-1].type != tokenize.ENDMARKER: |
|
614 | if tokens_by_line[-1][-1].type != tokenize.ENDMARKER: | |
608 | # We're in a multiline string or expression |
|
615 | # We're in a multiline string or expression | |
609 | return 'incomplete', find_last_indent(lines) |
|
616 | return 'incomplete', find_last_indent(lines) | |
610 | if len(tokens_by_line) == 1: |
|
617 | ||
|
618 | if len(tokens_by_line[-1]) == 1: | |||
611 | return 'incomplete', find_last_indent(lines) |
|
619 | return 'incomplete', find_last_indent(lines) | |
612 | # Find the last token on the previous line that's not NEWLINE or COMMENT |
|
620 | # Find the last token on the previous line that's not NEWLINE or COMMENT | |
613 |
toks_last_line = tokens_by_line[- |
|
621 | toks_last_line = tokens_by_line[-1] | |
614 |
ix = len(tok |
|
622 | ix = len(tokens_by_line) - 1 | |
615 | while ix >= 0 and toks_last_line[ix].type in {tokenize.NEWLINE, |
|
623 | ||
|
624 | ||||
|
625 | while ix >= 0 and toks_last_line[-1].type in {tokenize.NEWLINE, | |||
616 | tokenize.COMMENT}: |
|
626 | tokenize.COMMENT}: | |
617 | ix -= 1 |
|
627 | ix -= 1 | |
618 |
|
628 | if tokens_by_line[ix][-2].string == ':': | ||
619 | if toks_last_line[ix].string == ':': |
|
|||
620 | # The last line starts a block (e.g. 'if foo:') |
|
629 | # The last line starts a block (e.g. 'if foo:') | |
621 | ix = 0 |
|
630 | ix = 0 | |
622 | while toks_last_line[ix].type in {tokenize.INDENT, tokenize.DEDENT}: |
|
631 | while toks_last_line[ix].type in {tokenize.INDENT, tokenize.DEDENT}: | |
623 | ix += 1 |
|
632 | ix += 1 | |
624 | indent = toks_last_line[ix].start[1] |
|
633 | indent = toks_last_line[ix].start[1] | |
625 | return 'incomplete', indent + 4 |
|
634 | return 'incomplete', indent + 4 | |
|
635 | if tokens_by_line[ix][-2].string == '\\': | |||
|
636 | if not tokens_by_line[ix][-2].line.endswith('\\'): | |||
|
637 | return 'invalid', None | |||
626 |
|
638 | |||
627 |
# If there's a blank line at the end, assume we're ready to execute |
|
639 | # If there's a blank line at the end, assume we're ready to execute | |
628 | if not lines[-1].strip(): |
|
640 | if not lines[-1].strip(): | |
629 | return 'complete', None |
|
641 | return 'complete', None | |
630 |
|
642 | |||
631 | # At this point, our checks think the code is complete (or invalid). |
|
643 | # At this point, our checks think the code is complete (or invalid). | |
632 |
# We'll use codeop.compile_command to check this with the real parser |
|
644 | # We'll use codeop.compile_command to check this with the real parser | |
633 |
|
||||
634 | try: |
|
645 | try: | |
635 | with warnings.catch_warnings(): |
|
646 | with warnings.catch_warnings(): | |
636 | warnings.simplefilter('error', SyntaxWarning) |
|
647 | warnings.simplefilter('error', SyntaxWarning) | |
637 | compile_command(''.join(lines), symbol='exec') |
|
648 | res = compile_command(''.join(lines), symbol='exec') | |
638 | except (SyntaxError, OverflowError, ValueError, TypeError, |
|
649 | except (SyntaxError, OverflowError, ValueError, TypeError, | |
639 | MemoryError, SyntaxWarning): |
|
650 | MemoryError, SyntaxWarning): | |
640 | return 'invalid', None |
|
651 | return 'invalid', None | |
641 | else: |
|
652 | else: | |
642 | if len(lines) > 1 and not lines[-1].strip().endswith(':') \ |
|
653 | if res is None: | |
643 | and not lines[-2][:-1].endswith('\\'): |
|
|||
644 | return 'incomplete', find_last_indent(lines) |
|
654 | return 'incomplete', find_last_indent(lines) | |
|
655 | ||||
|
656 | if toks_last_line[-2].type == tokenize.DEDENT: | |||
|
657 | if not lines[-1].endswith('\n'): | |||
|
658 | return 'incomplete', find_last_indent(lines) | |||
|
659 | ||||
645 | return 'complete', None |
|
660 | return 'complete', None | |
646 |
|
661 | |||
647 |
|
662 |
General Comments 0
You need to be logged in to leave comments.
Login now