##// END OF EJS Templates
Fixes to make test suite more robust on Fedora....
Fernando Perez -
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
@@ -1,415 +1,420 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
33
34 # Ugly, but necessary hack to ensure the test suite finds our version of
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.
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
36 # Note that this must be done here, so the imports that come next work
37 # correctly even if IPython isn't installed yet.
37 # correctly even if IPython isn't installed yet.
38 p = os.path
38 p = os.path
39 ippath = p.abspath(p.join(p.dirname(__file__),'..','..'))
39 ippath = p.abspath(p.join(p.dirname(__file__),'..','..'))
40 sys.path.insert(0, ippath)
40 sys.path.insert(0, ippath)
41 #print 'ipp:', ippath # dbg
41 #print 'ipp:', ippath # dbg
42 #import IPython; print 'IP file:', IPython.__file__ # dbg
42 #import IPython; print 'IP file:', IPython.__file__ # dbg
43
43
44 # Note: monkeypatch!
44 # Note: monkeypatch!
45 # 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
46 # 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
47 # 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.
48 from IPython.testing import nosepatch
48 from IPython.testing import nosepatch
49 # Now, proceed to import nose itself
49 # Now, proceed to import nose itself
50 import nose.plugins.builtin
50 import nose.plugins.builtin
51 from nose.core import TestProgram
51 from nose.core import TestProgram
52
52
53 # Our own imports
53 # Our own imports
54 from IPython.utils import genutils
54 from IPython.utils import genutils
55 from IPython.utils.platutils import find_cmd, FindCmdError
55 from IPython.utils.platutils import find_cmd, FindCmdError
56 from IPython.testing import globalipapp
56 from IPython.testing import globalipapp
57 from IPython.testing import tools
57 from IPython.testing import tools
58 from IPython.testing.plugin.ipdoctest import IPythonDoctest
58 from IPython.testing.plugin.ipdoctest import IPythonDoctest
59
59
60 pjoin = path.join
60 pjoin = path.join
61
61
62 #-----------------------------------------------------------------------------
62 #-----------------------------------------------------------------------------
63 # Warnings control
63 # Warnings control
64 #-----------------------------------------------------------------------------
64 #-----------------------------------------------------------------------------
65 # 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
66 # that imports 'sets' as of today
66 # that imports 'sets' as of today
67 warnings.filterwarnings('ignore', 'the sets module is deprecated',
67 warnings.filterwarnings('ignore', 'the sets module is deprecated',
68 DeprecationWarning )
68 DeprecationWarning )
69
69
70 # This one also comes from Twisted
70 # This one also comes from Twisted
71 warnings.filterwarnings('ignore', 'the sha module is deprecated',
71 warnings.filterwarnings('ignore', 'the sha module is deprecated',
72 DeprecationWarning)
72 DeprecationWarning)
73
73
74 # Wx on Fedora11 spits these out
75 warnings.filterwarnings('ignore', 'wxPython/wxWidgets release number mismatch',
76 UserWarning)
77
74 #-----------------------------------------------------------------------------
78 #-----------------------------------------------------------------------------
75 # Logic for skipping doctests
79 # Logic for skipping doctests
76 #-----------------------------------------------------------------------------
80 #-----------------------------------------------------------------------------
77
81
78 def test_for(mod):
82 def test_for(mod):
79 """Test to see if mod is importable."""
83 """Test to see if mod is importable."""
80 try:
84 try:
81 __import__(mod)
85 __import__(mod)
82 except ImportError:
86 except ImportError:
83 return False
87 return False
84 else:
88 else:
85 return True
89 return True
86
90
87
91
88 have_curses = test_for('_curses')
92 have_curses = test_for('_curses')
89 have_wx = test_for('wx')
93 have_wx = test_for('wx')
90 have_wx_aui = test_for('wx.aui')
94 have_wx_aui = test_for('wx.aui')
91 have_zi = test_for('zope.interface')
95 have_zi = test_for('zope.interface')
92 have_twisted = test_for('twisted')
96 have_twisted = test_for('twisted')
93 have_foolscap = test_for('foolscap')
97 have_foolscap = test_for('foolscap')
94 have_objc = test_for('objc')
98 have_objc = test_for('objc')
95 have_pexpect = test_for('pexpect')
99 have_pexpect = test_for('pexpect')
96 have_gtk = test_for('gtk')
100 have_gtk = test_for('gtk')
97 have_gobject = test_for('gobject')
101 have_gobject = test_for('gobject')
98
102
99
103
100 def make_exclude():
104 def make_exclude():
101 """Make patterns of modules and packages to exclude from testing.
105 """Make patterns of modules and packages to exclude from testing.
102
106
103 For the IPythonDoctest plugin, we need to exclude certain patterns that
107 For the IPythonDoctest plugin, we need to exclude certain patterns that
104 cause testing problems. We should strive to minimize the number of
108 cause testing problems. We should strive to minimize the number of
105 skipped modules, since this means untested code. As the testing
109 skipped modules, since this means untested code. As the testing
106 machinery solidifies, this list should eventually become empty.
110 machinery solidifies, this list should eventually become empty.
107 These modules and packages will NOT get scanned by nose at all for tests.
111 These modules and packages will NOT get scanned by nose at all for tests.
108 """
112 """
109 # Simple utility to make IPython paths more readably, we need a lot of
113 # Simple utility to make IPython paths more readably, we need a lot of
110 # these below
114 # these below
111 ipjoin = lambda *paths: pjoin('IPython', *paths)
115 ipjoin = lambda *paths: pjoin('IPython', *paths)
112
116
113 exclusions = [ipjoin('external'),
117 exclusions = [ipjoin('external'),
114 ipjoin('frontend', 'process', 'winprocess.py'),
118 ipjoin('frontend', 'process', 'winprocess.py'),
115 # Deprecated old Shell and iplib modules, skip to avoid
119 # Deprecated old Shell and iplib modules, skip to avoid
116 # warnings
120 # warnings
117 ipjoin('Shell'),
121 ipjoin('Shell'),
118 ipjoin('iplib'),
122 ipjoin('iplib'),
119 pjoin('IPython_doctest_plugin'),
123 pjoin('IPython_doctest_plugin'),
120 ipjoin('quarantine'),
124 ipjoin('quarantine'),
121 ipjoin('deathrow'),
125 ipjoin('deathrow'),
122 ipjoin('testing', 'attic'),
126 ipjoin('testing', 'attic'),
123 # This guy is probably attic material
127 # This guy is probably attic material
124 ipjoin('testing', 'mkdoctests'),
128 ipjoin('testing', 'mkdoctests'),
125 # Testing inputhook will need a lot of thought, to figure out
129 # Testing inputhook will need a lot of thought, to figure out
126 # how to have tests that don't lock up with the gui event
130 # how to have tests that don't lock up with the gui event
127 # loops in the picture
131 # loops in the picture
128 ipjoin('lib', 'inputhook'),
132 ipjoin('lib', 'inputhook'),
129 # Config files aren't really importable stand-alone
133 # Config files aren't really importable stand-alone
130 ipjoin('config', 'default'),
134 ipjoin('config', 'default'),
131 ipjoin('config', 'profile'),
135 ipjoin('config', 'profile'),
132 ]
136 ]
133
137
134 if not have_wx:
138 if not have_wx:
135 exclusions.append(ipjoin('gui'))
139 exclusions.append(ipjoin('gui'))
136 exclusions.append(ipjoin('frontend', 'wx'))
140 exclusions.append(ipjoin('frontend', 'wx'))
137 exclusions.append(ipjoin('lib', 'inputhookwx'))
141 exclusions.append(ipjoin('lib', 'inputhookwx'))
138
142
139 if not have_gtk or not have_gobject:
143 if not have_gtk or not have_gobject:
140 exclusions.append(ipjoin('lib', 'inputhookgtk'))
144 exclusions.append(ipjoin('lib', 'inputhookgtk'))
141
145
142 if not have_wx_aui:
146 if not have_wx_aui:
143 exclusions.append(ipjoin('gui', 'wx', 'wxIPython'))
147 exclusions.append(ipjoin('gui', 'wx', 'wxIPython'))
144
148
145 if not have_objc:
149 if not have_objc:
146 exclusions.append(ipjoin('frontend', 'cocoa'))
150 exclusions.append(ipjoin('frontend', 'cocoa'))
147
151
148 if not sys.platform == 'win32':
152 if not sys.platform == 'win32':
149 exclusions.append(ipjoin('utils', 'platutils_win32'))
153 exclusions.append(ipjoin('utils', 'platutils_win32'))
150
154
151 # These have to be skipped on win32 because the use echo, rm, cd, etc.
155 # These have to be skipped on win32 because the use echo, rm, cd, etc.
152 # See ticket https://bugs.launchpad.net/bugs/366982
156 # See ticket https://bugs.launchpad.net/bugs/366982
153 if sys.platform == 'win32':
157 if sys.platform == 'win32':
154 exclusions.append(ipjoin('testing', 'plugin', 'test_exampleip'))
158 exclusions.append(ipjoin('testing', 'plugin', 'test_exampleip'))
155 exclusions.append(ipjoin('testing', 'plugin', 'dtexample'))
159 exclusions.append(ipjoin('testing', 'plugin', 'dtexample'))
156
160
157 if not os.name == 'posix':
161 if not os.name == 'posix':
158 exclusions.append(ipjoin('utils', 'platutils_posix'))
162 exclusions.append(ipjoin('utils', 'platutils_posix'))
159
163
160 if not have_pexpect:
164 if not have_pexpect:
161 exclusions.extend([ipjoin('scripts', 'irunner'),
165 exclusions.extend([ipjoin('scripts', 'irunner'),
162 ipjoin('lib', 'irunner')])
166 ipjoin('lib', 'irunner')])
163
167
164 # This is scary. We still have things in frontend and testing that
168 # This is scary. We still have things in frontend and testing that
165 # are being tested by nose that use twisted. We need to rethink
169 # are being tested by nose that use twisted. We need to rethink
166 # how we are isolating dependencies in testing.
170 # how we are isolating dependencies in testing.
167 if not (have_twisted and have_zi and have_foolscap):
171 if not (have_twisted and have_zi and have_foolscap):
168 exclusions.extend(
172 exclusions.extend(
169 [ipjoin('frontend', 'asyncfrontendbase'),
173 [ipjoin('frontend', 'asyncfrontendbase'),
170 ipjoin('frontend', 'prefilterfrontend'),
174 ipjoin('frontend', 'prefilterfrontend'),
171 ipjoin('frontend', 'frontendbase'),
175 ipjoin('frontend', 'frontendbase'),
172 ipjoin('frontend', 'linefrontendbase'),
176 ipjoin('frontend', 'linefrontendbase'),
173 ipjoin('frontend', 'tests', 'test_linefrontend'),
177 ipjoin('frontend', 'tests', 'test_linefrontend'),
174 ipjoin('frontend', 'tests', 'test_frontendbase'),
178 ipjoin('frontend', 'tests', 'test_frontendbase'),
175 ipjoin('frontend', 'tests', 'test_prefilterfrontend'),
179 ipjoin('frontend', 'tests', 'test_prefilterfrontend'),
176 ipjoin('frontend', 'tests', 'test_asyncfrontendbase'),
180 ipjoin('frontend', 'tests', 'test_asyncfrontendbase'),
177 ipjoin('testing', 'parametric'),
181 ipjoin('testing', 'parametric'),
178 ipjoin('testing', 'util'),
182 ipjoin('testing', 'util'),
179 ipjoin('testing', 'tests', 'test_decorators_trial'),
183 ipjoin('testing', 'tests', 'test_decorators_trial'),
180 ] )
184 ] )
181
185
182 # This is needed for the reg-exp to match on win32 in the ipdoctest plugin.
186 # This is needed for the reg-exp to match on win32 in the ipdoctest plugin.
183 if sys.platform == 'win32':
187 if sys.platform == 'win32':
184 exclusions = [s.replace('\\','\\\\') for s in exclusions]
188 exclusions = [s.replace('\\','\\\\') for s in exclusions]
185
189
186 return exclusions
190 return exclusions
187
191
188
192
189 #-----------------------------------------------------------------------------
193 #-----------------------------------------------------------------------------
190 # Functions and classes
194 # Functions and classes
191 #-----------------------------------------------------------------------------
195 #-----------------------------------------------------------------------------
192
196
193 class IPTester(object):
197 class IPTester(object):
194 """Call that calls iptest or trial in a subprocess.
198 """Call that calls iptest or trial in a subprocess.
195 """
199 """
196 #: string, name of test runner that will be called
200 #: string, name of test runner that will be called
197 runner = None
201 runner = None
198 #: list, parameters for test runner
202 #: list, parameters for test runner
199 params = None
203 params = None
200 #: list, arguments of system call to be made to call test runner
204 #: list, arguments of system call to be made to call test runner
201 call_args = None
205 call_args = None
202 #: list, process ids of subprocesses we start (for cleanup)
206 #: list, process ids of subprocesses we start (for cleanup)
203 pids = None
207 pids = None
204
208
205 def __init__(self, runner='iptest', params=None):
209 def __init__(self, runner='iptest', params=None):
206 """Create new test runner."""
210 """Create new test runner."""
207 if runner == 'iptest':
211 if runner == 'iptest':
208 # Find our own 'iptest' script OS-level entry point. Don't look
212 # Find our own 'iptest' script OS-level entry point. Don't look
209 # system-wide, so we are sure we pick up *this one*. And pass
213 # system-wide, so we are sure we pick up *this one*. And pass
210 # through to subprocess call our own sys.argv
214 # through to subprocess call our own sys.argv
211 self.runner = tools.cmd2argv(os.path.abspath(__file__)) + \
215 self.runner = tools.cmd2argv(os.path.abspath(__file__)) + \
212 sys.argv[1:]
216 sys.argv[1:]
213 else:
217 else:
214 self.runner = tools.cmd2argv(os.path.abspath(find_cmd('trial')))
218 self.runner = tools.cmd2argv(os.path.abspath(find_cmd('trial')))
215 if params is None:
219 if params is None:
216 params = []
220 params = []
217 if isinstance(params, str):
221 if isinstance(params, str):
218 params = [params]
222 params = [params]
219 self.params = params
223 self.params = params
220
224
221 # Assemble call
225 # Assemble call
222 self.call_args = self.runner+self.params
226 self.call_args = self.runner+self.params
223
227
224 # Store pids of anything we start to clean up on deletion, if possible
228 # Store pids of anything we start to clean up on deletion, if possible
225 # (on posix only, since win32 has no os.kill)
229 # (on posix only, since win32 has no os.kill)
226 self.pids = []
230 self.pids = []
227
231
228 if sys.platform == 'win32':
232 if sys.platform == 'win32':
229 def _run_cmd(self):
233 def _run_cmd(self):
230 # On Windows, use os.system instead of subprocess.call, because I
234 # On Windows, use os.system instead of subprocess.call, because I
231 # was having problems with subprocess and I just don't know enough
235 # was having problems with subprocess and I just don't know enough
232 # about win32 to debug this reliably. Os.system may be the 'old
236 # about win32 to debug this reliably. Os.system may be the 'old
233 # fashioned' way to do it, but it works just fine. If someone
237 # fashioned' way to do it, but it works just fine. If someone
234 # later can clean this up that's fine, as long as the tests run
238 # later can clean this up that's fine, as long as the tests run
235 # reliably in win32.
239 # reliably in win32.
236 return os.system(' '.join(self.call_args))
240 return os.system(' '.join(self.call_args))
237 else:
241 else:
238 def _run_cmd(self):
242 def _run_cmd(self):
239 subp = subprocess.Popen(self.call_args)
243 subp = subprocess.Popen(self.call_args)
240 self.pids.append(subp.pid)
244 self.pids.append(subp.pid)
241 # If this fails, the pid will be left in self.pids and cleaned up
245 # If this fails, the pid will be left in self.pids and cleaned up
242 # later, but if the wait call succeeds, then we can clear the
246 # later, but if the wait call succeeds, then we can clear the
243 # stored pid.
247 # stored pid.
244 retcode = subp.wait()
248 retcode = subp.wait()
245 self.pids.pop()
249 self.pids.pop()
246 return retcode
250 return retcode
247
251
248 def run(self):
252 def run(self):
249 """Run the stored commands"""
253 """Run the stored commands"""
250 try:
254 try:
251 return self._run_cmd()
255 return self._run_cmd()
252 except:
256 except:
253 import traceback
257 import traceback
254 traceback.print_exc()
258 traceback.print_exc()
255 return 1 # signal failure
259 return 1 # signal failure
256
260
257 def __del__(self):
261 def __del__(self):
258 """Cleanup on exit by killing any leftover processes."""
262 """Cleanup on exit by killing any leftover processes."""
259
263
260 if not hasattr(os, 'kill'):
264 if not hasattr(os, 'kill'):
261 return
265 return
262
266
263 for pid in self.pids:
267 for pid in self.pids:
264 try:
268 try:
265 print 'Cleaning stale PID:', pid
269 print 'Cleaning stale PID:', pid
266 os.kill(pid, signal.SIGKILL)
270 os.kill(pid, signal.SIGKILL)
267 except OSError:
271 except OSError:
268 # This is just a best effort, if we fail or the process was
272 # This is just a best effort, if we fail or the process was
269 # really gone, ignore it.
273 # really gone, ignore it.
270 pass
274 pass
271
275
272
276
273 def make_runners():
277 def make_runners():
274 """Define the top-level packages that need to be tested.
278 """Define the top-level packages that need to be tested.
275 """
279 """
276
280
277 nose_packages = ['config', 'core', 'extensions', 'frontend', 'lib',
281 # Packages to be tested via nose, that only depend on the stdlib
278 'scripts', 'testing', 'utils',
282 nose_pkg_names = ['config', 'core', 'extensions', 'frontend', 'lib',
279 # Note that we list the kernel here, though the bulk of it
283 'scripts', 'testing', 'utils' ]
280 # is twisted-based, because nose picks up doctests that
281 # twisted doesn't.
282 'kernel']
283 # The machinery in kernel needs twisted for real testing
284 # The machinery in kernel needs twisted for real testing
284 trial_packages = ['kernel']
285 trial_pkg_names = []
285
286
286 if have_wx:
287 if have_wx:
287 nose_packages.append('gui')
288 nose_pkg_names.append('gui')
288
289 #nose_packages = ['config', 'utils'] # dbg
290 #trial_packages = [] # dbg
291
292 nose_packages = ['IPython.%s' % m for m in nose_packages ]
293 trial_packages = ['IPython.%s' % m for m in trial_packages ]
294
289
295 # Make runners, most with nose
296 nose_testers = [IPTester(params=v) for v in nose_packages]
297 runners = zip(nose_packages, nose_testers)
298
299 # And add twisted ones if conditions are met
290 # And add twisted ones if conditions are met
300 if have_zi and have_twisted and have_foolscap:
291 if have_zi and have_twisted and have_foolscap:
301 trial_testers = [IPTester('trial', params=v) for v in trial_packages]
292 # Note that we list the kernel here, though the bulk of it is
302 runners.extend(zip(trial_packages, trial_testers))
293 # twisted-based, because nose picks up doctests that twisted doesn't.
303
294 nose_pkg_names.append('kernel')
295 trial_pkg_names.append('kernel')
296
297 # For debugging this code, only load quick stuff
298 #nose_pkg_names = ['config', 'utils'] # dbg
299 #trial_pkg_names = [] # dbg
300
301 # Make fully qualified package names prepending 'IPython.' to our name lists
302 nose_packages = ['IPython.%s' % m for m in nose_pkg_names ]
303 trial_packages = ['IPython.%s' % m for m in trial_pkg_names ]
304
305 # Make runners
306 runners = [ (v, IPTester('iptest', params=v)) for v in nose_packages ]
307 runners.extend([ (v, IPTester('trial', params=v)) for v in trial_packages ])
308
304 return runners
309 return runners
305
310
306
311
307 def run_iptest():
312 def run_iptest():
308 """Run the IPython test suite using nose.
313 """Run the IPython test suite using nose.
309
314
310 This function is called when this script is **not** called with the form
315 This function is called when this script is **not** called with the form
311 `iptest all`. It simply calls nose with appropriate command line flags
316 `iptest all`. It simply calls nose with appropriate command line flags
312 and accepts all of the standard nose arguments.
317 and accepts all of the standard nose arguments.
313 """
318 """
314
319
315 warnings.filterwarnings('ignore',
320 warnings.filterwarnings('ignore',
316 'This will be removed soon. Use IPython.testing.util instead')
321 'This will be removed soon. Use IPython.testing.util instead')
317
322
318 argv = sys.argv + [ '--detailed-errors',
323 argv = sys.argv + [ '--detailed-errors',
319 # Loading ipdoctest causes problems with Twisted, but
324 # Loading ipdoctest causes problems with Twisted, but
320 # our test suite runner now separates things and runs
325 # our test suite runner now separates things and runs
321 # all Twisted tests with trial.
326 # all Twisted tests with trial.
322 '--with-ipdoctest',
327 '--with-ipdoctest',
323 '--ipdoctest-tests','--ipdoctest-extension=txt',
328 '--ipdoctest-tests','--ipdoctest-extension=txt',
324
329
325 # We add --exe because of setuptools' imbecility (it
330 # We add --exe because of setuptools' imbecility (it
326 # blindly does chmod +x on ALL files). Nose does the
331 # blindly does chmod +x on ALL files). Nose does the
327 # right thing and it tries to avoid executables,
332 # right thing and it tries to avoid executables,
328 # setuptools unfortunately forces our hand here. This
333 # setuptools unfortunately forces our hand here. This
329 # has been discussed on the distutils list and the
334 # has been discussed on the distutils list and the
330 # setuptools devs refuse to fix this problem!
335 # setuptools devs refuse to fix this problem!
331 '--exe',
336 '--exe',
332 ]
337 ]
333
338
334
339
335 # Construct list of plugins, omitting the existing doctest plugin, which
340 # Construct list of plugins, omitting the existing doctest plugin, which
336 # ours replaces (and extends).
341 # ours replaces (and extends).
337 plugins = [IPythonDoctest(make_exclude())]
342 plugins = [IPythonDoctest(make_exclude())]
338 for p in nose.plugins.builtin.plugins:
343 for p in nose.plugins.builtin.plugins:
339 plug = p()
344 plug = p()
340 if plug.name == 'doctest':
345 if plug.name == 'doctest':
341 continue
346 continue
342 plugins.append(plug)
347 plugins.append(plug)
343
348
344 # We need a global ipython running in this process
349 # We need a global ipython running in this process
345 globalipapp.start_ipython()
350 globalipapp.start_ipython()
346 # Now nose can run
351 # Now nose can run
347 TestProgram(argv=argv, plugins=plugins)
352 TestProgram(argv=argv, plugins=plugins)
348
353
349
354
350 def run_iptestall():
355 def run_iptestall():
351 """Run the entire IPython test suite by calling nose and trial.
356 """Run the entire IPython test suite by calling nose and trial.
352
357
353 This function constructs :class:`IPTester` instances for all IPython
358 This function constructs :class:`IPTester` instances for all IPython
354 modules and package and then runs each of them. This causes the modules
359 modules and package and then runs each of them. This causes the modules
355 and packages of IPython to be tested each in their own subprocess using
360 and packages of IPython to be tested each in their own subprocess using
356 nose or twisted.trial appropriately.
361 nose or twisted.trial appropriately.
357 """
362 """
358
363
359 runners = make_runners()
364 runners = make_runners()
360
365
361 # Run the test runners in a temporary dir so we can nuke it when finished
366 # Run the test runners in a temporary dir so we can nuke it when finished
362 # to clean up any junk files left over by accident. This also makes it
367 # to clean up any junk files left over by accident. This also makes it
363 # robust against being run in non-writeable directories by mistake, as the
368 # robust against being run in non-writeable directories by mistake, as the
364 # temp dir will always be user-writeable.
369 # temp dir will always be user-writeable.
365 curdir = os.getcwd()
370 curdir = os.getcwd()
366 testdir = tempfile.gettempdir()
371 testdir = tempfile.gettempdir()
367 os.chdir(testdir)
372 os.chdir(testdir)
368
373
369 # Run all test runners, tracking execution time
374 # Run all test runners, tracking execution time
370 failed = []
375 failed = []
371 t_start = time.time()
376 t_start = time.time()
372 try:
377 try:
373 for (name, runner) in runners:
378 for (name, runner) in runners:
374 print '*'*70
379 print '*'*70
375 print 'IPython test group:',name
380 print 'IPython test group:',name
376 res = runner.run()
381 res = runner.run()
377 if res:
382 if res:
378 failed.append( (name, runner) )
383 failed.append( (name, runner) )
379 finally:
384 finally:
380 os.chdir(curdir)
385 os.chdir(curdir)
381 t_end = time.time()
386 t_end = time.time()
382 t_tests = t_end - t_start
387 t_tests = t_end - t_start
383 nrunners = len(runners)
388 nrunners = len(runners)
384 nfail = len(failed)
389 nfail = len(failed)
385 # summarize results
390 # summarize results
386 print
391 print
387 print '*'*70
392 print '*'*70
388 print 'Ran %s test groups in %.3fs' % (nrunners, t_tests)
393 print 'Ran %s test groups in %.3fs' % (nrunners, t_tests)
389 print
394 print
390 if not failed:
395 if not failed:
391 print 'OK'
396 print 'OK'
392 else:
397 else:
393 # If anything went wrong, point out what command to rerun manually to
398 # If anything went wrong, point out what command to rerun manually to
394 # see the actual errors and individual summary
399 # see the actual errors and individual summary
395 print 'ERROR - %s out of %s test groups failed.' % (nfail, nrunners)
400 print 'ERROR - %s out of %s test groups failed.' % (nfail, nrunners)
396 for name, failed_runner in failed:
401 for name, failed_runner in failed:
397 print '-'*40
402 print '-'*40
398 print 'Runner failed:',name
403 print 'Runner failed:',name
399 print 'You may wish to rerun this one individually, with:'
404 print 'You may wish to rerun this one individually, with:'
400 print ' '.join(failed_runner.call_args)
405 print ' '.join(failed_runner.call_args)
401 print
406 print
402
407
403
408
404 def main():
409 def main():
405 for arg in sys.argv[1:]:
410 for arg in sys.argv[1:]:
406 if arg.startswith('IPython'):
411 if arg.startswith('IPython'):
407 # This is in-process
412 # This is in-process
408 run_iptest()
413 run_iptest()
409 else:
414 else:
410 # This starts subprocesses
415 # This starts subprocesses
411 run_iptestall()
416 run_iptestall()
412
417
413
418
414 if __name__ == '__main__':
419 if __name__ == '__main__':
415 main()
420 main()
@@ -1,1892 +1,1868 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """General purpose utilities.
2 """General purpose utilities.
3
3
4 This is a grab-bag of stuff I find useful in most programs I write. Some of
4 This is a grab-bag of stuff I find useful in most programs I write. Some of
5 these things are also convenient when working at the command line.
5 these things are also convenient when working at the command line.
6 """
6 """
7
7
8 #*****************************************************************************
8 #*****************************************************************************
9 # Copyright (C) 2001-2006 Fernando Perez. <fperez@colorado.edu>
9 # Copyright (C) 2001-2006 Fernando Perez. <fperez@colorado.edu>
10 #
10 #
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
17 import __main__
18 import __main__
18
19
19 import os
20 import os
20 import platform
21 import platform
21 import re
22 import re
22 import shlex
23 import shlex
23 import shutil
24 import shutil
24 import subprocess
25 import subprocess
25 import sys
26 import sys
26 import time
27 import time
27 import types
28 import types
28 import warnings
29 import warnings
29
30
30 # Curses and termios are Unix-only modules
31 # Curses and termios are Unix-only modules
31 try:
32 try:
32 import curses
33 import curses
33 # We need termios as well, so if its import happens to raise, we bail on
34 # We need termios as well, so if its import happens to raise, we bail on
34 # using curses altogether.
35 # using curses altogether.
35 import termios
36 import termios
36 except ImportError:
37 except ImportError:
37 USE_CURSES = False
38 USE_CURSES = False
38 else:
39 else:
39 # Curses on Solaris may not be complete, so we can't use it there
40 # Curses on Solaris may not be complete, so we can't use it there
40 USE_CURSES = hasattr(curses,'initscr')
41 USE_CURSES = hasattr(curses,'initscr')
41
42
42 # Other IPython utilities
43 # Other IPython utilities
43 import IPython
44 import IPython
44 from IPython.external.Itpl import itpl,printpl
45 from IPython.external.Itpl import itpl,printpl
45 from IPython.utils import platutils
46 from IPython.utils import platutils
46 from IPython.utils.generics import result_display
47 from IPython.utils.generics import result_display
47 from IPython.external.path import path
48 from IPython.external.path import path
48
49 from .baseutils import getoutputerror
49
50
50 #****************************************************************************
51 #****************************************************************************
51 # Exceptions
52 # Exceptions
52 class Error(Exception):
53 class Error(Exception):
53 """Base class for exceptions in this module."""
54 """Base class for exceptions in this module."""
54 pass
55 pass
55
56
56 #----------------------------------------------------------------------------
57 #----------------------------------------------------------------------------
57 class IOStream:
58 class IOStream:
58 def __init__(self,stream,fallback):
59 def __init__(self,stream,fallback):
59 if not hasattr(stream,'write') or not hasattr(stream,'flush'):
60 if not hasattr(stream,'write') or not hasattr(stream,'flush'):
60 stream = fallback
61 stream = fallback
61 self.stream = stream
62 self.stream = stream
62 self._swrite = stream.write
63 self._swrite = stream.write
63 self.flush = stream.flush
64 self.flush = stream.flush
64
65
65 def write(self,data):
66 def write(self,data):
66 try:
67 try:
67 self._swrite(data)
68 self._swrite(data)
68 except:
69 except:
69 try:
70 try:
70 # print handles some unicode issues which may trip a plain
71 # print handles some unicode issues which may trip a plain
71 # write() call. Attempt to emulate write() by using a
72 # write() call. Attempt to emulate write() by using a
72 # trailing comma
73 # trailing comma
73 print >> self.stream, data,
74 print >> self.stream, data,
74 except:
75 except:
75 # if we get here, something is seriously broken.
76 # if we get here, something is seriously broken.
76 print >> sys.stderr, \
77 print >> sys.stderr, \
77 'ERROR - failed to write data to stream:', self.stream
78 'ERROR - failed to write data to stream:', self.stream
78
79
79 def writeln(self, data):
80 def writeln(self, data):
80 self.write(data)
81 self.write(data)
81 self.write('\n')
82 self.write('\n')
82
83
83 def close(self):
84 def close(self):
84 pass
85 pass
85
86
86
87
87 class IOTerm:
88 class IOTerm:
88 """ Term holds the file or file-like objects for handling I/O operations.
89 """ Term holds the file or file-like objects for handling I/O operations.
89
90
90 These are normally just sys.stdin, sys.stdout and sys.stderr but for
91 These are normally just sys.stdin, sys.stdout and sys.stderr but for
91 Windows they can can replaced to allow editing the strings before they are
92 Windows they can can replaced to allow editing the strings before they are
92 displayed."""
93 displayed."""
93
94
94 # In the future, having IPython channel all its I/O operations through
95 # In the future, having IPython channel all its I/O operations through
95 # this class will make it easier to embed it into other environments which
96 # this class will make it easier to embed it into other environments which
96 # are not a normal terminal (such as a GUI-based shell)
97 # are not a normal terminal (such as a GUI-based shell)
97 def __init__(self,cin=None,cout=None,cerr=None):
98 def __init__(self,cin=None,cout=None,cerr=None):
98 self.cin = IOStream(cin,sys.stdin)
99 self.cin = IOStream(cin,sys.stdin)
99 self.cout = IOStream(cout,sys.stdout)
100 self.cout = IOStream(cout,sys.stdout)
100 self.cerr = IOStream(cerr,sys.stderr)
101 self.cerr = IOStream(cerr,sys.stderr)
101
102
102 # Global variable to be used for all I/O
103 # Global variable to be used for all I/O
103 Term = IOTerm()
104 Term = IOTerm()
104
105
105 import IPython.utils.rlineimpl as readline
106 import IPython.utils.rlineimpl as readline
106 # Remake Term to use the readline i/o facilities
107 # Remake Term to use the readline i/o facilities
107 if sys.platform == 'win32' and readline.have_readline:
108 if sys.platform == 'win32' and readline.have_readline:
108
109
109 Term = IOTerm(cout=readline._outputfile,cerr=readline._outputfile)
110 Term = IOTerm(cout=readline._outputfile,cerr=readline._outputfile)
110
111
111
112
112 class Tee(object):
113 class Tee(object):
113 """A class to duplicate an output stream to stdout/err.
114 """A class to duplicate an output stream to stdout/err.
114
115
115 This works in a manner very similar to the Unix 'tee' command.
116 This works in a manner very similar to the Unix 'tee' command.
116
117
117 When the object is closed or deleted, it closes the original file given to
118 When the object is closed or deleted, it closes the original file given to
118 it for duplication.
119 it for duplication.
119 """
120 """
120 # Inspired by:
121 # Inspired by:
121 # http://mail.python.org/pipermail/python-list/2007-May/442737.html
122 # http://mail.python.org/pipermail/python-list/2007-May/442737.html
122
123
123 def __init__(self, file, mode=None, channel='stdout'):
124 def __init__(self, file, mode=None, channel='stdout'):
124 """Construct a new Tee object.
125 """Construct a new Tee object.
125
126
126 Parameters
127 Parameters
127 ----------
128 ----------
128 file : filename or open filehandle (writable)
129 file : filename or open filehandle (writable)
129 File that will be duplicated
130 File that will be duplicated
130
131
131 mode : optional, valid mode for open().
132 mode : optional, valid mode for open().
132 If a filename was give, open with this mode.
133 If a filename was give, open with this mode.
133
134
134 channel : str, one of ['stdout', 'stderr']
135 channel : str, one of ['stdout', 'stderr']
135 """
136 """
136 if channel not in ['stdout', 'stderr']:
137 if channel not in ['stdout', 'stderr']:
137 raise ValueError('Invalid channel spec %s' % channel)
138 raise ValueError('Invalid channel spec %s' % channel)
138
139
139 if hasattr(file, 'write') and hasattr(file, 'seek'):
140 if hasattr(file, 'write') and hasattr(file, 'seek'):
140 self.file = file
141 self.file = file
141 else:
142 else:
142 self.file = open(name, mode)
143 self.file = open(name, mode)
143 self.channel = channel
144 self.channel = channel
144 self.ostream = getattr(sys, channel)
145 self.ostream = getattr(sys, channel)
145 setattr(sys, channel, self)
146 setattr(sys, channel, self)
146 self._closed = False
147 self._closed = False
147
148
148 def close(self):
149 def close(self):
149 """Close the file and restore the channel."""
150 """Close the file and restore the channel."""
150 self.flush()
151 self.flush()
151 setattr(sys, self.channel, self.ostream)
152 setattr(sys, self.channel, self.ostream)
152 self.file.close()
153 self.file.close()
153 self._closed = True
154 self._closed = True
154
155
155 def write(self, data):
156 def write(self, data):
156 """Write data to both channels."""
157 """Write data to both channels."""
157 self.file.write(data)
158 self.file.write(data)
158 self.ostream.write(data)
159 self.ostream.write(data)
159 self.ostream.flush()
160 self.ostream.flush()
160
161
161 def flush(self):
162 def flush(self):
162 """Flush both channels."""
163 """Flush both channels."""
163 self.file.flush()
164 self.file.flush()
164 self.ostream.flush()
165 self.ostream.flush()
165
166
166 def __del__(self):
167 def __del__(self):
167 if not self._closed:
168 if not self._closed:
168 self.close()
169 self.close()
169
170
170
171
171 #****************************************************************************
172 #****************************************************************************
172 # Generic warning/error printer, used by everything else
173 # Generic warning/error printer, used by everything else
173 def warn(msg,level=2,exit_val=1):
174 def warn(msg,level=2,exit_val=1):
174 """Standard warning printer. Gives formatting consistency.
175 """Standard warning printer. Gives formatting consistency.
175
176
176 Output is sent to Term.cerr (sys.stderr by default).
177 Output is sent to Term.cerr (sys.stderr by default).
177
178
178 Options:
179 Options:
179
180
180 -level(2): allows finer control:
181 -level(2): allows finer control:
181 0 -> Do nothing, dummy function.
182 0 -> Do nothing, dummy function.
182 1 -> Print message.
183 1 -> Print message.
183 2 -> Print 'WARNING:' + message. (Default level).
184 2 -> Print 'WARNING:' + message. (Default level).
184 3 -> Print 'ERROR:' + message.
185 3 -> Print 'ERROR:' + message.
185 4 -> Print 'FATAL ERROR:' + message and trigger a sys.exit(exit_val).
186 4 -> Print 'FATAL ERROR:' + message and trigger a sys.exit(exit_val).
186
187
187 -exit_val (1): exit value returned by sys.exit() for a level 4
188 -exit_val (1): exit value returned by sys.exit() for a level 4
188 warning. Ignored for all other levels."""
189 warning. Ignored for all other levels."""
189
190
190 if level>0:
191 if level>0:
191 header = ['','','WARNING: ','ERROR: ','FATAL ERROR: ']
192 header = ['','','WARNING: ','ERROR: ','FATAL ERROR: ']
192 print >> Term.cerr, '%s%s' % (header[level],msg)
193 print >> Term.cerr, '%s%s' % (header[level],msg)
193 if level == 4:
194 if level == 4:
194 print >> Term.cerr,'Exiting.\n'
195 print >> Term.cerr,'Exiting.\n'
195 sys.exit(exit_val)
196 sys.exit(exit_val)
196
197
198
197 def info(msg):
199 def info(msg):
198 """Equivalent to warn(msg,level=1)."""
200 """Equivalent to warn(msg,level=1)."""
199
201
200 warn(msg,level=1)
202 warn(msg,level=1)
201
203
204
202 def error(msg):
205 def error(msg):
203 """Equivalent to warn(msg,level=3)."""
206 """Equivalent to warn(msg,level=3)."""
204
207
205 warn(msg,level=3)
208 warn(msg,level=3)
206
209
210
207 def fatal(msg,exit_val=1):
211 def fatal(msg,exit_val=1):
208 """Equivalent to warn(msg,exit_val=exit_val,level=4)."""
212 """Equivalent to warn(msg,exit_val=exit_val,level=4)."""
209
213
210 warn(msg,exit_val=exit_val,level=4)
214 warn(msg,exit_val=exit_val,level=4)
211
215
212 #---------------------------------------------------------------------------
216 #---------------------------------------------------------------------------
213 # Debugging routines
217 # Debugging routines
214 #
218 #
215 def debugx(expr,pre_msg=''):
219 def debugx(expr,pre_msg=''):
216 """Print the value of an expression from the caller's frame.
220 """Print the value of an expression from the caller's frame.
217
221
218 Takes an expression, evaluates it in the caller's frame and prints both
222 Takes an expression, evaluates it in the caller's frame and prints both
219 the given expression and the resulting value (as well as a debug mark
223 the given expression and the resulting value (as well as a debug mark
220 indicating the name of the calling function. The input must be of a form
224 indicating the name of the calling function. The input must be of a form
221 suitable for eval().
225 suitable for eval().
222
226
223 An optional message can be passed, which will be prepended to the printed
227 An optional message can be passed, which will be prepended to the printed
224 expr->value pair."""
228 expr->value pair."""
225
229
226 cf = sys._getframe(1)
230 cf = sys._getframe(1)
227 print '[DBG:%s] %s%s -> %r' % (cf.f_code.co_name,pre_msg,expr,
231 print '[DBG:%s] %s%s -> %r' % (cf.f_code.co_name,pre_msg,expr,
228 eval(expr,cf.f_globals,cf.f_locals))
232 eval(expr,cf.f_globals,cf.f_locals))
229
233
230 # deactivate it by uncommenting the following line, which makes it a no-op
234 # deactivate it by uncommenting the following line, which makes it a no-op
231 #def debugx(expr,pre_msg=''): pass
235 #def debugx(expr,pre_msg=''): pass
232
236
233 #----------------------------------------------------------------------------
237 #----------------------------------------------------------------------------
234 StringTypes = types.StringTypes
238 StringTypes = types.StringTypes
235
239
236 # Basic timing functionality
240 # Basic timing functionality
237
241
238 # If possible (Unix), use the resource module instead of time.clock()
242 # If possible (Unix), use the resource module instead of time.clock()
239 try:
243 try:
240 import resource
244 import resource
241 def clocku():
245 def clocku():
242 """clocku() -> floating point number
246 """clocku() -> floating point number
243
247
244 Return the *USER* CPU time in seconds since the start of the process.
248 Return the *USER* CPU time in seconds since the start of the process.
245 This is done via a call to resource.getrusage, so it avoids the
249 This is done via a call to resource.getrusage, so it avoids the
246 wraparound problems in time.clock()."""
250 wraparound problems in time.clock()."""
247
251
248 return resource.getrusage(resource.RUSAGE_SELF)[0]
252 return resource.getrusage(resource.RUSAGE_SELF)[0]
249
253
250 def clocks():
254 def clocks():
251 """clocks() -> floating point number
255 """clocks() -> floating point number
252
256
253 Return the *SYSTEM* CPU time in seconds since the start of the process.
257 Return the *SYSTEM* CPU time in seconds since the start of the process.
254 This is done via a call to resource.getrusage, so it avoids the
258 This is done via a call to resource.getrusage, so it avoids the
255 wraparound problems in time.clock()."""
259 wraparound problems in time.clock()."""
256
260
257 return resource.getrusage(resource.RUSAGE_SELF)[1]
261 return resource.getrusage(resource.RUSAGE_SELF)[1]
258
262
259 def clock():
263 def clock():
260 """clock() -> floating point number
264 """clock() -> floating point number
261
265
262 Return the *TOTAL USER+SYSTEM* CPU time in seconds since the start of
266 Return the *TOTAL USER+SYSTEM* CPU time in seconds since the start of
263 the process. This is done via a call to resource.getrusage, so it
267 the process. This is done via a call to resource.getrusage, so it
264 avoids the wraparound problems in time.clock()."""
268 avoids the wraparound problems in time.clock()."""
265
269
266 u,s = resource.getrusage(resource.RUSAGE_SELF)[:2]
270 u,s = resource.getrusage(resource.RUSAGE_SELF)[:2]
267 return u+s
271 return u+s
268
272
269 def clock2():
273 def clock2():
270 """clock2() -> (t_user,t_system)
274 """clock2() -> (t_user,t_system)
271
275
272 Similar to clock(), but return a tuple of user/system times."""
276 Similar to clock(), but return a tuple of user/system times."""
273 return resource.getrusage(resource.RUSAGE_SELF)[:2]
277 return resource.getrusage(resource.RUSAGE_SELF)[:2]
274
278
275 except ImportError:
279 except ImportError:
276 # There is no distinction of user/system time under windows, so we just use
280 # There is no distinction of user/system time under windows, so we just use
277 # time.clock() for everything...
281 # time.clock() for everything...
278 clocku = clocks = clock = time.clock
282 clocku = clocks = clock = time.clock
279 def clock2():
283 def clock2():
280 """Under windows, system CPU time can't be measured.
284 """Under windows, system CPU time can't be measured.
281
285
282 This just returns clock() and zero."""
286 This just returns clock() and zero."""
283 return time.clock(),0.0
287 return time.clock(),0.0
284
288
289
285 def timings_out(reps,func,*args,**kw):
290 def timings_out(reps,func,*args,**kw):
286 """timings_out(reps,func,*args,**kw) -> (t_total,t_per_call,output)
291 """timings_out(reps,func,*args,**kw) -> (t_total,t_per_call,output)
287
292
288 Execute a function reps times, return a tuple with the elapsed total
293 Execute a function reps times, return a tuple with the elapsed total
289 CPU time in seconds, the time per call and the function's output.
294 CPU time in seconds, the time per call and the function's output.
290
295
291 Under Unix, the return value is the sum of user+system time consumed by
296 Under Unix, the return value is the sum of user+system time consumed by
292 the process, computed via the resource module. This prevents problems
297 the process, computed via the resource module. This prevents problems
293 related to the wraparound effect which the time.clock() function has.
298 related to the wraparound effect which the time.clock() function has.
294
299
295 Under Windows the return value is in wall clock seconds. See the
300 Under Windows the return value is in wall clock seconds. See the
296 documentation for the time module for more details."""
301 documentation for the time module for more details."""
297
302
298 reps = int(reps)
303 reps = int(reps)
299 assert reps >=1, 'reps must be >= 1'
304 assert reps >=1, 'reps must be >= 1'
300 if reps==1:
305 if reps==1:
301 start = clock()
306 start = clock()
302 out = func(*args,**kw)
307 out = func(*args,**kw)
303 tot_time = clock()-start
308 tot_time = clock()-start
304 else:
309 else:
305 rng = xrange(reps-1) # the last time is executed separately to store output
310 rng = xrange(reps-1) # the last time is executed separately to store output
306 start = clock()
311 start = clock()
307 for dummy in rng: func(*args,**kw)
312 for dummy in rng: func(*args,**kw)
308 out = func(*args,**kw) # one last time
313 out = func(*args,**kw) # one last time
309 tot_time = clock()-start
314 tot_time = clock()-start
310 av_time = tot_time / reps
315 av_time = tot_time / reps
311 return tot_time,av_time,out
316 return tot_time,av_time,out
312
317
318
313 def timings(reps,func,*args,**kw):
319 def timings(reps,func,*args,**kw):
314 """timings(reps,func,*args,**kw) -> (t_total,t_per_call)
320 """timings(reps,func,*args,**kw) -> (t_total,t_per_call)
315
321
316 Execute a function reps times, return a tuple with the elapsed total CPU
322 Execute a function reps times, return a tuple with the elapsed total CPU
317 time in seconds and the time per call. These are just the first two values
323 time in seconds and the time per call. These are just the first two values
318 in timings_out()."""
324 in timings_out()."""
319
325
320 return timings_out(reps,func,*args,**kw)[0:2]
326 return timings_out(reps,func,*args,**kw)[0:2]
321
327
328
322 def timing(func,*args,**kw):
329 def timing(func,*args,**kw):
323 """timing(func,*args,**kw) -> t_total
330 """timing(func,*args,**kw) -> t_total
324
331
325 Execute a function once, return the elapsed total CPU time in
332 Execute a function once, return the elapsed total CPU time in
326 seconds. This is just the first value in timings_out()."""
333 seconds. This is just the first value in timings_out()."""
327
334
328 return timings_out(1,func,*args,**kw)[0]
335 return timings_out(1,func,*args,**kw)[0]
329
336
330 #****************************************************************************
337 #****************************************************************************
331 # file and system
338 # file and system
332
339
333 def arg_split(s,posix=False):
340 def arg_split(s,posix=False):
334 """Split a command line's arguments in a shell-like manner.
341 """Split a command line's arguments in a shell-like manner.
335
342
336 This is a modified version of the standard library's shlex.split()
343 This is a modified version of the standard library's shlex.split()
337 function, but with a default of posix=False for splitting, so that quotes
344 function, but with a default of posix=False for splitting, so that quotes
338 in inputs are respected."""
345 in inputs are respected."""
339
346
340 # XXX - there may be unicode-related problems here!!! I'm not sure that
347 # XXX - there may be unicode-related problems here!!! I'm not sure that
341 # shlex is truly unicode-safe, so it might be necessary to do
348 # shlex is truly unicode-safe, so it might be necessary to do
342 #
349 #
343 # s = s.encode(sys.stdin.encoding)
350 # s = s.encode(sys.stdin.encoding)
344 #
351 #
345 # first, to ensure that shlex gets a normal string. Input from anyone who
352 # first, to ensure that shlex gets a normal string. Input from anyone who
346 # knows more about unicode and shlex than I would be good to have here...
353 # knows more about unicode and shlex than I would be good to have here...
347 lex = shlex.shlex(s, posix=posix)
354 lex = shlex.shlex(s, posix=posix)
348 lex.whitespace_split = True
355 lex.whitespace_split = True
349 return list(lex)
356 return list(lex)
350
357
358
351 def system(cmd,verbose=0,debug=0,header=''):
359 def system(cmd,verbose=0,debug=0,header=''):
352 """Execute a system command, return its exit status.
360 """Execute a system command, return its exit status.
353
361
354 Options:
362 Options:
355
363
356 - verbose (0): print the command to be executed.
364 - verbose (0): print the command to be executed.
357
365
358 - debug (0): only print, do not actually execute.
366 - debug (0): only print, do not actually execute.
359
367
360 - header (''): Header to print on screen prior to the executed command (it
368 - header (''): Header to print on screen prior to the executed command (it
361 is only prepended to the command, no newlines are added).
369 is only prepended to the command, no newlines are added).
362
370
363 Note: a stateful version of this function is available through the
371 Note: a stateful version of this function is available through the
364 SystemExec class."""
372 SystemExec class."""
365
373
366 stat = 0
374 stat = 0
367 if verbose or debug: print header+cmd
375 if verbose or debug: print header+cmd
368 sys.stdout.flush()
376 sys.stdout.flush()
369 if not debug: stat = os.system(cmd)
377 if not debug: stat = os.system(cmd)
370 return stat
378 return stat
371
379
380
372 def abbrev_cwd():
381 def abbrev_cwd():
373 """ Return abbreviated version of cwd, e.g. d:mydir """
382 """ Return abbreviated version of cwd, e.g. d:mydir """
374 cwd = os.getcwd().replace('\\','/')
383 cwd = os.getcwd().replace('\\','/')
375 drivepart = ''
384 drivepart = ''
376 tail = cwd
385 tail = cwd
377 if sys.platform == 'win32':
386 if sys.platform == 'win32':
378 if len(cwd) < 4:
387 if len(cwd) < 4:
379 return cwd
388 return cwd
380 drivepart,tail = os.path.splitdrive(cwd)
389 drivepart,tail = os.path.splitdrive(cwd)
381
390
382
391
383 parts = tail.split('/')
392 parts = tail.split('/')
384 if len(parts) > 2:
393 if len(parts) > 2:
385 tail = '/'.join(parts[-2:])
394 tail = '/'.join(parts[-2:])
386
395
387 return (drivepart + (
396 return (drivepart + (
388 cwd == '/' and '/' or tail))
397 cwd == '/' and '/' or tail))
389
398
390
399
391 # This function is used by ipython in a lot of places to make system calls.
400 # This function is used by ipython in a lot of places to make system calls.
392 # We need it to be slightly different under win32, due to the vagaries of
401 # We need it to be slightly different under win32, due to the vagaries of
393 # 'network shares'. A win32 override is below.
402 # 'network shares'. A win32 override is below.
394
403
395 def shell(cmd,verbose=0,debug=0,header=''):
404 def shell(cmd,verbose=0,debug=0,header=''):
396 """Execute a command in the system shell, always return None.
405 """Execute a command in the system shell, always return None.
397
406
398 Options:
407 Options:
399
408
400 - verbose (0): print the command to be executed.
409 - verbose (0): print the command to be executed.
401
410
402 - debug (0): only print, do not actually execute.
411 - debug (0): only print, do not actually execute.
403
412
404 - header (''): Header to print on screen prior to the executed command (it
413 - header (''): Header to print on screen prior to the executed command (it
405 is only prepended to the command, no newlines are added).
414 is only prepended to the command, no newlines are added).
406
415
407 Note: this is similar to genutils.system(), but it returns None so it can
416 Note: this is similar to genutils.system(), but it returns None so it can
408 be conveniently used in interactive loops without getting the return value
417 be conveniently used in interactive loops without getting the return value
409 (typically 0) printed many times."""
418 (typically 0) printed many times."""
410
419
411 stat = 0
420 stat = 0
412 if verbose or debug: print header+cmd
421 if verbose or debug: print header+cmd
413 # flush stdout so we don't mangle python's buffering
422 # flush stdout so we don't mangle python's buffering
414 sys.stdout.flush()
423 sys.stdout.flush()
415
424
416 if not debug:
425 if not debug:
417 platutils.set_term_title("IPy " + cmd)
426 platutils.set_term_title("IPy " + cmd)
418 os.system(cmd)
427 os.system(cmd)
419 platutils.set_term_title("IPy " + abbrev_cwd())
428 platutils.set_term_title("IPy " + abbrev_cwd())
420
429
421 # override shell() for win32 to deal with network shares
430 # override shell() for win32 to deal with network shares
422 if os.name in ('nt','dos'):
431 if os.name in ('nt','dos'):
423
432
424 shell_ori = shell
433 shell_ori = shell
425
434
426 def shell(cmd,verbose=0,debug=0,header=''):
435 def shell(cmd,verbose=0,debug=0,header=''):
427 if os.getcwd().startswith(r"\\"):
436 if os.getcwd().startswith(r"\\"):
428 path = os.getcwd()
437 path = os.getcwd()
429 # change to c drive (cannot be on UNC-share when issuing os.system,
438 # change to c drive (cannot be on UNC-share when issuing os.system,
430 # as cmd.exe cannot handle UNC addresses)
439 # as cmd.exe cannot handle UNC addresses)
431 os.chdir("c:")
440 os.chdir("c:")
432 # issue pushd to the UNC-share and then run the command
441 # issue pushd to the UNC-share and then run the command
433 try:
442 try:
434 shell_ori('"pushd %s&&"'%path+cmd,verbose,debug,header)
443 shell_ori('"pushd %s&&"'%path+cmd,verbose,debug,header)
435 finally:
444 finally:
436 os.chdir(path)
445 os.chdir(path)
437 else:
446 else:
438 shell_ori(cmd,verbose,debug,header)
447 shell_ori(cmd,verbose,debug,header)
439
448
440 shell.__doc__ = shell_ori.__doc__
449 shell.__doc__ = shell_ori.__doc__
441
450
451
442 def getoutput(cmd,verbose=0,debug=0,header='',split=0):
452 def getoutput(cmd,verbose=0,debug=0,header='',split=0):
443 """Dummy substitute for perl's backquotes.
453 """Dummy substitute for perl's backquotes.
444
454
445 Executes a command and returns the output.
455 Executes a command and returns the output.
446
456
447 Accepts the same arguments as system(), plus:
457 Accepts the same arguments as system(), plus:
448
458
449 - split(0): if true, the output is returned as a list split on newlines.
459 - split(0): if true, the output is returned as a list split on newlines.
450
460
451 Note: a stateful version of this function is available through the
461 Note: a stateful version of this function is available through the
452 SystemExec class.
462 SystemExec class.
453
463
454 This is pretty much deprecated and rarely used,
464 This is pretty much deprecated and rarely used,
455 genutils.getoutputerror may be what you need.
465 genutils.getoutputerror may be what you need.
456
466
457 """
467 """
458
468
459 if verbose or debug: print header+cmd
469 if verbose or debug: print header+cmd
460 if not debug:
470 if not debug:
461 pipe = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE).stdout
471 pipe = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE).stdout
462 output = pipe.read()
472 output = pipe.read()
463 # stipping last \n is here for backwards compat.
473 # stipping last \n is here for backwards compat.
464 if output.endswith('\n'):
474 if output.endswith('\n'):
465 output = output[:-1]
475 output = output[:-1]
466 if split:
476 if split:
467 return output.split('\n')
477 return output.split('\n')
468 else:
478 else:
469 return output
479 return output
470
480
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
481 # for compatibility with older naming conventions
507 xsys = system
482 xsys = system
508 bq = getoutput
483 bq = getoutput
509
484
485
510 class SystemExec:
486 class SystemExec:
511 """Access the system and getoutput functions through a stateful interface.
487 """Access the system and getoutput functions through a stateful interface.
512
488
513 Note: here we refer to the system and getoutput functions from this
489 Note: here we refer to the system and getoutput functions from this
514 library, not the ones from the standard python library.
490 library, not the ones from the standard python library.
515
491
516 This class offers the system and getoutput functions as methods, but the
492 This class offers the system and getoutput functions as methods, but the
517 verbose, debug and header parameters can be set for the instance (at
493 verbose, debug and header parameters can be set for the instance (at
518 creation time or later) so that they don't need to be specified on each
494 creation time or later) so that they don't need to be specified on each
519 call.
495 call.
520
496
521 For efficiency reasons, there's no way to override the parameters on a
497 For efficiency reasons, there's no way to override the parameters on a
522 per-call basis other than by setting instance attributes. If you need
498 per-call basis other than by setting instance attributes. If you need
523 local overrides, it's best to directly call system() or getoutput().
499 local overrides, it's best to directly call system() or getoutput().
524
500
525 The following names are provided as alternate options:
501 The following names are provided as alternate options:
526 - xsys: alias to system
502 - xsys: alias to system
527 - bq: alias to getoutput
503 - bq: alias to getoutput
528
504
529 An instance can then be created as:
505 An instance can then be created as:
530 >>> sysexec = SystemExec(verbose=1,debug=0,header='Calling: ')
506 >>> sysexec = SystemExec(verbose=1,debug=0,header='Calling: ')
531 """
507 """
532
508
533 def __init__(self,verbose=0,debug=0,header='',split=0):
509 def __init__(self,verbose=0,debug=0,header='',split=0):
534 """Specify the instance's values for verbose, debug and header."""
510 """Specify the instance's values for verbose, debug and header."""
535 setattr_list(self,'verbose debug header split')
511 setattr_list(self,'verbose debug header split')
536
512
537 def system(self,cmd):
513 def system(self,cmd):
538 """Stateful interface to system(), with the same keyword parameters."""
514 """Stateful interface to system(), with the same keyword parameters."""
539
515
540 system(cmd,self.verbose,self.debug,self.header)
516 system(cmd,self.verbose,self.debug,self.header)
541
517
542 def shell(self,cmd):
518 def shell(self,cmd):
543 """Stateful interface to shell(), with the same keyword parameters."""
519 """Stateful interface to shell(), with the same keyword parameters."""
544
520
545 shell(cmd,self.verbose,self.debug,self.header)
521 shell(cmd,self.verbose,self.debug,self.header)
546
522
547 xsys = system # alias
523 xsys = system # alias
548
524
549 def getoutput(self,cmd):
525 def getoutput(self,cmd):
550 """Stateful interface to getoutput()."""
526 """Stateful interface to getoutput()."""
551
527
552 return getoutput(cmd,self.verbose,self.debug,self.header,self.split)
528 return getoutput(cmd,self.verbose,self.debug,self.header,self.split)
553
529
554 def getoutputerror(self,cmd):
530 def getoutputerror(self,cmd):
555 """Stateful interface to getoutputerror()."""
531 """Stateful interface to getoutputerror()."""
556
532
557 return getoutputerror(cmd,self.verbose,self.debug,self.header,self.split)
533 return getoutputerror(cmd,self.verbose,self.debug,self.header,self.split)
558
534
559 bq = getoutput # alias
535 bq = getoutput # alias
560
536
561 #-----------------------------------------------------------------------------
537 #-----------------------------------------------------------------------------
562 def mutex_opts(dict,ex_op):
538 def mutex_opts(dict,ex_op):
563 """Check for presence of mutually exclusive keys in a dict.
539 """Check for presence of mutually exclusive keys in a dict.
564
540
565 Call: mutex_opts(dict,[[op1a,op1b],[op2a,op2b]...]"""
541 Call: mutex_opts(dict,[[op1a,op1b],[op2a,op2b]...]"""
566 for op1,op2 in ex_op:
542 for op1,op2 in ex_op:
567 if op1 in dict and op2 in dict:
543 if op1 in dict and op2 in dict:
568 raise ValueError,'\n*** ERROR in Arguments *** '\
544 raise ValueError,'\n*** ERROR in Arguments *** '\
569 'Options '+op1+' and '+op2+' are mutually exclusive.'
545 'Options '+op1+' and '+op2+' are mutually exclusive.'
570
546
571 #-----------------------------------------------------------------------------
547 #-----------------------------------------------------------------------------
572 def get_py_filename(name):
548 def get_py_filename(name):
573 """Return a valid python filename in the current directory.
549 """Return a valid python filename in the current directory.
574
550
575 If the given name is not a file, it adds '.py' and searches again.
551 If the given name is not a file, it adds '.py' and searches again.
576 Raises IOError with an informative message if the file isn't found."""
552 Raises IOError with an informative message if the file isn't found."""
577
553
578 name = os.path.expanduser(name)
554 name = os.path.expanduser(name)
579 if not os.path.isfile(name) and not name.endswith('.py'):
555 if not os.path.isfile(name) and not name.endswith('.py'):
580 name += '.py'
556 name += '.py'
581 if os.path.isfile(name):
557 if os.path.isfile(name):
582 return name
558 return name
583 else:
559 else:
584 raise IOError,'File `%s` not found.' % name
560 raise IOError,'File `%s` not found.' % name
585
561
586 #-----------------------------------------------------------------------------
562 #-----------------------------------------------------------------------------
587
563
588
564
589 def filefind(filename, path_dirs=None):
565 def filefind(filename, path_dirs=None):
590 """Find a file by looking through a sequence of paths.
566 """Find a file by looking through a sequence of paths.
591
567
592 This iterates through a sequence of paths looking for a file and returns
568 This iterates through a sequence of paths looking for a file and returns
593 the full, absolute path of the first occurence of the file. If no set of
569 the full, absolute path of the first occurence of the file. If no set of
594 path dirs is given, the filename is tested as is, after running through
570 path dirs is given, the filename is tested as is, after running through
595 :func:`expandvars` and :func:`expanduser`. Thus a simple call::
571 :func:`expandvars` and :func:`expanduser`. Thus a simple call::
596
572
597 filefind('myfile.txt')
573 filefind('myfile.txt')
598
574
599 will find the file in the current working dir, but::
575 will find the file in the current working dir, but::
600
576
601 filefind('~/myfile.txt')
577 filefind('~/myfile.txt')
602
578
603 Will find the file in the users home directory. This function does not
579 Will find the file in the users home directory. This function does not
604 automatically try any paths, such as the cwd or the user's home directory.
580 automatically try any paths, such as the cwd or the user's home directory.
605
581
606 Parameters
582 Parameters
607 ----------
583 ----------
608 filename : str
584 filename : str
609 The filename to look for.
585 The filename to look for.
610 path_dirs : str, None or sequence of str
586 path_dirs : str, None or sequence of str
611 The sequence of paths to look for the file in. If None, the filename
587 The sequence of paths to look for the file in. If None, the filename
612 need to be absolute or be in the cwd. If a string, the string is
588 need to be absolute or be in the cwd. If a string, the string is
613 put into a sequence and the searched. If a sequence, walk through
589 put into a sequence and the searched. If a sequence, walk through
614 each element and join with ``filename``, calling :func:`expandvars`
590 each element and join with ``filename``, calling :func:`expandvars`
615 and :func:`expanduser` before testing for existence.
591 and :func:`expanduser` before testing for existence.
616
592
617 Returns
593 Returns
618 -------
594 -------
619 Raises :exc:`IOError` or returns absolute path to file.
595 Raises :exc:`IOError` or returns absolute path to file.
620 """
596 """
621
597
622 # If paths are quoted, abspath gets confused, strip them...
598 # If paths are quoted, abspath gets confused, strip them...
623 filename = filename.strip('"').strip("'")
599 filename = filename.strip('"').strip("'")
624 # If the input is an absolute path, just check it exists
600 # If the input is an absolute path, just check it exists
625 if os.path.isabs(filename) and os.path.isfile(filename):
601 if os.path.isabs(filename) and os.path.isfile(filename):
626 return filename
602 return filename
627
603
628 if path_dirs is None:
604 if path_dirs is None:
629 path_dirs = ("",)
605 path_dirs = ("",)
630 elif isinstance(path_dirs, basestring):
606 elif isinstance(path_dirs, basestring):
631 path_dirs = (path_dirs,)
607 path_dirs = (path_dirs,)
632
608
633 for path in path_dirs:
609 for path in path_dirs:
634 if path == '.': path = os.getcwd()
610 if path == '.': path = os.getcwd()
635 testname = expand_path(os.path.join(path, filename))
611 testname = expand_path(os.path.join(path, filename))
636 if os.path.isfile(testname):
612 if os.path.isfile(testname):
637 return os.path.abspath(testname)
613 return os.path.abspath(testname)
638
614
639 raise IOError("File %r does not exist in any of the search paths: %r" %
615 raise IOError("File %r does not exist in any of the search paths: %r" %
640 (filename, path_dirs) )
616 (filename, path_dirs) )
641
617
642
618
643 #----------------------------------------------------------------------------
619 #----------------------------------------------------------------------------
644 def file_read(filename):
620 def file_read(filename):
645 """Read a file and close it. Returns the file source."""
621 """Read a file and close it. Returns the file source."""
646 fobj = open(filename,'r');
622 fobj = open(filename,'r');
647 source = fobj.read();
623 source = fobj.read();
648 fobj.close()
624 fobj.close()
649 return source
625 return source
650
626
651 def file_readlines(filename):
627 def file_readlines(filename):
652 """Read a file and close it. Returns the file source using readlines()."""
628 """Read a file and close it. Returns the file source using readlines()."""
653 fobj = open(filename,'r');
629 fobj = open(filename,'r');
654 lines = fobj.readlines();
630 lines = fobj.readlines();
655 fobj.close()
631 fobj.close()
656 return lines
632 return lines
657
633
658 #----------------------------------------------------------------------------
634 #----------------------------------------------------------------------------
659 def target_outdated(target,deps):
635 def target_outdated(target,deps):
660 """Determine whether a target is out of date.
636 """Determine whether a target is out of date.
661
637
662 target_outdated(target,deps) -> 1/0
638 target_outdated(target,deps) -> 1/0
663
639
664 deps: list of filenames which MUST exist.
640 deps: list of filenames which MUST exist.
665 target: single filename which may or may not exist.
641 target: single filename which may or may not exist.
666
642
667 If target doesn't exist or is older than any file listed in deps, return
643 If target doesn't exist or is older than any file listed in deps, return
668 true, otherwise return false.
644 true, otherwise return false.
669 """
645 """
670 try:
646 try:
671 target_time = os.path.getmtime(target)
647 target_time = os.path.getmtime(target)
672 except os.error:
648 except os.error:
673 return 1
649 return 1
674 for dep in deps:
650 for dep in deps:
675 dep_time = os.path.getmtime(dep)
651 dep_time = os.path.getmtime(dep)
676 if dep_time > target_time:
652 if dep_time > target_time:
677 #print "For target",target,"Dep failed:",dep # dbg
653 #print "For target",target,"Dep failed:",dep # dbg
678 #print "times (dep,tar):",dep_time,target_time # dbg
654 #print "times (dep,tar):",dep_time,target_time # dbg
679 return 1
655 return 1
680 return 0
656 return 0
681
657
682 #-----------------------------------------------------------------------------
658 #-----------------------------------------------------------------------------
683 def target_update(target,deps,cmd):
659 def target_update(target,deps,cmd):
684 """Update a target with a given command given a list of dependencies.
660 """Update a target with a given command given a list of dependencies.
685
661
686 target_update(target,deps,cmd) -> runs cmd if target is outdated.
662 target_update(target,deps,cmd) -> runs cmd if target is outdated.
687
663
688 This is just a wrapper around target_outdated() which calls the given
664 This is just a wrapper around target_outdated() which calls the given
689 command if target is outdated."""
665 command if target is outdated."""
690
666
691 if target_outdated(target,deps):
667 if target_outdated(target,deps):
692 xsys(cmd)
668 xsys(cmd)
693
669
694 #----------------------------------------------------------------------------
670 #----------------------------------------------------------------------------
695 def unquote_ends(istr):
671 def unquote_ends(istr):
696 """Remove a single pair of quotes from the endpoints of a string."""
672 """Remove a single pair of quotes from the endpoints of a string."""
697
673
698 if not istr:
674 if not istr:
699 return istr
675 return istr
700 if (istr[0]=="'" and istr[-1]=="'") or \
676 if (istr[0]=="'" and istr[-1]=="'") or \
701 (istr[0]=='"' and istr[-1]=='"'):
677 (istr[0]=='"' and istr[-1]=='"'):
702 return istr[1:-1]
678 return istr[1:-1]
703 else:
679 else:
704 return istr
680 return istr
705
681
706 #----------------------------------------------------------------------------
682 #----------------------------------------------------------------------------
707 def flag_calls(func):
683 def flag_calls(func):
708 """Wrap a function to detect and flag when it gets called.
684 """Wrap a function to detect and flag when it gets called.
709
685
710 This is a decorator which takes a function and wraps it in a function with
686 This is a decorator which takes a function and wraps it in a function with
711 a 'called' attribute. wrapper.called is initialized to False.
687 a 'called' attribute. wrapper.called is initialized to False.
712
688
713 The wrapper.called attribute is set to False right before each call to the
689 The wrapper.called attribute is set to False right before each call to the
714 wrapped function, so if the call fails it remains False. After the call
690 wrapped function, so if the call fails it remains False. After the call
715 completes, wrapper.called is set to True and the output is returned.
691 completes, wrapper.called is set to True and the output is returned.
716
692
717 Testing for truth in wrapper.called allows you to determine if a call to
693 Testing for truth in wrapper.called allows you to determine if a call to
718 func() was attempted and succeeded."""
694 func() was attempted and succeeded."""
719
695
720 def wrapper(*args,**kw):
696 def wrapper(*args,**kw):
721 wrapper.called = False
697 wrapper.called = False
722 out = func(*args,**kw)
698 out = func(*args,**kw)
723 wrapper.called = True
699 wrapper.called = True
724 return out
700 return out
725
701
726 wrapper.called = False
702 wrapper.called = False
727 wrapper.__doc__ = func.__doc__
703 wrapper.__doc__ = func.__doc__
728 return wrapper
704 return wrapper
729
705
730 #----------------------------------------------------------------------------
706 #----------------------------------------------------------------------------
731 def dhook_wrap(func,*a,**k):
707 def dhook_wrap(func,*a,**k):
732 """Wrap a function call in a sys.displayhook controller.
708 """Wrap a function call in a sys.displayhook controller.
733
709
734 Returns a wrapper around func which calls func, with all its arguments and
710 Returns a wrapper around func which calls func, with all its arguments and
735 keywords unmodified, using the default sys.displayhook. Since IPython
711 keywords unmodified, using the default sys.displayhook. Since IPython
736 modifies sys.displayhook, it breaks the behavior of certain systems that
712 modifies sys.displayhook, it breaks the behavior of certain systems that
737 rely on the default behavior, notably doctest.
713 rely on the default behavior, notably doctest.
738 """
714 """
739
715
740 def f(*a,**k):
716 def f(*a,**k):
741
717
742 dhook_s = sys.displayhook
718 dhook_s = sys.displayhook
743 sys.displayhook = sys.__displayhook__
719 sys.displayhook = sys.__displayhook__
744 try:
720 try:
745 out = func(*a,**k)
721 out = func(*a,**k)
746 finally:
722 finally:
747 sys.displayhook = dhook_s
723 sys.displayhook = dhook_s
748
724
749 return out
725 return out
750
726
751 f.__doc__ = func.__doc__
727 f.__doc__ = func.__doc__
752 return f
728 return f
753
729
754 #----------------------------------------------------------------------------
730 #----------------------------------------------------------------------------
755 def doctest_reload():
731 def doctest_reload():
756 """Properly reload doctest to reuse it interactively.
732 """Properly reload doctest to reuse it interactively.
757
733
758 This routine:
734 This routine:
759
735
760 - imports doctest but does NOT reload it (see below).
736 - imports doctest but does NOT reload it (see below).
761
737
762 - resets its global 'master' attribute to None, so that multiple uses of
738 - resets its global 'master' attribute to None, so that multiple uses of
763 the module interactively don't produce cumulative reports.
739 the module interactively don't produce cumulative reports.
764
740
765 - Monkeypatches its core test runner method to protect it from IPython's
741 - Monkeypatches its core test runner method to protect it from IPython's
766 modified displayhook. Doctest expects the default displayhook behavior
742 modified displayhook. Doctest expects the default displayhook behavior
767 deep down, so our modification breaks it completely. For this reason, a
743 deep down, so our modification breaks it completely. For this reason, a
768 hard monkeypatch seems like a reasonable solution rather than asking
744 hard monkeypatch seems like a reasonable solution rather than asking
769 users to manually use a different doctest runner when under IPython.
745 users to manually use a different doctest runner when under IPython.
770
746
771 Notes
747 Notes
772 -----
748 -----
773
749
774 This function *used to* reload doctest, but this has been disabled because
750 This function *used to* reload doctest, but this has been disabled because
775 reloading doctest unconditionally can cause massive breakage of other
751 reloading doctest unconditionally can cause massive breakage of other
776 doctest-dependent modules already in memory, such as those for IPython's
752 doctest-dependent modules already in memory, such as those for IPython's
777 own testing system. The name wasn't changed to avoid breaking people's
753 own testing system. The name wasn't changed to avoid breaking people's
778 code, but the reload call isn't actually made anymore."""
754 code, but the reload call isn't actually made anymore."""
779
755
780 import doctest
756 import doctest
781 doctest.master = None
757 doctest.master = None
782 doctest.DocTestRunner.run = dhook_wrap(doctest.DocTestRunner.run)
758 doctest.DocTestRunner.run = dhook_wrap(doctest.DocTestRunner.run)
783
759
784 #----------------------------------------------------------------------------
760 #----------------------------------------------------------------------------
785 class HomeDirError(Error):
761 class HomeDirError(Error):
786 pass
762 pass
787
763
788 def get_home_dir():
764 def get_home_dir():
789 """Return the closest possible equivalent to a 'home' directory.
765 """Return the closest possible equivalent to a 'home' directory.
790
766
791 * On POSIX, we try $HOME.
767 * On POSIX, we try $HOME.
792 * On Windows we try:
768 * On Windows we try:
793 - %HOME%: rare, but some people with unix-like setups may have defined it
769 - %HOME%: rare, but some people with unix-like setups may have defined it
794 - %HOMESHARE%
770 - %HOMESHARE%
795 - %HOMEDRIVE\%HOMEPATH%
771 - %HOMEDRIVE\%HOMEPATH%
796 - %USERPROFILE%
772 - %USERPROFILE%
797 - Registry hack
773 - Registry hack
798 * On Dos C:\
774 * On Dos C:\
799
775
800 Currently only Posix and NT are implemented, a HomeDirError exception is
776 Currently only Posix and NT are implemented, a HomeDirError exception is
801 raised for all other OSes.
777 raised for all other OSes.
802 """
778 """
803
779
804 isdir = os.path.isdir
780 isdir = os.path.isdir
805 env = os.environ
781 env = os.environ
806
782
807 # first, check py2exe distribution root directory for _ipython.
783 # first, check py2exe distribution root directory for _ipython.
808 # This overrides all. Normally does not exist.
784 # This overrides all. Normally does not exist.
809
785
810 if hasattr(sys, "frozen"): #Is frozen by py2exe
786 if hasattr(sys, "frozen"): #Is frozen by py2exe
811 if '\\library.zip\\' in IPython.__file__.lower():#libraries compressed to zip-file
787 if '\\library.zip\\' in IPython.__file__.lower():#libraries compressed to zip-file
812 root, rest = IPython.__file__.lower().split('library.zip')
788 root, rest = IPython.__file__.lower().split('library.zip')
813 else:
789 else:
814 root=os.path.join(os.path.split(IPython.__file__)[0],"../../")
790 root=os.path.join(os.path.split(IPython.__file__)[0],"../../")
815 root=os.path.abspath(root).rstrip('\\')
791 root=os.path.abspath(root).rstrip('\\')
816 if isdir(os.path.join(root, '_ipython')):
792 if isdir(os.path.join(root, '_ipython')):
817 os.environ["IPYKITROOT"] = root
793 os.environ["IPYKITROOT"] = root
818 return root.decode(sys.getfilesystemencoding())
794 return root.decode(sys.getfilesystemencoding())
819
795
820 if os.name == 'posix':
796 if os.name == 'posix':
821 # Linux, Unix, AIX, OS X
797 # Linux, Unix, AIX, OS X
822 try:
798 try:
823 homedir = env['HOME']
799 homedir = env['HOME']
824 except KeyError:
800 except KeyError:
825 raise HomeDirError('Undefined $HOME, IPython cannot proceed.')
801 raise HomeDirError('Undefined $HOME, IPython cannot proceed.')
826 else:
802 else:
827 return homedir.decode(sys.getfilesystemencoding())
803 return homedir.decode(sys.getfilesystemencoding())
828 elif os.name == 'nt':
804 elif os.name == 'nt':
829 # Now for win9x, XP, Vista, 7?
805 # Now for win9x, XP, Vista, 7?
830 # For some strange reason all of these return 'nt' for os.name.
806 # For some strange reason all of these return 'nt' for os.name.
831 # First look for a network home directory. This will return the UNC
807 # First look for a network home directory. This will return the UNC
832 # path (\\server\\Users\%username%) not the mapped path (Z:\). This
808 # path (\\server\\Users\%username%) not the mapped path (Z:\). This
833 # is needed when running IPython on cluster where all paths have to
809 # is needed when running IPython on cluster where all paths have to
834 # be UNC.
810 # be UNC.
835 try:
811 try:
836 # A user with a lot of unix tools in win32 may have defined $HOME,
812 # A user with a lot of unix tools in win32 may have defined $HOME,
837 # honor it if it exists, but otherwise let the more typical
813 # honor it if it exists, but otherwise let the more typical
838 # %HOMESHARE% variable be used.
814 # %HOMESHARE% variable be used.
839 homedir = env.get('HOME')
815 homedir = env.get('HOME')
840 if homedir is None:
816 if homedir is None:
841 homedir = env['HOMESHARE']
817 homedir = env['HOMESHARE']
842 except KeyError:
818 except KeyError:
843 pass
819 pass
844 else:
820 else:
845 if isdir(homedir):
821 if isdir(homedir):
846 return homedir.decode(sys.getfilesystemencoding())
822 return homedir.decode(sys.getfilesystemencoding())
847
823
848 # Now look for a local home directory
824 # Now look for a local home directory
849 try:
825 try:
850 homedir = os.path.join(env['HOMEDRIVE'],env['HOMEPATH'])
826 homedir = os.path.join(env['HOMEDRIVE'],env['HOMEPATH'])
851 except KeyError:
827 except KeyError:
852 pass
828 pass
853 else:
829 else:
854 if isdir(homedir):
830 if isdir(homedir):
855 return homedir.decode(sys.getfilesystemencoding())
831 return homedir.decode(sys.getfilesystemencoding())
856
832
857 # Now the users profile directory
833 # Now the users profile directory
858 try:
834 try:
859 homedir = os.path.join(env['USERPROFILE'])
835 homedir = os.path.join(env['USERPROFILE'])
860 except KeyError:
836 except KeyError:
861 pass
837 pass
862 else:
838 else:
863 if isdir(homedir):
839 if isdir(homedir):
864 return homedir.decode(sys.getfilesystemencoding())
840 return homedir.decode(sys.getfilesystemencoding())
865
841
866 # Use the registry to get the 'My Documents' folder.
842 # Use the registry to get the 'My Documents' folder.
867 try:
843 try:
868 import _winreg as wreg
844 import _winreg as wreg
869 key = wreg.OpenKey(
845 key = wreg.OpenKey(
870 wreg.HKEY_CURRENT_USER,
846 wreg.HKEY_CURRENT_USER,
871 "Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders"
847 "Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders"
872 )
848 )
873 homedir = wreg.QueryValueEx(key,'Personal')[0]
849 homedir = wreg.QueryValueEx(key,'Personal')[0]
874 key.Close()
850 key.Close()
875 except:
851 except:
876 pass
852 pass
877 else:
853 else:
878 if isdir(homedir):
854 if isdir(homedir):
879 return homedir.decode(sys.getfilesystemencoding())
855 return homedir.decode(sys.getfilesystemencoding())
880
856
881 # If all else fails, raise HomeDirError
857 # If all else fails, raise HomeDirError
882 raise HomeDirError('No valid home directory could be found')
858 raise HomeDirError('No valid home directory could be found')
883 elif os.name == 'dos':
859 elif os.name == 'dos':
884 # Desperate, may do absurd things in classic MacOS. May work under DOS.
860 # Desperate, may do absurd things in classic MacOS. May work under DOS.
885 return 'C:\\'.decode(sys.getfilesystemencoding())
861 return 'C:\\'.decode(sys.getfilesystemencoding())
886 else:
862 else:
887 raise HomeDirError('No valid home directory could be found for your OS')
863 raise HomeDirError('No valid home directory could be found for your OS')
888
864
889
865
890 def get_ipython_dir():
866 def get_ipython_dir():
891 """Get the IPython directory for this platform and user.
867 """Get the IPython directory for this platform and user.
892
868
893 This uses the logic in `get_home_dir` to find the home directory
869 This uses the logic in `get_home_dir` to find the home directory
894 and the adds .ipython to the end of the path.
870 and the adds .ipython to the end of the path.
895 """
871 """
896 ipdir_def = '.ipython'
872 ipdir_def = '.ipython'
897 home_dir = get_home_dir()
873 home_dir = get_home_dir()
898 #import pdb; pdb.set_trace() # dbg
874 #import pdb; pdb.set_trace() # dbg
899 ipdir = os.environ.get(
875 ipdir = os.environ.get(
900 'IPYTHON_DIR', os.environ.get(
876 'IPYTHON_DIR', os.environ.get(
901 'IPYTHONDIR', os.path.join(home_dir, ipdir_def)
877 'IPYTHONDIR', os.path.join(home_dir, ipdir_def)
902 )
878 )
903 )
879 )
904 return ipdir.decode(sys.getfilesystemencoding())
880 return ipdir.decode(sys.getfilesystemencoding())
905
881
906
882
907 def get_ipython_package_dir():
883 def get_ipython_package_dir():
908 """Get the base directory where IPython itself is installed."""
884 """Get the base directory where IPython itself is installed."""
909 ipdir = os.path.dirname(IPython.__file__)
885 ipdir = os.path.dirname(IPython.__file__)
910 return ipdir.decode(sys.getfilesystemencoding())
886 return ipdir.decode(sys.getfilesystemencoding())
911
887
912
888
913 #****************************************************************************
889 #****************************************************************************
914 # strings and text
890 # strings and text
915
891
916 class LSString(str):
892 class LSString(str):
917 """String derivative with a special access attributes.
893 """String derivative with a special access attributes.
918
894
919 These are normal strings, but with the special attributes:
895 These are normal strings, but with the special attributes:
920
896
921 .l (or .list) : value as list (split on newlines).
897 .l (or .list) : value as list (split on newlines).
922 .n (or .nlstr): original value (the string itself).
898 .n (or .nlstr): original value (the string itself).
923 .s (or .spstr): value as whitespace-separated string.
899 .s (or .spstr): value as whitespace-separated string.
924 .p (or .paths): list of path objects
900 .p (or .paths): list of path objects
925
901
926 Any values which require transformations are computed only once and
902 Any values which require transformations are computed only once and
927 cached.
903 cached.
928
904
929 Such strings are very useful to efficiently interact with the shell, which
905 Such strings are very useful to efficiently interact with the shell, which
930 typically only understands whitespace-separated options for commands."""
906 typically only understands whitespace-separated options for commands."""
931
907
932 def get_list(self):
908 def get_list(self):
933 try:
909 try:
934 return self.__list
910 return self.__list
935 except AttributeError:
911 except AttributeError:
936 self.__list = self.split('\n')
912 self.__list = self.split('\n')
937 return self.__list
913 return self.__list
938
914
939 l = list = property(get_list)
915 l = list = property(get_list)
940
916
941 def get_spstr(self):
917 def get_spstr(self):
942 try:
918 try:
943 return self.__spstr
919 return self.__spstr
944 except AttributeError:
920 except AttributeError:
945 self.__spstr = self.replace('\n',' ')
921 self.__spstr = self.replace('\n',' ')
946 return self.__spstr
922 return self.__spstr
947
923
948 s = spstr = property(get_spstr)
924 s = spstr = property(get_spstr)
949
925
950 def get_nlstr(self):
926 def get_nlstr(self):
951 return self
927 return self
952
928
953 n = nlstr = property(get_nlstr)
929 n = nlstr = property(get_nlstr)
954
930
955 def get_paths(self):
931 def get_paths(self):
956 try:
932 try:
957 return self.__paths
933 return self.__paths
958 except AttributeError:
934 except AttributeError:
959 self.__paths = [path(p) for p in self.split('\n') if os.path.exists(p)]
935 self.__paths = [path(p) for p in self.split('\n') if os.path.exists(p)]
960 return self.__paths
936 return self.__paths
961
937
962 p = paths = property(get_paths)
938 p = paths = property(get_paths)
963
939
964 def print_lsstring(arg):
940 def print_lsstring(arg):
965 """ Prettier (non-repr-like) and more informative printer for LSString """
941 """ Prettier (non-repr-like) and more informative printer for LSString """
966 print "LSString (.p, .n, .l, .s available). Value:"
942 print "LSString (.p, .n, .l, .s available). Value:"
967 print arg
943 print arg
968
944
969 print_lsstring = result_display.when_type(LSString)(print_lsstring)
945 print_lsstring = result_display.when_type(LSString)(print_lsstring)
970
946
971 #----------------------------------------------------------------------------
947 #----------------------------------------------------------------------------
972 class SList(list):
948 class SList(list):
973 """List derivative with a special access attributes.
949 """List derivative with a special access attributes.
974
950
975 These are normal lists, but with the special attributes:
951 These are normal lists, but with the special attributes:
976
952
977 .l (or .list) : value as list (the list itself).
953 .l (or .list) : value as list (the list itself).
978 .n (or .nlstr): value as a string, joined on newlines.
954 .n (or .nlstr): value as a string, joined on newlines.
979 .s (or .spstr): value as a string, joined on spaces.
955 .s (or .spstr): value as a string, joined on spaces.
980 .p (or .paths): list of path objects
956 .p (or .paths): list of path objects
981
957
982 Any values which require transformations are computed only once and
958 Any values which require transformations are computed only once and
983 cached."""
959 cached."""
984
960
985 def get_list(self):
961 def get_list(self):
986 return self
962 return self
987
963
988 l = list = property(get_list)
964 l = list = property(get_list)
989
965
990 def get_spstr(self):
966 def get_spstr(self):
991 try:
967 try:
992 return self.__spstr
968 return self.__spstr
993 except AttributeError:
969 except AttributeError:
994 self.__spstr = ' '.join(self)
970 self.__spstr = ' '.join(self)
995 return self.__spstr
971 return self.__spstr
996
972
997 s = spstr = property(get_spstr)
973 s = spstr = property(get_spstr)
998
974
999 def get_nlstr(self):
975 def get_nlstr(self):
1000 try:
976 try:
1001 return self.__nlstr
977 return self.__nlstr
1002 except AttributeError:
978 except AttributeError:
1003 self.__nlstr = '\n'.join(self)
979 self.__nlstr = '\n'.join(self)
1004 return self.__nlstr
980 return self.__nlstr
1005
981
1006 n = nlstr = property(get_nlstr)
982 n = nlstr = property(get_nlstr)
1007
983
1008 def get_paths(self):
984 def get_paths(self):
1009 try:
985 try:
1010 return self.__paths
986 return self.__paths
1011 except AttributeError:
987 except AttributeError:
1012 self.__paths = [path(p) for p in self if os.path.exists(p)]
988 self.__paths = [path(p) for p in self if os.path.exists(p)]
1013 return self.__paths
989 return self.__paths
1014
990
1015 p = paths = property(get_paths)
991 p = paths = property(get_paths)
1016
992
1017 def grep(self, pattern, prune = False, field = None):
993 def grep(self, pattern, prune = False, field = None):
1018 """ Return all strings matching 'pattern' (a regex or callable)
994 """ Return all strings matching 'pattern' (a regex or callable)
1019
995
1020 This is case-insensitive. If prune is true, return all items
996 This is case-insensitive. If prune is true, return all items
1021 NOT matching the pattern.
997 NOT matching the pattern.
1022
998
1023 If field is specified, the match must occur in the specified
999 If field is specified, the match must occur in the specified
1024 whitespace-separated field.
1000 whitespace-separated field.
1025
1001
1026 Examples::
1002 Examples::
1027
1003
1028 a.grep( lambda x: x.startswith('C') )
1004 a.grep( lambda x: x.startswith('C') )
1029 a.grep('Cha.*log', prune=1)
1005 a.grep('Cha.*log', prune=1)
1030 a.grep('chm', field=-1)
1006 a.grep('chm', field=-1)
1031 """
1007 """
1032
1008
1033 def match_target(s):
1009 def match_target(s):
1034 if field is None:
1010 if field is None:
1035 return s
1011 return s
1036 parts = s.split()
1012 parts = s.split()
1037 try:
1013 try:
1038 tgt = parts[field]
1014 tgt = parts[field]
1039 return tgt
1015 return tgt
1040 except IndexError:
1016 except IndexError:
1041 return ""
1017 return ""
1042
1018
1043 if isinstance(pattern, basestring):
1019 if isinstance(pattern, basestring):
1044 pred = lambda x : re.search(pattern, x, re.IGNORECASE)
1020 pred = lambda x : re.search(pattern, x, re.IGNORECASE)
1045 else:
1021 else:
1046 pred = pattern
1022 pred = pattern
1047 if not prune:
1023 if not prune:
1048 return SList([el for el in self if pred(match_target(el))])
1024 return SList([el for el in self if pred(match_target(el))])
1049 else:
1025 else:
1050 return SList([el for el in self if not pred(match_target(el))])
1026 return SList([el for el in self if not pred(match_target(el))])
1051 def fields(self, *fields):
1027 def fields(self, *fields):
1052 """ Collect whitespace-separated fields from string list
1028 """ Collect whitespace-separated fields from string list
1053
1029
1054 Allows quick awk-like usage of string lists.
1030 Allows quick awk-like usage of string lists.
1055
1031
1056 Example data (in var a, created by 'a = !ls -l')::
1032 Example data (in var a, created by 'a = !ls -l')::
1057 -rwxrwxrwx 1 ville None 18 Dec 14 2006 ChangeLog
1033 -rwxrwxrwx 1 ville None 18 Dec 14 2006 ChangeLog
1058 drwxrwxrwx+ 6 ville None 0 Oct 24 18:05 IPython
1034 drwxrwxrwx+ 6 ville None 0 Oct 24 18:05 IPython
1059
1035
1060 a.fields(0) is ['-rwxrwxrwx', 'drwxrwxrwx+']
1036 a.fields(0) is ['-rwxrwxrwx', 'drwxrwxrwx+']
1061 a.fields(1,0) is ['1 -rwxrwxrwx', '6 drwxrwxrwx+']
1037 a.fields(1,0) is ['1 -rwxrwxrwx', '6 drwxrwxrwx+']
1062 (note the joining by space).
1038 (note the joining by space).
1063 a.fields(-1) is ['ChangeLog', 'IPython']
1039 a.fields(-1) is ['ChangeLog', 'IPython']
1064
1040
1065 IndexErrors are ignored.
1041 IndexErrors are ignored.
1066
1042
1067 Without args, fields() just split()'s the strings.
1043 Without args, fields() just split()'s the strings.
1068 """
1044 """
1069 if len(fields) == 0:
1045 if len(fields) == 0:
1070 return [el.split() for el in self]
1046 return [el.split() for el in self]
1071
1047
1072 res = SList()
1048 res = SList()
1073 for el in [f.split() for f in self]:
1049 for el in [f.split() for f in self]:
1074 lineparts = []
1050 lineparts = []
1075
1051
1076 for fd in fields:
1052 for fd in fields:
1077 try:
1053 try:
1078 lineparts.append(el[fd])
1054 lineparts.append(el[fd])
1079 except IndexError:
1055 except IndexError:
1080 pass
1056 pass
1081 if lineparts:
1057 if lineparts:
1082 res.append(" ".join(lineparts))
1058 res.append(" ".join(lineparts))
1083
1059
1084 return res
1060 return res
1085 def sort(self,field= None, nums = False):
1061 def sort(self,field= None, nums = False):
1086 """ sort by specified fields (see fields())
1062 """ sort by specified fields (see fields())
1087
1063
1088 Example::
1064 Example::
1089 a.sort(1, nums = True)
1065 a.sort(1, nums = True)
1090
1066
1091 Sorts a by second field, in numerical order (so that 21 > 3)
1067 Sorts a by second field, in numerical order (so that 21 > 3)
1092
1068
1093 """
1069 """
1094
1070
1095 #decorate, sort, undecorate
1071 #decorate, sort, undecorate
1096 if field is not None:
1072 if field is not None:
1097 dsu = [[SList([line]).fields(field), line] for line in self]
1073 dsu = [[SList([line]).fields(field), line] for line in self]
1098 else:
1074 else:
1099 dsu = [[line, line] for line in self]
1075 dsu = [[line, line] for line in self]
1100 if nums:
1076 if nums:
1101 for i in range(len(dsu)):
1077 for i in range(len(dsu)):
1102 numstr = "".join([ch for ch in dsu[i][0] if ch.isdigit()])
1078 numstr = "".join([ch for ch in dsu[i][0] if ch.isdigit()])
1103 try:
1079 try:
1104 n = int(numstr)
1080 n = int(numstr)
1105 except ValueError:
1081 except ValueError:
1106 n = 0;
1082 n = 0;
1107 dsu[i][0] = n
1083 dsu[i][0] = n
1108
1084
1109
1085
1110 dsu.sort()
1086 dsu.sort()
1111 return SList([t[1] for t in dsu])
1087 return SList([t[1] for t in dsu])
1112
1088
1113 def print_slist(arg):
1089 def print_slist(arg):
1114 """ Prettier (non-repr-like) and more informative printer for SList """
1090 """ Prettier (non-repr-like) and more informative printer for SList """
1115 print "SList (.p, .n, .l, .s, .grep(), .fields(), sort() available):"
1091 print "SList (.p, .n, .l, .s, .grep(), .fields(), sort() available):"
1116 if hasattr(arg, 'hideonce') and arg.hideonce:
1092 if hasattr(arg, 'hideonce') and arg.hideonce:
1117 arg.hideonce = False
1093 arg.hideonce = False
1118 return
1094 return
1119
1095
1120 nlprint(arg)
1096 nlprint(arg)
1121
1097
1122 print_slist = result_display.when_type(SList)(print_slist)
1098 print_slist = result_display.when_type(SList)(print_slist)
1123
1099
1124
1100
1125
1101
1126 #----------------------------------------------------------------------------
1102 #----------------------------------------------------------------------------
1127 def esc_quotes(strng):
1103 def esc_quotes(strng):
1128 """Return the input string with single and double quotes escaped out"""
1104 """Return the input string with single and double quotes escaped out"""
1129
1105
1130 return strng.replace('"','\\"').replace("'","\\'")
1106 return strng.replace('"','\\"').replace("'","\\'")
1131
1107
1132 #----------------------------------------------------------------------------
1108 #----------------------------------------------------------------------------
1133 def make_quoted_expr(s):
1109 def make_quoted_expr(s):
1134 """Return string s in appropriate quotes, using raw string if possible.
1110 """Return string s in appropriate quotes, using raw string if possible.
1135
1111
1136 XXX - example removed because it caused encoding errors in documentation
1112 XXX - example removed because it caused encoding errors in documentation
1137 generation. We need a new example that doesn't contain invalid chars.
1113 generation. We need a new example that doesn't contain invalid chars.
1138
1114
1139 Note the use of raw string and padding at the end to allow trailing
1115 Note the use of raw string and padding at the end to allow trailing
1140 backslash.
1116 backslash.
1141 """
1117 """
1142
1118
1143 tail = ''
1119 tail = ''
1144 tailpadding = ''
1120 tailpadding = ''
1145 raw = ''
1121 raw = ''
1146 if "\\" in s:
1122 if "\\" in s:
1147 raw = 'r'
1123 raw = 'r'
1148 if s.endswith('\\'):
1124 if s.endswith('\\'):
1149 tail = '[:-1]'
1125 tail = '[:-1]'
1150 tailpadding = '_'
1126 tailpadding = '_'
1151 if '"' not in s:
1127 if '"' not in s:
1152 quote = '"'
1128 quote = '"'
1153 elif "'" not in s:
1129 elif "'" not in s:
1154 quote = "'"
1130 quote = "'"
1155 elif '"""' not in s and not s.endswith('"'):
1131 elif '"""' not in s and not s.endswith('"'):
1156 quote = '"""'
1132 quote = '"""'
1157 elif "'''" not in s and not s.endswith("'"):
1133 elif "'''" not in s and not s.endswith("'"):
1158 quote = "'''"
1134 quote = "'''"
1159 else:
1135 else:
1160 # give up, backslash-escaped string will do
1136 # give up, backslash-escaped string will do
1161 return '"%s"' % esc_quotes(s)
1137 return '"%s"' % esc_quotes(s)
1162 res = raw + quote + s + tailpadding + quote + tail
1138 res = raw + quote + s + tailpadding + quote + tail
1163 return res
1139 return res
1164
1140
1165
1141
1166 #----------------------------------------------------------------------------
1142 #----------------------------------------------------------------------------
1167 def raw_input_multi(header='', ps1='==> ', ps2='..> ',terminate_str = '.'):
1143 def raw_input_multi(header='', ps1='==> ', ps2='..> ',terminate_str = '.'):
1168 """Take multiple lines of input.
1144 """Take multiple lines of input.
1169
1145
1170 A list with each line of input as a separate element is returned when a
1146 A list with each line of input as a separate element is returned when a
1171 termination string is entered (defaults to a single '.'). Input can also
1147 termination string is entered (defaults to a single '.'). Input can also
1172 terminate via EOF (^D in Unix, ^Z-RET in Windows).
1148 terminate via EOF (^D in Unix, ^Z-RET in Windows).
1173
1149
1174 Lines of input which end in \\ are joined into single entries (and a
1150 Lines of input which end in \\ are joined into single entries (and a
1175 secondary continuation prompt is issued as long as the user terminates
1151 secondary continuation prompt is issued as long as the user terminates
1176 lines with \\). This allows entering very long strings which are still
1152 lines with \\). This allows entering very long strings which are still
1177 meant to be treated as single entities.
1153 meant to be treated as single entities.
1178 """
1154 """
1179
1155
1180 try:
1156 try:
1181 if header:
1157 if header:
1182 header += '\n'
1158 header += '\n'
1183 lines = [raw_input(header + ps1)]
1159 lines = [raw_input(header + ps1)]
1184 except EOFError:
1160 except EOFError:
1185 return []
1161 return []
1186 terminate = [terminate_str]
1162 terminate = [terminate_str]
1187 try:
1163 try:
1188 while lines[-1:] != terminate:
1164 while lines[-1:] != terminate:
1189 new_line = raw_input(ps1)
1165 new_line = raw_input(ps1)
1190 while new_line.endswith('\\'):
1166 while new_line.endswith('\\'):
1191 new_line = new_line[:-1] + raw_input(ps2)
1167 new_line = new_line[:-1] + raw_input(ps2)
1192 lines.append(new_line)
1168 lines.append(new_line)
1193
1169
1194 return lines[:-1] # don't return the termination command
1170 return lines[:-1] # don't return the termination command
1195 except EOFError:
1171 except EOFError:
1196 print
1172 print
1197 return lines
1173 return lines
1198
1174
1199 #----------------------------------------------------------------------------
1175 #----------------------------------------------------------------------------
1200 def raw_input_ext(prompt='', ps2='... '):
1176 def raw_input_ext(prompt='', ps2='... '):
1201 """Similar to raw_input(), but accepts extended lines if input ends with \\."""
1177 """Similar to raw_input(), but accepts extended lines if input ends with \\."""
1202
1178
1203 line = raw_input(prompt)
1179 line = raw_input(prompt)
1204 while line.endswith('\\'):
1180 while line.endswith('\\'):
1205 line = line[:-1] + raw_input(ps2)
1181 line = line[:-1] + raw_input(ps2)
1206 return line
1182 return line
1207
1183
1208 #----------------------------------------------------------------------------
1184 #----------------------------------------------------------------------------
1209 def ask_yes_no(prompt,default=None):
1185 def ask_yes_no(prompt,default=None):
1210 """Asks a question and returns a boolean (y/n) answer.
1186 """Asks a question and returns a boolean (y/n) answer.
1211
1187
1212 If default is given (one of 'y','n'), it is used if the user input is
1188 If default is given (one of 'y','n'), it is used if the user input is
1213 empty. Otherwise the question is repeated until an answer is given.
1189 empty. Otherwise the question is repeated until an answer is given.
1214
1190
1215 An EOF is treated as the default answer. If there is no default, an
1191 An EOF is treated as the default answer. If there is no default, an
1216 exception is raised to prevent infinite loops.
1192 exception is raised to prevent infinite loops.
1217
1193
1218 Valid answers are: y/yes/n/no (match is not case sensitive)."""
1194 Valid answers are: y/yes/n/no (match is not case sensitive)."""
1219
1195
1220 answers = {'y':True,'n':False,'yes':True,'no':False}
1196 answers = {'y':True,'n':False,'yes':True,'no':False}
1221 ans = None
1197 ans = None
1222 while ans not in answers.keys():
1198 while ans not in answers.keys():
1223 try:
1199 try:
1224 ans = raw_input(prompt+' ').lower()
1200 ans = raw_input(prompt+' ').lower()
1225 if not ans: # response was an empty string
1201 if not ans: # response was an empty string
1226 ans = default
1202 ans = default
1227 except KeyboardInterrupt:
1203 except KeyboardInterrupt:
1228 pass
1204 pass
1229 except EOFError:
1205 except EOFError:
1230 if default in answers.keys():
1206 if default in answers.keys():
1231 ans = default
1207 ans = default
1232 print
1208 print
1233 else:
1209 else:
1234 raise
1210 raise
1235
1211
1236 return answers[ans]
1212 return answers[ans]
1237
1213
1238 #----------------------------------------------------------------------------
1214 #----------------------------------------------------------------------------
1239 class EvalDict:
1215 class EvalDict:
1240 """
1216 """
1241 Emulate a dict which evaluates its contents in the caller's frame.
1217 Emulate a dict which evaluates its contents in the caller's frame.
1242
1218
1243 Usage:
1219 Usage:
1244 >>> number = 19
1220 >>> number = 19
1245
1221
1246 >>> text = "python"
1222 >>> text = "python"
1247
1223
1248 >>> print "%(text.capitalize())s %(number/9.0).1f rules!" % EvalDict()
1224 >>> print "%(text.capitalize())s %(number/9.0).1f rules!" % EvalDict()
1249 Python 2.1 rules!
1225 Python 2.1 rules!
1250 """
1226 """
1251
1227
1252 # This version is due to sismex01@hebmex.com on c.l.py, and is basically a
1228 # This version is due to sismex01@hebmex.com on c.l.py, and is basically a
1253 # modified (shorter) version of:
1229 # modified (shorter) version of:
1254 # http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/66018 by
1230 # http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/66018 by
1255 # Skip Montanaro (skip@pobox.com).
1231 # Skip Montanaro (skip@pobox.com).
1256
1232
1257 def __getitem__(self, name):
1233 def __getitem__(self, name):
1258 frame = sys._getframe(1)
1234 frame = sys._getframe(1)
1259 return eval(name, frame.f_globals, frame.f_locals)
1235 return eval(name, frame.f_globals, frame.f_locals)
1260
1236
1261 EvalString = EvalDict # for backwards compatibility
1237 EvalString = EvalDict # for backwards compatibility
1262 #----------------------------------------------------------------------------
1238 #----------------------------------------------------------------------------
1263 def qw(words,flat=0,sep=None,maxsplit=-1):
1239 def qw(words,flat=0,sep=None,maxsplit=-1):
1264 """Similar to Perl's qw() operator, but with some more options.
1240 """Similar to Perl's qw() operator, but with some more options.
1265
1241
1266 qw(words,flat=0,sep=' ',maxsplit=-1) -> words.split(sep,maxsplit)
1242 qw(words,flat=0,sep=' ',maxsplit=-1) -> words.split(sep,maxsplit)
1267
1243
1268 words can also be a list itself, and with flat=1, the output will be
1244 words can also be a list itself, and with flat=1, the output will be
1269 recursively flattened.
1245 recursively flattened.
1270
1246
1271 Examples:
1247 Examples:
1272
1248
1273 >>> qw('1 2')
1249 >>> qw('1 2')
1274 ['1', '2']
1250 ['1', '2']
1275
1251
1276 >>> qw(['a b','1 2',['m n','p q']])
1252 >>> qw(['a b','1 2',['m n','p q']])
1277 [['a', 'b'], ['1', '2'], [['m', 'n'], ['p', 'q']]]
1253 [['a', 'b'], ['1', '2'], [['m', 'n'], ['p', 'q']]]
1278
1254
1279 >>> qw(['a b','1 2',['m n','p q']],flat=1)
1255 >>> qw(['a b','1 2',['m n','p q']],flat=1)
1280 ['a', 'b', '1', '2', 'm', 'n', 'p', 'q']
1256 ['a', 'b', '1', '2', 'm', 'n', 'p', 'q']
1281 """
1257 """
1282
1258
1283 if type(words) in StringTypes:
1259 if type(words) in StringTypes:
1284 return [word.strip() for word in words.split(sep,maxsplit)
1260 return [word.strip() for word in words.split(sep,maxsplit)
1285 if word and not word.isspace() ]
1261 if word and not word.isspace() ]
1286 if flat:
1262 if flat:
1287 return flatten(map(qw,words,[1]*len(words)))
1263 return flatten(map(qw,words,[1]*len(words)))
1288 return map(qw,words)
1264 return map(qw,words)
1289
1265
1290 #----------------------------------------------------------------------------
1266 #----------------------------------------------------------------------------
1291 def qwflat(words,sep=None,maxsplit=-1):
1267 def qwflat(words,sep=None,maxsplit=-1):
1292 """Calls qw(words) in flat mode. It's just a convenient shorthand."""
1268 """Calls qw(words) in flat mode. It's just a convenient shorthand."""
1293 return qw(words,1,sep,maxsplit)
1269 return qw(words,1,sep,maxsplit)
1294
1270
1295 #----------------------------------------------------------------------------
1271 #----------------------------------------------------------------------------
1296 def qw_lol(indata):
1272 def qw_lol(indata):
1297 """qw_lol('a b') -> [['a','b']],
1273 """qw_lol('a b') -> [['a','b']],
1298 otherwise it's just a call to qw().
1274 otherwise it's just a call to qw().
1299
1275
1300 We need this to make sure the modules_some keys *always* end up as a
1276 We need this to make sure the modules_some keys *always* end up as a
1301 list of lists."""
1277 list of lists."""
1302
1278
1303 if type(indata) in StringTypes:
1279 if type(indata) in StringTypes:
1304 return [qw(indata)]
1280 return [qw(indata)]
1305 else:
1281 else:
1306 return qw(indata)
1282 return qw(indata)
1307
1283
1308 #----------------------------------------------------------------------------
1284 #----------------------------------------------------------------------------
1309 def grep(pat,list,case=1):
1285 def grep(pat,list,case=1):
1310 """Simple minded grep-like function.
1286 """Simple minded grep-like function.
1311 grep(pat,list) returns occurrences of pat in list, None on failure.
1287 grep(pat,list) returns occurrences of pat in list, None on failure.
1312
1288
1313 It only does simple string matching, with no support for regexps. Use the
1289 It only does simple string matching, with no support for regexps. Use the
1314 option case=0 for case-insensitive matching."""
1290 option case=0 for case-insensitive matching."""
1315
1291
1316 # This is pretty crude. At least it should implement copying only references
1292 # This is pretty crude. At least it should implement copying only references
1317 # to the original data in case it's big. Now it copies the data for output.
1293 # to the original data in case it's big. Now it copies the data for output.
1318 out=[]
1294 out=[]
1319 if case:
1295 if case:
1320 for term in list:
1296 for term in list:
1321 if term.find(pat)>-1: out.append(term)
1297 if term.find(pat)>-1: out.append(term)
1322 else:
1298 else:
1323 lpat=pat.lower()
1299 lpat=pat.lower()
1324 for term in list:
1300 for term in list:
1325 if term.lower().find(lpat)>-1: out.append(term)
1301 if term.lower().find(lpat)>-1: out.append(term)
1326
1302
1327 if len(out): return out
1303 if len(out): return out
1328 else: return None
1304 else: return None
1329
1305
1330 #----------------------------------------------------------------------------
1306 #----------------------------------------------------------------------------
1331 def dgrep(pat,*opts):
1307 def dgrep(pat,*opts):
1332 """Return grep() on dir()+dir(__builtins__).
1308 """Return grep() on dir()+dir(__builtins__).
1333
1309
1334 A very common use of grep() when working interactively."""
1310 A very common use of grep() when working interactively."""
1335
1311
1336 return grep(pat,dir(__main__)+dir(__main__.__builtins__),*opts)
1312 return grep(pat,dir(__main__)+dir(__main__.__builtins__),*opts)
1337
1313
1338 #----------------------------------------------------------------------------
1314 #----------------------------------------------------------------------------
1339 def idgrep(pat):
1315 def idgrep(pat):
1340 """Case-insensitive dgrep()"""
1316 """Case-insensitive dgrep()"""
1341
1317
1342 return dgrep(pat,0)
1318 return dgrep(pat,0)
1343
1319
1344 #----------------------------------------------------------------------------
1320 #----------------------------------------------------------------------------
1345 def igrep(pat,list):
1321 def igrep(pat,list):
1346 """Synonym for case-insensitive grep."""
1322 """Synonym for case-insensitive grep."""
1347
1323
1348 return grep(pat,list,case=0)
1324 return grep(pat,list,case=0)
1349
1325
1350 #----------------------------------------------------------------------------
1326 #----------------------------------------------------------------------------
1351 def indent(str,nspaces=4,ntabs=0):
1327 def indent(str,nspaces=4,ntabs=0):
1352 """Indent a string a given number of spaces or tabstops.
1328 """Indent a string a given number of spaces or tabstops.
1353
1329
1354 indent(str,nspaces=4,ntabs=0) -> indent str by ntabs+nspaces.
1330 indent(str,nspaces=4,ntabs=0) -> indent str by ntabs+nspaces.
1355 """
1331 """
1356 if str is None:
1332 if str is None:
1357 return
1333 return
1358 ind = '\t'*ntabs+' '*nspaces
1334 ind = '\t'*ntabs+' '*nspaces
1359 outstr = '%s%s' % (ind,str.replace(os.linesep,os.linesep+ind))
1335 outstr = '%s%s' % (ind,str.replace(os.linesep,os.linesep+ind))
1360 if outstr.endswith(os.linesep+ind):
1336 if outstr.endswith(os.linesep+ind):
1361 return outstr[:-len(ind)]
1337 return outstr[:-len(ind)]
1362 else:
1338 else:
1363 return outstr
1339 return outstr
1364
1340
1365 #-----------------------------------------------------------------------------
1341 #-----------------------------------------------------------------------------
1366 def native_line_ends(filename,backup=1):
1342 def native_line_ends(filename,backup=1):
1367 """Convert (in-place) a file to line-ends native to the current OS.
1343 """Convert (in-place) a file to line-ends native to the current OS.
1368
1344
1369 If the optional backup argument is given as false, no backup of the
1345 If the optional backup argument is given as false, no backup of the
1370 original file is left. """
1346 original file is left. """
1371
1347
1372 backup_suffixes = {'posix':'~','dos':'.bak','nt':'.bak','mac':'.bak'}
1348 backup_suffixes = {'posix':'~','dos':'.bak','nt':'.bak','mac':'.bak'}
1373
1349
1374 bak_filename = filename + backup_suffixes[os.name]
1350 bak_filename = filename + backup_suffixes[os.name]
1375
1351
1376 original = open(filename).read()
1352 original = open(filename).read()
1377 shutil.copy2(filename,bak_filename)
1353 shutil.copy2(filename,bak_filename)
1378 try:
1354 try:
1379 new = open(filename,'wb')
1355 new = open(filename,'wb')
1380 new.write(os.linesep.join(original.splitlines()))
1356 new.write(os.linesep.join(original.splitlines()))
1381 new.write(os.linesep) # ALWAYS put an eol at the end of the file
1357 new.write(os.linesep) # ALWAYS put an eol at the end of the file
1382 new.close()
1358 new.close()
1383 except:
1359 except:
1384 os.rename(bak_filename,filename)
1360 os.rename(bak_filename,filename)
1385 if not backup:
1361 if not backup:
1386 try:
1362 try:
1387 os.remove(bak_filename)
1363 os.remove(bak_filename)
1388 except:
1364 except:
1389 pass
1365 pass
1390
1366
1391 #****************************************************************************
1367 #****************************************************************************
1392 # lists, dicts and structures
1368 # lists, dicts and structures
1393
1369
1394 def belong(candidates,checklist):
1370 def belong(candidates,checklist):
1395 """Check whether a list of items appear in a given list of options.
1371 """Check whether a list of items appear in a given list of options.
1396
1372
1397 Returns a list of 1 and 0, one for each candidate given."""
1373 Returns a list of 1 and 0, one for each candidate given."""
1398
1374
1399 return [x in checklist for x in candidates]
1375 return [x in checklist for x in candidates]
1400
1376
1401 #----------------------------------------------------------------------------
1377 #----------------------------------------------------------------------------
1402 def uniq_stable(elems):
1378 def uniq_stable(elems):
1403 """uniq_stable(elems) -> list
1379 """uniq_stable(elems) -> list
1404
1380
1405 Return from an iterable, a list of all the unique elements in the input,
1381 Return from an iterable, a list of all the unique elements in the input,
1406 but maintaining the order in which they first appear.
1382 but maintaining the order in which they first appear.
1407
1383
1408 A naive solution to this problem which just makes a dictionary with the
1384 A naive solution to this problem which just makes a dictionary with the
1409 elements as keys fails to respect the stability condition, since
1385 elements as keys fails to respect the stability condition, since
1410 dictionaries are unsorted by nature.
1386 dictionaries are unsorted by nature.
1411
1387
1412 Note: All elements in the input must be valid dictionary keys for this
1388 Note: All elements in the input must be valid dictionary keys for this
1413 routine to work, as it internally uses a dictionary for efficiency
1389 routine to work, as it internally uses a dictionary for efficiency
1414 reasons."""
1390 reasons."""
1415
1391
1416 unique = []
1392 unique = []
1417 unique_dict = {}
1393 unique_dict = {}
1418 for nn in elems:
1394 for nn in elems:
1419 if nn not in unique_dict:
1395 if nn not in unique_dict:
1420 unique.append(nn)
1396 unique.append(nn)
1421 unique_dict[nn] = None
1397 unique_dict[nn] = None
1422 return unique
1398 return unique
1423
1399
1424 #----------------------------------------------------------------------------
1400 #----------------------------------------------------------------------------
1425 class NLprinter:
1401 class NLprinter:
1426 """Print an arbitrarily nested list, indicating index numbers.
1402 """Print an arbitrarily nested list, indicating index numbers.
1427
1403
1428 An instance of this class called nlprint is available and callable as a
1404 An instance of this class called nlprint is available and callable as a
1429 function.
1405 function.
1430
1406
1431 nlprint(list,indent=' ',sep=': ') -> prints indenting each level by 'indent'
1407 nlprint(list,indent=' ',sep=': ') -> prints indenting each level by 'indent'
1432 and using 'sep' to separate the index from the value. """
1408 and using 'sep' to separate the index from the value. """
1433
1409
1434 def __init__(self):
1410 def __init__(self):
1435 self.depth = 0
1411 self.depth = 0
1436
1412
1437 def __call__(self,lst,pos='',**kw):
1413 def __call__(self,lst,pos='',**kw):
1438 """Prints the nested list numbering levels."""
1414 """Prints the nested list numbering levels."""
1439 kw.setdefault('indent',' ')
1415 kw.setdefault('indent',' ')
1440 kw.setdefault('sep',': ')
1416 kw.setdefault('sep',': ')
1441 kw.setdefault('start',0)
1417 kw.setdefault('start',0)
1442 kw.setdefault('stop',len(lst))
1418 kw.setdefault('stop',len(lst))
1443 # we need to remove start and stop from kw so they don't propagate
1419 # we need to remove start and stop from kw so they don't propagate
1444 # into a recursive call for a nested list.
1420 # into a recursive call for a nested list.
1445 start = kw['start']; del kw['start']
1421 start = kw['start']; del kw['start']
1446 stop = kw['stop']; del kw['stop']
1422 stop = kw['stop']; del kw['stop']
1447 if self.depth == 0 and 'header' in kw.keys():
1423 if self.depth == 0 and 'header' in kw.keys():
1448 print kw['header']
1424 print kw['header']
1449
1425
1450 for idx in range(start,stop):
1426 for idx in range(start,stop):
1451 elem = lst[idx]
1427 elem = lst[idx]
1452 if type(elem)==type([]):
1428 if type(elem)==type([]):
1453 self.depth += 1
1429 self.depth += 1
1454 self.__call__(elem,itpl('$pos$idx,'),**kw)
1430 self.__call__(elem,itpl('$pos$idx,'),**kw)
1455 self.depth -= 1
1431 self.depth -= 1
1456 else:
1432 else:
1457 printpl(kw['indent']*self.depth+'$pos$idx$kw["sep"]$elem')
1433 printpl(kw['indent']*self.depth+'$pos$idx$kw["sep"]$elem')
1458
1434
1459 nlprint = NLprinter()
1435 nlprint = NLprinter()
1460 #----------------------------------------------------------------------------
1436 #----------------------------------------------------------------------------
1461 def all_belong(candidates,checklist):
1437 def all_belong(candidates,checklist):
1462 """Check whether a list of items ALL appear in a given list of options.
1438 """Check whether a list of items ALL appear in a given list of options.
1463
1439
1464 Returns a single 1 or 0 value."""
1440 Returns a single 1 or 0 value."""
1465
1441
1466 return 1-(0 in [x in checklist for x in candidates])
1442 return 1-(0 in [x in checklist for x in candidates])
1467
1443
1468 #----------------------------------------------------------------------------
1444 #----------------------------------------------------------------------------
1469 def sort_compare(lst1,lst2,inplace = 1):
1445 def sort_compare(lst1,lst2,inplace = 1):
1470 """Sort and compare two lists.
1446 """Sort and compare two lists.
1471
1447
1472 By default it does it in place, thus modifying the lists. Use inplace = 0
1448 By default it does it in place, thus modifying the lists. Use inplace = 0
1473 to avoid that (at the cost of temporary copy creation)."""
1449 to avoid that (at the cost of temporary copy creation)."""
1474 if not inplace:
1450 if not inplace:
1475 lst1 = lst1[:]
1451 lst1 = lst1[:]
1476 lst2 = lst2[:]
1452 lst2 = lst2[:]
1477 lst1.sort(); lst2.sort()
1453 lst1.sort(); lst2.sort()
1478 return lst1 == lst2
1454 return lst1 == lst2
1479
1455
1480 #----------------------------------------------------------------------------
1456 #----------------------------------------------------------------------------
1481 def list2dict(lst):
1457 def list2dict(lst):
1482 """Takes a list of (key,value) pairs and turns it into a dict."""
1458 """Takes a list of (key,value) pairs and turns it into a dict."""
1483
1459
1484 dic = {}
1460 dic = {}
1485 for k,v in lst: dic[k] = v
1461 for k,v in lst: dic[k] = v
1486 return dic
1462 return dic
1487
1463
1488 #----------------------------------------------------------------------------
1464 #----------------------------------------------------------------------------
1489 def list2dict2(lst,default=''):
1465 def list2dict2(lst,default=''):
1490 """Takes a list and turns it into a dict.
1466 """Takes a list and turns it into a dict.
1491 Much slower than list2dict, but more versatile. This version can take
1467 Much slower than list2dict, but more versatile. This version can take
1492 lists with sublists of arbitrary length (including sclars)."""
1468 lists with sublists of arbitrary length (including sclars)."""
1493
1469
1494 dic = {}
1470 dic = {}
1495 for elem in lst:
1471 for elem in lst:
1496 if type(elem) in (types.ListType,types.TupleType):
1472 if type(elem) in (types.ListType,types.TupleType):
1497 size = len(elem)
1473 size = len(elem)
1498 if size == 0:
1474 if size == 0:
1499 pass
1475 pass
1500 elif size == 1:
1476 elif size == 1:
1501 dic[elem] = default
1477 dic[elem] = default
1502 else:
1478 else:
1503 k,v = elem[0], elem[1:]
1479 k,v = elem[0], elem[1:]
1504 if len(v) == 1: v = v[0]
1480 if len(v) == 1: v = v[0]
1505 dic[k] = v
1481 dic[k] = v
1506 else:
1482 else:
1507 dic[elem] = default
1483 dic[elem] = default
1508 return dic
1484 return dic
1509
1485
1510 #----------------------------------------------------------------------------
1486 #----------------------------------------------------------------------------
1511 def flatten(seq):
1487 def flatten(seq):
1512 """Flatten a list of lists (NOT recursive, only works for 2d lists)."""
1488 """Flatten a list of lists (NOT recursive, only works for 2d lists)."""
1513
1489
1514 return [x for subseq in seq for x in subseq]
1490 return [x for subseq in seq for x in subseq]
1515
1491
1516 #----------------------------------------------------------------------------
1492 #----------------------------------------------------------------------------
1517 def get_slice(seq,start=0,stop=None,step=1):
1493 def get_slice(seq,start=0,stop=None,step=1):
1518 """Get a slice of a sequence with variable step. Specify start,stop,step."""
1494 """Get a slice of a sequence with variable step. Specify start,stop,step."""
1519 if stop == None:
1495 if stop == None:
1520 stop = len(seq)
1496 stop = len(seq)
1521 item = lambda i: seq[i]
1497 item = lambda i: seq[i]
1522 return map(item,xrange(start,stop,step))
1498 return map(item,xrange(start,stop,step))
1523
1499
1524 #----------------------------------------------------------------------------
1500 #----------------------------------------------------------------------------
1525 def chop(seq,size):
1501 def chop(seq,size):
1526 """Chop a sequence into chunks of the given size."""
1502 """Chop a sequence into chunks of the given size."""
1527 chunk = lambda i: seq[i:i+size]
1503 chunk = lambda i: seq[i:i+size]
1528 return map(chunk,xrange(0,len(seq),size))
1504 return map(chunk,xrange(0,len(seq),size))
1529
1505
1530 #----------------------------------------------------------------------------
1506 #----------------------------------------------------------------------------
1531 # with is a keyword as of python 2.5, so this function is renamed to withobj
1507 # with is a keyword as of python 2.5, so this function is renamed to withobj
1532 # from its old 'with' name.
1508 # from its old 'with' name.
1533 def with_obj(object, **args):
1509 def with_obj(object, **args):
1534 """Set multiple attributes for an object, similar to Pascal's with.
1510 """Set multiple attributes for an object, similar to Pascal's with.
1535
1511
1536 Example:
1512 Example:
1537 with_obj(jim,
1513 with_obj(jim,
1538 born = 1960,
1514 born = 1960,
1539 haircolour = 'Brown',
1515 haircolour = 'Brown',
1540 eyecolour = 'Green')
1516 eyecolour = 'Green')
1541
1517
1542 Credit: Greg Ewing, in
1518 Credit: Greg Ewing, in
1543 http://mail.python.org/pipermail/python-list/2001-May/040703.html.
1519 http://mail.python.org/pipermail/python-list/2001-May/040703.html.
1544
1520
1545 NOTE: up until IPython 0.7.2, this was called simply 'with', but 'with'
1521 NOTE: up until IPython 0.7.2, this was called simply 'with', but 'with'
1546 has become a keyword for Python 2.5, so we had to rename it."""
1522 has become a keyword for Python 2.5, so we had to rename it."""
1547
1523
1548 object.__dict__.update(args)
1524 object.__dict__.update(args)
1549
1525
1550 #----------------------------------------------------------------------------
1526 #----------------------------------------------------------------------------
1551 def setattr_list(obj,alist,nspace = None):
1527 def setattr_list(obj,alist,nspace = None):
1552 """Set a list of attributes for an object taken from a namespace.
1528 """Set a list of attributes for an object taken from a namespace.
1553
1529
1554 setattr_list(obj,alist,nspace) -> sets in obj all the attributes listed in
1530 setattr_list(obj,alist,nspace) -> sets in obj all the attributes listed in
1555 alist with their values taken from nspace, which must be a dict (something
1531 alist with their values taken from nspace, which must be a dict (something
1556 like locals() will often do) If nspace isn't given, locals() of the
1532 like locals() will often do) If nspace isn't given, locals() of the
1557 *caller* is used, so in most cases you can omit it.
1533 *caller* is used, so in most cases you can omit it.
1558
1534
1559 Note that alist can be given as a string, which will be automatically
1535 Note that alist can be given as a string, which will be automatically
1560 split into a list on whitespace. If given as a list, it must be a list of
1536 split into a list on whitespace. If given as a list, it must be a list of
1561 *strings* (the variable names themselves), not of variables."""
1537 *strings* (the variable names themselves), not of variables."""
1562
1538
1563 # this grabs the local variables from the *previous* call frame -- that is
1539 # this grabs the local variables from the *previous* call frame -- that is
1564 # the locals from the function that called setattr_list().
1540 # the locals from the function that called setattr_list().
1565 # - snipped from weave.inline()
1541 # - snipped from weave.inline()
1566 if nspace is None:
1542 if nspace is None:
1567 call_frame = sys._getframe().f_back
1543 call_frame = sys._getframe().f_back
1568 nspace = call_frame.f_locals
1544 nspace = call_frame.f_locals
1569
1545
1570 if type(alist) in StringTypes:
1546 if type(alist) in StringTypes:
1571 alist = alist.split()
1547 alist = alist.split()
1572 for attr in alist:
1548 for attr in alist:
1573 val = eval(attr,nspace)
1549 val = eval(attr,nspace)
1574 setattr(obj,attr,val)
1550 setattr(obj,attr,val)
1575
1551
1576 #----------------------------------------------------------------------------
1552 #----------------------------------------------------------------------------
1577 def getattr_list(obj,alist,*args):
1553 def getattr_list(obj,alist,*args):
1578 """getattr_list(obj,alist[, default]) -> attribute list.
1554 """getattr_list(obj,alist[, default]) -> attribute list.
1579
1555
1580 Get a list of named attributes for an object. When a default argument is
1556 Get a list of named attributes for an object. When a default argument is
1581 given, it is returned when the attribute doesn't exist; without it, an
1557 given, it is returned when the attribute doesn't exist; without it, an
1582 exception is raised in that case.
1558 exception is raised in that case.
1583
1559
1584 Note that alist can be given as a string, which will be automatically
1560 Note that alist can be given as a string, which will be automatically
1585 split into a list on whitespace. If given as a list, it must be a list of
1561 split into a list on whitespace. If given as a list, it must be a list of
1586 *strings* (the variable names themselves), not of variables."""
1562 *strings* (the variable names themselves), not of variables."""
1587
1563
1588 if type(alist) in StringTypes:
1564 if type(alist) in StringTypes:
1589 alist = alist.split()
1565 alist = alist.split()
1590 if args:
1566 if args:
1591 if len(args)==1:
1567 if len(args)==1:
1592 default = args[0]
1568 default = args[0]
1593 return map(lambda attr: getattr(obj,attr,default),alist)
1569 return map(lambda attr: getattr(obj,attr,default),alist)
1594 else:
1570 else:
1595 raise ValueError,'getattr_list() takes only one optional argument'
1571 raise ValueError,'getattr_list() takes only one optional argument'
1596 else:
1572 else:
1597 return map(lambda attr: getattr(obj,attr),alist)
1573 return map(lambda attr: getattr(obj,attr),alist)
1598
1574
1599 #----------------------------------------------------------------------------
1575 #----------------------------------------------------------------------------
1600 def map_method(method,object_list,*argseq,**kw):
1576 def map_method(method,object_list,*argseq,**kw):
1601 """map_method(method,object_list,*args,**kw) -> list
1577 """map_method(method,object_list,*args,**kw) -> list
1602
1578
1603 Return a list of the results of applying the methods to the items of the
1579 Return a list of the results of applying the methods to the items of the
1604 argument sequence(s). If more than one sequence is given, the method is
1580 argument sequence(s). If more than one sequence is given, the method is
1605 called with an argument list consisting of the corresponding item of each
1581 called with an argument list consisting of the corresponding item of each
1606 sequence. All sequences must be of the same length.
1582 sequence. All sequences must be of the same length.
1607
1583
1608 Keyword arguments are passed verbatim to all objects called.
1584 Keyword arguments are passed verbatim to all objects called.
1609
1585
1610 This is Python code, so it's not nearly as fast as the builtin map()."""
1586 This is Python code, so it's not nearly as fast as the builtin map()."""
1611
1587
1612 out_list = []
1588 out_list = []
1613 idx = 0
1589 idx = 0
1614 for object in object_list:
1590 for object in object_list:
1615 try:
1591 try:
1616 handler = getattr(object, method)
1592 handler = getattr(object, method)
1617 except AttributeError:
1593 except AttributeError:
1618 out_list.append(None)
1594 out_list.append(None)
1619 else:
1595 else:
1620 if argseq:
1596 if argseq:
1621 args = map(lambda lst:lst[idx],argseq)
1597 args = map(lambda lst:lst[idx],argseq)
1622 #print 'ob',object,'hand',handler,'ar',args # dbg
1598 #print 'ob',object,'hand',handler,'ar',args # dbg
1623 out_list.append(handler(args,**kw))
1599 out_list.append(handler(args,**kw))
1624 else:
1600 else:
1625 out_list.append(handler(**kw))
1601 out_list.append(handler(**kw))
1626 idx += 1
1602 idx += 1
1627 return out_list
1603 return out_list
1628
1604
1629 #----------------------------------------------------------------------------
1605 #----------------------------------------------------------------------------
1630 def get_class_members(cls):
1606 def get_class_members(cls):
1631 ret = dir(cls)
1607 ret = dir(cls)
1632 if hasattr(cls,'__bases__'):
1608 if hasattr(cls,'__bases__'):
1633 for base in cls.__bases__:
1609 for base in cls.__bases__:
1634 ret.extend(get_class_members(base))
1610 ret.extend(get_class_members(base))
1635 return ret
1611 return ret
1636
1612
1637 #----------------------------------------------------------------------------
1613 #----------------------------------------------------------------------------
1638 def dir2(obj):
1614 def dir2(obj):
1639 """dir2(obj) -> list of strings
1615 """dir2(obj) -> list of strings
1640
1616
1641 Extended version of the Python builtin dir(), which does a few extra
1617 Extended version of the Python builtin dir(), which does a few extra
1642 checks, and supports common objects with unusual internals that confuse
1618 checks, and supports common objects with unusual internals that confuse
1643 dir(), such as Traits and PyCrust.
1619 dir(), such as Traits and PyCrust.
1644
1620
1645 This version is guaranteed to return only a list of true strings, whereas
1621 This version is guaranteed to return only a list of true strings, whereas
1646 dir() returns anything that objects inject into themselves, even if they
1622 dir() returns anything that objects inject into themselves, even if they
1647 are later not really valid for attribute access (many extension libraries
1623 are later not really valid for attribute access (many extension libraries
1648 have such bugs).
1624 have such bugs).
1649 """
1625 """
1650
1626
1651 # Start building the attribute list via dir(), and then complete it
1627 # Start building the attribute list via dir(), and then complete it
1652 # with a few extra special-purpose calls.
1628 # with a few extra special-purpose calls.
1653 words = dir(obj)
1629 words = dir(obj)
1654
1630
1655 if hasattr(obj,'__class__'):
1631 if hasattr(obj,'__class__'):
1656 words.append('__class__')
1632 words.append('__class__')
1657 words.extend(get_class_members(obj.__class__))
1633 words.extend(get_class_members(obj.__class__))
1658 #if '__base__' in words: 1/0
1634 #if '__base__' in words: 1/0
1659
1635
1660 # Some libraries (such as traits) may introduce duplicates, we want to
1636 # Some libraries (such as traits) may introduce duplicates, we want to
1661 # track and clean this up if it happens
1637 # track and clean this up if it happens
1662 may_have_dupes = False
1638 may_have_dupes = False
1663
1639
1664 # this is the 'dir' function for objects with Enthought's traits
1640 # this is the 'dir' function for objects with Enthought's traits
1665 if hasattr(obj, 'trait_names'):
1641 if hasattr(obj, 'trait_names'):
1666 try:
1642 try:
1667 words.extend(obj.trait_names())
1643 words.extend(obj.trait_names())
1668 may_have_dupes = True
1644 may_have_dupes = True
1669 except TypeError:
1645 except TypeError:
1670 # This will happen if `obj` is a class and not an instance.
1646 # This will happen if `obj` is a class and not an instance.
1671 pass
1647 pass
1672
1648
1673 # Support for PyCrust-style _getAttributeNames magic method.
1649 # Support for PyCrust-style _getAttributeNames magic method.
1674 if hasattr(obj, '_getAttributeNames'):
1650 if hasattr(obj, '_getAttributeNames'):
1675 try:
1651 try:
1676 words.extend(obj._getAttributeNames())
1652 words.extend(obj._getAttributeNames())
1677 may_have_dupes = True
1653 may_have_dupes = True
1678 except TypeError:
1654 except TypeError:
1679 # `obj` is a class and not an instance. Ignore
1655 # `obj` is a class and not an instance. Ignore
1680 # this error.
1656 # this error.
1681 pass
1657 pass
1682
1658
1683 if may_have_dupes:
1659 if may_have_dupes:
1684 # eliminate possible duplicates, as some traits may also
1660 # eliminate possible duplicates, as some traits may also
1685 # appear as normal attributes in the dir() call.
1661 # appear as normal attributes in the dir() call.
1686 words = list(set(words))
1662 words = list(set(words))
1687 words.sort()
1663 words.sort()
1688
1664
1689 # filter out non-string attributes which may be stuffed by dir() calls
1665 # filter out non-string attributes which may be stuffed by dir() calls
1690 # and poor coding in third-party modules
1666 # and poor coding in third-party modules
1691 return [w for w in words if isinstance(w, basestring)]
1667 return [w for w in words if isinstance(w, basestring)]
1692
1668
1693 #----------------------------------------------------------------------------
1669 #----------------------------------------------------------------------------
1694 def import_fail_info(mod_name,fns=None):
1670 def import_fail_info(mod_name,fns=None):
1695 """Inform load failure for a module."""
1671 """Inform load failure for a module."""
1696
1672
1697 if fns == None:
1673 if fns == None:
1698 warn("Loading of %s failed.\n" % (mod_name,))
1674 warn("Loading of %s failed.\n" % (mod_name,))
1699 else:
1675 else:
1700 warn("Loading of %s from %s failed.\n" % (fns,mod_name))
1676 warn("Loading of %s from %s failed.\n" % (fns,mod_name))
1701
1677
1702 #----------------------------------------------------------------------------
1678 #----------------------------------------------------------------------------
1703 # Proposed popitem() extension, written as a method
1679 # Proposed popitem() extension, written as a method
1704
1680
1705
1681
1706 class NotGiven: pass
1682 class NotGiven: pass
1707
1683
1708 def popkey(dct,key,default=NotGiven):
1684 def popkey(dct,key,default=NotGiven):
1709 """Return dct[key] and delete dct[key].
1685 """Return dct[key] and delete dct[key].
1710
1686
1711 If default is given, return it if dct[key] doesn't exist, otherwise raise
1687 If default is given, return it if dct[key] doesn't exist, otherwise raise
1712 KeyError. """
1688 KeyError. """
1713
1689
1714 try:
1690 try:
1715 val = dct[key]
1691 val = dct[key]
1716 except KeyError:
1692 except KeyError:
1717 if default is NotGiven:
1693 if default is NotGiven:
1718 raise
1694 raise
1719 else:
1695 else:
1720 return default
1696 return default
1721 else:
1697 else:
1722 del dct[key]
1698 del dct[key]
1723 return val
1699 return val
1724
1700
1725 def wrap_deprecated(func, suggest = '<nothing>'):
1701 def wrap_deprecated(func, suggest = '<nothing>'):
1726 def newFunc(*args, **kwargs):
1702 def newFunc(*args, **kwargs):
1727 warnings.warn("Call to deprecated function %s, use %s instead" %
1703 warnings.warn("Call to deprecated function %s, use %s instead" %
1728 ( func.__name__, suggest),
1704 ( func.__name__, suggest),
1729 category=DeprecationWarning,
1705 category=DeprecationWarning,
1730 stacklevel = 2)
1706 stacklevel = 2)
1731 return func(*args, **kwargs)
1707 return func(*args, **kwargs)
1732 return newFunc
1708 return newFunc
1733
1709
1734
1710
1735 def _num_cpus_unix():
1711 def _num_cpus_unix():
1736 """Return the number of active CPUs on a Unix system."""
1712 """Return the number of active CPUs on a Unix system."""
1737 return os.sysconf("SC_NPROCESSORS_ONLN")
1713 return os.sysconf("SC_NPROCESSORS_ONLN")
1738
1714
1739
1715
1740 def _num_cpus_darwin():
1716 def _num_cpus_darwin():
1741 """Return the number of active CPUs on a Darwin system."""
1717 """Return the number of active CPUs on a Darwin system."""
1742 p = subprocess.Popen(['sysctl','-n','hw.ncpu'],stdout=subprocess.PIPE)
1718 p = subprocess.Popen(['sysctl','-n','hw.ncpu'],stdout=subprocess.PIPE)
1743 return p.stdout.read()
1719 return p.stdout.read()
1744
1720
1745
1721
1746 def _num_cpus_windows():
1722 def _num_cpus_windows():
1747 """Return the number of active CPUs on a Windows system."""
1723 """Return the number of active CPUs on a Windows system."""
1748 return os.environ.get("NUMBER_OF_PROCESSORS")
1724 return os.environ.get("NUMBER_OF_PROCESSORS")
1749
1725
1750
1726
1751 def num_cpus():
1727 def num_cpus():
1752 """Return the effective number of CPUs in the system as an integer.
1728 """Return the effective number of CPUs in the system as an integer.
1753
1729
1754 This cross-platform function makes an attempt at finding the total number of
1730 This cross-platform function makes an attempt at finding the total number of
1755 available CPUs in the system, as returned by various underlying system and
1731 available CPUs in the system, as returned by various underlying system and
1756 python calls.
1732 python calls.
1757
1733
1758 If it can't find a sensible answer, it returns 1 (though an error *may* make
1734 If it can't find a sensible answer, it returns 1 (though an error *may* make
1759 it return a large positive number that's actually incorrect).
1735 it return a large positive number that's actually incorrect).
1760 """
1736 """
1761
1737
1762 # Many thanks to the Parallel Python project (http://www.parallelpython.com)
1738 # Many thanks to the Parallel Python project (http://www.parallelpython.com)
1763 # for the names of the keys we needed to look up for this function. This
1739 # for the names of the keys we needed to look up for this function. This
1764 # code was inspired by their equivalent function.
1740 # code was inspired by their equivalent function.
1765
1741
1766 ncpufuncs = {'Linux':_num_cpus_unix,
1742 ncpufuncs = {'Linux':_num_cpus_unix,
1767 'Darwin':_num_cpus_darwin,
1743 'Darwin':_num_cpus_darwin,
1768 'Windows':_num_cpus_windows,
1744 'Windows':_num_cpus_windows,
1769 # On Vista, python < 2.5.2 has a bug and returns 'Microsoft'
1745 # On Vista, python < 2.5.2 has a bug and returns 'Microsoft'
1770 # See http://bugs.python.org/issue1082 for details.
1746 # See http://bugs.python.org/issue1082 for details.
1771 'Microsoft':_num_cpus_windows,
1747 'Microsoft':_num_cpus_windows,
1772 }
1748 }
1773
1749
1774 ncpufunc = ncpufuncs.get(platform.system(),
1750 ncpufunc = ncpufuncs.get(platform.system(),
1775 # default to unix version (Solaris, AIX, etc)
1751 # default to unix version (Solaris, AIX, etc)
1776 _num_cpus_unix)
1752 _num_cpus_unix)
1777
1753
1778 try:
1754 try:
1779 ncpus = max(1,int(ncpufunc()))
1755 ncpus = max(1,int(ncpufunc()))
1780 except:
1756 except:
1781 ncpus = 1
1757 ncpus = 1
1782 return ncpus
1758 return ncpus
1783
1759
1784 def extract_vars(*names,**kw):
1760 def extract_vars(*names,**kw):
1785 """Extract a set of variables by name from another frame.
1761 """Extract a set of variables by name from another frame.
1786
1762
1787 :Parameters:
1763 :Parameters:
1788 - `*names`: strings
1764 - `*names`: strings
1789 One or more variable names which will be extracted from the caller's
1765 One or more variable names which will be extracted from the caller's
1790 frame.
1766 frame.
1791
1767
1792 :Keywords:
1768 :Keywords:
1793 - `depth`: integer (0)
1769 - `depth`: integer (0)
1794 How many frames in the stack to walk when looking for your variables.
1770 How many frames in the stack to walk when looking for your variables.
1795
1771
1796
1772
1797 Examples:
1773 Examples:
1798
1774
1799 In [2]: def func(x):
1775 In [2]: def func(x):
1800 ...: y = 1
1776 ...: y = 1
1801 ...: print extract_vars('x','y')
1777 ...: print extract_vars('x','y')
1802 ...:
1778 ...:
1803
1779
1804 In [3]: func('hello')
1780 In [3]: func('hello')
1805 {'y': 1, 'x': 'hello'}
1781 {'y': 1, 'x': 'hello'}
1806 """
1782 """
1807
1783
1808 depth = kw.get('depth',0)
1784 depth = kw.get('depth',0)
1809
1785
1810 callerNS = sys._getframe(depth+1).f_locals
1786 callerNS = sys._getframe(depth+1).f_locals
1811 return dict((k,callerNS[k]) for k in names)
1787 return dict((k,callerNS[k]) for k in names)
1812
1788
1813
1789
1814 def extract_vars_above(*names):
1790 def extract_vars_above(*names):
1815 """Extract a set of variables by name from another frame.
1791 """Extract a set of variables by name from another frame.
1816
1792
1817 Similar to extractVars(), but with a specified depth of 1, so that names
1793 Similar to extractVars(), but with a specified depth of 1, so that names
1818 are exctracted exactly from above the caller.
1794 are exctracted exactly from above the caller.
1819
1795
1820 This is simply a convenience function so that the very common case (for us)
1796 This is simply a convenience function so that the very common case (for us)
1821 of skipping exactly 1 frame doesn't have to construct a special dict for
1797 of skipping exactly 1 frame doesn't have to construct a special dict for
1822 keyword passing."""
1798 keyword passing."""
1823
1799
1824 callerNS = sys._getframe(2).f_locals
1800 callerNS = sys._getframe(2).f_locals
1825 return dict((k,callerNS[k]) for k in names)
1801 return dict((k,callerNS[k]) for k in names)
1826
1802
1827 def expand_path(s):
1803 def expand_path(s):
1828 """Expand $VARS and ~names in a string, like a shell
1804 """Expand $VARS and ~names in a string, like a shell
1829
1805
1830 :Examples:
1806 :Examples:
1831
1807
1832 In [2]: os.environ['FOO']='test'
1808 In [2]: os.environ['FOO']='test'
1833
1809
1834 In [3]: expand_path('variable FOO is $FOO')
1810 In [3]: expand_path('variable FOO is $FOO')
1835 Out[3]: 'variable FOO is test'
1811 Out[3]: 'variable FOO is test'
1836 """
1812 """
1837 # This is a pretty subtle hack. When expand user is given a UNC path
1813 # This is a pretty subtle hack. When expand user is given a UNC path
1838 # on Windows (\\server\share$\%username%), os.path.expandvars, removes
1814 # on Windows (\\server\share$\%username%), os.path.expandvars, removes
1839 # the $ to get (\\server\share\%username%). I think it considered $
1815 # the $ to get (\\server\share\%username%). I think it considered $
1840 # alone an empty var. But, we need the $ to remains there (it indicates
1816 # alone an empty var. But, we need the $ to remains there (it indicates
1841 # a hidden share).
1817 # a hidden share).
1842 if os.name=='nt':
1818 if os.name=='nt':
1843 s = s.replace('$\\', 'IPYTHON_TEMP')
1819 s = s.replace('$\\', 'IPYTHON_TEMP')
1844 s = os.path.expandvars(os.path.expanduser(s))
1820 s = os.path.expandvars(os.path.expanduser(s))
1845 if os.name=='nt':
1821 if os.name=='nt':
1846 s = s.replace('IPYTHON_TEMP', '$\\')
1822 s = s.replace('IPYTHON_TEMP', '$\\')
1847 return s
1823 return s
1848
1824
1849 def list_strings(arg):
1825 def list_strings(arg):
1850 """Always return a list of strings, given a string or list of strings
1826 """Always return a list of strings, given a string or list of strings
1851 as input.
1827 as input.
1852
1828
1853 :Examples:
1829 :Examples:
1854
1830
1855 In [7]: list_strings('A single string')
1831 In [7]: list_strings('A single string')
1856 Out[7]: ['A single string']
1832 Out[7]: ['A single string']
1857
1833
1858 In [8]: list_strings(['A single string in a list'])
1834 In [8]: list_strings(['A single string in a list'])
1859 Out[8]: ['A single string in a list']
1835 Out[8]: ['A single string in a list']
1860
1836
1861 In [9]: list_strings(['A','list','of','strings'])
1837 In [9]: list_strings(['A','list','of','strings'])
1862 Out[9]: ['A', 'list', 'of', 'strings']
1838 Out[9]: ['A', 'list', 'of', 'strings']
1863 """
1839 """
1864
1840
1865 if isinstance(arg,basestring): return [arg]
1841 if isinstance(arg,basestring): return [arg]
1866 else: return arg
1842 else: return arg
1867
1843
1868
1844
1869 #----------------------------------------------------------------------------
1845 #----------------------------------------------------------------------------
1870 def marquee(txt='',width=78,mark='*'):
1846 def marquee(txt='',width=78,mark='*'):
1871 """Return the input string centered in a 'marquee'.
1847 """Return the input string centered in a 'marquee'.
1872
1848
1873 :Examples:
1849 :Examples:
1874
1850
1875 In [16]: marquee('A test',40)
1851 In [16]: marquee('A test',40)
1876 Out[16]: '**************** A test ****************'
1852 Out[16]: '**************** A test ****************'
1877
1853
1878 In [17]: marquee('A test',40,'-')
1854 In [17]: marquee('A test',40,'-')
1879 Out[17]: '---------------- A test ----------------'
1855 Out[17]: '---------------- A test ----------------'
1880
1856
1881 In [18]: marquee('A test',40,' ')
1857 In [18]: marquee('A test',40,' ')
1882 Out[18]: ' A test '
1858 Out[18]: ' A test '
1883
1859
1884 """
1860 """
1885 if not txt:
1861 if not txt:
1886 return (mark*width)[:width]
1862 return (mark*width)[:width]
1887 nmark = (width-len(txt)-2)/len(mark)/2
1863 nmark = (width-len(txt)-2)/len(mark)/2
1888 if nmark < 0: nmark =0
1864 if nmark < 0: nmark =0
1889 marks = mark*nmark
1865 marks = mark*nmark
1890 return '%s %s %s' % (marks,txt,marks)
1866 return '%s %s %s' % (marks,txt,marks)
1891
1867
1892 #*************************** end of file <genutils.py> **********************
1868 #*************************** end of file <genutils.py> **********************
@@ -1,48 +1,61 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """ Platform specific utility functions, posix version
2 """ Platform specific utility functions, posix version
3
3
4 Importing this module directly is not portable - rather, import platutils
4 Importing this module directly is not portable - rather, import platutils
5 to use these functions in platform agnostic fashion.
5 to use these functions in platform agnostic fashion.
6 """
6 """
7
7
8 #*****************************************************************************
8 #*****************************************************************************
9 # Copyright (C) 2001-2006 Fernando Perez <fperez@colorado.edu>
9 # Copyright (C) 2001-2006 Fernando Perez <fperez@colorado.edu>
10 #
10 #
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 """
23
36
24
37
25 def _set_term_title_xterm(title):
38 def _set_term_title_xterm(title):
26 """ Change virtual terminal title in xterm-workalikes """
39 """ Change virtual terminal title in xterm-workalikes """
27 sys.stdout.write('\033]0;%s\007' % title)
40 sys.stdout.write('\033]0;%s\007' % title)
28
41
29 TERM = os.environ.get('TERM','')
42 TERM = os.environ.get('TERM','')
30
43
31 if (TERM == 'xterm') or (TERM == 'xterm-color'):
44 if (TERM == 'xterm') or (TERM == 'xterm-color'):
32 set_term_title = _set_term_title_xterm
45 set_term_title = _set_term_title_xterm
33 else:
46 else:
34 set_term_title = _dummy_op
47 set_term_title = _dummy_op
35
48
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('which %s' % cmd)[0]
40
53
41
54
42 def get_long_path_name(path):
55 def get_long_path_name(path):
43 """Dummy no-op."""
56 """Dummy no-op."""
44 return path
57 return path
45
58
46
59
47 def term_clear():
60 def term_clear():
48 os.system('clear')
61 os.system('clear')
General Comments 0
You need to be logged in to leave comments. Login now