@@ -214,6 +214,22 @@ def _find(self, tests, obj, name, module, source_lines, globs, seen):
214214 globs , seen )
215215
216216
217+ # second-chance checker; if the default comparison doesn't
218+ # pass, then see if the expected output string contains flags that
219+ # tell us to ignore the output
220+ class IPDoctestOutputChecker (doctest .OutputChecker ):
221+ def check_output (self , want , got , optionflags ):
222+ #print '*** My Checker!' # dbg
223+
224+ ret = doctest .OutputChecker .check_output (self , want , got ,
225+ optionflags )
226+ if not ret :
227+ if "#random" in want :
228+ return True
229+
230+ return ret
231+
232+
217233class DocTestCase (doctests .DocTestCase ):
218234 """Proxy for DocTestCase: provides an address() method that
219235 returns the correct address for the doctest case. Otherwise
@@ -227,26 +243,23 @@ class DocTestCase(doctests.DocTestCase):
227243 # Subclass nose.plugins.doctests.DocTestCase to work around a bug in
228244 # its constructor that blocks non-default arguments from being passed
229245 # down into doctest.DocTestCase
230- ## def __init__(self, test, optionflags=0, setUp=None, tearDown=None,
231- ## checker=None, obj=None, result_var='_'):
232- ## self._result_var = result_var
233- ## self._nose_obj = obj
234- ## doctest.DocTestCase.__init__(self, test,
235- ## optionflags=optionflags,
236- ## setUp=setUp, tearDown=tearDown,
237- ## checker=checker)
238-
239- # doctests loaded via find(obj) omit the module name
240- # so we need to override id, __repr__ and shortDescription
241- # bonus: this will squash a 2.3 vs 2.4 incompatiblity
242- def id (self ):
243- name = self ._dt_test .name
244- filename = self ._dt_test .filename
245- if filename is not None :
246- pk = getpackage (filename )
247- if pk is not None and not name .startswith (pk ):
248- name = "%s.%s" % (pk , name )
249- return name
246+
247+ def __init__ (self , test , optionflags = 0 , setUp = None , tearDown = None ,
248+ checker = None , obj = None , result_var = '_' ):
249+ self ._result_var = result_var
250+ doctests .DocTestCase .__init__ (self , test ,
251+ optionflags = optionflags ,
252+ setUp = setUp , tearDown = tearDown ,
253+ checker = checker )
254+ # Now we must actually copy the original constructor from the stdlib
255+ # doctest class, because we can't call it directly and a bug in nose
256+ # means it never gets passed the right arguments.
257+
258+ self ._dt_optionflags = optionflags
259+ self ._dt_checker = checker
260+ self ._dt_test = test
261+ self ._dt_setUp = setUp
262+ self ._dt_tearDown = tearDown
250263
251264
252265
@@ -325,8 +338,8 @@ def parse(self, string, name='<string>'):
325338 argument `name` is a name identifying this string, and is only
326339 used for error messages.
327340 """
328-
329- print 'Parse string:\n ' ,string # dbg
341+
342+ # print 'Parse string:\n',string # dbg
330343
331344 string = string .expandtabs ()
332345 # If all lines begin with the same indentation, then strip it.
@@ -390,9 +403,6 @@ def parse(self, string, name='<string>'):
390403 charno = m .end ()
391404 # Add any remaining post-example text to `output`.
392405 output .append (string [charno :])
393-
394- #print 'OUT:',output # dbg
395-
396406 return output
397407
398408 def _parse_example (self , m , name , lineno ,ip2py = False ):
@@ -517,8 +527,39 @@ def loadTestsFromExtensionModule(self,filename):
517527 sys .path .pop ()
518528 return tests
519529
530+ # NOTE: the method below is almost a copy of the original one in nose, with
531+ # a few modifications to control output checking.
532+
533+ def loadTestsFromModule (self , module ):
534+ #print 'lTM',module # dbg
535+
536+ if not self .matches (module .__name__ ):
537+ log .debug ("Doctest doesn't want module %s" , module )
538+ return
539+ tests = self .finder .find (module )
540+ if not tests :
541+ return
542+ tests .sort ()
543+ module_file = module .__file__
544+ if module_file [- 4 :] in ('.pyc' , '.pyo' ):
545+ module_file = module_file [:- 1 ]
546+ for test in tests :
547+ if not test .examples :
548+ continue
549+ if not test .filename :
550+ test .filename = module_file
551+
552+ #yield DocTestCase(test)
553+
554+ # always use whitespace and ellipsis options
555+ optionflags = doctest .NORMALIZE_WHITESPACE | doctest .ELLIPSIS
556+ checker = IPDoctestOutputChecker ()
557+ yield DocTestCase (test ,
558+ optionflags = optionflags ,
559+ checker = checker )
560+
520561 def loadTestsFromFile (self , filename ):
521- print 'lTF' ,filename # dbg
562+ # print 'lTF',filename # dbg
522563
523564 if is_extension_module (filename ):
524565 for t in self .loadTestsFromExtensionModule (filename ):
@@ -571,38 +612,6 @@ def wantFile(self,filename):
571612 else :
572613 return doctests .Doctest .wantFile (self ,filename )
573614
574- # NOTE: the method below is almost a copy of the original one in nose, with
575- # a few modifications to control output checking.
576-
577- def loadTestsFromModule (self , module ):
578- #print 'lTM',module # dbg
579-
580- if not self .matches (module .__name__ ):
581- log .debug ("Doctest doesn't want module %s" , module )
582- return
583- tests = self .finder .find (module )
584- if not tests :
585- return
586- tests .sort ()
587- module_file = module .__file__
588- if module_file [- 4 :] in ('.pyc' , '.pyo' ):
589- module_file = module_file [:- 1 ]
590- for test in tests :
591- if not test .examples :
592- continue
593- if not test .filename :
594- test .filename = module_file
595- yield DocTestCase (test )
596-
597- # always use whitespace and ellipsis options
598- optionflags = doctest .NORMALIZE_WHITESPACE | doctest .ELLIPSIS
599- #checker = DoctestOutputChecker()
600- checker = None
601- yield DocTestCase (test ,
602- optionflags = optionflags ,
603- checker = checker )
604-
605-
606615
607616class IPythonDoctest (ExtensionDoctest ):
608617 """Nose Plugin that supports doctests in extension modules.
0 commit comments