##// END OF EJS Templates
Make it possible to run the tests from the source dir without installation....
Fernando Perez -
Show More
@@ -0,0 +1,17 b''
1 #!/usr/bin/env python
2 """Test script for IPython.
3
4 The actual ipython test script to be installed with 'python setup.py install'
5 is in './scripts' directory. This file is here (ipython source root directory)
6 to facilitate non-root 'zero-installation testing' (just copy the source tree
7 somewhere and run ipython.py) and development.
8
9 You can run this script directly, type -h to see all options."""
10
11 # Ensure that the imported IPython is the local one, not a system-wide one
12 import os, sys
13 this_dir = os.path.dirname(os.path.abspath(__file__))
14 sys.path.insert(0, this_dir)
15
16 # Now proceed with execution
17 execfile(os.path.join(this_dir, 'IPython', 'scripts', 'iptest'))
@@ -1,397 +1,415 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """IPython Test Suite Runner.
2 """IPython Test Suite Runner.
3
3
4 This module provides a main entry point to a user script to test IPython
4 This module provides a main entry point to a user script to test IPython
5 itself from the command line. There are two ways of running this script:
5 itself from the command line. There are two ways of running this script:
6
6
7 1. With the syntax `iptest all`. This runs our entire test suite by
7 1. With the syntax `iptest all`. This runs our entire test suite by
8 calling this script (with different arguments) or trial recursively. This
8 calling this script (with different arguments) or trial recursively. This
9 causes modules and package to be tested in different processes, using nose
9 causes modules and package to be tested in different processes, using nose
10 or trial where appropriate.
10 or trial where appropriate.
11 2. With the regular nose syntax, like `iptest -vvs IPython`. In this form
11 2. With the regular nose syntax, like `iptest -vvs IPython`. In this form
12 the script simply calls nose, but with special command line flags and
12 the script simply calls nose, but with special command line flags and
13 plugins loaded.
13 plugins loaded.
14
14
15 For now, this script requires that both nose and twisted are installed. This
15 For now, this script requires that both nose and twisted are installed. This
16 will change in the future.
16 will change in the future.
17 """
17 """
18
18
19 #-----------------------------------------------------------------------------
19 #-----------------------------------------------------------------------------
20 # Module imports
20 # Module imports
21 #-----------------------------------------------------------------------------
21 #-----------------------------------------------------------------------------
22
22
23 # Stdlib
23 # Stdlib
24 import os
24 import os
25 import os.path as path
25 import os.path as path
26 import signal
26 import signal
27 import sys
27 import sys
28 import subprocess
28 import subprocess
29 import tempfile
29 import tempfile
30 import time
30 import time
31 import warnings
31 import warnings
32
32
33
34 # Ugly, but necessary hack to ensure the test suite finds our version of
35 # IPython and not a possibly different one that may exist system-wide.
36 # Note that this must be done here, so the imports that come next work
37 # correctly even if IPython isn't installed yet.
38 p = os.path
39 ippath = p.abspath(p.join(p.dirname(__file__),'..','..'))
40 sys.path.insert(0, ippath)
41 #print 'ipp:', ippath # dbg
42 #import IPython; print 'IP file:', IPython.__file__ # dbg
43
33 # Note: monkeypatch!
44 # Note: monkeypatch!
34 # We need to monkeypatch a small problem in nose itself first, before importing
45 # We need to monkeypatch a small problem in nose itself first, before importing
35 # it for actual use. This should get into nose upstream, but its release cycle
46 # it for actual use. This should get into nose upstream, but its release cycle
36 # is slow and we need it for our parametric tests to work correctly.
47 # is slow and we need it for our parametric tests to work correctly.
37 from IPython.testing import nosepatch
48 from IPython.testing import nosepatch
38 # Now, proceed to import nose itself
49 # Now, proceed to import nose itself
39 import nose.plugins.builtin
50 import nose.plugins.builtin
40 from nose.core import TestProgram
51 from nose.core import TestProgram
41
52
42 # Our own imports
53 # Our own imports
43 from IPython.utils import genutils
54 from IPython.utils import genutils
44 from IPython.utils.platutils import find_cmd, FindCmdError
55 from IPython.utils.platutils import find_cmd, FindCmdError
45 from IPython.testing import globalipapp
56 from IPython.testing import globalipapp
46 from IPython.testing import tools
57 from IPython.testing import tools
47 from IPython.testing.plugin.ipdoctest import IPythonDoctest
58 from IPython.testing.plugin.ipdoctest import IPythonDoctest
48
59
49 pjoin = path.join
60 pjoin = path.join
50
61
51 #-----------------------------------------------------------------------------
62 #-----------------------------------------------------------------------------
52 # Warnings control
63 # Warnings control
53 #-----------------------------------------------------------------------------
64 #-----------------------------------------------------------------------------
54 # Twisted generates annoying warnings with Python 2.6, as will do other code
65 # Twisted generates annoying warnings with Python 2.6, as will do other code
55 # that imports 'sets' as of today
66 # that imports 'sets' as of today
56 warnings.filterwarnings('ignore', 'the sets module is deprecated',
67 warnings.filterwarnings('ignore', 'the sets module is deprecated',
57 DeprecationWarning )
68 DeprecationWarning )
58
69
59 # This one also comes from Twisted
70 # This one also comes from Twisted
60 warnings.filterwarnings('ignore', 'the sha module is deprecated',
71 warnings.filterwarnings('ignore', 'the sha module is deprecated',
61 DeprecationWarning)
72 DeprecationWarning)
62
73
63 #-----------------------------------------------------------------------------
74 #-----------------------------------------------------------------------------
64 # Logic for skipping doctests
75 # Logic for skipping doctests
65 #-----------------------------------------------------------------------------
76 #-----------------------------------------------------------------------------
66
77
67 def test_for(mod):
78 def test_for(mod):
68 """Test to see if mod is importable."""
79 """Test to see if mod is importable."""
69 try:
80 try:
70 __import__(mod)
81 __import__(mod)
71 except ImportError:
82 except ImportError:
72 return False
83 return False
73 else:
84 else:
74 return True
85 return True
75
86
76
87
77 have_curses = test_for('_curses')
88 have_curses = test_for('_curses')
78 have_wx = test_for('wx')
89 have_wx = test_for('wx')
79 have_wx_aui = test_for('wx.aui')
90 have_wx_aui = test_for('wx.aui')
80 have_zi = test_for('zope.interface')
91 have_zi = test_for('zope.interface')
81 have_twisted = test_for('twisted')
92 have_twisted = test_for('twisted')
82 have_foolscap = test_for('foolscap')
93 have_foolscap = test_for('foolscap')
83 have_objc = test_for('objc')
94 have_objc = test_for('objc')
84 have_pexpect = test_for('pexpect')
95 have_pexpect = test_for('pexpect')
85 have_gtk = test_for('gtk')
96 have_gtk = test_for('gtk')
86 have_gobject = test_for('gobject')
97 have_gobject = test_for('gobject')
87
98
88
99
89 def make_exclude():
100 def make_exclude():
90 """Make patterns of modules and packages to exclude from testing.
101 """Make patterns of modules and packages to exclude from testing.
91
102
92 For the IPythonDoctest plugin, we need to exclude certain patterns that
103 For the IPythonDoctest plugin, we need to exclude certain patterns that
93 cause testing problems. We should strive to minimize the number of
104 cause testing problems. We should strive to minimize the number of
94 skipped modules, since this means untested code. As the testing
105 skipped modules, since this means untested code. As the testing
95 machinery solidifies, this list should eventually become empty.
106 machinery solidifies, this list should eventually become empty.
96 These modules and packages will NOT get scanned by nose at all for tests.
107 These modules and packages will NOT get scanned by nose at all for tests.
97 """
108 """
98 # Simple utility to make IPython paths more readably, we need a lot of
109 # Simple utility to make IPython paths more readably, we need a lot of
99 # these below
110 # these below
100 ipjoin = lambda *paths: pjoin('IPython', *paths)
111 ipjoin = lambda *paths: pjoin('IPython', *paths)
101
112
102 exclusions = [ipjoin('external'),
113 exclusions = [ipjoin('external'),
103 ipjoin('frontend', 'process', 'winprocess.py'),
114 ipjoin('frontend', 'process', 'winprocess.py'),
115 # Deprecated old Shell and iplib modules, skip to avoid
116 # warnings
117 ipjoin('Shell'),
118 ipjoin('iplib'),
104 pjoin('IPython_doctest_plugin'),
119 pjoin('IPython_doctest_plugin'),
105 ipjoin('quarantine'),
120 ipjoin('quarantine'),
106 ipjoin('deathrow'),
121 ipjoin('deathrow'),
107 ipjoin('testing', 'attic'),
122 ipjoin('testing', 'attic'),
108 # This guy is probably attic material
123 # This guy is probably attic material
109 ipjoin('testing', 'mkdoctests'),
124 ipjoin('testing', 'mkdoctests'),
110 # Testing inputhook will need a lot of thought, to figure out
125 # Testing inputhook will need a lot of thought, to figure out
111 # how to have tests that don't lock up with the gui event
126 # how to have tests that don't lock up with the gui event
112 # loops in the picture
127 # loops in the picture
113 ipjoin('lib', 'inputhook'),
128 ipjoin('lib', 'inputhook'),
114 # Config files aren't really importable stand-alone
129 # Config files aren't really importable stand-alone
115 ipjoin('config', 'default'),
130 ipjoin('config', 'default'),
116 ipjoin('config', 'profile'),
131 ipjoin('config', 'profile'),
117 ]
132 ]
118
133
119 if not have_wx:
134 if not have_wx:
120 exclusions.append(ipjoin('gui'))
135 exclusions.append(ipjoin('gui'))
121 exclusions.append(ipjoin('frontend', 'wx'))
136 exclusions.append(ipjoin('frontend', 'wx'))
122 exclusions.append(ipjoin('lib', 'inputhookwx'))
137 exclusions.append(ipjoin('lib', 'inputhookwx'))
123
138
124 if not have_gtk or not have_gobject:
139 if not have_gtk or not have_gobject:
125 exclusions.append(ipjoin('lib', 'inputhookgtk'))
140 exclusions.append(ipjoin('lib', 'inputhookgtk'))
126
141
127 if not have_wx_aui:
142 if not have_wx_aui:
128 exclusions.append(ipjoin('gui', 'wx', 'wxIPython'))
143 exclusions.append(ipjoin('gui', 'wx', 'wxIPython'))
129
144
130 if not have_objc:
145 if not have_objc:
131 exclusions.append(ipjoin('frontend', 'cocoa'))
146 exclusions.append(ipjoin('frontend', 'cocoa'))
132
147
133 if not sys.platform == 'win32':
148 if not sys.platform == 'win32':
134 exclusions.append(ipjoin('utils', 'platutils_win32'))
149 exclusions.append(ipjoin('utils', 'platutils_win32'))
135
150
136 # These have to be skipped on win32 because the use echo, rm, cd, etc.
151 # These have to be skipped on win32 because the use echo, rm, cd, etc.
137 # See ticket https://bugs.launchpad.net/bugs/366982
152 # See ticket https://bugs.launchpad.net/bugs/366982
138 if sys.platform == 'win32':
153 if sys.platform == 'win32':
139 exclusions.append(ipjoin('testing', 'plugin', 'test_exampleip'))
154 exclusions.append(ipjoin('testing', 'plugin', 'test_exampleip'))
140 exclusions.append(ipjoin('testing', 'plugin', 'dtexample'))
155 exclusions.append(ipjoin('testing', 'plugin', 'dtexample'))
141
156
142 if not os.name == 'posix':
157 if not os.name == 'posix':
143 exclusions.append(ipjoin('utils', 'platutils_posix'))
158 exclusions.append(ipjoin('utils', 'platutils_posix'))
144
159
145 if not have_pexpect:
160 if not have_pexpect:
146 exclusions.extend([ipjoin('scripts', 'irunner'),
161 exclusions.extend([ipjoin('scripts', 'irunner'),
147 ipjoin('lib', 'irunner')])
162 ipjoin('lib', 'irunner')])
148
163
149 # This is scary. We still have things in frontend and testing that
164 # This is scary. We still have things in frontend and testing that
150 # are being tested by nose that use twisted. We need to rethink
165 # are being tested by nose that use twisted. We need to rethink
151 # how we are isolating dependencies in testing.
166 # how we are isolating dependencies in testing.
152 if not (have_twisted and have_zi and have_foolscap):
167 if not (have_twisted and have_zi and have_foolscap):
153 exclusions.extend(
168 exclusions.extend(
154 [ipjoin('frontend', 'asyncfrontendbase'),
169 [ipjoin('frontend', 'asyncfrontendbase'),
155 ipjoin('frontend', 'prefilterfrontend'),
170 ipjoin('frontend', 'prefilterfrontend'),
156 ipjoin('frontend', 'frontendbase'),
171 ipjoin('frontend', 'frontendbase'),
157 ipjoin('frontend', 'linefrontendbase'),
172 ipjoin('frontend', 'linefrontendbase'),
158 ipjoin('frontend', 'tests', 'test_linefrontend'),
173 ipjoin('frontend', 'tests', 'test_linefrontend'),
159 ipjoin('frontend', 'tests', 'test_frontendbase'),
174 ipjoin('frontend', 'tests', 'test_frontendbase'),
160 ipjoin('frontend', 'tests', 'test_prefilterfrontend'),
175 ipjoin('frontend', 'tests', 'test_prefilterfrontend'),
161 ipjoin('frontend', 'tests', 'test_asyncfrontendbase'),
176 ipjoin('frontend', 'tests', 'test_asyncfrontendbase'),
162 ipjoin('testing', 'parametric'),
177 ipjoin('testing', 'parametric'),
163 ipjoin('testing', 'util'),
178 ipjoin('testing', 'util'),
164 ipjoin('testing', 'tests', 'test_decorators_trial'),
179 ipjoin('testing', 'tests', 'test_decorators_trial'),
165 ] )
180 ] )
166
181
167 # This is needed for the reg-exp to match on win32 in the ipdoctest plugin.
182 # This is needed for the reg-exp to match on win32 in the ipdoctest plugin.
168 if sys.platform == 'win32':
183 if sys.platform == 'win32':
169 exclusions = [s.replace('\\','\\\\') for s in exclusions]
184 exclusions = [s.replace('\\','\\\\') for s in exclusions]
170
185
171 return exclusions
186 return exclusions
172
187
173
188
174 #-----------------------------------------------------------------------------
189 #-----------------------------------------------------------------------------
175 # Functions and classes
190 # Functions and classes
176 #-----------------------------------------------------------------------------
191 #-----------------------------------------------------------------------------
177
192
178 class IPTester(object):
193 class IPTester(object):
179 """Call that calls iptest or trial in a subprocess.
194 """Call that calls iptest or trial in a subprocess.
180 """
195 """
181 #: string, name of test runner that will be called
196 #: string, name of test runner that will be called
182 runner = None
197 runner = None
183 #: list, parameters for test runner
198 #: list, parameters for test runner
184 params = None
199 params = None
185 #: list, arguments of system call to be made to call test runner
200 #: list, arguments of system call to be made to call test runner
186 call_args = None
201 call_args = None
187 #: list, process ids of subprocesses we start (for cleanup)
202 #: list, process ids of subprocesses we start (for cleanup)
188 pids = None
203 pids = None
189
204
190 def __init__(self, runner='iptest', params=None):
205 def __init__(self, runner='iptest', params=None):
191 """Create new test runner."""
206 """Create new test runner."""
192 if runner == 'iptest':
207 if runner == 'iptest':
193 # Find our own 'iptest' script OS-level entry point. Don't look
208 # Find our own 'iptest' script OS-level entry point. Don't look
194 # system-wide, so we are sure we pick up *this one*. And pass
209 # system-wide, so we are sure we pick up *this one*. And pass
195 # through to subprocess call our own sys.argv
210 # through to subprocess call our own sys.argv
196 self.runner = tools.cmd2argv(__file__) + sys.argv[1:]
211 self.runner = tools.cmd2argv(os.path.abspath(__file__)) + \
212 sys.argv[1:]
197 else:
213 else:
198 self.runner = tools.cmd2argv(os.path.abspath(find_cmd('trial')))
214 self.runner = tools.cmd2argv(os.path.abspath(find_cmd('trial')))
199 if params is None:
215 if params is None:
200 params = []
216 params = []
201 if isinstance(params, str):
217 if isinstance(params, str):
202 params = [params]
218 params = [params]
203 self.params = params
219 self.params = params
204
220
205 # Assemble call
221 # Assemble call
206 self.call_args = self.runner+self.params
222 self.call_args = self.runner+self.params
207
223
208 # Store pids of anything we start to clean up on deletion, if possible
224 # Store pids of anything we start to clean up on deletion, if possible
209 # (on posix only, since win32 has no os.kill)
225 # (on posix only, since win32 has no os.kill)
210 self.pids = []
226 self.pids = []
211
227
212 if sys.platform == 'win32':
228 if sys.platform == 'win32':
213 def _run_cmd(self):
229 def _run_cmd(self):
214 # On Windows, use os.system instead of subprocess.call, because I
230 # On Windows, use os.system instead of subprocess.call, because I
215 # was having problems with subprocess and I just don't know enough
231 # was having problems with subprocess and I just don't know enough
216 # about win32 to debug this reliably. Os.system may be the 'old
232 # about win32 to debug this reliably. Os.system may be the 'old
217 # fashioned' way to do it, but it works just fine. If someone
233 # fashioned' way to do it, but it works just fine. If someone
218 # later can clean this up that's fine, as long as the tests run
234 # later can clean this up that's fine, as long as the tests run
219 # reliably in win32.
235 # reliably in win32.
220 return os.system(' '.join(self.call_args))
236 return os.system(' '.join(self.call_args))
221 else:
237 else:
222 def _run_cmd(self):
238 def _run_cmd(self):
223 subp = subprocess.Popen(self.call_args)
239 subp = subprocess.Popen(self.call_args)
224 self.pids.append(subp.pid)
240 self.pids.append(subp.pid)
225 # If this fails, the pid will be left in self.pids and cleaned up
241 # If this fails, the pid will be left in self.pids and cleaned up
226 # later, but if the wait call succeeds, then we can clear the
242 # later, but if the wait call succeeds, then we can clear the
227 # stored pid.
243 # stored pid.
228 retcode = subp.wait()
244 retcode = subp.wait()
229 self.pids.pop()
245 self.pids.pop()
230 return retcode
246 return retcode
231
247
232 def run(self):
248 def run(self):
233 """Run the stored commands"""
249 """Run the stored commands"""
234 try:
250 try:
235 return self._run_cmd()
251 return self._run_cmd()
236 except:
252 except:
237 import traceback
253 import traceback
238 traceback.print_exc()
254 traceback.print_exc()
239 return 1 # signal failure
255 return 1 # signal failure
240
256
241 def __del__(self):
257 def __del__(self):
242 """Cleanup on exit by killing any leftover processes."""
258 """Cleanup on exit by killing any leftover processes."""
243
259
244 if not hasattr(os, 'kill'):
260 if not hasattr(os, 'kill'):
245 return
261 return
246
262
247 for pid in self.pids:
263 for pid in self.pids:
248 try:
264 try:
249 print 'Cleaning stale PID:', pid
265 print 'Cleaning stale PID:', pid
250 os.kill(pid, signal.SIGKILL)
266 os.kill(pid, signal.SIGKILL)
251 except OSError:
267 except OSError:
252 # This is just a best effort, if we fail or the process was
268 # This is just a best effort, if we fail or the process was
253 # really gone, ignore it.
269 # really gone, ignore it.
254 pass
270 pass
255
271
256
272
257 def make_runners():
273 def make_runners():
258 """Define the top-level packages that need to be tested.
274 """Define the top-level packages that need to be tested.
259 """
275 """
260
276
261 nose_packages = ['config', 'core', 'extensions', 'frontend', 'lib',
277 nose_packages = ['config', 'core', 'extensions', 'frontend', 'lib',
262 'scripts', 'testing', 'utils',
278 'scripts', 'testing', 'utils',
263 # Note that we list the kernel here, though the bulk of it
279 # Note that we list the kernel here, though the bulk of it
264 # is twisted-based, because nose picks up doctests that
280 # is twisted-based, because nose picks up doctests that
265 # twisted doesn't.
281 # twisted doesn't.
266 'kernel']
282 'kernel']
267 # The machinery in kernel needs twisted for real testing
283 # The machinery in kernel needs twisted for real testing
268 trial_packages = ['kernel']
284 trial_packages = ['kernel']
269
285
270 if have_wx:
286 if have_wx:
271 nose_packages.append('gui')
287 nose_packages.append('gui')
272
288
273 #nose_packages = ['config', 'utils'] # dbg
289 #nose_packages = ['config', 'utils'] # dbg
274 #trial_packages = [] # dbg
290 #trial_packages = [] # dbg
275
291
276 nose_packages = ['IPython.%s' % m for m in nose_packages ]
292 nose_packages = ['IPython.%s' % m for m in nose_packages ]
277 trial_packages = ['IPython.%s' % m for m in trial_packages ]
293 trial_packages = ['IPython.%s' % m for m in trial_packages ]
278
294
279 # Make runners, most with nose
295 # Make runners, most with nose
280 nose_testers = [IPTester(params=v) for v in nose_packages]
296 nose_testers = [IPTester(params=v) for v in nose_packages]
281 runners = zip(nose_packages, nose_testers)
297 runners = zip(nose_packages, nose_testers)
282
298
283 # And add twisted ones if conditions are met
299 # And add twisted ones if conditions are met
284 if have_zi and have_twisted and have_foolscap:
300 if have_zi and have_twisted and have_foolscap:
285 trial_testers = [IPTester('trial', params=v) for v in trial_packages]
301 trial_testers = [IPTester('trial', params=v) for v in trial_packages]
286 runners.extend(zip(trial_packages, trial_testers))
302 runners.extend(zip(trial_packages, trial_testers))
287
303
288 return runners
304 return runners
289
305
290
306
291 def run_iptest():
307 def run_iptest():
292 """Run the IPython test suite using nose.
308 """Run the IPython test suite using nose.
293
309
294 This function is called when this script is **not** called with the form
310 This function is called when this script is **not** called with the form
295 `iptest all`. It simply calls nose with appropriate command line flags
311 `iptest all`. It simply calls nose with appropriate command line flags
296 and accepts all of the standard nose arguments.
312 and accepts all of the standard nose arguments.
297 """
313 """
298
314
299 warnings.filterwarnings('ignore',
315 warnings.filterwarnings('ignore',
300 'This will be removed soon. Use IPython.testing.util instead')
316 'This will be removed soon. Use IPython.testing.util instead')
301
317
302 argv = sys.argv + [ '--detailed-errors',
318 argv = sys.argv + [ '--detailed-errors',
303 # Loading ipdoctest causes problems with Twisted, but
319 # Loading ipdoctest causes problems with Twisted, but
304 # our test suite runner now separates things and runs
320 # our test suite runner now separates things and runs
305 # all Twisted tests with trial.
321 # all Twisted tests with trial.
306 '--with-ipdoctest',
322 '--with-ipdoctest',
307 '--ipdoctest-tests','--ipdoctest-extension=txt',
323 '--ipdoctest-tests','--ipdoctest-extension=txt',
308
324
309 # We add --exe because of setuptools' imbecility (it
325 # We add --exe because of setuptools' imbecility (it
310 # blindly does chmod +x on ALL files). Nose does the
326 # blindly does chmod +x on ALL files). Nose does the
311 # right thing and it tries to avoid executables,
327 # right thing and it tries to avoid executables,
312 # setuptools unfortunately forces our hand here. This
328 # setuptools unfortunately forces our hand here. This
313 # has been discussed on the distutils list and the
329 # has been discussed on the distutils list and the
314 # setuptools devs refuse to fix this problem!
330 # setuptools devs refuse to fix this problem!
315 '--exe',
331 '--exe',
316 ]
332 ]
317
333
318
334
319 # Construct list of plugins, omitting the existing doctest plugin, which
335 # Construct list of plugins, omitting the existing doctest plugin, which
320 # ours replaces (and extends).
336 # ours replaces (and extends).
321 plugins = [IPythonDoctest(make_exclude())]
337 plugins = [IPythonDoctest(make_exclude())]
322 for p in nose.plugins.builtin.plugins:
338 for p in nose.plugins.builtin.plugins:
323 plug = p()
339 plug = p()
324 if plug.name == 'doctest':
340 if plug.name == 'doctest':
325 continue
341 continue
326 plugins.append(plug)
342 plugins.append(plug)
327
343
328 # We need a global ipython running in this process
344 # We need a global ipython running in this process
329 globalipapp.start_ipython()
345 globalipapp.start_ipython()
330 # Now nose can run
346 # Now nose can run
331 TestProgram(argv=argv, plugins=plugins)
347 TestProgram(argv=argv, plugins=plugins)
332
348
333
349
334 def run_iptestall():
350 def run_iptestall():
335 """Run the entire IPython test suite by calling nose and trial.
351 """Run the entire IPython test suite by calling nose and trial.
336
352
337 This function constructs :class:`IPTester` instances for all IPython
353 This function constructs :class:`IPTester` instances for all IPython
338 modules and package and then runs each of them. This causes the modules
354 modules and package and then runs each of them. This causes the modules
339 and packages of IPython to be tested each in their own subprocess using
355 and packages of IPython to be tested each in their own subprocess using
340 nose or twisted.trial appropriately.
356 nose or twisted.trial appropriately.
341 """
357 """
342
358
343 runners = make_runners()
359 runners = make_runners()
344
360
345 # Run the test runners in a temporary dir so we can nuke it when finished
361 # Run the test runners in a temporary dir so we can nuke it when finished
346 # to clean up any junk files left over by accident. This also makes it
362 # to clean up any junk files left over by accident. This also makes it
347 # robust against being run in non-writeable directories by mistake, as the
363 # robust against being run in non-writeable directories by mistake, as the
348 # temp dir will always be user-writeable.
364 # temp dir will always be user-writeable.
349 curdir = os.getcwd()
365 curdir = os.getcwd()
350 testdir = tempfile.gettempdir()
366 testdir = tempfile.gettempdir()
351 os.chdir(testdir)
367 os.chdir(testdir)
352
368
353 # Run all test runners, tracking execution time
369 # Run all test runners, tracking execution time
354 failed = []
370 failed = []
355 t_start = time.time()
371 t_start = time.time()
356 try:
372 try:
357 for (name, runner) in runners:
373 for (name, runner) in runners:
358 print '*'*70
374 print '*'*70
359 print 'IPython test group:',name
375 print 'IPython test group:',name
360 res = runner.run()
376 res = runner.run()
361 if res:
377 if res:
362 failed.append( (name, runner) )
378 failed.append( (name, runner) )
363 finally:
379 finally:
364 os.chdir(curdir)
380 os.chdir(curdir)
365 t_end = time.time()
381 t_end = time.time()
366 t_tests = t_end - t_start
382 t_tests = t_end - t_start
367 nrunners = len(runners)
383 nrunners = len(runners)
368 nfail = len(failed)
384 nfail = len(failed)
369 # summarize results
385 # summarize results
370 print
386 print
371 print '*'*70
387 print '*'*70
372 print 'Ran %s test groups in %.3fs' % (nrunners, t_tests)
388 print 'Ran %s test groups in %.3fs' % (nrunners, t_tests)
373 print
389 print
374 if not failed:
390 if not failed:
375 print 'OK'
391 print 'OK'
376 else:
392 else:
377 # If anything went wrong, point out what command to rerun manually to
393 # If anything went wrong, point out what command to rerun manually to
378 # see the actual errors and individual summary
394 # see the actual errors and individual summary
379 print 'ERROR - %s out of %s test groups failed.' % (nfail, nrunners)
395 print 'ERROR - %s out of %s test groups failed.' % (nfail, nrunners)
380 for name, failed_runner in failed:
396 for name, failed_runner in failed:
381 print '-'*40
397 print '-'*40
382 print 'Runner failed:',name
398 print 'Runner failed:',name
383 print 'You may wish to rerun this one individually, with:'
399 print 'You may wish to rerun this one individually, with:'
384 print ' '.join(failed_runner.call_args)
400 print ' '.join(failed_runner.call_args)
385 print
401 print
386
402
387
403
388 def main():
404 def main():
389 for arg in sys.argv[1:]:
405 for arg in sys.argv[1:]:
390 if arg.startswith('IPython'):
406 if arg.startswith('IPython'):
407 # This is in-process
391 run_iptest()
408 run_iptest()
392 else:
409 else:
410 # This starts subprocesses
393 run_iptestall()
411 run_iptestall()
394
412
395
413
396 if __name__ == '__main__':
414 if __name__ == '__main__':
397 main()
415 main()
@@ -1,315 +1,317 b''
1 """Generic testing tools that do NOT depend on Twisted.
1 """Generic testing tools that do NOT depend on Twisted.
2
2
3 In particular, this module exposes a set of top-level assert* functions that
3 In particular, this module exposes a set of top-level assert* functions that
4 can be used in place of nose.tools.assert* in method generators (the ones in
4 can be used in place of nose.tools.assert* in method generators (the ones in
5 nose can not, at least as of nose 0.10.4).
5 nose can not, at least as of nose 0.10.4).
6
6
7 Note: our testing package contains testing.util, which does depend on Twisted
7 Note: our testing package contains testing.util, which does depend on Twisted
8 and provides utilities for tests that manage Deferreds. All testing support
8 and provides utilities for tests that manage Deferreds. All testing support
9 tools that only depend on nose, IPython or the standard library should go here
9 tools that only depend on nose, IPython or the standard library should go here
10 instead.
10 instead.
11
11
12
12
13 Authors
13 Authors
14 -------
14 -------
15 - Fernando Perez <Fernando.Perez@berkeley.edu>
15 - Fernando Perez <Fernando.Perez@berkeley.edu>
16 """
16 """
17
17
18 #*****************************************************************************
18 #*****************************************************************************
19 # Copyright (C) 2009 The IPython Development Team
19 # Copyright (C) 2009 The IPython Development Team
20 #
20 #
21 # Distributed under the terms of the BSD License. The full license is in
21 # Distributed under the terms of the BSD License. The full license is in
22 # the file COPYING, distributed as part of this software.
22 # the file COPYING, distributed as part of this software.
23 #*****************************************************************************
23 #*****************************************************************************
24
24
25 #-----------------------------------------------------------------------------
25 #-----------------------------------------------------------------------------
26 # Required modules and packages
26 # Required modules and packages
27 #-----------------------------------------------------------------------------
27 #-----------------------------------------------------------------------------
28 from __future__ import absolute_import
28 from __future__ import absolute_import
29
29
30 import os
30 import os
31 import re
31 import re
32 import sys
32 import sys
33 import tempfile
33 import tempfile
34
34
35 try:
35 try:
36 # These tools are used by parts of the runtime, so we make the nose
36 # These tools are used by parts of the runtime, so we make the nose
37 # dependency optional at this point. Nose is a hard dependency to run the
37 # dependency optional at this point. Nose is a hard dependency to run the
38 # test suite, but NOT to use ipython itself.
38 # test suite, but NOT to use ipython itself.
39 import nose.tools as nt
39 import nose.tools as nt
40 has_nose = True
40 has_nose = True
41 except ImportError:
41 except ImportError:
42 has_nose = False
42 has_nose = False
43
43
44 from IPython.utils import genutils, platutils
44 from IPython.utils import genutils, platutils
45
45
46 from . import decorators as dec
46 from . import decorators as dec
47
47
48 #-----------------------------------------------------------------------------
48 #-----------------------------------------------------------------------------
49 # Globals
49 # Globals
50 #-----------------------------------------------------------------------------
50 #-----------------------------------------------------------------------------
51
51
52 # Make a bunch of nose.tools assert wrappers that can be used in test
52 # Make a bunch of nose.tools assert wrappers that can be used in test
53 # generators. This will expose an assert* function for each one in nose.tools.
53 # generators. This will expose an assert* function for each one in nose.tools.
54
54
55 _tpl = """
55 _tpl = """
56 def %(name)s(*a,**kw):
56 def %(name)s(*a,**kw):
57 return nt.%(name)s(*a,**kw)
57 return nt.%(name)s(*a,**kw)
58 """
58 """
59
59
60 if has_nose:
60 if has_nose:
61 for _x in [a for a in dir(nt) if a.startswith('assert')]:
61 for _x in [a for a in dir(nt) if a.startswith('assert')]:
62 exec _tpl % dict(name=_x)
62 exec _tpl % dict(name=_x)
63
63
64 #-----------------------------------------------------------------------------
64 #-----------------------------------------------------------------------------
65 # Functions and classes
65 # Functions and classes
66 #-----------------------------------------------------------------------------
66 #-----------------------------------------------------------------------------
67
67
68 # The docstring for full_path doctests differently on win32 (different path
68 # The docstring for full_path doctests differently on win32 (different path
69 # separator) so just skip the doctest there. The example remains informative.
69 # separator) so just skip the doctest there. The example remains informative.
70 doctest_deco = dec.skip_doctest if sys.platform == 'win32' else dec.null_deco
70 doctest_deco = dec.skip_doctest if sys.platform == 'win32' else dec.null_deco
71
71
72 @doctest_deco
72 @doctest_deco
73 def full_path(startPath,files):
73 def full_path(startPath,files):
74 """Make full paths for all the listed files, based on startPath.
74 """Make full paths for all the listed files, based on startPath.
75
75
76 Only the base part of startPath is kept, since this routine is typically
76 Only the base part of startPath is kept, since this routine is typically
77 used with a script's __file__ variable as startPath. The base of startPath
77 used with a script's __file__ variable as startPath. The base of startPath
78 is then prepended to all the listed files, forming the output list.
78 is then prepended to all the listed files, forming the output list.
79
79
80 Parameters
80 Parameters
81 ----------
81 ----------
82 startPath : string
82 startPath : string
83 Initial path to use as the base for the results. This path is split
83 Initial path to use as the base for the results. This path is split
84 using os.path.split() and only its first component is kept.
84 using os.path.split() and only its first component is kept.
85
85
86 files : string or list
86 files : string or list
87 One or more files.
87 One or more files.
88
88
89 Examples
89 Examples
90 --------
90 --------
91
91
92 >>> full_path('/foo/bar.py',['a.txt','b.txt'])
92 >>> full_path('/foo/bar.py',['a.txt','b.txt'])
93 ['/foo/a.txt', '/foo/b.txt']
93 ['/foo/a.txt', '/foo/b.txt']
94
94
95 >>> full_path('/foo',['a.txt','b.txt'])
95 >>> full_path('/foo',['a.txt','b.txt'])
96 ['/a.txt', '/b.txt']
96 ['/a.txt', '/b.txt']
97
97
98 If a single file is given, the output is still a list:
98 If a single file is given, the output is still a list:
99 >>> full_path('/foo','a.txt')
99 >>> full_path('/foo','a.txt')
100 ['/a.txt']
100 ['/a.txt']
101 """
101 """
102
102
103 files = genutils.list_strings(files)
103 files = genutils.list_strings(files)
104 base = os.path.split(startPath)[0]
104 base = os.path.split(startPath)[0]
105 return [ os.path.join(base,f) for f in files ]
105 return [ os.path.join(base,f) for f in files ]
106
106
107
107
108 def parse_test_output(txt):
108 def parse_test_output(txt):
109 """Parse the output of a test run and return errors, failures.
109 """Parse the output of a test run and return errors, failures.
110
110
111 Parameters
111 Parameters
112 ----------
112 ----------
113 txt : str
113 txt : str
114 Text output of a test run, assumed to contain a line of one of the
114 Text output of a test run, assumed to contain a line of one of the
115 following forms::
115 following forms::
116 'FAILED (errors=1)'
116 'FAILED (errors=1)'
117 'FAILED (failures=1)'
117 'FAILED (failures=1)'
118 'FAILED (errors=1, failures=1)'
118 'FAILED (errors=1, failures=1)'
119
119
120 Returns
120 Returns
121 -------
121 -------
122 nerr, nfail: number of errors and failures.
122 nerr, nfail: number of errors and failures.
123 """
123 """
124
124
125 err_m = re.search(r'^FAILED \(errors=(\d+)\)', txt, re.MULTILINE)
125 err_m = re.search(r'^FAILED \(errors=(\d+)\)', txt, re.MULTILINE)
126 if err_m:
126 if err_m:
127 nerr = int(err_m.group(1))
127 nerr = int(err_m.group(1))
128 nfail = 0
128 nfail = 0
129 return nerr, nfail
129 return nerr, nfail
130
130
131 fail_m = re.search(r'^FAILED \(failures=(\d+)\)', txt, re.MULTILINE)
131 fail_m = re.search(r'^FAILED \(failures=(\d+)\)', txt, re.MULTILINE)
132 if fail_m:
132 if fail_m:
133 nerr = 0
133 nerr = 0
134 nfail = int(fail_m.group(1))
134 nfail = int(fail_m.group(1))
135 return nerr, nfail
135 return nerr, nfail
136
136
137 both_m = re.search(r'^FAILED \(errors=(\d+), failures=(\d+)\)', txt,
137 both_m = re.search(r'^FAILED \(errors=(\d+), failures=(\d+)\)', txt,
138 re.MULTILINE)
138 re.MULTILINE)
139 if both_m:
139 if both_m:
140 nerr = int(both_m.group(1))
140 nerr = int(both_m.group(1))
141 nfail = int(both_m.group(2))
141 nfail = int(both_m.group(2))
142 return nerr, nfail
142 return nerr, nfail
143
143
144 # If the input didn't match any of these forms, assume no error/failures
144 # If the input didn't match any of these forms, assume no error/failures
145 return 0, 0
145 return 0, 0
146
146
147
147
148 # So nose doesn't think this is a test
148 # So nose doesn't think this is a test
149 parse_test_output.__test__ = False
149 parse_test_output.__test__ = False
150
150
151
151
152 def cmd2argv(cmd):
152 def cmd2argv(cmd):
153 r"""Take the path of a command and return a list (argv-style).
153 r"""Take the path of a command and return a list (argv-style).
154
154
155 For a given path ``cmd``, this returns [cmd] if cmd's extension is .exe,
155 For a given path ``cmd``, this returns [cmd] if cmd's extension is .exe,
156 .com or .bat, and ['python', cmd] otherwise.
156 .com or .bat, and ['python', cmd] otherwise.
157
157
158 This is mostly a Windows utility, to deal with the fact that the scripts in
158 This is mostly a Windows utility, to deal with the fact that the scripts in
159 Windows get wrapped in .exe entry points, so we have to call them
159 Windows get wrapped in .exe entry points, so we have to call them
160 differently.
160 differently.
161
161
162 Parameters
162 Parameters
163 ----------
163 ----------
164 cmd : string
164 cmd : string
165 The path of the command.
165 The path of the command.
166
166
167 Returns
167 Returns
168 -------
168 -------
169 argv-style list.
169 argv-style list.
170
170
171 Examples
171 Examples
172 --------
172 --------
173 In [2]: cmd2argv('/usr/bin/ipython')
173 In [2]: cmd2argv('/usr/bin/ipython')
174 Out[2]: ['python', '/usr/bin/ipython']
174 Out[2]: ['python', '/usr/bin/ipython']
175
175
176 In [3]: cmd2argv(r'C:\Python26\Scripts\ipython.exe')
176 In [3]: cmd2argv(r'C:\Python26\Scripts\ipython.exe')
177 Out[3]: ['C:\\Python26\\Scripts\\ipython.exe']
177 Out[3]: ['C:\\Python26\\Scripts\\ipython.exe']
178 """
178 """
179 ext = os.path.splitext(cmd)[1]
179 ext = os.path.splitext(cmd)[1]
180 if ext in ['.exe', '.com', '.bat']:
180 if ext in ['.exe', '.com', '.bat']:
181 return [cmd]
181 return [cmd]
182 else:
182 else:
183 return ['python', cmd]
183 return ['python', cmd]
184
184
185
185
186 def temp_pyfile(src, ext='.py'):
186 def temp_pyfile(src, ext='.py'):
187 """Make a temporary python file, return filename and filehandle.
187 """Make a temporary python file, return filename and filehandle.
188
188
189 Parameters
189 Parameters
190 ----------
190 ----------
191 src : string or list of strings (no need for ending newlines if list)
191 src : string or list of strings (no need for ending newlines if list)
192 Source code to be written to the file.
192 Source code to be written to the file.
193
193
194 ext : optional, string
194 ext : optional, string
195 Extension for the generated file.
195 Extension for the generated file.
196
196
197 Returns
197 Returns
198 -------
198 -------
199 (filename, open filehandle)
199 (filename, open filehandle)
200 It is the caller's responsibility to close the open file and unlink it.
200 It is the caller's responsibility to close the open file and unlink it.
201 """
201 """
202 fname = tempfile.mkstemp(ext)[1]
202 fname = tempfile.mkstemp(ext)[1]
203 f = open(fname,'w')
203 f = open(fname,'w')
204 f.write(src)
204 f.write(src)
205 f.flush()
205 f.flush()
206 return fname, f
206 return fname, f
207
207
208
208
209 def default_argv():
209 def default_argv():
210 """Return a valid default argv for creating testing instances of ipython"""
210 """Return a valid default argv for creating testing instances of ipython"""
211
211
212 return ['--quick', # so no config file is loaded
212 return ['--quick', # so no config file is loaded
213 # Other defaults to minimize side effects on stdout
213 # Other defaults to minimize side effects on stdout
214 '--colors=NoColor', '--no-term-title','--no-banner',
214 '--colors=NoColor', '--no-term-title','--no-banner',
215 '--autocall=0']
215 '--autocall=0']
216
216
217
217
218 def ipexec(fname, options=None):
218 def ipexec(fname, options=None):
219 """Utility to call 'ipython filename'.
219 """Utility to call 'ipython filename'.
220
220
221 Starts IPython witha minimal and safe configuration to make startup as fast
221 Starts IPython witha minimal and safe configuration to make startup as fast
222 as possible.
222 as possible.
223
223
224 Note that this starts IPython in a subprocess!
224 Note that this starts IPython in a subprocess!
225
225
226 Parameters
226 Parameters
227 ----------
227 ----------
228 fname : str
228 fname : str
229 Name of file to be executed (should have .py or .ipy extension).
229 Name of file to be executed (should have .py or .ipy extension).
230
230
231 options : optional, list
231 options : optional, list
232 Extra command-line flags to be passed to IPython.
232 Extra command-line flags to be passed to IPython.
233
233
234 Returns
234 Returns
235 -------
235 -------
236 (stdout, stderr) of ipython subprocess.
236 (stdout, stderr) of ipython subprocess.
237 """
237 """
238 if options is None: options = []
238 if options is None: options = []
239
239
240 # For these subprocess calls, eliminate all prompt printing so we only see
240 # For these subprocess calls, eliminate all prompt printing so we only see
241 # output from script execution
241 # output from script execution
242 prompt_opts = ['--prompt-in1=""', '--prompt-in2=""', '--prompt-out=""']
242 prompt_opts = ['--prompt-in1=""', '--prompt-in2=""', '--prompt-out=""']
243 cmdargs = ' '.join(default_argv() + prompt_opts + options)
243 cmdargs = ' '.join(default_argv() + prompt_opts + options)
244
244
245 _ip = get_ipython()
245 _ip = get_ipython()
246 test_dir = os.path.dirname(__file__)
246 test_dir = os.path.dirname(__file__)
247
247 # Find the ipython script from the package we're using, so that the test
248 # Find the ipython script from the package we're using, so that the test
248 # suite can be run from the source tree without an installed IPython
249 # suite can be run from the source tree without an installed IPython
249 ipython_package_dir = genutils.get_ipython_package_dir()
250 p = os.path
250 ipython_script = os.path.join(ipython_package_dir,'scripts','ipython')
251 ippath = p.abspath(p.join(p.dirname(__file__),'..','..'))
252 ipython_script = p.join(ippath, 'ipython.py')
251 ipython_cmd = 'python "%s"' % ipython_script
253 ipython_cmd = 'python "%s"' % ipython_script
252 # Absolute path for filename
254 # Absolute path for filename
253 full_fname = os.path.join(test_dir, fname)
255 full_fname = p.join(test_dir, fname)
254 full_cmd = '%s %s "%s"' % (ipython_cmd, cmdargs, full_fname)
256 full_cmd = '%s %s "%s"' % (ipython_cmd, cmdargs, full_fname)
255 return genutils.getoutputerror(full_cmd)
257 return genutils.getoutputerror(full_cmd)
256
258
257
259
258 def ipexec_validate(fname, expected_out, expected_err=None,
260 def ipexec_validate(fname, expected_out, expected_err=None,
259 options=None):
261 options=None):
260 """Utility to call 'ipython filename' and validate output/error.
262 """Utility to call 'ipython filename' and validate output/error.
261
263
262 This function raises an AssertionError if the validation fails.
264 This function raises an AssertionError if the validation fails.
263
265
264 Note that this starts IPython in a subprocess!
266 Note that this starts IPython in a subprocess!
265
267
266 Parameters
268 Parameters
267 ----------
269 ----------
268 fname : str
270 fname : str
269 Name of the file to be executed (should have .py or .ipy extension).
271 Name of the file to be executed (should have .py or .ipy extension).
270
272
271 expected_out : str
273 expected_out : str
272 Expected stdout of the process.
274 Expected stdout of the process.
273
275
274 expected_err : optional, str
276 expected_err : optional, str
275 Expected stderr of the process.
277 Expected stderr of the process.
276
278
277 options : optional, list
279 options : optional, list
278 Extra command-line flags to be passed to IPython.
280 Extra command-line flags to be passed to IPython.
279
281
280 Returns
282 Returns
281 -------
283 -------
282 None
284 None
283 """
285 """
284
286
285 import nose.tools as nt
287 import nose.tools as nt
286
288
287 out, err = ipexec(fname)
289 out, err = ipexec(fname)
288 nt.assert_equals(out.strip(), expected_out.strip())
290 nt.assert_equals(out.strip(), expected_out.strip())
289 if expected_err:
291 if expected_err:
290 nt.assert_equals(err.strip(), expected_err.strip())
292 nt.assert_equals(err.strip(), expected_err.strip())
291
293
292
294
293 class TempFileMixin(object):
295 class TempFileMixin(object):
294 """Utility class to create temporary Python/IPython files.
296 """Utility class to create temporary Python/IPython files.
295
297
296 Meant as a mixin class for test cases."""
298 Meant as a mixin class for test cases."""
297
299
298 def mktmp(self, src, ext='.py'):
300 def mktmp(self, src, ext='.py'):
299 """Make a valid python temp file."""
301 """Make a valid python temp file."""
300 fname, f = temp_pyfile(src, ext)
302 fname, f = temp_pyfile(src, ext)
301 self.tmpfile = f
303 self.tmpfile = f
302 self.fname = fname
304 self.fname = fname
303
305
304 def teardown(self):
306 def teardown(self):
305 if hasattr(self, 'tmpfile'):
307 if hasattr(self, 'tmpfile'):
306 # If the tmpfile wasn't made because of skipped tests, like in
308 # If the tmpfile wasn't made because of skipped tests, like in
307 # win32, there's nothing to cleanup.
309 # win32, there's nothing to cleanup.
308 self.tmpfile.close()
310 self.tmpfile.close()
309 try:
311 try:
310 os.unlink(self.fname)
312 os.unlink(self.fname)
311 except:
313 except:
312 # On Windows, even though we close the file, we still can't
314 # On Windows, even though we close the file, we still can't
313 # delete it. I have no clue why
315 # delete it. I have no clue why
314 pass
316 pass
315
317
@@ -1,11 +1,29 b''
1 ==============
1 ==============
2 IPython README
2 IPython README
3 ==============
3 ==============
4
4
5 Overview
5 Overview
6 ========
6 ========
7
7
8 Welcome to IPython. Our documentation can be found in the docs/source
8 Welcome to IPython. Our full documentation can be found in the ``docs/dist``
9 subdirectory. We also have ``.html`` and ``.pdf`` versions of this
9 subdirectory in ``.html`` and ``.pdf`` formats, also available online at our
10 documentation available on the IPython `website <http://ipython.scipy.org>`_.
10 `website <http://ipython.scipy.org>`_. The ``docs/source`` directory contains
11 the plaintext version of these manuals.
11
12
13
14 Instant running and testing
15 ===========================
16
17 You can run IPython from this directory without even installing it system-wide
18 by typing at the terminal:
19
20 .. code-block:: bash
21
22 python ipython.py
23
24 and similarly, you can execute the built-in test suite with:
25
26 .. code-block:: bash
27
28 python iptest.py
29 No newline at end of file
@@ -1,355 +1,372 b''
1 .. _testing:
1 .. _testing:
2
2
3 ==========================================
3 ==========================================
4 Testing IPython for users and developers
4 Testing IPython for users and developers
5 ==========================================
5 ==========================================
6
6
7 Overview
7 Overview
8 ========
8 ========
9
9
10 It is extremely important that all code contributed to IPython has tests.
10 It is extremely important that all code contributed to IPython has tests.
11 Tests should be written as unittests, doctests or other entities that the
11 Tests should be written as unittests, doctests or other entities that the
12 IPython test system can detect. See below for more details on this.
12 IPython test system can detect. See below for more details on this.
13
13
14 Each subpackage in IPython should have its own :file:`tests` directory that
14 Each subpackage in IPython should have its own :file:`tests` directory that
15 contains all of the tests for that subpackage. All of the files in the
15 contains all of the tests for that subpackage. All of the files in the
16 :file:`tests` directory should have the word "tests" in them to enable
16 :file:`tests` directory should have the word "tests" in them to enable
17 the testing framework to find them.
17 the testing framework to find them.
18
18
19 In docstrings, examples (either using IPython prompts like ``In [1]:`` or
19 In docstrings, examples (either using IPython prompts like ``In [1]:`` or
20 'classic' python ``>>>`` ones) can and should be included. The testing system
20 'classic' python ``>>>`` ones) can and should be included. The testing system
21 will detect them as doctests and will run them; it offers control to skip parts
21 will detect them as doctests and will run them; it offers control to skip parts
22 or all of a specific doctest if the example is meant to be informative but
22 or all of a specific doctest if the example is meant to be informative but
23 shows non-reproducible information (like filesystem data).
23 shows non-reproducible information (like filesystem data).
24
24
25 If a subpackage has any dependencies beyond the Python standard library, the
25 If a subpackage has any dependencies beyond the Python standard library, the
26 tests for that subpackage should be skipped if the dependencies are not found.
26 tests for that subpackage should be skipped if the dependencies are not found.
27 This is very important so users don't get tests failing simply because they
27 This is very important so users don't get tests failing simply because they
28 don't have dependencies.
28 don't have dependencies.
29
29
30 The testing system we use is a hybrid of nose_ and Twisted's trial_ test runner.
30 The testing system we use is a hybrid of nose_ and Twisted's trial_ test runner.
31 We use both because nose detects more things than Twisted and allows for more
31 We use both because nose detects more things than Twisted and allows for more
32 flexible (and lighter-weight) ways of writing tests; in particular we've
32 flexible (and lighter-weight) ways of writing tests; in particular we've
33 developed a nose plugin that allows us to paste verbatim IPython sessions and
33 developed a nose plugin that allows us to paste verbatim IPython sessions and
34 test them as doctests, which is extremely important for us. But the parts of
34 test them as doctests, which is extremely important for us. But the parts of
35 IPython that depend on Twisted must be tested using trial, because only trial
35 IPython that depend on Twisted must be tested using trial, because only trial
36 manages the Twisted reactor correctly.
36 manages the Twisted reactor correctly.
37
37
38 .. _nose: http://code.google.com/p/python-nose
38 .. _nose: http://code.google.com/p/python-nose
39 .. _trial: http://twistedmatrix.com/trac/wiki/TwistedTrial
39 .. _trial: http://twistedmatrix.com/trac/wiki/TwistedTrial
40
40
41
41
42 For the impatient: running the tests
42 For the impatient: running the tests
43 ====================================
43 ====================================
44
44
45 The simplest way to test IPython is to type at the command line:
45 You can run IPython from the source download directory without even installing
46 it system-wide or having configure anything, by typing at the terminal:
47
48 .. code-block:: bash
49
50 python ipython.py
51
52 and similarly, you can execute the built-in test suite with:
53
54 .. code-block:: bash
55
56 python iptest.py
57
58
59 Once you have either installed it or at least configured your system to be
60 able to import IPython, you can run the tests with:
46
61
47 .. code-block:: bash
62 .. code-block:: bash
48
63
49 python -c "import IPython; IPython.test()"
64 python -c "import IPython; IPython.test()"
50
65
51 This should work as long as IPython can be imported, even if you haven't fully
66 This should work as long as IPython can be imported, even if you haven't fully
52 installed the user-facing scripts yet (common in a development environment).
67 installed the user-facing scripts yet (common in a development environment).
53 After a lot of output, you should see something like:
68
69
70 Regardless of how you run things, you should eventually see something like:
54
71
55 .. code-block:: bash
72 .. code-block:: bash
56
73
57 ************************************************************************
74 ************************************************************************
58 Ran 10 test groups in 35.228s
75 Ran 10 test groups in 35.228s
59
76
60 OK
77 OK
61
78
62 If not, there will be a message indicating which test group failed and how to
79 If not, there will be a message indicating which test group failed and how to
63 rerun that group individually.
80 rerun that group individually.
64
81
65 But IPython ships with an entry point script called :file:`iptest` that offers
82 But IPython ships with an entry point script called :file:`iptest` that offers
66 fine-grain control over the test process and is particularly useful for
83 fine-grain control over the test process and is particularly useful for
67 developers; this script also manages intelligently both nose and trial,
84 developers; this script also manages intelligently both nose and trial,
68 choosing the correct test system for each of IPython's components. Running
85 choosing the correct test system for each of IPython's components. Running
69 :file:`iptest` without arguments gives output identical to that above, but with
86 :file:`iptest` without arguments gives output identical to that above, but with
70 it, you can also run specific tests with fine control. The :file:`iptest`
87 it, you can also run specific tests with fine control. The :file:`iptest`
71 script is installed with IPython, but if you are running from a source tree,
88 script is installed with IPython, but if you are running from a source tree,
72 you can find it in the :file:`IPython/scripts` directory and you can run
89 you can find it in the :file:`IPython/scripts` directory and you can run
73 directly from there.
90 directly from there.
74
91
75 For example, this tests the :mod:`IPython.utils` subpackage, the :option:`-v`
92 For example, this tests the :mod:`IPython.utils` subpackage, the :option:`-v`
76 option shows progress indicators:
93 option shows progress indicators:
77
94
78 .. code-block:: bash
95 .. code-block:: bash
79
96
80 maqroll[ipython]> cd IPython/scripts/
97 maqroll[ipython]> cd IPython/scripts/
81 maqroll[scripts]> ./iptest -v IPython.utils
98 maqroll[scripts]> ./iptest -v IPython.utils
82 ..........................SS..SSS............................S.S.........
99 ..........................SS..SSS............................S.S.........
83 ...................................................
100 ...................................................
84 ----------------------------------------------------------------------
101 ----------------------------------------------------------------------
85 Ran 125 tests in 0.070s
102 Ran 125 tests in 0.070s
86
103
87 OK (SKIP=7)
104 OK (SKIP=7)
88
105
89 Because :file:`iptest` is based on nose, you can use all nose options and
106 Because :file:`iptest` is based on nose, you can use all nose options and
90 syntax, typing ``iptest -h`` shows all available options. For example, this
107 syntax, typing ``iptest -h`` shows all available options. For example, this
91 lets you run the specific test :func:`test_rehashx` inside the
108 lets you run the specific test :func:`test_rehashx` inside the
92 :mod:`test_magic` module:
109 :mod:`test_magic` module:
93
110
94 .. code-block:: bash
111 .. code-block:: bash
95
112
96 maqroll[scripts]> ./iptest -vv IPython.core.tests.test_magic:test_rehashx
113 maqroll[scripts]> ./iptest -vv IPython.core.tests.test_magic:test_rehashx
97 IPython.core.tests.test_magic.test_rehashx(True,) ... ok
114 IPython.core.tests.test_magic.test_rehashx(True,) ... ok
98 IPython.core.tests.test_magic.test_rehashx(True,) ... ok
115 IPython.core.tests.test_magic.test_rehashx(True,) ... ok
99
116
100 ----------------------------------------------------------------------
117 ----------------------------------------------------------------------
101 Ran 2 tests in 0.101s
118 Ran 2 tests in 0.101s
102
119
103 OK
120 OK
104
121
105 When developing, the :option:`--pdb` and :option:`--pdb-failures` of nose are
122 When developing, the :option:`--pdb` and :option:`--pdb-failures` of nose are
106 particularly useful, these drop you into an interactive pdb session at the
123 particularly useful, these drop you into an interactive pdb session at the
107 point of the error or failure respectively.
124 point of the error or failure respectively.
108
125
109 To run Twisted-using tests, use the :command:`trial` command on a per file or
126 To run Twisted-using tests, use the :command:`trial` command on a per file or
110 package basis:
127 package basis:
111
128
112 .. code-block:: bash
129 .. code-block:: bash
113
130
114 trial IPython.kernel
131 trial IPython.kernel
115
132
116
133
117 For developers: writing tests
134 For developers: writing tests
118 =============================
135 =============================
119
136
120 By now IPython has a reasonable test suite, so the best way to see what's
137 By now IPython has a reasonable test suite, so the best way to see what's
121 available is to look at the :file:`tests` directory in most subpackages. But
138 available is to look at the :file:`tests` directory in most subpackages. But
122 here are a few pointers to make the process easier.
139 here are a few pointers to make the process easier.
123
140
124
141
125 Main tools: :mod:`IPython.testing`
142 Main tools: :mod:`IPython.testing`
126 ----------------------------------
143 ----------------------------------
127
144
128 The :mod:`IPython.testing` package is where all of the machinery to test
145 The :mod:`IPython.testing` package is where all of the machinery to test
129 IPython (rather than the tests for its various parts) lives. In particular,
146 IPython (rather than the tests for its various parts) lives. In particular,
130 the :mod:`iptest` module in there has all the smarts to control the test
147 the :mod:`iptest` module in there has all the smarts to control the test
131 process. In there, the :func:`make_exclude` function is used to build a
148 process. In there, the :func:`make_exclude` function is used to build a
132 blacklist of exclusions, these are modules that do not get even imported for
149 blacklist of exclusions, these are modules that do not get even imported for
133 tests. This is important so that things that would fail to even import because
150 tests. This is important so that things that would fail to even import because
134 of missing dependencies don't give errors to end users, as we stated above.
151 of missing dependencies don't give errors to end users, as we stated above.
135
152
136 The :mod:`decorators` module contains a lot of useful decorators, especially
153 The :mod:`decorators` module contains a lot of useful decorators, especially
137 useful to mark individual tests that should be skipped under certain conditions
154 useful to mark individual tests that should be skipped under certain conditions
138 (rather than blacklisting the package altogether because of a missing major
155 (rather than blacklisting the package altogether because of a missing major
139 dependency).
156 dependency).
140
157
141 Our nose plugin for doctests
158 Our nose plugin for doctests
142 ----------------------------
159 ----------------------------
143
160
144 The :mod:`plugin` subpackage in testing contains a nose plugin called
161 The :mod:`plugin` subpackage in testing contains a nose plugin called
145 :mod:`ipdoctest` that teaches nose about IPython syntax, so you can write
162 :mod:`ipdoctest` that teaches nose about IPython syntax, so you can write
146 doctests with IPython prompts. You can also mark doctest output with ``#
163 doctests with IPython prompts. You can also mark doctest output with ``#
147 random`` for the output corresponding to a single input to be ignored (stronger
164 random`` for the output corresponding to a single input to be ignored (stronger
148 than using ellipsis and useful to keep it as an example). If you want the
165 than using ellipsis and useful to keep it as an example). If you want the
149 entire docstring to be executed but none of the output from any input to be
166 entire docstring to be executed but none of the output from any input to be
150 checked, you can use the ``# all-random`` marker. The
167 checked, you can use the ``# all-random`` marker. The
151 :mod:`IPython.testing.plugin.dtexample` module contains examples of how to use
168 :mod:`IPython.testing.plugin.dtexample` module contains examples of how to use
152 these; for reference here is how to use ``# random``::
169 these; for reference here is how to use ``# random``::
153
170
154 def ranfunc():
171 def ranfunc():
155 """A function with some random output.
172 """A function with some random output.
156
173
157 Normal examples are verified as usual:
174 Normal examples are verified as usual:
158 >>> 1+3
175 >>> 1+3
159 4
176 4
160
177
161 But if you put '# random' in the output, it is ignored:
178 But if you put '# random' in the output, it is ignored:
162 >>> 1+3
179 >>> 1+3
163 junk goes here... # random
180 junk goes here... # random
164
181
165 >>> 1+2
182 >>> 1+2
166 again, anything goes #random
183 again, anything goes #random
167 if multiline, the random mark is only needed once.
184 if multiline, the random mark is only needed once.
168
185
169 >>> 1+2
186 >>> 1+2
170 You can also put the random marker at the end:
187 You can also put the random marker at the end:
171 # random
188 # random
172
189
173 >>> 1+2
190 >>> 1+2
174 # random
191 # random
175 .. or at the beginning.
192 .. or at the beginning.
176
193
177 More correct input is properly verified:
194 More correct input is properly verified:
178 >>> ranfunc()
195 >>> ranfunc()
179 'ranfunc'
196 'ranfunc'
180 """
197 """
181 return 'ranfunc'
198 return 'ranfunc'
182
199
183 and an example of ``# all-random``::
200 and an example of ``# all-random``::
184
201
185 def random_all():
202 def random_all():
186 """A function where we ignore the output of ALL examples.
203 """A function where we ignore the output of ALL examples.
187
204
188 Examples:
205 Examples:
189
206
190 # all-random
207 # all-random
191
208
192 This mark tells the testing machinery that all subsequent examples
209 This mark tells the testing machinery that all subsequent examples
193 should be treated as random (ignoring their output). They are still
210 should be treated as random (ignoring their output). They are still
194 executed, so if a they raise an error, it will be detected as such,
211 executed, so if a they raise an error, it will be detected as such,
195 but their output is completely ignored.
212 but their output is completely ignored.
196
213
197 >>> 1+3
214 >>> 1+3
198 junk goes here...
215 junk goes here...
199
216
200 >>> 1+3
217 >>> 1+3
201 klasdfj;
218 klasdfj;
202
219
203 In [8]: print 'hello'
220 In [8]: print 'hello'
204 world # random
221 world # random
205
222
206 In [9]: iprand()
223 In [9]: iprand()
207 Out[9]: 'iprand'
224 Out[9]: 'iprand'
208 """
225 """
209 return 'iprand'
226 return 'iprand'
210
227
211
228
212 When writing docstrings, you can use the ``@skip_doctest`` decorator to
229 When writing docstrings, you can use the ``@skip_doctest`` decorator to
213 indicate that a docstring should *not* be treated as a doctest at all. The
230 indicate that a docstring should *not* be treated as a doctest at all. The
214 difference betwee ``# all-random`` and ``@skip_doctest`` is that the former
231 difference betwee ``# all-random`` and ``@skip_doctest`` is that the former
215 executes the example but ignores output, while the latter doesn't execute any
232 executes the example but ignores output, while the latter doesn't execute any
216 code. ``@skip_doctest`` should be used for docstrings whose examples are
233 code. ``@skip_doctest`` should be used for docstrings whose examples are
217 purely informational.
234 purely informational.
218
235
219 If a given docstring fails under certain conditions but otherwise is a good
236 If a given docstring fails under certain conditions but otherwise is a good
220 doctest, you can use code like the following, that relies on the 'null'
237 doctest, you can use code like the following, that relies on the 'null'
221 decorator to leave the docstring intact where it works as a test::
238 decorator to leave the docstring intact where it works as a test::
222
239
223 # The docstring for full_path doctests differently on win32 (different path
240 # The docstring for full_path doctests differently on win32 (different path
224 # separator) so just skip the doctest there, and use a null decorator
241 # separator) so just skip the doctest there, and use a null decorator
225 # elsewhere:
242 # elsewhere:
226
243
227 doctest_deco = dec.skip_doctest if sys.platform == 'win32' else dec.null_deco
244 doctest_deco = dec.skip_doctest if sys.platform == 'win32' else dec.null_deco
228
245
229 @doctest_deco
246 @doctest_deco
230 def full_path(startPath,files):
247 def full_path(startPath,files):
231 """Make full paths for all the listed files, based on startPath..."""
248 """Make full paths for all the listed files, based on startPath..."""
232
249
233 # function body follows...
250 # function body follows...
234
251
235 With our nose plugin that understands IPython syntax, an extremely effective
252 With our nose plugin that understands IPython syntax, an extremely effective
236 way to write tests is to simply copy and paste an interactive session into a
253 way to write tests is to simply copy and paste an interactive session into a
237 docstring. You can writing this type of test, where your docstring is meant
254 docstring. You can writing this type of test, where your docstring is meant
238 *only* as a test, by prefixing the function name with ``doctest_`` and leaving
255 *only* as a test, by prefixing the function name with ``doctest_`` and leaving
239 its body *absolutely empty* other than the docstring. In
256 its body *absolutely empty* other than the docstring. In
240 :mod:`IPython.core.tests.test_magic` you can find several examples of this, but
257 :mod:`IPython.core.tests.test_magic` you can find several examples of this, but
241 for completeness sake, your code should look like this (a simple case)::
258 for completeness sake, your code should look like this (a simple case)::
242
259
243 def doctest_time():
260 def doctest_time():
244 """
261 """
245 In [10]: %time None
262 In [10]: %time None
246 CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
263 CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
247 Wall time: 0.00 s
264 Wall time: 0.00 s
248 """
265 """
249
266
250 This function is only analyzed for its docstring but it is not considered a
267 This function is only analyzed for its docstring but it is not considered a
251 separate test, which is why its body should be empty.
268 separate test, which is why its body should be empty.
252
269
253
270
254 Parametric tests done right
271 Parametric tests done right
255 ---------------------------
272 ---------------------------
256
273
257 If you need to run multiple tests inside the same standalone function or method
274 If you need to run multiple tests inside the same standalone function or method
258 of a :class:`unittest.TestCase` subclass, IPython provides the ``parametric``
275 of a :class:`unittest.TestCase` subclass, IPython provides the ``parametric``
259 decorator for this purpose. This is superior to how test generators work in
276 decorator for this purpose. This is superior to how test generators work in
260 nose, because IPython's keeps intact your stack, which makes debugging vastly
277 nose, because IPython's keeps intact your stack, which makes debugging vastly
261 easier. For example, these are some parametric tests both in class form and as
278 easier. For example, these are some parametric tests both in class form and as
262 a standalone function (choose in each situation the style that best fits the
279 a standalone function (choose in each situation the style that best fits the
263 problem at hand, since both work)::
280 problem at hand, since both work)::
264
281
265 from IPython.testing import decorators as dec
282 from IPython.testing import decorators as dec
266
283
267 def is_smaller(i,j):
284 def is_smaller(i,j):
268 assert i<j,"%s !< %s" % (i,j)
285 assert i<j,"%s !< %s" % (i,j)
269
286
270 class Tester(ParametricTestCase):
287 class Tester(ParametricTestCase):
271
288
272 def test_parametric(self):
289 def test_parametric(self):
273 yield is_smaller(3, 4)
290 yield is_smaller(3, 4)
274 x, y = 1, 2
291 x, y = 1, 2
275 yield is_smaller(x, y)
292 yield is_smaller(x, y)
276
293
277 @dec.parametric
294 @dec.parametric
278 def test_par_standalone():
295 def test_par_standalone():
279 yield is_smaller(3, 4)
296 yield is_smaller(3, 4)
280 x, y = 1, 2
297 x, y = 1, 2
281 yield is_smaller(x, y)
298 yield is_smaller(x, y)
282
299
283
300
284 Writing tests for Twisted-using code
301 Writing tests for Twisted-using code
285 ------------------------------------
302 ------------------------------------
286
303
287 Tests of Twisted [Twisted]_ using code should be written by subclassing the
304 Tests of Twisted [Twisted]_ using code should be written by subclassing the
288 ``TestCase`` class that comes with ``twisted.trial.unittest``. Furthermore, all
305 ``TestCase`` class that comes with ``twisted.trial.unittest``. Furthermore, all
289 :class:`Deferred` instances that are created in the test must be properly
306 :class:`Deferred` instances that are created in the test must be properly
290 chained and the final one *must* be the return value of the test method.
307 chained and the final one *must* be the return value of the test method.
291
308
292 .. note::
309 .. note::
293
310
294 The best place to see how to use the testing tools, are the tests for these
311 The best place to see how to use the testing tools, are the tests for these
295 tools themselves, which live in :mod:`IPython.testing.tests`.
312 tools themselves, which live in :mod:`IPython.testing.tests`.
296
313
297
314
298 Design requirements
315 Design requirements
299 ===================
316 ===================
300
317
301 This section is a set of notes on the key points of the IPython testing needs,
318 This section is a set of notes on the key points of the IPython testing needs,
302 that were used when writing the system and should be kept for reference as it
319 that were used when writing the system and should be kept for reference as it
303 eveolves.
320 eveolves.
304
321
305 Testing IPython in full requires modifications to the default behavior of nose
322 Testing IPython in full requires modifications to the default behavior of nose
306 and doctest, because the IPython prompt is not recognized to determine Python
323 and doctest, because the IPython prompt is not recognized to determine Python
307 input, and because IPython admits user input that is not valid Python (things
324 input, and because IPython admits user input that is not valid Python (things
308 like ``%magics`` and ``!system commands``.
325 like ``%magics`` and ``!system commands``.
309
326
310 We basically need to be able to test the following types of code:
327 We basically need to be able to test the following types of code:
311
328
312 1. Pure Python files containing normal tests. These are not a problem, since
329 1. Pure Python files containing normal tests. These are not a problem, since
313 Nose will pick them up as long as they conform to the (flexible) conventions
330 Nose will pick them up as long as they conform to the (flexible) conventions
314 used by nose to recognize tests.
331 used by nose to recognize tests.
315
332
316 2. Python files containing doctests. Here, we have two possibilities:
333 2. Python files containing doctests. Here, we have two possibilities:
317 - The prompts are the usual ``>>>`` and the input is pure Python.
334 - The prompts are the usual ``>>>`` and the input is pure Python.
318 - The prompts are of the form ``In [1]:`` and the input can contain extended
335 - The prompts are of the form ``In [1]:`` and the input can contain extended
319 IPython expressions.
336 IPython expressions.
320
337
321 In the first case, Nose will recognize the doctests as long as it is called
338 In the first case, Nose will recognize the doctests as long as it is called
322 with the ``--with-doctest`` flag. But the second case will likely require
339 with the ``--with-doctest`` flag. But the second case will likely require
323 modifications or the writing of a new doctest plugin for Nose that is
340 modifications or the writing of a new doctest plugin for Nose that is
324 IPython-aware.
341 IPython-aware.
325
342
326 3. ReStructuredText files that contain code blocks. For this type of file, we
343 3. ReStructuredText files that contain code blocks. For this type of file, we
327 have three distinct possibilities for the code blocks:
344 have three distinct possibilities for the code blocks:
328 - They use ``>>>`` prompts.
345 - They use ``>>>`` prompts.
329 - They use ``In [1]:`` prompts.
346 - They use ``In [1]:`` prompts.
330 - They are standalone blocks of pure Python code without any prompts.
347 - They are standalone blocks of pure Python code without any prompts.
331
348
332 The first two cases are similar to the situation #2 above, except that in
349 The first two cases are similar to the situation #2 above, except that in
333 this case the doctests must be extracted from input code blocks using
350 this case the doctests must be extracted from input code blocks using
334 docutils instead of from the Python docstrings.
351 docutils instead of from the Python docstrings.
335
352
336 In the third case, we must have a convention for distinguishing code blocks
353 In the third case, we must have a convention for distinguishing code blocks
337 that are meant for execution from others that may be snippets of shell code
354 that are meant for execution from others that may be snippets of shell code
338 or other examples not meant to be run. One possibility is to assume that
355 or other examples not meant to be run. One possibility is to assume that
339 all indented code blocks are meant for execution, but to have a special
356 all indented code blocks are meant for execution, but to have a special
340 docutils directive for input that should not be executed.
357 docutils directive for input that should not be executed.
341
358
342 For those code blocks that we will execute, the convention used will simply
359 For those code blocks that we will execute, the convention used will simply
343 be that they get called and are considered successful if they run to
360 be that they get called and are considered successful if they run to
344 completion without raising errors. This is similar to what Nose does for
361 completion without raising errors. This is similar to what Nose does for
345 standalone test functions, and by putting asserts or other forms of
362 standalone test functions, and by putting asserts or other forms of
346 exception-raising statements it becomes possible to have literate examples
363 exception-raising statements it becomes possible to have literate examples
347 that double as lightweight tests.
364 that double as lightweight tests.
348
365
349 4. Extension modules with doctests in function and method docstrings.
366 4. Extension modules with doctests in function and method docstrings.
350 Currently Nose simply can't find these docstrings correctly, because the
367 Currently Nose simply can't find these docstrings correctly, because the
351 underlying doctest DocTestFinder object fails there. Similarly to #2 above,
368 underlying doctest DocTestFinder object fails there. Similarly to #2 above,
352 the docstrings could have either pure python or IPython prompts.
369 the docstrings could have either pure python or IPython prompts.
353
370
354 Of these, only 3-c (reST with standalone code blocks) is not implemented at
371 Of these, only 3-c (reST with standalone code blocks) is not implemented at
355 this point.
372 this point.
@@ -1,12 +1,16 b''
1 #!/usr/bin/env python
1 #!/usr/bin/env python
2 # -*- coding: utf-8 -*-
2 # -*- coding: utf-8 -*-
3 """IPython -- An enhanced Interactive Python
3 """IPython -- An enhanced Interactive Python
4
4
5 The actual ipython script to be installed with 'python setup.py install' is
5 The actual ipython script to be installed with 'python setup.py install' is
6 in './scripts' directory. This file is here (ipython source root directory)
6 in './scripts' directory. This file is here (ipython source root directory)
7 to facilitate non-root 'zero-installation' (just copy the source tree
7 to facilitate non-root 'zero-installation' (just copy the source tree
8 somewhere and run ipython.py) and development. """
8 somewhere and run ipython.py) and development. """
9
9
10 from IPython.core.ipapp import launch_new_instance
10 # Ensure that the imported IPython is the local one, not a system-wide one
11 import os, sys
12 this_dir = os.path.dirname(os.path.abspath(__file__))
13 sys.path.insert(0, this_dir)
11
14
12 launch_new_instance()
15 # Now proceed with execution
16 execfile(os.path.join(this_dir, 'IPython', 'scripts', 'ipython'))
General Comments 0
You need to be logged in to leave comments. Login now