A class used to parse strings containing doctest examples.
| 601 | ###################################################################### |
| 602 | |
| 603 | class DocTestParser: |
| 604 | """ |
| 605 | A class used to parse strings containing doctest examples. |
| 606 | """ |
| 607 | # This regular expression is used to find doctest examples in a |
| 608 | # string. It defines three groups: `source` is the source code |
| 609 | # (including leading indentation and prompts); `indent` is the |
| 610 | # indentation of the first (PS1) line of the source code; and |
| 611 | # `want` is the expected output (including leading indentation). |
| 612 | _EXAMPLE_RE = re.compile(r''' |
| 613 | # Source consists of a PS1 line followed by zero or more PS2 lines. |
| 614 | (?P<source> |
| 615 | (?:^(?P<indent> [ ]*) >>> .*) # PS1 line |
| 616 | (?:\n [ ]* \.\.\. .*)*) # PS2 lines |
| 617 | \n? |
| 618 | # Want consists of any non-blank lines that do not start with PS1. |
| 619 | (?P<want> (?:(?![ ]*$) # Not a blank line |
| 620 | (?![ ]*>>>) # Not a line starting with PS1 |
| 621 | .+$\n? # But any other line |
| 622 | )*) |
| 623 | ''', re.MULTILINE | re.VERBOSE) |
| 624 | |
| 625 | # A regular expression for handling `want` strings that contain |
| 626 | # expected exceptions. It divides `want` into three pieces: |
| 627 | # - the traceback header line (`hdr`) |
| 628 | # - the traceback stack (`stack`) |
| 629 | # - the exception message (`msg`), as generated by |
| 630 | # traceback.format_exception_only() |
| 631 | # `msg` may have multiple lines. We assume/require that the |
| 632 | # exception message is the first non-indented line starting with a word |
| 633 | # character following the traceback header line. |
| 634 | _EXCEPTION_RE = re.compile(r""" |
| 635 | # Grab the traceback header. Different versions of Python have |
| 636 | # said different things on the first traceback line. |
| 637 | ^(?P<hdr> Traceback\ \( |
| 638 | (?: most\ recent\ call\ last |
| 639 | | innermost\ last |
| 640 | ) \) : |
| 641 | ) |
| 642 | \s* $ # toss trailing whitespace on the header. |
| 643 | (?P<stack> .*?) # don't blink: absorb stuff until... |
| 644 | ^ (?P<msg> \w+ .*) # a line *starts* with alphanum. |
| 645 | """, re.VERBOSE | re.MULTILINE | re.DOTALL) |
| 646 | |
| 647 | # A callable returning a true value iff its argument is a blank line |
| 648 | # or contains a single comment. |
| 649 | _IS_BLANK_OR_COMMENT = re.compile(r'^[ ]*(#.*)?$').match |
| 650 | |
| 651 | def parse(self, string, name='<string>'): |
| 652 | """ |
| 653 | Divide the given string into examples and intervening text, |
| 654 | and return them as a list of alternating Examples and strings. |
| 655 | Line numbers for the Examples are 0-based. The optional |
| 656 | argument `name` is a name identifying this string, and is only |
| 657 | used for error messages. |
| 658 | """ |
| 659 | string = string.expandtabs() |
| 660 | # If all lines begin with the same indentation, then strip it. |
searching dependent graphs…