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