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