##// END OF EJS Templates
irunner.py => lib/irunner.py and imports updated.
Brian Granger -
Show More
1 NO CONTENT: file renamed from IPython/irunner.py to IPython/lib/irunner.py
@@ -1,11 +1,14 b''
1 1 #!/usr/bin/env python
2 2 # encoding: utf-8
3 3
4 4 def test_import_backgroundjobs():
5 5 from IPython.lib import backgroundjobs
6 6
7 7 def test_import_deepreload():
8 8 from IPython.lib import deepreload
9 9
10 10 def test_import_demo():
11 from IPython.lib import demo No newline at end of file
11 from IPython.lib import demo
12
13 def test_import_irunner():
14 from IPython.lib import demo
@@ -1,800 +1,800 b''
1 1 #!/usr/bin/env python
2 2 """IPython-enhanced doctest module with unittest integration.
3 3
4 4 This module is heavily based on the standard library's doctest module, but
5 5 enhances it with IPython support. This enables docstrings to contain
6 6 unmodified IPython input and output pasted from real IPython sessions.
7 7
8 8 It should be possible to use this module as a drop-in replacement for doctest
9 9 whenever you wish to use IPython input.
10 10
11 11 Since the module absorbs all normal doctest functionality, you can use a mix of
12 12 both plain Python and IPython examples in any given module, though not in the
13 13 same docstring.
14 14
15 15 See a simple example at the bottom of this code which serves as self-test and
16 16 demonstration code. Simply run this file (use -v for details) to run the
17 17 tests.
18 18
19 19 This module also contains routines to ease the integration of doctests with
20 20 regular unittest-based testing. In particular, see the DocTestLoader class and
21 21 the makeTestSuite utility function.
22 22
23 23
24 24 Limitations:
25 25
26 26 - When generating examples for use as doctests, make sure that you have
27 27 pretty-printing OFF. This can be done either by starting ipython with the
28 28 flag '--nopprint', by setting pprint to 0 in your ipythonrc file, or by
29 29 interactively disabling it with %Pprint. This is required so that IPython
30 30 output matches that of normal Python, which is used by doctest for internal
31 31 execution.
32 32
33 33 - Do not rely on specific prompt numbers for results (such as using
34 34 '_34==True', for example). For IPython tests run via an external process
35 35 the prompt numbers may be different, and IPython tests run as normal python
36 36 code won't even have these special _NN variables set at all.
37 37
38 38 - IPython functions that produce output as a side-effect of calling a system
39 39 process (e.g. 'ls') can be doc-tested, but they must be handled in an
40 40 external IPython process. Such doctests must be tagged with:
41 41
42 42 # ipdoctest: EXTERNAL
43 43
44 44 so that the testing machinery handles them differently. Since these are run
45 45 via pexpect in an external process, they can't deal with exceptions or other
46 46 fancy featurs of regular doctests. You must limit such tests to simple
47 47 matching of the output. For this reason, I recommend you limit these kinds
48 48 of doctests to features that truly require a separate process, and use the
49 49 normal IPython ones (which have all the features of normal doctests) for
50 50 everything else. See the examples at the bottom of this file for a
51 51 comparison of what can be done with both types.
52 52 """
53 53
54 54 # Standard library imports
55 55 import __builtin__
56 56 import doctest
57 57 import inspect
58 58 import os
59 59 import re
60 60 import sys
61 61 import unittest
62 62
63 63 from doctest import *
64 64
65 65 from IPython.tools import utils
66 66 from IPython.core import ipapi
67 67
68 68 ###########################################################################
69 69 #
70 70 # We must start our own ipython object and heavily muck with it so that all the
71 71 # modifications IPython makes to system behavior don't send the doctest
72 72 # machinery into a fit. This code should be considered a gross hack, but it
73 73 # gets the job done.
74 74
75 75 import IPython
76 76
77 77 # Hack to restore __main__, which ipython modifies upon startup
78 78 _main = sys.modules.get('__main__')
79 79 ipython = IPython.Shell.IPShell(['--classic','--noterm_title']).IP
80 80 sys.modules['__main__'] = _main
81 81
82 82 # Deactivate the various python system hooks added by ipython for
83 83 # interactive convenience so we don't confuse the doctest system
84 84 sys.displayhook = sys.__displayhook__
85 85 sys.excepthook = sys.__excepthook__
86 86
87 87 # So that ipython magics and aliases can be doctested
88 88 __builtin__._ip = ipapi.get()
89 89
90 90 # for debugging only!!!
91 91 #from IPython.Shell import IPShellEmbed;ipshell=IPShellEmbed(['--noterm_title']) # dbg
92 92
93 93
94 94 # runner
95 from IPython.irunner import IPythonRunner
95 from IPython.lib.irunner import IPythonRunner
96 96 iprunner = IPythonRunner(echo=False)
97 97
98 98 ###########################################################################
99 99
100 100 # A simple subclassing of the original with a different class name, so we can
101 101 # distinguish and treat differently IPython examples from pure python ones.
102 102 class IPExample(doctest.Example): pass
103 103
104 104 class IPExternalExample(doctest.Example):
105 105 """Doctest examples to be run in an external process."""
106 106
107 107 def __init__(self, source, want, exc_msg=None, lineno=0, indent=0,
108 108 options=None):
109 109 # Parent constructor
110 110 doctest.Example.__init__(self,source,want,exc_msg,lineno,indent,options)
111 111
112 112 # An EXTRA newline is needed to prevent pexpect hangs
113 113 self.source += '\n'
114 114
115 115 class IPDocTestParser(doctest.DocTestParser):
116 116 """
117 117 A class used to parse strings containing doctest examples.
118 118
119 119 Note: This is a version modified to properly recognize IPython input and
120 120 convert any IPython examples into valid Python ones.
121 121 """
122 122 # This regular expression is used to find doctest examples in a
123 123 # string. It defines three groups: `source` is the source code
124 124 # (including leading indentation and prompts); `indent` is the
125 125 # indentation of the first (PS1) line of the source code; and
126 126 # `want` is the expected output (including leading indentation).
127 127
128 128 # Classic Python prompts or default IPython ones
129 129 _PS1_PY = r'>>>'
130 130 _PS2_PY = r'\.\.\.'
131 131
132 132 _PS1_IP = r'In\ \[\d+\]:'
133 133 _PS2_IP = r'\ \ \ \.\.\.+:'
134 134
135 135 _RE_TPL = r'''
136 136 # Source consists of a PS1 line followed by zero or more PS2 lines.
137 137 (?P<source>
138 138 (?:^(?P<indent> [ ]*) (?P<ps1> %s) .*) # PS1 line
139 139 (?:\n [ ]* (?P<ps2> %s) .*)*) # PS2 lines
140 140 \n? # a newline
141 141 # Want consists of any non-blank lines that do not start with PS1.
142 142 (?P<want> (?:(?![ ]*$) # Not a blank line
143 143 (?![ ]*%s) # Not a line starting with PS1
144 144 (?![ ]*%s) # Not a line starting with PS2
145 145 .*$\n? # But any other line
146 146 )*)
147 147 '''
148 148
149 149 _EXAMPLE_RE_PY = re.compile( _RE_TPL % (_PS1_PY,_PS2_PY,_PS1_PY,_PS2_PY),
150 150 re.MULTILINE | re.VERBOSE)
151 151
152 152 _EXAMPLE_RE_IP = re.compile( _RE_TPL % (_PS1_IP,_PS2_IP,_PS1_IP,_PS2_IP),
153 153 re.MULTILINE | re.VERBOSE)
154 154
155 155 def ip2py(self,source):
156 156 """Convert input IPython source into valid Python."""
157 157 out = []
158 158 newline = out.append
159 159 for line in source.splitlines():
160 160 newline(ipython.prefilter(line,True))
161 161 newline('') # ensure a closing newline, needed by doctest
162 162 return '\n'.join(out)
163 163
164 164 def parse(self, string, name='<string>'):
165 165 """
166 166 Divide the given string into examples and intervening text,
167 167 and return them as a list of alternating Examples and strings.
168 168 Line numbers for the Examples are 0-based. The optional
169 169 argument `name` is a name identifying this string, and is only
170 170 used for error messages.
171 171 """
172 172 string = string.expandtabs()
173 173 # If all lines begin with the same indentation, then strip it.
174 174 min_indent = self._min_indent(string)
175 175 if min_indent > 0:
176 176 string = '\n'.join([l[min_indent:] for l in string.split('\n')])
177 177
178 178 output = []
179 179 charno, lineno = 0, 0
180 180
181 181 # Whether to convert the input from ipython to python syntax
182 182 ip2py = False
183 183 # Find all doctest examples in the string. First, try them as Python
184 184 # examples, then as IPython ones
185 185 terms = list(self._EXAMPLE_RE_PY.finditer(string))
186 186 if terms:
187 187 # Normal Python example
188 188 Example = doctest.Example
189 189 else:
190 190 # It's an ipython example. Note that IPExamples are run
191 191 # in-process, so their syntax must be turned into valid python.
192 192 # IPExternalExamples are run out-of-process (via pexpect) so they
193 193 # don't need any filtering (a real ipython will be executing them).
194 194 terms = list(self._EXAMPLE_RE_IP.finditer(string))
195 195 if re.search(r'#\s*ipdoctest:\s*EXTERNAL',string):
196 196 #print '-'*70 # dbg
197 197 #print 'IPExternalExample, Source:\n',string # dbg
198 198 #print '-'*70 # dbg
199 199 Example = IPExternalExample
200 200 else:
201 201 #print '-'*70 # dbg
202 202 #print 'IPExample, Source:\n',string # dbg
203 203 #print '-'*70 # dbg
204 204 Example = IPExample
205 205 ip2py = True
206 206
207 207 for m in terms:
208 208 # Add the pre-example text to `output`.
209 209 output.append(string[charno:m.start()])
210 210 # Update lineno (lines before this example)
211 211 lineno += string.count('\n', charno, m.start())
212 212 # Extract info from the regexp match.
213 213 (source, options, want, exc_msg) = \
214 214 self._parse_example(m, name, lineno,ip2py)
215 215 if Example is IPExternalExample:
216 216 options[doctest.NORMALIZE_WHITESPACE] = True
217 217 # Create an Example, and add it to the list.
218 218 if not self._IS_BLANK_OR_COMMENT(source):
219 219 output.append(Example(source, want, exc_msg,
220 220 lineno=lineno,
221 221 indent=min_indent+len(m.group('indent')),
222 222 options=options))
223 223 # Update lineno (lines inside this example)
224 224 lineno += string.count('\n', m.start(), m.end())
225 225 # Update charno.
226 226 charno = m.end()
227 227 # Add any remaining post-example text to `output`.
228 228 output.append(string[charno:])
229 229
230 230 return output
231 231
232 232 def _parse_example(self, m, name, lineno,ip2py=False):
233 233 """
234 234 Given a regular expression match from `_EXAMPLE_RE` (`m`),
235 235 return a pair `(source, want)`, where `source` is the matched
236 236 example's source code (with prompts and indentation stripped);
237 237 and `want` is the example's expected output (with indentation
238 238 stripped).
239 239
240 240 `name` is the string's name, and `lineno` is the line number
241 241 where the example starts; both are used for error messages.
242 242
243 243 Optional:
244 244 `ip2py`: if true, filter the input via IPython to convert the syntax
245 245 into valid python.
246 246 """
247 247
248 248 # Get the example's indentation level.
249 249 indent = len(m.group('indent'))
250 250
251 251 # Divide source into lines; check that they're properly
252 252 # indented; and then strip their indentation & prompts.
253 253 source_lines = m.group('source').split('\n')
254 254
255 255 # We're using variable-length input prompts
256 256 ps1 = m.group('ps1')
257 257 ps2 = m.group('ps2')
258 258 ps1_len = len(ps1)
259 259
260 260 self._check_prompt_blank(source_lines, indent, name, lineno,ps1_len)
261 261 if ps2:
262 262 self._check_prefix(source_lines[1:], ' '*indent + ps2, name, lineno)
263 263
264 264 source = '\n'.join([sl[indent+ps1_len+1:] for sl in source_lines])
265 265
266 266 if ip2py:
267 267 # Convert source input from IPython into valid Python syntax
268 268 source = self.ip2py(source)
269 269
270 270 # Divide want into lines; check that it's properly indented; and
271 271 # then strip the indentation. Spaces before the last newline should
272 272 # be preserved, so plain rstrip() isn't good enough.
273 273 want = m.group('want')
274 274 want_lines = want.split('\n')
275 275 if len(want_lines) > 1 and re.match(r' *$', want_lines[-1]):
276 276 del want_lines[-1] # forget final newline & spaces after it
277 277 self._check_prefix(want_lines, ' '*indent, name,
278 278 lineno + len(source_lines))
279 279
280 280 # Remove ipython output prompt that might be present in the first line
281 281 want_lines[0] = re.sub(r'Out\[\d+\]: \s*?\n?','',want_lines[0])
282 282
283 283 want = '\n'.join([wl[indent:] for wl in want_lines])
284 284
285 285 # If `want` contains a traceback message, then extract it.
286 286 m = self._EXCEPTION_RE.match(want)
287 287 if m:
288 288 exc_msg = m.group('msg')
289 289 else:
290 290 exc_msg = None
291 291
292 292 # Extract options from the source.
293 293 options = self._find_options(source, name, lineno)
294 294
295 295 return source, options, want, exc_msg
296 296
297 297 def _check_prompt_blank(self, lines, indent, name, lineno, ps1_len):
298 298 """
299 299 Given the lines of a source string (including prompts and
300 300 leading indentation), check to make sure that every prompt is
301 301 followed by a space character. If any line is not followed by
302 302 a space character, then raise ValueError.
303 303
304 304 Note: IPython-modified version which takes the input prompt length as a
305 305 parameter, so that prompts of variable length can be dealt with.
306 306 """
307 307 space_idx = indent+ps1_len
308 308 min_len = space_idx+1
309 309 for i, line in enumerate(lines):
310 310 if len(line) >= min_len and line[space_idx] != ' ':
311 311 raise ValueError('line %r of the docstring for %s '
312 312 'lacks blank after %s: %r' %
313 313 (lineno+i+1, name,
314 314 line[indent:space_idx], line))
315 315
316 316
317 317 SKIP = register_optionflag('SKIP')
318 318
319 319 class IPDocTestRunner(doctest.DocTestRunner):
320 320 """Modified DocTestRunner which can also run IPython tests.
321 321
322 322 This runner is capable of handling IPython doctests that require
323 323 out-of-process output capture (such as system calls via !cmd or aliases).
324 324 Note however that because these tests are run in a separate process, many
325 325 of doctest's fancier capabilities (such as detailed exception analysis) are
326 326 not available. So try to limit such tests to simple cases of matching
327 327 actual output.
328 328 """
329 329
330 330 #/////////////////////////////////////////////////////////////////
331 331 # DocTest Running
332 332 #/////////////////////////////////////////////////////////////////
333 333
334 334 def _run_iptest(self, test, out):
335 335 """
336 336 Run the examples in `test`. Write the outcome of each example with one
337 337 of the `DocTestRunner.report_*` methods, using the writer function
338 338 `out`. Return a tuple `(f, t)`, where `t` is the number of examples
339 339 tried, and `f` is the number of examples that failed. The examples are
340 340 run in the namespace `test.globs`.
341 341
342 342 IPython note: this is a modified version of the original __run()
343 343 private method to handle out-of-process examples.
344 344 """
345 345
346 346 if out is None:
347 347 out = sys.stdout.write
348 348
349 349 # Keep track of the number of failures and tries.
350 350 failures = tries = 0
351 351
352 352 # Save the option flags (since option directives can be used
353 353 # to modify them).
354 354 original_optionflags = self.optionflags
355 355
356 356 SUCCESS, FAILURE, BOOM = range(3) # `outcome` state
357 357
358 358 check = self._checker.check_output
359 359
360 360 # Process each example.
361 361 for examplenum, example in enumerate(test.examples):
362 362
363 363 # If REPORT_ONLY_FIRST_FAILURE is set, then supress
364 364 # reporting after the first failure.
365 365 quiet = (self.optionflags & REPORT_ONLY_FIRST_FAILURE and
366 366 failures > 0)
367 367
368 368 # Merge in the example's options.
369 369 self.optionflags = original_optionflags
370 370 if example.options:
371 371 for (optionflag, val) in example.options.items():
372 372 if val:
373 373 self.optionflags |= optionflag
374 374 else:
375 375 self.optionflags &= ~optionflag
376 376
377 377 # If 'SKIP' is set, then skip this example.
378 378 if self.optionflags & SKIP:
379 379 continue
380 380
381 381 # Record that we started this example.
382 382 tries += 1
383 383 if not quiet:
384 384 self.report_start(out, test, example)
385 385
386 386 # Run the example in the given context (globs), and record
387 387 # any exception that gets raised. (But don't intercept
388 388 # keyboard interrupts.)
389 389 try:
390 390 # Don't blink! This is where the user's code gets run.
391 391 got = ''
392 392 # The code is run in an external process
393 393 got = iprunner.run_source(example.source,get_output=True)
394 394 except KeyboardInterrupt:
395 395 raise
396 396 except:
397 397 self.debugger.set_continue() # ==== Example Finished ====
398 398
399 399 outcome = FAILURE # guilty until proved innocent or insane
400 400
401 401 if check(example.want, got, self.optionflags):
402 402 outcome = SUCCESS
403 403
404 404 # Report the outcome.
405 405 if outcome is SUCCESS:
406 406 if not quiet:
407 407 self.report_success(out, test, example, got)
408 408 elif outcome is FAILURE:
409 409 if not quiet:
410 410 self.report_failure(out, test, example, got)
411 411 failures += 1
412 412 elif outcome is BOOM:
413 413 if not quiet:
414 414 self.report_unexpected_exception(out, test, example,
415 415 exc_info)
416 416 failures += 1
417 417 else:
418 418 assert False, ("unknown outcome", outcome)
419 419
420 420 # Restore the option flags (in case they were modified)
421 421 self.optionflags = original_optionflags
422 422
423 423 # Record and return the number of failures and tries.
424 424
425 425 # Hack to access a parent private method by working around Python's
426 426 # name mangling (which is fortunately simple).
427 427 doctest.DocTestRunner._DocTestRunner__record_outcome(self,test,
428 428 failures, tries)
429 429 return failures, tries
430 430
431 431 def run(self, test, compileflags=None, out=None, clear_globs=True):
432 432 """Run examples in `test`.
433 433
434 434 This method will defer to the parent for normal Python examples, but it
435 435 will run IPython ones via pexpect.
436 436 """
437 437 if not test.examples:
438 438 return
439 439
440 440 if isinstance(test.examples[0],IPExternalExample):
441 441 self._run_iptest(test,out)
442 442 else:
443 443 DocTestRunner.run(self,test,compileflags,out,clear_globs)
444 444
445 445
446 446 class IPDebugRunner(IPDocTestRunner,doctest.DebugRunner):
447 447 """IPython-modified DebugRunner, see the original class for details."""
448 448
449 449 def run(self, test, compileflags=None, out=None, clear_globs=True):
450 450 r = IPDocTestRunner.run(self, test, compileflags, out, False)
451 451 if clear_globs:
452 452 test.globs.clear()
453 453 return r
454 454
455 455
456 456 class IPDocTestLoader(unittest.TestLoader):
457 457 """A test loader with IPython-enhanced doctest support.
458 458
459 459 Instances of this loader will automatically add doctests found in a module
460 460 to the test suite returned by the loadTestsFromModule method. In
461 461 addition, at initialization time a string of doctests can be given to the
462 462 loader, enabling it to add doctests to a module which didn't have them in
463 463 its docstring, coming from an external source."""
464 464
465 465
466 466 def __init__(self,dt_files=None,dt_modules=None,test_finder=None):
467 467 """Initialize the test loader.
468 468
469 469 :Keywords:
470 470
471 471 dt_files : list (None)
472 472 List of names of files to be executed as doctests.
473 473
474 474 dt_modules : list (None)
475 475 List of module names to be scanned for doctests in their
476 476 docstrings.
477 477
478 478 test_finder : instance (None)
479 479 Instance of a testfinder (see doctest for details).
480 480 """
481 481
482 482 if dt_files is None: dt_files = []
483 483 if dt_modules is None: dt_modules = []
484 484 self.dt_files = utils.list_strings(dt_files)
485 485 self.dt_modules = utils.list_strings(dt_modules)
486 486 if test_finder is None:
487 487 test_finder = doctest.DocTestFinder(parser=IPDocTestParser())
488 488 self.test_finder = test_finder
489 489
490 490 def loadTestsFromModule(self, module):
491 491 """Return a suite of all tests cases contained in the given module.
492 492
493 493 If the loader was initialized with a doctests argument, then this
494 494 string is assigned as the module's docstring."""
495 495
496 496 # Start by loading any tests in the called module itself
497 497 suite = super(self.__class__,self).loadTestsFromModule(module)
498 498
499 499 # Now, load also tests referenced at construction time as companion
500 500 # doctests that reside in standalone files
501 501 for fname in self.dt_files:
502 502 #print 'mod:',module # dbg
503 503 #print 'fname:',fname # dbg
504 504 #suite.addTest(doctest.DocFileSuite(fname))
505 505 suite.addTest(doctest.DocFileSuite(fname,module_relative=False))
506 506 # Add docstring tests from module, if given at construction time
507 507 for mod in self.dt_modules:
508 508 suite.addTest(doctest.DocTestSuite(mod,
509 509 test_finder=self.test_finder))
510 510
511 511 #ipshell() # dbg
512 512 return suite
513 513
514 514 def my_import(name):
515 515 """Module importer - taken from the python documentation.
516 516
517 517 This function allows importing names with dots in them."""
518 518
519 519 mod = __import__(name)
520 520 components = name.split('.')
521 521 for comp in components[1:]:
522 522 mod = getattr(mod, comp)
523 523 return mod
524 524
525 525 def makeTestSuite(module_name,dt_files=None,dt_modules=None,idt=True):
526 526 """Make a TestSuite object for a given module, specified by name.
527 527
528 528 This extracts all the doctests associated with a module using a
529 529 DocTestLoader object.
530 530
531 531 :Parameters:
532 532
533 533 - module_name: a string containing the name of a module with unittests.
534 534
535 535 :Keywords:
536 536
537 537 dt_files : list of strings
538 538 List of names of plain text files to be treated as doctests.
539 539
540 540 dt_modules : list of strings
541 541 List of names of modules to be scanned for doctests in docstrings.
542 542
543 543 idt : bool (True)
544 544 If True, return integrated doctests. This means that each filename
545 545 listed in dt_files is turned into a *single* unittest, suitable for
546 546 running via unittest's runner or Twisted's Trial runner. If false, the
547 547 dt_files parameter is returned unmodified, so that other test runners
548 548 (such as oilrun) can run the doctests with finer granularity.
549 549 """
550 550
551 551 mod = my_import(module_name)
552 552 if idt:
553 553 suite = IPDocTestLoader(dt_files,dt_modules).loadTestsFromModule(mod)
554 554 else:
555 555 suite = IPDocTestLoader(None,dt_modules).loadTestsFromModule(mod)
556 556
557 557 if idt:
558 558 return suite
559 559 else:
560 560 return suite,dt_files
561 561
562 562 # Copied from doctest in py2.5 and modified for our purposes (since they don't
563 563 # parametrize what we need)
564 564
565 565 # For backward compatibility, a global instance of a DocTestRunner
566 566 # class, updated by testmod.
567 567 master = None
568 568
569 569 def testmod(m=None, name=None, globs=None, verbose=None,
570 570 report=True, optionflags=0, extraglobs=None,
571 571 raise_on_error=False, exclude_empty=False):
572 572 """m=None, name=None, globs=None, verbose=None, report=True,
573 573 optionflags=0, extraglobs=None, raise_on_error=False,
574 574 exclude_empty=False
575 575
576 576 Note: IPython-modified version which loads test finder and runners that
577 577 recognize IPython syntax in doctests.
578 578
579 579 Test examples in docstrings in functions and classes reachable
580 580 from module m (or the current module if m is not supplied), starting
581 581 with m.__doc__.
582 582
583 583 Also test examples reachable from dict m.__test__ if it exists and is
584 584 not None. m.__test__ maps names to functions, classes and strings;
585 585 function and class docstrings are tested even if the name is private;
586 586 strings are tested directly, as if they were docstrings.
587 587
588 588 Return (#failures, #tests).
589 589
590 590 See doctest.__doc__ for an overview.
591 591
592 592 Optional keyword arg "name" gives the name of the module; by default
593 593 use m.__name__.
594 594
595 595 Optional keyword arg "globs" gives a dict to be used as the globals
596 596 when executing examples; by default, use m.__dict__. A copy of this
597 597 dict is actually used for each docstring, so that each docstring's
598 598 examples start with a clean slate.
599 599
600 600 Optional keyword arg "extraglobs" gives a dictionary that should be
601 601 merged into the globals that are used to execute examples. By
602 602 default, no extra globals are used. This is new in 2.4.
603 603
604 604 Optional keyword arg "verbose" prints lots of stuff if true, prints
605 605 only failures if false; by default, it's true iff "-v" is in sys.argv.
606 606
607 607 Optional keyword arg "report" prints a summary at the end when true,
608 608 else prints nothing at the end. In verbose mode, the summary is
609 609 detailed, else very brief (in fact, empty if all tests passed).
610 610
611 611 Optional keyword arg "optionflags" or's together module constants,
612 612 and defaults to 0. This is new in 2.3. Possible values (see the
613 613 docs for details):
614 614
615 615 DONT_ACCEPT_TRUE_FOR_1
616 616 DONT_ACCEPT_BLANKLINE
617 617 NORMALIZE_WHITESPACE
618 618 ELLIPSIS
619 619 SKIP
620 620 IGNORE_EXCEPTION_DETAIL
621 621 REPORT_UDIFF
622 622 REPORT_CDIFF
623 623 REPORT_NDIFF
624 624 REPORT_ONLY_FIRST_FAILURE
625 625
626 626 Optional keyword arg "raise_on_error" raises an exception on the
627 627 first unexpected exception or failure. This allows failures to be
628 628 post-mortem debugged.
629 629
630 630 Advanced tomfoolery: testmod runs methods of a local instance of
631 631 class doctest.Tester, then merges the results into (or creates)
632 632 global Tester instance doctest.master. Methods of doctest.master
633 633 can be called directly too, if you want to do something unusual.
634 634 Passing report=0 to testmod is especially useful then, to delay
635 635 displaying a summary. Invoke doctest.master.summarize(verbose)
636 636 when you're done fiddling.
637 637 """
638 638 global master
639 639
640 640 # If no module was given, then use __main__.
641 641 if m is None:
642 642 # DWA - m will still be None if this wasn't invoked from the command
643 643 # line, in which case the following TypeError is about as good an error
644 644 # as we should expect
645 645 m = sys.modules.get('__main__')
646 646
647 647 # Check that we were actually given a module.
648 648 if not inspect.ismodule(m):
649 649 raise TypeError("testmod: module required; %r" % (m,))
650 650
651 651 # If no name was given, then use the module's name.
652 652 if name is None:
653 653 name = m.__name__
654 654
655 655 #----------------------------------------------------------------------
656 656 # fperez - make IPython finder and runner:
657 657 # Find, parse, and run all tests in the given module.
658 658 finder = DocTestFinder(exclude_empty=exclude_empty,
659 659 parser=IPDocTestParser())
660 660
661 661 if raise_on_error:
662 662 runner = IPDebugRunner(verbose=verbose, optionflags=optionflags)
663 663 else:
664 664 runner = IPDocTestRunner(verbose=verbose, optionflags=optionflags,
665 665 #checker=IPOutputChecker() # dbg
666 666 )
667 667
668 668 # /fperez - end of ipython changes
669 669 #----------------------------------------------------------------------
670 670
671 671 for test in finder.find(m, name, globs=globs, extraglobs=extraglobs):
672 672 runner.run(test)
673 673
674 674 if report:
675 675 runner.summarize()
676 676
677 677 if master is None:
678 678 master = runner
679 679 else:
680 680 master.merge(runner)
681 681
682 682 return runner.failures, runner.tries
683 683
684 684
685 685 # Simple testing and example code
686 686 if __name__ == "__main__":
687 687
688 688 def ipfunc():
689 689 """
690 690 Some ipython tests...
691 691
692 692 In [1]: import os
693 693
694 694 In [2]: cd /
695 695 /
696 696
697 697 In [3]: 2+3
698 698 Out[3]: 5
699 699
700 700 In [26]: for i in range(3):
701 701 ....: print i,
702 702 ....: print i+1,
703 703 ....:
704 704 0 1 1 2 2 3
705 705
706 706
707 707 Examples that access the operating system work:
708 708
709 709 In [19]: cd /tmp
710 710 /tmp
711 711
712 712 In [20]: mkdir foo_ipython
713 713
714 714 In [21]: cd foo_ipython
715 715 /tmp/foo_ipython
716 716
717 717 In [23]: !touch bar baz
718 718
719 719 # We unfortunately can't just call 'ls' because its output is not
720 720 # seen by doctest, since it happens in a separate process
721 721
722 722 In [24]: os.listdir('.')
723 723 Out[24]: ['bar', 'baz']
724 724
725 725 In [25]: cd /tmp
726 726 /tmp
727 727
728 728 In [26]: rm -rf foo_ipython
729 729
730 730
731 731 It's OK to use '_' for the last result, but do NOT try to use IPython's
732 732 numbered history of _NN outputs, since those won't exist under the
733 733 doctest environment:
734 734
735 735 In [7]: 3+4
736 736 Out[7]: 7
737 737
738 738 In [8]: _+3
739 739 Out[8]: 10
740 740 """
741 741
742 742 def ipfunc_external():
743 743 """
744 744 Tests that must be run in an external process
745 745
746 746
747 747 # ipdoctest: EXTERNAL
748 748
749 749 In [11]: for i in range(10):
750 750 ....: print i,
751 751 ....: print i+1,
752 752 ....:
753 753 0 1 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9 10
754 754
755 755
756 756 In [1]: import os
757 757
758 758 In [1]: print "hello"
759 759 hello
760 760
761 761 In [19]: cd /tmp
762 762 /tmp
763 763
764 764 In [20]: mkdir foo_ipython2
765 765
766 766 In [21]: cd foo_ipython2
767 767 /tmp/foo_ipython2
768 768
769 769 In [23]: !touch bar baz
770 770
771 771 In [24]: ls
772 772 bar baz
773 773
774 774 In [24]: !ls
775 775 bar baz
776 776
777 777 In [25]: cd /tmp
778 778 /tmp
779 779
780 780 In [26]: rm -rf foo_ipython2
781 781 """
782 782
783 783 def pyfunc():
784 784 """
785 785 Some pure python tests...
786 786
787 787 >>> import os
788 788
789 789 >>> 2+3
790 790 5
791 791
792 792 >>> for i in range(3):
793 793 ... print i,
794 794 ... print i+1,
795 795 ...
796 796 0 1 1 2 2 3
797 797 """
798 798
799 799 # Call the global testmod() just like you would with normal doctest
800 800 testmod()
@@ -1,300 +1,300 b''
1 1 # -*- coding: utf-8 -*-
2 2 """IPython Test Suite Runner.
3 3
4 4 This module provides a main entry point to a user script to test IPython
5 5 itself from the command line. There are two ways of running this script:
6 6
7 7 1. With the syntax `iptest all`. This runs our entire test suite by
8 8 calling this script (with different arguments) or trial recursively. This
9 9 causes modules and package to be tested in different processes, using nose
10 10 or trial where appropriate.
11 11 2. With the regular nose syntax, like `iptest -vvs IPython`. In this form
12 12 the script simply calls nose, but with special command line flags and
13 13 plugins loaded.
14 14
15 15 For now, this script requires that both nose and twisted are installed. This
16 16 will change in the future.
17 17 """
18 18
19 19 #-----------------------------------------------------------------------------
20 20 # Module imports
21 21 #-----------------------------------------------------------------------------
22 22
23 23 import os
24 24 import os.path as path
25 25 import sys
26 26 import subprocess
27 27 import time
28 28 import warnings
29 29
30 30 import nose.plugins.builtin
31 31 from nose.core import TestProgram
32 32
33 33 from IPython.platutils import find_cmd
34 34 from IPython.testing.plugin.ipdoctest import IPythonDoctest
35 35
36 36 pjoin = path.join
37 37
38 38 #-----------------------------------------------------------------------------
39 39 # Logic for skipping doctests
40 40 #-----------------------------------------------------------------------------
41 41
42 42 def test_for(mod):
43 43 """Test to see if mod is importable."""
44 44 try:
45 45 __import__(mod)
46 46 except ImportError:
47 47 return False
48 48 else:
49 49 return True
50 50
51 51 have_curses = test_for('_curses')
52 52 have_wx = test_for('wx')
53 53 have_zi = test_for('zope.interface')
54 54 have_twisted = test_for('twisted')
55 55 have_foolscap = test_for('foolscap')
56 56 have_objc = test_for('objc')
57 57 have_pexpect = test_for('pexpect')
58 58
59 59 # For the IPythonDoctest plugin, we need to exclude certain patterns that cause
60 60 # testing problems. We should strive to minimize the number of skipped
61 61 # modules, since this means untested code. As the testing machinery
62 62 # solidifies, this list should eventually become empty.
63 63 EXCLUDE = [pjoin('IPython', 'external'),
64 64 pjoin('IPython', 'frontend', 'process', 'winprocess.py'),
65 65 pjoin('IPython_doctest_plugin'),
66 66 pjoin('IPython', 'Gnuplot'),
67 67 pjoin('IPython', 'Extensions', 'ipy_'),
68 68 pjoin('IPython', 'Extensions', 'clearcmd'),
69 69 pjoin('IPython', 'Extensions', 'PhysicalQInteractive'),
70 70 pjoin('IPython', 'Extensions', 'scitedirector'),
71 71 pjoin('IPython', 'Extensions', 'numeric_formats'),
72 72 pjoin('IPython', 'testing', 'attic'),
73 73 pjoin('IPython', 'testing', 'tutils'),
74 74 pjoin('IPython', 'testing', 'tools'),
75 75 pjoin('IPython', 'testing', 'mkdoctests')
76 76 ]
77 77
78 78 if not have_wx:
79 79 EXCLUDE.append(pjoin('IPython', 'Extensions', 'igrid'))
80 80 EXCLUDE.append(pjoin('IPython', 'gui'))
81 81 EXCLUDE.append(pjoin('IPython', 'frontend', 'wx'))
82 82
83 83 if not have_objc:
84 84 EXCLUDE.append(pjoin('IPython', 'frontend', 'cocoa'))
85 85
86 86 if not have_curses:
87 87 EXCLUDE.append(pjoin('IPython', 'Extensions', 'ibrowse'))
88 88
89 89 if not sys.platform == 'win32':
90 90 EXCLUDE.append(pjoin('IPython', 'platutils_win32'))
91 91
92 92 # These have to be skipped on win32 because the use echo, rm, cd, etc.
93 93 # See ticket https://bugs.launchpad.net/bugs/366982
94 94 if sys.platform == 'win32':
95 95 EXCLUDE.append(pjoin('IPython', 'testing', 'plugin', 'test_exampleip'))
96 96 EXCLUDE.append(pjoin('IPython', 'testing', 'plugin', 'dtexample'))
97 97
98 98 if not os.name == 'posix':
99 99 EXCLUDE.append(pjoin('IPython', 'platutils_posix'))
100 100
101 101 if not have_pexpect:
102 EXCLUDE.append(pjoin('IPython', 'irunner'))
102 EXCLUDE.append(pjoin('IPython', 'lib', 'irunner'))
103 103
104 104 # This is needed for the reg-exp to match on win32 in the ipdoctest plugin.
105 105 if sys.platform == 'win32':
106 106 EXCLUDE = [s.replace('\\','\\\\') for s in EXCLUDE]
107 107
108 108
109 109 #-----------------------------------------------------------------------------
110 110 # Functions and classes
111 111 #-----------------------------------------------------------------------------
112 112
113 113 def run_iptest():
114 114 """Run the IPython test suite using nose.
115 115
116 116 This function is called when this script is **not** called with the form
117 117 `iptest all`. It simply calls nose with appropriate command line flags
118 118 and accepts all of the standard nose arguments.
119 119 """
120 120
121 121 warnings.filterwarnings('ignore',
122 122 'This will be removed soon. Use IPython.testing.util instead')
123 123
124 124 argv = sys.argv + [
125 125 # Loading ipdoctest causes problems with Twisted.
126 126 # I am removing this as a temporary fix to get the
127 127 # test suite back into working shape. Our nose
128 128 # plugin needs to be gone through with a fine
129 129 # toothed comb to find what is causing the problem.
130 130 '--with-ipdoctest',
131 131 '--ipdoctest-tests','--ipdoctest-extension=txt',
132 132 '--detailed-errors',
133 133
134 134 # We add --exe because of setuptools' imbecility (it
135 135 # blindly does chmod +x on ALL files). Nose does the
136 136 # right thing and it tries to avoid executables,
137 137 # setuptools unfortunately forces our hand here. This
138 138 # has been discussed on the distutils list and the
139 139 # setuptools devs refuse to fix this problem!
140 140 '--exe',
141 141 ]
142 142
143 143 # Detect if any tests were required by explicitly calling an IPython
144 144 # submodule or giving a specific path
145 145 has_tests = False
146 146 for arg in sys.argv:
147 147 if 'IPython' in arg or arg.endswith('.py') or \
148 148 (':' in arg and '.py' in arg):
149 149 has_tests = True
150 150 break
151 151
152 152 # If nothing was specifically requested, test full IPython
153 153 if not has_tests:
154 154 argv.append('IPython')
155 155
156 156 # Construct list of plugins, omitting the existing doctest plugin, which
157 157 # ours replaces (and extends).
158 158 plugins = [IPythonDoctest(EXCLUDE)]
159 159 for p in nose.plugins.builtin.plugins:
160 160 plug = p()
161 161 if plug.name == 'doctest':
162 162 continue
163 163
164 164 #print '*** adding plugin:',plug.name # dbg
165 165 plugins.append(plug)
166 166
167 167 TestProgram(argv=argv,plugins=plugins)
168 168
169 169
170 170 class IPTester(object):
171 171 """Call that calls iptest or trial in a subprocess.
172 172 """
173 173 def __init__(self,runner='iptest',params=None):
174 174 """ """
175 175 if runner == 'iptest':
176 176 self.runner = ['iptest','-v']
177 177 else:
178 178 self.runner = [find_cmd('trial')]
179 179 if params is None:
180 180 params = []
181 181 if isinstance(params,str):
182 182 params = [params]
183 183 self.params = params
184 184
185 185 # Assemble call
186 186 self.call_args = self.runner+self.params
187 187
188 188 def run(self):
189 189 """Run the stored commands"""
190 190 return subprocess.call(self.call_args)
191 191
192 192
193 193 def make_runners():
194 194 """Define the modules and packages that need to be tested.
195 195 """
196 196
197 197 # This omits additional top-level modules that should not be doctested.
198 198 # XXX: Shell.py is also ommited because of a bug in the skip_doctest
199 199 # decorator. See ticket https://bugs.launchpad.net/bugs/366209
200 200 top_mod = \
201 201 ['backgroundjobs.py', 'coloransi.py', 'completer.py', 'configloader.py',
202 202 'crashhandler.py', 'debugger.py', 'deepreload.py', 'demo.py',
203 203 'DPyGetOpt.py', 'dtutils.py', 'excolors.py', 'fakemodule.py',
204 204 'generics.py', 'genutils.py', 'history.py', 'hooks.py', 'ipapi.py',
205 205 'iplib.py', 'ipmaker.py', 'ipstruct.py', 'Itpl.py',
206 206 'logger.py', 'macro.py', 'Magic.py', 'OInspect.py',
207 207 'OutputTrap.py', 'platutils.py', 'prefilter.py', 'Prompts.py',
208 208 'PyColorize.py', 'Release.py', 'rlineimpl.py', 'shadowns.py',
209 209 'shellglobals.py', 'strdispatch.py', 'twshell.py',
210 210 'ultraTB.py', 'upgrade_dir.py', 'usage.py', 'wildcard.py',
211 211 # See note above for why this is skipped
212 212 # 'Shell.py',
213 213 'winconsole.py']
214 214
215 215 if have_pexpect:
216 216 top_mod.append('irunner.py')
217 217
218 218 if sys.platform == 'win32':
219 219 top_mod.append('platutils_win32.py')
220 220 elif os.name == 'posix':
221 221 top_mod.append('platutils_posix.py')
222 222 else:
223 223 top_mod.append('platutils_dummy.py')
224 224
225 225 # These are tested by nose, so skip IPython.kernel
226 226 top_pack = ['config','Extensions','frontend',
227 227 'testing','tests','tools','UserConfig']
228 228
229 229 if have_wx:
230 230 top_pack.append('gui')
231 231
232 232 modules = ['IPython.%s' % m[:-3] for m in top_mod ]
233 233 packages = ['IPython.%s' % m for m in top_pack ]
234 234
235 235 # Make runners
236 236 runners = dict(zip(top_pack, [IPTester(params=v) for v in packages]))
237 237
238 238 # Test IPython.kernel using trial if twisted is installed
239 239 if have_zi and have_twisted and have_foolscap:
240 240 runners['trial'] = IPTester('trial',['IPython'])
241 241
242 242 runners['modules'] = IPTester(params=modules)
243 243
244 244 return runners
245 245
246 246
247 247 def run_iptestall():
248 248 """Run the entire IPython test suite by calling nose and trial.
249 249
250 250 This function constructs :class:`IPTester` instances for all IPython
251 251 modules and package and then runs each of them. This causes the modules
252 252 and packages of IPython to be tested each in their own subprocess using
253 253 nose or twisted.trial appropriately.
254 254 """
255 255 runners = make_runners()
256 256 # Run all test runners, tracking execution time
257 257 failed = {}
258 258 t_start = time.time()
259 259 for name,runner in runners.iteritems():
260 260 print '*'*77
261 261 print 'IPython test set:',name
262 262 res = runner.run()
263 263 if res:
264 264 failed[name] = res
265 265 t_end = time.time()
266 266 t_tests = t_end - t_start
267 267 nrunners = len(runners)
268 268 nfail = len(failed)
269 269 # summarize results
270 270 print
271 271 print '*'*77
272 272 print 'Ran %s test sets in %.3fs' % (nrunners, t_tests)
273 273 print
274 274 if not failed:
275 275 print 'OK'
276 276 else:
277 277 # If anything went wrong, point out what command to rerun manually to
278 278 # see the actual errors and individual summary
279 279 print 'ERROR - %s out of %s test sets failed.' % (nfail, nrunners)
280 280 for name in failed:
281 281 failed_runner = runners[name]
282 282 print '-'*40
283 283 print 'Runner failed:',name
284 284 print 'You may wish to rerun this one individually, with:'
285 285 print ' '.join(failed_runner.call_args)
286 286 print
287 287
288 288
289 289 def main():
290 290 if len(sys.argv) == 1:
291 291 run_iptestall()
292 292 else:
293 293 if sys.argv[1] == 'all':
294 294 run_iptestall()
295 295 else:
296 296 run_iptest()
297 297
298 298
299 299 if __name__ == '__main__':
300 300 main() No newline at end of file
@@ -1,244 +1,244 b''
1 1 #!/usr/bin/env python
2 2 """Utility for making a doctest file out of Python or IPython input.
3 3
4 4 %prog [options] input_file [output_file]
5 5
6 6 This script is a convenient generator of doctest files that uses IPython's
7 7 irunner script to execute valid Python or IPython input in a separate process,
8 8 capture all of the output, and write it to an output file.
9 9
10 10 It can be used in one of two ways:
11 11
12 12 1. With a plain Python or IPython input file (denoted by extensions '.py' or
13 13 '.ipy'. In this case, the output is an auto-generated reST file with a
14 14 basic header, and the captured Python input and output contained in an
15 15 indented code block.
16 16
17 17 If no output filename is given, the input name is used, with the extension
18 18 replaced by '.txt'.
19 19
20 20 2. With an input template file. Template files are simply plain text files
21 21 with special directives of the form
22 22
23 23 %run filename
24 24
25 25 to include the named file at that point.
26 26
27 27 If no output filename is given and the input filename is of the form
28 28 'base.tpl.txt', the output will be automatically named 'base.txt'.
29 29 """
30 30
31 31 # Standard library imports
32 32
33 33 import optparse
34 34 import os
35 35 import re
36 36 import sys
37 37 import tempfile
38 38
39 39 # IPython-specific libraries
40 from IPython import irunner
40 from IPython.lib import irunner
41 41 from IPython.utils.genutils import fatal
42 42
43 43 class IndentOut(object):
44 44 """A simple output stream that indents all output by a fixed amount.
45 45
46 46 Instances of this class trap output to a given stream and first reformat it
47 47 to indent every input line."""
48 48
49 49 def __init__(self,out=sys.stdout,indent=4):
50 50 """Create an indented writer.
51 51
52 52 :Keywords:
53 53
54 54 - `out` : stream (sys.stdout)
55 55 Output stream to actually write to after indenting.
56 56
57 57 - `indent` : int
58 58 Number of spaces to indent every input line by.
59 59 """
60 60
61 61 self.indent_text = ' '*indent
62 62 self.indent = re.compile('^',re.MULTILINE).sub
63 63 self.out = out
64 64 self._write = out.write
65 65 self.buffer = []
66 66 self._closed = False
67 67
68 68 def write(self,data):
69 69 """Write a string to the output stream."""
70 70
71 71 if self._closed:
72 72 raise ValueError('I/O operation on closed file')
73 73 self.buffer.append(data)
74 74
75 75 def flush(self):
76 76 if self.buffer:
77 77 data = ''.join(self.buffer)
78 78 self.buffer[:] = []
79 79 self._write(self.indent(self.indent_text,data))
80 80
81 81 def close(self):
82 82 self.flush()
83 83 self._closed = True
84 84
85 85 class RunnerFactory(object):
86 86 """Code runner factory.
87 87
88 88 This class provides an IPython code runner, but enforces that only one
89 89 runner is every instantiated. The runner is created based on the extension
90 90 of the first file to run, and it raises an exception if a runner is later
91 91 requested for a different extension type.
92 92
93 93 This ensures that we don't generate example files for doctest with a mix of
94 94 python and ipython syntax.
95 95 """
96 96
97 97 def __init__(self,out=sys.stdout):
98 98 """Instantiate a code runner."""
99 99
100 100 self.out = out
101 101 self.runner = None
102 102 self.runnerClass = None
103 103
104 104 def _makeRunner(self,runnerClass):
105 105 self.runnerClass = runnerClass
106 106 self.runner = runnerClass(out=self.out)
107 107 return self.runner
108 108
109 109 def __call__(self,fname):
110 110 """Return a runner for the given filename."""
111 111
112 112 if fname.endswith('.py'):
113 113 runnerClass = irunner.PythonRunner
114 114 elif fname.endswith('.ipy'):
115 115 runnerClass = irunner.IPythonRunner
116 116 else:
117 117 raise ValueError('Unknown file type for Runner: %r' % fname)
118 118
119 119 if self.runner is None:
120 120 return self._makeRunner(runnerClass)
121 121 else:
122 122 if runnerClass==self.runnerClass:
123 123 return self.runner
124 124 else:
125 125 e='A runner of type %r can not run file %r' % \
126 126 (self.runnerClass,fname)
127 127 raise ValueError(e)
128 128
129 129 TPL = """
130 130 =========================
131 131 Auto-generated doctests
132 132 =========================
133 133
134 134 This file was auto-generated by IPython in its entirety. If you need finer
135 135 control over the contents, simply make a manual template. See the
136 136 mkdoctests.py script for details.
137 137
138 138 %%run %s
139 139 """
140 140
141 141 def main():
142 142 """Run as a script."""
143 143
144 144 # Parse options and arguments.
145 145 parser = optparse.OptionParser(usage=__doc__)
146 146 newopt = parser.add_option
147 147 newopt('-f','--force',action='store_true',dest='force',default=False,
148 148 help='Force overwriting of the output file.')
149 149 newopt('-s','--stdout',action='store_true',dest='stdout',default=False,
150 150 help='Use stdout instead of a file for output.')
151 151
152 152 opts,args = parser.parse_args()
153 153 if len(args) < 1:
154 154 parser.error("incorrect number of arguments")
155 155
156 156 # Input filename
157 157 fname = args[0]
158 158
159 159 # We auto-generate the output file based on a trivial template to make it
160 160 # really easy to create simple doctests.
161 161
162 162 auto_gen_output = False
163 163 try:
164 164 outfname = args[1]
165 165 except IndexError:
166 166 outfname = None
167 167
168 168 if fname.endswith('.tpl.txt') and outfname is None:
169 169 outfname = fname.replace('.tpl.txt','.txt')
170 170 else:
171 171 bname, ext = os.path.splitext(fname)
172 172 if ext in ['.py','.ipy']:
173 173 auto_gen_output = True
174 174 if outfname is None:
175 175 outfname = bname+'.txt'
176 176
177 177 # Open input file
178 178
179 179 # In auto-gen mode, we actually change the name of the input file to be our
180 180 # auto-generated template
181 181 if auto_gen_output:
182 182 infile = tempfile.TemporaryFile()
183 183 infile.write(TPL % fname)
184 184 infile.flush()
185 185 infile.seek(0)
186 186 else:
187 187 infile = open(fname)
188 188
189 189 # Now open the output file. If opts.stdout was given, this overrides any
190 190 # explicit choice of output filename and just directs all output to
191 191 # stdout.
192 192 if opts.stdout:
193 193 outfile = sys.stdout
194 194 else:
195 195 # Argument processing finished, start main code
196 196 if os.path.isfile(outfname) and not opts.force:
197 197 fatal("Output file %r exists, use --force (-f) to overwrite."
198 198 % outfname)
199 199 outfile = open(outfname,'w')
200 200
201 201
202 202 # all output from included files will be indented
203 203 indentOut = IndentOut(outfile,4)
204 204 getRunner = RunnerFactory(indentOut)
205 205
206 206 # Marker in reST for transition lines
207 207 rst_transition = '\n'+'-'*76+'\n\n'
208 208
209 209 # local shorthand for loop
210 210 write = outfile.write
211 211
212 212 # Process input, simply writing back out all normal lines and executing the
213 213 # files in lines marked as '%run filename'.
214 214 for line in infile:
215 215 if line.startswith('%run '):
216 216 # We don't support files with spaces in their names.
217 217 incfname = line.split()[1]
218 218
219 219 # We make the output of the included file appear bracketed between
220 220 # clear reST transition marks, and indent it so that if anyone
221 221 # makes an HTML or PDF out of the file, all doctest input and
222 222 # output appears in proper literal blocks.
223 223 write(rst_transition)
224 224 write('Begin included file %s::\n\n' % incfname)
225 225
226 226 # I deliberately do NOT trap any exceptions here, so that if
227 227 # there's any problem, the user running this at the command line
228 228 # finds out immediately by the code blowing up, rather than ending
229 229 # up silently with an incomplete or incorrect file.
230 230 getRunner(incfname).run_file(incfname)
231 231
232 232 write('\nEnd included file %s\n' % incfname)
233 233 write(rst_transition)
234 234 else:
235 235 # The rest of the input file is just written out
236 236 write(line)
237 237 infile.close()
238 238
239 239 # Don't close sys.stdout!!!
240 240 if outfile is not sys.stdout:
241 241 outfile.close()
242 242
243 243 if __name__ == '__main__':
244 244 main()
General Comments 0
You need to be logged in to leave comments. Login now