##// END OF EJS Templates
First failed attempt to get the test suite to run.
Brian Granger -
Show More
@@ -1,7 +1,5 b''
1 1 #!/usr/bin/env python
2 2 # encoding: utf-8
3 3
4 def test_import_userconfig():
5 from IPython.config import userconfig
6 4
7 5
@@ -1,65 +1,62 b''
1 1 #!/usr/bin/env python
2 2 # encoding: utf-8
3 3
4 4 def test_import_completer():
5 5 from IPython.core import completer
6 6
7 7 def test_import_crashhandler():
8 8 from IPython.core import crashhandler
9 9
10 10 def test_import_debugger():
11 11 from IPython.core import debugger
12 12
13 13 def test_import_fakemodule():
14 14 from IPython.core import fakemodule
15 15
16 16 def test_import_excolors():
17 17 from IPython.core import excolors
18 18
19 19 def test_import_history():
20 20 from IPython.core import history
21 21
22 22 def test_import_hooks():
23 23 from IPython.core import hooks
24 24
25 25 def test_import_ipapi():
26 26 from IPython.core import ipapi
27 27
28 28 def test_import_iplib():
29 29 from IPython.core import iplib
30 30
31 31 def test_import_logger():
32 32 from IPython.core import logger
33 33
34 34 def test_import_macro():
35 35 from IPython.core import macro
36 36
37 37 def test_import_magic():
38 38 from IPython.core import magic
39 39
40 40 def test_import_oinspect():
41 41 from IPython.core import oinspect
42 42
43 43 def test_import_outputtrap():
44 44 from IPython.core import outputtrap
45 45
46 46 def test_import_prefilter():
47 47 from IPython.core import prefilter
48 48
49 49 def test_import_prompts():
50 50 from IPython.core import prompts
51 51
52 52 def test_import_release():
53 53 from IPython.core import release
54 54
55 55 def test_import_shadowns():
56 56 from IPython.core import shadowns
57 57
58 def test_import_shell():
59 from IPython.core import shell
60
61 58 def test_import_ultratb():
62 59 from IPython.core import ultratb
63 60
64 61 def test_import_usage():
65 62 from IPython.core import usage
@@ -1,441 +1,441 b''
1 1 #!/usr/bin/env python
2 2 """Module for interactively running scripts.
3 3
4 4 This module implements classes for interactively running scripts written for
5 5 any system with a prompt which can be matched by a regexp suitable for
6 6 pexpect. It can be used to run as if they had been typed up interactively, an
7 7 arbitrary series of commands for the target system.
8 8
9 9 The module includes classes ready for IPython (with the default prompts),
10 10 plain Python and SAGE, but making a new one is trivial. To see how to use it,
11 11 simply run the module as a script:
12 12
13 13 ./irunner.py --help
14 14
15 15
16 16 This is an extension of Ken Schutte <kschutte-AT-csail.mit.edu>'s script
17 17 contributed on the ipython-user list:
18 18
19 19 http://scipy.net/pipermail/ipython-user/2006-May/001705.html
20 20
21 21
22 22 NOTES:
23 23
24 24 - This module requires pexpect, available in most linux distros, or which can
25 25 be downloaded from
26 26
27 27 http://pexpect.sourceforge.net
28 28
29 29 - Because pexpect only works under Unix or Windows-Cygwin, this has the same
30 30 limitations. This means that it will NOT work under native windows Python.
31 31 """
32 32
33 33 # Stdlib imports
34 34 import optparse
35 35 import os
36 36 import sys
37 37
38 38 # Third-party modules.
39 39 import pexpect
40 40
41 41 # Global usage strings, to avoid indentation issues when typing it below.
42 42 USAGE = """
43 43 Interactive script runner, type: %s
44 44
45 45 runner [opts] script_name
46 46 """
47 47
48 48 def pexpect_monkeypatch():
49 49 """Patch pexpect to prevent unhandled exceptions at VM teardown.
50 50
51 51 Calling this function will monkeypatch the pexpect.spawn class and modify
52 52 its __del__ method to make it more robust in the face of failures that can
53 53 occur if it is called when the Python VM is shutting down.
54 54
55 55 Since Python may fire __del__ methods arbitrarily late, it's possible for
56 56 them to execute during the teardown of the Python VM itself. At this
57 57 point, various builtin modules have been reset to None. Thus, the call to
58 58 self.close() will trigger an exception because it tries to call os.close(),
59 59 and os is now None.
60 60 """
61 61
62 62 if pexpect.__version__[:3] >= '2.2':
63 63 # No need to patch, fix is already the upstream version.
64 64 return
65 65
66 66 def __del__(self):
67 67 """This makes sure that no system resources are left open.
68 68 Python only garbage collects Python objects. OS file descriptors
69 69 are not Python objects, so they must be handled explicitly.
70 70 If the child file descriptor was opened outside of this class
71 71 (passed to the constructor) then this does not close it.
72 72 """
73 73 if not self.closed:
74 74 try:
75 75 self.close()
76 76 except AttributeError:
77 77 pass
78 78
79 79 pexpect.spawn.__del__ = __del__
80 80
81 81 pexpect_monkeypatch()
82 82
83 83 # The generic runner class
84 84 class InteractiveRunner(object):
85 85 """Class to run a sequence of commands through an interactive program."""
86 86
87 87 def __init__(self,program,prompts,args=None,out=sys.stdout,echo=True):
88 88 """Construct a runner.
89 89
90 90 Inputs:
91 91
92 92 - program: command to execute the given program.
93 93
94 94 - prompts: a list of patterns to match as valid prompts, in the
95 95 format used by pexpect. This basically means that it can be either
96 96 a string (to be compiled as a regular expression) or a list of such
97 97 (it must be a true list, as pexpect does type checks).
98 98
99 99 If more than one prompt is given, the first is treated as the main
100 100 program prompt and the others as 'continuation' prompts, like
101 101 python's. This means that blank lines in the input source are
102 102 ommitted when the first prompt is matched, but are NOT ommitted when
103 103 the continuation one matches, since this is how python signals the
104 104 end of multiline input interactively.
105 105
106 106 Optional inputs:
107 107
108 108 - args(None): optional list of strings to pass as arguments to the
109 109 child program.
110 110
111 111 - out(sys.stdout): if given, an output stream to be used when writing
112 112 output. The only requirement is that it must have a .write() method.
113 113
114 114 Public members not parameterized in the constructor:
115 115
116 116 - delaybeforesend(0): Newer versions of pexpect have a delay before
117 117 sending each new input. For our purposes here, it's typically best
118 118 to just set this to zero, but if you encounter reliability problems
119 119 or want an interactive run to pause briefly at each prompt, just
120 120 increase this value (it is measured in seconds). Note that this
121 121 variable is not honored at all by older versions of pexpect.
122 122 """
123 123
124 124 self.program = program
125 125 self.prompts = prompts
126 126 if args is None: args = []
127 127 self.args = args
128 128 self.out = out
129 129 self.echo = echo
130 130 # Other public members which we don't make as parameters, but which
131 131 # users may occasionally want to tweak
132 132 self.delaybeforesend = 0
133 133
134 134 # Create child process and hold on to it so we don't have to re-create
135 135 # for every single execution call
136 136 c = self.child = pexpect.spawn(self.program,self.args,timeout=None)
137 137 c.delaybeforesend = self.delaybeforesend
138 138 # pexpect hard-codes the terminal size as (24,80) (rows,columns).
139 139 # This causes problems because any line longer than 80 characters gets
140 140 # completely overwrapped on the printed outptut (even though
141 141 # internally the code runs fine). We reset this to 99 rows X 200
142 142 # columns (arbitrarily chosen), which should avoid problems in all
143 143 # reasonable cases.
144 144 c.setwinsize(99,200)
145 145
146 146 def close(self):
147 147 """close child process"""
148 148
149 149 self.child.close()
150 150
151 151 def run_file(self,fname,interact=False,get_output=False):
152 152 """Run the given file interactively.
153 153
154 154 Inputs:
155 155
156 156 -fname: name of the file to execute.
157 157
158 158 See the run_source docstring for the meaning of the optional
159 159 arguments."""
160 160
161 161 fobj = open(fname,'r')
162 162 try:
163 163 out = self.run_source(fobj,interact,get_output)
164 164 finally:
165 165 fobj.close()
166 166 if get_output:
167 167 return out
168 168
169 169 def run_source(self,source,interact=False,get_output=False):
170 170 """Run the given source code interactively.
171 171
172 172 Inputs:
173 173
174 174 - source: a string of code to be executed, or an open file object we
175 175 can iterate over.
176 176
177 177 Optional inputs:
178 178
179 179 - interact(False): if true, start to interact with the running
180 180 program at the end of the script. Otherwise, just exit.
181 181
182 182 - get_output(False): if true, capture the output of the child process
183 183 (filtering the input commands out) and return it as a string.
184 184
185 185 Returns:
186 186 A string containing the process output, but only if requested.
187 187 """
188 188
189 189 # if the source is a string, chop it up in lines so we can iterate
190 190 # over it just as if it were an open file.
191 191 if not isinstance(source,file):
192 192 source = source.splitlines(True)
193 193
194 194 if self.echo:
195 195 # normalize all strings we write to use the native OS line
196 196 # separators.
197 197 linesep = os.linesep
198 198 stdwrite = self.out.write
199 199 write = lambda s: stdwrite(s.replace('\r\n',linesep))
200 200 else:
201 201 # Quiet mode, all writes are no-ops
202 202 write = lambda s: None
203 203
204 204 c = self.child
205 205 prompts = c.compile_pattern_list(self.prompts)
206 206 prompt_idx = c.expect_list(prompts)
207 207
208 208 # Flag whether the script ends normally or not, to know whether we can
209 209 # do anything further with the underlying process.
210 210 end_normal = True
211 211
212 212 # If the output was requested, store it in a list for return at the end
213 213 if get_output:
214 214 output = []
215 215 store_output = output.append
216 216
217 217 for cmd in source:
218 218 # skip blank lines for all matches to the 'main' prompt, while the
219 219 # secondary prompts do not
220 220 if prompt_idx==0 and \
221 221 (cmd.isspace() or cmd.lstrip().startswith('#')):
222 222 write(cmd)
223 223 continue
224 224
225 #write('AFTER: '+c.after) # dbg
225 # write('AFTER: '+c.after) # dbg
226 226 write(c.after)
227 227 c.send(cmd)
228 228 try:
229 229 prompt_idx = c.expect_list(prompts)
230 230 except pexpect.EOF:
231 231 # this will happen if the child dies unexpectedly
232 232 write(c.before)
233 233 end_normal = False
234 234 break
235 235
236 236 write(c.before)
237 237
238 238 # With an echoing process, the output we get in c.before contains
239 239 # the command sent, a newline, and then the actual process output
240 240 if get_output:
241 241 store_output(c.before[len(cmd+'\n'):])
242 242 #write('CMD: <<%s>>' % cmd) # dbg
243 243 #write('OUTPUT: <<%s>>' % output[-1]) # dbg
244 244
245 245 self.out.flush()
246 246 if end_normal:
247 247 if interact:
248 248 c.send('\n')
249 249 print '<< Starting interactive mode >>',
250 250 try:
251 251 c.interact()
252 252 except OSError:
253 253 # This is what fires when the child stops. Simply print a
254 254 # newline so the system prompt is aligned. The extra
255 255 # space is there to make sure it gets printed, otherwise
256 256 # OS buffering sometimes just suppresses it.
257 257 write(' \n')
258 258 self.out.flush()
259 259 else:
260 260 if interact:
261 261 e="Further interaction is not possible: child process is dead."
262 262 print >> sys.stderr, e
263 263
264 264 # Leave the child ready for more input later on, otherwise select just
265 265 # hangs on the second invocation.
266 266 c.send('\n')
267 267
268 268 # Return any requested output
269 269 if get_output:
270 270 return ''.join(output)
271 271
272 272 def main(self,argv=None):
273 273 """Run as a command-line script."""
274 274
275 275 parser = optparse.OptionParser(usage=USAGE % self.__class__.__name__)
276 276 newopt = parser.add_option
277 277 newopt('-i','--interact',action='store_true',default=False,
278 278 help='Interact with the program after the script is run.')
279 279
280 280 opts,args = parser.parse_args(argv)
281 281
282 282 if len(args) != 1:
283 283 print >> sys.stderr,"You must supply exactly one file to run."
284 284 sys.exit(1)
285 285
286 286 self.run_file(args[0],opts.interact)
287 287
288 288
289 289 # Specific runners for particular programs
290 290 class IPythonRunner(InteractiveRunner):
291 291 """Interactive IPython runner.
292 292
293 293 This initalizes IPython in 'nocolor' mode for simplicity. This lets us
294 294 avoid having to write a regexp that matches ANSI sequences, though pexpect
295 295 does support them. If anyone contributes patches for ANSI color support,
296 296 they will be welcome.
297 297
298 298 It also sets the prompts manually, since the prompt regexps for
299 299 pexpect need to be matched to the actual prompts, so user-customized
300 300 prompts would break this.
301 301 """
302 302
303 303 def __init__(self,program = 'ipython',args=None,out=sys.stdout,echo=True):
304 304 """New runner, optionally passing the ipython command to use."""
305 305
306 306 args0 = ['-colors','NoColor',
307 307 '-pi1','In [\\#]: ',
308 308 '-pi2',' .\\D.: ',
309 309 '-noterm_title',
310 310 '-noautoindent']
311 311 if args is None: args = args0
312 312 else: args = args0 + args
313 313 prompts = [r'In \[\d+\]: ',r' \.*: ']
314 314 InteractiveRunner.__init__(self,program,prompts,args,out,echo)
315 315
316 316
317 317 class PythonRunner(InteractiveRunner):
318 318 """Interactive Python runner."""
319 319
320 320 def __init__(self,program='python',args=None,out=sys.stdout,echo=True):
321 321 """New runner, optionally passing the python command to use."""
322 322
323 323 prompts = [r'>>> ',r'\.\.\. ']
324 324 InteractiveRunner.__init__(self,program,prompts,args,out,echo)
325 325
326 326
327 327 class SAGERunner(InteractiveRunner):
328 328 """Interactive SAGE runner.
329 329
330 330 WARNING: this runner only works if you manually configure your SAGE copy
331 331 to use 'colors NoColor' in the ipythonrc config file, since currently the
332 332 prompt matching regexp does not identify color sequences."""
333 333
334 334 def __init__(self,program='sage',args=None,out=sys.stdout,echo=True):
335 335 """New runner, optionally passing the sage command to use."""
336 336
337 337 prompts = ['sage: ',r'\s*\.\.\. ']
338 338 InteractiveRunner.__init__(self,program,prompts,args,out,echo)
339 339
340 340
341 341 class RunnerFactory(object):
342 342 """Code runner factory.
343 343
344 344 This class provides an IPython code runner, but enforces that only one
345 345 runner is ever instantiated. The runner is created based on the extension
346 346 of the first file to run, and it raises an exception if a runner is later
347 347 requested for a different extension type.
348 348
349 349 This ensures that we don't generate example files for doctest with a mix of
350 350 python and ipython syntax.
351 351 """
352 352
353 353 def __init__(self,out=sys.stdout):
354 354 """Instantiate a code runner."""
355 355
356 356 self.out = out
357 357 self.runner = None
358 358 self.runnerClass = None
359 359
360 360 def _makeRunner(self,runnerClass):
361 361 self.runnerClass = runnerClass
362 362 self.runner = runnerClass(out=self.out)
363 363 return self.runner
364 364
365 365 def __call__(self,fname):
366 366 """Return a runner for the given filename."""
367 367
368 368 if fname.endswith('.py'):
369 369 runnerClass = PythonRunner
370 370 elif fname.endswith('.ipy'):
371 371 runnerClass = IPythonRunner
372 372 else:
373 373 raise ValueError('Unknown file type for Runner: %r' % fname)
374 374
375 375 if self.runner is None:
376 376 return self._makeRunner(runnerClass)
377 377 else:
378 378 if runnerClass==self.runnerClass:
379 379 return self.runner
380 380 else:
381 381 e='A runner of type %r can not run file %r' % \
382 382 (self.runnerClass,fname)
383 383 raise ValueError(e)
384 384
385 385
386 386 # Global usage string, to avoid indentation issues if typed in a function def.
387 387 MAIN_USAGE = """
388 388 %prog [options] file_to_run
389 389
390 390 This is an interface to the various interactive runners available in this
391 391 module. If you want to pass specific options to one of the runners, you need
392 392 to first terminate the main options with a '--', and then provide the runner's
393 393 options. For example:
394 394
395 395 irunner.py --python -- --help
396 396
397 397 will pass --help to the python runner. Similarly,
398 398
399 399 irunner.py --ipython -- --interact script.ipy
400 400
401 401 will run the script.ipy file under the IPython runner, and then will start to
402 402 interact with IPython at the end of the script (instead of exiting).
403 403
404 404 The already implemented runners are listed below; adding one for a new program
405 405 is a trivial task, see the source for examples.
406 406
407 407 WARNING: the SAGE runner only works if you manually configure your SAGE copy
408 408 to use 'colors NoColor' in the ipythonrc config file, since currently the
409 409 prompt matching regexp does not identify color sequences.
410 410 """
411 411
412 412 def main():
413 413 """Run as a command-line script."""
414 414
415 415 parser = optparse.OptionParser(usage=MAIN_USAGE)
416 416 newopt = parser.add_option
417 417 parser.set_defaults(mode='ipython')
418 418 newopt('--ipython',action='store_const',dest='mode',const='ipython',
419 419 help='IPython interactive runner (default).')
420 420 newopt('--python',action='store_const',dest='mode',const='python',
421 421 help='Python interactive runner.')
422 422 newopt('--sage',action='store_const',dest='mode',const='sage',
423 423 help='SAGE interactive runner.')
424 424
425 425 opts,args = parser.parse_args()
426 426 runners = dict(ipython=IPythonRunner,
427 427 python=PythonRunner,
428 428 sage=SAGERunner)
429 429
430 430 try:
431 431 ext = os.path.splitext(args[0])[-1]
432 432 except IndexError:
433 433 ext = ''
434 434 modes = {'.ipy':'ipython',
435 435 '.py':'python',
436 436 '.sage':'sage'}
437 437 mode = modes.get(ext,opts.mode)
438 438 runners[mode]().main(args)
439 439
440 440 if __name__ == '__main__':
441 441 main()
@@ -1,334 +1,324 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 tempfile
28 28 import time
29 29 import warnings
30 30
31 31 import nose.plugins.builtin
32 32 from nose.core import TestProgram
33 33
34 34 from IPython.utils.platutils import find_cmd
35 from IPython.testing.plugin.ipdoctest import IPythonDoctest
35 # from IPython.testing.plugin.ipdoctest import IPythonDoctest
36 36
37 37 pjoin = path.join
38 38
39 39 #-----------------------------------------------------------------------------
40 40 # Logic for skipping doctests
41 41 #-----------------------------------------------------------------------------
42 42
43 43 def test_for(mod):
44 44 """Test to see if mod is importable."""
45 45 try:
46 46 __import__(mod)
47 47 except ImportError:
48 48 return False
49 49 else:
50 50 return True
51 51
52 52 have_curses = test_for('_curses')
53 53 have_wx = test_for('wx')
54 54 have_wx_aui = test_for('wx.aui')
55 55 have_zi = test_for('zope.interface')
56 56 have_twisted = test_for('twisted')
57 57 have_foolscap = test_for('foolscap')
58 58 have_objc = test_for('objc')
59 59 have_pexpect = test_for('pexpect')
60 60 have_gtk = test_for('gtk')
61 61 have_gobject = test_for('gobject')
62 62
63 63
64 64 def make_exclude():
65 65
66 66 # For the IPythonDoctest plugin, we need to exclude certain patterns that cause
67 67 # testing problems. We should strive to minimize the number of skipped
68 68 # modules, since this means untested code. As the testing machinery
69 69 # solidifies, this list should eventually become empty.
70 70 EXCLUDE = [pjoin('IPython', 'external'),
71 71 pjoin('IPython', 'frontend', 'process', 'winprocess.py'),
72 72 pjoin('IPython_doctest_plugin'),
73 pjoin('IPython', 'extensions', 'ipy_'),
74 pjoin('IPython', 'extensions', 'PhysicalQInput'),
75 pjoin('IPython', 'extensions', 'PhysicalQInteractive'),
76 pjoin('IPython', 'extensions', 'InterpreterPasteInput'),
77 pjoin('IPython', 'extensions', 'scitedirector'),
78 pjoin('IPython', 'extensions', 'numeric_formats'),
73 pjoin('IPython', 'quarantine'),
74 pjoin('IPython', 'deathrow'),
79 75 pjoin('IPython', 'testing', 'attic'),
80 76 pjoin('IPython', 'testing', 'tools'),
81 77 pjoin('IPython', 'testing', 'mkdoctests'),
82 78 pjoin('IPython', 'lib', 'inputhook')
83 79 ]
84 80
85 81 if not have_wx:
86 EXCLUDE.append(pjoin('IPython', 'extensions', 'igrid'))
87 82 EXCLUDE.append(pjoin('IPython', 'gui'))
88 83 EXCLUDE.append(pjoin('IPython', 'frontend', 'wx'))
89 84 EXCLUDE.append(pjoin('IPython', 'lib', 'inputhookwx'))
90 85
91 86 if not have_gtk or not have_gobject:
92 87 EXCLUDE.append(pjoin('IPython', 'lib', 'inputhookgtk'))
93 88
94 89 if not have_wx_aui:
95 90 EXCLUDE.append(pjoin('IPython', 'gui', 'wx', 'wxIPython'))
96 91
97 92 if not have_objc:
98 93 EXCLUDE.append(pjoin('IPython', 'frontend', 'cocoa'))
99 94
100 if not have_curses:
101 EXCLUDE.append(pjoin('IPython', 'extensions', 'ibrowse'))
102
103 95 if not sys.platform == 'win32':
104 96 EXCLUDE.append(pjoin('IPython', 'utils', 'platutils_win32'))
105 97
106 98 # These have to be skipped on win32 because the use echo, rm, cd, etc.
107 99 # See ticket https://bugs.launchpad.net/bugs/366982
108 100 if sys.platform == 'win32':
109 101 EXCLUDE.append(pjoin('IPython', 'testing', 'plugin', 'test_exampleip'))
110 102 EXCLUDE.append(pjoin('IPython', 'testing', 'plugin', 'dtexample'))
111 103
112 104 if not os.name == 'posix':
113 105 EXCLUDE.append(pjoin('IPython', 'utils', 'platutils_posix'))
114 106
115 107 if not have_pexpect:
116 108 EXCLUDE.append(pjoin('IPython', 'scripts', 'irunner'))
117 109
118 110 # This is scary. We still have things in frontend and testing that
119 111 # are being tested by nose that use twisted. We need to rethink
120 112 # how we are isolating dependencies in testing.
121 113 if not (have_twisted and have_zi and have_foolscap):
122 114 EXCLUDE.append(pjoin('IPython', 'frontend', 'asyncfrontendbase'))
123 115 EXCLUDE.append(pjoin('IPython', 'frontend', 'prefilterfrontend'))
124 116 EXCLUDE.append(pjoin('IPython', 'frontend', 'frontendbase'))
125 117 EXCLUDE.append(pjoin('IPython', 'frontend', 'linefrontendbase'))
126 118 EXCLUDE.append(pjoin('IPython', 'frontend', 'tests',
127 119 'test_linefrontend'))
128 120 EXCLUDE.append(pjoin('IPython', 'frontend', 'tests',
129 121 'test_frontendbase'))
130 122 EXCLUDE.append(pjoin('IPython', 'frontend', 'tests',
131 123 'test_prefilterfrontend'))
132 124 EXCLUDE.append(pjoin('IPython', 'frontend', 'tests',
133 125 'test_asyncfrontendbase')),
134 126 EXCLUDE.append(pjoin('IPython', 'testing', 'parametric'))
135 127 EXCLUDE.append(pjoin('IPython', 'testing', 'util'))
136 128 EXCLUDE.append(pjoin('IPython', 'testing', 'tests',
137 129 'test_decorators_trial'))
138 130
139 # Skip shell always because of a bug in FakeModule.
140 EXCLUDE.append(pjoin('IPython', 'core', 'shell'))
141
142 131 # This is needed for the reg-exp to match on win32 in the ipdoctest plugin.
143 132 if sys.platform == 'win32':
144 133 EXCLUDE = [s.replace('\\','\\\\') for s in EXCLUDE]
145 134
146 135 return EXCLUDE
147 136
148 137
149 138 #-----------------------------------------------------------------------------
150 139 # Functions and classes
151 140 #-----------------------------------------------------------------------------
152 141
153 142 def run_iptest():
154 143 """Run the IPython test suite using nose.
155 144
156 145 This function is called when this script is **not** called with the form
157 146 `iptest all`. It simply calls nose with appropriate command line flags
158 147 and accepts all of the standard nose arguments.
159 148 """
160 149
161 150 warnings.filterwarnings('ignore',
162 151 'This will be removed soon. Use IPython.testing.util instead')
163 152
164 153 argv = sys.argv + [
165 154 # Loading ipdoctest causes problems with Twisted.
166 155 # I am removing this as a temporary fix to get the
167 156 # test suite back into working shape. Our nose
168 157 # plugin needs to be gone through with a fine
169 158 # toothed comb to find what is causing the problem.
170 '--with-ipdoctest',
171 '--ipdoctest-tests','--ipdoctest-extension=txt',
172 '--detailed-errors',
159 # '--with-ipdoctest',
160 # '--ipdoctest-tests','--ipdoctest-extension=txt',
161 # '--detailed-errors',
173 162
174 163 # We add --exe because of setuptools' imbecility (it
175 164 # blindly does chmod +x on ALL files). Nose does the
176 165 # right thing and it tries to avoid executables,
177 166 # setuptools unfortunately forces our hand here. This
178 167 # has been discussed on the distutils list and the
179 168 # setuptools devs refuse to fix this problem!
180 169 '--exe',
181 170 ]
182 171
183 172 # Detect if any tests were required by explicitly calling an IPython
184 173 # submodule or giving a specific path
185 174 has_tests = False
186 175 for arg in sys.argv:
187 176 if 'IPython' in arg or arg.endswith('.py') or \
188 177 (':' in arg and '.py' in arg):
189 178 has_tests = True
190 179 break
191 180
192 181 # If nothing was specifically requested, test full IPython
193 182 if not has_tests:
194 183 argv.append('IPython')
195 184
196 185 # Construct list of plugins, omitting the existing doctest plugin, which
197 186 # ours replaces (and extends).
198 187 EXCLUDE = make_exclude()
199 plugins = [IPythonDoctest(EXCLUDE)]
188 plugins = []
189 # plugins = [IPythonDoctest(EXCLUDE)]
200 190 for p in nose.plugins.builtin.plugins:
201 191 plug = p()
202 192 if plug.name == 'doctest':
203 193 continue
204 194 plugins.append(plug)
205 195
206 196 TestProgram(argv=argv,plugins=plugins)
207 197
208 198
209 199 class IPTester(object):
210 200 """Call that calls iptest or trial in a subprocess.
211 201 """
212 202 def __init__(self,runner='iptest',params=None):
213 203 """ """
214 204 if runner == 'iptest':
215 205 self.runner = ['iptest','-v']
216 206 else:
217 207 self.runner = [find_cmd('trial')]
218 208 if params is None:
219 209 params = []
220 210 if isinstance(params,str):
221 211 params = [params]
222 212 self.params = params
223 213
224 214 # Assemble call
225 215 self.call_args = self.runner+self.params
226 216
227 217 if sys.platform == 'win32':
228 218 def run(self):
229 219 """Run the stored commands"""
230 220 # On Windows, cd to temporary directory to run tests. Otherwise,
231 221 # Twisted's trial may not be able to execute 'trial IPython', since
232 222 # it will confuse the IPython module name with the ipython
233 223 # execution scripts, because the windows file system isn't case
234 224 # sensitive.
235 225 # We also use os.system instead of subprocess.call, because I was
236 226 # having problems with subprocess and I just don't know enough
237 227 # about win32 to debug this reliably. Os.system may be the 'old
238 228 # fashioned' way to do it, but it works just fine. If someone
239 229 # later can clean this up that's fine, as long as the tests run
240 230 # reliably in win32.
241 231 curdir = os.getcwd()
242 232 os.chdir(tempfile.gettempdir())
243 233 stat = os.system(' '.join(self.call_args))
244 234 os.chdir(curdir)
245 235 return stat
246 236 else:
247 237 def run(self):
248 238 """Run the stored commands"""
249 239 return subprocess.call(self.call_args)
250 240
251 241
252 242 def make_runners():
253 243 """Define the top-level packages that need to be tested.
254 244 """
255 245
256 246 nose_packages = ['config', 'core', 'extensions',
257 'frontend', 'lib', 'quarantine',
247 'frontend', 'lib',
258 248 'scripts', 'testing', 'utils']
259 249 trial_packages = ['kernel']
260 250
261 251 if have_wx:
262 252 nose_packages.append('gui')
263 253
264 254 nose_packages = ['IPython.%s' % m for m in nose_packages ]
265 255 trial_packages = ['IPython.%s' % m for m in trial_packages ]
266 256
267 257 # Make runners
268 258 runners = dict()
269 259
270 260 nose_runners = dict(zip(nose_packages, [IPTester(params=v) for v in nose_packages]))
271 261 if have_zi and have_twisted and have_foolscap:
272 262 trial_runners = dict(zip(trial_packages, [IPTester('trial',params=v) for v in trial_packages]))
273 263 runners.update(nose_runners)
274 264 runners.update(trial_runners)
275 265
276 266 return runners
277 267
278 268
279 269 def run_iptestall():
280 270 """Run the entire IPython test suite by calling nose and trial.
281 271
282 272 This function constructs :class:`IPTester` instances for all IPython
283 273 modules and package and then runs each of them. This causes the modules
284 274 and packages of IPython to be tested each in their own subprocess using
285 275 nose or twisted.trial appropriately.
286 276 """
287 277
288 278 runners = make_runners()
289 279
290 280 # Run all test runners, tracking execution time
291 281 failed = {}
292 282 t_start = time.time()
293 283 for name,runner in runners.iteritems():
294 284 print '*'*77
295 285 print 'IPython test group:',name
296 286 res = runner.run()
297 287 if res:
298 288 failed[name] = res
299 289 t_end = time.time()
300 290 t_tests = t_end - t_start
301 291 nrunners = len(runners)
302 292 nfail = len(failed)
303 293 # summarize results
304 294 print
305 295 print '*'*77
306 296 print 'Ran %s test groups in %.3fs' % (nrunners, t_tests)
307 297 print
308 298 if not failed:
309 299 print 'OK'
310 300 else:
311 301 # If anything went wrong, point out what command to rerun manually to
312 302 # see the actual errors and individual summary
313 303 print 'ERROR - %s out of %s test groups failed.' % (nfail, nrunners)
314 304 for name in failed:
315 305 failed_runner = runners[name]
316 306 print '-'*40
317 307 print 'Runner failed:',name
318 308 print 'You may wish to rerun this one individually, with:'
319 309 print ' '.join(failed_runner.call_args)
320 310 print
321 311
322 312
323 313 def main():
324 314 if len(sys.argv) == 1:
325 315 run_iptestall()
326 316 else:
327 317 if sys.argv[1] == 'all':
328 318 run_iptestall()
329 319 else:
330 320 run_iptest()
331 321
332 322
333 323 if __name__ == '__main__':
334 324 main()
General Comments 0
You need to be logged in to leave comments. Login now