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