##// END OF EJS Templates
sort() returns SList (obviously), %cpaste foo assigns the pasted block to foo as string list
Ville M. Vainio -
Show More

The requested changes are too big and content was truncated. Show full diff

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