|
172 | 172 | def block_parser(part, rgxin, rgxout, fmtin, fmtout): |
173 | 173 | """ |
174 | 174 | part is a string of ipython text, comprised of at most one |
175 | | - input, one ouput, comments, and blank lines. The block parser |
| 175 | + input, one output, comments, and blank lines. The block parser |
176 | 176 | parses the text into a list of:: |
177 | 177 |
|
178 | 178 | blocks = [ (TOKEN0, data0), (TOKEN1, data1), ...] |
@@ -297,8 +297,8 @@ def __init__(self, exec_lines=None): |
297 | 297 |
|
298 | 298 | # Create and initialize global ipython, but don't start its mainloop. |
299 | 299 | # This will persist across different EmbededSphinxShell instances. |
300 | | - atexit.register(self.cleanup) |
301 | 300 | IP = InteractiveShell.instance(config=config, profile_dir=profile) |
| 301 | + atexit.register(self.cleanup) |
302 | 302 |
|
303 | 303 | # io.stdout redirect must be done after instantiating InteractiveShell |
304 | 304 | io.stdout = self.cout |
@@ -657,14 +657,41 @@ def process_block(self, block): |
657 | 657 | image_file = None |
658 | 658 | image_directive = None |
659 | 659 |
|
| 660 | + found_input = False |
660 | 661 | for token, data in block: |
661 | 662 | if token == COMMENT: |
662 | 663 | out_data = self.process_comment(data) |
663 | 664 | elif token == INPUT: |
| 665 | + found_input = True |
664 | 666 | (out_data, input_lines, output, is_doctest, |
665 | 667 | decorator, image_file, image_directive) = \ |
666 | 668 | self.process_input(data, input_prompt, lineno) |
667 | 669 | elif token == OUTPUT: |
| 670 | + if not found_input: |
| 671 | + |
| 672 | + TAB = ' ' * 4 |
| 673 | + linenumber = 0 |
| 674 | + source = 'Unavailable' |
| 675 | + content = 'Unavailable' |
| 676 | + if self.directive: |
| 677 | + linenumber = self.directive.state.document.current_line |
| 678 | + source = self.directive.state.document.current_source |
| 679 | + content = self.directive.content |
| 680 | + # Add tabs and join into a single string. |
| 681 | + content = '\n'.join([TAB + line for line in content]) |
| 682 | + |
| 683 | + e = ('\n\nInvalid block: Block contains an output prompt ' |
| 684 | + 'without an input prompt.\n\n' |
| 685 | + 'Document source: {0}\n\n' |
| 686 | + 'Content begins at line {1}: \n\n{2}\n\n' |
| 687 | + 'Problematic block within content: \n\n{TAB}{3}\n\n') |
| 688 | + e = e.format(source, linenumber, content, block, TAB=TAB) |
| 689 | + |
| 690 | + # Write, rather than include in exception, since Sphinx |
| 691 | + # will truncate tracebacks. |
| 692 | + sys.stdout.write(e) |
| 693 | + raise RuntimeError('An invalid block was detected.') |
| 694 | + |
668 | 695 | out_data = \ |
669 | 696 | self.process_output(data, output_prompt, input_lines, |
670 | 697 | output, is_doctest, decorator, |
@@ -923,6 +950,8 @@ def run(self): |
923 | 950 | content = self.content |
924 | 951 | self.content = self.shell.process_pure_python(content) |
925 | 952 |
|
| 953 | + # parts consists of all text within the ipython-block. |
| 954 | + # Each part is an input/output block. |
926 | 955 | parts = '\n'.join(self.content).split('\n\n') |
927 | 956 |
|
928 | 957 | lines = ['.. code-block:: ipython', ''] |
|
0 commit comments