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