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