##// END OF EJS Templates
Fix submitted output in verbatim mode.
chebee7i -
Show More
@@ -86,11 +86,14 b' documentation.'
86 86 Pseudo-Decorators
87 87 =================
88 88
89 Note: Only one decorator is supported per input. If more than one decorator
90 is specified, then only the last one is used.
91
89 92 In addition to the Pseudo-Decorators/options described at the above link,
90 several enhancements have been made.
91 The directive will emit a message to the console at build-time if
92 code-execution resulted in an exception or warning. You can suppress these on
93 a per-block basis by specifying the :okexcept: or :okwarning: options:
93 several enhancements have been made. The directive will emit a message to the
94 console at build-time if code-execution resulted in an exception or warning.
95 You can suppress these on a per-block basis by specifying the :okexcept:
96 or :okwarning: options:
94 97
95 98 .. code-block:: rst
96 99
@@ -203,8 +206,8 b' def block_parser(part, rgxin, rgxout, fmtin, fmtout):'
203 206 continue
204 207
205 208 if line_stripped.startswith('@'):
206 # we're assuming at most one decorator -- may need to
207 # rethink
209 # Here is where we assume there is, at most, one decorator.
210 # Might need to rethink this.
208 211 decorator = line_stripped
209 212 continue
210 213
@@ -442,16 +445,57 b' class EmbeddedSphinxShell(object):'
442 445 ret.append(formatted_line)
443 446
444 447 if not is_suppress and len(rest.strip()) and is_verbatim:
445 # the "rest" is the standard output of the
446 # input, which needs to be added in
447 # verbatim mode
448 # The "rest" is the standard output of the input.
449 # This needs to be added, even in verbatim mode.
448 450 ret.append(rest)
449 451
452 # Fetch the processed output. (This is not the submitted output.)
450 453 self.cout.seek(0)
451 output = self.cout.read()
454 processed_output = self.cout.read()
452 455 if not is_suppress and not is_semicolon:
453 ret.append(output)
454 elif is_semicolon: # get spacing right
456 #
457 # In IPythonDirective.run, the elements of `ret` are eventually
458 # combined such that '' entries correspond to newlines. So if
459 # `processed_output` is equal to '', then the adding it to `ret`
460 # ensures that there is a blank line between consecutive inputs
461 # that have no outputs, as in:
462 #
463 # In [1]: x = 4
464 #
465 # In [2]: x = 5
466 #
467 # When there is processed output, it has a '\n' at the tail end. So
468 # adding the output to `ret` will provide the necessary spacing
469 # between consecutive input/output blocks, as in:
470 #
471 # In [1]: x
472 # Out[1]: 5
473 #
474 # In [2]: x
475 # Out[2]: 5
476 #
477 # When there is stdout from the input, it also has a '\n' at the
478 # tail end, and so this ensures proper spacing as well. E.g.:
479 #
480 # In [1]: print x
481 # 5
482 #
483 # In [2]: x = 5
484 #
485 # When in verbatim mode, `processed_output` is empty (because
486 # nothing was passed to IP. Sometimes the submitted code block has
487 # an Out[] portion and sometimes it does not. When it does not, we
488 # need to ensure proper spacing, so we have to add '' to `ret`.
489 # However, if there is an Out[] in the submitted code, then we do
490 # not want to add a newline as `process_output` has stuff to add.
491 # The difficulty is that `process_input` doesn't know if
492 # `process_output` will be called---so it doesn't know if there is
493 # Out[] in the code block. The requires that we include a hack in
494 # `process_block`. See the comments there.
495 #
496 ret.append(processed_output)
497 elif is_semicolon:
498 # Make sure there is a newline after the semicolon.
455 499 ret.append('')
456 500
457 501 # context information
@@ -463,12 +507,12 b' class EmbeddedSphinxShell(object):'
463 507
464 508 # output any exceptions raised during execution to stdout
465 509 # unless :okexcept: has been specified.
466 if not is_okexcept and "Traceback" in output:
510 if not is_okexcept and "Traceback" in processed_output:
467 511 s = "\nException in %s at block ending on line %s\n" % (filename, lineno)
468 512 s += "Specify :okexcept: as an option in the ipython:: block to suppress this message\n"
469 513 sys.stdout.write('\n\n>>>' + ('-' * 73))
470 514 sys.stdout.write(s)
471 sys.stdout.write(output)
515 sys.stdout.write(processed_output)
472 516 sys.stdout.write('<<<' + ('-' * 73) + '\n\n')
473 517
474 518 # output any warning raised during execution to stdout
@@ -486,21 +530,25 b' class EmbeddedSphinxShell(object):'
486 530 sys.stdout.write('<<<' + ('-' * 73) + '\n')
487 531
488 532 self.cout.truncate(0)
489 return (ret, input_lines, output, is_doctest, decorator, image_file,
490 image_directive)
533
534 return (ret, input_lines, processed_output,
535 is_doctest, decorator, image_file, image_directive)
491 536
492 537
493 def process_output(self, data, output_prompt,
494 input_lines, output, is_doctest, decorator, image_file):
538 def process_output(self, data, output_prompt, input_lines, output,
539 is_doctest, decorator, image_file):
495 540 """
496 541 Process data block for OUTPUT token.
497 542
498 543 """
544 # Recall: `data` is the submitted output, and `output` is the processed
545 # output from `input_lines`.
546
499 547 TAB = ' ' * 4
500 548
501 549 if is_doctest and output is not None:
502 550
503 found = output
551 found = output # This is the processed output
504 552 found = found.strip()
505 553 submitted = data.strip()
506 554
@@ -542,13 +590,28 b' class EmbeddedSphinxShell(object):'
542 590 else:
543 591 self.custom_doctest(decorator, input_lines, found, submitted)
544 592
545 # Make sure output is processed when in verbatim mode.
593 # When in verbatim mode, this holds additional submitted output
594 # to be written in the final Sphinx output.
546 595 # https://github.com/ipython/ipython/issues/5776
596 out_data = []
597
547 598 is_verbatim = decorator=='@verbatim' or self.is_verbatim
548 if is_verbatim:
549 out_data = data
550 else:
551 out_data = None
599 if is_verbatim and data.strip():
600 # Note that `ret` in `process_block` has '' as its last element if
601 # the code block was in verbatim mode. So if there is no submitted
602 # output, then we will have proper spacing only if we do not add
603 # an additional '' to `out_data`. This is why we condition on
604 # `and data.strip()`.
605
606 # The submitted output has no output prompt. If we want the
607 # prompt and the code to appear, we need to join them now
608 # instead of adding them separately---as this would create an
609 # undesired newline. How we do this ultimately depends on the
610 # format of the output regex. I'll do what works for the default
611 # prompt for now, and we might have to adjust if it doesn't work
612 # in other cases. Finally, the submitted output does not have
613 # a trailing newline, so we must add it manually.
614 out_data.append("{0} {1}\n".format(output_prompt, data))
552 615
553 616 return out_data
554 617
@@ -589,14 +652,22 b' class EmbeddedSphinxShell(object):'
589 652 if token == COMMENT:
590 653 out_data = self.process_comment(data)
591 654 elif token == INPUT:
592 (out_data, input_lines, output, is_doctest, decorator,
593 image_file, image_directive) = \
655 (out_data, input_lines, output, is_doctest,
656 decorator, image_file, image_directive) = \
594 657 self.process_input(data, input_prompt, lineno)
595 658 elif token == OUTPUT:
596 659 out_data = \
597 self.process_output(data, output_prompt,
598 input_lines, output, is_doctest,
599 decorator, image_file)
660 self.process_output(data, output_prompt, input_lines,
661 output, is_doctest, decorator,
662 image_file)
663 if out_data:
664 # Then there was user submitted output in verbatim mode.
665 # We need to remove the last element of `ret` that was
666 # added in `process_input`, as it is '' and would introduce
667 # an undesirable newline.
668 assert(ret[-1] == '')
669 del ret[-1]
670
600 671 if out_data:
601 672 ret.extend(out_data)
602 673
@@ -853,7 +924,8 b' class IPythonDirective(Directive):'
853 924 if len(block):
854 925 rows, figure = self.shell.process_block(block)
855 926 for row in rows:
856 lines.extend([' %s'%line for line in row.split('\n')])
927 lines.extend([' {0}'.format(line)
928 for line in row.split('\n')])
857 929
858 930 if figure is not None:
859 931 figures.append(figure)
@@ -863,7 +935,7 b' class IPythonDirective(Directive):'
863 935 lines.extend(figure.split('\n'))
864 936 lines.append('')
865 937
866 if len(lines)>2:
938 if len(lines) > 2:
867 939 if debug:
868 940 print('\n'.join(lines))
869 941 else:
General Comments 0
You need to be logged in to leave comments. Login now