Show More
@@ -470,9 +470,12 b' def make_tokens_by_line(lines):' | |||
|
470 | 470 | except tokenize.TokenError: |
|
471 | 471 | # Input ended in a multiline string or expression. That's OK for us. |
|
472 | 472 | pass |
|
473 | ||
|
474 | ||
|
473 | 475 | if not tokens_by_line[-1]: |
|
474 | 476 | tokens_by_line.pop() |
|
475 | 477 | |
|
478 | ||
|
476 | 479 | return tokens_by_line |
|
477 | 480 | |
|
478 | 481 | def show_linewise_tokens(s: str): |
@@ -579,7 +582,24 b' class TransformerManager:' | |||
|
579 | 582 | The number of spaces by which to indent the next line of code. If |
|
580 | 583 | status is not 'incomplete', this is None. |
|
581 | 584 | """ |
|
585 | # Remember if the lines ends in a new line. | |
|
586 | ends_with_newline = False | |
|
587 | for character in reversed(cell): | |
|
588 | if character == '\n': | |
|
589 | ends_with_newline = True | |
|
590 | break | |
|
591 | elif character.strip(): | |
|
592 | break | |
|
593 | else: | |
|
594 | continue | |
|
595 | ||
|
596 | if ends_with_newline: | |
|
597 | # Append an newline for consistent tokenization | |
|
598 | # See https://bugs.python.org/issue33899 | |
|
599 | cell += '\n' | |
|
600 | ||
|
582 | 601 | lines = cell.splitlines(keepends=True) |
|
602 | ||
|
583 | 603 | if not lines: |
|
584 | 604 | return 'complete', None |
|
585 | 605 | |
@@ -608,6 +628,7 b' class TransformerManager:' | |||
|
608 | 628 | return 'invalid', None |
|
609 | 629 | |
|
610 | 630 | tokens_by_line = make_tokens_by_line(lines) |
|
631 | ||
|
611 | 632 | if not tokens_by_line: |
|
612 | 633 | return 'incomplete', find_last_indent(lines) |
|
613 | 634 | |
@@ -615,30 +636,33 b' class TransformerManager:' | |||
|
615 | 636 | # We're in a multiline string or expression |
|
616 | 637 | return 'incomplete', find_last_indent(lines) |
|
617 | 638 | |
|
618 | if len(tokens_by_line[-1]) == 1: | |
|
619 | return 'incomplete', find_last_indent(lines) | |
|
620 | # Find the last token on the previous line that's not NEWLINE or COMMENT | |
|
621 |
|
|
|
622 | ix = len(tokens_by_line) - 1 | |
|
639 | newline_types = {tokenize.NEWLINE, tokenize.COMMENT, tokenize.ENDMARKER} | |
|
640 | ||
|
641 | # Remove newline_types for the list of tokens | |
|
642 | while len(tokens_by_line) > 1 and len(tokens_by_line[-1]) == 1 \ | |
|
643 | and tokens_by_line[-1][-1].type in newline_types: | |
|
644 | tokens_by_line.pop() | |
|
623 | 645 | |
|
646 | last_line_token = tokens_by_line[-1] | |
|
624 | 647 | |
|
625 |
while |
|
|
626 | tokenize.COMMENT}: | |
|
627 | ix -= 1 | |
|
628 | if tokens_by_line[ix][-2].string == ':': | |
|
648 | while tokens_by_line[-1][-1].type in newline_types: | |
|
649 | last_line_token = tokens_by_line[-1].pop() | |
|
650 | ||
|
651 | if len(last_line_token) == 1 and not last_line_token[-1]: | |
|
652 | return 'incomplete', 0 | |
|
653 | ||
|
654 | if last_line_token[-1].string == ':': | |
|
629 | 655 | # The last line starts a block (e.g. 'if foo:') |
|
630 | 656 | ix = 0 |
|
631 | while toks_last_line[ix].type in {tokenize.INDENT, tokenize.DEDENT}: | |
|
657 | while last_line_token[ix].type \ | |
|
658 | in {tokenize.INDENT, tokenize.DEDENT}: | |
|
632 | 659 | ix += 1 |
|
633 | indent = toks_last_line[ix].start[1] | |
|
660 | ||
|
661 | indent = last_line_token[ix].start[1] | |
|
634 | 662 | 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 | |
|
638 | 663 | |
|
639 | # If there's a blank line at the end, assume we're ready to execute | |
|
640 | if not lines[-1].strip(): | |
|
641 | return 'complete', None | |
|
664 | if last_line_token[-1].line.endswith('\\'): | |
|
665 | return 'incomplete', None | |
|
642 | 666 | |
|
643 | 667 | # At this point, our checks think the code is complete (or invalid). |
|
644 | 668 | # We'll use codeop.compile_command to check this with the real parser |
@@ -653,12 +677,13 b' class TransformerManager:' | |||
|
653 | 677 | if res is None: |
|
654 | 678 | return 'incomplete', find_last_indent(lines) |
|
655 | 679 | |
|
656 |
if |
|
|
657 | return 'complete', None | |
|
680 | if last_line_token[-1].type == tokenize.DEDENT: | |
|
681 | if ends_with_newline: | |
|
682 | return 'complete', None | |
|
683 | return 'incomplete', find_last_indent(lines) | |
|
658 | 684 | |
|
659 | if toks_last_line[-2].type == tokenize.DEDENT: | |
|
660 | if not lines[-1].endswith('\n'): | |
|
661 | return 'incomplete', find_last_indent(lines) | |
|
685 | if len(last_line_token) <= 1: | |
|
686 | return 'incomplete', find_last_indent(lines) | |
|
662 | 687 | |
|
663 | 688 | return 'complete', None |
|
664 | 689 |
General Comments 0
You need to be logged in to leave comments.
Login now