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