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