Show More
@@ -568,239 +568,22 b' class IPDocTestParser(doctest.DocTestParser):' | |||||
568 | SKIP = doctest.register_optionflag('SKIP') |
|
568 | SKIP = doctest.register_optionflag('SKIP') | |
569 |
|
569 | |||
570 |
|
570 | |||
571 | class IPDocTestRunner(doctest.DocTestRunner): |
|
571 | class IPDocTestRunner(doctest.DocTestRunner,object): | |
572 |
|
572 | """Test runner that synchronizes the IPython namespace with test globals. | ||
573 | # Unfortunately, doctest uses a private method (__run) for the actual run |
|
|||
574 | # execution, so we can't cleanly override just that part. Instead, we have |
|
|||
575 | # to copy/paste the entire run() implementation so we can call our own |
|
|||
576 | # customized runner. |
|
|||
577 |
|
||||
578 | #///////////////////////////////////////////////////////////////// |
|
|||
579 | # DocTest Running |
|
|||
580 | #///////////////////////////////////////////////////////////////// |
|
|||
581 |
|
||||
582 | __LINECACHE_FILENAME_RE = re.compile(r'<doctest ' |
|
|||
583 | r'(?P<name>[\w\.]+)' |
|
|||
584 | r'\[(?P<examplenum>\d+)\]>$') |
|
|||
585 |
|
||||
586 | def __patched_linecache_getlines(self, filename, module_globals=None): |
|
|||
587 | m = self.__LINECACHE_FILENAME_RE.match(filename) |
|
|||
588 | if m and m.group('name') == self.test.name: |
|
|||
589 | example = self.test.examples[int(m.group('examplenum'))] |
|
|||
590 | return example.source.splitlines(True) |
|
|||
591 | else: |
|
|||
592 | return self.save_linecache_getlines(filename, module_globals) |
|
|||
593 |
|
||||
594 |
|
||||
595 | def _run_ip(self, test, compileflags, out): |
|
|||
596 |
|
|
573 | """ | |
597 | Run the examples in `test`. Write the outcome of each example |
|
|||
598 | with one of the `DocTestRunner.report_*` methods, using the |
|
|||
599 | writer function `out`. `compileflags` is the set of compiler |
|
|||
600 | flags that should be used to execute examples. Return a tuple |
|
|||
601 | `(f, t)`, where `t` is the number of examples tried, and `f` |
|
|||
602 | is the number of examples that failed. The examples are run |
|
|||
603 | in the namespace `test.globs`. |
|
|||
604 | """ |
|
|||
605 |
|
||||
606 | #print 'Custom ip runner! __run' # dbg |
|
|||
607 |
|
||||
608 | # Keep track of the number of failures and tries. |
|
|||
609 | failures = tries = 0 |
|
|||
610 |
|
||||
611 | # Save the option flags (since option directives can be used |
|
|||
612 | # to modify them). |
|
|||
613 | original_optionflags = self.optionflags |
|
|||
614 |
|
||||
615 | SUCCESS, FAILURE, BOOM = range(3) # `outcome` state |
|
|||
616 |
|
||||
617 | check = self._checker.check_output |
|
|||
618 |
|
||||
619 | # Process each example. |
|
|||
620 | for examplenum, example in enumerate(test.examples): |
|
|||
621 |
|
||||
622 | # If REPORT_ONLY_FIRST_FAILURE is set, then supress |
|
|||
623 | # reporting after the first failure. |
|
|||
624 | quiet = (self.optionflags & REPORT_ONLY_FIRST_FAILURE and |
|
|||
625 | failures > 0) |
|
|||
626 |
|
||||
627 | # Merge in the example's options. |
|
|||
628 | self.optionflags = original_optionflags |
|
|||
629 | if example.options: |
|
|||
630 | for (optionflag, val) in example.options.items(): |
|
|||
631 | if val: |
|
|||
632 | self.optionflags |= optionflag |
|
|||
633 | else: |
|
|||
634 | self.optionflags &= ~optionflag |
|
|||
635 |
|
||||
636 | # If 'SKIP' is set, then skip this example. |
|
|||
637 | if self.optionflags & SKIP: |
|
|||
638 | continue |
|
|||
639 |
|
||||
640 | # Record that we started this example. |
|
|||
641 | tries += 1 |
|
|||
642 | if not quiet: |
|
|||
643 | self.report_start(out, test, example) |
|
|||
644 |
|
||||
645 | # Use a special filename for compile(), so we can retrieve |
|
|||
646 | # the source code during interactive debugging (see |
|
|||
647 | # __patched_linecache_getlines). |
|
|||
648 | filename = '<doctest %s[%d]>' % (test.name, examplenum) |
|
|||
649 |
|
||||
650 | # Run the example in the given context (globs), and record |
|
|||
651 | # any exception that gets raised. (But don't intercept |
|
|||
652 | # keyboard interrupts.) |
|
|||
653 | try: |
|
|||
654 | # Don't blink! This is where the user's code gets run. |
|
|||
655 |
|
||||
656 | # Hack: ipython needs access to the execution context of the |
|
|||
657 | # example, so that it can propagate user variables loaded by |
|
|||
658 | # %run into test.globs. We put them here into our modified |
|
|||
659 | # %run as a function attribute. Our new %run will then only |
|
|||
660 | # make the namespace update when called (rather than |
|
|||
661 | # unconconditionally updating test.globs here for all examples, |
|
|||
662 | # most of which won't be calling %run anyway). |
|
|||
663 | _run_ns_sync.test_globs = test.globs |
|
|||
664 |
|
||||
665 | exec compile(example.source, filename, "single", |
|
|||
666 | compileflags, 1) in test.globs |
|
|||
667 | self.debugger.set_continue() # ==== Example Finished ==== |
|
|||
668 | exception = None |
|
|||
669 | except KeyboardInterrupt: |
|
|||
670 | raise |
|
|||
671 | except: |
|
|||
672 | exception = sys.exc_info() |
|
|||
673 | self.debugger.set_continue() # ==== Example Finished ==== |
|
|||
674 |
|
||||
675 | got = self._fakeout.getvalue() # the actual output |
|
|||
676 | self._fakeout.truncate(0) |
|
|||
677 | outcome = FAILURE # guilty until proved innocent or insane |
|
|||
678 |
|
||||
679 | # If the example executed without raising any exceptions, |
|
|||
680 | # verify its output. |
|
|||
681 | if exception is None: |
|
|||
682 | if check(example.want, got, self.optionflags): |
|
|||
683 | outcome = SUCCESS |
|
|||
684 |
|
||||
685 | # The example raised an exception: check if it was expected. |
|
|||
686 | else: |
|
|||
687 | exc_info = sys.exc_info() |
|
|||
688 | exc_msg = traceback.format_exception_only(*exc_info[:2])[-1] |
|
|||
689 | if not quiet: |
|
|||
690 | got += _exception_traceback(exc_info) |
|
|||
691 |
|
||||
692 | # If `example.exc_msg` is None, then we weren't expecting |
|
|||
693 | # an exception. |
|
|||
694 | if example.exc_msg is None: |
|
|||
695 | outcome = BOOM |
|
|||
696 |
|
||||
697 | # We expected an exception: see whether it matches. |
|
|||
698 | elif check(example.exc_msg, exc_msg, self.optionflags): |
|
|||
699 | outcome = SUCCESS |
|
|||
700 |
|
||||
701 | # Another chance if they didn't care about the detail. |
|
|||
702 | elif self.optionflags & IGNORE_EXCEPTION_DETAIL: |
|
|||
703 | m1 = re.match(r'[^:]*:', example.exc_msg) |
|
|||
704 | m2 = re.match(r'[^:]*:', exc_msg) |
|
|||
705 | if m1 and m2 and check(m1.group(0), m2.group(0), |
|
|||
706 | self.optionflags): |
|
|||
707 | outcome = SUCCESS |
|
|||
708 |
|
||||
709 | # Report the outcome. |
|
|||
710 | if outcome is SUCCESS: |
|
|||
711 | if not quiet: |
|
|||
712 | self.report_success(out, test, example, got) |
|
|||
713 | elif outcome is FAILURE: |
|
|||
714 | if not quiet: |
|
|||
715 | self.report_failure(out, test, example, got) |
|
|||
716 | failures += 1 |
|
|||
717 | elif outcome is BOOM: |
|
|||
718 | if not quiet: |
|
|||
719 | self.report_unexpected_exception(out, test, example, |
|
|||
720 | exc_info) |
|
|||
721 | failures += 1 |
|
|||
722 | else: |
|
|||
723 | assert False, ("unknown outcome", outcome) |
|
|||
724 |
|
||||
725 | # Restore the option flags (in case they were modified) |
|
|||
726 | self.optionflags = original_optionflags |
|
|||
727 |
|
||||
728 | # Record and return the number of failures and tries. |
|
|||
729 |
|
||||
730 | # Hack to access a parent private method by working around Python's |
|
|||
731 | # name mangling (which is fortunately simple). |
|
|||
732 | #self.__record_outcome(test, failures, tries) |
|
|||
733 | doctest.DocTestRunner._DocTestRunner__record_outcome(self,test, |
|
|||
734 | failures, tries) |
|
|||
735 |
|
||||
736 | return failures, tries |
|
|||
737 |
|
||||
738 |
|
||||
739 | # Unfortunately doctest has chosen to implement a couple of key methods as |
|
|||
740 | # private (__run, in particular). We are forced to copy the entire run |
|
|||
741 | # method here just so we can override that one. Ugh. |
|
|||
742 |
|
574 | |||
743 | def run(self, test, compileflags=None, out=None, clear_globs=True): |
|
575 | def run(self, test, compileflags=None, out=None, clear_globs=True): | |
744 | """ |
|
|||
745 | Run the examples in `test`, and display the results using the |
|
|||
746 | writer function `out`. |
|
|||
747 |
|
||||
748 | The examples are run in the namespace `test.globs`. If |
|
|||
749 | `clear_globs` is true (the default), then this namespace will |
|
|||
750 | be cleared after the test runs, to help with garbage |
|
|||
751 | collection. If you would like to examine the namespace after |
|
|||
752 | the test completes, then use `clear_globs=False`. |
|
|||
753 |
|
||||
754 | `compileflags` gives the set of flags that should be used by |
|
|||
755 | the Python compiler when running the examples. If not |
|
|||
756 | specified, then it will default to the set of future-import |
|
|||
757 | flags that apply to `globs`. |
|
|||
758 |
|
||||
759 | The output of each example is checked using |
|
|||
760 | `DocTestRunner.check_output`, and the results are formatted by |
|
|||
761 | the `DocTestRunner.report_*` methods. |
|
|||
762 | """ |
|
|||
763 | #print 'Custom ip runner!' # dbg |
|
|||
764 |
|
||||
765 | self.test = test |
|
|||
766 |
|
||||
767 | if compileflags is None: |
|
|||
768 | compileflags = _extract_future_flags(test.globs) |
|
|||
769 |
|
||||
770 | save_stdout = sys.stdout |
|
|||
771 | if out is None: |
|
|||
772 | out = save_stdout.write |
|
|||
773 | sys.stdout = self._fakeout |
|
|||
774 |
|
576 | |||
775 | # Patch pdb.set_trace to restore sys.stdout during interactive |
|
577 | # Hack: ipython needs access to the execution context of the example, | |
776 | # debugging (so it's not still redirected to self._fakeout). |
|
578 | # so that it can propagate user variables loaded by %run into | |
777 | # Note that the interactive output will go to *our* |
|
579 | # test.globs. We put them here into our modified %run as a function | |
778 | # save_stdout, even if that's not the real sys.stdout; this |
|
580 | # attribute. Our new %run will then only make the namespace update | |
779 | # allows us to write test cases for the set_trace behavior. |
|
581 | # when called (rather than unconconditionally updating test.globs here | |
780 | save_set_trace = pdb.set_trace |
|
582 | # for all examples, most of which won't be calling %run anyway). | |
781 | self.debugger = _OutputRedirectingPdb(save_stdout) |
|
583 | _run_ns_sync.test_globs = test.globs | |
782 | self.debugger.reset() |
|
|||
783 | pdb.set_trace = self.debugger.set_trace |
|
|||
784 |
|
||||
785 | # Patch linecache.getlines, so we can see the example's source |
|
|||
786 | # when we're inside the debugger. |
|
|||
787 | self.save_linecache_getlines = linecache.getlines |
|
|||
788 | linecache.getlines = self.__patched_linecache_getlines |
|
|||
789 |
|
584 | |||
790 | try: |
|
585 | return super(IPDocTestRunner,self).run(test, | |
791 | # Hack to access a parent private method by working around Python's |
|
586 | compileflags,out,clear_globs) | |
792 | # name mangling (which is fortunately simple). |
|
|||
793 | #return self.__run(test, compileflags, out) |
|
|||
794 | return self._run_ip(test, compileflags, out) |
|
|||
795 | #return doctest.DocTestRunner._DocTestRunner__run(self,test, |
|
|||
796 | # compileflags, out) |
|
|||
797 | finally: |
|
|||
798 | _ip.user_ns.update(test.globs) |
|
|||
799 | sys.stdout = save_stdout |
|
|||
800 | pdb.set_trace = save_set_trace |
|
|||
801 | linecache.getlines = self.save_linecache_getlines |
|
|||
802 | if clear_globs: |
|
|||
803 | test.globs.clear() |
|
|||
804 |
|
587 | |||
805 |
|
588 | |||
806 | class DocFileCase(doctest.DocFileCase): |
|
589 | class DocFileCase(doctest.DocFileCase): |
General Comments 0
You need to be logged in to leave comments.
Login now