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