##// END OF EJS Templates
Improvements to namespace handling with %run....
Fernando Perez -
Show More
@@ -43,9 +43,19 b' import logging'
43 import os
43 import os
44 import re
44 import re
45 import sys
45 import sys
46 import traceback
46 import unittest
47 import unittest
47
48
48 from inspect import getmodule
49 from inspect import getmodule
50 from StringIO import StringIO
51
52 # We are overriding the default doctest runner, so we need to import a few
53 # things from doctest directly
54 from doctest import (REPORTING_FLAGS, REPORT_ONLY_FIRST_FAILURE,
55 _unittest_reportflags, DocTestRunner,
56 _extract_future_flags, pdb, _OutputRedirectingPdb,
57 _exception_traceback,
58 linecache)
49
59
50 # Third-party modules
60 # Third-party modules
51 import nose.core
61 import nose.core
@@ -83,6 +93,10 b' class ncdict(dict):'
83 return self
93 return self
84
94
85
95
96 # XXX - Hack to modify the %run command so we can sync the user's namespace
97 # with the test globals. Once we move over to a clean magic system, this will
98 # be done with much less ugliness.
99
86 def _my_run(self,arg_s,runner=None):
100 def _my_run(self,arg_s,runner=None):
87 """
101 """
88 """
102 """
@@ -292,6 +306,32 b' class DocTestCase(doctests.DocTestCase):'
292 self._dt_setUp = setUp
306 self._dt_setUp = setUp
293 self._dt_tearDown = tearDown
307 self._dt_tearDown = tearDown
294
308
309 # Modified runTest from the default stdlib
310 def runTest(self):
311 #print 'HERE!' # dbg
312
313 test = self._dt_test
314 old = sys.stdout
315 new = StringIO()
316 optionflags = self._dt_optionflags
317
318 if not (optionflags & REPORTING_FLAGS):
319 # The option flags don't include any reporting flags,
320 # so add the default reporting flags
321 optionflags |= _unittest_reportflags
322
323 runner = IPDocTestRunner(optionflags=optionflags,
324 checker=self._dt_checker, verbose=False)
325
326 try:
327 runner.DIVIDER = "-"*70
328 failures, tries = runner.run(
329 test, out=new.write, clear_globs=False)
330 finally:
331 sys.stdout = old
332
333 if failures:
334 raise self.failureException(self.format_failure(new.getvalue()))
295
335
296
336
297 # A simple subclassing of the original with a different class name, so we can
337 # A simple subclassing of the original with a different class name, so we can
@@ -520,6 +560,7 b' class IPDocTestParser(doctest.DocTestParser):'
520 (lineno+i+1, name,
560 (lineno+i+1, name,
521 line[indent:space_idx], line))
561 line[indent:space_idx], line))
522
562
563
523 SKIP = doctest.register_optionflag('SKIP')
564 SKIP = doctest.register_optionflag('SKIP')
524
565
525
566
@@ -529,11 +570,25 b' class IPDocTestRunner(doctest.DocTestRunner):'
529 # execution, so we can't cleanly override just that part. Instead, we have
570 # execution, so we can't cleanly override just that part. Instead, we have
530 # to copy/paste the entire run() implementation so we can call our own
571 # to copy/paste the entire run() implementation so we can call our own
531 # customized runner.
572 # customized runner.
573
532 #/////////////////////////////////////////////////////////////////
574 #/////////////////////////////////////////////////////////////////
533 # DocTest Running
575 # DocTest Running
534 #/////////////////////////////////////////////////////////////////
576 #/////////////////////////////////////////////////////////////////
577
578 __LINECACHE_FILENAME_RE = re.compile(r'<doctest '
579 r'(?P<name>[\w\.]+)'
580 r'\[(?P<examplenum>\d+)\]>$')
581
582 def __patched_linecache_getlines(self, filename, module_globals=None):
583 m = self.__LINECACHE_FILENAME_RE.match(filename)
584 if m and m.group('name') == self.test.name:
585 example = self.test.examples[int(m.group('examplenum'))]
586 return example.source.splitlines(True)
587 else:
588 return self.save_linecache_getlines(filename, module_globals)
589
535
590
536 def __run(self, test, compileflags, out):
591 def _run_ip(self, test, compileflags, out):
537 """
592 """
538 Run the examples in `test`. Write the outcome of each example
593 Run the examples in `test`. Write the outcome of each example
539 with one of the `DocTestRunner.report_*` methods, using the
594 with one of the `DocTestRunner.report_*` methods, using the
@@ -543,6 +598,9 b' class IPDocTestRunner(doctest.DocTestRunner):'
543 is the number of examples that failed. The examples are run
598 is the number of examples that failed. The examples are run
544 in the namespace `test.globs`.
599 in the namespace `test.globs`.
545 """
600 """
601
602 #print 'Custom ip runner! __run' # dbg
603
546 # Keep track of the number of failures and tries.
604 # Keep track of the number of failures and tries.
547 failures = tries = 0
605 failures = tries = 0
548
606
@@ -593,6 +651,10 b' class IPDocTestRunner(doctest.DocTestRunner):'
593 exec compile(example.source, filename, "single",
651 exec compile(example.source, filename, "single",
594 compileflags, 1) in test.globs
652 compileflags, 1) in test.globs
595 self.debugger.set_continue() # ==== Example Finished ====
653 self.debugger.set_continue() # ==== Example Finished ====
654 # ipython
655 #_ip.user_ns.update(test.globs)
656 test.globs.update(_ip.user_ns)
657 #
596 exception = None
658 exception = None
597 except KeyboardInterrupt:
659 except KeyboardInterrupt:
598 raise
660 raise
@@ -655,14 +717,15 b' class IPDocTestRunner(doctest.DocTestRunner):'
655
717
656 # Record and return the number of failures and tries.
718 # Record and return the number of failures and tries.
657
719
658 #self.__record_outcome(test, failures, tries)
659
660 # Hack to access a parent private method by working around Python's
720 # Hack to access a parent private method by working around Python's
661 # name mangling (which is fortunately simple).
721 # name mangling (which is fortunately simple).
722 #self.__record_outcome(test, failures, tries)
662 doctest.DocTestRunner._DocTestRunner__record_outcome(self,test,
723 doctest.DocTestRunner._DocTestRunner__record_outcome(self,test,
663 failures, tries)
724 failures, tries)
725
664 return failures, tries
726 return failures, tries
665
727
728
666 def run(self, test, compileflags=None, out=None, clear_globs=True):
729 def run(self, test, compileflags=None, out=None, clear_globs=True):
667 """
730 """
668 Run the examples in `test`, and display the results using the
731 Run the examples in `test`, and display the results using the
@@ -683,6 +746,8 b' class IPDocTestRunner(doctest.DocTestRunner):'
683 `DocTestRunner.check_output`, and the results are formatted by
746 `DocTestRunner.check_output`, and the results are formatted by
684 the `DocTestRunner.report_*` methods.
747 the `DocTestRunner.report_*` methods.
685 """
748 """
749 #print 'Custom ip runner!' # dbg
750
686 self.test = test
751 self.test = test
687
752
688 if compileflags is None:
753 if compileflags is None:
@@ -709,8 +774,14 b' class IPDocTestRunner(doctest.DocTestRunner):'
709 linecache.getlines = self.__patched_linecache_getlines
774 linecache.getlines = self.__patched_linecache_getlines
710
775
711 try:
776 try:
712 return self.__run(test, compileflags, out)
777 # Hack to access a parent private method by working around Python's
778 # name mangling (which is fortunately simple).
779 #return self.__run(test, compileflags, out)
780 return self._run_ip(test, compileflags, out)
781 #return doctest.DocTestRunner._DocTestRunner__run(self,test,
782 # compileflags, out)
713 finally:
783 finally:
784 _ip.user_ns.update(test.globs)
714 sys.stdout = save_stdout
785 sys.stdout = save_stdout
715 pdb.set_trace = save_set_trace
786 pdb.set_trace = save_set_trace
716 linecache.getlines = self.save_linecache_getlines
787 linecache.getlines = self.save_linecache_getlines
@@ -865,3 +936,6 b' class IPythonDoctest(ExtensionDoctest):'
865 self.globs = None
936 self.globs = None
866
937
867 self.extraglobs = None
938 self.extraglobs = None
939
940 # Use a specially modified test runner that is IPython-aware
941 self.iprunner = None
General Comments 0
You need to be logged in to leave comments. Login now