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