##// END OF EJS Templates
Jorgen Stenarson's patch (minor mods) to support network shares under win32.
fperez -
Show More

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

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