##// END OF EJS Templates
Cleanups, document, working on support for full random tests.
Fernando Perez -
Show More
@@ -74,28 +74,36 b' def ipfunc():'
74 def ranfunc():
74 def ranfunc():
75 """A function with some random output.
75 """A function with some random output.
76
76
77 Normal inputs are verified as usual:
77 >>> 1+3
78 >>> 1+3
78 junk goes here... #random
79 4
79
80
81 But if you put '# random' in the output, it is ignored:
80 >>> 1+3
82 >>> 1+3
81 4
83 junk goes here... # random
82
84
83 >>> 1+2
85 >>> 1+2
84 again, anything goes #random
86 again, anything goes #random
85 if multiline, the random mark is only needed in teh first line.
87 if multiline, the random mark is only needed once.
86
88
87 >>> 1+3
89 >>> 1+2
88 4
90 You can also put the random marker at the end:
91 # random
92
93 >>> 1+2
94 # random
95 .. or at the beginning.
89
96
97 More correct input is properly verified:
90 >>> ranfunc()
98 >>> ranfunc()
91 'ranfunc'
99 'ranfunc'
92 """
100 """
93 return 'ranfunc'
101 return 'ranfunc'
94
102
95
103
96 if 1:
104 if 0:
97 def ranf2():
105 def ranf2():
98 """A function whose examples'output are all to be ignored.
106 """A function whose examples' output are completely ignored.
99
107
100 Examples:
108 Examples:
101
109
@@ -184,33 +184,24 b' class DocTestFinder(doctest.DocTestFinder):'
184 module.
184 module.
185 """
185 """
186 if module is None:
186 if module is None:
187 #print '_fm C1' # dbg
188 return True
187 return True
189 elif inspect.isfunction(object):
188 elif inspect.isfunction(object):
190 #print '_fm C2' # dbg
191 return module.__dict__ is object.func_globals
189 return module.__dict__ is object.func_globals
192 elif inspect.isbuiltin(object):
190 elif inspect.isbuiltin(object):
193 #print '_fm C2-1' # dbg
194 return module.__name__ == object.__module__
191 return module.__name__ == object.__module__
195 elif inspect.isclass(object):
192 elif inspect.isclass(object):
196 #print '_fm C3' # dbg
197 return module.__name__ == object.__module__
193 return module.__name__ == object.__module__
198 elif inspect.ismethod(object):
194 elif inspect.ismethod(object):
199 # This one may be a bug in cython that fails to correctly set the
195 # This one may be a bug in cython that fails to correctly set the
200 # __module__ attribute of methods, but since the same error is easy
196 # __module__ attribute of methods, but since the same error is easy
201 # to make by extension code writers, having this safety in place
197 # to make by extension code writers, having this safety in place
202 # isn't such a bad idea
198 # isn't such a bad idea
203 #print '_fm C3-1' # dbg
204 return module.__name__ == object.im_class.__module__
199 return module.__name__ == object.im_class.__module__
205 elif inspect.getmodule(object) is not None:
200 elif inspect.getmodule(object) is not None:
206 #print '_fm C4' # dbg
207 #print 'C4 mod',module,'obj',object # dbg
208 return module is inspect.getmodule(object)
201 return module is inspect.getmodule(object)
209 elif hasattr(object, '__module__'):
202 elif hasattr(object, '__module__'):
210 #print '_fm C5' # dbg
211 return module.__name__ == object.__module__
203 return module.__name__ == object.__module__
212 elif isinstance(object, property):
204 elif isinstance(object, property):
213 #print '_fm C6' # dbg
214 return True # [XX] no way not be sure.
205 return True # [XX] no way not be sure.
215 else:
206 else:
216 raise ValueError("object must be a class or function")
207 raise ValueError("object must be a class or function")
@@ -263,18 +254,28 b' class DocTestFinder(doctest.DocTestFinder):'
263 globs, seen)
254 globs, seen)
264
255
265
256
266 # second-chance checker; if the default comparison doesn't
267 # pass, then see if the expected output string contains flags that
268 # tell us to ignore the output
269 class IPDoctestOutputChecker(doctest.OutputChecker):
257 class IPDoctestOutputChecker(doctest.OutputChecker):
258 """Second-chance checker with support for random tests.
259
260 If the default comparison doesn't pass, this checker looks in the expected
261 output string for flags that tell us to ignore the output.
262 """
263
264 random_re = re.compile(r'#\s*random')
265
270 def check_output(self, want, got, optionflags):
266 def check_output(self, want, got, optionflags):
271 #print '*** My Checker!' # dbg
267 """Check output, accepting special markers embedded in the output.
272
268
269 If the output didn't pass the default validation but the special string
270 '#random' is included, we accept it."""
271
272 # Let the original tester verify first, in case people have valid tests
273 # that happen to have a comment saying '#random' embedded in.
273 ret = doctest.OutputChecker.check_output(self, want, got,
274 ret = doctest.OutputChecker.check_output(self, want, got,
274 optionflags)
275 optionflags)
275 if not ret:
276 if not ret and self.random_re.search(want):
276 if "#random" in want:
277 #print >> sys.stderr, 'RANDOM OK:',want # dbg
277 return True
278 return True
278
279
279 return ret
280 return ret
280
281
@@ -405,6 +406,8 b' class IPDocTestParser(doctest.DocTestParser):'
405 _EXAMPLE_RE_IP = re.compile( _RE_TPL % (_PS1_IP,_PS2_IP,_PS1_IP,_PS2_IP),
406 _EXAMPLE_RE_IP = re.compile( _RE_TPL % (_PS1_IP,_PS2_IP,_PS1_IP,_PS2_IP),
406 re.MULTILINE | re.VERBOSE)
407 re.MULTILINE | re.VERBOSE)
407
408
409 _EXTERNAL_IP = re.compile(r'#\s*ipdoctest:\s*EXTERNAL')
410
408 def ip2py(self,source):
411 def ip2py(self,source):
409 """Convert input IPython source into valid Python."""
412 """Convert input IPython source into valid Python."""
410 out = []
413 out = []
@@ -452,7 +455,7 b' class IPDocTestParser(doctest.DocTestParser):'
452 # IPExternalExamples are run out-of-process (via pexpect) so they
455 # IPExternalExamples are run out-of-process (via pexpect) so they
453 # don't need any filtering (a real ipython will be executing them).
456 # don't need any filtering (a real ipython will be executing them).
454 terms = list(self._EXAMPLE_RE_IP.finditer(string))
457 terms = list(self._EXAMPLE_RE_IP.finditer(string))
455 if re.search(r'#\s*ipdoctest:\s*EXTERNAL',string):
458 if self._EXTERNAL_IP.search(string):
456 #print '-'*70 # dbg
459 #print '-'*70 # dbg
457 #print 'IPExternalExample, Source:\n',string # dbg
460 #print 'IPExternalExample, Source:\n',string # dbg
458 #print '-'*70 # dbg
461 #print '-'*70 # dbg
General Comments 0
You need to be logged in to leave comments. Login now