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