##// END OF EJS Templates
Fix naming convention to PEP 8.
Fernando Perez -
Show More
@@ -1,877 +1,875 b''
1 1 """Nose Plugin that supports IPython doctests.
2 2
3 3 Limitations:
4 4
5 5 - When generating examples for use as doctests, make sure that you have
6 6 pretty-printing OFF. This can be done either by starting ipython with the
7 7 flag '--nopprint', by setting pprint to 0 in your ipythonrc file, or by
8 8 interactively disabling it with %Pprint. This is required so that IPython
9 9 output matches that of normal Python, which is used by doctest for internal
10 10 execution.
11 11
12 12 - Do not rely on specific prompt numbers for results (such as using
13 13 '_34==True', for example). For IPython tests run via an external process the
14 14 prompt numbers may be different, and IPython tests run as normal python code
15 15 won't even have these special _NN variables set at all.
16 16 """
17 17
18
19 18 #-----------------------------------------------------------------------------
20 19 # Module imports
21 20
22 21 # From the standard library
23 22 import __builtin__
24 23 import commands
25 24 import doctest
26 25 import inspect
27 26 import logging
28 27 import os
29 28 import re
30 29 import sys
31 30 import traceback
32 31 import unittest
33 32
34 33 from inspect import getmodule
35 34 from StringIO import StringIO
36 35
37 36 # We are overriding the default doctest runner, so we need to import a few
38 37 # things from doctest directly
39 38 from doctest import (REPORTING_FLAGS, REPORT_ONLY_FIRST_FAILURE,
40 39 _unittest_reportflags, DocTestRunner,
41 40 _extract_future_flags, pdb, _OutputRedirectingPdb,
42 41 _exception_traceback,
43 42 linecache)
44 43
45 44 # Third-party modules
46 45 import nose.core
47 46
48 47 from nose.plugins import doctests, Plugin
49 48 from nose.util import anyp, getpackage, test_address, resolve_name, tolist
50 49
51 50 #-----------------------------------------------------------------------------
52 51 # Module globals and other constants
53 52
54 53 log = logging.getLogger(__name__)
55 54
56 55 ###########################################################################
57 56 # *** HACK ***
58 57 # We must start our own ipython object and heavily muck with it so that all the
59 58 # modifications IPython makes to system behavior don't send the doctest
60 59 # machinery into a fit. This code should be considered a gross hack, but it
61 60 # gets the job done.
62 61
63 62
64 63 # Hack to modify the %run command so we can sync the user's namespace with the
65 64 # test globals. Once we move over to a clean magic system, this will be done
66 65 # with much less ugliness.
67 66
68 67 class py_file_finder(object):
69 68 def __init__(self,test_filename):
70 69 self.test_filename = test_filename
71 70
72 71 def __call__(self,name):
73 72 from IPython.genutils import get_py_filename
74 73 try:
75 74 return get_py_filename(name)
76 75 except IOError:
77 76 test_dir = os.path.dirname(self.test_filename)
78 77 new_path = os.path.join(test_dir,name)
79 78 return get_py_filename(new_path)
80 79
81 80
82 81 def _run_ns_sync(self,arg_s,runner=None):
83 82 """Modified version of %run that syncs testing namespaces.
84 83
85 84 This is strictly needed for running doctests that call %run.
86 85 """
87 86
88 87 finder = py_file_finder(_run_ns_sync.test_filename)
89 88 out = _ip.IP.magic_run_ori(arg_s,runner,finder)
90 89 _run_ns_sync.test_globs.update(_ip.user_ns)
91 90 return out
92 91
93 92
94 93 class ipnsdict(dict):
95 94 """A special subclass of dict for use as an IPython namespace in doctests.
96 95
97 96 This subclass adds a simple checkpointing capability so that when testing
98 97 machinery clears it (we use it as the test execution context), it doesn't
99 98 get completely destroyed.
100 99 """
101 100
102 101 def __init__(self,*a):
103 102 dict.__init__(self,*a)
104 103 self._savedict = {}
105 104
106 105 def clear(self):
107 106 dict.clear(self)
108 107 self.update(self._savedict)
109 108
110 109 def _checkpoint(self):
111 110 self._savedict.clear()
112 111 self._savedict.update(self)
113 112
114 113 def update(self,other):
115 114 self._checkpoint()
116 115 dict.update(self,other)
117 116 # If '_' is in the namespace, python won't set it when executing code,
118 117 # and we have examples that test it. So we ensure that the namespace
119 118 # is always 'clean' of it before it's used for test code execution.
120 119 self.pop('_',None)
121 120
122 121
123 122 def start_ipython():
124 123 """Start a global IPython shell, which we need for IPython-specific syntax.
125 124 """
126 125
127 126 # This function should only ever run once!
128 127 if hasattr(start_ipython,'already_called'):
129 128 return
130 129 start_ipython.already_called = True
131 130
132 131 # Ok, first time we're called, go ahead
133 132 import new
134 133
135 134 import IPython
136 135
137 136 def xsys(cmd):
138 137 """Execute a command and print its output.
139 138
140 139 This is just a convenience function to replace the IPython system call
141 140 with one that is more doctest-friendly.
142 141 """
143 142 cmd = _ip.IP.var_expand(cmd,depth=1)
144 143 sys.stdout.write(commands.getoutput(cmd))
145 144 sys.stdout.flush()
146 145
147 146 # Store certain global objects that IPython modifies
148 147 _displayhook = sys.displayhook
149 148 _excepthook = sys.excepthook
150 149 _main = sys.modules.get('__main__')
151 150
152 151 # Start IPython instance. We customize it to start with minimal frills.
153 152 user_ns,global_ns = IPython.ipapi.make_user_namespaces(ipnsdict(),dict())
154 153 IPython.Shell.IPShell(['--colors=NoColor','--noterm_title'],
155 154 user_ns,global_ns)
156 155
157 156 # Deactivate the various python system hooks added by ipython for
158 157 # interactive convenience so we don't confuse the doctest system
159 158 sys.modules['__main__'] = _main
160 159 sys.displayhook = _displayhook
161 160 sys.excepthook = _excepthook
162 161
163 162 # So that ipython magics and aliases can be doctested (they work by making
164 163 # a call into a global _ip object)
165 164 _ip = IPython.ipapi.get()
166 165 __builtin__._ip = _ip
167 166
168 167 # Modify the IPython system call with one that uses getoutput, so that we
169 168 # can capture subcommands and print them to Python's stdout, otherwise the
170 169 # doctest machinery would miss them.
171 170 _ip.system = xsys
172 171
173 172 # Also patch our %run function in.
174 173 im = new.instancemethod(_run_ns_sync,_ip.IP, _ip.IP.__class__)
175 174 _ip.IP.magic_run_ori = _ip.IP.magic_run
176 175 _ip.IP.magic_run = im
177 176
178 177 # The start call MUST be made here. I'm not sure yet why it doesn't work if
179 178 # it is made later, at plugin initialization time, but in all my tests, that's
180 179 # the case.
181 180 start_ipython()
182 181
183 182 # *** END HACK ***
184 183 ###########################################################################
185 184
186 185 # Classes and functions
187 186
188 187 def is_extension_module(filename):
189 188 """Return whether the given filename is an extension module.
190 189
191 190 This simply checks that the extension is either .so or .pyd.
192 191 """
193 192 return os.path.splitext(filename)[1].lower() in ('.so','.pyd')
194 193
195 194
196 195 class DocTestSkip(object):
197 196 """Object wrapper for doctests to be skipped."""
198 197
199 198 ds_skip = """Doctest to skip.
200 199 >>> 1 #doctest: +SKIP
201 200 """
202 201
203 202 def __init__(self,obj):
204 203 self.obj = obj
205 204
206 205 def __getattribute__(self,key):
207 206 if key == '__doc__':
208 207 return DocTestSkip.ds_skip
209 208 else:
210 209 return getattr(object.__getattribute__(self,'obj'),key)
211 210
212 211 # Modified version of the one in the stdlib, that fixes a python bug (doctests
213 212 # not found in extension modules, http://bugs.python.org/issue3158)
214 213 class DocTestFinder(doctest.DocTestFinder):
215 214
216 215 def _from_module(self, module, object):
217 216 """
218 217 Return true if the given object is defined in the given
219 218 module.
220 219 """
221 220 if module is None:
222 221 return True
223 222 elif inspect.isfunction(object):
224 223 return module.__dict__ is object.func_globals
225 224 elif inspect.isbuiltin(object):
226 225 return module.__name__ == object.__module__
227 226 elif inspect.isclass(object):
228 227 return module.__name__ == object.__module__
229 228 elif inspect.ismethod(object):
230 229 # This one may be a bug in cython that fails to correctly set the
231 230 # __module__ attribute of methods, but since the same error is easy
232 231 # to make by extension code writers, having this safety in place
233 232 # isn't such a bad idea
234 233 return module.__name__ == object.im_class.__module__
235 234 elif inspect.getmodule(object) is not None:
236 235 return module is inspect.getmodule(object)
237 236 elif hasattr(object, '__module__'):
238 237 return module.__name__ == object.__module__
239 238 elif isinstance(object, property):
240 239 return True # [XX] no way not be sure.
241 240 else:
242 241 raise ValueError("object must be a class or function")
243 242
244 243 def _find(self, tests, obj, name, module, source_lines, globs, seen):
245 244 """
246 245 Find tests for the given object and any contained objects, and
247 246 add them to `tests`.
248 247 """
249 248
250 249 if hasattr(obj,"skip_doctest"):
251 250 #print 'SKIPPING DOCTEST FOR:',obj # dbg
252 251 obj = DocTestSkip(obj)
253 252
254 253 doctest.DocTestFinder._find(self,tests, obj, name, module,
255 254 source_lines, globs, seen)
256 255
257 256 # Below we re-run pieces of the above method with manual modifications,
258 257 # because the original code is buggy and fails to correctly identify
259 258 # doctests in extension modules.
260 259
261 260 # Local shorthands
262 261 from inspect import isroutine, isclass, ismodule
263 262
264 263 # Look for tests in a module's contained objects.
265 264 if inspect.ismodule(obj) and self._recurse:
266 265 for valname, val in obj.__dict__.items():
267 266 valname1 = '%s.%s' % (name, valname)
268 267 if ( (isroutine(val) or isclass(val))
269 268 and self._from_module(module, val) ):
270 269
271 270 self._find(tests, val, valname1, module, source_lines,
272 271 globs, seen)
273 272
274 273 # Look for tests in a class's contained objects.
275 274 if inspect.isclass(obj) and self._recurse:
276 275 #print 'RECURSE into class:',obj # dbg
277 276 for valname, val in obj.__dict__.items():
278 277 # Special handling for staticmethod/classmethod.
279 278 if isinstance(val, staticmethod):
280 279 val = getattr(obj, valname)
281 280 if isinstance(val, classmethod):
282 281 val = getattr(obj, valname).im_func
283 282
284 283 # Recurse to methods, properties, and nested classes.
285 284 if ((inspect.isfunction(val) or inspect.isclass(val) or
286 285 inspect.ismethod(val) or
287 286 isinstance(val, property)) and
288 287 self._from_module(module, val)):
289 288 valname = '%s.%s' % (name, valname)
290 289 self._find(tests, val, valname, module, source_lines,
291 290 globs, seen)
292 291
293 292
294 293 class IPDoctestOutputChecker(doctest.OutputChecker):
295 294 """Second-chance checker with support for random tests.
296 295
297 296 If the default comparison doesn't pass, this checker looks in the expected
298 297 output string for flags that tell us to ignore the output.
299 298 """
300 299
301 300 random_re = re.compile(r'#\s*random\s+')
302 301
303 302 def check_output(self, want, got, optionflags):
304 303 """Check output, accepting special markers embedded in the output.
305 304
306 305 If the output didn't pass the default validation but the special string
307 306 '#random' is included, we accept it."""
308 307
309 308 # Let the original tester verify first, in case people have valid tests
310 309 # that happen to have a comment saying '#random' embedded in.
311 310 ret = doctest.OutputChecker.check_output(self, want, got,
312 311 optionflags)
313 312 if not ret and self.random_re.search(want):
314 313 #print >> sys.stderr, 'RANDOM OK:',want # dbg
315 314 return True
316 315
317 316 return ret
318 317
319 318
320 319 class DocTestCase(doctests.DocTestCase):
321 320 """Proxy for DocTestCase: provides an address() method that
322 321 returns the correct address for the doctest case. Otherwise
323 322 acts as a proxy to the test case. To provide hints for address(),
324 323 an obj may also be passed -- this will be used as the test object
325 324 for purposes of determining the test address, if it is provided.
326 325 """
327 326
328 327 # Note: this method was taken from numpy's nosetester module.
329 328
330 329 # Subclass nose.plugins.doctests.DocTestCase to work around a bug in
331 330 # its constructor that blocks non-default arguments from being passed
332 331 # down into doctest.DocTestCase
333 332
334 333 def __init__(self, test, optionflags=0, setUp=None, tearDown=None,
335 334 checker=None, obj=None, result_var='_'):
336 335 self._result_var = result_var
337 336 doctests.DocTestCase.__init__(self, test,
338 337 optionflags=optionflags,
339 338 setUp=setUp, tearDown=tearDown,
340 339 checker=checker)
341 340 # Now we must actually copy the original constructor from the stdlib
342 341 # doctest class, because we can't call it directly and a bug in nose
343 342 # means it never gets passed the right arguments.
344 343
345 344 self._dt_optionflags = optionflags
346 345 self._dt_checker = checker
347 346 self._dt_test = test
348 347 self._dt_setUp = setUp
349 348 self._dt_tearDown = tearDown
350 349
351 350 # XXX - store this runner once in the object!
352 351 runner = IPDocTestRunner(optionflags=optionflags,
353 352 checker=checker, verbose=False)
354 353 self._dt_runner = runner
355 354
356 355
357 356 # Each doctest should remember what directory it was loaded from...
358 357 self._ori_dir = os.getcwd()
359 358
360 359 # Modified runTest from the default stdlib
361 360 def runTest(self):
362 361 test = self._dt_test
363 362 runner = self._dt_runner
364 363
365 364 old = sys.stdout
366 365 new = StringIO()
367 366 optionflags = self._dt_optionflags
368 367
369 368 if not (optionflags & REPORTING_FLAGS):
370 369 # The option flags don't include any reporting flags,
371 370 # so add the default reporting flags
372 371 optionflags |= _unittest_reportflags
373 372
374 373 try:
375 374 # Save our current directory and switch out to the one where the
376 375 # test was originally created, in case another doctest did a
377 376 # directory change. We'll restore this in the finally clause.
378 377 curdir = os.getcwd()
379 378 os.chdir(self._ori_dir)
380 379
381 380 runner.DIVIDER = "-"*70
382 381 failures, tries = runner.run(test,out=new.write,
383 382 clear_globs=False)
384 383 finally:
385 384 sys.stdout = old
386 385 os.chdir(curdir)
387 386
388 387 if failures:
389 388 raise self.failureException(self.format_failure(new.getvalue()))
390 389
391 390 def setUp(self):
392 391 """Modified test setup that syncs with ipython namespace"""
393 392
394 393 if isinstance(self._dt_test.examples[0],IPExample):
395 394 # for IPython examples *only*, we swap the globals with the ipython
396 395 # namespace, after updating it with the globals (which doctest
397 396 # fills with the necessary info from the module being tested).
398 397 _ip.IP.user_ns.update(self._dt_test.globs)
399 398 self._dt_test.globs = _ip.IP.user_ns
400 399
401 400 doctests.DocTestCase.setUp(self)
402 401
403 402
404 403 # A simple subclassing of the original with a different class name, so we can
405 404 # distinguish and treat differently IPython examples from pure python ones.
406 405 class IPExample(doctest.Example): pass
407 406
408 407
409 408 class IPExternalExample(doctest.Example):
410 409 """Doctest examples to be run in an external process."""
411 410
412 411 def __init__(self, source, want, exc_msg=None, lineno=0, indent=0,
413 412 options=None):
414 413 # Parent constructor
415 414 doctest.Example.__init__(self,source,want,exc_msg,lineno,indent,options)
416 415
417 416 # An EXTRA newline is needed to prevent pexpect hangs
418 417 self.source += '\n'
419 418
420 419
421 420 class IPDocTestParser(doctest.DocTestParser):
422 421 """
423 422 A class used to parse strings containing doctest examples.
424 423
425 424 Note: This is a version modified to properly recognize IPython input and
426 425 convert any IPython examples into valid Python ones.
427 426 """
428 427 # This regular expression is used to find doctest examples in a
429 428 # string. It defines three groups: `source` is the source code
430 429 # (including leading indentation and prompts); `indent` is the
431 430 # indentation of the first (PS1) line of the source code; and
432 431 # `want` is the expected output (including leading indentation).
433 432
434 433 # Classic Python prompts or default IPython ones
435 434 _PS1_PY = r'>>>'
436 435 _PS2_PY = r'\.\.\.'
437 436
438 437 _PS1_IP = r'In\ \[\d+\]:'
439 438 _PS2_IP = r'\ \ \ \.\.\.+:'
440 439
441 440 _RE_TPL = r'''
442 441 # Source consists of a PS1 line followed by zero or more PS2 lines.
443 442 (?P<source>
444 443 (?:^(?P<indent> [ ]*) (?P<ps1> %s) .*) # PS1 line
445 444 (?:\n [ ]* (?P<ps2> %s) .*)*) # PS2 lines
446 445 \n? # a newline
447 446 # Want consists of any non-blank lines that do not start with PS1.
448 447 (?P<want> (?:(?![ ]*$) # Not a blank line
449 448 (?![ ]*%s) # Not a line starting with PS1
450 449 (?![ ]*%s) # Not a line starting with PS2
451 450 .*$\n? # But any other line
452 451 )*)
453 452 '''
454 453
455 454 _EXAMPLE_RE_PY = re.compile( _RE_TPL % (_PS1_PY,_PS2_PY,_PS1_PY,_PS2_PY),
456 455 re.MULTILINE | re.VERBOSE)
457 456
458 457 _EXAMPLE_RE_IP = re.compile( _RE_TPL % (_PS1_IP,_PS2_IP,_PS1_IP,_PS2_IP),
459 458 re.MULTILINE | re.VERBOSE)
460 459
461 460 # Mark a test as being fully random. In this case, we simply append the
462 461 # random marker ('#random') to each individual example's output. This way
463 462 # we don't need to modify any other code.
464 463 _RANDOM_TEST = re.compile(r'#\s*all-random\s+')
465 464
466 465 # Mark tests to be executed in an external process - currently unsupported.
467 466 _EXTERNAL_IP = re.compile(r'#\s*ipdoctest:\s*EXTERNAL')
468 467
469 468 def ip2py(self,source):
470 469 """Convert input IPython source into valid Python."""
471 470 out = []
472 471 newline = out.append
473 472 #print 'IPSRC:\n',source,'\n###' # dbg
474 473 # The input source must be first stripped of all bracketing whitespace
475 474 # and turned into lines, so it looks to the parser like regular user
476 475 # input
477 476 for lnum,line in enumerate(source.strip().splitlines()):
478 477 newline(_ip.IP.prefilter(line,lnum>0))
479 478 newline('') # ensure a closing newline, needed by doctest
480 479 #print "PYSRC:", '\n'.join(out) # dbg
481 480 return '\n'.join(out)
482 481
483 482 def parse(self, string, name='<string>'):
484 483 """
485 484 Divide the given string into examples and intervening text,
486 485 and return them as a list of alternating Examples and strings.
487 486 Line numbers for the Examples are 0-based. The optional
488 487 argument `name` is a name identifying this string, and is only
489 488 used for error messages.
490 489 """
491 490
492 491 #print 'Parse string:\n',string # dbg
493 492
494 493 string = string.expandtabs()
495 494 # If all lines begin with the same indentation, then strip it.
496 495 min_indent = self._min_indent(string)
497 496 if min_indent > 0:
498 497 string = '\n'.join([l[min_indent:] for l in string.split('\n')])
499 498
500 499 output = []
501 500 charno, lineno = 0, 0
502 501
503 502 # We make 'all random' tests by adding the '# random' mark to every
504 503 # block of output in the test.
505 504 if self._RANDOM_TEST.search(string):
506 505 random_marker = '\n# random'
507 506 else:
508 507 random_marker = ''
509 508
510 509 # Whether to convert the input from ipython to python syntax
511 510 ip2py = False
512 511 # Find all doctest examples in the string. First, try them as Python
513 512 # examples, then as IPython ones
514 513 terms = list(self._EXAMPLE_RE_PY.finditer(string))
515 514 if terms:
516 515 # Normal Python example
517 516 #print '-'*70 # dbg
518 517 #print 'PyExample, Source:\n',string # dbg
519 518 #print '-'*70 # dbg
520 519 Example = doctest.Example
521 520 else:
522 521 # It's an ipython example. Note that IPExamples are run
523 522 # in-process, so their syntax must be turned into valid python.
524 523 # IPExternalExamples are run out-of-process (via pexpect) so they
525 524 # don't need any filtering (a real ipython will be executing them).
526 525 terms = list(self._EXAMPLE_RE_IP.finditer(string))
527 526 if self._EXTERNAL_IP.search(string):
528 527 #print '-'*70 # dbg
529 528 #print 'IPExternalExample, Source:\n',string # dbg
530 529 #print '-'*70 # dbg
531 530 Example = IPExternalExample
532 531 else:
533 532 #print '-'*70 # dbg
534 533 #print 'IPExample, Source:\n',string # dbg
535 534 #print '-'*70 # dbg
536 535 Example = IPExample
537 536 ip2py = True
538 537
539 538 for m in terms:
540 539 # Add the pre-example text to `output`.
541 540 output.append(string[charno:m.start()])
542 541 # Update lineno (lines before this example)
543 542 lineno += string.count('\n', charno, m.start())
544 543 # Extract info from the regexp match.
545 544 (source, options, want, exc_msg) = \
546 545 self._parse_example(m, name, lineno,ip2py)
547 546
548 547 # Append the random-output marker (it defaults to empty in most
549 548 # cases, it's only non-empty for 'all-random' tests):
550 549 want += random_marker
551 550
552 551 if Example is IPExternalExample:
553 552 options[doctest.NORMALIZE_WHITESPACE] = True
554 553 want += '\n'
555 554
556 555 # Create an Example, and add it to the list.
557 556 if not self._IS_BLANK_OR_COMMENT(source):
558 557 output.append(Example(source, want, exc_msg,
559 558 lineno=lineno,
560 559 indent=min_indent+len(m.group('indent')),
561 560 options=options))
562 561 # Update lineno (lines inside this example)
563 562 lineno += string.count('\n', m.start(), m.end())
564 563 # Update charno.
565 564 charno = m.end()
566 565 # Add any remaining post-example text to `output`.
567 566 output.append(string[charno:])
568 567 return output
569 568
570 569 def _parse_example(self, m, name, lineno,ip2py=False):
571 570 """
572 571 Given a regular expression match from `_EXAMPLE_RE` (`m`),
573 572 return a pair `(source, want)`, where `source` is the matched
574 573 example's source code (with prompts and indentation stripped);
575 574 and `want` is the example's expected output (with indentation
576 575 stripped).
577 576
578 577 `name` is the string's name, and `lineno` is the line number
579 578 where the example starts; both are used for error messages.
580 579
581 580 Optional:
582 581 `ip2py`: if true, filter the input via IPython to convert the syntax
583 582 into valid python.
584 583 """
585 584
586 585 # Get the example's indentation level.
587 586 indent = len(m.group('indent'))
588 587
589 588 # Divide source into lines; check that they're properly
590 589 # indented; and then strip their indentation & prompts.
591 590 source_lines = m.group('source').split('\n')
592 591
593 592 # We're using variable-length input prompts
594 593 ps1 = m.group('ps1')
595 594 ps2 = m.group('ps2')
596 595 ps1_len = len(ps1)
597 596
598 597 self._check_prompt_blank(source_lines, indent, name, lineno,ps1_len)
599 598 if ps2:
600 599 self._check_prefix(source_lines[1:], ' '*indent + ps2, name, lineno)
601 600
602 601 source = '\n'.join([sl[indent+ps1_len+1:] for sl in source_lines])
603 602
604 603 if ip2py:
605 604 # Convert source input from IPython into valid Python syntax
606 605 source = self.ip2py(source)
607 606
608 607 # Divide want into lines; check that it's properly indented; and
609 608 # then strip the indentation. Spaces before the last newline should
610 609 # be preserved, so plain rstrip() isn't good enough.
611 610 want = m.group('want')
612 611 want_lines = want.split('\n')
613 612 if len(want_lines) > 1 and re.match(r' *$', want_lines[-1]):
614 613 del want_lines[-1] # forget final newline & spaces after it
615 614 self._check_prefix(want_lines, ' '*indent, name,
616 615 lineno + len(source_lines))
617 616
618 617 # Remove ipython output prompt that might be present in the first line
619 618 want_lines[0] = re.sub(r'Out\[\d+\]: \s*?\n?','',want_lines[0])
620 619
621 620 want = '\n'.join([wl[indent:] for wl in want_lines])
622 621
623 622 # If `want` contains a traceback message, then extract it.
624 623 m = self._EXCEPTION_RE.match(want)
625 624 if m:
626 625 exc_msg = m.group('msg')
627 626 else:
628 627 exc_msg = None
629 628
630 629 # Extract options from the source.
631 630 options = self._find_options(source, name, lineno)
632 631
633 632 return source, options, want, exc_msg
634 633
635 634 def _check_prompt_blank(self, lines, indent, name, lineno, ps1_len):
636 635 """
637 636 Given the lines of a source string (including prompts and
638 637 leading indentation), check to make sure that every prompt is
639 638 followed by a space character. If any line is not followed by
640 639 a space character, then raise ValueError.
641 640
642 641 Note: IPython-modified version which takes the input prompt length as a
643 642 parameter, so that prompts of variable length can be dealt with.
644 643 """
645 644 space_idx = indent+ps1_len
646 645 min_len = space_idx+1
647 646 for i, line in enumerate(lines):
648 647 if len(line) >= min_len and line[space_idx] != ' ':
649 648 raise ValueError('line %r of the docstring for %s '
650 649 'lacks blank after %s: %r' %
651 650 (lineno+i+1, name,
652 651 line[indent:space_idx], line))
653 652
654 653
655 654 SKIP = doctest.register_optionflag('SKIP')
656 655
657 656
658 657 class IPDocTestRunner(doctest.DocTestRunner,object):
659 658 """Test runner that synchronizes the IPython namespace with test globals.
660 659 """
661 660
662 661 def run(self, test, compileflags=None, out=None, clear_globs=True):
663 662
664 663 # Hack: ipython needs access to the execution context of the example,
665 664 # so that it can propagate user variables loaded by %run into
666 665 # test.globs. We put them here into our modified %run as a function
667 666 # attribute. Our new %run will then only make the namespace update
668 667 # when called (rather than unconconditionally updating test.globs here
669 668 # for all examples, most of which won't be calling %run anyway).
670 669 _run_ns_sync.test_globs = test.globs
671 670 _run_ns_sync.test_filename = test.filename
672 671
673 672 return super(IPDocTestRunner,self).run(test,
674 673 compileflags,out,clear_globs)
675 674
676 675
677 676 class DocFileCase(doctest.DocFileCase):
678 677 """Overrides to provide filename
679 678 """
680 679 def address(self):
681 680 return (self._dt_test.filename, None, None)
682 681
683 682
684 683 class ExtensionDoctest(doctests.Doctest):
685 684 """Nose Plugin that supports doctests in extension modules.
686 685 """
687 686 name = 'extdoctest' # call nosetests with --with-extdoctest
688 687 enabled = True
689 688
690 689 def __init__(self,exclude_patterns=None):
691 690 """Create a new ExtensionDoctest plugin.
692 691
693 692 Parameters
694 693 ----------
695 694
696 695 exclude_patterns : sequence of strings, optional
697 696 These patterns are compiled as regular expressions, subsequently used
698 697 to exclude any filename which matches them from inclusion in the test
699 698 suite (using pattern.search(), NOT pattern.match() ).
700 699 """
701 700
702 701 if exclude_patterns is None:
703 702 exclude_patterns = []
704 703 self.exclude_patterns = map(re.compile,exclude_patterns)
705 704 doctests.Doctest.__init__(self)
706 705
707 706 def options(self, parser, env=os.environ):
708 707 Plugin.options(self, parser, env)
709 708 parser.add_option('--doctest-tests', action='store_true',
710 709 dest='doctest_tests',
711 710 default=env.get('NOSE_DOCTEST_TESTS',True),
712 711 help="Also look for doctests in test modules. "
713 712 "Note that classes, methods and functions should "
714 713 "have either doctests or non-doctest tests, "
715 714 "not both. [NOSE_DOCTEST_TESTS]")
716 715 parser.add_option('--doctest-extension', action="append",
717 716 dest="doctestExtension",
718 717 help="Also look for doctests in files with "
719 718 "this extension [NOSE_DOCTEST_EXTENSION]")
720 719 # Set the default as a list, if given in env; otherwise
721 720 # an additional value set on the command line will cause
722 721 # an error.
723 722 env_setting = env.get('NOSE_DOCTEST_EXTENSION')
724 723 if env_setting is not None:
725 724 parser.set_defaults(doctestExtension=tolist(env_setting))
726 725
727 726
728 727 def configure(self, options, config):
729 728 Plugin.configure(self, options, config)
730 729 self.doctest_tests = options.doctest_tests
731 730 self.extension = tolist(options.doctestExtension)
732 731
733 732 self.parser = doctest.DocTestParser()
734 733 self.finder = DocTestFinder()
735 734 self.checker = IPDoctestOutputChecker()
736 735 self.globs = None
737 736 self.extraglobs = None
738 737
739 738
740 739 def loadTestsFromExtensionModule(self,filename):
741 740 bpath,mod = os.path.split(filename)
742 741 modname = os.path.splitext(mod)[0]
743 742 try:
744 743 sys.path.append(bpath)
745 744 module = __import__(modname)
746 745 tests = list(self.loadTestsFromModule(module))
747 746 finally:
748 747 sys.path.pop()
749 748 return tests
750 749
751 750 # NOTE: the method below is almost a copy of the original one in nose, with
752 751 # a few modifications to control output checking.
753 752
754 753 def loadTestsFromModule(self, module):
755 754 #print '*** ipdoctest - lTM',module # dbg
756 755
757 756 if not self.matches(module.__name__):
758 757 log.debug("Doctest doesn't want module %s", module)
759 758 return
760 759
761 760 tests = self.finder.find(module,globs=self.globs,
762 761 extraglobs=self.extraglobs)
763 762 if not tests:
764 763 return
765 764
766 765 # always use whitespace and ellipsis options
767 766 optionflags = doctest.NORMALIZE_WHITESPACE | doctest.ELLIPSIS
768 767
769 768 tests.sort()
770 769 module_file = module.__file__
771 770 if module_file[-4:] in ('.pyc', '.pyo'):
772 771 module_file = module_file[:-1]
773 772 for test in tests:
774 773 if not test.examples:
775 774 continue
776 775 if not test.filename:
777 776 test.filename = module_file
778 777
779 778 yield DocTestCase(test,
780 779 optionflags=optionflags,
781 780 checker=self.checker)
782 781
783 782
784 783 def loadTestsFromFile(self, filename):
785 784 if is_extension_module(filename):
786 785 for t in self.loadTestsFromExtensionModule(filename):
787 786 yield t
788 787 else:
789 788 if self.extension and anyp(filename.endswith, self.extension):
790 789 name = os.path.basename(filename)
791 790 dh = open(filename)
792 791 try:
793 792 doc = dh.read()
794 793 finally:
795 794 dh.close()
796 795 test = self.parser.get_doctest(
797 796 doc, globs={'__file__': filename}, name=name,
798 797 filename=filename, lineno=0)
799 798 if test.examples:
800 799 #print 'FileCase:',test.examples # dbg
801 800 yield DocFileCase(test)
802 801 else:
803 802 yield False # no tests to load
804 803
805 804 def wantFile(self,filename):
806 805 """Return whether the given filename should be scanned for tests.
807 806
808 807 Modified version that accepts extension modules as valid containers for
809 808 doctests.
810 809 """
811 810 #print '*** ipdoctest- wantFile:',filename # dbg
812 811
813 812 for pat in self.exclude_patterns:
814 813 if pat.search(filename):
815 814 #print '###>>> SKIP:',filename # dbg
816 815 return False
817 816
818 817 if is_extension_module(filename):
819 818 return True
820 819 else:
821 820 return doctests.Doctest.wantFile(self,filename)
822 821
823 822
824 823 class IPythonDoctest(ExtensionDoctest):
825 824 """Nose Plugin that supports doctests in extension modules.
826 825 """
827 826 name = 'ipdoctest' # call nosetests with --with-ipdoctest
828 827 enabled = True
829 828
830 829 def makeTest(self, obj, parent):
831 830 """Look for doctests in the given object, which will be a
832 831 function, method or class.
833 832 """
834 833 # always use whitespace and ellipsis options
835 834 optionflags = doctest.NORMALIZE_WHITESPACE | doctest.ELLIPSIS
836 835
837 836 doctests = self.finder.find(obj, module=getmodule(parent))
838 837 if doctests:
839 838 for test in doctests:
840 839 if len(test.examples) == 0:
841 840 continue
842 841
843 842 yield DocTestCase(test, obj=obj,
844 843 optionflags=optionflags,
845 844 checker=self.checker)
846 845
847 846 def options(self, parser, env=os.environ):
848 847 Plugin.options(self, parser, env)
849 848 parser.add_option('--ipdoctest-tests', action='store_true',
850 849 dest='ipdoctest_tests',
851 850 default=env.get('NOSE_IPDOCTEST_TESTS',True),
852 851 help="Also look for doctests in test modules. "
853 852 "Note that classes, methods and functions should "
854 853 "have either doctests or non-doctest tests, "
855 854 "not both. [NOSE_IPDOCTEST_TESTS]")
856 855 parser.add_option('--ipdoctest-extension', action="append",
857 dest="ipdoctestExtension",
856 dest="ipdoctest_extension",
858 857 help="Also look for doctests in files with "
859 858 "this extension [NOSE_IPDOCTEST_EXTENSION]")
860 859 # Set the default as a list, if given in env; otherwise
861 860 # an additional value set on the command line will cause
862 861 # an error.
863 862 env_setting = env.get('NOSE_IPDOCTEST_EXTENSION')
864 863 if env_setting is not None:
865 parser.set_defaults(ipdoctestExtension=tolist(env_setting))
864 parser.set_defaults(ipdoctest_extension=tolist(env_setting))
866 865
867 866 def configure(self, options, config):
868 867 Plugin.configure(self, options, config)
869 868 self.doctest_tests = options.ipdoctest_tests
870 self.extension = tolist(options.ipdoctestExtension)
869 self.extension = tolist(options.ipdoctest_extension)
871 870
872 871 self.parser = IPDocTestParser()
873 872 self.finder = DocTestFinder(parser=self.parser)
874 873 self.checker = IPDoctestOutputChecker()
875 874 self.globs = None
876 875 self.extraglobs = None
877
General Comments 0
You need to be logged in to leave comments. Login now