##// END OF EJS Templates
Replace links to launchpad bugs in comments/docstrings with equivalent github links.
Thomas Kluyver -
Show More
@@ -1,47 +1,47 b''
1 1 """Minimal script to reproduce our nasty reference counting bug.
2 2
3 The problem is related to https://bugs.launchpad.net/ipython/+bug/269966
3 The problem is related to https://github.com/ipython/ipython/issues/141
4 4
5 5 The original fix for that appeared to work, but John D. Hunter found a
6 6 matplotlib example which, when run twice in a row, would break. The problem
7 7 were references held by open figures to internals of Tkinter.
8 8
9 9 This code reproduces the problem that John saw, without matplotlib.
10 10
11 11 This script is meant to be called by other parts of the test suite that call it
12 via %run as if it were executed interactively by the user. As of 2009-04-13,
13 test_magic.py calls it.
12 via %run as if it were executed interactively by the user. As of 2011-05-29,
13 test_run.py calls it.
14 14 """
15 15
16 16 #-----------------------------------------------------------------------------
17 17 # Module imports
18 18 #-----------------------------------------------------------------------------
19 19 import sys
20 20
21 21 from IPython.core import ipapi
22 22
23 23 #-----------------------------------------------------------------------------
24 24 # Globals
25 25 #-----------------------------------------------------------------------------
26 26
27 27 # This needs to be here because nose and other test runners will import
28 28 # this module. Importing this module has potential side effects that we
29 29 # want to prevent.
30 30 if __name__ == '__main__':
31 31
32 32 ip = ipapi.get()
33 33
34 34 if not '_refbug_cache' in ip.user_ns:
35 35 ip.user_ns['_refbug_cache'] = []
36 36
37 37
38 38 aglobal = 'Hello'
39 39 def f():
40 40 return aglobal
41 41
42 42 cache = ip.user_ns['_refbug_cache']
43 43 cache.append(f)
44 44
45 45 def call_f():
46 46 for func in cache:
47 47 print 'lowercased:',func().lower()
@@ -1,68 +1,68 b''
1 1 """Tests for input manipulation machinery."""
2 2
3 3 #-----------------------------------------------------------------------------
4 4 # Imports
5 5 #-----------------------------------------------------------------------------
6 6 import nose.tools as nt
7 7
8 8 from IPython.testing import tools as tt, decorators as dec
9 9 from IPython.testing.globalipapp import get_ipython
10 10
11 11 #-----------------------------------------------------------------------------
12 12 # Tests
13 13 #-----------------------------------------------------------------------------
14 14 ip = get_ipython()
15 15
16 16 @dec.parametric
17 17 def test_prefilter():
18 18 """Test user input conversions"""
19 19
20 20 # pairs of (raw, expected correct) input
21 21 pairs = [ ('2+2','2+2'),
22 22 ('>>> 2+2','2+2'),
23 23 ('>>> # This is a comment\n'
24 24 '... 2+2',
25 25 '# This is a comment\n'
26 26 '2+2'),
27 27 # Some IPython input
28 28 ('In [1]: 1', '1'),
29 29 ('In [2]: for i in range(5):\n'
30 30 ' ...: print i,',
31 31 'for i in range(5):\n'
32 32 ' print i,'),
33 33 ]
34 34
35 35 for raw, correct in pairs:
36 36 yield nt.assert_equals(ip.prefilter(raw), correct)
37 37
38 38 @dec.parametric
39 39 def test_autocall_binops():
40 """See https://bugs.launchpad.net/ipython/+bug/315706"""
40 """See https://github.com/ipython/ipython/issues/81"""
41 41 ip.magic('autocall 2')
42 42 f = lambda x: x
43 43 ip.user_ns['f'] = f
44 44 try:
45 45 yield nt.assert_equals(ip.prefilter('f 1'),'f(1)')
46 46 for t in ['f +1', 'f -1']:
47 47 yield nt.assert_equals(ip.prefilter(t), t)
48 48 finally:
49 49 ip.magic('autocall 0')
50 50 del ip.user_ns['f']
51 51
52 52 @dec.parametric
53 53 def test_issue114():
54 54 """Check that multiline string literals don't expand as magic
55 55 see http://github.com/ipython/ipython/issues/#issue/114"""
56 56
57 57 template = '"""\n%s\n"""'
58 58 # Store the current value of multi_line_specials and turn it off before
59 59 # running test, since it could be true (case in which the test doesn't make
60 60 # sense, as multiline string literals *will* expand as magic in that case).
61 61 msp = ip.prefilter_manager.multi_line_specials
62 62 ip.prefilter_manager.multi_line_specials = False
63 63 try:
64 64 for mgk in ip.lsmagic():
65 65 raw = template % mgk
66 66 yield nt.assert_equals(ip.prefilter(raw), raw)
67 67 finally:
68 68 ip.prefilter_manager.multi_line_specials = msp
@@ -1,205 +1,203 b''
1 1 """Tests for code execution (%run and related), which is particularly tricky.
2 2
3 3 Because of how %run manages namespaces, and the fact that we are trying here to
4 4 verify subtle object deletion and reference counting issues, the %run tests
5 5 will be kept in this separate file. This makes it easier to aggregate in one
6 6 place the tricks needed to handle it; most other magics are much easier to test
7 7 and we do so in a common test_magic file.
8 8 """
9 9 from __future__ import absolute_import
10 10
11 11 #-----------------------------------------------------------------------------
12 12 # Imports
13 13 #-----------------------------------------------------------------------------
14 14
15 15 import os
16 16 import sys
17 17 import tempfile
18 18
19 19 import nose.tools as nt
20 20
21 21 from IPython.testing import decorators as dec
22 22 from IPython.testing import tools as tt
23 23
24 24 #-----------------------------------------------------------------------------
25 25 # Test functions begin
26 26 #-----------------------------------------------------------------------------
27 27
28 28 def doctest_refbug():
29 29 """Very nasty problem with references held by multiple runs of a script.
30 See: https://bugs.launchpad.net/ipython/+bug/269966
30 See: https://github.com/ipython/ipython/issues/141
31 31
32 32 In [1]: _ip.clear_main_mod_cache()
33 33 # random
34 34
35 35 In [2]: %run refbug
36 36
37 37 In [3]: call_f()
38 38 lowercased: hello
39 39
40 40 In [4]: %run refbug
41 41
42 42 In [5]: call_f()
43 43 lowercased: hello
44 44 lowercased: hello
45 45 """
46 46
47 47
48 48 def doctest_run_builtins():
49 49 r"""Check that %run doesn't damage __builtins__.
50 50
51 51 In [1]: import tempfile
52 52
53 53 In [2]: bid1 = id(__builtins__)
54 54
55 55 In [3]: fname = tempfile.mkstemp('.py')[1]
56 56
57 57 In [3]: f = open(fname,'w')
58 58
59 59 In [4]: f.write('pass\n')
60 60
61 61 In [5]: f.flush()
62 62
63 63 In [6]: t1 = type(__builtins__)
64 64
65 65 In [7]: %run $fname
66 66
67 67 In [7]: f.close()
68 68
69 69 In [8]: bid2 = id(__builtins__)
70 70
71 71 In [9]: t2 = type(__builtins__)
72 72
73 73 In [10]: t1 == t2
74 74 Out[10]: True
75 75
76 76 In [10]: bid1 == bid2
77 77 Out[10]: True
78 78
79 79 In [12]: try:
80 80 ....: os.unlink(fname)
81 81 ....: except:
82 82 ....: pass
83 83 ....:
84 84 """
85 85
86 86 def doctest_reset_del():
87 87 """Test that resetting doesn't cause errors in __del__ methods.
88 88
89 89 In [2]: class A(object):
90 90 ...: def __del__(self):
91 91 ...: print str("Hi")
92 92 ...:
93 93
94 94 In [3]: a = A()
95 95
96 96 In [4]: get_ipython().reset()
97 97 Hi
98 98
99 99 In [5]: 1+1
100 100 Out[5]: 2
101 101 """
102 102
103 103 # For some tests, it will be handy to organize them in a class with a common
104 104 # setup that makes a temp file
105 105
106 106 class TestMagicRunPass(tt.TempFileMixin):
107 107
108 108 def setup(self):
109 109 """Make a valid python temp file."""
110 110 self.mktmp('pass\n')
111 111
112 112 def run_tmpfile(self):
113 113 _ip = get_ipython()
114 114 # This fails on Windows if self.tmpfile.name has spaces or "~" in it.
115 115 # See below and ticket https://bugs.launchpad.net/bugs/366353
116 116 _ip.magic('run %s' % self.fname)
117 117
118 118 def test_builtins_id(self):
119 119 """Check that %run doesn't damage __builtins__ """
120 120 _ip = get_ipython()
121 121 # Test that the id of __builtins__ is not modified by %run
122 122 bid1 = id(_ip.user_ns['__builtins__'])
123 123 self.run_tmpfile()
124 124 bid2 = id(_ip.user_ns['__builtins__'])
125 125 tt.assert_equals(bid1, bid2)
126 126
127 127 def test_builtins_type(self):
128 128 """Check that the type of __builtins__ doesn't change with %run.
129 129
130 130 However, the above could pass if __builtins__ was already modified to
131 131 be a dict (it should be a module) by a previous use of %run. So we
132 132 also check explicitly that it really is a module:
133 133 """
134 134 _ip = get_ipython()
135 135 self.run_tmpfile()
136 136 tt.assert_equals(type(_ip.user_ns['__builtins__']),type(sys))
137 137
138 138 def test_prompts(self):
139 139 """Test that prompts correctly generate after %run"""
140 140 self.run_tmpfile()
141 141 _ip = get_ipython()
142 142 p2 = str(_ip.displayhook.prompt2).strip()
143 143 nt.assert_equals(p2[:3], '...')
144 144
145 145
146 146 class TestMagicRunSimple(tt.TempFileMixin):
147 147
148 148 def test_simpledef(self):
149 149 """Test that simple class definitions work."""
150 150 src = ("class foo: pass\n"
151 151 "def f(): return foo()")
152 152 self.mktmp(src)
153 153 _ip.magic('run %s' % self.fname)
154 154 _ip.run_cell('t = isinstance(f(), foo)')
155 155 nt.assert_true(_ip.user_ns['t'])
156 156
157 157 def test_obj_del(self):
158 158 """Test that object's __del__ methods are called on exit."""
159 159
160 # This test is known to fail on win32.
161 # See ticket https://bugs.launchpad.net/bugs/366334
162 160 src = ("class A(object):\n"
163 161 " def __del__(self):\n"
164 162 " print 'object A deleted'\n"
165 163 "a = A()\n")
166 164 self.mktmp(src)
167 165 tt.ipexec_validate(self.fname, 'object A deleted')
168 166
169 167 @dec.skip_known_failure
170 168 def test_aggressive_namespace_cleanup(self):
171 169 """Test that namespace cleanup is not too aggressive GH-238
172 170
173 171 Returning from another run magic deletes the namespace"""
174 172 # see ticket https://github.com/ipython/ipython/issues/238
175 173 class secondtmp(tt.TempFileMixin): pass
176 174 empty = secondtmp()
177 175 empty.mktmp('')
178 176 src = ("ip = get_ipython()\n"
179 177 "for i in range(5):\n"
180 178 " try:\n"
181 179 " ip.magic('run %s')\n"
182 180 " except NameError, e:\n"
183 181 " print i;break\n" % empty.fname)
184 182 self.mktmp(src)
185 183 _ip.magic('run %s' % self.fname)
186 184 _ip.run_cell('ip == get_ipython()')
187 185 tt.assert_equals(_ip.user_ns['i'], 5)
188 186
189 187 @dec.skip_win32
190 188 def test_tclass(self):
191 189 mydir = os.path.dirname(__file__)
192 190 tc = os.path.join(mydir, 'tclass')
193 191 src = ("%%run '%s' C-first\n"
194 192 "%%run '%s' C-second\n"
195 193 "%%run '%s' C-third\n") % (tc, tc, tc)
196 194 self.mktmp(src, '.ipy')
197 195 out = """\
198 196 ARGV 1-: [u'C-first']
199 197 ARGV 1-: [u'C-second']
200 198 tclass.py: deleting object: C-first
201 199 ARGV 1-: [u'C-third']
202 200 tclass.py: deleting object: C-second
203 201 tclass.py: deleting object: C-third
204 202 """
205 203 tt.ipexec_validate(self.fname, out)
@@ -1,443 +1,443 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) 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 """
16 16
17 17 #-----------------------------------------------------------------------------
18 18 # Copyright (C) 2009 The IPython Development Team
19 19 #
20 20 # Distributed under the terms of the BSD License. The full license is in
21 21 # the file COPYING, distributed as part of this software.
22 22 #-----------------------------------------------------------------------------
23 23
24 24 #-----------------------------------------------------------------------------
25 25 # Imports
26 26 #-----------------------------------------------------------------------------
27 27
28 28 # Stdlib
29 29 import os
30 30 import os.path as path
31 31 import signal
32 32 import sys
33 33 import subprocess
34 34 import tempfile
35 35 import time
36 36 import warnings
37 37
38 38 # Note: monkeypatch!
39 39 # We need to monkeypatch a small problem in nose itself first, before importing
40 40 # it for actual use. This should get into nose upstream, but its release cycle
41 41 # is slow and we need it for our parametric tests to work correctly.
42 42 from IPython.testing import nosepatch
43 43 # Now, proceed to import nose itself
44 44 import nose.plugins.builtin
45 45 from nose.core import TestProgram
46 46
47 47 # Our own imports
48 48 from IPython.utils.path import get_ipython_module_path
49 49 from IPython.utils.process import find_cmd, pycmd2argv
50 50 from IPython.utils.sysinfo import sys_info
51 51
52 52 from IPython.testing import globalipapp
53 53 from IPython.testing.plugin.ipdoctest import IPythonDoctest
54 54 from IPython.external.decorators import KnownFailure
55 55
56 56 pjoin = path.join
57 57
58 58
59 59 #-----------------------------------------------------------------------------
60 60 # Globals
61 61 #-----------------------------------------------------------------------------
62 62
63 63
64 64 #-----------------------------------------------------------------------------
65 65 # Warnings control
66 66 #-----------------------------------------------------------------------------
67 67
68 68 # Twisted generates annoying warnings with Python 2.6, as will do other code
69 69 # that imports 'sets' as of today
70 70 warnings.filterwarnings('ignore', 'the sets module is deprecated',
71 71 DeprecationWarning )
72 72
73 73 # This one also comes from Twisted
74 74 warnings.filterwarnings('ignore', 'the sha module is deprecated',
75 75 DeprecationWarning)
76 76
77 77 # Wx on Fedora11 spits these out
78 78 warnings.filterwarnings('ignore', 'wxPython/wxWidgets release number mismatch',
79 79 UserWarning)
80 80
81 81 #-----------------------------------------------------------------------------
82 82 # Logic for skipping doctests
83 83 #-----------------------------------------------------------------------------
84 84
85 85 def test_for(mod, min_version=None):
86 86 """Test to see if mod is importable."""
87 87 try:
88 88 __import__(mod)
89 89 except (ImportError, RuntimeError):
90 90 # GTK reports Runtime error if it can't be initialized even if it's
91 91 # importable.
92 92 return False
93 93 else:
94 94 if min_version:
95 95 return sys.modules[mod].__version__ >= min_version
96 96 else:
97 97 return True
98 98
99 99 # Global dict where we can store information on what we have and what we don't
100 100 # have available at test run time
101 101 have = {}
102 102
103 103 have['curses'] = test_for('_curses')
104 104 have['matplotlib'] = test_for('matplotlib')
105 105 have['pexpect'] = test_for('pexpect')
106 106 have['pymongo'] = test_for('pymongo')
107 107 have['wx'] = test_for('wx')
108 108 have['wx.aui'] = test_for('wx.aui')
109 109 if os.name == 'nt':
110 110 have['zmq'] = test_for('zmq', '2.1.7')
111 111 else:
112 112 have['zmq'] = test_for('zmq', '2.1.4')
113 113 have['qt'] = test_for('IPython.external.qt')
114 114
115 115 #-----------------------------------------------------------------------------
116 116 # Functions and classes
117 117 #-----------------------------------------------------------------------------
118 118
119 119 def report():
120 120 """Return a string with a summary report of test-related variables."""
121 121
122 122 out = [ sys_info(), '\n']
123 123
124 124 avail = []
125 125 not_avail = []
126 126
127 127 for k, is_avail in have.items():
128 128 if is_avail:
129 129 avail.append(k)
130 130 else:
131 131 not_avail.append(k)
132 132
133 133 if avail:
134 134 out.append('\nTools and libraries available at test time:\n')
135 135 avail.sort()
136 136 out.append(' ' + ' '.join(avail)+'\n')
137 137
138 138 if not_avail:
139 139 out.append('\nTools and libraries NOT available at test time:\n')
140 140 not_avail.sort()
141 141 out.append(' ' + ' '.join(not_avail)+'\n')
142 142
143 143 return ''.join(out)
144 144
145 145
146 146 def make_exclude():
147 147 """Make patterns of modules and packages to exclude from testing.
148 148
149 149 For the IPythonDoctest plugin, we need to exclude certain patterns that
150 150 cause testing problems. We should strive to minimize the number of
151 151 skipped modules, since this means untested code.
152 152
153 153 These modules and packages will NOT get scanned by nose at all for tests.
154 154 """
155 155 # Simple utility to make IPython paths more readably, we need a lot of
156 156 # these below
157 157 ipjoin = lambda *paths: pjoin('IPython', *paths)
158 158
159 159 exclusions = [ipjoin('external'),
160 160 pjoin('IPython_doctest_plugin'),
161 161 ipjoin('quarantine'),
162 162 ipjoin('deathrow'),
163 163 ipjoin('testing', 'attic'),
164 164 # This guy is probably attic material
165 165 ipjoin('testing', 'mkdoctests'),
166 166 # Testing inputhook will need a lot of thought, to figure out
167 167 # how to have tests that don't lock up with the gui event
168 168 # loops in the picture
169 169 ipjoin('lib', 'inputhook'),
170 170 # Config files aren't really importable stand-alone
171 171 ipjoin('config', 'default'),
172 172 ipjoin('config', 'profile'),
173 173 ]
174 174
175 175 if not have['wx']:
176 176 exclusions.append(ipjoin('lib', 'inputhookwx'))
177 177
178 178 # We do this unconditionally, so that the test suite doesn't import
179 179 # gtk, changing the default encoding and masking some unicode bugs.
180 180 exclusions.append(ipjoin('lib', 'inputhookgtk'))
181 181
182 182 # These have to be skipped on win32 because the use echo, rm, cd, etc.
183 # See ticket https://bugs.launchpad.net/bugs/366982
183 # See ticket https://github.com/ipython/ipython/issues/87
184 184 if sys.platform == 'win32':
185 185 exclusions.append(ipjoin('testing', 'plugin', 'test_exampleip'))
186 186 exclusions.append(ipjoin('testing', 'plugin', 'dtexample'))
187 187
188 188 if not have['pexpect']:
189 189 exclusions.extend([ipjoin('scripts', 'irunner'),
190 190 ipjoin('lib', 'irunner'),
191 191 ipjoin('lib', 'tests', 'test_irunner')])
192 192
193 193 if not have['zmq']:
194 194 exclusions.append(ipjoin('zmq'))
195 195 exclusions.append(ipjoin('frontend', 'qt'))
196 196 exclusions.append(ipjoin('parallel'))
197 197 elif not have['qt']:
198 198 exclusions.append(ipjoin('frontend', 'qt'))
199 199
200 200 if not have['pymongo']:
201 201 exclusions.append(ipjoin('parallel', 'controller', 'mongodb'))
202 202 exclusions.append(ipjoin('parallel', 'tests', 'test_mongodb'))
203 203
204 204 if not have['matplotlib']:
205 205 exclusions.extend([ipjoin('lib', 'pylabtools'),
206 206 ipjoin('lib', 'tests', 'test_pylabtools')])
207 207
208 208 # This is needed for the reg-exp to match on win32 in the ipdoctest plugin.
209 209 if sys.platform == 'win32':
210 210 exclusions = [s.replace('\\','\\\\') for s in exclusions]
211 211
212 212 return exclusions
213 213
214 214
215 215 class IPTester(object):
216 216 """Call that calls iptest or trial in a subprocess.
217 217 """
218 218 #: string, name of test runner that will be called
219 219 runner = None
220 220 #: list, parameters for test runner
221 221 params = None
222 222 #: list, arguments of system call to be made to call test runner
223 223 call_args = None
224 224 #: list, process ids of subprocesses we start (for cleanup)
225 225 pids = None
226 226
227 227 def __init__(self, runner='iptest', params=None):
228 228 """Create new test runner."""
229 229 p = os.path
230 230 if runner == 'iptest':
231 231 iptest_app = get_ipython_module_path('IPython.testing.iptest')
232 232 self.runner = pycmd2argv(iptest_app) + sys.argv[1:]
233 233 else:
234 234 raise Exception('Not a valid test runner: %s' % repr(runner))
235 235 if params is None:
236 236 params = []
237 237 if isinstance(params, str):
238 238 params = [params]
239 239 self.params = params
240 240
241 241 # Assemble call
242 242 self.call_args = self.runner+self.params
243 243
244 244 # Store pids of anything we start to clean up on deletion, if possible
245 245 # (on posix only, since win32 has no os.kill)
246 246 self.pids = []
247 247
248 248 if sys.platform == 'win32':
249 249 def _run_cmd(self):
250 250 # On Windows, use os.system instead of subprocess.call, because I
251 251 # was having problems with subprocess and I just don't know enough
252 252 # about win32 to debug this reliably. Os.system may be the 'old
253 253 # fashioned' way to do it, but it works just fine. If someone
254 254 # later can clean this up that's fine, as long as the tests run
255 255 # reliably in win32.
256 256 # What types of problems are you having. They may be related to
257 257 # running Python in unboffered mode. BG.
258 258 return os.system(' '.join(self.call_args))
259 259 else:
260 260 def _run_cmd(self):
261 261 # print >> sys.stderr, '*** CMD:', ' '.join(self.call_args) # dbg
262 262 subp = subprocess.Popen(self.call_args)
263 263 self.pids.append(subp.pid)
264 264 # If this fails, the pid will be left in self.pids and cleaned up
265 265 # later, but if the wait call succeeds, then we can clear the
266 266 # stored pid.
267 267 retcode = subp.wait()
268 268 self.pids.pop()
269 269 return retcode
270 270
271 271 def run(self):
272 272 """Run the stored commands"""
273 273 try:
274 274 return self._run_cmd()
275 275 except:
276 276 import traceback
277 277 traceback.print_exc()
278 278 return 1 # signal failure
279 279
280 280 def __del__(self):
281 281 """Cleanup on exit by killing any leftover processes."""
282 282
283 283 if not hasattr(os, 'kill'):
284 284 return
285 285
286 286 for pid in self.pids:
287 287 try:
288 288 print 'Cleaning stale PID:', pid
289 289 os.kill(pid, signal.SIGKILL)
290 290 except OSError:
291 291 # This is just a best effort, if we fail or the process was
292 292 # really gone, ignore it.
293 293 pass
294 294
295 295
296 296 def make_runners():
297 297 """Define the top-level packages that need to be tested.
298 298 """
299 299
300 300 # Packages to be tested via nose, that only depend on the stdlib
301 301 nose_pkg_names = ['config', 'core', 'extensions', 'frontend', 'lib',
302 302 'scripts', 'testing', 'utils' ]
303 303
304 304 if have['zmq']:
305 305 nose_pkg_names.append('parallel')
306 306
307 307 # For debugging this code, only load quick stuff
308 308 #nose_pkg_names = ['core', 'extensions'] # dbg
309 309
310 310 # Make fully qualified package names prepending 'IPython.' to our name lists
311 311 nose_packages = ['IPython.%s' % m for m in nose_pkg_names ]
312 312
313 313 # Make runners
314 314 runners = [ (v, IPTester('iptest', params=v)) for v in nose_packages ]
315 315
316 316 return runners
317 317
318 318
319 319 def run_iptest():
320 320 """Run the IPython test suite using nose.
321 321
322 322 This function is called when this script is **not** called with the form
323 323 `iptest all`. It simply calls nose with appropriate command line flags
324 324 and accepts all of the standard nose arguments.
325 325 """
326 326
327 327 warnings.filterwarnings('ignore',
328 328 'This will be removed soon. Use IPython.testing.util instead')
329 329
330 330 argv = sys.argv + [ '--detailed-errors', # extra info in tracebacks
331 331
332 332 # Loading ipdoctest causes problems with Twisted, but
333 333 # our test suite runner now separates things and runs
334 334 # all Twisted tests with trial.
335 335 '--with-ipdoctest',
336 336 '--ipdoctest-tests','--ipdoctest-extension=txt',
337 337
338 338 # We add --exe because of setuptools' imbecility (it
339 339 # blindly does chmod +x on ALL files). Nose does the
340 340 # right thing and it tries to avoid executables,
341 341 # setuptools unfortunately forces our hand here. This
342 342 # has been discussed on the distutils list and the
343 343 # setuptools devs refuse to fix this problem!
344 344 '--exe',
345 345 ]
346 346
347 347 if nose.__version__ >= '0.11':
348 348 # I don't fully understand why we need this one, but depending on what
349 349 # directory the test suite is run from, if we don't give it, 0 tests
350 350 # get run. Specifically, if the test suite is run from the source dir
351 351 # with an argument (like 'iptest.py IPython.core', 0 tests are run,
352 352 # even if the same call done in this directory works fine). It appears
353 353 # that if the requested package is in the current dir, nose bails early
354 354 # by default. Since it's otherwise harmless, leave it in by default
355 355 # for nose >= 0.11, though unfortunately nose 0.10 doesn't support it.
356 356 argv.append('--traverse-namespace')
357 357
358 358 # Construct list of plugins, omitting the existing doctest plugin, which
359 359 # ours replaces (and extends).
360 360 plugins = [IPythonDoctest(make_exclude()), KnownFailure()]
361 361 for p in nose.plugins.builtin.plugins:
362 362 plug = p()
363 363 if plug.name == 'doctest':
364 364 continue
365 365 plugins.append(plug)
366 366
367 367 # We need a global ipython running in this process
368 368 globalipapp.start_ipython()
369 369 # Now nose can run
370 370 TestProgram(argv=argv, plugins=plugins)
371 371
372 372
373 373 def run_iptestall():
374 374 """Run the entire IPython test suite by calling nose and trial.
375 375
376 376 This function constructs :class:`IPTester` instances for all IPython
377 377 modules and package and then runs each of them. This causes the modules
378 378 and packages of IPython to be tested each in their own subprocess using
379 379 nose or twisted.trial appropriately.
380 380 """
381 381
382 382 runners = make_runners()
383 383
384 384 # Run the test runners in a temporary dir so we can nuke it when finished
385 385 # to clean up any junk files left over by accident. This also makes it
386 386 # robust against being run in non-writeable directories by mistake, as the
387 387 # temp dir will always be user-writeable.
388 388 curdir = os.getcwd()
389 389 testdir = tempfile.gettempdir()
390 390 os.chdir(testdir)
391 391
392 392 # Run all test runners, tracking execution time
393 393 failed = []
394 394 t_start = time.time()
395 395 try:
396 396 for (name, runner) in runners:
397 397 print '*'*70
398 398 print 'IPython test group:',name
399 399 res = runner.run()
400 400 if res:
401 401 failed.append( (name, runner) )
402 402 finally:
403 403 os.chdir(curdir)
404 404 t_end = time.time()
405 405 t_tests = t_end - t_start
406 406 nrunners = len(runners)
407 407 nfail = len(failed)
408 408 # summarize results
409 409 print
410 410 print '*'*70
411 411 print 'Test suite completed for system with the following information:'
412 412 print report()
413 413 print 'Ran %s test groups in %.3fs' % (nrunners, t_tests)
414 414 print
415 415 print 'Status:'
416 416 if not failed:
417 417 print 'OK'
418 418 else:
419 419 # If anything went wrong, point out what command to rerun manually to
420 420 # see the actual errors and individual summary
421 421 print 'ERROR - %s out of %s test groups failed.' % (nfail, nrunners)
422 422 for name, failed_runner in failed:
423 423 print '-'*40
424 424 print 'Runner failed:',name
425 425 print 'You may wish to rerun this one individually, with:'
426 426 print ' '.join(failed_runner.call_args)
427 427 print
428 428 # Ensure that our exit code indicates failure
429 429 sys.exit(1)
430 430
431 431
432 432 def main():
433 433 for arg in sys.argv[1:]:
434 434 if arg.startswith('IPython'):
435 435 # This is in-process
436 436 run_iptest()
437 437 else:
438 438 # This starts subprocesses
439 439 run_iptestall()
440 440
441 441
442 442 if __name__ == '__main__':
443 443 main()
General Comments 0
You need to be logged in to leave comments. Login now