A class used to parse strings containing doctest examples. Note: This is a version modified to properly recognize IPython input and convert any IPython examples into valid Python ones.
| 80 | |
| 81 | |
| 82 | class IPDocTestParser(doctest.DocTestParser): |
| 83 | """ |
| 84 | A class used to parse strings containing doctest examples. |
| 85 | |
| 86 | Note: This is a version modified to properly recognize IPython input and |
| 87 | convert any IPython examples into valid Python ones. |
| 88 | """ |
| 89 | # This regular expression is used to find doctest examples in a |
| 90 | # string. It defines three groups: `source` is the source code |
| 91 | # (including leading indentation and prompts); `indent` is the |
| 92 | # indentation of the first (PS1) line of the source code; and |
| 93 | # `want` is the expected output (including leading indentation). |
| 94 | |
| 95 | # Classic Python prompts or default IPython ones |
| 96 | _PS1_PY = r'>>>' |
| 97 | _PS2_PY = r'\.\.\.' |
| 98 | |
| 99 | _PS1_IP = r'In\ \[\d+\]:' |
| 100 | _PS2_IP = r'\ \ \ \.\.\.+:' |
| 101 | |
| 102 | _RE_TPL = r''' |
| 103 | # Source consists of a PS1 line followed by zero or more PS2 lines. |
| 104 | (?P<source> |
| 105 | (?:^(?P<indent> [ ]*) (?P<ps1> %s) .*) # PS1 line |
| 106 | (?:\n [ ]* (?P<ps2> %s) .*)*) # PS2 lines |
| 107 | \n? # a newline |
| 108 | # Want consists of any non-blank lines that do not start with PS1. |
| 109 | (?P<want> (?:(?![ ]*$) # Not a blank line |
| 110 | (?![ ]*%s) # Not a line starting with PS1 |
| 111 | (?![ ]*%s) # Not a line starting with PS2 |
| 112 | .*$\n? # But any other line |
| 113 | )*) |
| 114 | ''' |
| 115 | |
| 116 | _EXAMPLE_RE_PY = re.compile( _RE_TPL % (_PS1_PY,_PS2_PY,_PS1_PY,_PS2_PY), |
| 117 | re.MULTILINE | re.VERBOSE) |
| 118 | |
| 119 | _EXAMPLE_RE_IP = re.compile( _RE_TPL % (_PS1_IP,_PS2_IP,_PS1_IP,_PS2_IP), |
| 120 | re.MULTILINE | re.VERBOSE) |
| 121 | |
| 122 | # Mark a test as being fully random. In this case, we simply append the |
| 123 | # random marker ('#random') to each individual example's output. This way |
| 124 | # we don't need to modify any other code. |
| 125 | _RANDOM_TEST = re.compile(r'#\s*all-random\s+') |
| 126 | |
| 127 | def ip2py(self,source): |
| 128 | """Convert input IPython source into valid Python.""" |
| 129 | block = _ip.input_transformer_manager.transform_cell(source) |
| 130 | if len(block.splitlines()) == 1: |
| 131 | return _ip.prefilter(block) |
| 132 | else: |
| 133 | return block |
| 134 | |
| 135 | def parse(self, string, name='<string>'): |
| 136 | """ |
| 137 | Divide the given string into examples and intervening text, |
| 138 | and return them as a list of alternating Examples and strings. |
| 139 | Line numbers for the Examples are 0-based. The optional |