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