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 |
# |
|
|
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 |
# |
|
|
446 |
# |
|
|
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 |
|
|
|
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, |
|
|
593 |
|
|
|
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 |
|
|
|
599 |
|
|
|
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([' |
|
|
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) |
General Comments 0
You need to be logged in to leave comments.
Login now