##// END OF EJS Templates
Merging with upstream trunk-dev, which is the base for this branch
Fernando Perez -
r2497:728f86a9 merge
parent child Browse files
Show More
@@ -0,0 +1,51 b''
1 """Base utilities support for IPython.
2
3 Warning: this is a module that other utilities modules will import from, so it
4 can ONLY depend on the standard library, and NOTHING ELSE. In particular, this
5 module can NOT import anything from IPython, or circular dependencies will arise.
6 """
7
8 #-----------------------------------------------------------------------------
9 # Imports
10 #-----------------------------------------------------------------------------
11
12 import subprocess
13
14 #-----------------------------------------------------------------------------
15 # Functions
16 #-----------------------------------------------------------------------------
17
18 def getoutputerror(cmd,verbose=0,debug=0,header='',split=0):
19 """Return (standard output,standard error) of executing cmd in a shell.
20
21 Accepts the same arguments as system(), plus:
22
23 - split(0): if true, each of stdout/err is returned as a list split on
24 newlines.
25
26 Note: a stateful version of this function is available through the
27 SystemExec class."""
28
29 if verbose or debug: print header+cmd
30 if not cmd:
31 if split:
32 return [],[]
33 else:
34 return '',''
35 if not debug:
36 p = subprocess.Popen(cmd, shell=True,
37 stdin=subprocess.PIPE,
38 stdout=subprocess.PIPE,
39 stderr=subprocess.PIPE,
40 close_fds=True)
41 pin, pout, perr = (p.stdin, p.stdout, p.stderr)
42
43 tout = pout.read().rstrip()
44 terr = perr.read().rstrip()
45 pin.close()
46 pout.close()
47 perr.close()
48 if split:
49 return tout.split('\n'),terr.split('\n')
50 else:
51 return tout,terr
@@ -0,0 +1,26 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, and will test IPython from an importable
6 location.
7
8 This file is here (ipython source root directory) to facilitate non-root
9 'zero-installation testing and development' (just copy the source tree
10 somewhere and run iptest.py).
11
12 You can run this script directly, type -h to see all options."""
13
14 # Ensure that the imported IPython packages come from *THIS* IPython, not some
15 # other one that may exist system-wide
16 import os, sys
17 this_dir = os.path.dirname(os.path.abspath(__file__))
18 sys.path.insert(0, this_dir)
19
20 import IPython.testing.tools as t
21 import IPython.testing.iptest as ipt
22 t.INSTALLED = False
23 ipt.INSTALLED = False
24
25 # Now proceed with execution
26 execfile(os.path.join(this_dir, 'IPython', 'scripts', 'iptest'))
@@ -26,9 +26,12 b' from pprint import pformat'
26 # Our own
26 # Our own
27 from IPython.core import release
27 from IPython.core import release
28 from IPython.core import ultratb
28 from IPython.core import ultratb
29 from IPython.utils.genutils import sys_info
30
29 from IPython.external.Itpl import itpl
31 from IPython.external.Itpl import itpl
30
32
31 #****************************************************************************
33 #****************************************************************************
34
32 class CrashHandler(object):
35 class CrashHandler(object):
33 """Customizable crash handlers for IPython-based systems.
36 """Customizable crash handlers for IPython-based systems.
34
37
@@ -166,21 +169,13 b' $self.bug_tracker'
166
169
167 def make_report(self,traceback):
170 def make_report(self,traceback):
168 """Return a string containing a crash report."""
171 """Return a string containing a crash report."""
169 import platform
170
172
171 sec_sep = self.section_sep
173 sec_sep = self.section_sep
172
174
173 report = []
175 report = ['*'*75+'\n\n'+'IPython post-mortem report\n\n']
174 rpt_add = report.append
176 rpt_add = report.append
177 rpt_add(sys_info())
175
178
176 rpt_add('*'*75+'\n\n'+'IPython post-mortem report\n\n')
177 rpt_add('IPython version: %s \n' % release.version)
178 rpt_add('BZR revision : %s \n' % release.revision)
179 rpt_add('Platform info : os.name -> %s, sys.platform -> %s\n' %
180 (os.name,sys.platform) )
181 rpt_add(' : %s\n' % platform.platform())
182 rpt_add('Python info : %s\n' % sys.version)
183
184 try:
179 try:
185 config = pformat(self.app.config)
180 config = pformat(self.app.config)
186 rpt_add(sec_sep+'Current user configuration structure:\n\n')
181 rpt_add(sec_sep+'Current user configuration structure:\n\n')
@@ -85,22 +85,22 b" def magic_history(self, parameter_s = ''):"
85 if 'g' in opts:
85 if 'g' in opts:
86 init = 1
86 init = 1
87 final = len(input_hist)
87 final = len(input_hist)
88 parts = parameter_s.split(None,1)
88 parts = parameter_s.split(None, 1)
89 if len(parts) == 1:
89 if len(parts) == 1:
90 parts += '*'
90 parts += '*'
91 head, pattern = parts
91 head, pattern = parts
92 pattern = "*" + pattern + "*"
92 pattern = "*" + pattern + "*"
93 elif len(args) == 0:
93 elif len(args) == 0:
94 final = len(input_hist)
94 final = len(input_hist)-1
95 init = max(1,final-default_length)
95 init = max(1,final-default_length)
96 elif len(args) == 1:
96 elif len(args) == 1:
97 final = len(input_hist)
97 final = len(input_hist)
98 init = max(1,final-int(args[0]))
98 init = max(1, final-int(args[0]))
99 elif len(args) == 2:
99 elif len(args) == 2:
100 init,final = map(int,args)
100 init, final = map(int, args)
101 else:
101 else:
102 warn('%hist takes 0, 1 or 2 arguments separated by spaces.')
102 warn('%hist takes 0, 1 or 2 arguments separated by spaces.')
103 print self.magic_hist.__doc__
103 print >> Term.cout, self.magic_hist.__doc__
104 return
104 return
105
105
106 width = len(str(final))
106 width = len(str(final))
@@ -114,13 +114,14 b" def magic_history(self, parameter_s = ''):"
114 sh = self.shadowhist.all()
114 sh = self.shadowhist.all()
115 for idx, s in sh:
115 for idx, s in sh:
116 if fnmatch.fnmatch(s, pattern):
116 if fnmatch.fnmatch(s, pattern):
117 print "0%d: %s" %(idx, s)
117 print >> outfile, "0%d: %s" %(idx, s)
118 found = True
118 found = True
119
119
120 if found:
120 if found:
121 print "==="
121 print >> outfile, "==="
122 print "shadow history ends, fetch by %rep <number> (must start with 0)"
122 print >> outfile, \
123 print "=== start of normal history ==="
123 "shadow history ends, fetch by %rep <number> (must start with 0)"
124 print >> outfile, "=== start of normal history ==="
124
125
125 for in_num in range(init,final):
126 for in_num in range(init,final):
126 inline = input_hist[in_num]
127 inline = input_hist[in_num]
@@ -130,7 +131,7 b" def magic_history(self, parameter_s = ''):"
130 multiline = int(inline.count('\n') > 1)
131 multiline = int(inline.count('\n') > 1)
131 if print_nums:
132 if print_nums:
132 print >> outfile, \
133 print >> outfile, \
133 '%s:%s' % (str(in_num).ljust(width),line_sep[multiline]),
134 '%s:%s' % (str(in_num).ljust(width), line_sep[multiline]),
134 if pyprompts:
135 if pyprompts:
135 print >> outfile, '>>>',
136 print >> outfile, '>>>',
136 if multiline:
137 if multiline:
@@ -141,9 +142,10 b" def magic_history(self, parameter_s = ''):"
141 print >> outfile, inline,
142 print >> outfile, inline,
142 else:
143 else:
143 print >> outfile, inline,
144 print >> outfile, inline,
144 output = self.shell.user_ns['Out'].get(in_num)
145 if print_outputs:
145 if output is not None:
146 output = self.shell.user_ns['Out'].get(in_num)
146 print repr(output)
147 if output is not None:
148 print >> outfile, repr(output)
147
149
148 if close_at_end:
150 if close_at_end:
149 outfile.close()
151 outfile.close()
@@ -219,14 +219,21 b' def make_user_namespaces(user_ns=None, user_global_ns=None):'
219 of the interpreter and a dict to be used as the global namespace.
219 of the interpreter and a dict to be used as the global namespace.
220 """
220 """
221
221
222
223 # We must ensure that __builtin__ (without the final 's') is always
224 # available and pointing to the __builtin__ *module*. For more details:
225 # http://mail.python.org/pipermail/python-dev/2001-April/014068.html
226
222 if user_ns is None:
227 if user_ns is None:
223 # Set __name__ to __main__ to better match the behavior of the
228 # Set __name__ to __main__ to better match the behavior of the
224 # normal interpreter.
229 # normal interpreter.
225 user_ns = {'__name__' :'__main__',
230 user_ns = {'__name__' :'__main__',
231 '__builtin__' : __builtin__,
226 '__builtins__' : __builtin__,
232 '__builtins__' : __builtin__,
227 }
233 }
228 else:
234 else:
229 user_ns.setdefault('__name__','__main__')
235 user_ns.setdefault('__name__','__main__')
236 user_ns.setdefault('__builtin__',__builtin__)
230 user_ns.setdefault('__builtins__',__builtin__)
237 user_ns.setdefault('__builtins__',__builtin__)
231
238
232 if user_global_ns is None:
239 if user_global_ns is None:
@@ -970,8 +977,20 b' class InteractiveShell(Component, Magic):'
970 # user_ns, and we sync that contents into user_config_ns so that these
977 # user_ns, and we sync that contents into user_config_ns so that these
971 # initial variables aren't shown by %who. After the sync, we add the
978 # initial variables aren't shown by %who. After the sync, we add the
972 # rest of what we *do* want the user to see with %who even on a new
979 # rest of what we *do* want the user to see with %who even on a new
973 # session.
980 # session (probably nothing, so theye really only see their own stuff)
974 ns = {}
981
982 # The user dict must *always* have a __builtin__ reference to the
983 # Python standard __builtin__ namespace, which must be imported.
984 # This is so that certain operations in prompt evaluation can be
985 # reliably executed with builtins. Note that we can NOT use
986 # __builtins__ (note the 's'), because that can either be a dict or a
987 # module, and can even mutate at runtime, depending on the context
988 # (Python makes no guarantees on it). In contrast, __builtin__ is
989 # always a module object, though it must be explicitly imported.
990
991 # For more details:
992 # http://mail.python.org/pipermail/python-dev/2001-April/014068.html
993 ns = dict(__builtin__ = __builtin__)
975
994
976 # Put 'help' in the user namespace
995 # Put 'help' in the user namespace
977 try:
996 try:
@@ -987,20 +1006,23 b' class InteractiveShell(Component, Magic):'
987
1006
988 ns['_sh'] = shadowns
1007 ns['_sh'] = shadowns
989
1008
990 # Sync what we've added so far to user_config_ns so these aren't seen
1009 # user aliases to input and output histories. These shouldn't show up
991 # by %who
1010 # in %who, as they can have very large reprs.
992 self.user_config_ns.update(ns)
993
994 # Now, continue adding more contents
995
996 # user aliases to input and output histories
997 ns['In'] = self.input_hist
1011 ns['In'] = self.input_hist
998 ns['Out'] = self.output_hist
1012 ns['Out'] = self.output_hist
999
1013
1000 # Store myself as the public api!!!
1014 # Store myself as the public api!!!
1001 ns['get_ipython'] = self.get_ipython
1015 ns['get_ipython'] = self.get_ipython
1016
1017 # Sync what we've added so far to user_config_ns so these aren't seen
1018 # by %who
1019 self.user_config_ns.update(ns)
1020
1021 # Anything put into ns now would show up in %who. Think twice before
1022 # putting anything here, as we really want %who to show the user their
1023 # stuff, not our variables.
1002
1024
1003 # And update the real user's namespace
1025 # Finally, update the real user's namespace
1004 self.user_ns.update(ns)
1026 self.user_ns.update(ns)
1005
1027
1006
1028
@@ -2537,6 +2537,9 b' Defaulting color scheme to \'NoColor\'"""'
2537
2537
2538 self.shell.ask_exit()
2538 self.shell.ask_exit()
2539
2539
2540 # Add aliases as magics so all common forms work: exit, quit, Exit, Quit.
2541 magic_exit = magic_quit = magic_Quit = magic_Exit
2542
2540 #......................................................................
2543 #......................................................................
2541 # Functions to implement unix shell-type things
2544 # Functions to implement unix shell-type things
2542
2545
@@ -131,8 +131,14 b' prompt_specials_color = {'
131 # Prompt/history count, with the actual digits replaced by dots. Used
131 # Prompt/history count, with the actual digits replaced by dots. Used
132 # mainly in continuation prompts (prompt_in2)
132 # mainly in continuation prompts (prompt_in2)
133 #r'\D': '${"."*len(str(self.cache.prompt_count))}',
133 #r'\D': '${"."*len(str(self.cache.prompt_count))}',
134 # More robust form of the above expression, that uses __builtins__
134
135 r'\D': '${"."*__builtins__.len(__builtins__.str(self.cache.prompt_count))}',
135 # More robust form of the above expression, that uses the __builtin__
136 # module. Note that we can NOT use __builtins__ (note the 's'), because
137 # that can either be a dict or a module, and can even mutate at runtime,
138 # depending on the context (Python makes no guarantees on it). In
139 # contrast, __builtin__ is always a module object, though it must be
140 # explicitly imported.
141 r'\D': '${"."*__builtin__.len(__builtin__.str(self.cache.prompt_count))}',
136
142
137 # Current working directory
143 # Current working directory
138 r'\w': '${os.getcwd()}',
144 r'\w': '${os.getcwd()}',
@@ -215,6 +221,7 b' def str_safe(arg):'
215 out = '<ERROR: %s>' % msg
221 out = '<ERROR: %s>' % msg
216 except Exception,msg:
222 except Exception,msg:
217 out = '<ERROR: %s>' % msg
223 out = '<ERROR: %s>' % msg
224 #raise # dbg
218 return out
225 return out
219
226
220 class BasePrompt(object):
227 class BasePrompt(object):
@@ -23,7 +23,7 b" name = 'ipython'"
23 development = True # change this to False to do a release
23 development = True # change this to False to do a release
24 version_base = '0.11'
24 version_base = '0.11'
25 branch = 'ipython'
25 branch = 'ipython'
26 revision = '1321'
26 revision = '1346'
27
27
28 if development:
28 if development:
29 if branch == 'ipython':
29 if branch == 'ipython':
@@ -13,7 +13,7 b' class C(object):'
13
13
14 def __del__(self):
14 def __del__(self):
15 print 'tclass.py: deleting object:',self.name
15 print 'tclass.py: deleting object:',self.name
16
16 sys.stdout.flush()
17
17
18 try:
18 try:
19 name = sys.argv[1]
19 name = sys.argv[1]
@@ -28,3 +28,4 b' else:'
28 # This next print statement is NOT debugging, we're making the check on a
28 # This next print statement is NOT debugging, we're making the check on a
29 # completely separate process so we verify by capturing stdout:
29 # completely separate process so we verify by capturing stdout:
30 print 'ARGV 1-:', sys.argv[1:]
30 print 'ARGV 1-:', sys.argv[1:]
31 sys.stdout.flush()
@@ -153,7 +153,6 b' def doctest_hist_op():'
153 >>> ss
153 >>> ss
154 <...s instance at ...>
154 <...s instance at ...>
155 >>>
155 >>>
156 >>> get_ipython().magic("hist -op")
157 """
156 """
158
157
159 def test_shist():
158 def test_shist():
@@ -67,7 +67,7 b' def doctest_run_builtins():'
67
67
68 In [6]: t1 = type(__builtins__)
68 In [6]: t1 = type(__builtins__)
69
69
70 In [7]: %run "$fname"
70 In [7]: %run $fname
71
71
72 In [7]: f.close()
72 In [7]: f.close()
73
73
@@ -101,7 +101,7 b' class TestMagicRunPass(tt.TempFileMixin):'
101 _ip = get_ipython()
101 _ip = get_ipython()
102 # This fails on Windows if self.tmpfile.name has spaces or "~" in it.
102 # This fails on Windows if self.tmpfile.name has spaces or "~" in it.
103 # See below and ticket https://bugs.launchpad.net/bugs/366353
103 # See below and ticket https://bugs.launchpad.net/bugs/366353
104 _ip.magic('run "%s"' % self.fname)
104 _ip.magic('run %s' % self.fname)
105
105
106 def test_builtins_id(self):
106 def test_builtins_id(self):
107 """Check that %run doesn't damage __builtins__ """
107 """Check that %run doesn't damage __builtins__ """
@@ -20,7 +20,7 b' import sys'
20 from nose.tools import assert_equal
20 from nose.tools import assert_equal
21
21
22 from IPython.frontend.prefilterfrontend import PrefilterFrontEnd
22 from IPython.frontend.prefilterfrontend import PrefilterFrontEnd
23 from IPython.core.ipapi import get as get_ipython0
23 from IPython.testing.globalipapp import get_ipython
24 from IPython.testing.tools import default_argv
24 from IPython.testing.tools import default_argv
25
25
26 #-----------------------------------------------------------------------------
26 #-----------------------------------------------------------------------------
@@ -60,7 +60,7 b' def isolate_ipython0(func):'
60 with arguments.
60 with arguments.
61 """
61 """
62 def my_func():
62 def my_func():
63 ip0 = get_ipython0()
63 ip0 = get_ipython()
64 if ip0 is None:
64 if ip0 is None:
65 return func()
65 return func()
66 # We have a real ipython running...
66 # We have a real ipython running...
@@ -169,7 +169,7 b' def test_magic():'
169 f.input_buffer += '%who'
169 f.input_buffer += '%who'
170 f._on_enter()
170 f._on_enter()
171 out_value = f.out.getvalue()
171 out_value = f.out.getvalue()
172 assert_equal(out_value, 'In\tOut\tget_ipython\t\n')
172 assert_equal(out_value, 'Interactive namespace is empty.\n')
173
173
174
174
175 @isolate_ipython0
175 @isolate_ipython0
@@ -22,4 +22,4 b' __docformat__ = "restructuredtext en"'
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 from IPython.kernel.error import TaskRejectError No newline at end of file
25 from IPython.kernel.error import TaskRejectError
@@ -20,6 +20,7 b' from __future__ import with_statement'
20 import os
20 import os
21 import shutil
21 import shutil
22 import sys
22 import sys
23 import warnings
23
24
24 from twisted.python import log
25 from twisted.python import log
25
26
@@ -27,13 +28,25 b' from IPython.core import release'
27 from IPython.config.loader import PyFileConfigLoader
28 from IPython.config.loader import PyFileConfigLoader
28 from IPython.core.application import Application
29 from IPython.core.application import Application
29 from IPython.core.component import Component
30 from IPython.core.component import Component
31 from IPython.utils.genutils import get_ipython_dir, get_ipython_package_dir
30 from IPython.utils.traitlets import Unicode, Bool
32 from IPython.utils.traitlets import Unicode, Bool
31 from IPython.utils import genutils
33 from IPython.utils import genutils
32
34
33 #-----------------------------------------------------------------------------
35 #-----------------------------------------------------------------------------
34 # Imports
36 # Warnings control
35 #-----------------------------------------------------------------------------
37 #-----------------------------------------------------------------------------
38 # Twisted generates annoying warnings with Python 2.6, as will do other code
39 # that imports 'sets' as of today
40 warnings.filterwarnings('ignore', 'the sets module is deprecated',
41 DeprecationWarning )
36
42
43 # This one also comes from Twisted
44 warnings.filterwarnings('ignore', 'the sha module is deprecated',
45 DeprecationWarning)
46
47 #-----------------------------------------------------------------------------
48 # Classes and functions
49 #-----------------------------------------------------------------------------
37
50
38 class ClusterDirError(Exception):
51 class ClusterDirError(Exception):
39 pass
52 pass
@@ -352,9 +365,6 b' class ApplicationWithClusterDir(Application):'
352 self.default_config.Global.cluster_dir = self.cluster_dir
365 self.default_config.Global.cluster_dir = self.cluster_dir
353 self.command_line_config.Global.cluster_dir = self.cluster_dir
366 self.command_line_config.Global.cluster_dir = self.cluster_dir
354
367
355 # Set the search path to the cluster directory
356 self.config_file_paths = (self.cluster_dir,)
357
358 def find_config_file_name(self):
368 def find_config_file_name(self):
359 """Find the config file name for this application."""
369 """Find the config file name for this application."""
360 # For this type of Application it should be set as a class attribute.
370 # For this type of Application it should be set as a class attribute.
@@ -362,8 +372,11 b' class ApplicationWithClusterDir(Application):'
362 self.log.critical("No config filename found")
372 self.log.critical("No config filename found")
363
373
364 def find_config_file_paths(self):
374 def find_config_file_paths(self):
365 # Set the search path to the cluster directory
375 # Include our own config directory last, so that users can still find
366 self.config_file_paths = (self.cluster_dir,)
376 # our shipped copies of builtin config files even if they don't have
377 # them in their ipython cluster directory.
378 conf_dir = os.path.join(get_ipython_package_dir(), 'config', 'default')
379 self.config_file_paths = (self.cluster_dir, conf_dir)
367
380
368 def pre_construct(self):
381 def pre_construct(self):
369 # The log and security dirs were set earlier, but here we put them
382 # The log and security dirs were set earlier, but here we put them
@@ -17,8 +17,6 b' __test__ = {}'
17 #-------------------------------------------------------------------------------
17 #-------------------------------------------------------------------------------
18 # Imports
18 # Imports
19 #-------------------------------------------------------------------------------
19 #-------------------------------------------------------------------------------
20 from twisted.python import failure
21
22 from IPython.kernel.core import error
20 from IPython.kernel.core import error
23
21
24 #-------------------------------------------------------------------------------
22 #-------------------------------------------------------------------------------
@@ -179,6 +177,8 b' class CompositeError(KernelError):'
179 raise et, ev, etb
177 raise et, ev, etb
180
178
181 def collect_exceptions(rlist, method):
179 def collect_exceptions(rlist, method):
180 from twisted.python import failure
181
182 elist = []
182 elist = []
183 for r in rlist:
183 for r in rlist:
184 if isinstance(r, failure.Failure):
184 if isinstance(r, failure.Failure):
@@ -3,6 +3,22 b''
3 """IPython Test Suite Runner.
3 """IPython Test Suite Runner.
4 """
4 """
5
5
6 from IPython.testing import iptest
6 # The tests can't even run if nose isn't available, so might as well give the
7 # user a civilized error message in that case.
7
8
8 iptest.main()
9 try:
10 import nose
11 except ImportError:
12 error = """\
13 ERROR: The IPython test suite requires nose to run.
14
15 Please install nose on your system first and try again.
16 For information on installing nose, see:
17 http://somethingaboutorange.com/mrl/projects/nose
18
19 Exiting."""
20 import sys
21 print >> sys.stderr, error
22 else:
23 from IPython.testing import iptest
24 iptest.main()
@@ -16,8 +16,6 b' 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 from __future__ import absolute_import
20
21 #-----------------------------------------------------------------------------
19 #-----------------------------------------------------------------------------
22 # Module imports
20 # Module imports
23 #-----------------------------------------------------------------------------
21 #-----------------------------------------------------------------------------
@@ -25,6 +23,7 b' from __future__ import absolute_import'
25 # Stdlib
23 # Stdlib
26 import os
24 import os
27 import os.path as path
25 import os.path as path
26 import platform
28 import signal
27 import signal
29 import sys
28 import sys
30 import subprocess
29 import subprocess
@@ -32,24 +31,46 b' import tempfile'
32 import time
31 import time
33 import warnings
32 import warnings
34
33
34
35 # Ugly, but necessary hack to ensure the test suite finds our version of
36 # IPython and not a possibly different one that may exist system-wide.
37 # Note that this must be done here, so the imports that come next work
38 # correctly even if IPython isn't installed yet.
39 p = os.path
40 ippath = p.abspath(p.join(p.dirname(__file__),'..','..'))
41 sys.path.insert(0, ippath)
42
35 # Note: monkeypatch!
43 # Note: monkeypatch!
36 # We need to monkeypatch a small problem in nose itself first, before importing
44 # We need to monkeypatch a small problem in nose itself first, before importing
37 # it for actual use. This should get into nose upstream, but its release cycle
45 # it for actual use. This should get into nose upstream, but its release cycle
38 # is slow and we need it for our parametric tests to work correctly.
46 # is slow and we need it for our parametric tests to work correctly.
39 from . import nosepatch
47 from IPython.testing import nosepatch
40 # Now, proceed to import nose itself
48 # Now, proceed to import nose itself
41 import nose.plugins.builtin
49 import nose.plugins.builtin
42 from nose.core import TestProgram
50 from nose.core import TestProgram
43
51
44 # Our own imports
52 # Our own imports
53 from IPython.core import release
45 from IPython.utils import genutils
54 from IPython.utils import genutils
46 from IPython.utils.platutils import find_cmd, FindCmdError
55 from IPython.utils.platutils import find_cmd, FindCmdError
47 from . import globalipapp
56 from IPython.testing import globalipapp
48 from . import tools
57 from IPython.testing import tools
49 from .plugin.ipdoctest import IPythonDoctest
58 from IPython.testing.plugin.ipdoctest import IPythonDoctest
50
59
51 pjoin = path.join
60 pjoin = path.join
52
61
62
63 #-----------------------------------------------------------------------------
64 # Globals
65 #-----------------------------------------------------------------------------
66
67 # By default, we assume IPython has been installed. But if the test suite is
68 # being run from a source tree that has NOT been installed yet, this flag can
69 # be set to False by the entry point scripts, to let us know that we must call
70 # the source tree versions of the scripts which manipulate sys.path instead of
71 # assuming that things exist system-wide.
72 INSTALLED = True
73
53 #-----------------------------------------------------------------------------
74 #-----------------------------------------------------------------------------
54 # Warnings control
75 # Warnings control
55 #-----------------------------------------------------------------------------
76 #-----------------------------------------------------------------------------
@@ -62,6 +83,10 b" warnings.filterwarnings('ignore', 'the sets module is deprecated',"
62 warnings.filterwarnings('ignore', 'the sha module is deprecated',
83 warnings.filterwarnings('ignore', 'the sha module is deprecated',
63 DeprecationWarning)
84 DeprecationWarning)
64
85
86 # Wx on Fedora11 spits these out
87 warnings.filterwarnings('ignore', 'wxPython/wxWidgets release number mismatch',
88 UserWarning)
89
65 #-----------------------------------------------------------------------------
90 #-----------------------------------------------------------------------------
66 # Logic for skipping doctests
91 # Logic for skipping doctests
67 #-----------------------------------------------------------------------------
92 #-----------------------------------------------------------------------------
@@ -70,22 +95,59 b' def test_for(mod):'
70 """Test to see if mod is importable."""
95 """Test to see if mod is importable."""
71 try:
96 try:
72 __import__(mod)
97 __import__(mod)
73 except ImportError:
98 except (ImportError, RuntimeError):
99 # GTK reports Runtime error if it can't be initialized even if it's
100 # importable.
74 return False
101 return False
75 else:
102 else:
76 return True
103 return True
77
104
105 # Global dict where we can store information on what we have and what we don't
106 # have available at test run time
107 have = {}
108
109 have['curses'] = test_for('_curses')
110 have['wx'] = test_for('wx')
111 have['wx.aui'] = test_for('wx.aui')
112 have['zope.interface'] = test_for('zope.interface')
113 have['twisted'] = test_for('twisted')
114 have['foolscap'] = test_for('foolscap')
115 have['objc'] = test_for('objc')
116 have['pexpect'] = test_for('pexpect')
117 have['gtk'] = test_for('gtk')
118 have['gobject'] = test_for('gobject')
119
120 #-----------------------------------------------------------------------------
121 # Functions and classes
122 #-----------------------------------------------------------------------------
123
124 def report():
125 """Return a string with a summary report of test-related variables."""
126
127 out = [ genutils.sys_info() ]
128
129 out.append('\nRunning from an installed IPython: %s\n' % INSTALLED)
130
131 avail = []
132 not_avail = []
78
133
79 have_curses = test_for('_curses')
134 for k, is_avail in have.items():
80 have_wx = test_for('wx')
135 if is_avail:
81 have_wx_aui = test_for('wx.aui')
136 avail.append(k)
82 have_zi = test_for('zope.interface')
137 else:
83 have_twisted = test_for('twisted')
138 not_avail.append(k)
84 have_foolscap = test_for('foolscap')
139
85 have_objc = test_for('objc')
140 if avail:
86 have_pexpect = test_for('pexpect')
141 out.append('\nTools and libraries available at test time:\n')
87 have_gtk = test_for('gtk')
142 avail.sort()
88 have_gobject = test_for('gobject')
143 out.append(' ' + ' '.join(avail)+'\n')
144
145 if not_avail:
146 out.append('\nTools and libraries NOT available at test time:\n')
147 not_avail.sort()
148 out.append(' ' + ' '.join(not_avail)+'\n')
149
150 return ''.join(out)
89
151
90
152
91 def make_exclude():
153 def make_exclude():
@@ -103,6 +165,10 b' def make_exclude():'
103
165
104 exclusions = [ipjoin('external'),
166 exclusions = [ipjoin('external'),
105 ipjoin('frontend', 'process', 'winprocess.py'),
167 ipjoin('frontend', 'process', 'winprocess.py'),
168 # Deprecated old Shell and iplib modules, skip to avoid
169 # warnings
170 ipjoin('Shell'),
171 ipjoin('iplib'),
106 pjoin('IPython_doctest_plugin'),
172 pjoin('IPython_doctest_plugin'),
107 ipjoin('quarantine'),
173 ipjoin('quarantine'),
108 ipjoin('deathrow'),
174 ipjoin('deathrow'),
@@ -118,18 +184,18 b' def make_exclude():'
118 ipjoin('config', 'profile'),
184 ipjoin('config', 'profile'),
119 ]
185 ]
120
186
121 if not have_wx:
187 if not have['wx']:
122 exclusions.append(ipjoin('gui'))
188 exclusions.append(ipjoin('gui'))
123 exclusions.append(ipjoin('frontend', 'wx'))
189 exclusions.append(ipjoin('frontend', 'wx'))
124 exclusions.append(ipjoin('lib', 'inputhookwx'))
190 exclusions.append(ipjoin('lib', 'inputhookwx'))
125
191
126 if not have_gtk or not have_gobject:
192 if not have['gtk'] or not have['gobject']:
127 exclusions.append(ipjoin('lib', 'inputhookgtk'))
193 exclusions.append(ipjoin('lib', 'inputhookgtk'))
128
194
129 if not have_wx_aui:
195 if not have['wx.aui']:
130 exclusions.append(ipjoin('gui', 'wx', 'wxIPython'))
196 exclusions.append(ipjoin('gui', 'wx', 'wxIPython'))
131
197
132 if not have_objc:
198 if not have['objc']:
133 exclusions.append(ipjoin('frontend', 'cocoa'))
199 exclusions.append(ipjoin('frontend', 'cocoa'))
134
200
135 if not sys.platform == 'win32':
201 if not sys.platform == 'win32':
@@ -144,14 +210,14 b' def make_exclude():'
144 if not os.name == 'posix':
210 if not os.name == 'posix':
145 exclusions.append(ipjoin('utils', 'platutils_posix'))
211 exclusions.append(ipjoin('utils', 'platutils_posix'))
146
212
147 if not have_pexpect:
213 if not have['pexpect']:
148 exclusions.extend([ipjoin('scripts', 'irunner'),
214 exclusions.extend([ipjoin('scripts', 'irunner'),
149 ipjoin('lib', 'irunner')])
215 ipjoin('lib', 'irunner')])
150
216
151 # This is scary. We still have things in frontend and testing that
217 # This is scary. We still have things in frontend and testing that
152 # are being tested by nose that use twisted. We need to rethink
218 # are being tested by nose that use twisted. We need to rethink
153 # how we are isolating dependencies in testing.
219 # how we are isolating dependencies in testing.
154 if not (have_twisted and have_zi and have_foolscap):
220 if not (have['twisted'] and have['zope.interface'] and have['foolscap']):
155 exclusions.extend(
221 exclusions.extend(
156 [ipjoin('frontend', 'asyncfrontendbase'),
222 [ipjoin('frontend', 'asyncfrontendbase'),
157 ipjoin('frontend', 'prefilterfrontend'),
223 ipjoin('frontend', 'prefilterfrontend'),
@@ -173,10 +239,6 b' def make_exclude():'
173 return exclusions
239 return exclusions
174
240
175
241
176 #-----------------------------------------------------------------------------
177 # Functions and classes
178 #-----------------------------------------------------------------------------
179
180 class IPTester(object):
242 class IPTester(object):
181 """Call that calls iptest or trial in a subprocess.
243 """Call that calls iptest or trial in a subprocess.
182 """
244 """
@@ -189,24 +251,27 b' class IPTester(object):'
189 #: list, process ids of subprocesses we start (for cleanup)
251 #: list, process ids of subprocesses we start (for cleanup)
190 pids = None
252 pids = None
191
253
192 def __init__(self,runner='iptest',params=None):
254 def __init__(self, runner='iptest', params=None):
193 """Create new test runner."""
255 """Create new test runner."""
256 p = os.path
194 if runner == 'iptest':
257 if runner == 'iptest':
195 # Find our own 'iptest' script OS-level entry point
258 if INSTALLED:
196 try:
259 self.runner = tools.cmd2argv(
197 iptest_path = os.path.abspath(find_cmd('iptest'))
260 p.abspath(find_cmd('iptest'))) + sys.argv[1:]
198 except FindCmdError:
261 else:
199 # Script not installed (may be the case for testing situations
262 # Find our own 'iptest' script OS-level entry point. Don't
200 # that are running from a source tree only), pull from internal
263 # look system-wide, so we are sure we pick up *this one*. And
201 # path:
264 # pass through to subprocess call our own sys.argv
202 pak_dir = os.path.abspath(genutils.get_ipython_package_dir())
265 ippath = p.abspath(p.join(p.dirname(__file__),'..','..'))
203 iptest_path = pjoin(pak_dir, 'scripts', 'iptest')
266 script = p.join(ippath, 'iptest.py')
204 self.runner = tools.cmd2argv(iptest_path) + ['-v']
267 self.runner = tools.cmd2argv(script) + sys.argv[1:]
268
205 else:
269 else:
206 self.runner = tools.cmd2argv(os.path.abspath(find_cmd('trial')))
270 # For trial, it needs to be installed system-wide
271 self.runner = tools.cmd2argv(p.abspath(find_cmd('trial')))
207 if params is None:
272 if params is None:
208 params = []
273 params = []
209 if isinstance(params,str):
274 if isinstance(params, str):
210 params = [params]
275 params = [params]
211 self.params = params
276 self.params = params
212
277
@@ -228,6 +293,7 b' class IPTester(object):'
228 return os.system(' '.join(self.call_args))
293 return os.system(' '.join(self.call_args))
229 else:
294 else:
230 def _run_cmd(self):
295 def _run_cmd(self):
296 #print >> sys.stderr, '*** CMD:', ' '.join(self.call_args) # dbg
231 subp = subprocess.Popen(self.call_args)
297 subp = subprocess.Popen(self.call_args)
232 self.pids.append(subp.pid)
298 self.pids.append(subp.pid)
233 # If this fails, the pid will be left in self.pids and cleaned up
299 # If this fails, the pid will be left in self.pids and cleaned up
@@ -266,31 +332,34 b' def make_runners():'
266 """Define the top-level packages that need to be tested.
332 """Define the top-level packages that need to be tested.
267 """
333 """
268
334
269 nose_packages = ['config', 'core', 'extensions', 'frontend', 'lib',
335 # Packages to be tested via nose, that only depend on the stdlib
270 'scripts', 'testing', 'utils',
336 nose_pkg_names = ['config', 'core', 'extensions', 'frontend', 'lib',
271 # Note that we list the kernel here, though the bulk of it
337 'scripts', 'testing', 'utils' ]
272 # is twisted-based, because nose picks up doctests that
338 # The machinery in kernel needs twisted for real testing
273 # twisted doesn't.
339 trial_pkg_names = []
274 'kernel']
275 trial_packages = ['kernel']
276
277 if have_wx:
278 nose_packages.append('gui')
279
280 #nose_packages = ['core'] # dbg
281 #trial_packages = [] # dbg
282
340
283 nose_packages = ['IPython.%s' % m for m in nose_packages ]
341 if have['wx']:
284 trial_packages = ['IPython.%s' % m for m in trial_packages ]
342 nose_pkg_names.append('gui')
285
343
286 # Make runners, most with nose
287 nose_testers = [IPTester(params=v) for v in nose_packages]
288 runners = dict(zip(nose_packages, nose_testers))
289 # And add twisted ones if conditions are met
344 # And add twisted ones if conditions are met
290 if have_zi and have_twisted and have_foolscap:
345 if have['zope.interface'] and have['twisted'] and have['foolscap']:
291 trial_testers = [IPTester('trial',params=v) for v in trial_packages]
346 # Note that we list the kernel here, though the bulk of it is
292 runners.update(dict(zip(trial_packages,trial_testers)))
347 # twisted-based, because nose picks up doctests that twisted doesn't.
293
348 nose_pkg_names.append('kernel')
349 trial_pkg_names.append('kernel')
350
351 # For debugging this code, only load quick stuff
352 #nose_pkg_names = ['core', 'extensions'] # dbg
353 #trial_pkg_names = [] # dbg
354
355 # Make fully qualified package names prepending 'IPython.' to our name lists
356 nose_packages = ['IPython.%s' % m for m in nose_pkg_names ]
357 trial_packages = ['IPython.%s' % m for m in trial_pkg_names ]
358
359 # Make runners
360 runners = [ (v, IPTester('iptest', params=v)) for v in nose_packages ]
361 runners.extend([ (v, IPTester('trial', params=v)) for v in trial_packages ])
362
294 return runners
363 return runners
295
364
296
365
@@ -305,15 +374,14 b' def run_iptest():'
305 warnings.filterwarnings('ignore',
374 warnings.filterwarnings('ignore',
306 'This will be removed soon. Use IPython.testing.util instead')
375 'This will be removed soon. Use IPython.testing.util instead')
307
376
308 argv = sys.argv + [ '--detailed-errors',
377 argv = sys.argv + [ '--detailed-errors', # extra info in tracebacks
378
309 # Loading ipdoctest causes problems with Twisted, but
379 # Loading ipdoctest causes problems with Twisted, but
310 # our test suite runner now separates things and runs
380 # our test suite runner now separates things and runs
311 # all Twisted tests with trial.
381 # all Twisted tests with trial.
312 '--with-ipdoctest',
382 '--with-ipdoctest',
313 '--ipdoctest-tests','--ipdoctest-extension=txt',
383 '--ipdoctest-tests','--ipdoctest-extension=txt',
314
384
315 #'-x','-s', # dbg
316
317 # We add --exe because of setuptools' imbecility (it
385 # We add --exe because of setuptools' imbecility (it
318 # blindly does chmod +x on ALL files). Nose does the
386 # blindly does chmod +x on ALL files). Nose does the
319 # right thing and it tries to avoid executables,
387 # right thing and it tries to avoid executables,
@@ -323,21 +391,19 b' def run_iptest():'
323 '--exe',
391 '--exe',
324 ]
392 ]
325
393
326 # Detect if any tests were required by explicitly calling an IPython
394 if nose.__version__ >= '0.11':
327 # submodule or giving a specific path
395 # I don't fully understand why we need this one, but depending on what
328 has_tests = False
396 # directory the test suite is run from, if we don't give it, 0 tests
329 for arg in sys.argv:
397 # get run. Specifically, if the test suite is run from the source dir
330 if 'IPython' in arg or arg.endswith('.py') or \
398 # with an argument (like 'iptest.py IPython.core', 0 tests are run,
331 (':' in arg and '.py' in arg):
399 # even if the same call done in this directory works fine). It appears
332 has_tests = True
400 # that if the requested package is in the current dir, nose bails early
333 break
401 # by default. Since it's otherwise harmless, leave it in by default
334
402 # for nose >= 0.11, though unfortunately nose 0.10 doesn't support it.
335 # If nothing was specifically requested, test full IPython
403 argv.append('--traverse-namespace')
336 if not has_tests:
404
337 argv.append('IPython')
405 # Construct list of plugins, omitting the existing doctest plugin, which
338
406 # ours replaces (and extends).
339 ## # Construct list of plugins, omitting the existing doctest plugin, which
340 ## # ours replaces (and extends).
341 plugins = [IPythonDoctest(make_exclude())]
407 plugins = [IPythonDoctest(make_exclude())]
342 for p in nose.plugins.builtin.plugins:
408 for p in nose.plugins.builtin.plugins:
343 plug = p()
409 plug = p()
@@ -348,7 +414,7 b' def run_iptest():'
348 # We need a global ipython running in this process
414 # We need a global ipython running in this process
349 globalipapp.start_ipython()
415 globalipapp.start_ipython()
350 # Now nose can run
416 # Now nose can run
351 TestProgram(argv=argv,plugins=plugins)
417 TestProgram(argv=argv, plugins=plugins)
352
418
353
419
354 def run_iptestall():
420 def run_iptestall():
@@ -371,15 +437,15 b' def run_iptestall():'
371 os.chdir(testdir)
437 os.chdir(testdir)
372
438
373 # Run all test runners, tracking execution time
439 # Run all test runners, tracking execution time
374 failed = {}
440 failed = []
375 t_start = time.time()
441 t_start = time.time()
376 try:
442 try:
377 for name,runner in runners.iteritems():
443 for (name, runner) in runners:
378 print '*'*77
444 print '*'*70
379 print 'IPython test group:',name
445 print 'IPython test group:',name
380 res = runner.run()
446 res = runner.run()
381 if res:
447 if res:
382 failed[name] = res
448 failed.append( (name, runner) )
383 finally:
449 finally:
384 os.chdir(curdir)
450 os.chdir(curdir)
385 t_end = time.time()
451 t_end = time.time()
@@ -388,17 +454,19 b' def run_iptestall():'
388 nfail = len(failed)
454 nfail = len(failed)
389 # summarize results
455 # summarize results
390 print
456 print
391 print '*'*77
457 print '*'*70
458 print 'Test suite completed for system with the following information:'
459 print report()
392 print 'Ran %s test groups in %.3fs' % (nrunners, t_tests)
460 print 'Ran %s test groups in %.3fs' % (nrunners, t_tests)
393 print
461 print
462 print 'Status:'
394 if not failed:
463 if not failed:
395 print 'OK'
464 print 'OK'
396 else:
465 else:
397 # If anything went wrong, point out what command to rerun manually to
466 # If anything went wrong, point out what command to rerun manually to
398 # see the actual errors and individual summary
467 # see the actual errors and individual summary
399 print 'ERROR - %s out of %s test groups failed.' % (nfail, nrunners)
468 print 'ERROR - %s out of %s test groups failed.' % (nfail, nrunners)
400 for name in failed:
469 for name, failed_runner in failed:
401 failed_runner = runners[name]
402 print '-'*40
470 print '-'*40
403 print 'Runner failed:',name
471 print 'Runner failed:',name
404 print 'You may wish to rerun this one individually, with:'
472 print 'You may wish to rerun this one individually, with:'
@@ -407,13 +475,13 b' def run_iptestall():'
407
475
408
476
409 def main():
477 def main():
410 if len(sys.argv) == 1:
478 for arg in sys.argv[1:]:
411 run_iptestall()
479 if arg.startswith('IPython'):
412 else:
480 # This is in-process
413 if sys.argv[1] == 'all':
414 run_iptestall()
415 else:
416 run_iptest()
481 run_iptest()
482 else:
483 # This starts subprocesses
484 run_iptestall()
417
485
418
486
419 if __name__ == '__main__':
487 if __name__ == '__main__':
@@ -114,11 +114,12 b' def test_skip_dt_decorator():'
114 # Fetch the docstring from doctest_bad after decoration.
114 # Fetch the docstring from doctest_bad after decoration.
115 val = doctest_bad.__doc__
115 val = doctest_bad.__doc__
116
116
117 assert check==val,"doctest_bad docstrings don't match"
117 nt.assert_equal(check,val,"doctest_bad docstrings don't match")
118
118
119
119 # Doctest skipping should work for class methods too
120 # Doctest skipping should work for class methods too
120 class foo(object):
121 class FooClass(object):
121 """Foo
122 """FooClass
122
123
123 Example:
124 Example:
124
125
@@ -128,22 +129,22 b' class foo(object):'
128
129
129 @dec.skip_doctest
130 @dec.skip_doctest
130 def __init__(self,x):
131 def __init__(self,x):
131 """Make a foo.
132 """Make a FooClass.
132
133
133 Example:
134 Example:
134
135
135 >>> f = foo(3)
136 >>> f = FooClass(3)
136 junk
137 junk
137 """
138 """
138 print 'Making a foo.'
139 print 'Making a FooClass.'
139 self.x = x
140 self.x = x
140
141
141 @dec.skip_doctest
142 @dec.skip_doctest
142 def bar(self,y):
143 def bar(self,y):
143 """Example:
144 """Example:
144
145
145 >>> f = foo(3)
146 >>> ff = FooClass(3)
146 >>> f.bar(0)
147 >>> ff.bar(0)
147 boom!
148 boom!
148 >>> 1/0
149 >>> 1/0
149 bam!
150 bam!
@@ -153,15 +154,14 b' class foo(object):'
153 def baz(self,y):
154 def baz(self,y):
154 """Example:
155 """Example:
155
156
156 >>> f = foo(3)
157 >>> ff2 = FooClass(3)
157 Making a foo.
158 Making a FooClass.
158 >>> f.baz(3)
159 >>> ff2.baz(3)
159 True
160 True
160 """
161 """
161 return self.x==y
162 return self.x==y
162
163
163
164
164
165 def test_skip_dt_decorator2():
165 def test_skip_dt_decorator2():
166 """Doctest-skipping decorator should preserve function signature.
166 """Doctest-skipping decorator should preserve function signature.
167 """
167 """
@@ -49,6 +49,13 b' from . import decorators as dec'
49 # Globals
49 # Globals
50 #-----------------------------------------------------------------------------
50 #-----------------------------------------------------------------------------
51
51
52 # By default, we assume IPython has been installed. But if the test suite is
53 # being run from a source tree that has NOT been installed yet, this flag can
54 # be set to False by the entry point scripts, to let us know that we must call
55 # the source tree versions of the scripts which manipulate sys.path instead of
56 # assuming that things exist system-wide.
57 INSTALLED = True
58
52 # Make a bunch of nose.tools assert wrappers that can be used in test
59 # 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.
60 # generators. This will expose an assert* function for each one in nose.tools.
54
61
@@ -209,14 +216,10 b" def temp_pyfile(src, ext='.py'):"
209 def default_argv():
216 def default_argv():
210 """Return a valid default argv for creating testing instances of ipython"""
217 """Return a valid default argv for creating testing instances of ipython"""
211
218
212 # Get the install directory for the user configuration and tell ipython to
219 return ['--quick', # so no config file is loaded
213 # use the default profile from there.
220 # Other defaults to minimize side effects on stdout
214 from IPython.config import default
221 '--colors=NoColor', '--no-term-title','--no-banner',
215 ipcdir = os.path.dirname(default.__file__)
222 '--autocall=0']
216 ipconf = os.path.join(ipcdir,'ipython_config.py')
217 return ['--colors=NoColor', '--no-term-title','--no-banner',
218 '--config-file="%s"' % ipconf, '--autocall=0',
219 '--prompt-out=""']
220
223
221
224
222 def ipexec(fname, options=None):
225 def ipexec(fname, options=None):
@@ -240,22 +243,32 b' def ipexec(fname, options=None):'
240 (stdout, stderr) of ipython subprocess.
243 (stdout, stderr) of ipython subprocess.
241 """
244 """
242 if options is None: options = []
245 if options is None: options = []
243 cmdargs = ' '.join(default_argv() + options)
246
247 # For these subprocess calls, eliminate all prompt printing so we only see
248 # output from script execution
249 prompt_opts = ['--prompt-in1=""', '--prompt-in2=""', '--prompt-out=""']
250 cmdargs = ' '.join(default_argv() + prompt_opts + options)
244
251
245 _ip = get_ipython()
252 _ip = get_ipython()
246 test_dir = os.path.dirname(__file__)
253 test_dir = os.path.dirname(__file__)
254
247 # Find the ipython script from the package we're using, so that the test
255 # 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
256 # suite can be run from the source tree without an installed IPython
249 ipython_package_dir = genutils.get_ipython_package_dir()
257 p = os.path
250 ipython_script = os.path.join(ipython_package_dir,'scripts','ipython')
258 if INSTALLED:
251 ipython_cmd = 'python "%s"' % ipython_script
259 ipython_cmd = platutils.find_cmd('ipython')
260 else:
261 ippath = p.abspath(p.join(p.dirname(__file__),'..','..'))
262 ipython_script = p.join(ippath, 'ipython.py')
263 ipython_cmd = 'python "%s"' % ipython_script
252 # Absolute path for filename
264 # Absolute path for filename
253 full_fname = os.path.join(test_dir, fname)
265 full_fname = p.join(test_dir, fname)
254 full_cmd = '%s %s "%s"' % (ipython_cmd, cmdargs, full_fname)
266 full_cmd = '%s %s %s' % (ipython_cmd, cmdargs, full_fname)
267 #print >> sys.stderr, 'FULL CMD:', full_cmd # dbg
255 return genutils.getoutputerror(full_cmd)
268 return genutils.getoutputerror(full_cmd)
256
269
257
270
258 def ipexec_validate(fname, expected_out, expected_err=None,
271 def ipexec_validate(fname, expected_out, expected_err='',
259 options=None):
272 options=None):
260 """Utility to call 'ipython filename' and validate output/error.
273 """Utility to call 'ipython filename' and validate output/error.
261
274
@@ -285,9 +298,18 b' def ipexec_validate(fname, expected_out, expected_err=None,'
285 import nose.tools as nt
298 import nose.tools as nt
286
299
287 out, err = ipexec(fname)
300 out, err = ipexec(fname)
301 #print 'OUT', out # dbg
302 #print 'ERR', err # dbg
303 # If there are any errors, we must check those befor stdout, as they may be
304 # more informative than simply having an empty stdout.
305 if err:
306 if expected_err:
307 nt.assert_equals(err.strip(), expected_err.strip())
308 else:
309 raise ValueError('Running file %r produced error: %r' %
310 (fname, err))
311 # If no errors or output on stderr was expected, match stdout
288 nt.assert_equals(out.strip(), expected_out.strip())
312 nt.assert_equals(out.strip(), expected_out.strip())
289 if expected_err:
290 nt.assert_equals(err.strip(), expected_err.strip())
291
313
292
314
293 class TempFileMixin(object):
315 class TempFileMixin(object):
@@ -11,6 +11,7 b' these things are also convenient when working at the command line.'
11 # Distributed under the terms of the BSD License. The full license is in
11 # Distributed under the terms of the BSD License. The full license is in
12 # the file COPYING, distributed as part of this software.
12 # the file COPYING, distributed as part of this software.
13 #*****************************************************************************
13 #*****************************************************************************
14 from __future__ import absolute_import
14
15
15 #****************************************************************************
16 #****************************************************************************
16 # required modules from the Python standard library
17 # required modules from the Python standard library
@@ -41,11 +42,12 b' else:'
41
42
42 # Other IPython utilities
43 # Other IPython utilities
43 import IPython
44 import IPython
45 from IPython.core import release
44 from IPython.external.Itpl import itpl,printpl
46 from IPython.external.Itpl import itpl,printpl
45 from IPython.utils import platutils
47 from IPython.utils import platutils
46 from IPython.utils.generics import result_display
48 from IPython.utils.generics import result_display
47 from IPython.external.path import path
49 from IPython.external.path import path
48
50 from .baseutils import getoutputerror
49
51
50 #****************************************************************************
52 #****************************************************************************
51 # Exceptions
53 # Exceptions
@@ -194,21 +196,49 b' def warn(msg,level=2,exit_val=1):'
194 print >> Term.cerr,'Exiting.\n'
196 print >> Term.cerr,'Exiting.\n'
195 sys.exit(exit_val)
197 sys.exit(exit_val)
196
198
199
197 def info(msg):
200 def info(msg):
198 """Equivalent to warn(msg,level=1)."""
201 """Equivalent to warn(msg,level=1)."""
199
202
200 warn(msg,level=1)
203 warn(msg,level=1)
201
204
205
202 def error(msg):
206 def error(msg):
203 """Equivalent to warn(msg,level=3)."""
207 """Equivalent to warn(msg,level=3)."""
204
208
205 warn(msg,level=3)
209 warn(msg,level=3)
206
210
211
207 def fatal(msg,exit_val=1):
212 def fatal(msg,exit_val=1):
208 """Equivalent to warn(msg,exit_val=exit_val,level=4)."""
213 """Equivalent to warn(msg,exit_val=exit_val,level=4)."""
209
214
210 warn(msg,exit_val=exit_val,level=4)
215 warn(msg,exit_val=exit_val,level=4)
211
216
217 def sys_info():
218 """Return useful information about IPython and the system, as a string.
219
220 Examples
221 --------
222 In [1]: print(sys_info())
223 IPython version: 0.11.bzr.r1340 # random
224 BZR revision : 1340
225 Platform info : os.name -> posix, sys.platform -> linux2
226 : Linux-2.6.31-17-generic-i686-with-Ubuntu-9.10-karmic
227 Python info : 2.6.4 (r264:75706, Dec 7 2009, 18:45:15)
228 [GCC 4.4.1]
229 """
230 import platform
231 out = []
232 out.append('IPython version: %s' % release.version)
233 out.append('BZR revision : %s' % release.revision)
234 out.append('Platform info : os.name -> %s, sys.platform -> %s' %
235 (os.name,sys.platform) )
236 out.append(' : %s' % platform.platform())
237 out.append('Python info : %s' % sys.version)
238 out.append('') # ensure closing newline
239 return '\n'.join(out)
240
241
212 #---------------------------------------------------------------------------
242 #---------------------------------------------------------------------------
213 # Debugging routines
243 # Debugging routines
214 #
244 #
@@ -282,6 +312,7 b' except ImportError:'
282 This just returns clock() and zero."""
312 This just returns clock() and zero."""
283 return time.clock(),0.0
313 return time.clock(),0.0
284
314
315
285 def timings_out(reps,func,*args,**kw):
316 def timings_out(reps,func,*args,**kw):
286 """timings_out(reps,func,*args,**kw) -> (t_total,t_per_call,output)
317 """timings_out(reps,func,*args,**kw) -> (t_total,t_per_call,output)
287
318
@@ -310,6 +341,7 b' def timings_out(reps,func,*args,**kw):'
310 av_time = tot_time / reps
341 av_time = tot_time / reps
311 return tot_time,av_time,out
342 return tot_time,av_time,out
312
343
344
313 def timings(reps,func,*args,**kw):
345 def timings(reps,func,*args,**kw):
314 """timings(reps,func,*args,**kw) -> (t_total,t_per_call)
346 """timings(reps,func,*args,**kw) -> (t_total,t_per_call)
315
347
@@ -319,6 +351,7 b' def timings(reps,func,*args,**kw):'
319
351
320 return timings_out(reps,func,*args,**kw)[0:2]
352 return timings_out(reps,func,*args,**kw)[0:2]
321
353
354
322 def timing(func,*args,**kw):
355 def timing(func,*args,**kw):
323 """timing(func,*args,**kw) -> t_total
356 """timing(func,*args,**kw) -> t_total
324
357
@@ -348,6 +381,7 b' def arg_split(s,posix=False):'
348 lex.whitespace_split = True
381 lex.whitespace_split = True
349 return list(lex)
382 return list(lex)
350
383
384
351 def system(cmd,verbose=0,debug=0,header=''):
385 def system(cmd,verbose=0,debug=0,header=''):
352 """Execute a system command, return its exit status.
386 """Execute a system command, return its exit status.
353
387
@@ -369,6 +403,7 b" def system(cmd,verbose=0,debug=0,header=''):"
369 if not debug: stat = os.system(cmd)
403 if not debug: stat = os.system(cmd)
370 return stat
404 return stat
371
405
406
372 def abbrev_cwd():
407 def abbrev_cwd():
373 """ Return abbreviated version of cwd, e.g. d:mydir """
408 """ Return abbreviated version of cwd, e.g. d:mydir """
374 cwd = os.getcwd().replace('\\','/')
409 cwd = os.getcwd().replace('\\','/')
@@ -439,6 +474,7 b" if os.name in ('nt','dos'):"
439
474
440 shell.__doc__ = shell_ori.__doc__
475 shell.__doc__ = shell_ori.__doc__
441
476
477
442 def getoutput(cmd,verbose=0,debug=0,header='',split=0):
478 def getoutput(cmd,verbose=0,debug=0,header='',split=0):
443 """Dummy substitute for perl's backquotes.
479 """Dummy substitute for perl's backquotes.
444
480
@@ -468,45 +504,11 b" def getoutput(cmd,verbose=0,debug=0,header='',split=0):"
468 else:
504 else:
469 return output
505 return output
470
506
471 def getoutputerror(cmd,verbose=0,debug=0,header='',split=0):
472 """Return (standard output,standard error) of executing cmd in a shell.
473
474 Accepts the same arguments as system(), plus:
475
476 - split(0): if true, each of stdout/err is returned as a list split on
477 newlines.
478
479 Note: a stateful version of this function is available through the
480 SystemExec class."""
481
482 if verbose or debug: print header+cmd
483 if not cmd:
484 if split:
485 return [],[]
486 else:
487 return '',''
488 if not debug:
489 p = subprocess.Popen(cmd, shell=True,
490 stdin=subprocess.PIPE,
491 stdout=subprocess.PIPE,
492 stderr=subprocess.PIPE,
493 close_fds=True)
494 pin, pout, perr = (p.stdin, p.stdout, p.stderr)
495
496 tout = pout.read().rstrip()
497 terr = perr.read().rstrip()
498 pin.close()
499 pout.close()
500 perr.close()
501 if split:
502 return tout.split('\n'),terr.split('\n')
503 else:
504 return tout,terr
505
506 # for compatibility with older naming conventions
507 # for compatibility with older naming conventions
507 xsys = system
508 xsys = system
508 bq = getoutput
509 bq = getoutput
509
510
511
510 class SystemExec:
512 class SystemExec:
511 """Access the system and getoutput functions through a stateful interface.
513 """Access the system and getoutput functions through a stateful interface.
512
514
@@ -635,9 +637,9 b' def filefind(filename, path_dirs=None):'
635 testname = expand_path(os.path.join(path, filename))
637 testname = expand_path(os.path.join(path, filename))
636 if os.path.isfile(testname):
638 if os.path.isfile(testname):
637 return os.path.abspath(testname)
639 return os.path.abspath(testname)
638 raise IOError("File does not exist in any "
640
639 "of the search paths: %r, %r" % \
641 raise IOError("File %r does not exist in any of the search paths: %r" %
640 (filename, path_dirs))
642 (filename, path_dirs) )
641
643
642
644
643 #----------------------------------------------------------------------------
645 #----------------------------------------------------------------------------
@@ -11,12 +11,25 b' to use these functions in platform agnostic fashion.'
11 # Distributed under the terms of the BSD License. The full license is in
11 # Distributed under the terms of the BSD License. The full license is in
12 # the file COPYING, distributed as part of this software.
12 # the file COPYING, distributed as part of this software.
13 #*****************************************************************************
13 #*****************************************************************************
14 #-----------------------------------------------------------------------------
15 # Imports
16 #-----------------------------------------------------------------------------
17 from __future__ import absolute_import
14
18
15 import sys
19 import sys
16 import os
20 import os
17
21
22 from .baseutils import getoutputerror
23
24 #-----------------------------------------------------------------------------
25 # Globals
26 #-----------------------------------------------------------------------------
27
18 ignore_termtitle = True
28 ignore_termtitle = True
19
29
30 #-----------------------------------------------------------------------------
31 # Functions
32 #-----------------------------------------------------------------------------
20
33
21 def _dummy_op(*a, **b):
34 def _dummy_op(*a, **b):
22 """ A no-op function """
35 """ A no-op function """
@@ -36,7 +49,7 b' else:'
36
49
37 def find_cmd(cmd):
50 def find_cmd(cmd):
38 """Find the full path to a command using which."""
51 """Find the full path to a command using which."""
39 return os.popen('which %s' % cmd).read().strip()
52 return getoutputerror('/usr/bin/env which %s' % cmd)[0]
40
53
41
54
42 def get_long_path_name(path):
55 def get_long_path_name(path):
@@ -1,4 +1,3 b''
1 #!/usr/bin/env python
2 # encoding: utf-8
1 # encoding: utf-8
3
2
4 def test_import_coloransi():
3 def test_import_coloransi():
@@ -1,4 +1,5 b''
1 include ipython.py
1 include ipython.py
2 include iptest.py
2 include setupbase.py
3 include setupbase.py
3 include setupegg.py
4 include setupegg.py
4
5
@@ -5,7 +5,25 b' IPython README'
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
@@ -42,7 +42,25 b' manages the Twisted reactor correctly.'
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 This script manages intelligently both nose and trial, choosing the correct
60 test system for each of IPython's components.
61
62 Once you have either installed it or at least configured your system to be
63 able to import IPython, you can run the tests with:
46
64
47 .. code-block:: bash
65 .. code-block:: bash
48
66
@@ -50,57 +68,72 b' The simplest way to test IPython is to type at the command line:'
50
68
51 This should work as long as IPython can be imported, even if you haven't fully
69 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).
70 installed the user-facing scripts yet (common in a development environment).
53 After a lot of output, you should see something like:
71 Once you have installed IPython, you will have available system-wide a script
72 called :file:`iptest` that does the exact same as the :file:`iptest.py` script
73 in the source directory, so you can then test simply with:
54
74
55 .. code-block:: bash
75 .. code-block:: bash
56
57 ************************************************************************
58 Ran 10 test groups in 35.228s
59
76
60 OK
77 iptest [args]
61
78
62 If not, there will be a message indicating which test group failed and how to
63 rerun that group individually.
64
79
65 But IPython ships with an entry point script called :file:`iptest` that offers
80 Regardless of how you run things, you should eventually see something like:
66 fine-grain control over the test process and is particularly useful for
67 developers; this script also manages intelligently both nose and trial,
68 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
70 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,
72 you can find it in the :file:`IPython/scripts` directory and you can run
73 directly from there.
74
81
75 For example, this tests the :mod:`IPython.utils` subpackage, the :option:`-v`
82 .. code-block:: bash
76 option shows progress indicators:
83
84 **********************************************************************
85 Test suite completed for system with the following information:
86 IPython version: 0.11.bzr.r1340
87 BZR revision : 1340
88 Platform info : os.name -> posix, sys.platform -> linux2
89 : Linux-2.6.31-17-generic-i686-with-Ubuntu-9.10-karmic
90 Python info : 2.6.4 (r264:75706, Dec 7 2009, 18:45:15)
91 [GCC 4.4.1]
92
93 Running from an installed IPython: True
94
95 Tools and libraries available at test time:
96 curses foolscap gobject gtk pexpect twisted wx wx.aui zope.interface
97
98 Tools and libraries NOT available at test time:
99 objc
100
101 Ran 11 test groups in 36.244s
102
103 Status:
104 OK
105
106 If not, there will be a message indicating which test group failed and how to
107 rerun that group individually. For example, this tests the
108 :mod:`IPython.utils` subpackage, the :option:`-v` option shows progress
109 indicators:
77
110
78 .. code-block:: bash
111 .. code-block:: bash
79
112
80 maqroll[ipython]> cd IPython/scripts/
113 $ python iptest.py -v IPython.utils
81 maqroll[scripts]> ./iptest -v IPython.utils
114 ..........................SS..SSS............................S.S...
82 ..........................SS..SSS............................S.S.........
115 .........................................................
83 ...................................................
116 ----------------------------------------------------------------------
84 ----------------------------------------------------------------------
117 Ran 125 tests in 0.119s
85 Ran 125 tests in 0.070s
118
119 OK (SKIP=7)
86
120
87 OK (SKIP=7)
88
121
89 Because :file:`iptest` is based on nose, you can use all nose options and
122 Because the IPython test machinery is based on nose, you can use all nose
90 syntax, typing ``iptest -h`` shows all available options. For example, this
123 options and syntax, typing ``iptest -h`` shows all available options. For
91 lets you run the specific test :func:`test_rehashx` inside the
124 example, this lets you run the specific test :func:`test_rehashx` inside the
92 :mod:`test_magic` module:
125 :mod:`test_magic` module:
93
126
94 .. code-block:: bash
127 .. code-block:: bash
95
128
96 maqroll[scripts]> ./iptest -vv IPython.core.tests.test_magic:test_rehashx
129 $ python iptest.py -vv IPython.core.tests.test_magic:test_rehashx
97 IPython.core.tests.test_magic.test_rehashx(True,) ... ok
130 IPython.core.tests.test_magic.test_rehashx(True,) ... ok
98 IPython.core.tests.test_magic.test_rehashx(True,) ... ok
131 IPython.core.tests.test_magic.test_rehashx(True,) ... ok
99
132
100 ----------------------------------------------------------------------
133 ----------------------------------------------------------------------
101 Ran 2 tests in 0.101s
134 Ran 2 tests in 0.100s
102
135
103 OK
136 OK
104
137
105 When developing, the :option:`--pdb` and :option:`--pdb-failures` of nose are
138 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
139 particularly useful, these drop you into an interactive pdb session at the
@@ -7,6 +7,10 b" 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'))
@@ -13,6 +13,23 b' requires utilities which are not available under Windows."""'
13 # the file COPYING, distributed as part of this software.
13 # the file COPYING, distributed as part of this software.
14 #-------------------------------------------------------------------------------
14 #-------------------------------------------------------------------------------
15
15
16 #-----------------------------------------------------------------------------
17 # Minimal Python version sanity check
18 #-----------------------------------------------------------------------------
19
20 import sys
21
22 # This check is also made in IPython/__init__, don't forget to update both when
23 # changing Python version requirements.
24 if sys.version[0:3] < '2.5':
25 error = """\
26 ERROR: 'IPython requires Python Version 2.5 or above.'
27 Exiting."""
28 print >> sys.stderr, error
29 sys.exit(1)
30
31 # At least we're on Python 2.5 or newer, move on.
32
16 #-------------------------------------------------------------------------------
33 #-------------------------------------------------------------------------------
17 # Imports
34 # Imports
18 #-------------------------------------------------------------------------------
35 #-------------------------------------------------------------------------------
@@ -20,7 +37,6 b' requires utilities which are not available under Windows."""'
20 # Stdlib imports
37 # Stdlib imports
21 import os
38 import os
22 import shutil
39 import shutil
23 import sys
24
40
25 from glob import glob
41 from glob import glob
26
42
@@ -30,6 +46,7 b" if os.path.exists('MANIFEST'): os.remove('MANIFEST')"
30
46
31 from distutils.core import setup
47 from distutils.core import setup
32
48
49 # Our own imports
33 from IPython.utils.genutils import target_update
50 from IPython.utils.genutils import target_update
34
51
35 from setupbase import (
52 from setupbase import (
General Comments 0
You need to be logged in to leave comments. Login now