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