##// END OF EJS Templates
use popen in genutils.getoutput
vivainio -
Show More

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

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