Show More
@@ -81,10 +81,26 b' def float_doctest(sphinx_shell, args, input_lines, found, submitted):' | |||||
81 | submitted[~submitted_isnan], |
|
81 | submitted[~submitted_isnan], | |
82 | rtol=rtol, atol=atol) |
|
82 | rtol=rtol, atol=atol) | |
83 |
|
83 | |||
|
84 | TAB = ' ' * 4 | |||
|
85 | directive = sphinx_shell.directive | |||
|
86 | if directive is None: | |||
|
87 | source = 'Unavailable' | |||
|
88 | content = 'Unavailable' | |||
|
89 | else: | |||
|
90 | source = directive.state.document.current_source | |||
|
91 | # Add tabs and make into a single string. | |||
|
92 | content = '\n'.join([TAB + line for line in directive.content]) | |||
|
93 | ||||
84 | if error: |
|
94 | if error: | |
85 | e = ('doctest float comparison failure for input_lines={0} with ' |
|
95 | ||
86 | 'found_output={1} and submitted ' |
|
96 | e = ('doctest float comparison failure\n\n' | |
87 | 'output="{2}"'.format(input_lines, repr(found), repr(submitted)) ) |
|
97 | 'Document source: {0}\n\n' | |
|
98 | 'Raw content: \n{1}\n\n' | |||
|
99 | 'On input line(s):\n{TAB}{2}\n\n' | |||
|
100 | 'we found output:\n{TAB}{3}\n\n' | |||
|
101 | 'instead of the expected:\n{TAB}{4}\n\n') | |||
|
102 | e = e.format(source, content, '\n'.join(input_lines), repr(found), | |||
|
103 | repr(submitted), TAB=TAB) | |||
88 | raise RuntimeError(e) |
|
104 | raise RuntimeError(e) | |
89 |
|
105 | |||
90 | doctests = { |
|
106 | doctests = { |
@@ -155,7 +155,6 b' def block_parser(part, rgxin, rgxout, fmtin, fmtout):' | |||||
155 | INPUT_LINE: the input as string (possibly multi-line) |
|
155 | INPUT_LINE: the input as string (possibly multi-line) | |
156 | REST : any stdout generated by the input line (not OUTPUT) |
|
156 | REST : any stdout generated by the input line (not OUTPUT) | |
157 |
|
157 | |||
158 |
|
||||
159 | OUTPUT: the output string, possibly multi-line |
|
158 | OUTPUT: the output string, possibly multi-line | |
160 |
|
159 | |||
161 | """ |
|
160 | """ | |
@@ -279,6 +278,9 b' class EmbeddedSphinxShell(object):' | |||||
279 | self.is_doctest = False |
|
278 | self.is_doctest = False | |
280 | self.is_suppress = False |
|
279 | self.is_suppress = False | |
281 |
|
280 | |||
|
281 | # Optionally, provide more detailed information to shell. | |||
|
282 | self.directive = None | |||
|
283 | ||||
282 | # on the first call to the savefig decorator, we'll import |
|
284 | # on the first call to the savefig decorator, we'll import | |
283 | # pyplot as plt so we can make a call to the plt.gcf().savefig |
|
285 | # pyplot as plt so we can make a call to the plt.gcf().savefig | |
284 | self._pyplot_imported = False |
|
286 | self._pyplot_imported = False | |
@@ -293,7 +295,7 b' class EmbeddedSphinxShell(object):' | |||||
293 |
|
295 | |||
294 | def process_input_line(self, line, store_history=True): |
|
296 | def process_input_line(self, line, store_history=True): | |
295 | """process the input, capturing stdout""" |
|
297 | """process the input, capturing stdout""" | |
296 | #print "input='%s'"%self.input |
|
298 | ||
297 | stdout = sys.stdout |
|
299 | stdout = sys.stdout | |
298 | splitter = self.IP.input_splitter |
|
300 | splitter = self.IP.input_splitter | |
299 | try: |
|
301 | try: | |
@@ -337,11 +339,14 b' class EmbeddedSphinxShell(object):' | |||||
337 |
|
339 | |||
338 | # Callbacks for each type of token |
|
340 | # Callbacks for each type of token | |
339 | def process_input(self, data, input_prompt, lineno): |
|
341 | def process_input(self, data, input_prompt, lineno): | |
340 | """Process data block for INPUT token.""" |
|
342 | """ | |
|
343 | Process data block for INPUT token. | |||
|
344 | ||||
|
345 | """ | |||
341 | decorator, input, rest = data |
|
346 | decorator, input, rest = data | |
342 | image_file = None |
|
347 | image_file = None | |
343 | image_directive = None |
|
348 | image_directive = None | |
344 | #print 'INPUT:', data # dbg |
|
349 | ||
345 | is_verbatim = decorator=='@verbatim' or self.is_verbatim |
|
350 | is_verbatim = decorator=='@verbatim' or self.is_verbatim | |
346 | is_doctest = (decorator is not None and \ |
|
351 | is_doctest = (decorator is not None and \ | |
347 | decorator.startswith('@doctest')) or self.is_doctest |
|
352 | decorator.startswith('@doctest')) or self.is_doctest | |
@@ -403,22 +408,41 b' class EmbeddedSphinxShell(object):' | |||||
403 | self.cout.truncate(0) |
|
408 | self.cout.truncate(0) | |
404 | return (ret, input_lines, output, is_doctest, decorator, image_file, |
|
409 | return (ret, input_lines, output, is_doctest, decorator, image_file, | |
405 | image_directive) |
|
410 | image_directive) | |
406 | #print 'OUTPUT', output # dbg |
|
411 | ||
407 |
|
412 | |||
408 | def process_output(self, data, output_prompt, |
|
413 | def process_output(self, data, output_prompt, | |
409 | input_lines, output, is_doctest, decorator, image_file): |
|
414 | input_lines, output, is_doctest, decorator, image_file): | |
410 | """Process data block for OUTPUT token.""" |
|
415 | """ | |
|
416 | Process data block for OUTPUT token. | |||
|
417 | ||||
|
418 | """ | |||
|
419 | TAB = ' ' * 4 | |||
|
420 | ||||
411 | if is_doctest and output is not None: |
|
421 | if is_doctest and output is not None: | |
412 |
|
422 | |||
413 | found = output |
|
423 | found = output | |
414 | found = found.strip() |
|
424 | found = found.strip() | |
415 | submitted = data.strip() |
|
425 | submitted = data.strip() | |
416 |
|
426 | |||
|
427 | if self.directive is None: | |||
|
428 | source = 'Unavailable' | |||
|
429 | content = 'Unavailable' | |||
|
430 | else: | |||
|
431 | source = self.directive.state.document.current_source | |||
|
432 | content = self.directive.content | |||
|
433 | # Add tabs and join into a single string. | |||
|
434 | content = '\n'.join([TAB + line for line in content]) | |||
|
435 | ||||
417 | # Make sure the output contains the output prompt. |
|
436 | # Make sure the output contains the output prompt. | |
418 | ind = found.find(output_prompt) |
|
437 | ind = found.find(output_prompt) | |
419 | if ind < 0: |
|
438 | if ind < 0: | |
420 |
e = ('output prompt |
|
439 | e = ('output does not contain output prompt\n\n' | |
421 | 'not match out line={1}'.format(output_prompt, found)) |
|
440 | 'Document source: {0}\n\n' | |
|
441 | 'Raw content: \n{1}\n\n' | |||
|
442 | 'Input line(s):\n{TAB}{2}\n\n' | |||
|
443 | 'Output line(s):\n{TAB}{3}\n\n') | |||
|
444 | e = e.format(source, content, '\n'.join(input_lines), | |||
|
445 | repr(found), TAB=TAB) | |||
422 | raise RuntimeError(e) |
|
446 | raise RuntimeError(e) | |
423 | found = found[len(output_prompt):].strip() |
|
447 | found = found[len(output_prompt):].strip() | |
424 |
|
448 | |||
@@ -426,9 +450,14 b' class EmbeddedSphinxShell(object):' | |||||
426 | if decorator.strip() == '@doctest': |
|
450 | if decorator.strip() == '@doctest': | |
427 | # Standard doctest |
|
451 | # Standard doctest | |
428 | if found != submitted: |
|
452 | if found != submitted: | |
429 |
e = ('doctest failure |
|
453 | e = ('doctest failure\n\n' | |
430 | 'found_output="{1}" and submitted ' |
|
454 | 'Document source: {0}\n\n' | |
431 | 'output="{2}"'.format(input_lines, found, submitted) ) |
|
455 | 'Raw content: \n{1}\n\n' | |
|
456 | 'On input line(s):\n{TAB}{2}\n\n' | |||
|
457 | 'we found output:\n{TAB}{3}\n\n' | |||
|
458 | 'instead of the expected:\n{TAB}{4}\n\n') | |||
|
459 | e = e.format(source, content, '\n'.join(input_lines), | |||
|
460 | repr(found), repr(submitted), TAB=TAB) | |||
432 | raise RuntimeError(e) |
|
461 | raise RuntimeError(e) | |
433 | else: |
|
462 | else: | |
434 | self.custom_doctest(decorator, input_lines, found, submitted) |
|
463 | self.custom_doctest(decorator, input_lines, found, submitted) | |
@@ -653,6 +682,9 b' class IPythonDirective(Directive):' | |||||
653 | # setting its backend since exec_lines might import pylab. |
|
682 | # setting its backend since exec_lines might import pylab. | |
654 | self.shell = EmbeddedSphinxShell(exec_lines) |
|
683 | self.shell = EmbeddedSphinxShell(exec_lines) | |
655 |
|
684 | |||
|
685 | # Store IPython directive to enable better error messages | |||
|
686 | self.shell.directive = self | |||
|
687 | ||||
656 | # reset the execution count if we haven't processed this doc |
|
688 | # reset the execution count if we haven't processed this doc | |
657 | #NOTE: this may be borked if there are multiple seen_doc tmp files |
|
689 | #NOTE: this may be borked if there are multiple seen_doc tmp files | |
658 | #check time stamp? |
|
690 | #check time stamp? | |
@@ -676,7 +708,6 b' class IPythonDirective(Directive):' | |||||
676 |
|
708 | |||
677 | return rgxin, rgxout, promptin, promptout |
|
709 | return rgxin, rgxout, promptin, promptout | |
678 |
|
710 | |||
679 |
|
||||
680 | def teardown(self): |
|
711 | def teardown(self): | |
681 | # delete last bookmark |
|
712 | # delete last bookmark | |
682 | self.shell.process_input_line('bookmark -d ipy_savedir', |
|
713 | self.shell.process_input_line('bookmark -d ipy_savedir', | |
@@ -702,7 +733,7 b' class IPythonDirective(Directive):' | |||||
702 |
|
733 | |||
703 | parts = '\n'.join(self.content).split('\n\n') |
|
734 | parts = '\n'.join(self.content).split('\n\n') | |
704 |
|
735 | |||
705 | lines = ['.. code-block:: ipython',''] |
|
736 | lines = ['.. code-block:: ipython', ''] | |
706 | figures = [] |
|
737 | figures = [] | |
707 |
|
738 | |||
708 | for part in parts: |
|
739 | for part in parts: | |
@@ -724,7 +755,9 b' class IPythonDirective(Directive):' | |||||
724 | if debug: |
|
755 | if debug: | |
725 | print('\n'.join(lines)) |
|
756 | print('\n'.join(lines)) | |
726 | else: |
|
757 | else: | |
727 | # This is what makes the lines appear in the final output. |
|
758 | # This has to do with input, not output. But if we comment | |
|
759 | # these lines out, then no IPython code will appear in the | |||
|
760 | # final output. | |||
728 | self.state_machine.insert_input( |
|
761 | self.state_machine.insert_input( | |
729 | lines, self.state_machine.input_lines.source(0)) |
|
762 | lines, self.state_machine.input_lines.source(0)) | |
730 |
|
763 |
General Comments 0
You need to be logged in to leave comments.
Login now