##// END OF EJS Templates
Provide helpful error messages on doctest failures.
chebee7i -
Show More
@@ -81,10 +81,26 b' def float_doctest(sphinx_shell, args, input_lines, found, submitted):'
81 81 submitted[~submitted_isnan],
82 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 94 if error:
85 e = ('doctest float comparison failure for input_lines={0} with '
86 'found_output={1} and submitted '
87 'output="{2}"'.format(input_lines, repr(found), repr(submitted)) )
95
96 e = ('doctest float comparison failure\n\n'
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 104 raise RuntimeError(e)
89 105
90 106 doctests = {
@@ -155,7 +155,6 b' def block_parser(part, rgxin, rgxout, fmtin, fmtout):'
155 155 INPUT_LINE: the input as string (possibly multi-line)
156 156 REST : any stdout generated by the input line (not OUTPUT)
157 157
158
159 158 OUTPUT: the output string, possibly multi-line
160 159
161 160 """
@@ -279,6 +278,9 b' class EmbeddedSphinxShell(object):'
279 278 self.is_doctest = False
280 279 self.is_suppress = False
281 280
281 # Optionally, provide more detailed information to shell.
282 self.directive = None
283
282 284 # on the first call to the savefig decorator, we'll import
283 285 # pyplot as plt so we can make a call to the plt.gcf().savefig
284 286 self._pyplot_imported = False
@@ -293,7 +295,7 b' class EmbeddedSphinxShell(object):'
293 295
294 296 def process_input_line(self, line, store_history=True):
295 297 """process the input, capturing stdout"""
296 #print "input='%s'"%self.input
298
297 299 stdout = sys.stdout
298 300 splitter = self.IP.input_splitter
299 301 try:
@@ -337,11 +339,14 b' class EmbeddedSphinxShell(object):'
337 339
338 340 # Callbacks for each type of token
339 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 346 decorator, input, rest = data
342 347 image_file = None
343 348 image_directive = None
344 #print 'INPUT:', data # dbg
349
345 350 is_verbatim = decorator=='@verbatim' or self.is_verbatim
346 351 is_doctest = (decorator is not None and \
347 352 decorator.startswith('@doctest')) or self.is_doctest
@@ -403,22 +408,41 b' class EmbeddedSphinxShell(object):'
403 408 self.cout.truncate(0)
404 409 return (ret, input_lines, output, is_doctest, decorator, image_file,
405 410 image_directive)
406 #print 'OUTPUT', output # dbg
411
407 412
408 413 def process_output(self, data, output_prompt,
409 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 421 if is_doctest and output is not None:
412 422
413 423 found = output
414 424 found = found.strip()
415 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 436 # Make sure the output contains the output prompt.
418 437 ind = found.find(output_prompt)
419 438 if ind < 0:
420 e = ('output prompt="{0}" does '
421 'not match out line={1}'.format(output_prompt, found))
439 e = ('output does not contain output prompt\n\n'
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 446 raise RuntimeError(e)
423 447 found = found[len(output_prompt):].strip()
424 448
@@ -426,9 +450,14 b' class EmbeddedSphinxShell(object):'
426 450 if decorator.strip() == '@doctest':
427 451 # Standard doctest
428 452 if found != submitted:
429 e = ('doctest failure for input_lines="{0}" with '
430 'found_output="{1}" and submitted '
431 'output="{2}"'.format(input_lines, found, submitted) )
453 e = ('doctest failure\n\n'
454 'Document source: {0}\n\n'
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 461 raise RuntimeError(e)
433 462 else:
434 463 self.custom_doctest(decorator, input_lines, found, submitted)
@@ -653,6 +682,9 b' class IPythonDirective(Directive):'
653 682 # setting its backend since exec_lines might import pylab.
654 683 self.shell = EmbeddedSphinxShell(exec_lines)
655 684
685 # Store IPython directive to enable better error messages
686 self.shell.directive = self
687
656 688 # reset the execution count if we haven't processed this doc
657 689 #NOTE: this may be borked if there are multiple seen_doc tmp files
658 690 #check time stamp?
@@ -676,7 +708,6 b' class IPythonDirective(Directive):'
676 708
677 709 return rgxin, rgxout, promptin, promptout
678 710
679
680 711 def teardown(self):
681 712 # delete last bookmark
682 713 self.shell.process_input_line('bookmark -d ipy_savedir',
@@ -702,7 +733,7 b' class IPythonDirective(Directive):'
702 733
703 734 parts = '\n'.join(self.content).split('\n\n')
704 735
705 lines = ['.. code-block:: ipython','']
736 lines = ['.. code-block:: ipython', '']
706 737 figures = []
707 738
708 739 for part in parts:
@@ -724,7 +755,9 b' class IPythonDirective(Directive):'
724 755 if debug:
725 756 print('\n'.join(lines))
726 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 761 self.state_machine.insert_input(
729 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