##// END OF EJS Templates
fix to help users with invalid $HOME under win32.
fperez -
r6:396feddb
parent child Browse files
Show More

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

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