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