##// END OF EJS Templates
Cleaner implementation of the namespace handling fix....
Fernando Perez -
Show More
@@ -1,941 +1,955 b''
1 """Nose Plugin that supports IPython doctests.
1 """Nose Plugin that supports IPython doctests.
2
2
3 Limitations:
3 Limitations:
4
4
5 - When generating examples for use as doctests, make sure that you have
5 - When generating examples for use as doctests, make sure that you have
6 pretty-printing OFF. This can be done either by starting ipython with the
6 pretty-printing OFF. This can be done either by starting ipython with the
7 flag '--nopprint', by setting pprint to 0 in your ipythonrc file, or by
7 flag '--nopprint', by setting pprint to 0 in your ipythonrc file, or by
8 interactively disabling it with %Pprint. This is required so that IPython
8 interactively disabling it with %Pprint. This is required so that IPython
9 output matches that of normal Python, which is used by doctest for internal
9 output matches that of normal Python, which is used by doctest for internal
10 execution.
10 execution.
11
11
12 - Do not rely on specific prompt numbers for results (such as using
12 - Do not rely on specific prompt numbers for results (such as using
13 '_34==True', for example). For IPython tests run via an external process the
13 '_34==True', for example). For IPython tests run via an external process the
14 prompt numbers may be different, and IPython tests run as normal python code
14 prompt numbers may be different, and IPython tests run as normal python code
15 won't even have these special _NN variables set at all.
15 won't even have these special _NN variables set at all.
16
16
17 - IPython functions that produce output as a side-effect of calling a system
17 - IPython functions that produce output as a side-effect of calling a system
18 process (e.g. 'ls') can be doc-tested, but they must be handled in an
18 process (e.g. 'ls') can be doc-tested, but they must be handled in an
19 external IPython process. Such doctests must be tagged with:
19 external IPython process. Such doctests must be tagged with:
20
20
21 # ipdoctest: EXTERNAL
21 # ipdoctest: EXTERNAL
22
22
23 so that the testing machinery handles them differently. Since these are run
23 so that the testing machinery handles them differently. Since these are run
24 via pexpect in an external process, they can't deal with exceptions or other
24 via pexpect in an external process, they can't deal with exceptions or other
25 fancy featurs of regular doctests. You must limit such tests to simple
25 fancy featurs of regular doctests. You must limit such tests to simple
26 matching of the output. For this reason, I recommend you limit these kinds
26 matching of the output. For this reason, I recommend you limit these kinds
27 of doctests to features that truly require a separate process, and use the
27 of doctests to features that truly require a separate process, and use the
28 normal IPython ones (which have all the features of normal doctests) for
28 normal IPython ones (which have all the features of normal doctests) for
29 everything else. See the examples at the bottom of this file for a
29 everything else. See the examples at the bottom of this file for a
30 comparison of what can be done with both types.
30 comparison of what can be done with both types.
31 """
31 """
32
32
33
33
34 #-----------------------------------------------------------------------------
34 #-----------------------------------------------------------------------------
35 # Module imports
35 # Module imports
36
36
37 # From the standard library
37 # From the standard library
38 import __builtin__
38 import __builtin__
39 import commands
39 import commands
40 import doctest
40 import doctest
41 import inspect
41 import inspect
42 import logging
42 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 traceback
47 import unittest
47 import unittest
48
48
49 from inspect import getmodule
49 from inspect import getmodule
50 from StringIO import StringIO
50 from StringIO import StringIO
51
51
52 # We are overriding the default doctest runner, so we need to import a few
52 # We are overriding the default doctest runner, so we need to import a few
53 # things from doctest directly
53 # things from doctest directly
54 from doctest import (REPORTING_FLAGS, REPORT_ONLY_FIRST_FAILURE,
54 from doctest import (REPORTING_FLAGS, REPORT_ONLY_FIRST_FAILURE,
55 _unittest_reportflags, DocTestRunner,
55 _unittest_reportflags, DocTestRunner,
56 _extract_future_flags, pdb, _OutputRedirectingPdb,
56 _extract_future_flags, pdb, _OutputRedirectingPdb,
57 _exception_traceback,
57 _exception_traceback,
58 linecache)
58 linecache)
59
59
60 # Third-party modules
60 # Third-party modules
61 import nose.core
61 import nose.core
62
62
63 from nose.plugins import doctests, Plugin
63 from nose.plugins import doctests, Plugin
64 from nose.util import anyp, getpackage, test_address, resolve_name, tolist
64 from nose.util import anyp, getpackage, test_address, resolve_name, tolist
65
65
66 # Our own imports
66 # Our own imports
67 #from extdoctest import ExtensionDoctest, DocTestFinder
67 #from extdoctest import ExtensionDoctest, DocTestFinder
68 #from dttools import DocTestFinder, DocTestCase
68 #from dttools import DocTestFinder, DocTestCase
69 #-----------------------------------------------------------------------------
69 #-----------------------------------------------------------------------------
70 # Module globals and other constants
70 # Module globals and other constants
71
71
72 log = logging.getLogger(__name__)
72 log = logging.getLogger(__name__)
73
73
74 ###########################################################################
74 ###########################################################################
75 # *** HACK ***
75 # *** HACK ***
76 # We must start our own ipython object and heavily muck with it so that all the
76 # We must start our own ipython object and heavily muck with it so that all the
77 # modifications IPython makes to system behavior don't send the doctest
77 # modifications IPython makes to system behavior don't send the doctest
78 # machinery into a fit. This code should be considered a gross hack, but it
78 # machinery into a fit. This code should be considered a gross hack, but it
79 # gets the job done.
79 # gets the job done.
80
80
81 class ncdict(dict):
81 class ncdict(dict):
82 """Non-copying dict class.
82 """Non-copying dict class.
83
83
84 This is a special-purpose dict subclass that overrides the .copy() method
84 This is a special-purpose dict subclass that overrides the .copy() method
85 to return the original object itself. We need it to ensure that doctests
85 to return the original object itself. We need it to ensure that doctests
86 happen in the IPython namespace, but doctest always makes a shallow copy of
86 happen in the IPython namespace, but doctest always makes a shallow copy of
87 the given globals for execution. Since we actually *want* this namespace
87 the given globals for execution. Since we actually *want* this namespace
88 to be persistent (this is how the user's session maintains state), we
88 to be persistent (this is how the user's session maintains state), we
89 simply fool doctest by returning the original object upoon copy.
89 simply fool doctest by returning the original object upoon copy.
90 """
90 """
91
91
92 def copy(self):
92 def copy(self):
93 return self
93 return self
94
94
95
95
96 # XXX - Hack to modify the %run command so we can sync the user's namespace
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
97 # with the test globals. Once we move over to a clean magic system, this will
98 # be done with much less ugliness.
98 # be done with much less ugliness.
99
99
100 def _my_run(self,arg_s,runner=None):
100 def _run_ns_sync(self,arg_s,runner=None):
101 """
101 """Modified version of %run that syncs testing namespaces.
102
103 This is strictly needed for running doctests that call %run.
102 """
104 """
103 #print 'HA!' # dbg
105
104
106 out = _ip.IP.magic_run_ori(arg_s,runner)
105 return _ip.IP.magic_run_ori(arg_s,runner)
107 _run_ns_sync.test_globs.update(_ip.user_ns)
108 return out
106
109
107
110
108 def start_ipython():
111 def start_ipython():
109 """Start a global IPython shell, which we need for IPython-specific syntax.
112 """Start a global IPython shell, which we need for IPython-specific syntax.
110 """
113 """
114 import new
115
111 import IPython
116 import IPython
112
117
113 def xsys(cmd):
118 def xsys(cmd):
114 """Execute a command and print its output.
119 """Execute a command and print its output.
115
120
116 This is just a convenience function to replace the IPython system call
121 This is just a convenience function to replace the IPython system call
117 with one that is more doctest-friendly.
122 with one that is more doctest-friendly.
118 """
123 """
119 cmd = _ip.IP.var_expand(cmd,depth=1)
124 cmd = _ip.IP.var_expand(cmd,depth=1)
120 sys.stdout.write(commands.getoutput(cmd))
125 sys.stdout.write(commands.getoutput(cmd))
121 sys.stdout.flush()
126 sys.stdout.flush()
122
127
123 # Store certain global objects that IPython modifies
128 # Store certain global objects that IPython modifies
124 _displayhook = sys.displayhook
129 _displayhook = sys.displayhook
125 _excepthook = sys.excepthook
130 _excepthook = sys.excepthook
126 _main = sys.modules.get('__main__')
131 _main = sys.modules.get('__main__')
127
132
128 # Start IPython instance. We customize it to start with minimal frills and
133 # Start IPython instance. We customize it to start with minimal frills and
129 # with our own namespace.
134 # with our own namespace.
130 argv = ['--classic','--noterm_title']
135 argv = ['--classic','--noterm_title']
131 user_ns = ncdict()
136 user_ns = ncdict()
132 IPython.Shell.IPShell(argv,user_ns)
137 IPython.Shell.IPShell(argv,user_ns)
133
138
134 # Deactivate the various python system hooks added by ipython for
139 # Deactivate the various python system hooks added by ipython for
135 # interactive convenience so we don't confuse the doctest system
140 # interactive convenience so we don't confuse the doctest system
136 sys.modules['__main__'] = _main
141 sys.modules['__main__'] = _main
137 sys.displayhook = _displayhook
142 sys.displayhook = _displayhook
138 sys.excepthook = _excepthook
143 sys.excepthook = _excepthook
139
144
140 # So that ipython magics and aliases can be doctested (they work by making
145 # So that ipython magics and aliases can be doctested (they work by making
141 # a call into a global _ip object)
146 # a call into a global _ip object)
142 _ip = IPython.ipapi.get()
147 _ip = IPython.ipapi.get()
143 __builtin__._ip = _ip
148 __builtin__._ip = _ip
144
149
145 # Modify the IPython system call with one that uses getoutput, so that we
150 # Modify the IPython system call with one that uses getoutput, so that we
146 # can capture subcommands and print them to Python's stdout, otherwise the
151 # can capture subcommands and print them to Python's stdout, otherwise the
147 # doctest machinery would miss them.
152 # doctest machinery would miss them.
148 _ip.system = xsys
153 _ip.system = xsys
149
154
150 import new
155 im = new.instancemethod(_run_ns_sync,_ip.IP, _ip.IP.__class__)
151 im = new.instancemethod(_my_run,_ip.IP, _ip.IP.__class__)
152 _ip.IP.magic_run_ori = _ip.IP.magic_run
156 _ip.IP.magic_run_ori = _ip.IP.magic_run
153 _ip.IP.magic_run = im
157 _ip.IP.magic_run = im
154
158
155 # The start call MUST be made here. I'm not sure yet why it doesn't work if
159 # The start call MUST be made here. I'm not sure yet why it doesn't work if
156 # it is made later, at plugin initialization time, but in all my tests, that's
160 # it is made later, at plugin initialization time, but in all my tests, that's
157 # the case.
161 # the case.
158 start_ipython()
162 start_ipython()
159
163
160 # *** END HACK ***
164 # *** END HACK ***
161 ###########################################################################
165 ###########################################################################
162
166
163 # Classes and functions
167 # Classes and functions
164
168
165 def is_extension_module(filename):
169 def is_extension_module(filename):
166 """Return whether the given filename is an extension module.
170 """Return whether the given filename is an extension module.
167
171
168 This simply checks that the extension is either .so or .pyd.
172 This simply checks that the extension is either .so or .pyd.
169 """
173 """
170 return os.path.splitext(filename)[1].lower() in ('.so','.pyd')
174 return os.path.splitext(filename)[1].lower() in ('.so','.pyd')
171
175
172
176
173 # Modified version of the one in the stdlib, that fixes a python bug (doctests
177 # Modified version of the one in the stdlib, that fixes a python bug (doctests
174 # not found in extension modules, http://bugs.python.org/issue3158)
178 # not found in extension modules, http://bugs.python.org/issue3158)
175 class DocTestFinder(doctest.DocTestFinder):
179 class DocTestFinder(doctest.DocTestFinder):
176
180
177 def _from_module(self, module, object):
181 def _from_module(self, module, object):
178 """
182 """
179 Return true if the given object is defined in the given
183 Return true if the given object is defined in the given
180 module.
184 module.
181 """
185 """
182 if module is None:
186 if module is None:
183 #print '_fm C1' # dbg
187 #print '_fm C1' # dbg
184 return True
188 return True
185 elif inspect.isfunction(object):
189 elif inspect.isfunction(object):
186 #print '_fm C2' # dbg
190 #print '_fm C2' # dbg
187 return module.__dict__ is object.func_globals
191 return module.__dict__ is object.func_globals
188 elif inspect.isbuiltin(object):
192 elif inspect.isbuiltin(object):
189 #print '_fm C2-1' # dbg
193 #print '_fm C2-1' # dbg
190 return module.__name__ == object.__module__
194 return module.__name__ == object.__module__
191 elif inspect.isclass(object):
195 elif inspect.isclass(object):
192 #print '_fm C3' # dbg
196 #print '_fm C3' # dbg
193 return module.__name__ == object.__module__
197 return module.__name__ == object.__module__
194 elif inspect.ismethod(object):
198 elif inspect.ismethod(object):
195 # This one may be a bug in cython that fails to correctly set the
199 # This one may be a bug in cython that fails to correctly set the
196 # __module__ attribute of methods, but since the same error is easy
200 # __module__ attribute of methods, but since the same error is easy
197 # to make by extension code writers, having this safety in place
201 # to make by extension code writers, having this safety in place
198 # isn't such a bad idea
202 # isn't such a bad idea
199 #print '_fm C3-1' # dbg
203 #print '_fm C3-1' # dbg
200 return module.__name__ == object.im_class.__module__
204 return module.__name__ == object.im_class.__module__
201 elif inspect.getmodule(object) is not None:
205 elif inspect.getmodule(object) is not None:
202 #print '_fm C4' # dbg
206 #print '_fm C4' # dbg
203 #print 'C4 mod',module,'obj',object # dbg
207 #print 'C4 mod',module,'obj',object # dbg
204 return module is inspect.getmodule(object)
208 return module is inspect.getmodule(object)
205 elif hasattr(object, '__module__'):
209 elif hasattr(object, '__module__'):
206 #print '_fm C5' # dbg
210 #print '_fm C5' # dbg
207 return module.__name__ == object.__module__
211 return module.__name__ == object.__module__
208 elif isinstance(object, property):
212 elif isinstance(object, property):
209 #print '_fm C6' # dbg
213 #print '_fm C6' # dbg
210 return True # [XX] no way not be sure.
214 return True # [XX] no way not be sure.
211 else:
215 else:
212 raise ValueError("object must be a class or function")
216 raise ValueError("object must be a class or function")
213
217
214 def _find(self, tests, obj, name, module, source_lines, globs, seen):
218 def _find(self, tests, obj, name, module, source_lines, globs, seen):
215 """
219 """
216 Find tests for the given object and any contained objects, and
220 Find tests for the given object and any contained objects, and
217 add them to `tests`.
221 add them to `tests`.
218 """
222 """
219
223
220 doctest.DocTestFinder._find(self,tests, obj, name, module,
224 doctest.DocTestFinder._find(self,tests, obj, name, module,
221 source_lines, globs, seen)
225 source_lines, globs, seen)
222
226
223 # Below we re-run pieces of the above method with manual modifications,
227 # Below we re-run pieces of the above method with manual modifications,
224 # because the original code is buggy and fails to correctly identify
228 # because the original code is buggy and fails to correctly identify
225 # doctests in extension modules.
229 # doctests in extension modules.
226
230
227 # Local shorthands
231 # Local shorthands
228 from inspect import isroutine, isclass, ismodule
232 from inspect import isroutine, isclass, ismodule
229
233
230 # Look for tests in a module's contained objects.
234 # Look for tests in a module's contained objects.
231 if inspect.ismodule(obj) and self._recurse:
235 if inspect.ismodule(obj) and self._recurse:
232 for valname, val in obj.__dict__.items():
236 for valname, val in obj.__dict__.items():
233 valname1 = '%s.%s' % (name, valname)
237 valname1 = '%s.%s' % (name, valname)
234 if ( (isroutine(val) or isclass(val))
238 if ( (isroutine(val) or isclass(val))
235 and self._from_module(module, val) ):
239 and self._from_module(module, val) ):
236
240
237 self._find(tests, val, valname1, module, source_lines,
241 self._find(tests, val, valname1, module, source_lines,
238 globs, seen)
242 globs, seen)
239
243
240 # Look for tests in a class's contained objects.
244 # Look for tests in a class's contained objects.
241 if inspect.isclass(obj) and self._recurse:
245 if inspect.isclass(obj) and self._recurse:
242 #print 'RECURSE into class:',obj # dbg
246 #print 'RECURSE into class:',obj # dbg
243 for valname, val in obj.__dict__.items():
247 for valname, val in obj.__dict__.items():
244 #valname1 = '%s.%s' % (name, valname) # dbg
248 #valname1 = '%s.%s' % (name, valname) # dbg
245 #print 'N',name,'VN:',valname,'val:',str(val)[:77] # dbg
249 #print 'N',name,'VN:',valname,'val:',str(val)[:77] # dbg
246 # Special handling for staticmethod/classmethod.
250 # Special handling for staticmethod/classmethod.
247 if isinstance(val, staticmethod):
251 if isinstance(val, staticmethod):
248 val = getattr(obj, valname)
252 val = getattr(obj, valname)
249 if isinstance(val, classmethod):
253 if isinstance(val, classmethod):
250 val = getattr(obj, valname).im_func
254 val = getattr(obj, valname).im_func
251
255
252 # Recurse to methods, properties, and nested classes.
256 # Recurse to methods, properties, and nested classes.
253 if ((inspect.isfunction(val) or inspect.isclass(val) or
257 if ((inspect.isfunction(val) or inspect.isclass(val) or
254 inspect.ismethod(val) or
258 inspect.ismethod(val) or
255 isinstance(val, property)) and
259 isinstance(val, property)) and
256 self._from_module(module, val)):
260 self._from_module(module, val)):
257 valname = '%s.%s' % (name, valname)
261 valname = '%s.%s' % (name, valname)
258 self._find(tests, val, valname, module, source_lines,
262 self._find(tests, val, valname, module, source_lines,
259 globs, seen)
263 globs, seen)
260
264
261
265
262 # second-chance checker; if the default comparison doesn't
266 # second-chance checker; if the default comparison doesn't
263 # pass, then see if the expected output string contains flags that
267 # pass, then see if the expected output string contains flags that
264 # tell us to ignore the output
268 # tell us to ignore the output
265 class IPDoctestOutputChecker(doctest.OutputChecker):
269 class IPDoctestOutputChecker(doctest.OutputChecker):
266 def check_output(self, want, got, optionflags):
270 def check_output(self, want, got, optionflags):
267 #print '*** My Checker!' # dbg
271 #print '*** My Checker!' # dbg
268
272
269 ret = doctest.OutputChecker.check_output(self, want, got,
273 ret = doctest.OutputChecker.check_output(self, want, got,
270 optionflags)
274 optionflags)
271 if not ret:
275 if not ret:
272 if "#random" in want:
276 if "#random" in want:
273 return True
277 return True
274
278
275 return ret
279 return ret
276
280
277
281
278 class DocTestCase(doctests.DocTestCase):
282 class DocTestCase(doctests.DocTestCase):
279 """Proxy for DocTestCase: provides an address() method that
283 """Proxy for DocTestCase: provides an address() method that
280 returns the correct address for the doctest case. Otherwise
284 returns the correct address for the doctest case. Otherwise
281 acts as a proxy to the test case. To provide hints for address(),
285 acts as a proxy to the test case. To provide hints for address(),
282 an obj may also be passed -- this will be used as the test object
286 an obj may also be passed -- this will be used as the test object
283 for purposes of determining the test address, if it is provided.
287 for purposes of determining the test address, if it is provided.
284 """
288 """
285
289
286 # Note: this method was taken from numpy's nosetester module.
290 # Note: this method was taken from numpy's nosetester module.
287
291
288 # Subclass nose.plugins.doctests.DocTestCase to work around a bug in
292 # Subclass nose.plugins.doctests.DocTestCase to work around a bug in
289 # its constructor that blocks non-default arguments from being passed
293 # its constructor that blocks non-default arguments from being passed
290 # down into doctest.DocTestCase
294 # down into doctest.DocTestCase
291
295
292 def __init__(self, test, optionflags=0, setUp=None, tearDown=None,
296 def __init__(self, test, optionflags=0, setUp=None, tearDown=None,
293 checker=None, obj=None, result_var='_'):
297 checker=None, obj=None, result_var='_'):
294 self._result_var = result_var
298 self._result_var = result_var
295 doctests.DocTestCase.__init__(self, test,
299 doctests.DocTestCase.__init__(self, test,
296 optionflags=optionflags,
300 optionflags=optionflags,
297 setUp=setUp, tearDown=tearDown,
301 setUp=setUp, tearDown=tearDown,
298 checker=checker)
302 checker=checker)
299 # Now we must actually copy the original constructor from the stdlib
303 # Now we must actually copy the original constructor from the stdlib
300 # doctest class, because we can't call it directly and a bug in nose
304 # doctest class, because we can't call it directly and a bug in nose
301 # means it never gets passed the right arguments.
305 # means it never gets passed the right arguments.
302
306
303 self._dt_optionflags = optionflags
307 self._dt_optionflags = optionflags
304 self._dt_checker = checker
308 self._dt_checker = checker
305 self._dt_test = test
309 self._dt_test = test
306 self._dt_setUp = setUp
310 self._dt_setUp = setUp
307 self._dt_tearDown = tearDown
311 self._dt_tearDown = tearDown
308
312
309 # Modified runTest from the default stdlib
313 # Modified runTest from the default stdlib
310 def runTest(self):
314 def runTest(self):
311 #print 'HERE!' # dbg
315 #print 'HERE!' # dbg
312
316
313 test = self._dt_test
317 test = self._dt_test
314 old = sys.stdout
318 old = sys.stdout
315 new = StringIO()
319 new = StringIO()
316 optionflags = self._dt_optionflags
320 optionflags = self._dt_optionflags
317
321
318 if not (optionflags & REPORTING_FLAGS):
322 if not (optionflags & REPORTING_FLAGS):
319 # The option flags don't include any reporting flags,
323 # The option flags don't include any reporting flags,
320 # so add the default reporting flags
324 # so add the default reporting flags
321 optionflags |= _unittest_reportflags
325 optionflags |= _unittest_reportflags
322
326
323 runner = IPDocTestRunner(optionflags=optionflags,
327 runner = IPDocTestRunner(optionflags=optionflags,
324 checker=self._dt_checker, verbose=False)
328 checker=self._dt_checker, verbose=False)
325
329
326 try:
330 try:
327 runner.DIVIDER = "-"*70
331 runner.DIVIDER = "-"*70
328 failures, tries = runner.run(
332 failures, tries = runner.run(
329 test, out=new.write, clear_globs=False)
333 test, out=new.write, clear_globs=False)
330 finally:
334 finally:
331 sys.stdout = old
335 sys.stdout = old
332
336
333 if failures:
337 if failures:
334 raise self.failureException(self.format_failure(new.getvalue()))
338 raise self.failureException(self.format_failure(new.getvalue()))
335
339
336
340
337 # A simple subclassing of the original with a different class name, so we can
341 # A simple subclassing of the original with a different class name, so we can
338 # distinguish and treat differently IPython examples from pure python ones.
342 # distinguish and treat differently IPython examples from pure python ones.
339 class IPExample(doctest.Example): pass
343 class IPExample(doctest.Example): pass
340
344
341
345
342 class IPExternalExample(doctest.Example):
346 class IPExternalExample(doctest.Example):
343 """Doctest examples to be run in an external process."""
347 """Doctest examples to be run in an external process."""
344
348
345 def __init__(self, source, want, exc_msg=None, lineno=0, indent=0,
349 def __init__(self, source, want, exc_msg=None, lineno=0, indent=0,
346 options=None):
350 options=None):
347 # Parent constructor
351 # Parent constructor
348 doctest.Example.__init__(self,source,want,exc_msg,lineno,indent,options)
352 doctest.Example.__init__(self,source,want,exc_msg,lineno,indent,options)
349
353
350 # An EXTRA newline is needed to prevent pexpect hangs
354 # An EXTRA newline is needed to prevent pexpect hangs
351 self.source += '\n'
355 self.source += '\n'
352
356
353
357
354 class IPDocTestParser(doctest.DocTestParser):
358 class IPDocTestParser(doctest.DocTestParser):
355 """
359 """
356 A class used to parse strings containing doctest examples.
360 A class used to parse strings containing doctest examples.
357
361
358 Note: This is a version modified to properly recognize IPython input and
362 Note: This is a version modified to properly recognize IPython input and
359 convert any IPython examples into valid Python ones.
363 convert any IPython examples into valid Python ones.
360 """
364 """
361 # This regular expression is used to find doctest examples in a
365 # This regular expression is used to find doctest examples in a
362 # string. It defines three groups: `source` is the source code
366 # string. It defines three groups: `source` is the source code
363 # (including leading indentation and prompts); `indent` is the
367 # (including leading indentation and prompts); `indent` is the
364 # indentation of the first (PS1) line of the source code; and
368 # indentation of the first (PS1) line of the source code; and
365 # `want` is the expected output (including leading indentation).
369 # `want` is the expected output (including leading indentation).
366
370
367 # Classic Python prompts or default IPython ones
371 # Classic Python prompts or default IPython ones
368 _PS1_PY = r'>>>'
372 _PS1_PY = r'>>>'
369 _PS2_PY = r'\.\.\.'
373 _PS2_PY = r'\.\.\.'
370
374
371 _PS1_IP = r'In\ \[\d+\]:'
375 _PS1_IP = r'In\ \[\d+\]:'
372 _PS2_IP = r'\ \ \ \.\.\.+:'
376 _PS2_IP = r'\ \ \ \.\.\.+:'
373
377
374 _RE_TPL = r'''
378 _RE_TPL = r'''
375 # Source consists of a PS1 line followed by zero or more PS2 lines.
379 # Source consists of a PS1 line followed by zero or more PS2 lines.
376 (?P<source>
380 (?P<source>
377 (?:^(?P<indent> [ ]*) (?P<ps1> %s) .*) # PS1 line
381 (?:^(?P<indent> [ ]*) (?P<ps1> %s) .*) # PS1 line
378 (?:\n [ ]* (?P<ps2> %s) .*)*) # PS2 lines
382 (?:\n [ ]* (?P<ps2> %s) .*)*) # PS2 lines
379 \n? # a newline
383 \n? # a newline
380 # Want consists of any non-blank lines that do not start with PS1.
384 # Want consists of any non-blank lines that do not start with PS1.
381 (?P<want> (?:(?![ ]*$) # Not a blank line
385 (?P<want> (?:(?![ ]*$) # Not a blank line
382 (?![ ]*%s) # Not a line starting with PS1
386 (?![ ]*%s) # Not a line starting with PS1
383 (?![ ]*%s) # Not a line starting with PS2
387 (?![ ]*%s) # Not a line starting with PS2
384 .*$\n? # But any other line
388 .*$\n? # But any other line
385 )*)
389 )*)
386 '''
390 '''
387
391
388 _EXAMPLE_RE_PY = re.compile( _RE_TPL % (_PS1_PY,_PS2_PY,_PS1_PY,_PS2_PY),
392 _EXAMPLE_RE_PY = re.compile( _RE_TPL % (_PS1_PY,_PS2_PY,_PS1_PY,_PS2_PY),
389 re.MULTILINE | re.VERBOSE)
393 re.MULTILINE | re.VERBOSE)
390
394
391 _EXAMPLE_RE_IP = re.compile( _RE_TPL % (_PS1_IP,_PS2_IP,_PS1_IP,_PS2_IP),
395 _EXAMPLE_RE_IP = re.compile( _RE_TPL % (_PS1_IP,_PS2_IP,_PS1_IP,_PS2_IP),
392 re.MULTILINE | re.VERBOSE)
396 re.MULTILINE | re.VERBOSE)
393
397
394 def ip2py(self,source):
398 def ip2py(self,source):
395 """Convert input IPython source into valid Python."""
399 """Convert input IPython source into valid Python."""
396 out = []
400 out = []
397 newline = out.append
401 newline = out.append
398 for lnum,line in enumerate(source.splitlines()):
402 for lnum,line in enumerate(source.splitlines()):
399 newline(_ip.IP.prefilter(line,lnum>0))
403 newline(_ip.IP.prefilter(line,lnum>0))
400 newline('') # ensure a closing newline, needed by doctest
404 newline('') # ensure a closing newline, needed by doctest
401 #print "PYSRC:", '\n'.join(out) # dbg
405 #print "PYSRC:", '\n'.join(out) # dbg
402 return '\n'.join(out)
406 return '\n'.join(out)
403
407
404 def parse(self, string, name='<string>'):
408 def parse(self, string, name='<string>'):
405 """
409 """
406 Divide the given string into examples and intervening text,
410 Divide the given string into examples and intervening text,
407 and return them as a list of alternating Examples and strings.
411 and return them as a list of alternating Examples and strings.
408 Line numbers for the Examples are 0-based. The optional
412 Line numbers for the Examples are 0-based. The optional
409 argument `name` is a name identifying this string, and is only
413 argument `name` is a name identifying this string, and is only
410 used for error messages.
414 used for error messages.
411 """
415 """
412
416
413 #print 'Parse string:\n',string # dbg
417 #print 'Parse string:\n',string # dbg
414
418
415 string = string.expandtabs()
419 string = string.expandtabs()
416 # If all lines begin with the same indentation, then strip it.
420 # If all lines begin with the same indentation, then strip it.
417 min_indent = self._min_indent(string)
421 min_indent = self._min_indent(string)
418 if min_indent > 0:
422 if min_indent > 0:
419 string = '\n'.join([l[min_indent:] for l in string.split('\n')])
423 string = '\n'.join([l[min_indent:] for l in string.split('\n')])
420
424
421 output = []
425 output = []
422 charno, lineno = 0, 0
426 charno, lineno = 0, 0
423
427
424 # Whether to convert the input from ipython to python syntax
428 # Whether to convert the input from ipython to python syntax
425 ip2py = False
429 ip2py = False
426 # Find all doctest examples in the string. First, try them as Python
430 # Find all doctest examples in the string. First, try them as Python
427 # examples, then as IPython ones
431 # examples, then as IPython ones
428 terms = list(self._EXAMPLE_RE_PY.finditer(string))
432 terms = list(self._EXAMPLE_RE_PY.finditer(string))
429 if terms:
433 if terms:
430 # Normal Python example
434 # Normal Python example
431 #print '-'*70 # dbg
435 #print '-'*70 # dbg
432 #print 'PyExample, Source:\n',string # dbg
436 #print 'PyExample, Source:\n',string # dbg
433 #print '-'*70 # dbg
437 #print '-'*70 # dbg
434 Example = doctest.Example
438 Example = doctest.Example
435 else:
439 else:
436 # It's an ipython example. Note that IPExamples are run
440 # It's an ipython example. Note that IPExamples are run
437 # in-process, so their syntax must be turned into valid python.
441 # in-process, so their syntax must be turned into valid python.
438 # IPExternalExamples are run out-of-process (via pexpect) so they
442 # IPExternalExamples are run out-of-process (via pexpect) so they
439 # don't need any filtering (a real ipython will be executing them).
443 # don't need any filtering (a real ipython will be executing them).
440 terms = list(self._EXAMPLE_RE_IP.finditer(string))
444 terms = list(self._EXAMPLE_RE_IP.finditer(string))
441 if re.search(r'#\s*ipdoctest:\s*EXTERNAL',string):
445 if re.search(r'#\s*ipdoctest:\s*EXTERNAL',string):
442 #print '-'*70 # dbg
446 #print '-'*70 # dbg
443 #print 'IPExternalExample, Source:\n',string # dbg
447 #print 'IPExternalExample, Source:\n',string # dbg
444 #print '-'*70 # dbg
448 #print '-'*70 # dbg
445 Example = IPExternalExample
449 Example = IPExternalExample
446 else:
450 else:
447 #print '-'*70 # dbg
451 #print '-'*70 # dbg
448 #print 'IPExample, Source:\n',string # dbg
452 #print 'IPExample, Source:\n',string # dbg
449 #print '-'*70 # dbg
453 #print '-'*70 # dbg
450 Example = IPExample
454 Example = IPExample
451 ip2py = True
455 ip2py = True
452
456
453 for m in terms:
457 for m in terms:
454 # Add the pre-example text to `output`.
458 # Add the pre-example text to `output`.
455 output.append(string[charno:m.start()])
459 output.append(string[charno:m.start()])
456 # Update lineno (lines before this example)
460 # Update lineno (lines before this example)
457 lineno += string.count('\n', charno, m.start())
461 lineno += string.count('\n', charno, m.start())
458 # Extract info from the regexp match.
462 # Extract info from the regexp match.
459 (source, options, want, exc_msg) = \
463 (source, options, want, exc_msg) = \
460 self._parse_example(m, name, lineno,ip2py)
464 self._parse_example(m, name, lineno,ip2py)
461 if Example is IPExternalExample:
465 if Example is IPExternalExample:
462 options[doctest.NORMALIZE_WHITESPACE] = True
466 options[doctest.NORMALIZE_WHITESPACE] = True
463 want += '\n'
467 want += '\n'
464 # Create an Example, and add it to the list.
468 # Create an Example, and add it to the list.
465 if not self._IS_BLANK_OR_COMMENT(source):
469 if not self._IS_BLANK_OR_COMMENT(source):
466 #print 'Example source:', source # dbg
470 #print 'Example source:', source # dbg
467 output.append(Example(source, want, exc_msg,
471 output.append(Example(source, want, exc_msg,
468 lineno=lineno,
472 lineno=lineno,
469 indent=min_indent+len(m.group('indent')),
473 indent=min_indent+len(m.group('indent')),
470 options=options))
474 options=options))
471 # Update lineno (lines inside this example)
475 # Update lineno (lines inside this example)
472 lineno += string.count('\n', m.start(), m.end())
476 lineno += string.count('\n', m.start(), m.end())
473 # Update charno.
477 # Update charno.
474 charno = m.end()
478 charno = m.end()
475 # Add any remaining post-example text to `output`.
479 # Add any remaining post-example text to `output`.
476 output.append(string[charno:])
480 output.append(string[charno:])
477 return output
481 return output
478
482
479 def _parse_example(self, m, name, lineno,ip2py=False):
483 def _parse_example(self, m, name, lineno,ip2py=False):
480 """
484 """
481 Given a regular expression match from `_EXAMPLE_RE` (`m`),
485 Given a regular expression match from `_EXAMPLE_RE` (`m`),
482 return a pair `(source, want)`, where `source` is the matched
486 return a pair `(source, want)`, where `source` is the matched
483 example's source code (with prompts and indentation stripped);
487 example's source code (with prompts and indentation stripped);
484 and `want` is the example's expected output (with indentation
488 and `want` is the example's expected output (with indentation
485 stripped).
489 stripped).
486
490
487 `name` is the string's name, and `lineno` is the line number
491 `name` is the string's name, and `lineno` is the line number
488 where the example starts; both are used for error messages.
492 where the example starts; both are used for error messages.
489
493
490 Optional:
494 Optional:
491 `ip2py`: if true, filter the input via IPython to convert the syntax
495 `ip2py`: if true, filter the input via IPython to convert the syntax
492 into valid python.
496 into valid python.
493 """
497 """
494
498
495 # Get the example's indentation level.
499 # Get the example's indentation level.
496 indent = len(m.group('indent'))
500 indent = len(m.group('indent'))
497
501
498 # Divide source into lines; check that they're properly
502 # Divide source into lines; check that they're properly
499 # indented; and then strip their indentation & prompts.
503 # indented; and then strip their indentation & prompts.
500 source_lines = m.group('source').split('\n')
504 source_lines = m.group('source').split('\n')
501
505
502 # We're using variable-length input prompts
506 # We're using variable-length input prompts
503 ps1 = m.group('ps1')
507 ps1 = m.group('ps1')
504 ps2 = m.group('ps2')
508 ps2 = m.group('ps2')
505 ps1_len = len(ps1)
509 ps1_len = len(ps1)
506
510
507 self._check_prompt_blank(source_lines, indent, name, lineno,ps1_len)
511 self._check_prompt_blank(source_lines, indent, name, lineno,ps1_len)
508 if ps2:
512 if ps2:
509 self._check_prefix(source_lines[1:], ' '*indent + ps2, name, lineno)
513 self._check_prefix(source_lines[1:], ' '*indent + ps2, name, lineno)
510
514
511 source = '\n'.join([sl[indent+ps1_len+1:] for sl in source_lines])
515 source = '\n'.join([sl[indent+ps1_len+1:] for sl in source_lines])
512
516
513 if ip2py:
517 if ip2py:
514 # Convert source input from IPython into valid Python syntax
518 # Convert source input from IPython into valid Python syntax
515 source = self.ip2py(source)
519 source = self.ip2py(source)
516
520
517 # Divide want into lines; check that it's properly indented; and
521 # Divide want into lines; check that it's properly indented; and
518 # then strip the indentation. Spaces before the last newline should
522 # then strip the indentation. Spaces before the last newline should
519 # be preserved, so plain rstrip() isn't good enough.
523 # be preserved, so plain rstrip() isn't good enough.
520 want = m.group('want')
524 want = m.group('want')
521 want_lines = want.split('\n')
525 want_lines = want.split('\n')
522 if len(want_lines) > 1 and re.match(r' *$', want_lines[-1]):
526 if len(want_lines) > 1 and re.match(r' *$', want_lines[-1]):
523 del want_lines[-1] # forget final newline & spaces after it
527 del want_lines[-1] # forget final newline & spaces after it
524 self._check_prefix(want_lines, ' '*indent, name,
528 self._check_prefix(want_lines, ' '*indent, name,
525 lineno + len(source_lines))
529 lineno + len(source_lines))
526
530
527 # Remove ipython output prompt that might be present in the first line
531 # Remove ipython output prompt that might be present in the first line
528 want_lines[0] = re.sub(r'Out\[\d+\]: \s*?\n?','',want_lines[0])
532 want_lines[0] = re.sub(r'Out\[\d+\]: \s*?\n?','',want_lines[0])
529
533
530 want = '\n'.join([wl[indent:] for wl in want_lines])
534 want = '\n'.join([wl[indent:] for wl in want_lines])
531
535
532 # If `want` contains a traceback message, then extract it.
536 # If `want` contains a traceback message, then extract it.
533 m = self._EXCEPTION_RE.match(want)
537 m = self._EXCEPTION_RE.match(want)
534 if m:
538 if m:
535 exc_msg = m.group('msg')
539 exc_msg = m.group('msg')
536 else:
540 else:
537 exc_msg = None
541 exc_msg = None
538
542
539 # Extract options from the source.
543 # Extract options from the source.
540 options = self._find_options(source, name, lineno)
544 options = self._find_options(source, name, lineno)
541
545
542 return source, options, want, exc_msg
546 return source, options, want, exc_msg
543
547
544 def _check_prompt_blank(self, lines, indent, name, lineno, ps1_len):
548 def _check_prompt_blank(self, lines, indent, name, lineno, ps1_len):
545 """
549 """
546 Given the lines of a source string (including prompts and
550 Given the lines of a source string (including prompts and
547 leading indentation), check to make sure that every prompt is
551 leading indentation), check to make sure that every prompt is
548 followed by a space character. If any line is not followed by
552 followed by a space character. If any line is not followed by
549 a space character, then raise ValueError.
553 a space character, then raise ValueError.
550
554
551 Note: IPython-modified version which takes the input prompt length as a
555 Note: IPython-modified version which takes the input prompt length as a
552 parameter, so that prompts of variable length can be dealt with.
556 parameter, so that prompts of variable length can be dealt with.
553 """
557 """
554 space_idx = indent+ps1_len
558 space_idx = indent+ps1_len
555 min_len = space_idx+1
559 min_len = space_idx+1
556 for i, line in enumerate(lines):
560 for i, line in enumerate(lines):
557 if len(line) >= min_len and line[space_idx] != ' ':
561 if len(line) >= min_len and line[space_idx] != ' ':
558 raise ValueError('line %r of the docstring for %s '
562 raise ValueError('line %r of the docstring for %s '
559 'lacks blank after %s: %r' %
563 'lacks blank after %s: %r' %
560 (lineno+i+1, name,
564 (lineno+i+1, name,
561 line[indent:space_idx], line))
565 line[indent:space_idx], line))
562
566
563
567
564 SKIP = doctest.register_optionflag('SKIP')
568 SKIP = doctest.register_optionflag('SKIP')
565
569
566
570
567 class IPDocTestRunner(doctest.DocTestRunner):
571 class IPDocTestRunner(doctest.DocTestRunner):
568
572
569 # Unfortunately, doctest uses a private method (__run) for the actual run
573 # Unfortunately, doctest uses a private method (__run) for the actual run
570 # execution, so we can't cleanly override just that part. Instead, we have
574 # execution, so we can't cleanly override just that part. Instead, we have
571 # to copy/paste the entire run() implementation so we can call our own
575 # to copy/paste the entire run() implementation so we can call our own
572 # customized runner.
576 # customized runner.
573
577
574 #/////////////////////////////////////////////////////////////////
578 #/////////////////////////////////////////////////////////////////
575 # DocTest Running
579 # DocTest Running
576 #/////////////////////////////////////////////////////////////////
580 #/////////////////////////////////////////////////////////////////
577
581
578 __LINECACHE_FILENAME_RE = re.compile(r'<doctest '
582 __LINECACHE_FILENAME_RE = re.compile(r'<doctest '
579 r'(?P<name>[\w\.]+)'
583 r'(?P<name>[\w\.]+)'
580 r'\[(?P<examplenum>\d+)\]>$')
584 r'\[(?P<examplenum>\d+)\]>$')
581
585
582 def __patched_linecache_getlines(self, filename, module_globals=None):
586 def __patched_linecache_getlines(self, filename, module_globals=None):
583 m = self.__LINECACHE_FILENAME_RE.match(filename)
587 m = self.__LINECACHE_FILENAME_RE.match(filename)
584 if m and m.group('name') == self.test.name:
588 if m and m.group('name') == self.test.name:
585 example = self.test.examples[int(m.group('examplenum'))]
589 example = self.test.examples[int(m.group('examplenum'))]
586 return example.source.splitlines(True)
590 return example.source.splitlines(True)
587 else:
591 else:
588 return self.save_linecache_getlines(filename, module_globals)
592 return self.save_linecache_getlines(filename, module_globals)
589
593
590
594
591 def _run_ip(self, test, compileflags, out):
595 def _run_ip(self, test, compileflags, out):
592 """
596 """
593 Run the examples in `test`. Write the outcome of each example
597 Run the examples in `test`. Write the outcome of each example
594 with one of the `DocTestRunner.report_*` methods, using the
598 with one of the `DocTestRunner.report_*` methods, using the
595 writer function `out`. `compileflags` is the set of compiler
599 writer function `out`. `compileflags` is the set of compiler
596 flags that should be used to execute examples. Return a tuple
600 flags that should be used to execute examples. Return a tuple
597 `(f, t)`, where `t` is the number of examples tried, and `f`
601 `(f, t)`, where `t` is the number of examples tried, and `f`
598 is the number of examples that failed. The examples are run
602 is the number of examples that failed. The examples are run
599 in the namespace `test.globs`.
603 in the namespace `test.globs`.
600 """
604 """
601
605
602 #print 'Custom ip runner! __run' # dbg
606 #print 'Custom ip runner! __run' # dbg
603
607
604 # Keep track of the number of failures and tries.
608 # Keep track of the number of failures and tries.
605 failures = tries = 0
609 failures = tries = 0
606
610
607 # Save the option flags (since option directives can be used
611 # Save the option flags (since option directives can be used
608 # to modify them).
612 # to modify them).
609 original_optionflags = self.optionflags
613 original_optionflags = self.optionflags
610
614
611 SUCCESS, FAILURE, BOOM = range(3) # `outcome` state
615 SUCCESS, FAILURE, BOOM = range(3) # `outcome` state
612
616
613 check = self._checker.check_output
617 check = self._checker.check_output
614
618
615 # Process each example.
619 # Process each example.
616 for examplenum, example in enumerate(test.examples):
620 for examplenum, example in enumerate(test.examples):
617
621
618 # If REPORT_ONLY_FIRST_FAILURE is set, then supress
622 # If REPORT_ONLY_FIRST_FAILURE is set, then supress
619 # reporting after the first failure.
623 # reporting after the first failure.
620 quiet = (self.optionflags & REPORT_ONLY_FIRST_FAILURE and
624 quiet = (self.optionflags & REPORT_ONLY_FIRST_FAILURE and
621 failures > 0)
625 failures > 0)
622
626
623 # Merge in the example's options.
627 # Merge in the example's options.
624 self.optionflags = original_optionflags
628 self.optionflags = original_optionflags
625 if example.options:
629 if example.options:
626 for (optionflag, val) in example.options.items():
630 for (optionflag, val) in example.options.items():
627 if val:
631 if val:
628 self.optionflags |= optionflag
632 self.optionflags |= optionflag
629 else:
633 else:
630 self.optionflags &= ~optionflag
634 self.optionflags &= ~optionflag
631
635
632 # If 'SKIP' is set, then skip this example.
636 # If 'SKIP' is set, then skip this example.
633 if self.optionflags & SKIP:
637 if self.optionflags & SKIP:
634 continue
638 continue
635
639
636 # Record that we started this example.
640 # Record that we started this example.
637 tries += 1
641 tries += 1
638 if not quiet:
642 if not quiet:
639 self.report_start(out, test, example)
643 self.report_start(out, test, example)
640
644
641 # Use a special filename for compile(), so we can retrieve
645 # Use a special filename for compile(), so we can retrieve
642 # the source code during interactive debugging (see
646 # the source code during interactive debugging (see
643 # __patched_linecache_getlines).
647 # __patched_linecache_getlines).
644 filename = '<doctest %s[%d]>' % (test.name, examplenum)
648 filename = '<doctest %s[%d]>' % (test.name, examplenum)
645
649
646 # Run the example in the given context (globs), and record
650 # Run the example in the given context (globs), and record
647 # any exception that gets raised. (But don't intercept
651 # any exception that gets raised. (But don't intercept
648 # keyboard interrupts.)
652 # keyboard interrupts.)
649 try:
653 try:
650 # Don't blink! This is where the user's code gets run.
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
651 exec compile(example.source, filename, "single",
665 exec compile(example.source, filename, "single",
652 compileflags, 1) in test.globs
666 compileflags, 1) in test.globs
653 self.debugger.set_continue() # ==== Example Finished ====
667 self.debugger.set_continue() # ==== Example Finished ====
654 # ipython
655 #_ip.user_ns.update(test.globs)
656 test.globs.update(_ip.user_ns)
657 #
658 exception = None
668 exception = None
659 except KeyboardInterrupt:
669 except KeyboardInterrupt:
660 raise
670 raise
661 except:
671 except:
662 exception = sys.exc_info()
672 exception = sys.exc_info()
663 self.debugger.set_continue() # ==== Example Finished ====
673 self.debugger.set_continue() # ==== Example Finished ====
664
674
665 got = self._fakeout.getvalue() # the actual output
675 got = self._fakeout.getvalue() # the actual output
666 self._fakeout.truncate(0)
676 self._fakeout.truncate(0)
667 outcome = FAILURE # guilty until proved innocent or insane
677 outcome = FAILURE # guilty until proved innocent or insane
668
678
669 # If the example executed without raising any exceptions,
679 # If the example executed without raising any exceptions,
670 # verify its output.
680 # verify its output.
671 if exception is None:
681 if exception is None:
672 if check(example.want, got, self.optionflags):
682 if check(example.want, got, self.optionflags):
673 outcome = SUCCESS
683 outcome = SUCCESS
674
684
675 # The example raised an exception: check if it was expected.
685 # The example raised an exception: check if it was expected.
676 else:
686 else:
677 exc_info = sys.exc_info()
687 exc_info = sys.exc_info()
678 exc_msg = traceback.format_exception_only(*exc_info[:2])[-1]
688 exc_msg = traceback.format_exception_only(*exc_info[:2])[-1]
679 if not quiet:
689 if not quiet:
680 got += _exception_traceback(exc_info)
690 got += _exception_traceback(exc_info)
681
691
682 # If `example.exc_msg` is None, then we weren't expecting
692 # If `example.exc_msg` is None, then we weren't expecting
683 # an exception.
693 # an exception.
684 if example.exc_msg is None:
694 if example.exc_msg is None:
685 outcome = BOOM
695 outcome = BOOM
686
696
687 # We expected an exception: see whether it matches.
697 # We expected an exception: see whether it matches.
688 elif check(example.exc_msg, exc_msg, self.optionflags):
698 elif check(example.exc_msg, exc_msg, self.optionflags):
689 outcome = SUCCESS
699 outcome = SUCCESS
690
700
691 # Another chance if they didn't care about the detail.
701 # Another chance if they didn't care about the detail.
692 elif self.optionflags & IGNORE_EXCEPTION_DETAIL:
702 elif self.optionflags & IGNORE_EXCEPTION_DETAIL:
693 m1 = re.match(r'[^:]*:', example.exc_msg)
703 m1 = re.match(r'[^:]*:', example.exc_msg)
694 m2 = re.match(r'[^:]*:', exc_msg)
704 m2 = re.match(r'[^:]*:', exc_msg)
695 if m1 and m2 and check(m1.group(0), m2.group(0),
705 if m1 and m2 and check(m1.group(0), m2.group(0),
696 self.optionflags):
706 self.optionflags):
697 outcome = SUCCESS
707 outcome = SUCCESS
698
708
699 # Report the outcome.
709 # Report the outcome.
700 if outcome is SUCCESS:
710 if outcome is SUCCESS:
701 if not quiet:
711 if not quiet:
702 self.report_success(out, test, example, got)
712 self.report_success(out, test, example, got)
703 elif outcome is FAILURE:
713 elif outcome is FAILURE:
704 if not quiet:
714 if not quiet:
705 self.report_failure(out, test, example, got)
715 self.report_failure(out, test, example, got)
706 failures += 1
716 failures += 1
707 elif outcome is BOOM:
717 elif outcome is BOOM:
708 if not quiet:
718 if not quiet:
709 self.report_unexpected_exception(out, test, example,
719 self.report_unexpected_exception(out, test, example,
710 exc_info)
720 exc_info)
711 failures += 1
721 failures += 1
712 else:
722 else:
713 assert False, ("unknown outcome", outcome)
723 assert False, ("unknown outcome", outcome)
714
724
715 # Restore the option flags (in case they were modified)
725 # Restore the option flags (in case they were modified)
716 self.optionflags = original_optionflags
726 self.optionflags = original_optionflags
717
727
718 # Record and return the number of failures and tries.
728 # Record and return the number of failures and tries.
719
729
720 # Hack to access a parent private method by working around Python's
730 # Hack to access a parent private method by working around Python's
721 # name mangling (which is fortunately simple).
731 # name mangling (which is fortunately simple).
722 #self.__record_outcome(test, failures, tries)
732 #self.__record_outcome(test, failures, tries)
723 doctest.DocTestRunner._DocTestRunner__record_outcome(self,test,
733 doctest.DocTestRunner._DocTestRunner__record_outcome(self,test,
724 failures, tries)
734 failures, tries)
725
735
726 return failures, tries
736 return failures, tries
727
737
728
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
729 def run(self, test, compileflags=None, out=None, clear_globs=True):
743 def run(self, test, compileflags=None, out=None, clear_globs=True):
730 """
744 """
731 Run the examples in `test`, and display the results using the
745 Run the examples in `test`, and display the results using the
732 writer function `out`.
746 writer function `out`.
733
747
734 The examples are run in the namespace `test.globs`. If
748 The examples are run in the namespace `test.globs`. If
735 `clear_globs` is true (the default), then this namespace will
749 `clear_globs` is true (the default), then this namespace will
736 be cleared after the test runs, to help with garbage
750 be cleared after the test runs, to help with garbage
737 collection. If you would like to examine the namespace after
751 collection. If you would like to examine the namespace after
738 the test completes, then use `clear_globs=False`.
752 the test completes, then use `clear_globs=False`.
739
753
740 `compileflags` gives the set of flags that should be used by
754 `compileflags` gives the set of flags that should be used by
741 the Python compiler when running the examples. If not
755 the Python compiler when running the examples. If not
742 specified, then it will default to the set of future-import
756 specified, then it will default to the set of future-import
743 flags that apply to `globs`.
757 flags that apply to `globs`.
744
758
745 The output of each example is checked using
759 The output of each example is checked using
746 `DocTestRunner.check_output`, and the results are formatted by
760 `DocTestRunner.check_output`, and the results are formatted by
747 the `DocTestRunner.report_*` methods.
761 the `DocTestRunner.report_*` methods.
748 """
762 """
749 #print 'Custom ip runner!' # dbg
763 #print 'Custom ip runner!' # dbg
750
764
751 self.test = test
765 self.test = test
752
766
753 if compileflags is None:
767 if compileflags is None:
754 compileflags = _extract_future_flags(test.globs)
768 compileflags = _extract_future_flags(test.globs)
755
769
756 save_stdout = sys.stdout
770 save_stdout = sys.stdout
757 if out is None:
771 if out is None:
758 out = save_stdout.write
772 out = save_stdout.write
759 sys.stdout = self._fakeout
773 sys.stdout = self._fakeout
760
774
761 # Patch pdb.set_trace to restore sys.stdout during interactive
775 # Patch pdb.set_trace to restore sys.stdout during interactive
762 # debugging (so it's not still redirected to self._fakeout).
776 # debugging (so it's not still redirected to self._fakeout).
763 # Note that the interactive output will go to *our*
777 # Note that the interactive output will go to *our*
764 # save_stdout, even if that's not the real sys.stdout; this
778 # save_stdout, even if that's not the real sys.stdout; this
765 # allows us to write test cases for the set_trace behavior.
779 # allows us to write test cases for the set_trace behavior.
766 save_set_trace = pdb.set_trace
780 save_set_trace = pdb.set_trace
767 self.debugger = _OutputRedirectingPdb(save_stdout)
781 self.debugger = _OutputRedirectingPdb(save_stdout)
768 self.debugger.reset()
782 self.debugger.reset()
769 pdb.set_trace = self.debugger.set_trace
783 pdb.set_trace = self.debugger.set_trace
770
784
771 # Patch linecache.getlines, so we can see the example's source
785 # Patch linecache.getlines, so we can see the example's source
772 # when we're inside the debugger.
786 # when we're inside the debugger.
773 self.save_linecache_getlines = linecache.getlines
787 self.save_linecache_getlines = linecache.getlines
774 linecache.getlines = self.__patched_linecache_getlines
788 linecache.getlines = self.__patched_linecache_getlines
775
789
776 try:
790 try:
777 # Hack to access a parent private method by working around Python's
791 # Hack to access a parent private method by working around Python's
778 # name mangling (which is fortunately simple).
792 # name mangling (which is fortunately simple).
779 #return self.__run(test, compileflags, out)
793 #return self.__run(test, compileflags, out)
780 return self._run_ip(test, compileflags, out)
794 return self._run_ip(test, compileflags, out)
781 #return doctest.DocTestRunner._DocTestRunner__run(self,test,
795 #return doctest.DocTestRunner._DocTestRunner__run(self,test,
782 # compileflags, out)
796 # compileflags, out)
783 finally:
797 finally:
784 _ip.user_ns.update(test.globs)
798 _ip.user_ns.update(test.globs)
785 sys.stdout = save_stdout
799 sys.stdout = save_stdout
786 pdb.set_trace = save_set_trace
800 pdb.set_trace = save_set_trace
787 linecache.getlines = self.save_linecache_getlines
801 linecache.getlines = self.save_linecache_getlines
788 if clear_globs:
802 if clear_globs:
789 test.globs.clear()
803 test.globs.clear()
790
804
791
805
792 class DocFileCase(doctest.DocFileCase):
806 class DocFileCase(doctest.DocFileCase):
793 """Overrides to provide filename
807 """Overrides to provide filename
794 """
808 """
795 def address(self):
809 def address(self):
796 return (self._dt_test.filename, None, None)
810 return (self._dt_test.filename, None, None)
797
811
798
812
799 class ExtensionDoctest(doctests.Doctest):
813 class ExtensionDoctest(doctests.Doctest):
800 """Nose Plugin that supports doctests in extension modules.
814 """Nose Plugin that supports doctests in extension modules.
801 """
815 """
802 name = 'extdoctest' # call nosetests with --with-extdoctest
816 name = 'extdoctest' # call nosetests with --with-extdoctest
803 enabled = True
817 enabled = True
804
818
805 def options(self, parser, env=os.environ):
819 def options(self, parser, env=os.environ):
806 Plugin.options(self, parser, env)
820 Plugin.options(self, parser, env)
807
821
808 def configure(self, options, config):
822 def configure(self, options, config):
809 Plugin.configure(self, options, config)
823 Plugin.configure(self, options, config)
810 self.doctest_tests = options.doctest_tests
824 self.doctest_tests = options.doctest_tests
811 self.extension = tolist(options.doctestExtension)
825 self.extension = tolist(options.doctestExtension)
812 self.finder = DocTestFinder()
826 self.finder = DocTestFinder()
813 self.parser = doctest.DocTestParser()
827 self.parser = doctest.DocTestParser()
814 self.globs = None
828 self.globs = None
815 self.extraglobs = None
829 self.extraglobs = None
816
830
817 def loadTestsFromExtensionModule(self,filename):
831 def loadTestsFromExtensionModule(self,filename):
818 bpath,mod = os.path.split(filename)
832 bpath,mod = os.path.split(filename)
819 modname = os.path.splitext(mod)[0]
833 modname = os.path.splitext(mod)[0]
820 try:
834 try:
821 sys.path.append(bpath)
835 sys.path.append(bpath)
822 module = __import__(modname)
836 module = __import__(modname)
823 tests = list(self.loadTestsFromModule(module))
837 tests = list(self.loadTestsFromModule(module))
824 finally:
838 finally:
825 sys.path.pop()
839 sys.path.pop()
826 return tests
840 return tests
827
841
828 # NOTE: the method below is almost a copy of the original one in nose, with
842 # NOTE: the method below is almost a copy of the original one in nose, with
829 # a few modifications to control output checking.
843 # a few modifications to control output checking.
830
844
831 def loadTestsFromModule(self, module):
845 def loadTestsFromModule(self, module):
832 #print 'lTM',module # dbg
846 #print 'lTM',module # dbg
833
847
834 if not self.matches(module.__name__):
848 if not self.matches(module.__name__):
835 log.debug("Doctest doesn't want module %s", module)
849 log.debug("Doctest doesn't want module %s", module)
836 return
850 return
837
851
838 ## try:
852 ## try:
839 ## print 'Globs:',self.globs.keys() # dbg
853 ## print 'Globs:',self.globs.keys() # dbg
840 ## except:
854 ## except:
841 ## pass
855 ## pass
842
856
843 tests = self.finder.find(module,globs=self.globs,
857 tests = self.finder.find(module,globs=self.globs,
844 extraglobs=self.extraglobs)
858 extraglobs=self.extraglobs)
845 if not tests:
859 if not tests:
846 return
860 return
847 tests.sort()
861 tests.sort()
848 module_file = module.__file__
862 module_file = module.__file__
849 if module_file[-4:] in ('.pyc', '.pyo'):
863 if module_file[-4:] in ('.pyc', '.pyo'):
850 module_file = module_file[:-1]
864 module_file = module_file[:-1]
851 for test in tests:
865 for test in tests:
852 if not test.examples:
866 if not test.examples:
853 continue
867 continue
854 if not test.filename:
868 if not test.filename:
855 test.filename = module_file
869 test.filename = module_file
856
870
857 # xxx - checker and options may be ok instantiated once outside loop
871 # xxx - checker and options may be ok instantiated once outside loop
858
872
859 # always use whitespace and ellipsis options
873 # always use whitespace and ellipsis options
860 optionflags = doctest.NORMALIZE_WHITESPACE | doctest.ELLIPSIS
874 optionflags = doctest.NORMALIZE_WHITESPACE | doctest.ELLIPSIS
861 checker = IPDoctestOutputChecker()
875 checker = IPDoctestOutputChecker()
862
876
863 yield DocTestCase(test,
877 yield DocTestCase(test,
864 optionflags=optionflags,
878 optionflags=optionflags,
865 checker=checker)
879 checker=checker)
866
880
867 def loadTestsFromFile(self, filename):
881 def loadTestsFromFile(self, filename):
868 #print 'lTF',filename # dbg
882 #print 'lTF',filename # dbg
869
883
870 if is_extension_module(filename):
884 if is_extension_module(filename):
871 for t in self.loadTestsFromExtensionModule(filename):
885 for t in self.loadTestsFromExtensionModule(filename):
872 yield t
886 yield t
873 else:
887 else:
874 if self.extension and anyp(filename.endswith, self.extension):
888 if self.extension and anyp(filename.endswith, self.extension):
875 name = os.path.basename(filename)
889 name = os.path.basename(filename)
876 dh = open(filename)
890 dh = open(filename)
877 try:
891 try:
878 doc = dh.read()
892 doc = dh.read()
879 finally:
893 finally:
880 dh.close()
894 dh.close()
881 test = self.parser.get_doctest(
895 test = self.parser.get_doctest(
882 doc, globs={'__file__': filename}, name=name,
896 doc, globs={'__file__': filename}, name=name,
883 filename=filename, lineno=0)
897 filename=filename, lineno=0)
884 if test.examples:
898 if test.examples:
885 #print 'FileCase:',test.examples # dbg
899 #print 'FileCase:',test.examples # dbg
886 yield DocFileCase(test)
900 yield DocFileCase(test)
887 else:
901 else:
888 yield False # no tests to load
902 yield False # no tests to load
889
903
890 def wantFile(self,filename):
904 def wantFile(self,filename):
891 """Return whether the given filename should be scanned for tests.
905 """Return whether the given filename should be scanned for tests.
892
906
893 Modified version that accepts extension modules as valid containers for
907 Modified version that accepts extension modules as valid containers for
894 doctests.
908 doctests.
895 """
909 """
896 #print 'Filename:',filename # dbg
910 #print 'Filename:',filename # dbg
897
911
898 # temporarily hardcoded list, will move to driver later
912 # temporarily hardcoded list, will move to driver later
899 exclude = ['IPython/external/',
913 exclude = ['IPython/external/',
900 'IPython/Extensions/ipy_',
914 'IPython/Extensions/ipy_',
901 'IPython/platutils_win32',
915 'IPython/platutils_win32',
902 'IPython/frontend/cocoa',
916 'IPython/frontend/cocoa',
903 'IPython_doctest_plugin',
917 'IPython_doctest_plugin',
904 'IPython/Gnuplot',
918 'IPython/Gnuplot',
905 'IPython/Extensions/PhysicalQIn']
919 'IPython/Extensions/PhysicalQIn']
906
920
907 for fex in exclude:
921 for fex in exclude:
908 if fex in filename: # substring
922 if fex in filename: # substring
909 #print '###>>> SKIP:',filename # dbg
923 #print '###>>> SKIP:',filename # dbg
910 return False
924 return False
911
925
912 if is_extension_module(filename):
926 if is_extension_module(filename):
913 return True
927 return True
914 else:
928 else:
915 return doctests.Doctest.wantFile(self,filename)
929 return doctests.Doctest.wantFile(self,filename)
916
930
917
931
918 class IPythonDoctest(ExtensionDoctest):
932 class IPythonDoctest(ExtensionDoctest):
919 """Nose Plugin that supports doctests in extension modules.
933 """Nose Plugin that supports doctests in extension modules.
920 """
934 """
921 name = 'ipdoctest' # call nosetests with --with-ipdoctest
935 name = 'ipdoctest' # call nosetests with --with-ipdoctest
922 enabled = True
936 enabled = True
923
937
924 def configure(self, options, config):
938 def configure(self, options, config):
925
939
926 Plugin.configure(self, options, config)
940 Plugin.configure(self, options, config)
927 self.doctest_tests = options.doctest_tests
941 self.doctest_tests = options.doctest_tests
928 self.extension = tolist(options.doctestExtension)
942 self.extension = tolist(options.doctestExtension)
929 self.parser = IPDocTestParser()
943 self.parser = IPDocTestParser()
930 self.finder = DocTestFinder(parser=self.parser)
944 self.finder = DocTestFinder(parser=self.parser)
931
945
932 # XXX - we need to run in the ipython user's namespace, but doing so is
946 # XXX - we need to run in the ipython user's namespace, but doing so is
933 # breaking normal doctests!
947 # breaking normal doctests!
934
948
935 #self.globs = _ip.user_ns
949 #self.globs = _ip.user_ns
936 self.globs = None
950 self.globs = None
937
951
938 self.extraglobs = None
952 self.extraglobs = None
939
953
940 # Use a specially modified test runner that is IPython-aware
954 # Use a specially modified test runner that is IPython-aware
941 self.iprunner = None
955 self.iprunner = None
General Comments 0
You need to be logged in to leave comments. Login now