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