##// END OF EJS Templates
- Modified clock() to return total (user+system) time. Introduced...
fperez -
Show More

The requested changes are too big and content was truncated. Show full diff

@@ -1,1731 +1,1751 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 General purpose utilities.
3 General purpose utilities.
4
4
5 This is a grab-bag of stuff I find useful in most programs I write. Some of
5 This is a grab-bag of stuff I find useful in most programs I write. Some of
6 these things are also convenient when working at the command line.
6 these things are also convenient when working at the command line.
7
7
8 $Id: genutils.py 1930 2006-11-26 17:22:13Z vivainio $"""
8 $Id: genutils.py 2108 2007-02-23 00:31:17Z fperez $"""
9
9
10 #*****************************************************************************
10 #*****************************************************************************
11 # Copyright (C) 2001-2006 Fernando Perez. <fperez@colorado.edu>
11 # Copyright (C) 2001-2006 Fernando Perez. <fperez@colorado.edu>
12 #
12 #
13 # Distributed under the terms of the BSD License. The full license is in
13 # Distributed under the terms of the BSD License. The full license is in
14 # the file COPYING, distributed as part of this software.
14 # the file COPYING, distributed as part of this software.
15 #*****************************************************************************
15 #*****************************************************************************
16
16
17 from IPython import Release
17 from IPython import Release
18 __author__ = '%s <%s>' % Release.authors['Fernando']
18 __author__ = '%s <%s>' % Release.authors['Fernando']
19 __license__ = Release.license
19 __license__ = Release.license
20
20
21 #****************************************************************************
21 #****************************************************************************
22 # required modules from the Python standard library
22 # required modules from the Python standard library
23 import __main__
23 import __main__
24 import commands
24 import commands
25 import os
25 import os
26 import re
26 import re
27 import shlex
27 import shlex
28 import shutil
28 import shutil
29 import sys
29 import sys
30 import tempfile
30 import tempfile
31 import time
31 import time
32 import types
32 import types
33 import warnings
33 import warnings
34
34
35 # Other IPython utilities
35 # Other IPython utilities
36 from IPython.Itpl import Itpl,itpl,printpl
36 from IPython.Itpl import Itpl,itpl,printpl
37 from IPython import DPyGetOpt
37 from IPython import DPyGetOpt
38 from path import path
38 from path import path
39 if os.name == "nt":
39 if os.name == "nt":
40 from IPython.winconsole import get_console_size
40 from IPython.winconsole import get_console_size
41
41
42 #****************************************************************************
42 #****************************************************************************
43 # Exceptions
43 # Exceptions
44 class Error(Exception):
44 class Error(Exception):
45 """Base class for exceptions in this module."""
45 """Base class for exceptions in this module."""
46 pass
46 pass
47
47
48 #----------------------------------------------------------------------------
48 #----------------------------------------------------------------------------
49 class IOStream:
49 class IOStream:
50 def __init__(self,stream,fallback):
50 def __init__(self,stream,fallback):
51 if not hasattr(stream,'write') or not hasattr(stream,'flush'):
51 if not hasattr(stream,'write') or not hasattr(stream,'flush'):
52 stream = fallback
52 stream = fallback
53 self.stream = stream
53 self.stream = stream
54 self._swrite = stream.write
54 self._swrite = stream.write
55 self.flush = stream.flush
55 self.flush = stream.flush
56
56
57 def write(self,data):
57 def write(self,data):
58 try:
58 try:
59 self._swrite(data)
59 self._swrite(data)
60 except:
60 except:
61 try:
61 try:
62 # print handles some unicode issues which may trip a plain
62 # print handles some unicode issues which may trip a plain
63 # write() call. Attempt to emulate write() by using a
63 # write() call. Attempt to emulate write() by using a
64 # trailing comma
64 # trailing comma
65 print >> self.stream, data,
65 print >> self.stream, data,
66 except:
66 except:
67 # if we get here, something is seriously broken.
67 # if we get here, something is seriously broken.
68 print >> sys.stderr, \
68 print >> sys.stderr, \
69 'ERROR - failed to write data to stream:', self.stream
69 'ERROR - failed to write data to stream:', self.stream
70
70
71 class IOTerm:
71 class IOTerm:
72 """ Term holds the file or file-like objects for handling I/O operations.
72 """ Term holds the file or file-like objects for handling I/O operations.
73
73
74 These are normally just sys.stdin, sys.stdout and sys.stderr but for
74 These are normally just sys.stdin, sys.stdout and sys.stderr but for
75 Windows they can can replaced to allow editing the strings before they are
75 Windows they can can replaced to allow editing the strings before they are
76 displayed."""
76 displayed."""
77
77
78 # In the future, having IPython channel all its I/O operations through
78 # In the future, having IPython channel all its I/O operations through
79 # this class will make it easier to embed it into other environments which
79 # this class will make it easier to embed it into other environments which
80 # are not a normal terminal (such as a GUI-based shell)
80 # are not a normal terminal (such as a GUI-based shell)
81 def __init__(self,cin=None,cout=None,cerr=None):
81 def __init__(self,cin=None,cout=None,cerr=None):
82 self.cin = IOStream(cin,sys.stdin)
82 self.cin = IOStream(cin,sys.stdin)
83 self.cout = IOStream(cout,sys.stdout)
83 self.cout = IOStream(cout,sys.stdout)
84 self.cerr = IOStream(cerr,sys.stderr)
84 self.cerr = IOStream(cerr,sys.stderr)
85
85
86 # Global variable to be used for all I/O
86 # Global variable to be used for all I/O
87 Term = IOTerm()
87 Term = IOTerm()
88
88
89 import IPython.rlineimpl as readline
89 import IPython.rlineimpl as readline
90 # Remake Term to use the readline i/o facilities
90 # Remake Term to use the readline i/o facilities
91 if sys.platform == 'win32' and readline.have_readline:
91 if sys.platform == 'win32' and readline.have_readline:
92
92
93 Term = IOTerm(cout=readline._outputfile,cerr=readline._outputfile)
93 Term = IOTerm(cout=readline._outputfile,cerr=readline._outputfile)
94
94
95
95
96 #****************************************************************************
96 #****************************************************************************
97 # Generic warning/error printer, used by everything else
97 # Generic warning/error printer, used by everything else
98 def warn(msg,level=2,exit_val=1):
98 def warn(msg,level=2,exit_val=1):
99 """Standard warning printer. Gives formatting consistency.
99 """Standard warning printer. Gives formatting consistency.
100
100
101 Output is sent to Term.cerr (sys.stderr by default).
101 Output is sent to Term.cerr (sys.stderr by default).
102
102
103 Options:
103 Options:
104
104
105 -level(2): allows finer control:
105 -level(2): allows finer control:
106 0 -> Do nothing, dummy function.
106 0 -> Do nothing, dummy function.
107 1 -> Print message.
107 1 -> Print message.
108 2 -> Print 'WARNING:' + message. (Default level).
108 2 -> Print 'WARNING:' + message. (Default level).
109 3 -> Print 'ERROR:' + message.
109 3 -> Print 'ERROR:' + message.
110 4 -> Print 'FATAL ERROR:' + message and trigger a sys.exit(exit_val).
110 4 -> Print 'FATAL ERROR:' + message and trigger a sys.exit(exit_val).
111
111
112 -exit_val (1): exit value returned by sys.exit() for a level 4
112 -exit_val (1): exit value returned by sys.exit() for a level 4
113 warning. Ignored for all other levels."""
113 warning. Ignored for all other levels."""
114
114
115 if level>0:
115 if level>0:
116 header = ['','','WARNING: ','ERROR: ','FATAL ERROR: ']
116 header = ['','','WARNING: ','ERROR: ','FATAL ERROR: ']
117 print >> Term.cerr, '%s%s' % (header[level],msg)
117 print >> Term.cerr, '%s%s' % (header[level],msg)
118 if level == 4:
118 if level == 4:
119 print >> Term.cerr,'Exiting.\n'
119 print >> Term.cerr,'Exiting.\n'
120 sys.exit(exit_val)
120 sys.exit(exit_val)
121
121
122 def info(msg):
122 def info(msg):
123 """Equivalent to warn(msg,level=1)."""
123 """Equivalent to warn(msg,level=1)."""
124
124
125 warn(msg,level=1)
125 warn(msg,level=1)
126
126
127 def error(msg):
127 def error(msg):
128 """Equivalent to warn(msg,level=3)."""
128 """Equivalent to warn(msg,level=3)."""
129
129
130 warn(msg,level=3)
130 warn(msg,level=3)
131
131
132 def fatal(msg,exit_val=1):
132 def fatal(msg,exit_val=1):
133 """Equivalent to warn(msg,exit_val=exit_val,level=4)."""
133 """Equivalent to warn(msg,exit_val=exit_val,level=4)."""
134
134
135 warn(msg,exit_val=exit_val,level=4)
135 warn(msg,exit_val=exit_val,level=4)
136
136
137 #---------------------------------------------------------------------------
137 #---------------------------------------------------------------------------
138 # Debugging routines
138 # Debugging routines
139 #
139 #
140 def debugx(expr,pre_msg=''):
140 def debugx(expr,pre_msg=''):
141 """Print the value of an expression from the caller's frame.
141 """Print the value of an expression from the caller's frame.
142
142
143 Takes an expression, evaluates it in the caller's frame and prints both
143 Takes an expression, evaluates it in the caller's frame and prints both
144 the given expression and the resulting value (as well as a debug mark
144 the given expression and the resulting value (as well as a debug mark
145 indicating the name of the calling function. The input must be of a form
145 indicating the name of the calling function. The input must be of a form
146 suitable for eval().
146 suitable for eval().
147
147
148 An optional message can be passed, which will be prepended to the printed
148 An optional message can be passed, which will be prepended to the printed
149 expr->value pair."""
149 expr->value pair."""
150
150
151 cf = sys._getframe(1)
151 cf = sys._getframe(1)
152 print '[DBG:%s] %s%s -> %r' % (cf.f_code.co_name,pre_msg,expr,
152 print '[DBG:%s] %s%s -> %r' % (cf.f_code.co_name,pre_msg,expr,
153 eval(expr,cf.f_globals,cf.f_locals))
153 eval(expr,cf.f_globals,cf.f_locals))
154
154
155 # deactivate it by uncommenting the following line, which makes it a no-op
155 # deactivate it by uncommenting the following line, which makes it a no-op
156 #def debugx(expr,pre_msg=''): pass
156 #def debugx(expr,pre_msg=''): pass
157
157
158 #----------------------------------------------------------------------------
158 #----------------------------------------------------------------------------
159 StringTypes = types.StringTypes
159 StringTypes = types.StringTypes
160
160
161 # Basic timing functionality
161 # Basic timing functionality
162
162
163 # If possible (Unix), use the resource module instead of time.clock()
163 # If possible (Unix), use the resource module instead of time.clock()
164 try:
164 try:
165 import resource
165 import resource
166 def clock():
166 def clocku():
167 """clock() -> floating point number
167 """clocku() -> floating point number
168
168
169 Return the CPU time in seconds (user time only, system time is
169 Return the *USER* CPU time in seconds since the start of the process.
170 ignored) since the start of the process. This is done via a call to
170 This is done via a call to resource.getrusage, so it avoids the
171 resource.getrusage, so it avoids the wraparound problems in
171 wraparound problems in time.clock()."""
172 time.clock()."""
173
172
174 return resource.getrusage(resource.RUSAGE_SELF)[0]
173 return resource.getrusage(resource.RUSAGE_SELF)[0]
175
174
175 def clocks():
176 """clocks() -> floating point number
177
178 Return the *SYSTEM* CPU time in seconds since the start of the process.
179 This is done via a call to resource.getrusage, so it avoids the
180 wraparound problems in time.clock()."""
181
182 return resource.getrusage(resource.RUSAGE_SELF)[1]
183
184 def clock():
185 """clock() -> floating point number
186
187 Return the *TOTAL USER+SYSTEM* CPU time in seconds since the start of
188 the process. This is done via a call to resource.getrusage, so it
189 avoids the wraparound problems in time.clock()."""
190
191 u,s = resource.getrusage(resource.RUSAGE_SELF)[:2]
192 return u+s
193
176 def clock2():
194 def clock2():
177 """clock2() -> (t_user,t_system)
195 """clock2() -> (t_user,t_system)
178
196
179 Similar to clock(), but return a tuple of user/system times."""
197 Similar to clock(), but return a tuple of user/system times."""
180 return resource.getrusage(resource.RUSAGE_SELF)[:2]
198 return resource.getrusage(resource.RUSAGE_SELF)[:2]
181
199
182 except ImportError:
200 except ImportError:
183 clock = time.clock
201 # There is no distinction of user/system time under windows, so we just use
202 # time.clock() for everything...
203 clocku = clocks = clock = time.clock
184 def clock2():
204 def clock2():
185 """Under windows, system CPU time can't be measured.
205 """Under windows, system CPU time can't be measured.
186
206
187 This just returns clock() and zero."""
207 This just returns clock() and zero."""
188 return time.clock(),0.0
208 return time.clock(),0.0
189
209
190 def timings_out(reps,func,*args,**kw):
210 def timings_out(reps,func,*args,**kw):
191 """timings_out(reps,func,*args,**kw) -> (t_total,t_per_call,output)
211 """timings_out(reps,func,*args,**kw) -> (t_total,t_per_call,output)
192
212
193 Execute a function reps times, return a tuple with the elapsed total
213 Execute a function reps times, return a tuple with the elapsed total
194 CPU time in seconds, the time per call and the function's output.
214 CPU time in seconds, the time per call and the function's output.
195
215
196 Under Unix, the return value is the sum of user+system time consumed by
216 Under Unix, the return value is the sum of user+system time consumed by
197 the process, computed via the resource module. This prevents problems
217 the process, computed via the resource module. This prevents problems
198 related to the wraparound effect which the time.clock() function has.
218 related to the wraparound effect which the time.clock() function has.
199
219
200 Under Windows the return value is in wall clock seconds. See the
220 Under Windows the return value is in wall clock seconds. See the
201 documentation for the time module for more details."""
221 documentation for the time module for more details."""
202
222
203 reps = int(reps)
223 reps = int(reps)
204 assert reps >=1, 'reps must be >= 1'
224 assert reps >=1, 'reps must be >= 1'
205 if reps==1:
225 if reps==1:
206 start = clock()
226 start = clock()
207 out = func(*args,**kw)
227 out = func(*args,**kw)
208 tot_time = clock()-start
228 tot_time = clock()-start
209 else:
229 else:
210 rng = xrange(reps-1) # the last time is executed separately to store output
230 rng = xrange(reps-1) # the last time is executed separately to store output
211 start = clock()
231 start = clock()
212 for dummy in rng: func(*args,**kw)
232 for dummy in rng: func(*args,**kw)
213 out = func(*args,**kw) # one last time
233 out = func(*args,**kw) # one last time
214 tot_time = clock()-start
234 tot_time = clock()-start
215 av_time = tot_time / reps
235 av_time = tot_time / reps
216 return tot_time,av_time,out
236 return tot_time,av_time,out
217
237
218 def timings(reps,func,*args,**kw):
238 def timings(reps,func,*args,**kw):
219 """timings(reps,func,*args,**kw) -> (t_total,t_per_call)
239 """timings(reps,func,*args,**kw) -> (t_total,t_per_call)
220
240
221 Execute a function reps times, return a tuple with the elapsed total CPU
241 Execute a function reps times, return a tuple with the elapsed total CPU
222 time in seconds and the time per call. These are just the first two values
242 time in seconds and the time per call. These are just the first two values
223 in timings_out()."""
243 in timings_out()."""
224
244
225 return timings_out(reps,func,*args,**kw)[0:2]
245 return timings_out(reps,func,*args,**kw)[0:2]
226
246
227 def timing(func,*args,**kw):
247 def timing(func,*args,**kw):
228 """timing(func,*args,**kw) -> t_total
248 """timing(func,*args,**kw) -> t_total
229
249
230 Execute a function once, return the elapsed total CPU time in
250 Execute a function once, return the elapsed total CPU time in
231 seconds. This is just the first value in timings_out()."""
251 seconds. This is just the first value in timings_out()."""
232
252
233 return timings_out(1,func,*args,**kw)[0]
253 return timings_out(1,func,*args,**kw)[0]
234
254
235 #****************************************************************************
255 #****************************************************************************
236 # file and system
256 # file and system
237
257
238 def arg_split(s,posix=False):
258 def arg_split(s,posix=False):
239 """Split a command line's arguments in a shell-like manner.
259 """Split a command line's arguments in a shell-like manner.
240
260
241 This is a modified version of the standard library's shlex.split()
261 This is a modified version of the standard library's shlex.split()
242 function, but with a default of posix=False for splitting, so that quotes
262 function, but with a default of posix=False for splitting, so that quotes
243 in inputs are respected."""
263 in inputs are respected."""
244
264
245 lex = shlex.shlex(s, posix=posix)
265 lex = shlex.shlex(s, posix=posix)
246 lex.whitespace_split = True
266 lex.whitespace_split = True
247 return list(lex)
267 return list(lex)
248
268
249 def system(cmd,verbose=0,debug=0,header=''):
269 def system(cmd,verbose=0,debug=0,header=''):
250 """Execute a system command, return its exit status.
270 """Execute a system command, return its exit status.
251
271
252 Options:
272 Options:
253
273
254 - verbose (0): print the command to be executed.
274 - verbose (0): print the command to be executed.
255
275
256 - debug (0): only print, do not actually execute.
276 - debug (0): only print, do not actually execute.
257
277
258 - header (''): Header to print on screen prior to the executed command (it
278 - header (''): Header to print on screen prior to the executed command (it
259 is only prepended to the command, no newlines are added).
279 is only prepended to the command, no newlines are added).
260
280
261 Note: a stateful version of this function is available through the
281 Note: a stateful version of this function is available through the
262 SystemExec class."""
282 SystemExec class."""
263
283
264 stat = 0
284 stat = 0
265 if verbose or debug: print header+cmd
285 if verbose or debug: print header+cmd
266 sys.stdout.flush()
286 sys.stdout.flush()
267 if not debug: stat = os.system(cmd)
287 if not debug: stat = os.system(cmd)
268 return stat
288 return stat
269
289
270 # This function is used by ipython in a lot of places to make system calls.
290 # This function is used by ipython in a lot of places to make system calls.
271 # We need it to be slightly different under win32, due to the vagaries of
291 # We need it to be slightly different under win32, due to the vagaries of
272 # 'network shares'. A win32 override is below.
292 # 'network shares'. A win32 override is below.
273
293
274 def shell(cmd,verbose=0,debug=0,header=''):
294 def shell(cmd,verbose=0,debug=0,header=''):
275 """Execute a command in the system shell, always return None.
295 """Execute a command in the system shell, always return None.
276
296
277 Options:
297 Options:
278
298
279 - verbose (0): print the command to be executed.
299 - verbose (0): print the command to be executed.
280
300
281 - debug (0): only print, do not actually execute.
301 - debug (0): only print, do not actually execute.
282
302
283 - header (''): Header to print on screen prior to the executed command (it
303 - header (''): Header to print on screen prior to the executed command (it
284 is only prepended to the command, no newlines are added).
304 is only prepended to the command, no newlines are added).
285
305
286 Note: this is similar to genutils.system(), but it returns None so it can
306 Note: this is similar to genutils.system(), but it returns None so it can
287 be conveniently used in interactive loops without getting the return value
307 be conveniently used in interactive loops without getting the return value
288 (typically 0) printed many times."""
308 (typically 0) printed many times."""
289
309
290 stat = 0
310 stat = 0
291 if verbose or debug: print header+cmd
311 if verbose or debug: print header+cmd
292 # flush stdout so we don't mangle python's buffering
312 # flush stdout so we don't mangle python's buffering
293 sys.stdout.flush()
313 sys.stdout.flush()
294 if not debug:
314 if not debug:
295 os.system(cmd)
315 os.system(cmd)
296
316
297 # override shell() for win32 to deal with network shares
317 # override shell() for win32 to deal with network shares
298 if os.name in ('nt','dos'):
318 if os.name in ('nt','dos'):
299
319
300 shell_ori = shell
320 shell_ori = shell
301
321
302 def shell(cmd,verbose=0,debug=0,header=''):
322 def shell(cmd,verbose=0,debug=0,header=''):
303 if os.getcwd().startswith(r"\\"):
323 if os.getcwd().startswith(r"\\"):
304 path = os.getcwd()
324 path = os.getcwd()
305 # change to c drive (cannot be on UNC-share when issuing os.system,
325 # change to c drive (cannot be on UNC-share when issuing os.system,
306 # as cmd.exe cannot handle UNC addresses)
326 # as cmd.exe cannot handle UNC addresses)
307 os.chdir("c:")
327 os.chdir("c:")
308 # issue pushd to the UNC-share and then run the command
328 # issue pushd to the UNC-share and then run the command
309 try:
329 try:
310 shell_ori('"pushd %s&&"'%path+cmd,verbose,debug,header)
330 shell_ori('"pushd %s&&"'%path+cmd,verbose,debug,header)
311 finally:
331 finally:
312 os.chdir(path)
332 os.chdir(path)
313 else:
333 else:
314 shell_ori(cmd,verbose,debug,header)
334 shell_ori(cmd,verbose,debug,header)
315
335
316 shell.__doc__ = shell_ori.__doc__
336 shell.__doc__ = shell_ori.__doc__
317
337
318 def getoutput(cmd,verbose=0,debug=0,header='',split=0):
338 def getoutput(cmd,verbose=0,debug=0,header='',split=0):
319 """Dummy substitute for perl's backquotes.
339 """Dummy substitute for perl's backquotes.
320
340
321 Executes a command and returns the output.
341 Executes a command and returns the output.
322
342
323 Accepts the same arguments as system(), plus:
343 Accepts the same arguments as system(), plus:
324
344
325 - split(0): if true, the output is returned as a list split on newlines.
345 - split(0): if true, the output is returned as a list split on newlines.
326
346
327 Note: a stateful version of this function is available through the
347 Note: a stateful version of this function is available through the
328 SystemExec class.
348 SystemExec class.
329
349
330 This is pretty much deprecated and rarely used,
350 This is pretty much deprecated and rarely used,
331 genutils.getoutputerror may be what you need.
351 genutils.getoutputerror may be what you need.
332
352
333 """
353 """
334
354
335 if verbose or debug: print header+cmd
355 if verbose or debug: print header+cmd
336 if not debug:
356 if not debug:
337 output = os.popen(cmd).read()
357 output = os.popen(cmd).read()
338 # stipping last \n is here for backwards compat.
358 # stipping last \n is here for backwards compat.
339 if output.endswith('\n'):
359 if output.endswith('\n'):
340 output = output[:-1]
360 output = output[:-1]
341 if split:
361 if split:
342 return output.split('\n')
362 return output.split('\n')
343 else:
363 else:
344 return output
364 return output
345
365
346 def getoutputerror(cmd,verbose=0,debug=0,header='',split=0):
366 def getoutputerror(cmd,verbose=0,debug=0,header='',split=0):
347 """Return (standard output,standard error) of executing cmd in a shell.
367 """Return (standard output,standard error) of executing cmd in a shell.
348
368
349 Accepts the same arguments as system(), plus:
369 Accepts the same arguments as system(), plus:
350
370
351 - split(0): if true, each of stdout/err is returned as a list split on
371 - split(0): if true, each of stdout/err is returned as a list split on
352 newlines.
372 newlines.
353
373
354 Note: a stateful version of this function is available through the
374 Note: a stateful version of this function is available through the
355 SystemExec class."""
375 SystemExec class."""
356
376
357 if verbose or debug: print header+cmd
377 if verbose or debug: print header+cmd
358 if not cmd:
378 if not cmd:
359 if split:
379 if split:
360 return [],[]
380 return [],[]
361 else:
381 else:
362 return '',''
382 return '',''
363 if not debug:
383 if not debug:
364 pin,pout,perr = os.popen3(cmd)
384 pin,pout,perr = os.popen3(cmd)
365 tout = pout.read().rstrip()
385 tout = pout.read().rstrip()
366 terr = perr.read().rstrip()
386 terr = perr.read().rstrip()
367 pin.close()
387 pin.close()
368 pout.close()
388 pout.close()
369 perr.close()
389 perr.close()
370 if split:
390 if split:
371 return tout.split('\n'),terr.split('\n')
391 return tout.split('\n'),terr.split('\n')
372 else:
392 else:
373 return tout,terr
393 return tout,terr
374
394
375 # for compatibility with older naming conventions
395 # for compatibility with older naming conventions
376 xsys = system
396 xsys = system
377 bq = getoutput
397 bq = getoutput
378
398
379 class SystemExec:
399 class SystemExec:
380 """Access the system and getoutput functions through a stateful interface.
400 """Access the system and getoutput functions through a stateful interface.
381
401
382 Note: here we refer to the system and getoutput functions from this
402 Note: here we refer to the system and getoutput functions from this
383 library, not the ones from the standard python library.
403 library, not the ones from the standard python library.
384
404
385 This class offers the system and getoutput functions as methods, but the
405 This class offers the system and getoutput functions as methods, but the
386 verbose, debug and header parameters can be set for the instance (at
406 verbose, debug and header parameters can be set for the instance (at
387 creation time or later) so that they don't need to be specified on each
407 creation time or later) so that they don't need to be specified on each
388 call.
408 call.
389
409
390 For efficiency reasons, there's no way to override the parameters on a
410 For efficiency reasons, there's no way to override the parameters on a
391 per-call basis other than by setting instance attributes. If you need
411 per-call basis other than by setting instance attributes. If you need
392 local overrides, it's best to directly call system() or getoutput().
412 local overrides, it's best to directly call system() or getoutput().
393
413
394 The following names are provided as alternate options:
414 The following names are provided as alternate options:
395 - xsys: alias to system
415 - xsys: alias to system
396 - bq: alias to getoutput
416 - bq: alias to getoutput
397
417
398 An instance can then be created as:
418 An instance can then be created as:
399 >>> sysexec = SystemExec(verbose=1,debug=0,header='Calling: ')
419 >>> sysexec = SystemExec(verbose=1,debug=0,header='Calling: ')
400
420
401 And used as:
421 And used as:
402 >>> sysexec.xsys('pwd')
422 >>> sysexec.xsys('pwd')
403 >>> dirlist = sysexec.bq('ls -l')
423 >>> dirlist = sysexec.bq('ls -l')
404 """
424 """
405
425
406 def __init__(self,verbose=0,debug=0,header='',split=0):
426 def __init__(self,verbose=0,debug=0,header='',split=0):
407 """Specify the instance's values for verbose, debug and header."""
427 """Specify the instance's values for verbose, debug and header."""
408 setattr_list(self,'verbose debug header split')
428 setattr_list(self,'verbose debug header split')
409
429
410 def system(self,cmd):
430 def system(self,cmd):
411 """Stateful interface to system(), with the same keyword parameters."""
431 """Stateful interface to system(), with the same keyword parameters."""
412
432
413 system(cmd,self.verbose,self.debug,self.header)
433 system(cmd,self.verbose,self.debug,self.header)
414
434
415 def shell(self,cmd):
435 def shell(self,cmd):
416 """Stateful interface to shell(), with the same keyword parameters."""
436 """Stateful interface to shell(), with the same keyword parameters."""
417
437
418 shell(cmd,self.verbose,self.debug,self.header)
438 shell(cmd,self.verbose,self.debug,self.header)
419
439
420 xsys = system # alias
440 xsys = system # alias
421
441
422 def getoutput(self,cmd):
442 def getoutput(self,cmd):
423 """Stateful interface to getoutput()."""
443 """Stateful interface to getoutput()."""
424
444
425 return getoutput(cmd,self.verbose,self.debug,self.header,self.split)
445 return getoutput(cmd,self.verbose,self.debug,self.header,self.split)
426
446
427 def getoutputerror(self,cmd):
447 def getoutputerror(self,cmd):
428 """Stateful interface to getoutputerror()."""
448 """Stateful interface to getoutputerror()."""
429
449
430 return getoutputerror(cmd,self.verbose,self.debug,self.header,self.split)
450 return getoutputerror(cmd,self.verbose,self.debug,self.header,self.split)
431
451
432 bq = getoutput # alias
452 bq = getoutput # alias
433
453
434 #-----------------------------------------------------------------------------
454 #-----------------------------------------------------------------------------
435 def mutex_opts(dict,ex_op):
455 def mutex_opts(dict,ex_op):
436 """Check for presence of mutually exclusive keys in a dict.
456 """Check for presence of mutually exclusive keys in a dict.
437
457
438 Call: mutex_opts(dict,[[op1a,op1b],[op2a,op2b]...]"""
458 Call: mutex_opts(dict,[[op1a,op1b],[op2a,op2b]...]"""
439 for op1,op2 in ex_op:
459 for op1,op2 in ex_op:
440 if op1 in dict and op2 in dict:
460 if op1 in dict and op2 in dict:
441 raise ValueError,'\n*** ERROR in Arguments *** '\
461 raise ValueError,'\n*** ERROR in Arguments *** '\
442 'Options '+op1+' and '+op2+' are mutually exclusive.'
462 'Options '+op1+' and '+op2+' are mutually exclusive.'
443
463
444 #-----------------------------------------------------------------------------
464 #-----------------------------------------------------------------------------
445 def get_py_filename(name):
465 def get_py_filename(name):
446 """Return a valid python filename in the current directory.
466 """Return a valid python filename in the current directory.
447
467
448 If the given name is not a file, it adds '.py' and searches again.
468 If the given name is not a file, it adds '.py' and searches again.
449 Raises IOError with an informative message if the file isn't found."""
469 Raises IOError with an informative message if the file isn't found."""
450
470
451 name = os.path.expanduser(name)
471 name = os.path.expanduser(name)
452 if not os.path.isfile(name) and not name.endswith('.py'):
472 if not os.path.isfile(name) and not name.endswith('.py'):
453 name += '.py'
473 name += '.py'
454 if os.path.isfile(name):
474 if os.path.isfile(name):
455 return name
475 return name
456 else:
476 else:
457 raise IOError,'File `%s` not found.' % name
477 raise IOError,'File `%s` not found.' % name
458
478
459 #-----------------------------------------------------------------------------
479 #-----------------------------------------------------------------------------
460 def filefind(fname,alt_dirs = None):
480 def filefind(fname,alt_dirs = None):
461 """Return the given filename either in the current directory, if it
481 """Return the given filename either in the current directory, if it
462 exists, or in a specified list of directories.
482 exists, or in a specified list of directories.
463
483
464 ~ expansion is done on all file and directory names.
484 ~ expansion is done on all file and directory names.
465
485
466 Upon an unsuccessful search, raise an IOError exception."""
486 Upon an unsuccessful search, raise an IOError exception."""
467
487
468 if alt_dirs is None:
488 if alt_dirs is None:
469 try:
489 try:
470 alt_dirs = get_home_dir()
490 alt_dirs = get_home_dir()
471 except HomeDirError:
491 except HomeDirError:
472 alt_dirs = os.getcwd()
492 alt_dirs = os.getcwd()
473 search = [fname] + list_strings(alt_dirs)
493 search = [fname] + list_strings(alt_dirs)
474 search = map(os.path.expanduser,search)
494 search = map(os.path.expanduser,search)
475 #print 'search list for',fname,'list:',search # dbg
495 #print 'search list for',fname,'list:',search # dbg
476 fname = search[0]
496 fname = search[0]
477 if os.path.isfile(fname):
497 if os.path.isfile(fname):
478 return fname
498 return fname
479 for direc in search[1:]:
499 for direc in search[1:]:
480 testname = os.path.join(direc,fname)
500 testname = os.path.join(direc,fname)
481 #print 'testname',testname # dbg
501 #print 'testname',testname # dbg
482 if os.path.isfile(testname):
502 if os.path.isfile(testname):
483 return testname
503 return testname
484 raise IOError,'File' + `fname` + \
504 raise IOError,'File' + `fname` + \
485 ' not found in current or supplied directories:' + `alt_dirs`
505 ' not found in current or supplied directories:' + `alt_dirs`
486
506
487 #----------------------------------------------------------------------------
507 #----------------------------------------------------------------------------
488 def file_read(filename):
508 def file_read(filename):
489 """Read a file and close it. Returns the file source."""
509 """Read a file and close it. Returns the file source."""
490 fobj = open(filename,'r');
510 fobj = open(filename,'r');
491 source = fobj.read();
511 source = fobj.read();
492 fobj.close()
512 fobj.close()
493 return source
513 return source
494
514
495 def file_readlines(filename):
515 def file_readlines(filename):
496 """Read a file and close it. Returns the file source using readlines()."""
516 """Read a file and close it. Returns the file source using readlines()."""
497 fobj = open(filename,'r');
517 fobj = open(filename,'r');
498 lines = fobj.readlines();
518 lines = fobj.readlines();
499 fobj.close()
519 fobj.close()
500 return lines
520 return lines
501
521
502 #----------------------------------------------------------------------------
522 #----------------------------------------------------------------------------
503 def target_outdated(target,deps):
523 def target_outdated(target,deps):
504 """Determine whether a target is out of date.
524 """Determine whether a target is out of date.
505
525
506 target_outdated(target,deps) -> 1/0
526 target_outdated(target,deps) -> 1/0
507
527
508 deps: list of filenames which MUST exist.
528 deps: list of filenames which MUST exist.
509 target: single filename which may or may not exist.
529 target: single filename which may or may not exist.
510
530
511 If target doesn't exist or is older than any file listed in deps, return
531 If target doesn't exist or is older than any file listed in deps, return
512 true, otherwise return false.
532 true, otherwise return false.
513 """
533 """
514 try:
534 try:
515 target_time = os.path.getmtime(target)
535 target_time = os.path.getmtime(target)
516 except os.error:
536 except os.error:
517 return 1
537 return 1
518 for dep in deps:
538 for dep in deps:
519 dep_time = os.path.getmtime(dep)
539 dep_time = os.path.getmtime(dep)
520 if dep_time > target_time:
540 if dep_time > target_time:
521 #print "For target",target,"Dep failed:",dep # dbg
541 #print "For target",target,"Dep failed:",dep # dbg
522 #print "times (dep,tar):",dep_time,target_time # dbg
542 #print "times (dep,tar):",dep_time,target_time # dbg
523 return 1
543 return 1
524 return 0
544 return 0
525
545
526 #-----------------------------------------------------------------------------
546 #-----------------------------------------------------------------------------
527 def target_update(target,deps,cmd):
547 def target_update(target,deps,cmd):
528 """Update a target with a given command given a list of dependencies.
548 """Update a target with a given command given a list of dependencies.
529
549
530 target_update(target,deps,cmd) -> runs cmd if target is outdated.
550 target_update(target,deps,cmd) -> runs cmd if target is outdated.
531
551
532 This is just a wrapper around target_outdated() which calls the given
552 This is just a wrapper around target_outdated() which calls the given
533 command if target is outdated."""
553 command if target is outdated."""
534
554
535 if target_outdated(target,deps):
555 if target_outdated(target,deps):
536 xsys(cmd)
556 xsys(cmd)
537
557
538 #----------------------------------------------------------------------------
558 #----------------------------------------------------------------------------
539 def unquote_ends(istr):
559 def unquote_ends(istr):
540 """Remove a single pair of quotes from the endpoints of a string."""
560 """Remove a single pair of quotes from the endpoints of a string."""
541
561
542 if not istr:
562 if not istr:
543 return istr
563 return istr
544 if (istr[0]=="'" and istr[-1]=="'") or \
564 if (istr[0]=="'" and istr[-1]=="'") or \
545 (istr[0]=='"' and istr[-1]=='"'):
565 (istr[0]=='"' and istr[-1]=='"'):
546 return istr[1:-1]
566 return istr[1:-1]
547 else:
567 else:
548 return istr
568 return istr
549
569
550 #----------------------------------------------------------------------------
570 #----------------------------------------------------------------------------
551 def process_cmdline(argv,names=[],defaults={},usage=''):
571 def process_cmdline(argv,names=[],defaults={},usage=''):
552 """ Process command-line options and arguments.
572 """ Process command-line options and arguments.
553
573
554 Arguments:
574 Arguments:
555
575
556 - argv: list of arguments, typically sys.argv.
576 - argv: list of arguments, typically sys.argv.
557
577
558 - names: list of option names. See DPyGetOpt docs for details on options
578 - names: list of option names. See DPyGetOpt docs for details on options
559 syntax.
579 syntax.
560
580
561 - defaults: dict of default values.
581 - defaults: dict of default values.
562
582
563 - usage: optional usage notice to print if a wrong argument is passed.
583 - usage: optional usage notice to print if a wrong argument is passed.
564
584
565 Return a dict of options and a list of free arguments."""
585 Return a dict of options and a list of free arguments."""
566
586
567 getopt = DPyGetOpt.DPyGetOpt()
587 getopt = DPyGetOpt.DPyGetOpt()
568 getopt.setIgnoreCase(0)
588 getopt.setIgnoreCase(0)
569 getopt.parseConfiguration(names)
589 getopt.parseConfiguration(names)
570
590
571 try:
591 try:
572 getopt.processArguments(argv)
592 getopt.processArguments(argv)
573 except:
593 except:
574 print usage
594 print usage
575 warn(`sys.exc_value`,level=4)
595 warn(`sys.exc_value`,level=4)
576
596
577 defaults.update(getopt.optionValues)
597 defaults.update(getopt.optionValues)
578 args = getopt.freeValues
598 args = getopt.freeValues
579
599
580 return defaults,args
600 return defaults,args
581
601
582 #----------------------------------------------------------------------------
602 #----------------------------------------------------------------------------
583 def optstr2types(ostr):
603 def optstr2types(ostr):
584 """Convert a string of option names to a dict of type mappings.
604 """Convert a string of option names to a dict of type mappings.
585
605
586 optstr2types(str) -> {None:'string_opts',int:'int_opts',float:'float_opts'}
606 optstr2types(str) -> {None:'string_opts',int:'int_opts',float:'float_opts'}
587
607
588 This is used to get the types of all the options in a string formatted
608 This is used to get the types of all the options in a string formatted
589 with the conventions of DPyGetOpt. The 'type' None is used for options
609 with the conventions of DPyGetOpt. The 'type' None is used for options
590 which are strings (they need no further conversion). This function's main
610 which are strings (they need no further conversion). This function's main
591 use is to get a typemap for use with read_dict().
611 use is to get a typemap for use with read_dict().
592 """
612 """
593
613
594 typeconv = {None:'',int:'',float:''}
614 typeconv = {None:'',int:'',float:''}
595 typemap = {'s':None,'i':int,'f':float}
615 typemap = {'s':None,'i':int,'f':float}
596 opt_re = re.compile(r'([\w]*)([^:=]*:?=?)([sif]?)')
616 opt_re = re.compile(r'([\w]*)([^:=]*:?=?)([sif]?)')
597
617
598 for w in ostr.split():
618 for w in ostr.split():
599 oname,alias,otype = opt_re.match(w).groups()
619 oname,alias,otype = opt_re.match(w).groups()
600 if otype == '' or alias == '!': # simple switches are integers too
620 if otype == '' or alias == '!': # simple switches are integers too
601 otype = 'i'
621 otype = 'i'
602 typeconv[typemap[otype]] += oname + ' '
622 typeconv[typemap[otype]] += oname + ' '
603 return typeconv
623 return typeconv
604
624
605 #----------------------------------------------------------------------------
625 #----------------------------------------------------------------------------
606 def read_dict(filename,type_conv=None,**opt):
626 def read_dict(filename,type_conv=None,**opt):
607
627
608 """Read a dictionary of key=value pairs from an input file, optionally
628 """Read a dictionary of key=value pairs from an input file, optionally
609 performing conversions on the resulting values.
629 performing conversions on the resulting values.
610
630
611 read_dict(filename,type_conv,**opt) -> dict
631 read_dict(filename,type_conv,**opt) -> dict
612
632
613 Only one value per line is accepted, the format should be
633 Only one value per line is accepted, the format should be
614 # optional comments are ignored
634 # optional comments are ignored
615 key value\n
635 key value\n
616
636
617 Args:
637 Args:
618
638
619 - type_conv: A dictionary specifying which keys need to be converted to
639 - type_conv: A dictionary specifying which keys need to be converted to
620 which types. By default all keys are read as strings. This dictionary
640 which types. By default all keys are read as strings. This dictionary
621 should have as its keys valid conversion functions for strings
641 should have as its keys valid conversion functions for strings
622 (int,long,float,complex, or your own). The value for each key
642 (int,long,float,complex, or your own). The value for each key
623 (converter) should be a whitespace separated string containing the names
643 (converter) should be a whitespace separated string containing the names
624 of all the entries in the file to be converted using that function. For
644 of all the entries in the file to be converted using that function. For
625 keys to be left alone, use None as the conversion function (only needed
645 keys to be left alone, use None as the conversion function (only needed
626 with purge=1, see below).
646 with purge=1, see below).
627
647
628 - opt: dictionary with extra options as below (default in parens)
648 - opt: dictionary with extra options as below (default in parens)
629
649
630 purge(0): if set to 1, all keys *not* listed in type_conv are purged out
650 purge(0): if set to 1, all keys *not* listed in type_conv are purged out
631 of the dictionary to be returned. If purge is going to be used, the
651 of the dictionary to be returned. If purge is going to be used, the
632 set of keys to be left as strings also has to be explicitly specified
652 set of keys to be left as strings also has to be explicitly specified
633 using the (non-existent) conversion function None.
653 using the (non-existent) conversion function None.
634
654
635 fs(None): field separator. This is the key/value separator to be used
655 fs(None): field separator. This is the key/value separator to be used
636 when parsing the file. The None default means any whitespace [behavior
656 when parsing the file. The None default means any whitespace [behavior
637 of string.split()].
657 of string.split()].
638
658
639 strip(0): if 1, strip string values of leading/trailinig whitespace.
659 strip(0): if 1, strip string values of leading/trailinig whitespace.
640
660
641 warn(1): warning level if requested keys are not found in file.
661 warn(1): warning level if requested keys are not found in file.
642 - 0: silently ignore.
662 - 0: silently ignore.
643 - 1: inform but proceed.
663 - 1: inform but proceed.
644 - 2: raise KeyError exception.
664 - 2: raise KeyError exception.
645
665
646 no_empty(0): if 1, remove keys with whitespace strings as a value.
666 no_empty(0): if 1, remove keys with whitespace strings as a value.
647
667
648 unique([]): list of keys (or space separated string) which can't be
668 unique([]): list of keys (or space separated string) which can't be
649 repeated. If one such key is found in the file, each new instance
669 repeated. If one such key is found in the file, each new instance
650 overwrites the previous one. For keys not listed here, the behavior is
670 overwrites the previous one. For keys not listed here, the behavior is
651 to make a list of all appearances.
671 to make a list of all appearances.
652
672
653 Example:
673 Example:
654 If the input file test.ini has:
674 If the input file test.ini has:
655 i 3
675 i 3
656 x 4.5
676 x 4.5
657 y 5.5
677 y 5.5
658 s hi ho
678 s hi ho
659 Then:
679 Then:
660
680
661 >>> type_conv={int:'i',float:'x',None:'s'}
681 >>> type_conv={int:'i',float:'x',None:'s'}
662 >>> read_dict('test.ini')
682 >>> read_dict('test.ini')
663 {'i': '3', 's': 'hi ho', 'x': '4.5', 'y': '5.5'}
683 {'i': '3', 's': 'hi ho', 'x': '4.5', 'y': '5.5'}
664 >>> read_dict('test.ini',type_conv)
684 >>> read_dict('test.ini',type_conv)
665 {'i': 3, 's': 'hi ho', 'x': 4.5, 'y': '5.5'}
685 {'i': 3, 's': 'hi ho', 'x': 4.5, 'y': '5.5'}
666 >>> read_dict('test.ini',type_conv,purge=1)
686 >>> read_dict('test.ini',type_conv,purge=1)
667 {'i': 3, 's': 'hi ho', 'x': 4.5}
687 {'i': 3, 's': 'hi ho', 'x': 4.5}
668 """
688 """
669
689
670 # starting config
690 # starting config
671 opt.setdefault('purge',0)
691 opt.setdefault('purge',0)
672 opt.setdefault('fs',None) # field sep defaults to any whitespace
692 opt.setdefault('fs',None) # field sep defaults to any whitespace
673 opt.setdefault('strip',0)
693 opt.setdefault('strip',0)
674 opt.setdefault('warn',1)
694 opt.setdefault('warn',1)
675 opt.setdefault('no_empty',0)
695 opt.setdefault('no_empty',0)
676 opt.setdefault('unique','')
696 opt.setdefault('unique','')
677 if type(opt['unique']) in StringTypes:
697 if type(opt['unique']) in StringTypes:
678 unique_keys = qw(opt['unique'])
698 unique_keys = qw(opt['unique'])
679 elif type(opt['unique']) in (types.TupleType,types.ListType):
699 elif type(opt['unique']) in (types.TupleType,types.ListType):
680 unique_keys = opt['unique']
700 unique_keys = opt['unique']
681 else:
701 else:
682 raise ValueError, 'Unique keys must be given as a string, List or Tuple'
702 raise ValueError, 'Unique keys must be given as a string, List or Tuple'
683
703
684 dict = {}
704 dict = {}
685 # first read in table of values as strings
705 # first read in table of values as strings
686 file = open(filename,'r')
706 file = open(filename,'r')
687 for line in file.readlines():
707 for line in file.readlines():
688 line = line.strip()
708 line = line.strip()
689 if len(line) and line[0]=='#': continue
709 if len(line) and line[0]=='#': continue
690 if len(line)>0:
710 if len(line)>0:
691 lsplit = line.split(opt['fs'],1)
711 lsplit = line.split(opt['fs'],1)
692 try:
712 try:
693 key,val = lsplit
713 key,val = lsplit
694 except ValueError:
714 except ValueError:
695 key,val = lsplit[0],''
715 key,val = lsplit[0],''
696 key = key.strip()
716 key = key.strip()
697 if opt['strip']: val = val.strip()
717 if opt['strip']: val = val.strip()
698 if val == "''" or val == '""': val = ''
718 if val == "''" or val == '""': val = ''
699 if opt['no_empty'] and (val=='' or val.isspace()):
719 if opt['no_empty'] and (val=='' or val.isspace()):
700 continue
720 continue
701 # if a key is found more than once in the file, build a list
721 # if a key is found more than once in the file, build a list
702 # unless it's in the 'unique' list. In that case, last found in file
722 # unless it's in the 'unique' list. In that case, last found in file
703 # takes precedence. User beware.
723 # takes precedence. User beware.
704 try:
724 try:
705 if dict[key] and key in unique_keys:
725 if dict[key] and key in unique_keys:
706 dict[key] = val
726 dict[key] = val
707 elif type(dict[key]) is types.ListType:
727 elif type(dict[key]) is types.ListType:
708 dict[key].append(val)
728 dict[key].append(val)
709 else:
729 else:
710 dict[key] = [dict[key],val]
730 dict[key] = [dict[key],val]
711 except KeyError:
731 except KeyError:
712 dict[key] = val
732 dict[key] = val
713 # purge if requested
733 # purge if requested
714 if opt['purge']:
734 if opt['purge']:
715 accepted_keys = qwflat(type_conv.values())
735 accepted_keys = qwflat(type_conv.values())
716 for key in dict.keys():
736 for key in dict.keys():
717 if key in accepted_keys: continue
737 if key in accepted_keys: continue
718 del(dict[key])
738 del(dict[key])
719 # now convert if requested
739 # now convert if requested
720 if type_conv==None: return dict
740 if type_conv==None: return dict
721 conversions = type_conv.keys()
741 conversions = type_conv.keys()
722 try: conversions.remove(None)
742 try: conversions.remove(None)
723 except: pass
743 except: pass
724 for convert in conversions:
744 for convert in conversions:
725 for val in qw(type_conv[convert]):
745 for val in qw(type_conv[convert]):
726 try:
746 try:
727 dict[val] = convert(dict[val])
747 dict[val] = convert(dict[val])
728 except KeyError,e:
748 except KeyError,e:
729 if opt['warn'] == 0:
749 if opt['warn'] == 0:
730 pass
750 pass
731 elif opt['warn'] == 1:
751 elif opt['warn'] == 1:
732 print >>sys.stderr, 'Warning: key',val,\
752 print >>sys.stderr, 'Warning: key',val,\
733 'not found in file',filename
753 'not found in file',filename
734 elif opt['warn'] == 2:
754 elif opt['warn'] == 2:
735 raise KeyError,e
755 raise KeyError,e
736 else:
756 else:
737 raise ValueError,'Warning level must be 0,1 or 2'
757 raise ValueError,'Warning level must be 0,1 or 2'
738
758
739 return dict
759 return dict
740
760
741 #----------------------------------------------------------------------------
761 #----------------------------------------------------------------------------
742 def flag_calls(func):
762 def flag_calls(func):
743 """Wrap a function to detect and flag when it gets called.
763 """Wrap a function to detect and flag when it gets called.
744
764
745 This is a decorator which takes a function and wraps it in a function with
765 This is a decorator which takes a function and wraps it in a function with
746 a 'called' attribute. wrapper.called is initialized to False.
766 a 'called' attribute. wrapper.called is initialized to False.
747
767
748 The wrapper.called attribute is set to False right before each call to the
768 The wrapper.called attribute is set to False right before each call to the
749 wrapped function, so if the call fails it remains False. After the call
769 wrapped function, so if the call fails it remains False. After the call
750 completes, wrapper.called is set to True and the output is returned.
770 completes, wrapper.called is set to True and the output is returned.
751
771
752 Testing for truth in wrapper.called allows you to determine if a call to
772 Testing for truth in wrapper.called allows you to determine if a call to
753 func() was attempted and succeeded."""
773 func() was attempted and succeeded."""
754
774
755 def wrapper(*args,**kw):
775 def wrapper(*args,**kw):
756 wrapper.called = False
776 wrapper.called = False
757 out = func(*args,**kw)
777 out = func(*args,**kw)
758 wrapper.called = True
778 wrapper.called = True
759 return out
779 return out
760
780
761 wrapper.called = False
781 wrapper.called = False
762 wrapper.__doc__ = func.__doc__
782 wrapper.__doc__ = func.__doc__
763 return wrapper
783 return wrapper
764
784
765 #----------------------------------------------------------------------------
785 #----------------------------------------------------------------------------
766 class HomeDirError(Error):
786 class HomeDirError(Error):
767 pass
787 pass
768
788
769 def get_home_dir():
789 def get_home_dir():
770 """Return the closest possible equivalent to a 'home' directory.
790 """Return the closest possible equivalent to a 'home' directory.
771
791
772 We first try $HOME. Absent that, on NT it's $HOMEDRIVE\$HOMEPATH.
792 We first try $HOME. Absent that, on NT it's $HOMEDRIVE\$HOMEPATH.
773
793
774 Currently only Posix and NT are implemented, a HomeDirError exception is
794 Currently only Posix and NT are implemented, a HomeDirError exception is
775 raised for all other OSes. """
795 raised for all other OSes. """
776
796
777 isdir = os.path.isdir
797 isdir = os.path.isdir
778 env = os.environ
798 env = os.environ
779 try:
799 try:
780 homedir = env['HOME']
800 homedir = env['HOME']
781 if not isdir(homedir):
801 if not isdir(homedir):
782 # in case a user stuck some string which does NOT resolve to a
802 # in case a user stuck some string which does NOT resolve to a
783 # valid path, it's as good as if we hadn't foud it
803 # valid path, it's as good as if we hadn't foud it
784 raise KeyError
804 raise KeyError
785 return homedir
805 return homedir
786 except KeyError:
806 except KeyError:
787 if os.name == 'posix':
807 if os.name == 'posix':
788 raise HomeDirError,'undefined $HOME, IPython can not proceed.'
808 raise HomeDirError,'undefined $HOME, IPython can not proceed.'
789 elif os.name == 'nt':
809 elif os.name == 'nt':
790 # For some strange reason, win9x returns 'nt' for os.name.
810 # For some strange reason, win9x returns 'nt' for os.name.
791 try:
811 try:
792 homedir = os.path.join(env['HOMEDRIVE'],env['HOMEPATH'])
812 homedir = os.path.join(env['HOMEDRIVE'],env['HOMEPATH'])
793 if not isdir(homedir):
813 if not isdir(homedir):
794 homedir = os.path.join(env['USERPROFILE'])
814 homedir = os.path.join(env['USERPROFILE'])
795 if not isdir(homedir):
815 if not isdir(homedir):
796 raise HomeDirError
816 raise HomeDirError
797 return homedir
817 return homedir
798 except:
818 except:
799 try:
819 try:
800 # Use the registry to get the 'My Documents' folder.
820 # Use the registry to get the 'My Documents' folder.
801 import _winreg as wreg
821 import _winreg as wreg
802 key = wreg.OpenKey(wreg.HKEY_CURRENT_USER,
822 key = wreg.OpenKey(wreg.HKEY_CURRENT_USER,
803 "Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders")
823 "Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders")
804 homedir = wreg.QueryValueEx(key,'Personal')[0]
824 homedir = wreg.QueryValueEx(key,'Personal')[0]
805 key.Close()
825 key.Close()
806 if not isdir(homedir):
826 if not isdir(homedir):
807 e = ('Invalid "Personal" folder registry key '
827 e = ('Invalid "Personal" folder registry key '
808 'typically "My Documents".\n'
828 'typically "My Documents".\n'
809 'Value: %s\n'
829 'Value: %s\n'
810 'This is not a valid directory on your system.' %
830 'This is not a valid directory on your system.' %
811 homedir)
831 homedir)
812 raise HomeDirError(e)
832 raise HomeDirError(e)
813 return homedir
833 return homedir
814 except HomeDirError:
834 except HomeDirError:
815 raise
835 raise
816 except:
836 except:
817 return 'C:\\'
837 return 'C:\\'
818 elif os.name == 'dos':
838 elif os.name == 'dos':
819 # Desperate, may do absurd things in classic MacOS. May work under DOS.
839 # Desperate, may do absurd things in classic MacOS. May work under DOS.
820 return 'C:\\'
840 return 'C:\\'
821 else:
841 else:
822 raise HomeDirError,'support for your operating system not implemented.'
842 raise HomeDirError,'support for your operating system not implemented.'
823
843
824 #****************************************************************************
844 #****************************************************************************
825 # strings and text
845 # strings and text
826
846
827 class LSString(str):
847 class LSString(str):
828 """String derivative with a special access attributes.
848 """String derivative with a special access attributes.
829
849
830 These are normal strings, but with the special attributes:
850 These are normal strings, but with the special attributes:
831
851
832 .l (or .list) : value as list (split on newlines).
852 .l (or .list) : value as list (split on newlines).
833 .n (or .nlstr): original value (the string itself).
853 .n (or .nlstr): original value (the string itself).
834 .s (or .spstr): value as whitespace-separated string.
854 .s (or .spstr): value as whitespace-separated string.
835
855
836 Any values which require transformations are computed only once and
856 Any values which require transformations are computed only once and
837 cached.
857 cached.
838
858
839 Such strings are very useful to efficiently interact with the shell, which
859 Such strings are very useful to efficiently interact with the shell, which
840 typically only understands whitespace-separated options for commands."""
860 typically only understands whitespace-separated options for commands."""
841
861
842 def get_list(self):
862 def get_list(self):
843 try:
863 try:
844 return self.__list
864 return self.__list
845 except AttributeError:
865 except AttributeError:
846 self.__list = self.split('\n')
866 self.__list = self.split('\n')
847 return self.__list
867 return self.__list
848
868
849 l = list = property(get_list)
869 l = list = property(get_list)
850
870
851 def get_spstr(self):
871 def get_spstr(self):
852 try:
872 try:
853 return self.__spstr
873 return self.__spstr
854 except AttributeError:
874 except AttributeError:
855 self.__spstr = self.replace('\n',' ')
875 self.__spstr = self.replace('\n',' ')
856 return self.__spstr
876 return self.__spstr
857
877
858 s = spstr = property(get_spstr)
878 s = spstr = property(get_spstr)
859
879
860 def get_nlstr(self):
880 def get_nlstr(self):
861 return self
881 return self
862
882
863 n = nlstr = property(get_nlstr)
883 n = nlstr = property(get_nlstr)
864
884
865 def get_paths(self):
885 def get_paths(self):
866 try:
886 try:
867 return self.__paths
887 return self.__paths
868 except AttributeError:
888 except AttributeError:
869 self.__paths = [path(p) for p in self.split('\n') if os.path.exists(p)]
889 self.__paths = [path(p) for p in self.split('\n') if os.path.exists(p)]
870 return self.__paths
890 return self.__paths
871
891
872 p = paths = property(get_paths)
892 p = paths = property(get_paths)
873
893
874
894
875 #----------------------------------------------------------------------------
895 #----------------------------------------------------------------------------
876 class SList(list):
896 class SList(list):
877 """List derivative with a special access attributes.
897 """List derivative with a special access attributes.
878
898
879 These are normal lists, but with the special attributes:
899 These are normal lists, but with the special attributes:
880
900
881 .l (or .list) : value as list (the list itself).
901 .l (or .list) : value as list (the list itself).
882 .n (or .nlstr): value as a string, joined on newlines.
902 .n (or .nlstr): value as a string, joined on newlines.
883 .s (or .spstr): value as a string, joined on spaces.
903 .s (or .spstr): value as a string, joined on spaces.
884
904
885 Any values which require transformations are computed only once and
905 Any values which require transformations are computed only once and
886 cached."""
906 cached."""
887
907
888 def get_list(self):
908 def get_list(self):
889 return self
909 return self
890
910
891 l = list = property(get_list)
911 l = list = property(get_list)
892
912
893 def get_spstr(self):
913 def get_spstr(self):
894 try:
914 try:
895 return self.__spstr
915 return self.__spstr
896 except AttributeError:
916 except AttributeError:
897 self.__spstr = ' '.join(self)
917 self.__spstr = ' '.join(self)
898 return self.__spstr
918 return self.__spstr
899
919
900 s = spstr = property(get_spstr)
920 s = spstr = property(get_spstr)
901
921
902 def get_nlstr(self):
922 def get_nlstr(self):
903 try:
923 try:
904 return self.__nlstr
924 return self.__nlstr
905 except AttributeError:
925 except AttributeError:
906 self.__nlstr = '\n'.join(self)
926 self.__nlstr = '\n'.join(self)
907 return self.__nlstr
927 return self.__nlstr
908
928
909 n = nlstr = property(get_nlstr)
929 n = nlstr = property(get_nlstr)
910
930
911 def get_paths(self):
931 def get_paths(self):
912 try:
932 try:
913 return self.__paths
933 return self.__paths
914 except AttributeError:
934 except AttributeError:
915 self.__paths = [path(p) for p in self if os.path.exists(p)]
935 self.__paths = [path(p) for p in self if os.path.exists(p)]
916 return self.__paths
936 return self.__paths
917
937
918 p = paths = property(get_paths)
938 p = paths = property(get_paths)
919
939
920 #----------------------------------------------------------------------------
940 #----------------------------------------------------------------------------
921 def esc_quotes(strng):
941 def esc_quotes(strng):
922 """Return the input string with single and double quotes escaped out"""
942 """Return the input string with single and double quotes escaped out"""
923
943
924 return strng.replace('"','\\"').replace("'","\\'")
944 return strng.replace('"','\\"').replace("'","\\'")
925
945
926 #----------------------------------------------------------------------------
946 #----------------------------------------------------------------------------
927 def make_quoted_expr(s):
947 def make_quoted_expr(s):
928 """Return string s in appropriate quotes, using raw string if possible.
948 """Return string s in appropriate quotes, using raw string if possible.
929
949
930 Effectively this turns string: cd \ao\ao\
950 Effectively this turns string: cd \ao\ao\
931 to: r"cd \ao\ao\_"[:-1]
951 to: r"cd \ao\ao\_"[:-1]
932
952
933 Note the use of raw string and padding at the end to allow trailing backslash.
953 Note the use of raw string and padding at the end to allow trailing backslash.
934
954
935 """
955 """
936
956
937 tail = ''
957 tail = ''
938 tailpadding = ''
958 tailpadding = ''
939 raw = ''
959 raw = ''
940 if "\\" in s:
960 if "\\" in s:
941 raw = 'r'
961 raw = 'r'
942 if s.endswith('\\'):
962 if s.endswith('\\'):
943 tail = '[:-1]'
963 tail = '[:-1]'
944 tailpadding = '_'
964 tailpadding = '_'
945 if '"' not in s:
965 if '"' not in s:
946 quote = '"'
966 quote = '"'
947 elif "'" not in s:
967 elif "'" not in s:
948 quote = "'"
968 quote = "'"
949 elif '"""' not in s and not s.endswith('"'):
969 elif '"""' not in s and not s.endswith('"'):
950 quote = '"""'
970 quote = '"""'
951 elif "'''" not in s and not s.endswith("'"):
971 elif "'''" not in s and not s.endswith("'"):
952 quote = "'''"
972 quote = "'''"
953 else:
973 else:
954 # give up, backslash-escaped string will do
974 # give up, backslash-escaped string will do
955 return '"%s"' % esc_quotes(s)
975 return '"%s"' % esc_quotes(s)
956 res = itpl("$raw$quote$s$tailpadding$quote$tail")
976 res = itpl("$raw$quote$s$tailpadding$quote$tail")
957 return res
977 return res
958
978
959
979
960 #----------------------------------------------------------------------------
980 #----------------------------------------------------------------------------
961 def raw_input_multi(header='', ps1='==> ', ps2='..> ',terminate_str = '.'):
981 def raw_input_multi(header='', ps1='==> ', ps2='..> ',terminate_str = '.'):
962 """Take multiple lines of input.
982 """Take multiple lines of input.
963
983
964 A list with each line of input as a separate element is returned when a
984 A list with each line of input as a separate element is returned when a
965 termination string is entered (defaults to a single '.'). Input can also
985 termination string is entered (defaults to a single '.'). Input can also
966 terminate via EOF (^D in Unix, ^Z-RET in Windows).
986 terminate via EOF (^D in Unix, ^Z-RET in Windows).
967
987
968 Lines of input which end in \\ are joined into single entries (and a
988 Lines of input which end in \\ are joined into single entries (and a
969 secondary continuation prompt is issued as long as the user terminates
989 secondary continuation prompt is issued as long as the user terminates
970 lines with \\). This allows entering very long strings which are still
990 lines with \\). This allows entering very long strings which are still
971 meant to be treated as single entities.
991 meant to be treated as single entities.
972 """
992 """
973
993
974 try:
994 try:
975 if header:
995 if header:
976 header += '\n'
996 header += '\n'
977 lines = [raw_input(header + ps1)]
997 lines = [raw_input(header + ps1)]
978 except EOFError:
998 except EOFError:
979 return []
999 return []
980 terminate = [terminate_str]
1000 terminate = [terminate_str]
981 try:
1001 try:
982 while lines[-1:] != terminate:
1002 while lines[-1:] != terminate:
983 new_line = raw_input(ps1)
1003 new_line = raw_input(ps1)
984 while new_line.endswith('\\'):
1004 while new_line.endswith('\\'):
985 new_line = new_line[:-1] + raw_input(ps2)
1005 new_line = new_line[:-1] + raw_input(ps2)
986 lines.append(new_line)
1006 lines.append(new_line)
987
1007
988 return lines[:-1] # don't return the termination command
1008 return lines[:-1] # don't return the termination command
989 except EOFError:
1009 except EOFError:
990 print
1010 print
991 return lines
1011 return lines
992
1012
993 #----------------------------------------------------------------------------
1013 #----------------------------------------------------------------------------
994 def raw_input_ext(prompt='', ps2='... '):
1014 def raw_input_ext(prompt='', ps2='... '):
995 """Similar to raw_input(), but accepts extended lines if input ends with \\."""
1015 """Similar to raw_input(), but accepts extended lines if input ends with \\."""
996
1016
997 line = raw_input(prompt)
1017 line = raw_input(prompt)
998 while line.endswith('\\'):
1018 while line.endswith('\\'):
999 line = line[:-1] + raw_input(ps2)
1019 line = line[:-1] + raw_input(ps2)
1000 return line
1020 return line
1001
1021
1002 #----------------------------------------------------------------------------
1022 #----------------------------------------------------------------------------
1003 def ask_yes_no(prompt,default=None):
1023 def ask_yes_no(prompt,default=None):
1004 """Asks a question and returns an integer 1/0 (y/n) answer.
1024 """Asks a question and returns an integer 1/0 (y/n) answer.
1005
1025
1006 If default is given (one of 'y','n'), it is used if the user input is
1026 If default is given (one of 'y','n'), it is used if the user input is
1007 empty. Otherwise the question is repeated until an answer is given.
1027 empty. Otherwise the question is repeated until an answer is given.
1008
1028
1009 An EOF is treated as the default answer. If there is no default, an
1029 An EOF is treated as the default answer. If there is no default, an
1010 exception is raised to prevent infinite loops.
1030 exception is raised to prevent infinite loops.
1011
1031
1012 Valid answers are: y/yes/n/no (match is not case sensitive)."""
1032 Valid answers are: y/yes/n/no (match is not case sensitive)."""
1013
1033
1014 answers = {'y':True,'n':False,'yes':True,'no':False}
1034 answers = {'y':True,'n':False,'yes':True,'no':False}
1015 ans = None
1035 ans = None
1016 while ans not in answers.keys():
1036 while ans not in answers.keys():
1017 try:
1037 try:
1018 ans = raw_input(prompt+' ').lower()
1038 ans = raw_input(prompt+' ').lower()
1019 if not ans: # response was an empty string
1039 if not ans: # response was an empty string
1020 ans = default
1040 ans = default
1021 except KeyboardInterrupt:
1041 except KeyboardInterrupt:
1022 pass
1042 pass
1023 except EOFError:
1043 except EOFError:
1024 if default in answers.keys():
1044 if default in answers.keys():
1025 ans = default
1045 ans = default
1026 print
1046 print
1027 else:
1047 else:
1028 raise
1048 raise
1029
1049
1030 return answers[ans]
1050 return answers[ans]
1031
1051
1032 #----------------------------------------------------------------------------
1052 #----------------------------------------------------------------------------
1033 def marquee(txt='',width=78,mark='*'):
1053 def marquee(txt='',width=78,mark='*'):
1034 """Return the input string centered in a 'marquee'."""
1054 """Return the input string centered in a 'marquee'."""
1035 if not txt:
1055 if not txt:
1036 return (mark*width)[:width]
1056 return (mark*width)[:width]
1037 nmark = (width-len(txt)-2)/len(mark)/2
1057 nmark = (width-len(txt)-2)/len(mark)/2
1038 if nmark < 0: nmark =0
1058 if nmark < 0: nmark =0
1039 marks = mark*nmark
1059 marks = mark*nmark
1040 return '%s %s %s' % (marks,txt,marks)
1060 return '%s %s %s' % (marks,txt,marks)
1041
1061
1042 #----------------------------------------------------------------------------
1062 #----------------------------------------------------------------------------
1043 class EvalDict:
1063 class EvalDict:
1044 """
1064 """
1045 Emulate a dict which evaluates its contents in the caller's frame.
1065 Emulate a dict which evaluates its contents in the caller's frame.
1046
1066
1047 Usage:
1067 Usage:
1048 >>>number = 19
1068 >>>number = 19
1049 >>>text = "python"
1069 >>>text = "python"
1050 >>>print "%(text.capitalize())s %(number/9.0).1f rules!" % EvalDict()
1070 >>>print "%(text.capitalize())s %(number/9.0).1f rules!" % EvalDict()
1051 """
1071 """
1052
1072
1053 # This version is due to sismex01@hebmex.com on c.l.py, and is basically a
1073 # This version is due to sismex01@hebmex.com on c.l.py, and is basically a
1054 # modified (shorter) version of:
1074 # modified (shorter) version of:
1055 # http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/66018 by
1075 # http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/66018 by
1056 # Skip Montanaro (skip@pobox.com).
1076 # Skip Montanaro (skip@pobox.com).
1057
1077
1058 def __getitem__(self, name):
1078 def __getitem__(self, name):
1059 frame = sys._getframe(1)
1079 frame = sys._getframe(1)
1060 return eval(name, frame.f_globals, frame.f_locals)
1080 return eval(name, frame.f_globals, frame.f_locals)
1061
1081
1062 EvalString = EvalDict # for backwards compatibility
1082 EvalString = EvalDict # for backwards compatibility
1063 #----------------------------------------------------------------------------
1083 #----------------------------------------------------------------------------
1064 def qw(words,flat=0,sep=None,maxsplit=-1):
1084 def qw(words,flat=0,sep=None,maxsplit=-1):
1065 """Similar to Perl's qw() operator, but with some more options.
1085 """Similar to Perl's qw() operator, but with some more options.
1066
1086
1067 qw(words,flat=0,sep=' ',maxsplit=-1) -> words.split(sep,maxsplit)
1087 qw(words,flat=0,sep=' ',maxsplit=-1) -> words.split(sep,maxsplit)
1068
1088
1069 words can also be a list itself, and with flat=1, the output will be
1089 words can also be a list itself, and with flat=1, the output will be
1070 recursively flattened. Examples:
1090 recursively flattened. Examples:
1071
1091
1072 >>> qw('1 2')
1092 >>> qw('1 2')
1073 ['1', '2']
1093 ['1', '2']
1074 >>> qw(['a b','1 2',['m n','p q']])
1094 >>> qw(['a b','1 2',['m n','p q']])
1075 [['a', 'b'], ['1', '2'], [['m', 'n'], ['p', 'q']]]
1095 [['a', 'b'], ['1', '2'], [['m', 'n'], ['p', 'q']]]
1076 >>> qw(['a b','1 2',['m n','p q']],flat=1)
1096 >>> qw(['a b','1 2',['m n','p q']],flat=1)
1077 ['a', 'b', '1', '2', 'm', 'n', 'p', 'q'] """
1097 ['a', 'b', '1', '2', 'm', 'n', 'p', 'q'] """
1078
1098
1079 if type(words) in StringTypes:
1099 if type(words) in StringTypes:
1080 return [word.strip() for word in words.split(sep,maxsplit)
1100 return [word.strip() for word in words.split(sep,maxsplit)
1081 if word and not word.isspace() ]
1101 if word and not word.isspace() ]
1082 if flat:
1102 if flat:
1083 return flatten(map(qw,words,[1]*len(words)))
1103 return flatten(map(qw,words,[1]*len(words)))
1084 return map(qw,words)
1104 return map(qw,words)
1085
1105
1086 #----------------------------------------------------------------------------
1106 #----------------------------------------------------------------------------
1087 def qwflat(words,sep=None,maxsplit=-1):
1107 def qwflat(words,sep=None,maxsplit=-1):
1088 """Calls qw(words) in flat mode. It's just a convenient shorthand."""
1108 """Calls qw(words) in flat mode. It's just a convenient shorthand."""
1089 return qw(words,1,sep,maxsplit)
1109 return qw(words,1,sep,maxsplit)
1090
1110
1091 #----------------------------------------------------------------------------
1111 #----------------------------------------------------------------------------
1092 def qw_lol(indata):
1112 def qw_lol(indata):
1093 """qw_lol('a b') -> [['a','b']],
1113 """qw_lol('a b') -> [['a','b']],
1094 otherwise it's just a call to qw().
1114 otherwise it's just a call to qw().
1095
1115
1096 We need this to make sure the modules_some keys *always* end up as a
1116 We need this to make sure the modules_some keys *always* end up as a
1097 list of lists."""
1117 list of lists."""
1098
1118
1099 if type(indata) in StringTypes:
1119 if type(indata) in StringTypes:
1100 return [qw(indata)]
1120 return [qw(indata)]
1101 else:
1121 else:
1102 return qw(indata)
1122 return qw(indata)
1103
1123
1104 #-----------------------------------------------------------------------------
1124 #-----------------------------------------------------------------------------
1105 def list_strings(arg):
1125 def list_strings(arg):
1106 """Always return a list of strings, given a string or list of strings
1126 """Always return a list of strings, given a string or list of strings
1107 as input."""
1127 as input."""
1108
1128
1109 if type(arg) in StringTypes: return [arg]
1129 if type(arg) in StringTypes: return [arg]
1110 else: return arg
1130 else: return arg
1111
1131
1112 #----------------------------------------------------------------------------
1132 #----------------------------------------------------------------------------
1113 def grep(pat,list,case=1):
1133 def grep(pat,list,case=1):
1114 """Simple minded grep-like function.
1134 """Simple minded grep-like function.
1115 grep(pat,list) returns occurrences of pat in list, None on failure.
1135 grep(pat,list) returns occurrences of pat in list, None on failure.
1116
1136
1117 It only does simple string matching, with no support for regexps. Use the
1137 It only does simple string matching, with no support for regexps. Use the
1118 option case=0 for case-insensitive matching."""
1138 option case=0 for case-insensitive matching."""
1119
1139
1120 # This is pretty crude. At least it should implement copying only references
1140 # This is pretty crude. At least it should implement copying only references
1121 # to the original data in case it's big. Now it copies the data for output.
1141 # to the original data in case it's big. Now it copies the data for output.
1122 out=[]
1142 out=[]
1123 if case:
1143 if case:
1124 for term in list:
1144 for term in list:
1125 if term.find(pat)>-1: out.append(term)
1145 if term.find(pat)>-1: out.append(term)
1126 else:
1146 else:
1127 lpat=pat.lower()
1147 lpat=pat.lower()
1128 for term in list:
1148 for term in list:
1129 if term.lower().find(lpat)>-1: out.append(term)
1149 if term.lower().find(lpat)>-1: out.append(term)
1130
1150
1131 if len(out): return out
1151 if len(out): return out
1132 else: return None
1152 else: return None
1133
1153
1134 #----------------------------------------------------------------------------
1154 #----------------------------------------------------------------------------
1135 def dgrep(pat,*opts):
1155 def dgrep(pat,*opts):
1136 """Return grep() on dir()+dir(__builtins__).
1156 """Return grep() on dir()+dir(__builtins__).
1137
1157
1138 A very common use of grep() when working interactively."""
1158 A very common use of grep() when working interactively."""
1139
1159
1140 return grep(pat,dir(__main__)+dir(__main__.__builtins__),*opts)
1160 return grep(pat,dir(__main__)+dir(__main__.__builtins__),*opts)
1141
1161
1142 #----------------------------------------------------------------------------
1162 #----------------------------------------------------------------------------
1143 def idgrep(pat):
1163 def idgrep(pat):
1144 """Case-insensitive dgrep()"""
1164 """Case-insensitive dgrep()"""
1145
1165
1146 return dgrep(pat,0)
1166 return dgrep(pat,0)
1147
1167
1148 #----------------------------------------------------------------------------
1168 #----------------------------------------------------------------------------
1149 def igrep(pat,list):
1169 def igrep(pat,list):
1150 """Synonym for case-insensitive grep."""
1170 """Synonym for case-insensitive grep."""
1151
1171
1152 return grep(pat,list,case=0)
1172 return grep(pat,list,case=0)
1153
1173
1154 #----------------------------------------------------------------------------
1174 #----------------------------------------------------------------------------
1155 def indent(str,nspaces=4,ntabs=0):
1175 def indent(str,nspaces=4,ntabs=0):
1156 """Indent a string a given number of spaces or tabstops.
1176 """Indent a string a given number of spaces or tabstops.
1157
1177
1158 indent(str,nspaces=4,ntabs=0) -> indent str by ntabs+nspaces.
1178 indent(str,nspaces=4,ntabs=0) -> indent str by ntabs+nspaces.
1159 """
1179 """
1160 if str is None:
1180 if str is None:
1161 return
1181 return
1162 ind = '\t'*ntabs+' '*nspaces
1182 ind = '\t'*ntabs+' '*nspaces
1163 outstr = '%s%s' % (ind,str.replace(os.linesep,os.linesep+ind))
1183 outstr = '%s%s' % (ind,str.replace(os.linesep,os.linesep+ind))
1164 if outstr.endswith(os.linesep+ind):
1184 if outstr.endswith(os.linesep+ind):
1165 return outstr[:-len(ind)]
1185 return outstr[:-len(ind)]
1166 else:
1186 else:
1167 return outstr
1187 return outstr
1168
1188
1169 #-----------------------------------------------------------------------------
1189 #-----------------------------------------------------------------------------
1170 def native_line_ends(filename,backup=1):
1190 def native_line_ends(filename,backup=1):
1171 """Convert (in-place) a file to line-ends native to the current OS.
1191 """Convert (in-place) a file to line-ends native to the current OS.
1172
1192
1173 If the optional backup argument is given as false, no backup of the
1193 If the optional backup argument is given as false, no backup of the
1174 original file is left. """
1194 original file is left. """
1175
1195
1176 backup_suffixes = {'posix':'~','dos':'.bak','nt':'.bak','mac':'.bak'}
1196 backup_suffixes = {'posix':'~','dos':'.bak','nt':'.bak','mac':'.bak'}
1177
1197
1178 bak_filename = filename + backup_suffixes[os.name]
1198 bak_filename = filename + backup_suffixes[os.name]
1179
1199
1180 original = open(filename).read()
1200 original = open(filename).read()
1181 shutil.copy2(filename,bak_filename)
1201 shutil.copy2(filename,bak_filename)
1182 try:
1202 try:
1183 new = open(filename,'wb')
1203 new = open(filename,'wb')
1184 new.write(os.linesep.join(original.splitlines()))
1204 new.write(os.linesep.join(original.splitlines()))
1185 new.write(os.linesep) # ALWAYS put an eol at the end of the file
1205 new.write(os.linesep) # ALWAYS put an eol at the end of the file
1186 new.close()
1206 new.close()
1187 except:
1207 except:
1188 os.rename(bak_filename,filename)
1208 os.rename(bak_filename,filename)
1189 if not backup:
1209 if not backup:
1190 try:
1210 try:
1191 os.remove(bak_filename)
1211 os.remove(bak_filename)
1192 except:
1212 except:
1193 pass
1213 pass
1194
1214
1195 #----------------------------------------------------------------------------
1215 #----------------------------------------------------------------------------
1196 def get_pager_cmd(pager_cmd = None):
1216 def get_pager_cmd(pager_cmd = None):
1197 """Return a pager command.
1217 """Return a pager command.
1198
1218
1199 Makes some attempts at finding an OS-correct one."""
1219 Makes some attempts at finding an OS-correct one."""
1200
1220
1201 if os.name == 'posix':
1221 if os.name == 'posix':
1202 default_pager_cmd = 'less -r' # -r for color control sequences
1222 default_pager_cmd = 'less -r' # -r for color control sequences
1203 elif os.name in ['nt','dos']:
1223 elif os.name in ['nt','dos']:
1204 default_pager_cmd = 'type'
1224 default_pager_cmd = 'type'
1205
1225
1206 if pager_cmd is None:
1226 if pager_cmd is None:
1207 try:
1227 try:
1208 pager_cmd = os.environ['PAGER']
1228 pager_cmd = os.environ['PAGER']
1209 except:
1229 except:
1210 pager_cmd = default_pager_cmd
1230 pager_cmd = default_pager_cmd
1211 return pager_cmd
1231 return pager_cmd
1212
1232
1213 #-----------------------------------------------------------------------------
1233 #-----------------------------------------------------------------------------
1214 def get_pager_start(pager,start):
1234 def get_pager_start(pager,start):
1215 """Return the string for paging files with an offset.
1235 """Return the string for paging files with an offset.
1216
1236
1217 This is the '+N' argument which less and more (under Unix) accept.
1237 This is the '+N' argument which less and more (under Unix) accept.
1218 """
1238 """
1219
1239
1220 if pager in ['less','more']:
1240 if pager in ['less','more']:
1221 if start:
1241 if start:
1222 start_string = '+' + str(start)
1242 start_string = '+' + str(start)
1223 else:
1243 else:
1224 start_string = ''
1244 start_string = ''
1225 else:
1245 else:
1226 start_string = ''
1246 start_string = ''
1227 return start_string
1247 return start_string
1228
1248
1229 #----------------------------------------------------------------------------
1249 #----------------------------------------------------------------------------
1230 if os.name == "nt":
1250 if os.name == "nt":
1231 import msvcrt
1251 import msvcrt
1232 def page_more():
1252 def page_more():
1233 """ Smart pausing between pages
1253 """ Smart pausing between pages
1234
1254
1235 @return: True if need print more lines, False if quit
1255 @return: True if need print more lines, False if quit
1236 """
1256 """
1237 Term.cout.write('---Return to continue, q to quit--- ')
1257 Term.cout.write('---Return to continue, q to quit--- ')
1238 ans = msvcrt.getch()
1258 ans = msvcrt.getch()
1239 if ans in ("q", "Q"):
1259 if ans in ("q", "Q"):
1240 result = False
1260 result = False
1241 else:
1261 else:
1242 result = True
1262 result = True
1243 Term.cout.write("\b"*37 + " "*37 + "\b"*37)
1263 Term.cout.write("\b"*37 + " "*37 + "\b"*37)
1244 return result
1264 return result
1245 else:
1265 else:
1246 def page_more():
1266 def page_more():
1247 ans = raw_input('---Return to continue, q to quit--- ')
1267 ans = raw_input('---Return to continue, q to quit--- ')
1248 if ans.lower().startswith('q'):
1268 if ans.lower().startswith('q'):
1249 return False
1269 return False
1250 else:
1270 else:
1251 return True
1271 return True
1252
1272
1253 esc_re = re.compile(r"(\x1b[^m]+m)")
1273 esc_re = re.compile(r"(\x1b[^m]+m)")
1254
1274
1255 def page_dumb(strng,start=0,screen_lines=25):
1275 def page_dumb(strng,start=0,screen_lines=25):
1256 """Very dumb 'pager' in Python, for when nothing else works.
1276 """Very dumb 'pager' in Python, for when nothing else works.
1257
1277
1258 Only moves forward, same interface as page(), except for pager_cmd and
1278 Only moves forward, same interface as page(), except for pager_cmd and
1259 mode."""
1279 mode."""
1260
1280
1261 out_ln = strng.splitlines()[start:]
1281 out_ln = strng.splitlines()[start:]
1262 screens = chop(out_ln,screen_lines-1)
1282 screens = chop(out_ln,screen_lines-1)
1263 if len(screens) == 1:
1283 if len(screens) == 1:
1264 print >>Term.cout, os.linesep.join(screens[0])
1284 print >>Term.cout, os.linesep.join(screens[0])
1265 else:
1285 else:
1266 last_escape = ""
1286 last_escape = ""
1267 for scr in screens[0:-1]:
1287 for scr in screens[0:-1]:
1268 hunk = os.linesep.join(scr)
1288 hunk = os.linesep.join(scr)
1269 print >>Term.cout, last_escape + hunk
1289 print >>Term.cout, last_escape + hunk
1270 if not page_more():
1290 if not page_more():
1271 return
1291 return
1272 esc_list = esc_re.findall(hunk)
1292 esc_list = esc_re.findall(hunk)
1273 if len(esc_list) > 0:
1293 if len(esc_list) > 0:
1274 last_escape = esc_list[-1]
1294 last_escape = esc_list[-1]
1275 print >>Term.cout, last_escape + os.linesep.join(screens[-1])
1295 print >>Term.cout, last_escape + os.linesep.join(screens[-1])
1276
1296
1277 #----------------------------------------------------------------------------
1297 #----------------------------------------------------------------------------
1278 def page(strng,start=0,screen_lines=0,pager_cmd = None):
1298 def page(strng,start=0,screen_lines=0,pager_cmd = None):
1279 """Print a string, piping through a pager after a certain length.
1299 """Print a string, piping through a pager after a certain length.
1280
1300
1281 The screen_lines parameter specifies the number of *usable* lines of your
1301 The screen_lines parameter specifies the number of *usable* lines of your
1282 terminal screen (total lines minus lines you need to reserve to show other
1302 terminal screen (total lines minus lines you need to reserve to show other
1283 information).
1303 information).
1284
1304
1285 If you set screen_lines to a number <=0, page() will try to auto-determine
1305 If you set screen_lines to a number <=0, page() will try to auto-determine
1286 your screen size and will only use up to (screen_size+screen_lines) for
1306 your screen size and will only use up to (screen_size+screen_lines) for
1287 printing, paging after that. That is, if you want auto-detection but need
1307 printing, paging after that. That is, if you want auto-detection but need
1288 to reserve the bottom 3 lines of the screen, use screen_lines = -3, and for
1308 to reserve the bottom 3 lines of the screen, use screen_lines = -3, and for
1289 auto-detection without any lines reserved simply use screen_lines = 0.
1309 auto-detection without any lines reserved simply use screen_lines = 0.
1290
1310
1291 If a string won't fit in the allowed lines, it is sent through the
1311 If a string won't fit in the allowed lines, it is sent through the
1292 specified pager command. If none given, look for PAGER in the environment,
1312 specified pager command. If none given, look for PAGER in the environment,
1293 and ultimately default to less.
1313 and ultimately default to less.
1294
1314
1295 If no system pager works, the string is sent through a 'dumb pager'
1315 If no system pager works, the string is sent through a 'dumb pager'
1296 written in python, very simplistic.
1316 written in python, very simplistic.
1297 """
1317 """
1298
1318
1299 # Ugly kludge, but calling curses.initscr() flat out crashes in emacs
1319 # Ugly kludge, but calling curses.initscr() flat out crashes in emacs
1300 TERM = os.environ.get('TERM','dumb')
1320 TERM = os.environ.get('TERM','dumb')
1301 if TERM in ['dumb','emacs'] and os.name != 'nt':
1321 if TERM in ['dumb','emacs'] and os.name != 'nt':
1302 print strng
1322 print strng
1303 return
1323 return
1304 # chop off the topmost part of the string we don't want to see
1324 # chop off the topmost part of the string we don't want to see
1305 str_lines = strng.split(os.linesep)[start:]
1325 str_lines = strng.split(os.linesep)[start:]
1306 str_toprint = os.linesep.join(str_lines)
1326 str_toprint = os.linesep.join(str_lines)
1307 num_newlines = len(str_lines)
1327 num_newlines = len(str_lines)
1308 len_str = len(str_toprint)
1328 len_str = len(str_toprint)
1309
1329
1310 # Dumb heuristics to guesstimate number of on-screen lines the string
1330 # Dumb heuristics to guesstimate number of on-screen lines the string
1311 # takes. Very basic, but good enough for docstrings in reasonable
1331 # takes. Very basic, but good enough for docstrings in reasonable
1312 # terminals. If someone later feels like refining it, it's not hard.
1332 # terminals. If someone later feels like refining it, it's not hard.
1313 numlines = max(num_newlines,int(len_str/80)+1)
1333 numlines = max(num_newlines,int(len_str/80)+1)
1314
1334
1315 if os.name == "nt":
1335 if os.name == "nt":
1316 screen_lines_def = get_console_size(defaulty=25)[1]
1336 screen_lines_def = get_console_size(defaulty=25)[1]
1317 else:
1337 else:
1318 screen_lines_def = 25 # default value if we can't auto-determine
1338 screen_lines_def = 25 # default value if we can't auto-determine
1319
1339
1320 # auto-determine screen size
1340 # auto-determine screen size
1321 if screen_lines <= 0:
1341 if screen_lines <= 0:
1322 if TERM=='xterm':
1342 if TERM=='xterm':
1323 try:
1343 try:
1324 import curses
1344 import curses
1325 if hasattr(curses,'initscr'):
1345 if hasattr(curses,'initscr'):
1326 use_curses = 1
1346 use_curses = 1
1327 else:
1347 else:
1328 use_curses = 0
1348 use_curses = 0
1329 except ImportError:
1349 except ImportError:
1330 use_curses = 0
1350 use_curses = 0
1331 else:
1351 else:
1332 # curses causes problems on many terminals other than xterm.
1352 # curses causes problems on many terminals other than xterm.
1333 use_curses = 0
1353 use_curses = 0
1334 if use_curses:
1354 if use_curses:
1335 scr = curses.initscr()
1355 scr = curses.initscr()
1336 screen_lines_real,screen_cols = scr.getmaxyx()
1356 screen_lines_real,screen_cols = scr.getmaxyx()
1337 curses.endwin()
1357 curses.endwin()
1338 screen_lines += screen_lines_real
1358 screen_lines += screen_lines_real
1339 #print '***Screen size:',screen_lines_real,'lines x',\
1359 #print '***Screen size:',screen_lines_real,'lines x',\
1340 #screen_cols,'columns.' # dbg
1360 #screen_cols,'columns.' # dbg
1341 else:
1361 else:
1342 screen_lines += screen_lines_def
1362 screen_lines += screen_lines_def
1343
1363
1344 #print 'numlines',numlines,'screenlines',screen_lines # dbg
1364 #print 'numlines',numlines,'screenlines',screen_lines # dbg
1345 if numlines <= screen_lines :
1365 if numlines <= screen_lines :
1346 #print '*** normal print' # dbg
1366 #print '*** normal print' # dbg
1347 print >>Term.cout, str_toprint
1367 print >>Term.cout, str_toprint
1348 else:
1368 else:
1349 # Try to open pager and default to internal one if that fails.
1369 # Try to open pager and default to internal one if that fails.
1350 # All failure modes are tagged as 'retval=1', to match the return
1370 # All failure modes are tagged as 'retval=1', to match the return
1351 # value of a failed system command. If any intermediate attempt
1371 # value of a failed system command. If any intermediate attempt
1352 # sets retval to 1, at the end we resort to our own page_dumb() pager.
1372 # sets retval to 1, at the end we resort to our own page_dumb() pager.
1353 pager_cmd = get_pager_cmd(pager_cmd)
1373 pager_cmd = get_pager_cmd(pager_cmd)
1354 pager_cmd += ' ' + get_pager_start(pager_cmd,start)
1374 pager_cmd += ' ' + get_pager_start(pager_cmd,start)
1355 if os.name == 'nt':
1375 if os.name == 'nt':
1356 if pager_cmd.startswith('type'):
1376 if pager_cmd.startswith('type'):
1357 # The default WinXP 'type' command is failing on complex strings.
1377 # The default WinXP 'type' command is failing on complex strings.
1358 retval = 1
1378 retval = 1
1359 else:
1379 else:
1360 tmpname = tempfile.mktemp('.txt')
1380 tmpname = tempfile.mktemp('.txt')
1361 tmpfile = file(tmpname,'wt')
1381 tmpfile = file(tmpname,'wt')
1362 tmpfile.write(strng)
1382 tmpfile.write(strng)
1363 tmpfile.close()
1383 tmpfile.close()
1364 cmd = "%s < %s" % (pager_cmd,tmpname)
1384 cmd = "%s < %s" % (pager_cmd,tmpname)
1365 if os.system(cmd):
1385 if os.system(cmd):
1366 retval = 1
1386 retval = 1
1367 else:
1387 else:
1368 retval = None
1388 retval = None
1369 os.remove(tmpname)
1389 os.remove(tmpname)
1370 else:
1390 else:
1371 try:
1391 try:
1372 retval = None
1392 retval = None
1373 # if I use popen4, things hang. No idea why.
1393 # if I use popen4, things hang. No idea why.
1374 #pager,shell_out = os.popen4(pager_cmd)
1394 #pager,shell_out = os.popen4(pager_cmd)
1375 pager = os.popen(pager_cmd,'w')
1395 pager = os.popen(pager_cmd,'w')
1376 pager.write(strng)
1396 pager.write(strng)
1377 pager.close()
1397 pager.close()
1378 retval = pager.close() # success returns None
1398 retval = pager.close() # success returns None
1379 except IOError,msg: # broken pipe when user quits
1399 except IOError,msg: # broken pipe when user quits
1380 if msg.args == (32,'Broken pipe'):
1400 if msg.args == (32,'Broken pipe'):
1381 retval = None
1401 retval = None
1382 else:
1402 else:
1383 retval = 1
1403 retval = 1
1384 except OSError:
1404 except OSError:
1385 # Other strange problems, sometimes seen in Win2k/cygwin
1405 # Other strange problems, sometimes seen in Win2k/cygwin
1386 retval = 1
1406 retval = 1
1387 if retval is not None:
1407 if retval is not None:
1388 page_dumb(strng,screen_lines=screen_lines)
1408 page_dumb(strng,screen_lines=screen_lines)
1389
1409
1390 #----------------------------------------------------------------------------
1410 #----------------------------------------------------------------------------
1391 def page_file(fname,start = 0, pager_cmd = None):
1411 def page_file(fname,start = 0, pager_cmd = None):
1392 """Page a file, using an optional pager command and starting line.
1412 """Page a file, using an optional pager command and starting line.
1393 """
1413 """
1394
1414
1395 pager_cmd = get_pager_cmd(pager_cmd)
1415 pager_cmd = get_pager_cmd(pager_cmd)
1396 pager_cmd += ' ' + get_pager_start(pager_cmd,start)
1416 pager_cmd += ' ' + get_pager_start(pager_cmd,start)
1397
1417
1398 try:
1418 try:
1399 if os.environ['TERM'] in ['emacs','dumb']:
1419 if os.environ['TERM'] in ['emacs','dumb']:
1400 raise EnvironmentError
1420 raise EnvironmentError
1401 xsys(pager_cmd + ' ' + fname)
1421 xsys(pager_cmd + ' ' + fname)
1402 except:
1422 except:
1403 try:
1423 try:
1404 if start > 0:
1424 if start > 0:
1405 start -= 1
1425 start -= 1
1406 page(open(fname).read(),start)
1426 page(open(fname).read(),start)
1407 except:
1427 except:
1408 print 'Unable to show file',`fname`
1428 print 'Unable to show file',`fname`
1409
1429
1410 #----------------------------------------------------------------------------
1430 #----------------------------------------------------------------------------
1411 def snip_print(str,width = 75,print_full = 0,header = ''):
1431 def snip_print(str,width = 75,print_full = 0,header = ''):
1412 """Print a string snipping the midsection to fit in width.
1432 """Print a string snipping the midsection to fit in width.
1413
1433
1414 print_full: mode control:
1434 print_full: mode control:
1415 - 0: only snip long strings
1435 - 0: only snip long strings
1416 - 1: send to page() directly.
1436 - 1: send to page() directly.
1417 - 2: snip long strings and ask for full length viewing with page()
1437 - 2: snip long strings and ask for full length viewing with page()
1418 Return 1 if snipping was necessary, 0 otherwise."""
1438 Return 1 if snipping was necessary, 0 otherwise."""
1419
1439
1420 if print_full == 1:
1440 if print_full == 1:
1421 page(header+str)
1441 page(header+str)
1422 return 0
1442 return 0
1423
1443
1424 print header,
1444 print header,
1425 if len(str) < width:
1445 if len(str) < width:
1426 print str
1446 print str
1427 snip = 0
1447 snip = 0
1428 else:
1448 else:
1429 whalf = int((width -5)/2)
1449 whalf = int((width -5)/2)
1430 print str[:whalf] + ' <...> ' + str[-whalf:]
1450 print str[:whalf] + ' <...> ' + str[-whalf:]
1431 snip = 1
1451 snip = 1
1432 if snip and print_full == 2:
1452 if snip and print_full == 2:
1433 if raw_input(header+' Snipped. View (y/n)? [N]').lower() == 'y':
1453 if raw_input(header+' Snipped. View (y/n)? [N]').lower() == 'y':
1434 page(str)
1454 page(str)
1435 return snip
1455 return snip
1436
1456
1437 #****************************************************************************
1457 #****************************************************************************
1438 # lists, dicts and structures
1458 # lists, dicts and structures
1439
1459
1440 def belong(candidates,checklist):
1460 def belong(candidates,checklist):
1441 """Check whether a list of items appear in a given list of options.
1461 """Check whether a list of items appear in a given list of options.
1442
1462
1443 Returns a list of 1 and 0, one for each candidate given."""
1463 Returns a list of 1 and 0, one for each candidate given."""
1444
1464
1445 return [x in checklist for x in candidates]
1465 return [x in checklist for x in candidates]
1446
1466
1447 #----------------------------------------------------------------------------
1467 #----------------------------------------------------------------------------
1448 def uniq_stable(elems):
1468 def uniq_stable(elems):
1449 """uniq_stable(elems) -> list
1469 """uniq_stable(elems) -> list
1450
1470
1451 Return from an iterable, a list of all the unique elements in the input,
1471 Return from an iterable, a list of all the unique elements in the input,
1452 but maintaining the order in which they first appear.
1472 but maintaining the order in which they first appear.
1453
1473
1454 A naive solution to this problem which just makes a dictionary with the
1474 A naive solution to this problem which just makes a dictionary with the
1455 elements as keys fails to respect the stability condition, since
1475 elements as keys fails to respect the stability condition, since
1456 dictionaries are unsorted by nature.
1476 dictionaries are unsorted by nature.
1457
1477
1458 Note: All elements in the input must be valid dictionary keys for this
1478 Note: All elements in the input must be valid dictionary keys for this
1459 routine to work, as it internally uses a dictionary for efficiency
1479 routine to work, as it internally uses a dictionary for efficiency
1460 reasons."""
1480 reasons."""
1461
1481
1462 unique = []
1482 unique = []
1463 unique_dict = {}
1483 unique_dict = {}
1464 for nn in elems:
1484 for nn in elems:
1465 if nn not in unique_dict:
1485 if nn not in unique_dict:
1466 unique.append(nn)
1486 unique.append(nn)
1467 unique_dict[nn] = None
1487 unique_dict[nn] = None
1468 return unique
1488 return unique
1469
1489
1470 #----------------------------------------------------------------------------
1490 #----------------------------------------------------------------------------
1471 class NLprinter:
1491 class NLprinter:
1472 """Print an arbitrarily nested list, indicating index numbers.
1492 """Print an arbitrarily nested list, indicating index numbers.
1473
1493
1474 An instance of this class called nlprint is available and callable as a
1494 An instance of this class called nlprint is available and callable as a
1475 function.
1495 function.
1476
1496
1477 nlprint(list,indent=' ',sep=': ') -> prints indenting each level by 'indent'
1497 nlprint(list,indent=' ',sep=': ') -> prints indenting each level by 'indent'
1478 and using 'sep' to separate the index from the value. """
1498 and using 'sep' to separate the index from the value. """
1479
1499
1480 def __init__(self):
1500 def __init__(self):
1481 self.depth = 0
1501 self.depth = 0
1482
1502
1483 def __call__(self,lst,pos='',**kw):
1503 def __call__(self,lst,pos='',**kw):
1484 """Prints the nested list numbering levels."""
1504 """Prints the nested list numbering levels."""
1485 kw.setdefault('indent',' ')
1505 kw.setdefault('indent',' ')
1486 kw.setdefault('sep',': ')
1506 kw.setdefault('sep',': ')
1487 kw.setdefault('start',0)
1507 kw.setdefault('start',0)
1488 kw.setdefault('stop',len(lst))
1508 kw.setdefault('stop',len(lst))
1489 # we need to remove start and stop from kw so they don't propagate
1509 # we need to remove start and stop from kw so they don't propagate
1490 # into a recursive call for a nested list.
1510 # into a recursive call for a nested list.
1491 start = kw['start']; del kw['start']
1511 start = kw['start']; del kw['start']
1492 stop = kw['stop']; del kw['stop']
1512 stop = kw['stop']; del kw['stop']
1493 if self.depth == 0 and 'header' in kw.keys():
1513 if self.depth == 0 and 'header' in kw.keys():
1494 print kw['header']
1514 print kw['header']
1495
1515
1496 for idx in range(start,stop):
1516 for idx in range(start,stop):
1497 elem = lst[idx]
1517 elem = lst[idx]
1498 if type(elem)==type([]):
1518 if type(elem)==type([]):
1499 self.depth += 1
1519 self.depth += 1
1500 self.__call__(elem,itpl('$pos$idx,'),**kw)
1520 self.__call__(elem,itpl('$pos$idx,'),**kw)
1501 self.depth -= 1
1521 self.depth -= 1
1502 else:
1522 else:
1503 printpl(kw['indent']*self.depth+'$pos$idx$kw["sep"]$elem')
1523 printpl(kw['indent']*self.depth+'$pos$idx$kw["sep"]$elem')
1504
1524
1505 nlprint = NLprinter()
1525 nlprint = NLprinter()
1506 #----------------------------------------------------------------------------
1526 #----------------------------------------------------------------------------
1507 def all_belong(candidates,checklist):
1527 def all_belong(candidates,checklist):
1508 """Check whether a list of items ALL appear in a given list of options.
1528 """Check whether a list of items ALL appear in a given list of options.
1509
1529
1510 Returns a single 1 or 0 value."""
1530 Returns a single 1 or 0 value."""
1511
1531
1512 return 1-(0 in [x in checklist for x in candidates])
1532 return 1-(0 in [x in checklist for x in candidates])
1513
1533
1514 #----------------------------------------------------------------------------
1534 #----------------------------------------------------------------------------
1515 def sort_compare(lst1,lst2,inplace = 1):
1535 def sort_compare(lst1,lst2,inplace = 1):
1516 """Sort and compare two lists.
1536 """Sort and compare two lists.
1517
1537
1518 By default it does it in place, thus modifying the lists. Use inplace = 0
1538 By default it does it in place, thus modifying the lists. Use inplace = 0
1519 to avoid that (at the cost of temporary copy creation)."""
1539 to avoid that (at the cost of temporary copy creation)."""
1520 if not inplace:
1540 if not inplace:
1521 lst1 = lst1[:]
1541 lst1 = lst1[:]
1522 lst2 = lst2[:]
1542 lst2 = lst2[:]
1523 lst1.sort(); lst2.sort()
1543 lst1.sort(); lst2.sort()
1524 return lst1 == lst2
1544 return lst1 == lst2
1525
1545
1526 #----------------------------------------------------------------------------
1546 #----------------------------------------------------------------------------
1527 def mkdict(**kwargs):
1547 def mkdict(**kwargs):
1528 """Return a dict from a keyword list.
1548 """Return a dict from a keyword list.
1529
1549
1530 It's just syntactic sugar for making ditcionary creation more convenient:
1550 It's just syntactic sugar for making ditcionary creation more convenient:
1531 # the standard way
1551 # the standard way
1532 >>>data = { 'red' : 1, 'green' : 2, 'blue' : 3 }
1552 >>>data = { 'red' : 1, 'green' : 2, 'blue' : 3 }
1533 # a cleaner way
1553 # a cleaner way
1534 >>>data = dict(red=1, green=2, blue=3)
1554 >>>data = dict(red=1, green=2, blue=3)
1535
1555
1536 If you need more than this, look at the Struct() class."""
1556 If you need more than this, look at the Struct() class."""
1537
1557
1538 return kwargs
1558 return kwargs
1539
1559
1540 #----------------------------------------------------------------------------
1560 #----------------------------------------------------------------------------
1541 def list2dict(lst):
1561 def list2dict(lst):
1542 """Takes a list of (key,value) pairs and turns it into a dict."""
1562 """Takes a list of (key,value) pairs and turns it into a dict."""
1543
1563
1544 dic = {}
1564 dic = {}
1545 for k,v in lst: dic[k] = v
1565 for k,v in lst: dic[k] = v
1546 return dic
1566 return dic
1547
1567
1548 #----------------------------------------------------------------------------
1568 #----------------------------------------------------------------------------
1549 def list2dict2(lst,default=''):
1569 def list2dict2(lst,default=''):
1550 """Takes a list and turns it into a dict.
1570 """Takes a list and turns it into a dict.
1551 Much slower than list2dict, but more versatile. This version can take
1571 Much slower than list2dict, but more versatile. This version can take
1552 lists with sublists of arbitrary length (including sclars)."""
1572 lists with sublists of arbitrary length (including sclars)."""
1553
1573
1554 dic = {}
1574 dic = {}
1555 for elem in lst:
1575 for elem in lst:
1556 if type(elem) in (types.ListType,types.TupleType):
1576 if type(elem) in (types.ListType,types.TupleType):
1557 size = len(elem)
1577 size = len(elem)
1558 if size == 0:
1578 if size == 0:
1559 pass
1579 pass
1560 elif size == 1:
1580 elif size == 1:
1561 dic[elem] = default
1581 dic[elem] = default
1562 else:
1582 else:
1563 k,v = elem[0], elem[1:]
1583 k,v = elem[0], elem[1:]
1564 if len(v) == 1: v = v[0]
1584 if len(v) == 1: v = v[0]
1565 dic[k] = v
1585 dic[k] = v
1566 else:
1586 else:
1567 dic[elem] = default
1587 dic[elem] = default
1568 return dic
1588 return dic
1569
1589
1570 #----------------------------------------------------------------------------
1590 #----------------------------------------------------------------------------
1571 def flatten(seq):
1591 def flatten(seq):
1572 """Flatten a list of lists (NOT recursive, only works for 2d lists)."""
1592 """Flatten a list of lists (NOT recursive, only works for 2d lists)."""
1573
1593
1574 return [x for subseq in seq for x in subseq]
1594 return [x for subseq in seq for x in subseq]
1575
1595
1576 #----------------------------------------------------------------------------
1596 #----------------------------------------------------------------------------
1577 def get_slice(seq,start=0,stop=None,step=1):
1597 def get_slice(seq,start=0,stop=None,step=1):
1578 """Get a slice of a sequence with variable step. Specify start,stop,step."""
1598 """Get a slice of a sequence with variable step. Specify start,stop,step."""
1579 if stop == None:
1599 if stop == None:
1580 stop = len(seq)
1600 stop = len(seq)
1581 item = lambda i: seq[i]
1601 item = lambda i: seq[i]
1582 return map(item,xrange(start,stop,step))
1602 return map(item,xrange(start,stop,step))
1583
1603
1584 #----------------------------------------------------------------------------
1604 #----------------------------------------------------------------------------
1585 def chop(seq,size):
1605 def chop(seq,size):
1586 """Chop a sequence into chunks of the given size."""
1606 """Chop a sequence into chunks of the given size."""
1587 chunk = lambda i: seq[i:i+size]
1607 chunk = lambda i: seq[i:i+size]
1588 return map(chunk,xrange(0,len(seq),size))
1608 return map(chunk,xrange(0,len(seq),size))
1589
1609
1590 #----------------------------------------------------------------------------
1610 #----------------------------------------------------------------------------
1591 # with is a keyword as of python 2.5, so this function is renamed to withobj
1611 # with is a keyword as of python 2.5, so this function is renamed to withobj
1592 # from its old 'with' name.
1612 # from its old 'with' name.
1593 def with_obj(object, **args):
1613 def with_obj(object, **args):
1594 """Set multiple attributes for an object, similar to Pascal's with.
1614 """Set multiple attributes for an object, similar to Pascal's with.
1595
1615
1596 Example:
1616 Example:
1597 with_obj(jim,
1617 with_obj(jim,
1598 born = 1960,
1618 born = 1960,
1599 haircolour = 'Brown',
1619 haircolour = 'Brown',
1600 eyecolour = 'Green')
1620 eyecolour = 'Green')
1601
1621
1602 Credit: Greg Ewing, in
1622 Credit: Greg Ewing, in
1603 http://mail.python.org/pipermail/python-list/2001-May/040703.html.
1623 http://mail.python.org/pipermail/python-list/2001-May/040703.html.
1604
1624
1605 NOTE: up until IPython 0.7.2, this was called simply 'with', but 'with'
1625 NOTE: up until IPython 0.7.2, this was called simply 'with', but 'with'
1606 has become a keyword for Python 2.5, so we had to rename it."""
1626 has become a keyword for Python 2.5, so we had to rename it."""
1607
1627
1608 object.__dict__.update(args)
1628 object.__dict__.update(args)
1609
1629
1610 #----------------------------------------------------------------------------
1630 #----------------------------------------------------------------------------
1611 def setattr_list(obj,alist,nspace = None):
1631 def setattr_list(obj,alist,nspace = None):
1612 """Set a list of attributes for an object taken from a namespace.
1632 """Set a list of attributes for an object taken from a namespace.
1613
1633
1614 setattr_list(obj,alist,nspace) -> sets in obj all the attributes listed in
1634 setattr_list(obj,alist,nspace) -> sets in obj all the attributes listed in
1615 alist with their values taken from nspace, which must be a dict (something
1635 alist with their values taken from nspace, which must be a dict (something
1616 like locals() will often do) If nspace isn't given, locals() of the
1636 like locals() will often do) If nspace isn't given, locals() of the
1617 *caller* is used, so in most cases you can omit it.
1637 *caller* is used, so in most cases you can omit it.
1618
1638
1619 Note that alist can be given as a string, which will be automatically
1639 Note that alist can be given as a string, which will be automatically
1620 split into a list on whitespace. If given as a list, it must be a list of
1640 split into a list on whitespace. If given as a list, it must be a list of
1621 *strings* (the variable names themselves), not of variables."""
1641 *strings* (the variable names themselves), not of variables."""
1622
1642
1623 # this grabs the local variables from the *previous* call frame -- that is
1643 # this grabs the local variables from the *previous* call frame -- that is
1624 # the locals from the function that called setattr_list().
1644 # the locals from the function that called setattr_list().
1625 # - snipped from weave.inline()
1645 # - snipped from weave.inline()
1626 if nspace is None:
1646 if nspace is None:
1627 call_frame = sys._getframe().f_back
1647 call_frame = sys._getframe().f_back
1628 nspace = call_frame.f_locals
1648 nspace = call_frame.f_locals
1629
1649
1630 if type(alist) in StringTypes:
1650 if type(alist) in StringTypes:
1631 alist = alist.split()
1651 alist = alist.split()
1632 for attr in alist:
1652 for attr in alist:
1633 val = eval(attr,nspace)
1653 val = eval(attr,nspace)
1634 setattr(obj,attr,val)
1654 setattr(obj,attr,val)
1635
1655
1636 #----------------------------------------------------------------------------
1656 #----------------------------------------------------------------------------
1637 def getattr_list(obj,alist,*args):
1657 def getattr_list(obj,alist,*args):
1638 """getattr_list(obj,alist[, default]) -> attribute list.
1658 """getattr_list(obj,alist[, default]) -> attribute list.
1639
1659
1640 Get a list of named attributes for an object. When a default argument is
1660 Get a list of named attributes for an object. When a default argument is
1641 given, it is returned when the attribute doesn't exist; without it, an
1661 given, it is returned when the attribute doesn't exist; without it, an
1642 exception is raised in that case.
1662 exception is raised in that case.
1643
1663
1644 Note that alist can be given as a string, which will be automatically
1664 Note that alist can be given as a string, which will be automatically
1645 split into a list on whitespace. If given as a list, it must be a list of
1665 split into a list on whitespace. If given as a list, it must be a list of
1646 *strings* (the variable names themselves), not of variables."""
1666 *strings* (the variable names themselves), not of variables."""
1647
1667
1648 if type(alist) in StringTypes:
1668 if type(alist) in StringTypes:
1649 alist = alist.split()
1669 alist = alist.split()
1650 if args:
1670 if args:
1651 if len(args)==1:
1671 if len(args)==1:
1652 default = args[0]
1672 default = args[0]
1653 return map(lambda attr: getattr(obj,attr,default),alist)
1673 return map(lambda attr: getattr(obj,attr,default),alist)
1654 else:
1674 else:
1655 raise ValueError,'getattr_list() takes only one optional argument'
1675 raise ValueError,'getattr_list() takes only one optional argument'
1656 else:
1676 else:
1657 return map(lambda attr: getattr(obj,attr),alist)
1677 return map(lambda attr: getattr(obj,attr),alist)
1658
1678
1659 #----------------------------------------------------------------------------
1679 #----------------------------------------------------------------------------
1660 def map_method(method,object_list,*argseq,**kw):
1680 def map_method(method,object_list,*argseq,**kw):
1661 """map_method(method,object_list,*args,**kw) -> list
1681 """map_method(method,object_list,*args,**kw) -> list
1662
1682
1663 Return a list of the results of applying the methods to the items of the
1683 Return a list of the results of applying the methods to the items of the
1664 argument sequence(s). If more than one sequence is given, the method is
1684 argument sequence(s). If more than one sequence is given, the method is
1665 called with an argument list consisting of the corresponding item of each
1685 called with an argument list consisting of the corresponding item of each
1666 sequence. All sequences must be of the same length.
1686 sequence. All sequences must be of the same length.
1667
1687
1668 Keyword arguments are passed verbatim to all objects called.
1688 Keyword arguments are passed verbatim to all objects called.
1669
1689
1670 This is Python code, so it's not nearly as fast as the builtin map()."""
1690 This is Python code, so it's not nearly as fast as the builtin map()."""
1671
1691
1672 out_list = []
1692 out_list = []
1673 idx = 0
1693 idx = 0
1674 for object in object_list:
1694 for object in object_list:
1675 try:
1695 try:
1676 handler = getattr(object, method)
1696 handler = getattr(object, method)
1677 except AttributeError:
1697 except AttributeError:
1678 out_list.append(None)
1698 out_list.append(None)
1679 else:
1699 else:
1680 if argseq:
1700 if argseq:
1681 args = map(lambda lst:lst[idx],argseq)
1701 args = map(lambda lst:lst[idx],argseq)
1682 #print 'ob',object,'hand',handler,'ar',args # dbg
1702 #print 'ob',object,'hand',handler,'ar',args # dbg
1683 out_list.append(handler(args,**kw))
1703 out_list.append(handler(args,**kw))
1684 else:
1704 else:
1685 out_list.append(handler(**kw))
1705 out_list.append(handler(**kw))
1686 idx += 1
1706 idx += 1
1687 return out_list
1707 return out_list
1688
1708
1689 #----------------------------------------------------------------------------
1709 #----------------------------------------------------------------------------
1690 def import_fail_info(mod_name,fns=None):
1710 def import_fail_info(mod_name,fns=None):
1691 """Inform load failure for a module."""
1711 """Inform load failure for a module."""
1692
1712
1693 if fns == None:
1713 if fns == None:
1694 warn("Loading of %s failed.\n" % (mod_name,))
1714 warn("Loading of %s failed.\n" % (mod_name,))
1695 else:
1715 else:
1696 warn("Loading of %s from %s failed.\n" % (fns,mod_name))
1716 warn("Loading of %s from %s failed.\n" % (fns,mod_name))
1697
1717
1698 #----------------------------------------------------------------------------
1718 #----------------------------------------------------------------------------
1699 # Proposed popitem() extension, written as a method
1719 # Proposed popitem() extension, written as a method
1700
1720
1701
1721
1702 class NotGiven: pass
1722 class NotGiven: pass
1703
1723
1704 def popkey(dct,key,default=NotGiven):
1724 def popkey(dct,key,default=NotGiven):
1705 """Return dct[key] and delete dct[key].
1725 """Return dct[key] and delete dct[key].
1706
1726
1707 If default is given, return it if dct[key] doesn't exist, otherwise raise
1727 If default is given, return it if dct[key] doesn't exist, otherwise raise
1708 KeyError. """
1728 KeyError. """
1709
1729
1710 try:
1730 try:
1711 val = dct[key]
1731 val = dct[key]
1712 except KeyError:
1732 except KeyError:
1713 if default is NotGiven:
1733 if default is NotGiven:
1714 raise
1734 raise
1715 else:
1735 else:
1716 return default
1736 return default
1717 else:
1737 else:
1718 del dct[key]
1738 del dct[key]
1719 return val
1739 return val
1720
1740
1721 def wrap_deprecated(func, suggest = '<nothing>'):
1741 def wrap_deprecated(func, suggest = '<nothing>'):
1722 def newFunc(*args, **kwargs):
1742 def newFunc(*args, **kwargs):
1723 warnings.warn("Call to deprecated function %s, use %s instead" %
1743 warnings.warn("Call to deprecated function %s, use %s instead" %
1724 ( func.__name__, suggest),
1744 ( func.__name__, suggest),
1725 category=DeprecationWarning,
1745 category=DeprecationWarning,
1726 stacklevel = 2)
1746 stacklevel = 2)
1727 return func(*args, **kwargs)
1747 return func(*args, **kwargs)
1728 return newFunc
1748 return newFunc
1729
1749
1730 #*************************** end of file <genutils.py> **********************
1750 #*************************** end of file <genutils.py> **********************
1731
1751
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
General Comments 0
You need to be logged in to leave comments. Login now