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